From 63b41817541ed47fb2dd8c4abac888841d100aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 7 Aug 2025 17:23:46 +0200 Subject: [PATCH 001/154] chore: Prepare for vendoring develop --- .github/workflows/vendor.yaml | 2 ++ vendor.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/vendor.yaml b/.github/workflows/vendor.yaml index 45a01d7410d..5a7041de198 100644 --- a/.github/workflows/vendor.yaml +++ b/.github/workflows/vendor.yaml @@ -22,6 +22,8 @@ jobs: include: - branch: main upstream: master + - branch: next + upstream: develop outputs: sha: ${{ steps.commit.outputs.sha }} diff --git a/vendor.sh b/vendor.sh index 9d9a905689d..793e1fbf027 100755 --- a/vendor.sh +++ b/vendor.sh @@ -16,7 +16,7 @@ repo_name=${project} if [ -z "$1" ]; then - upstream_basedir=../../${project} + upstream_basedir=../../../${project} else upstream_basedir="$1" fi From e6304954e98424f8e9d7f70998f18dead832f7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 7 Aug 2025 17:32:49 +0200 Subject: [PATCH 002/154] vendor: Update vendored sources to igraph/igraph@1db733b231a2744fe1cab9973bd0bff3419634a5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: wrap igraph's interruption handler in the Infomap interface to ensure type compatiblity with Infomap's setup fix: Include C++ header chore: Add deps refactor!: igraph_community_leading_eigenvector() takes a history parameter of type igraph_vector_int_t fix: adapt code after merging master into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: update changelog [skip ci] refactor!: igraph_rewire() now takes an igraph_edge_type_sw_t parameter instead of igraph_rewiring_t docs: improve label propagation doc formatting Merge branch 'master' into develop Merge branch 'master' into develop fix: port selection method between Bellman-Ford vs Johnson from Python interface refactor: added weights argument to all shortest path related functions, fixes igraph/igraph#2481 refactor: rename igraph_vector_index_int to igraph_vector_index_in_place, add documentation Merge pull request igraph/igraph#2813 from igraph/feat/directed-leiden fix: do not compile in Infomap's main() and also remove unneeded files and update some missed files to Infoma 2.8.0, including the license fixes igraph/igraph#2814 fix: fix Stimulus function definitions fix: adapt to changed on develop after merging master Merge branch 'master' into develop style: EOL and trailing whitespace fixes chore: updated contributors list feat: igraph_rich_club_sequence() (igraph/igraph#2740) Add coloring verification functions (igraph/igraph#2758) (igraph/igraph#2807) fix: fix header for igraph_invert_permutation() after merging master and update copyright header Merge branch 'master' into develop chore: update changelog [skip ci] feat: igraph_nearest_neighbor_graph() (igraph/igraph#2788) Merge branch 'master' into develop fix: remove duplicate entry of igraph_invert_permutation() from changelog now that it is also on master Merge branch 'master' into develop tests: some cleanup in igraph_maximal_cliques() test tests: check community indexing for Infomap Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop refactor: rename resolution_parameter to resolution in Leiden implementation refactor: shorten names of static functions in Leiden implementation refactor: use "vertex" instead of "node" phrasing in Leiden implementation tests: update tests after removal of POS/NEGINFINITY refactor!: remove IGRAPH_POSINFINITY/NEGINFINITY Merge branch 'master' into develop docs: improve Infomap docs docs: improve Infomap docs fix: improve input validation for Infomap refactor: some validation reordering for clearer errors/warnings and cleanup Merge branch 'master' into develop Merge branch 'master' into develop tests: improve Infomap tests, document that isolated vertices are supported fix: use moduleIndex() in Infomap-to-igraph membership translation as we must ensure that cluster indices < vcount fix: validate graph size before calling Infomap refactor: enable OpenMP for Infomap refactor: leave handling of unweighted graphs up to Infomap chore: update Infomap to 2.8.0 tests: prettify Infomap test refactor: Infomap prettification refactor: add basic validation to Infomap input fix: use appropriate headers in Infomap docs: update Infomap documentation fix: do consider number of trials in Infomap function refactor: rename infomap top-level code to .cpp extension refactor: readability and formatting in Infomap top-level code chore: update Infomap copyright header and remove outdated information Merge branch 'master' into develop Merge branch 'master' into develop chore: include Infomap in acknowledgements [skip ci] fix: adapted new percolation functions to the new API Merge branch 'master' into develop Merge branch 'master' into develop Merge pull request igraph/igraph#2801 from igraph/feat/setup-random fix: remove RNG_BEGIN() macro that creeped back into the codebase Merge branch 'master' into develop feat: igraph_is_simple() can now ignore edge directions Merge branch 'master' into develop refactor: removed experimental marker from several functions, refs igraph/igraph#2576 doc: document that the sortedness of igraph_adjlist_t is not guaranteed refactor!: igraph_adjlist_init_complementer() now takes an igraph_loops_t argument refactor!: deprecated igraph_sparsemat() and igraph_weighted_sparsemat() functions were removed Merge branch 'master' into develop chore: updated changelog fix: fix copyright header in infomap.cc Merge branch 'develop' into update/infomap fix: allow membership == null in igraph_community_infomap() ci: exclude vendor/infomap from coverage calculations refactor: infomap integration CMakeLists.txt cleanup chore: remove unneeded files from vendored infomap source fix: decrease testing precision due to numerical precision / differences. Remove RNG_BEGIN and RNG_END, following igraph/igraph#2583. Merge branch 'develop' into update/infomap test: spaces should not be trimmed refactor: use igraph's RNG instead of the C++ RNG doc: move igraph_community_infomap doc snippet to the right place Merge branch 'develop' into update/infomap Use network from infomap class. Change argument checking style: Change indent Add exception handling for graph to network function Check arguments, handle NULL arguments. Handle directed networks Do not use InfomapWrapper test: Updated tests fix: NULL pointer for interruption fix: pass config Add interruption and exception handling Configure infomap separately, and seed RNG. Extract get membership to separate function Return code length Make infomap silent fix: initialise membership vector Handle NULL node / edge weight vectors Remove exception handling for debugging fix missing sources fix: correct building against infomap Copy infomap source instead of submodule Always use internal build for Infomap. Make Infomap vendored optional dependency cmake: Require CXX 14 because of infomap. infomap: initial rough implementation. cmake: add infomap source files. refactor: Added upstream infomap repository. refactor: remove old implementation of infomap. Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop tests: better tests for community optimal modularity feat: resolution parameter for community_optimal_modularity() Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop refactor!: igraph_barabasi_aging_game() no longer considers an empty outseq vector as missing. refactor!: do not interpret empty outseq vectors are missing in recent_degree_game() and recent_degree_aging_game() Merge pull request igraph/igraph#2688 from igraph/refactor/null-vectors doc: remove accidentally re-added 'scale' parameter documentation from eigenvector centralization Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: fix typos in changelog [skip ci] fix: feedback_vertex_set interface after merging master Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge pull request igraph/igraph#2667 from igraph/refactor/strvector-print refactor!: igraph_vector_reverse() no longer returns an error code Merge branch 'master' into develop refactor!: igraph_vector_swap_elements() no longer returns an error code fix: adapt strvector_swap_elements() after mering master Merge branch 'master' into develop Merge branch 'master' into develop feat: igraph_int_t, refs igraph/igraph#2664 refactor: minor header cleanup refactor: remove unneeded header Merge branch 'master' into develop Merge branch 'master' into develop refactor!: remove vector_binsearch2() Merge branch 'master' into develop refactor!: remove igraph_vector_qsort_ind(), refs igraph/igraph#2616 Merge branch 'master' into develop refactor: remove unnecessary struct names chore: move note about rng_set_default() to beginning of changelog [skip ci] Merge branch 'master' into develop refactor: typed list swap functions no longer return an error code Merge branch 'master' into develop fix: eliminate compiler warning about unused parameter fix: restore GML reader warning about composite attributes, fixes igraph/igraph#2659 chore: comment typos [skip ci] Merge branch 'master' into develop Merge branch 'master' into develop Merge pull request igraph/igraph#2652 from igraph/refactor/all-simple-paths refactor!: remove igraph_array3_t Merge branch 'master' into develop Merge pull request igraph/igraph#2656 from igraph/refactor/internal-vector-functions Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: fix typo in parameter name fix: add missing error check fix: null-dereference in community_optimal_modularity() when passing the null or singleton graph, requesting modularity, but not requesting membership fix: null-dereference in igraph_community_voronoi() when membership == NULL and modularity != NULL fix: igraph_modularity() no longer allows NULL for 'modularity' as this is pointless and wasn't working correctly anyway refactor: readability and variable localization in max flow implementation Merge branch 'master' into develop fuzzer: expand fuzzers fuzzer: expand misc_algos fuzzer Merge branch 'master' into develop fix: work around potential infinite loop in igraph_community_multilevel() by repeated re-randomization of the vertex processing order fixes igraph/igraph#2650 Merge branch 'master' into develop fuzzer: fix another memory leak in misc_algos_weighted fuzzer: improve misc_algos_weighted fuzzer: fix memory leak in misc_algos_weighted fuzzer Merge branch 'master' into develop Merge branch 'master' into develop bench: fix severe memory leak due to repetition in igraph_adjacency() benchmark fuzzer: remove unused data structures from misc_algos_weighted bench: adapt community benchmark for changes on develop bench: more cleanup in benchmarks Merge branch 'master' into develop Merge branch 'master' into develop fuzzing: fix weighted_centrality fuzzer fuzzing: add more fuzzers Merge branch 'master' into develop chore: mean_degree(), count_loops() and hypercube() are no longer experimental refactor!: remove igraph_random_edge_walk() refactor!: remove igraph_zeroin() refactor!: remove igraph_sparsemat_(copy|eye|diag)() refactor!: remove igraph_vector_move_interval2() fix: remove commented assert from vector_ptr_size() feat: igraph_vector_ptr_resize_min() refactor: remove no-longer-needed performance workaround for vector_append from GraphML reader chore: update changelog doc: include missing vector_ptr functions in docs refactor: doubling allocation strategy for vector_ptr_append() feat: igraph_vector_ptr_capacity() refactor: doubling allocation strategy for strvector_append() refactor: doubling allocation strategy for vector_append() refactor: igraph_get_stochastic_sparse() no longer rejects graphs with zero out/in degrees. Closes igraph/igraph#2502 Merge branch 'master' into develop refactor: rename igraph_topology.h to igraph_isomorphism.h refactor!: remove deprecated igraph_transitive_closure_dag() refactor: remove deprecated isomorphism functions refactor!: remove igraph_(read|write)_graph_dimacs() refactor!: remove igraph_subgraph_edges() refactor!: remove the deprecated igraph_laplacian() and igraph_are_connected() Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop refactor!: remove deprecated igraph_get_sparsemat() and igraph_get_stochastic_sparsemat() fix: handle error code in Kruskal implementation Merge branch 'master' into develop chore: update changelog, mention C++14 requirement [skip ci] Merge branch 'master' into develop refactor: remove redundant spanning tree functions as discussed with @ntamas igraph_minimum_spanning_tree() gives access to all available functionality refactor: cleanup in spanning tree functions chore: update changelog to mention spanning tree API refactoring tests: minimum spanning tree benchmark and tests refactor!: refactor spanning tree API to return edge IDs, step two feat: complete spanning tree with Kruskal’s algorithm refactor!: refactor spanning tree to use edge IDs, step one feat: minimum spanning tree with Kurskal's algorithm Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: updated changelog chore: run pre-commit hooks chore: bump VERSION property in shared library Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: error message update doc: fix references to parameter names in igraph_delete_vertices_map() Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: minor cleanup adjlist / inclist docs doc: update HITS and eigenvector centrality docs test: clean up many examples Merge branch 'master' into develop Merge branch 'master' into develop fix: fix functions.yaml Merge branch 'master' into develop Merge branch 'master' into develop Merge pull request igraph/igraph#2627 from igraph/fix/init_adjlist-multiloop-detection Merge branch 'master' into develop Merge pull request igraph/igraph#2625 from igraph/refactor/undirected-hub-authority fuzzing: add graphicality and graph realization fuzzers test: test multi-loop detection/caching with adjlist_init() Merge branch 'master' into develop interfaces: remove unused types chore: update changelog Merge branch 'master' into develop refactor!: remove deprecated igraph_lattice(), igraph_tree(), igraph_erdos_renyi_game(), igraph_bipartite_game() chore: update changelog [skip ci] doc: remove leftover references to deprecated functions in docs Merge branch 'master' into develop refactor!: remove deprecated vector_init_seq() refactor!: remove deprecated vs/vss/es/ess_seq() refactor!: remove deprecated vector/matrix_e/e_ptr/copy() Merge branch 'master' into develop fix: ensure non-negative random perturbation also for undirected eigenvector centrality chore: add note about random initial vector perturbation in eigenvectore-related functions refactor: remove accidentally committed dead code fix: for eigenvector-related centralities, add only positive noise to starting ARPACK vector this eliminates "Error from calculation of a real Schur form" errors when using both vendored ARPACK and LAPACK Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop bench: fix LAD benchmark after merging master into develop Merge pull request igraph/igraph#2621 from igraph/fix/error-text doc: update error code docs Merge branch 'master' into develop Merge pull request igraph/igraph#2620 from igraph/fix/hub-authority-robustness bench: fix benchmarks after merging master into develop Merge branch 'master' into develop refactor: make use of bitsets in community_edge_betweenness() tests: fix example after merging master branch Merge branch 'master' into develop fuzzing: expand algorithm fuzzers Merge branch 'master' into develop Merge branch 'master' into develop fuzz: IGRAPH_LPA_FAST label propagation is now undirected only, refs igraph/igraph#2608 Merge branch 'master' into develop docs: further improvements to community_edges_betweenness() docs docs: improve community_edge_betweenness() docs Merge pull request igraph/igraph#2594 from igraph/refactor/hub-authority chore: typo in changelog [skip ci] Merge pull request igraph/igraph#2592 from igraph/refactor/eigenvector-centrality-mode-support Merge branch 'master' into develop fuzz: compile libxml2 with optimizations Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop fix: fix Stimulus specs after recent merge Merge branch 'master' into develop Merge pull request igraph/igraph#2591 from igraph/perf/adjmat-interation-order bench: improve adj. matrix -> graph conversion benchmark bench: add benchmark for dense adjacency matrix to graph conversion docs: more educational igraph_weighted_adjacency() example docs: add missing docs for weights parameter of igraph_weighted_biadjacency() refactor: do not minimize weights storage in igraph_weighted_biadjacency() fix: add some missing IGRAPH_CHECK after label propagation update Add fast label propagation (igraph/igraph#2451) Merge branch 'master' into develop tests: test biadjacency matrix with zero row or coumn count tests: igraph_weighted_biadjacency tests: finish "incidence" -> "biadjacency" renaming tests: expand igraph_biadjacency tests tests: use "bipartite adjacency matrix" instead of "incidence matrix" refactor!: igraph_biadjacency() now truancates non-integer matrix entires instead of rounding them up refactor!: remove deprecated igraph_incidence() and igraph_get_incidence() refactor: remove unused 'types' parameter of igraph_i_bipartite_game_gnm_multi() refactor!: igraph_biadjacency() now only requires positive entries when creating multi-edges feat: igraph_weighted_biadjacency(), refs igraph/igraph#2414 refactor: cleanup in igraph_biadjacency() refactor!: igraph_get_biadjacency() now takes a weights parameter, refs igraph/igraph#2414 chore: updated pre-commit hooks chore: update changelog test: test NaN passthrough in weighted_adjacency() fix: pass through NaN values when building graph from weighted adjacency matrix refactor: minort cleanup in some games fix: remove RNG_BEGIN/END from igraph_rng_get_dirichlet() as it lead to nested RNG_BEGIN/END calls and it's unnecessary since this function takes an RNG object as input chore: punctuation in error message Merge branch 'master' into develop Merge branch 'master' into develop Merge pull request igraph/igraph#2580 from igraph/refactor/remove-deprecated-1 Merge branch 'master' into develop chore: update changelog tests: update variable naming in community_edge_betweenness() tests docs: update community_edge_betweenness docs and example refactor: edge betweenness community detection now takes separate weights and lengths and uses weights as defined by Newman: Analysis of weighted networks (2004) refactor!: minimum_size_separators() no longer returns any separators for complete graphs Fixes igraph/igraph#1910 Fixes igraph/igraph#2518 Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop fix: `ARPACK_DEFAULTS` typo in functions.yaml (igraph/igraph#2569) Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop refactor: improve readability, eliminate warnings in cattributes implementation Merge branch 'master' into develop fix: fix memory leak in igraph_read_graph_lgl() when weights are present, fixes igraph/igraph#2557 Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop refactor!: removed IGRAPH_ARPACK_... in favour of IGRAPH_EARPACK refactor!: remove IGRAPH_GLP_... error codes refactor!: progress and status handlers now return error codes intact, refs igraph/igraph#2199 refactor!: remove IGRAPH_CPUTIME error code and the time limit feature of igraph_subisomorphic_lad() refactor!: remove IGRAPH_EGLP and IGRAPH_ELAPACK error codes docs: fix doc build (correct typo in function name) Merge branch 'master' into develop docs: complete removal of deprecated igraph_automorphisms() and fix doc build fix: fix signature of igraph_canonical_permutation() Merge branch 'master' into develop fix: update error strings refactor!: remove deprecated IGRAPH_EDRL refactor!: removed unused IGRAPH_ENONZERO and IGRAPH_EATTRIBUTES error codes feat: added IGRAPH_EINVEID error code refactor!: remove IGRAPH_NONSQUARE error code, refs igraph/igraph#1975 refactor!: remove IGRAPH_EINVEVECTOR error code, refs igraph/igraph#1975 feat: added generic, algorithm-agnostic versions of igraph_count_automorphisms(), igraph_automorphism_group() and igraph_canonical_permutation() refactor!: rename BLISS-specific isomorphism functions so they always have _bliss in the suffix - part 2 refactor!: rename BLISS-specific isomorphism functions so they always have _bliss in the suffix Merge branch 'master' into develop fix: fix segfault in GraphML reader refactor: remove unneeded include refactor: remove deprecated igraph_decompose_destroy() Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge pull request igraph/igraph#2470 from igraph/feat/is-biconnected Merge branch 'master' into develop Merge pull request igraph/igraph#2462 from igraph/feat/attribute-record-list Merge branch 'master' into develop fix: re-added missing master header in changelog Merge branch 'master' into develop Merge branch 'master' into develop refactor: consistently use ARPACK_DEFAULTS as the default arpack options chore: updated changelog feat: include Texinfo docs in source tarball fix: fix typo fix: look for either docbook2x-texi or docbook2texi fix: replace utf8 with utf-8 to prevent a warning when building texinfo docs ci: make sure that the Texinfo docs are also built Add target to build documentation in info format docs: clarify that Infomap considers edge directions fuzzer: update libxml2 to 2.12.3 fix: correct header includion in cliquer chore(deps): bump github/codeql-action from 2 to 3 chore(deps): bump actions/upload-artifact from 3 to 4 doc: clarify the effect of loop edges in igraph_similarity_inverse_log_weighted(), closes igraph/igraph#2448 refactor: rename deprecated functions in generated interfaces docs: fix typos refactor: clean up dfs/bfs and their docs refactor: replace void* with const igraph_vector_ptr_t* in attribute-related functions; more refactoring coming soon refactor!: strvector now contains pointers to const Merge branch 'master' into develop refactor: rename igraph_i_attribute_gettype() to igraph_i_attribute_get_type() for sake of consistency refactor: simplify attribute table init, copy and destroy methods chore: post-release tasks Merge branch 'master' into develop fix: fix stimulus function spec Merge branch 'master' into develop fix: community_spinglass_single() now uses igraph_real_t for output parameters that return real values, fixes igraph/igraph#2435 Merge branch 'master' into develop fix: fix jdm unit test and add rate-limited interruption to erdos_renyi_gnm_multi() fix: fix Stimulus type specs Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop fix: fix Stimulus type specs fix: allow interruption for multigaph case of G(n,m) generator Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: fixed line endings and stale whitespace fix!: NCOL and LGL readers now use a default weight of 1, closes igraph/igraph#2395 fix: EDGEWEIGHTS type parameter was renamed to EDGE_WEIGHTS earlier Merge branch 'master' into develop Merge branch 'master' into develop refactor!: igraph_vector_swap() and igraph_matrix_swap() no longer return an error code Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Multi edge support for igraph_bipartite_game_gnm (igraph/igraph#2375) Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop correct number of erdos_renyi arguments in voronoi test chore: fix mismerged changelog refactor!: remove deprecated allocation macros Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop docs: clarify that usage of sub-headers is not supported closes igraph/igraph#2332 Merge branch 'master' into develop refactor: more readable variable named in similarity code Use two vertex selectors in Jaccard and Dice (igraph/igraph#2346) Merge branch 'master' into develop chore: update changelog, mentioning the the Pajek reader/writer now uses the 'name' attribute docs: update Pajek docs, mentioning that the 'name' attribute is used Merge pull request igraph/igraph#2276 from igraph/fix/pajek-names Merge pull request igraph/igraph#2265 from VRajesh7649/feat/erdos_penyi_gnm_multiedges Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop refactor: fixed singular/plural issues with abstract types in types.yaml, now they are consistent fix: fix typo in functions.yaml refactor: rename igraph_delete_vertices_idx() to igraph_delete_vertices_map(), closes igraph/igraph#2310 Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop chore: update changelog [skip ci] refactor: igraph_rng_set_default() now returns old RNG, fixes igraph/igraph#2273 Merge branch 'master' into develop Merge branch 'master' into develop move community_fastgreedy example to tests move community_edge_betweenness example to tests (igraph/igraph#2270) Revert "move community_edge_betweenness example to tests" move community_edge_betweenness example to tests Merge branch 'master' into develop refactor!: igraph_vector_shuffle() no longer returns an error code, closes igraph/igraph#2268 Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop fix: standards-complient definition for igraph_allow_interruption() refactor: replace IGRAPH_SUCCESS by false in IGRAPH_ALLOW_INTERRUPTION() refactor!: interruption handlers now return igraph_bool_t Merge branch 'master' into develop refactor!: removed void* argument of interruption handlers Merge branch 'master' into develop refactor!: igraph_induced_subgraph_map() does not offset the vertex IDs in the mapping any more refactor!: igraph_delete_vertices_idx() does not offset the vertex IDs in the mapping any more Merge branch 'master' into develop Merge branch 'master' into develop Merge branch 'master' into develop add mode parameter to distances_johnson (igraph/igraph#2218) Merge branch 'master' into develop chore: added 'develop' section to changelog Merge branch 'master' into develop Merge branch 'master' into develop refactor: remove unused 'destroy' field from heap data types; ABI-breaking change; refs igraph/igraph#2214 --- R/aaa-auto.R | 1261 ++----- R/games.R | 3 +- R/paths.R | 4 +- R/structural-properties.R | 4 +- R/trees.R | 4 +- patch/0001-fix-include-quotes.patch | 25 - patch/0002-upstream-deps.patch | 28 - patch/0003-Temporary-fix.patch | 25 - patch/0004-Tweak-function-definitions.patch | 154 + ...4-chore-Fix-remaining-Stimulus-types.patch | 63 - src/Makevars.in | 3 +- src/Makevars.ucrt | 3 +- src/Makevars.win | 3 +- src/cpp11.cpp | 150 +- src/rinterface.c | 2040 +++++++---- src/rinterface.h | 3 +- src/rinterface_extra.c | 212 +- src/sources-igraph.mk | 2 +- src/vendor/cigraph/.all-contributorsrc | 27 + src/vendor/cigraph/ACKNOWLEDGEMENTS.md | 9 + src/vendor/cigraph/CHANGELOG.md | 163 +- src/vendor/cigraph/CMakeLists.txt | 4 +- src/vendor/cigraph/CONTRIBUTORS.md | 3 + src/vendor/cigraph/CONTRIBUTORS.txt | 3 + src/vendor/cigraph/codecov.yml | 1 + .../etc/cmake/cpack_install_script.cmake | 5 + .../cigraph/etc/cmake/dependencies.cmake | 16 +- src/vendor/cigraph/etc/cmake/features.cmake | 1 + src/vendor/cigraph/etc/cmake/packaging.cmake | 8 +- src/vendor/cigraph/include/igraph.h | 13 +- src/vendor/cigraph/include/igraph_adjlist.h | 23 +- src/vendor/cigraph/include/igraph_arpack.h | 77 +- src/vendor/cigraph/include/igraph_array.h | 63 - src/vendor/cigraph/include/igraph_array_pmt.h | 54 - .../cigraph/include/igraph_attributes.h | 372 +- src/vendor/cigraph/include/igraph_bipartite.h | 63 +- src/vendor/cigraph/include/igraph_bitset.h | 11 +- .../cigraph/include/igraph_bitset_list.h | 11 +- src/vendor/cigraph/include/igraph_blas.h | 13 +- .../cigraph/include/igraph_centrality.h | 106 +- src/vendor/cigraph/include/igraph_cliques.h | 13 +- .../cigraph/include/igraph_cocitation.h | 31 +- .../cigraph/include/igraph_cohesive_blocks.h | 13 +- src/vendor/cigraph/include/igraph_coloring.h | 40 +- src/vendor/cigraph/include/igraph_community.h | 71 +- src/vendor/cigraph/include/igraph_complex.h | 21 +- .../cigraph/include/igraph_components.h | 22 +- src/vendor/cigraph/include/igraph_config.h.in | 12 +- src/vendor/cigraph/include/igraph_constants.h | 73 +- .../cigraph/include/igraph_constructors.h | 26 +- .../cigraph/include/igraph_conversion.h | 21 +- src/vendor/cigraph/include/igraph_cycles.h | 23 +- src/vendor/cigraph/include/igraph_datatype.h | 15 +- src/vendor/cigraph/include/igraph_decls.h | 18 +- src/vendor/cigraph/include/igraph_dqueue.h | 13 +- .../cigraph/include/igraph_dqueue_pmt.h | 10 +- src/vendor/cigraph/include/igraph_eigen.h | 13 +- src/vendor/cigraph/include/igraph_embedding.h | 13 +- src/vendor/cigraph/include/igraph_epidemics.h | 13 +- src/vendor/cigraph/include/igraph_error.h | 122 +- src/vendor/cigraph/include/igraph_eulerian.h | 13 +- src/vendor/cigraph/include/igraph_flow.h | 13 +- src/vendor/cigraph/include/igraph_foreign.h | 23 +- src/vendor/cigraph/include/igraph_games.h | 39 +- .../cigraph/include/igraph_graph_list.h | 15 +- .../cigraph/include/igraph_graphicality.h | 12 +- src/vendor/cigraph/include/igraph_graphlets.h | 13 +- src/vendor/cigraph/include/igraph_heap.h | 13 +- src/vendor/cigraph/include/igraph_heap_pmt.h | 10 +- src/vendor/cigraph/include/igraph_hrg.h | 13 +- src/vendor/cigraph/include/igraph_interface.h | 74 +- src/vendor/cigraph/include/igraph_interrupt.h | 27 +- ...igraph_topology.h => igraph_isomorphism.h} | 80 +- src/vendor/cigraph/include/igraph_iterators.h | 35 +- src/vendor/cigraph/include/igraph_lapack.h | 13 +- src/vendor/cigraph/include/igraph_layout.h | 13 +- src/vendor/cigraph/include/igraph_lsap.h | 21 +- src/vendor/cigraph/include/igraph_matching.h | 12 +- src/vendor/cigraph/include/igraph_matrix.h | 16 +- .../cigraph/include/igraph_matrix_list.h | 12 +- .../cigraph/include/igraph_matrix_pmt.h | 18 +- src/vendor/cigraph/include/igraph_memory.h | 19 +- .../include/igraph_microscopic_update.h | 61 - src/vendor/cigraph/include/igraph_mixing.h | 13 +- src/vendor/cigraph/include/igraph_motifs.h | 23 +- .../cigraph/include/igraph_neighborhood.h | 13 +- src/vendor/cigraph/include/igraph_nongraph.h | 25 +- src/vendor/cigraph/include/igraph_operators.h | 34 +- src/vendor/cigraph/include/igraph_paths.h | 250 +- src/vendor/cigraph/include/igraph_pmt.h | 17 +- src/vendor/cigraph/include/igraph_pmt_off.h | 9 +- src/vendor/cigraph/include/igraph_progress.h | 55 +- src/vendor/cigraph/include/igraph_psumtree.h | 13 +- src/vendor/cigraph/include/igraph_qsort.h | 13 +- src/vendor/cigraph/include/igraph_random.h | 37 +- .../cigraph/include/igraph_reachability.h | 6 +- src/vendor/cigraph/include/igraph_sampling.h | 45 + src/vendor/cigraph/include/igraph_scan.h | 13 +- .../cigraph/include/igraph_separators.h | 17 +- src/vendor/cigraph/include/igraph_setup.h | 31 + src/vendor/cigraph/include/igraph_sparsemat.h | 29 +- src/vendor/cigraph/include/igraph_spatial.h | 55 + src/vendor/cigraph/include/igraph_stack.h | 13 +- src/vendor/cigraph/include/igraph_stack_pmt.h | 9 +- src/vendor/cigraph/include/igraph_statusbar.h | 36 +- .../cigraph/include/igraph_structural.h | 62 +- src/vendor/cigraph/include/igraph_strvector.h | 39 +- .../cigraph/include/igraph_threading.h.in | 13 +- .../cigraph/include/igraph_transitivity.h | 19 +- .../cigraph/include/igraph_typed_list_pmt.h | 13 +- src/vendor/cigraph/include/igraph_types.h | 26 +- src/vendor/cigraph/include/igraph_vector.h | 39 +- .../cigraph/include/igraph_vector_list.h | 12 +- .../cigraph/include/igraph_vector_pmt.h | 33 +- .../cigraph/include/igraph_vector_ptr.h | 20 +- .../cigraph/include/igraph_vector_type.h | 9 +- .../cigraph/include/igraph_version.h.in | 13 +- src/vendor/cigraph/include/igraph_visitor.h | 13 +- src/vendor/cigraph/interfaces/functions.yaml | 733 ++-- src/vendor/cigraph/interfaces/types.yaml | 72 +- src/vendor/cigraph/src/CMakeLists.txt | 21 +- .../cigraph/src/centrality/betweenness.c | 12 +- .../src/centrality/centrality_internal.h | 6 +- .../cigraph/src/centrality/centrality_other.c | 28 +- .../cigraph/src/centrality/centralization.c | 138 +- src/vendor/cigraph/src/centrality/closeness.c | 6 +- src/vendor/cigraph/src/centrality/coreness.c | 7 +- .../cigraph/src/centrality/eigenvector.c | 254 +- .../cigraph/src/centrality/hub_authority.c | 282 +- src/vendor/cigraph/src/centrality/pagerank.c | 14 +- src/vendor/cigraph/src/centrality/prpack.cpp | 1 - .../centrality/prpack/prpack_igraph_graph.cpp | 2 +- .../cigraph/src/centrality/prpack_internal.h | 5 +- src/vendor/cigraph/src/centrality/truss.cpp | 6 +- .../cigraph/src/cliques/cliquer_internal.h | 4 +- src/vendor/cigraph/src/cliques/cliques.c | 3 +- src/vendor/cigraph/src/cliques/glet.c | 27 +- .../cigraph/src/cliques/maximal_cliques.c | 1 - .../src/cliques/maximal_cliques_template.h | 1 - .../cigraph/src/community/edge_betweenness.c | 160 +- .../cigraph/src/community/fast_modularity.c | 18 +- src/vendor/cigraph/src/community/fluid.c | 60 +- src/vendor/cigraph/src/community/infomap.cpp | 258 ++ .../cigraph/src/community/infomap/infomap.cc | 323 -- .../community/infomap/infomap_FlowGraph.cc | 382 -- .../src/community/infomap/infomap_FlowGraph.h | 81 - .../src/community/infomap/infomap_Greedy.cc | 522 --- .../src/community/infomap/infomap_Greedy.h | 74 - .../src/community/infomap/infomap_Node.h | 52 - .../cigraph/src/community/label_propagation.c | 704 +++- .../src/community/leading_eigenvector.c | 63 +- src/vendor/cigraph/src/community/leiden.c | 835 +++-- src/vendor/cigraph/src/community/louvain.c | 6 +- src/vendor/cigraph/src/community/modularity.c | 2 - .../src/community/optimal_modularity.c | 25 +- .../src/community/spinglass/NetDataTypes.cpp | 1 - .../src/community/spinglass/NetDataTypes.h | 1 - .../src/community/spinglass/NetRoutines.cpp | 1 - .../src/community/spinglass/NetRoutines.h | 1 - .../src/community/spinglass/clustertool.cpp | 29 +- .../src/community/spinglass/pottsmodel_2.cpp | 5 +- .../src/community/spinglass/pottsmodel_2.h | 5 +- src/vendor/cigraph/src/community/voronoi.c | 13 +- .../src/community/walktrap/walktrap.cpp | 1 - .../walktrap/walktrap_communities.cpp | 1 - .../community/walktrap/walktrap_communities.h | 1 - .../src/community/walktrap/walktrap_graph.cpp | 1 - .../src/community/walktrap/walktrap_graph.h | 1 - .../src/community/walktrap/walktrap_heap.cpp | 1 - .../src/community/walktrap/walktrap_heap.h | 1 - src/vendor/cigraph/src/config.h.in | 1 + .../src/connectivity/cohesive_blocks.c | 7 +- .../cigraph/src/connectivity/components.c | 65 +- .../cigraph/src/connectivity/percolation.c | 8 +- .../cigraph/src/connectivity/reachability.c | 2 - .../cigraph/src/connectivity/separators.c | 42 +- .../cigraph/src/constructors/adjacency.c | 387 +- .../cigraph/src/constructors/atlas-edges.h | 5 +- .../src/constructors/basic_constructors.c | 11 +- .../cigraph/src/constructors/de_bruijn.c | 1 - src/vendor/cigraph/src/constructors/famous.c | 3 - src/vendor/cigraph/src/constructors/full.c | 1 - src/vendor/cigraph/src/constructors/kautz.c | 1 - .../cigraph/src/constructors/lattices.c | 4 - src/vendor/cigraph/src/constructors/lcf.c | 58 +- .../cigraph/src/constructors/linegraph.c | 7 +- .../cigraph/src/constructors/mycielskian.c | 10 +- src/vendor/cigraph/src/constructors/prufer.c | 1 - src/vendor/cigraph/src/constructors/regular.c | 41 +- src/vendor/cigraph/src/constructors/trees.c | 2 - src/vendor/cigraph/src/core/array.c | 50 - src/vendor/cigraph/src/core/array.pmt | 110 - src/vendor/cigraph/src/core/buckets.c | 1 - src/vendor/cigraph/src/core/buckets.h | 5 +- src/vendor/cigraph/src/core/cutheap.c | 1 - src/vendor/cigraph/src/core/cutheap.h | 5 +- src/vendor/cigraph/src/core/dqueue.c | 1 - src/vendor/cigraph/src/core/dqueue.pmt | 13 - src/vendor/cigraph/src/core/error.c | 105 +- src/vendor/cigraph/src/core/estack.c | 1 - src/vendor/cigraph/src/core/estack.h | 5 +- .../cigraph/src/core/fixed_vectorlist.c | 1 - .../cigraph/src/core/fixed_vectorlist.h | 5 +- src/vendor/cigraph/src/core/grid.h | 5 +- src/vendor/cigraph/src/core/heap.c | 1 - src/vendor/cigraph/src/core/heap.pmt | 9 +- src/vendor/cigraph/src/core/indheap.c | 113 +- src/vendor/cigraph/src/core/indheap.h | 11 +- src/vendor/cigraph/src/core/interruption.c | 9 +- src/vendor/cigraph/src/core/interruption.h | 14 +- src/vendor/cigraph/src/core/marked_queue.c | 1 - src/vendor/cigraph/src/core/marked_queue.h | 5 +- src/vendor/cigraph/src/core/matrix.c | 14 - src/vendor/cigraph/src/core/matrix.pmt | 44 +- src/vendor/cigraph/src/core/matrix_list.c | 1 - src/vendor/cigraph/src/core/printing.c | 1 - src/vendor/cigraph/src/core/progress.c | 19 +- src/vendor/cigraph/src/core/psumtree.c | 1 - src/vendor/cigraph/src/core/set.h | 4 +- src/vendor/cigraph/src/core/setup.c | 68 + src/vendor/cigraph/src/core/sparsemat.c | 297 +- src/vendor/cigraph/src/core/stack.c | 1 - src/vendor/cigraph/src/core/stack.pmt | 1 - src/vendor/cigraph/src/core/statusbar.c | 23 +- src/vendor/cigraph/src/core/strvector.c | 171 +- src/vendor/cigraph/src/core/trie.c | 1 - src/vendor/cigraph/src/core/trie.h | 5 +- src/vendor/cigraph/src/core/typed_list.pmt | 42 +- src/vendor/cigraph/src/core/vector.c | 153 +- src/vendor/cigraph/src/core/vector.pmt | 193 +- src/vendor/cigraph/src/core/vector_list.c | 1 - src/vendor/cigraph/src/core/vector_ptr.c | 105 +- src/vendor/cigraph/src/flow/flow.c | 159 +- src/vendor/cigraph/src/flow/flow_conversion.c | 1 - src/vendor/cigraph/src/flow/flow_internal.h | 5 +- src/vendor/cigraph/src/flow/st-cuts.c | 24 +- src/vendor/cigraph/src/games/barabasi.c | 40 +- .../cigraph/src/games/callaway_traits.c | 6 - src/vendor/cigraph/src/games/chung_lu.c | 2 - src/vendor/cigraph/src/games/citations.c | 14 - src/vendor/cigraph/src/games/correlated.c | 8 +- .../cigraph/src/games/degree_sequence.c | 69 +- .../degree_sequence_vl/degree_sequence_vl.h | 4 +- .../gengraph_mr-connected.cpp | 6 - src/vendor/cigraph/src/games/dotproduct.c | 191 +- src/vendor/cigraph/src/games/erdos_renyi.c | 523 ++- src/vendor/cigraph/src/games/establishment.c | 6 - src/vendor/cigraph/src/games/forestfire.c | 5 - src/vendor/cigraph/src/games/grg.c | 6 - src/vendor/cigraph/src/games/growing_random.c | 6 - src/vendor/cigraph/src/games/islands.c | 8 +- src/vendor/cigraph/src/games/k_regular.c | 2 - src/vendor/cigraph/src/games/preference.c | 10 - src/vendor/cigraph/src/games/recent_degree.c | 32 +- src/vendor/cigraph/src/games/sbm.c | 15 +- src/vendor/cigraph/src/games/static_fitness.c | 6 +- src/vendor/cigraph/src/games/tree.c | 8 - src/vendor/cigraph/src/games/watts_strogatz.c | 2 - src/vendor/cigraph/src/graph/adjlist.c | 215 +- src/vendor/cigraph/src/graph/attributes.c | 634 +++- src/vendor/cigraph/src/graph/attributes.h | 40 +- src/vendor/cigraph/src/graph/basic_query.c | 30 - src/vendor/cigraph/src/graph/caching.h | 4 +- src/vendor/cigraph/src/graph/cattributes.c | 3233 +++++------------ src/vendor/cigraph/src/graph/graph_list.c | 1 - src/vendor/cigraph/src/graph/internal.h | 14 +- src/vendor/cigraph/src/graph/iterators.c | 164 +- src/vendor/cigraph/src/graph/type_common.c | 68 +- .../cigraph/src/graph/type_indexededgelist.c | 358 +- src/vendor/cigraph/src/graph/visitors.c | 5 +- src/vendor/cigraph/src/hrg/hrg.cc | 43 +- .../cigraph/src/internal/glpk_support.c | 25 +- .../cigraph/src/internal/glpk_support.h | 14 +- .../cigraph/src/internal/gmp_internal.h | 2 - src/vendor/cigraph/src/internal/hacks.c | 1 - src/vendor/cigraph/src/internal/hacks.h | 5 +- src/vendor/cigraph/src/internal/utils.c | 2 +- src/vendor/cigraph/src/internal/zeroin.c | 201 - src/vendor/cigraph/src/io/dimacs.c | 31 - src/vendor/cigraph/src/io/dl-lexer.l | 5 +- src/vendor/cigraph/src/io/dl.c | 40 +- src/vendor/cigraph/src/io/dot.c | 1 - src/vendor/cigraph/src/io/edgelist.c | 1 - src/vendor/cigraph/src/io/gml-lexer.l | 4 +- src/vendor/cigraph/src/io/gml-tree.h | 4 +- src/vendor/cigraph/src/io/gml.c | 188 +- src/vendor/cigraph/src/io/graphdb.c | 1 - src/vendor/cigraph/src/io/graphml.c | 424 +-- src/vendor/cigraph/src/io/leda.c | 5 +- src/vendor/cigraph/src/io/lgl-lexer.l | 4 +- src/vendor/cigraph/src/io/lgl-parser.y | 2 +- src/vendor/cigraph/src/io/lgl.c | 53 +- src/vendor/cigraph/src/io/ncol-lexer.l | 4 +- src/vendor/cigraph/src/io/ncol-parser.y | 2 +- src/vendor/cigraph/src/io/ncol.c | 52 +- src/vendor/cigraph/src/io/pajek-header.h | 6 +- src/vendor/cigraph/src/io/pajek-lexer.l | 4 +- src/vendor/cigraph/src/io/pajek-parser.y | 240 +- src/vendor/cigraph/src/io/pajek.c | 99 +- src/vendor/cigraph/src/io/parse_utils.c | 4 - src/vendor/cigraph/src/isomorphism/bliss.cc | 173 +- .../cigraph/src/isomorphism/isoclasses.c | 7 +- .../cigraph/src/isomorphism/isoclasses.h | 5 +- .../src/isomorphism/isomorphism_misc.c | 3 +- src/vendor/cigraph/src/isomorphism/lad.c | 20 +- src/vendor/cigraph/src/isomorphism/queries.c | 30 +- src/vendor/cigraph/src/isomorphism/vf2.c | 45 +- src/vendor/cigraph/src/layout/circular.c | 2 - .../cigraph/src/layout/davidson_harel.c | 18 +- .../cigraph/src/layout/drl/drl_layout.cpp | 4 - .../cigraph/src/layout/drl/drl_layout_3d.cpp | 4 - .../cigraph/src/layout/fruchterman_reingold.c | 6 - src/vendor/cigraph/src/layout/gem.c | 13 +- src/vendor/cigraph/src/layout/graphopt.c | 2 - src/vendor/cigraph/src/layout/large_graph.c | 10 +- .../cigraph/src/layout/layout_bipartite.c | 2 - src/vendor/cigraph/src/layout/layout_grid.c | 2 - .../cigraph/src/layout/layout_internal.h | 5 +- src/vendor/cigraph/src/layout/layout_random.c | 14 - src/vendor/cigraph/src/layout/mds.c | 9 +- src/vendor/cigraph/src/layout/merge_dla.c | 29 +- src/vendor/cigraph/src/layout/merge_grid.h | 4 +- .../cigraph/src/layout/reingold_tilford.c | 6 +- src/vendor/cigraph/src/layout/sugiyama.c | 36 +- src/vendor/cigraph/src/layout/umap.c | 8 +- src/vendor/cigraph/src/linalg/arpack.c | 276 +- .../cigraph/src/linalg/arpack_internal.h | 5 +- src/vendor/cigraph/src/linalg/blas.c | 2 - src/vendor/cigraph/src/linalg/blas_internal.h | 6 +- src/vendor/cigraph/src/linalg/eigen.c | 5 +- src/vendor/cigraph/src/linalg/lapack.c | 73 +- .../cigraph/src/linalg/lapack_internal.h | 6 +- src/vendor/cigraph/src/math/complex.c | 15 - src/vendor/cigraph/src/math/safe_intop.h | 4 +- src/vendor/cigraph/src/math/utils.c | 21 - src/vendor/cigraph/src/misc/bipartite.c | 569 ++- src/vendor/cigraph/src/misc/chordality.c | 1 - src/vendor/cigraph/src/misc/cocitation.c | 60 +- src/vendor/cigraph/src/misc/coloring.c | 221 +- src/vendor/cigraph/src/misc/conversion.c | 168 +- src/vendor/cigraph/src/misc/cycle_bases.c | 2 +- .../cigraph/src/misc/degree_sequence.cpp | 4 +- src/vendor/cigraph/src/misc/embedding.c | 11 +- .../cigraph/src/misc/feedback_arc_set.c | 33 +- .../cigraph/src/misc/feedback_arc_set.h | 4 +- src/vendor/cigraph/src/misc/graphicality.c | 5 +- src/vendor/cigraph/src/misc/graphicality.h | 27 + src/vendor/cigraph/src/misc/matching.c | 35 +- .../cigraph/src/misc/microscopic_update.c | 1209 ------ src/vendor/cigraph/src/misc/mixing.c | 19 +- src/vendor/cigraph/src/misc/motifs.c | 68 +- src/vendor/cigraph/src/misc/order_cycle.h | 4 +- src/vendor/cigraph/src/misc/other.c | 1 - src/vendor/cigraph/src/misc/power_law_fit.c | 9 - src/vendor/cigraph/src/misc/scan.c | 43 +- src/vendor/cigraph/src/misc/sir.c | 21 +- src/vendor/cigraph/src/misc/spanning_trees.c | 486 ++- src/vendor/cigraph/src/operators/add_edge.c | 2 - .../cigraph/src/operators/complementer.c | 6 +- src/vendor/cigraph/src/operators/compose.c | 5 +- .../src/operators/connect_neighborhood.c | 14 +- src/vendor/cigraph/src/operators/contract.c | 4 +- src/vendor/cigraph/src/operators/difference.c | 4 +- .../cigraph/src/operators/disjoint_union.c | 1 - .../cigraph/src/operators/intersection.c | 1 - src/vendor/cigraph/src/operators/join.c | 3 - .../cigraph/src/operators/misc_internal.c | 1 - .../cigraph/src/operators/misc_internal.h | 5 +- src/vendor/cigraph/src/operators/permute.c | 26 +- src/vendor/cigraph/src/operators/products.c | 192 +- src/vendor/cigraph/src/operators/reverse.c | 3 +- src/vendor/cigraph/src/operators/rewire.c | 209 +- .../cigraph/src/operators/rewire_edges.c | 20 +- .../cigraph/src/operators/rewire_internal.h | 10 +- src/vendor/cigraph/src/operators/simplify.c | 4 +- src/vendor/cigraph/src/operators/subgraph.c | 52 +- src/vendor/cigraph/src/operators/subgraph.h | 6 +- src/vendor/cigraph/src/operators/union.c | 3 - .../cigraph/src/paths/all_shortest_paths.c | 41 +- src/vendor/cigraph/src/paths/astar.c | 2 - src/vendor/cigraph/src/paths/bellman_ford.c | 24 +- src/vendor/cigraph/src/paths/dijkstra.c | 28 +- src/vendor/cigraph/src/paths/distances.c | 459 +-- src/vendor/cigraph/src/paths/eulerian.c | 2 - src/vendor/cigraph/src/paths/floyd_warshall.c | 2 - src/vendor/cigraph/src/paths/johnson.c | 81 +- src/vendor/cigraph/src/paths/random_walk.c | 56 - src/vendor/cigraph/src/paths/shortest_paths.c | 283 +- src/vendor/cigraph/src/paths/simple_paths.c | 118 +- src/vendor/cigraph/src/paths/sparsifier.c | 2 - src/vendor/cigraph/src/paths/unweighted.c | 129 +- src/vendor/cigraph/src/paths/voronoi.c | 4 - src/vendor/cigraph/src/paths/widest_paths.c | 2 - .../cigraph/src/properties/basic_properties.c | 14 +- src/vendor/cigraph/src/properties/complete.c | 13 +- .../cigraph/src/properties/constraint.c | 20 +- .../src/properties/convergence_degree.c | 2 - src/vendor/cigraph/src/properties/dag.c | 133 +- src/vendor/cigraph/src/properties/degrees.c | 78 +- src/vendor/cigraph/src/properties/girth.c | 2 - src/vendor/cigraph/src/properties/loops.c | 4 - .../cigraph/src/properties/multiplicity.c | 50 +- .../cigraph/src/properties/neighborhood.c | 8 +- src/vendor/cigraph/src/properties/perfect.c | 9 +- .../src/properties/properties_internal.h | 5 +- src/vendor/cigraph/src/properties/rich_club.c | 166 + src/vendor/cigraph/src/properties/spectral.c | 58 - src/vendor/cigraph/src/properties/trees.c | 14 +- src/vendor/cigraph/src/properties/triangles.c | 30 +- .../src/properties/triangles_template.h | 4 +- .../src/properties/triangles_template1.h | 2 - src/vendor/cigraph/src/random/random.c | 88 +- .../cigraph/src/random/random_device.cpp | 43 + .../cigraph/src/random/random_internal.h | 35 +- src/vendor/cigraph/src/random/rng_pcg32.c | 6 +- src/vendor/cigraph/src/random/sampling.c | 192 + .../cigraph/src/spatial/nearest_neighbor.cpp | 283 ++ src/vendor/cigraph/vendor/CMakeLists.txt | 1 + src/vendor/cigraph/vendor/cs/cs_randperm.c | 2 - .../cigraph/vendor/infomap/CITATION.cff | 16 + .../cigraph/vendor/infomap/CMakeLists.txt | 48 + .../cigraph/vendor/infomap/LICENSE_GPLv3.txt | 674 ++++ src/vendor/cigraph/vendor/infomap/README.rst | 162 + .../cigraph/vendor/infomap/src/Infomap.h | 103 + .../infomap/src/core/BiasedMapEquation.cpp | 238 ++ .../infomap/src/core/BiasedMapEquation.h | 178 + .../vendor/infomap/src/core/FlowData.h | 165 + .../vendor/infomap/src/core/InfoEdge.cpp | 26 + .../vendor/infomap/src/core/InfoEdge.h | 47 + .../vendor/infomap/src/core/InfoNode.cpp | 405 +++ .../vendor/infomap/src/core/InfoNode.h | 374 ++ .../vendor/infomap/src/core/InfomapBase.cpp | 2182 +++++++++++ .../vendor/infomap/src/core/InfomapBase.h | 583 +++ .../vendor/infomap/src/core/InfomapConfig.h | 137 + .../infomap/src/core/InfomapOptimizer.h | 764 ++++ .../infomap/src/core/InfomapOptimizerBase.h | 111 + .../vendor/infomap/src/core/MapEquation.h | 337 ++ .../infomap/src/core/MemMapEquation.cpp | 449 +++ .../vendor/infomap/src/core/MemMapEquation.h | 172 + .../infomap/src/core/MetaMapEquation.cpp | 269 ++ .../vendor/infomap/src/core/MetaMapEquation.h | 183 + .../vendor/infomap/src/core/StateNetwork.cpp | 329 ++ .../vendor/infomap/src/core/StateNetwork.h | 216 ++ .../src/core/iterators/InfomapIterator.cpp | 238 ++ .../src/core/iterators/InfomapIterator.h | 341 ++ .../infomap/src/core/iterators/IterWrapper.h | 32 + .../src/core/iterators/infomapIterators.h | 369 ++ .../src/core/iterators/treeIterators.h | 628 ++++ .../vendor/infomap/src/io/ClusterMap.cpp | 189 + .../vendor/infomap/src/io/ClusterMap.h | 52 + .../cigraph/vendor/infomap/src/io/Config.cpp | 264 ++ .../cigraph/vendor/infomap/src/io/Config.h | 268 ++ .../cigraph/vendor/infomap/src/io/Network.cpp | 990 +++++ .../cigraph/vendor/infomap/src/io/Network.h | 214 ++ .../cigraph/vendor/infomap/src/io/Output.cpp | 629 ++++ .../cigraph/vendor/infomap/src/io/Output.h | 36 + .../infomap/src/io/ProgramInterface.cpp | 341 ++ .../vendor/infomap/src/io/ProgramInterface.h | 417 +++ .../cigraph/vendor/infomap/src/io/SafeFile.h | 87 + .../cigraph/vendor/infomap/src/utils/Date.h | 69 + .../vendor/infomap/src/utils/FileURI.cpp | 50 + .../vendor/infomap/src/utils/FileURI.h | 54 + .../infomap/src/utils/FlowCalculator.cpp | 898 +++++ .../vendor/infomap/src/utils/FlowCalculator.h | 75 + .../cigraph/vendor/infomap/src/utils/Log.cpp | 17 + .../cigraph/vendor/infomap/src/utils/Log.h | 103 + .../vendor/infomap/src/utils/MetaCollection.h | 153 + .../cigraph/vendor/infomap/src/utils/Random.h | 45 + .../vendor/infomap/src/utils/Stopwatch.h | 103 + .../vendor/infomap/src/utils/VectorMap.h | 82 + .../vendor/infomap/src/utils/convert.h | 216 ++ .../vendor/infomap/src/utils/infomath.h | 57 + .../cigraph/vendor/infomap/src/version.h | 19 + .../vendor/lapack/fortran_intrinsics.c | 1 - .../cigraph/vendor/nanoflann/nanoflann.hpp | 2740 ++++++++++++++ src/vendor/cigraph/vendor/plfit/gss.h | 4 +- src/vendor/cigraph/vendor/plfit/hzeta.h | 4 +- src/vendor/cigraph/vendor/plfit/kolmogorov.h | 4 +- src/vendor/cigraph/vendor/plfit/lbfgs.h | 14 +- src/vendor/cigraph/vendor/plfit/plfit.c | 1 - src/vendor/cigraph/vendor/plfit/plfit.h | 5 +- src/vendor/cigraph/vendor/plfit/plfit_decls.h | 12 +- src/vendor/cigraph/vendor/plfit/plfit_error.h | 4 +- src/vendor/cigraph/vendor/plfit/plfit_mt.h | 4 +- .../cigraph/vendor/plfit/plfit_sampling.h | 4 +- src/vendor/igraph_config.h | 4 +- src/vendor/igraph_threading.h | 13 +- src/vendor/igraph_version.h | 17 +- src/vendor/io/dl-lexer.c | 67 +- src/vendor/io/gml-lexer.c | 4 +- src/vendor/io/lgl-lexer.c | 4 +- src/vendor/io/lgl-parser.c | 2 +- src/vendor/io/ncol-lexer.c | 4 +- src/vendor/io/ncol-parser.c | 2 +- src/vendor/io/pajek-lexer.c | 4 +- src/vendor/io/pajek-parser.c | 562 +-- src/vendor/io/parsers/dl-lexer.h | 2 +- src/vendor/io/parsers/pajek-parser.h | 2 +- tools/build-requirements.txt | 2 +- tools/stimulus/functions-R.yaml | 174 +- tools/stimulus/types-RC.yaml | 62 +- tools/stimulus/types-RR.yaml | 40 +- 502 files changed, 31439 insertions(+), 16626 deletions(-) delete mode 100644 patch/0001-fix-include-quotes.patch delete mode 100644 patch/0002-upstream-deps.patch delete mode 100644 patch/0003-Temporary-fix.patch create mode 100644 patch/0004-Tweak-function-definitions.patch delete mode 100644 patch/0004-chore-Fix-remaining-Stimulus-types.patch delete mode 100644 src/vendor/cigraph/include/igraph_array.h delete mode 100644 src/vendor/cigraph/include/igraph_array_pmt.h rename src/vendor/cigraph/include/{igraph_topology.h => igraph_isomorphism.h} (83%) delete mode 100644 src/vendor/cigraph/include/igraph_microscopic_update.h create mode 100644 src/vendor/cigraph/include/igraph_sampling.h create mode 100644 src/vendor/cigraph/include/igraph_setup.h create mode 100644 src/vendor/cigraph/include/igraph_spatial.h create mode 100644 src/vendor/cigraph/src/community/infomap.cpp delete mode 100644 src/vendor/cigraph/src/community/infomap/infomap.cc delete mode 100644 src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.cc delete mode 100644 src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.h delete mode 100644 src/vendor/cigraph/src/community/infomap/infomap_Greedy.cc delete mode 100644 src/vendor/cigraph/src/community/infomap/infomap_Greedy.h delete mode 100644 src/vendor/cigraph/src/community/infomap/infomap_Node.h delete mode 100644 src/vendor/cigraph/src/core/array.c delete mode 100644 src/vendor/cigraph/src/core/array.pmt create mode 100644 src/vendor/cigraph/src/core/setup.c delete mode 100644 src/vendor/cigraph/src/internal/zeroin.c create mode 100644 src/vendor/cigraph/src/misc/graphicality.h delete mode 100644 src/vendor/cigraph/src/misc/microscopic_update.c create mode 100644 src/vendor/cigraph/src/properties/rich_club.c create mode 100644 src/vendor/cigraph/src/random/random_device.cpp create mode 100644 src/vendor/cigraph/src/random/sampling.c create mode 100644 src/vendor/cigraph/src/spatial/nearest_neighbor.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/CITATION.cff create mode 100644 src/vendor/cigraph/vendor/infomap/CMakeLists.txt create mode 100644 src/vendor/cigraph/vendor/infomap/LICENSE_GPLv3.txt create mode 100644 src/vendor/cigraph/vendor/infomap/README.rst create mode 100644 src/vendor/cigraph/vendor/infomap/src/Infomap.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/FlowData.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfoNode.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfoNode.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfomapConfig.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/iterators/IterWrapper.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/iterators/infomapIterators.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/core/iterators/treeIterators.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/Config.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/Config.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/Network.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/Network.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/Output.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/Output.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/io/SafeFile.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/Date.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/FileURI.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/FileURI.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/Log.cpp create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/Log.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/MetaCollection.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/Random.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/Stopwatch.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/VectorMap.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/convert.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/utils/infomath.h create mode 100644 src/vendor/cigraph/vendor/infomap/src/version.h create mode 100644 src/vendor/cigraph/vendor/nanoflann/nanoflann.hpp diff --git a/R/aaa-auto.R b/R/aaa-auto.R index d0f88a35744..89acea8e617 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 } @@ -268,7 +268,7 @@ kautz_impl <- function(m, n) { res } -lcf_vector_impl <- function(n, shifts, repeats=1) { +lcf_impl <- function(n, shifts, repeats=1) { # Argument checks n <- as.numeric(n) shifts <- as.numeric(shifts) @@ -276,11 +276,7 @@ lcf_vector_impl <- function(n, shifts, repeats=1) { on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_lcf_vector, n, shifts, repeats) - - if (igraph_opt("add.params")) { - res$name <- 'LCF graph' - } + res <- .Call(R_igraph_lcf, n, shifts, repeats) res } @@ -435,16 +431,31 @@ erdos_renyi_game_gnp_impl <- function(n, p, directed=FALSE, loops=FALSE) { res } -erdos_renyi_game_gnm_impl <- function(n, m, directed=FALSE, loops=FALSE) { +erdos_renyi_game_gnm_impl <- function(n, m, directed=FALSE, loops=FALSE, multiple=FALSE) { # Argument checks n <- as.numeric(n) m <- as.numeric(m) directed <- as.logical(directed) loops <- as.logical(loops) + multiple <- as.logical(multiple) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_erdos_renyi_game_gnm, n, m, directed, loops) + res <- .Call(R_igraph_erdos_renyi_game_gnm, n, m, directed, loops, multiple) + + res +} + +iea_game_impl <- function(n, m, directed=FALSE, loops=FALSE) { + # Argument checks + n <- as.numeric(n) + m <- as.numeric(m) + directed <- as.logical(directed) + loops <- as.logical(loops) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_iea_game, n, m, directed, loops) res } @@ -769,46 +780,6 @@ dot_product_game_impl <- function(vecs, directed=FALSE) { res } -sample_sphere_surface_impl <- function(dim, n=1, radius=1, positive=TRUE) { - # Argument checks - dim <- as.numeric(dim) - n <- as.numeric(n) - radius <- as.numeric(radius) - positive <- as.logical(positive) - - on.exit( .Call(R_igraph_finalizer) ) - # Function call - res <- .Call(R_igraph_sample_sphere_surface, dim, n, radius, positive) - - res -} - -sample_sphere_volume_impl <- function(dim, n=1, radius=1, positive=TRUE) { - # Argument checks - dim <- as.numeric(dim) - n <- as.numeric(n) - radius <- as.numeric(radius) - positive <- as.logical(positive) - - on.exit( .Call(R_igraph_finalizer) ) - # Function call - res <- .Call(R_igraph_sample_sphere_volume, dim, n, radius, positive) - - res -} - -sample_dirichlet_impl <- function(n, alpha) { - # Argument checks - n <- as.numeric(n) - alpha <- as.numeric(alpha) - - on.exit( .Call(R_igraph_finalizer) ) - # Function call - res <- .Call(R_igraph_sample_dirichlet, n, alpha) - - res -} - are_adjacent_impl <- function(graph, v1, v2) { # Argument checks ensure_igraph(graph) @@ -833,14 +804,6 @@ closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "tot ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) @@ -857,14 +820,6 @@ closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } normalized <- as.logical(normalized) cutoff <- as.numeric(cutoff) @@ -877,7 +832,7 @@ closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all res } -get_shortest_path_impl <- function(graph, from, to, mode=c("out", "in", "all", "total")) { +get_shortest_path_impl <- function(graph, weights=NULL, from, to, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) @@ -892,7 +847,7 @@ get_shortest_path_impl <- function(graph, from, to, mode=c("out", "in", "all", " on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_get_shortest_path, graph, from-1, to-1, mode) + res <- .Call(R_igraph_get_shortest_path, graph, weights, from-1, to-1, mode) if (igraph_opt("return.vs.es")) { res$vertices <- create_vs(graph, res$vertices) } @@ -913,14 +868,6 @@ get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, m if (length(to) == 0) { stop("No vertex was specified") } - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -946,14 +893,6 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode= if (length(to) == 0) { stop("No vertex was specified") } - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -968,7 +907,7 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode= res } -get_all_shortest_paths_impl <- function(graph, from, to, mode=c("out", "in", "all", "total")) { +get_all_shortest_paths_impl <- function(graph, weights=NULL, from, to, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) @@ -980,13 +919,8 @@ get_all_shortest_paths_impl <- function(graph, from, to, mode=c("out", "in", "al on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_get_all_shortest_paths, graph, from-1, to-1, mode) - if (igraph_opt("return.vs.es")) { - res$vpaths <- lapply(res$vpaths, unsafe_create_vs, graph = graph, verts = V(graph)) - } - if (igraph_opt("return.vs.es")) { - res$epaths <- lapply(res$epaths, unsafe_create_es, graph = graph, es = E(graph)) - } + res <- .Call(R_igraph_get_all_shortest_paths, graph, weights, from-1, to-1, mode) + res } @@ -998,25 +932,12 @@ get_all_shortest_paths_dijkstra_impl <- function(graph, from, to=V(graph), weigh stop("No vertex was specified") } to <- as_igraph_vs(graph, to) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(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_get_all_shortest_paths_dijkstra, graph, from-1, to-1, weights, mode) - if (igraph_opt("return.vs.es")) { - res$vpaths <- lapply(res$vpaths, unsafe_create_vs, graph = graph, verts = V(graph)) - } - if (igraph_opt("return.vs.es")) { - res$epaths <- lapply(res$epaths, unsafe_create_es, graph = graph, es = E(graph)) - } + res } @@ -1025,14 +946,6 @@ voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in check_dots_empty() ensure_igraph(graph) generators <- as_igraph_vs(graph, generators) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) tiebreaker <- switch(igraph.match.arg(tiebreaker), "first"=0L, "last"=1L, "random"=2L) @@ -1043,7 +956,7 @@ voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in res } -get_all_simple_paths_impl <- function(graph, from, to=V(graph), cutoff=-1, mode=c("out", "in", "all", "total")) { +get_all_simple_paths_impl <- function(graph, from, to=V(graph), minlen=-1, maxlen=-1, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) @@ -1051,15 +964,14 @@ get_all_simple_paths_impl <- function(graph, from, to=V(graph), cutoff=-1, mode= stop("No vertex was specified") } to <- as_igraph_vs(graph, to) - cutoff <- as.numeric(cutoff) + minlen <- as.numeric(minlen) + maxlen <- as.numeric(maxlen) 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_get_all_simple_paths, graph, from-1, to-1, cutoff, mode) - if (igraph_opt("return.vs.es")) { - res <- create_vs(graph, res) - } + res <- .Call(R_igraph_get_all_simple_paths, graph, from-1, to-1, minlen, maxlen, mode) + res } @@ -1067,14 +979,6 @@ get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mod # Argument checks check_dots_empty() ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } k <- as.numeric(k) from <- as_igraph_vs(graph, from) if (length(from) == 0) { @@ -1089,16 +993,11 @@ get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mod on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_get_k_shortest_paths, graph, weights, k, from-1, to-1, mode) - if (igraph_opt("return.vs.es")) { - res$vpaths <- lapply(res$vpaths, unsafe_create_vs, graph = graph, verts = V(graph)) - } - if (igraph_opt("return.vs.es")) { - res$epaths <- lapply(res$epaths, unsafe_create_es, graph = graph, es = E(graph)) - } + res } -get_widest_path_impl <- function(graph, from, to, weights=NULL, mode=c("out", "in", "all", "total")) { +get_widest_path_impl <- function(graph, from, to, weights, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) @@ -1109,14 +1008,6 @@ get_widest_path_impl <- function(graph, from, to, weights=NULL, mode=c("out", "i if (length(to) == 0) { stop("No vertex was specified") } - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1131,7 +1022,7 @@ get_widest_path_impl <- function(graph, from, to, weights=NULL, mode=c("out", "i res } -get_widest_paths_impl <- function(graph, from, to=V(graph), weights=NULL, mode=c("out", "in", "all", "total")) { +get_widest_paths_impl <- function(graph, from, to=V(graph), weights, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) @@ -1139,41 +1030,20 @@ get_widest_paths_impl <- function(graph, from, to=V(graph), weights=NULL, mode=c stop("No vertex was specified") } to <- as_igraph_vs(graph, to) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(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_get_widest_paths, graph, from-1, to-1, weights, mode) - if (igraph_opt("return.vs.es")) { - res$vertices <- lapply(res$vertices, unsafe_create_vs, graph = graph, verts = V(graph)) - } - if (igraph_opt("return.vs.es")) { - res$edges <- lapply(res$edges, unsafe_create_es, graph = graph, es = E(graph)) - } + res } -widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph), weights=NULL, mode=c("out", "in", "all", "total")) { +widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph), weights, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) to <- as_igraph_vs(graph, to) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1183,19 +1053,11 @@ widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph), res } -widest_path_widths_floyd_warshall_impl <- function(graph, from=V(graph), to=V(graph), weights=NULL, mode=c("out", "in", "all", "total")) { +widest_path_widths_floyd_warshall_impl <- function(graph, from=V(graph), to=V(graph), weights, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) to <- as_igraph_vs(graph, to) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1209,14 +1071,6 @@ spanner_impl <- function(graph, stretch, weights=NULL) { # Argument checks ensure_igraph(graph) stretch <- as.numeric(stretch) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1232,14 +1086,6 @@ betweenness_cutoff_impl <- function(graph, vids=V(graph), directed=TRUE, weights ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) directed <- as.logical(directed) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } cutoff <- as.numeric(cutoff) on.exit( .Call(R_igraph_finalizer) ) @@ -1258,14 +1104,6 @@ betweenness_subset_impl <- function(graph, vids=V(graph), directed=TRUE, sources directed <- as.logical(directed) sources <- as_igraph_vs(graph, sources) targets <- as_igraph_vs(graph, targets) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1280,14 +1118,6 @@ edge_betweenness_impl <- function(graph, directed=TRUE, weights=NULL) { # Argument checks ensure_igraph(graph) directed <- as.logical(directed) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1300,14 +1130,6 @@ edge_betweenness_cutoff_impl <- function(graph, directed=TRUE, weights=NULL, cut # Argument checks ensure_igraph(graph) directed <- as.logical(directed) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } cutoff <- as.numeric(cutoff) on.exit( .Call(R_igraph_finalizer) ) @@ -1324,19 +1146,13 @@ edge_betweenness_subset_impl <- function(graph, eids=E(graph), directed=TRUE, so directed <- as.logical(directed) sources <- as_igraph_vs(graph, sources) targets <- as_igraph_vs(graph, targets) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } 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", eids) + } res } @@ -1345,14 +1161,6 @@ harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } normalized <- as.logical(normalized) cutoff <- as.numeric(cutoff) @@ -1373,14 +1181,6 @@ personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V directed <- as.logical(directed) damping <- as.numeric(damping) if (!is.null(personalized)) personalized <- as.numeric(personalized) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } if (is.null(options)) { if (algo == 0L) { options <- list(niter=1000, eps=0.001) @@ -1408,14 +1208,6 @@ personalized_pagerank_vs_impl <- function(graph, algo=c("prpack", "arpack"), vid directed <- as.logical(directed) damping <- as.numeric(damping) reset.vids <- as_igraph_vs(graph, reset.vids) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } if (is.null(options)) { if (algo == 0L) { options <- list(niter=1000, eps=0.001) @@ -1476,23 +1268,15 @@ reverse_edges_impl <- function(graph, eids=E(graph)) { res } -average_path_length_dijkstra_impl <- function(graph, weights=NULL, directed=TRUE, unconnected=TRUE, details=FALSE) { +average_path_length_impl <- function(graph, weights=NULL, directed=TRUE, unconn=TRUE, details=FALSE) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } directed <- as.logical(directed) - unconnected <- as.logical(unconnected) + unconn <- as.logical(unconn) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_average_path_length_dijkstra, graph, weights, directed, unconnected) + res <- .Call(R_igraph_average_path_length, graph, weights, directed, unconn) if (!details) { res <- res$res } @@ -1566,14 +1350,6 @@ transitivity_barrat_impl <- function(graph, vids=V(graph), weights=NULL, mode=c( # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "nan"=0L, "zero"=1L) on.exit( .Call(R_igraph_finalizer) ) @@ -1611,13 +1387,13 @@ reciprocity_impl <- function(graph, ignore.loops=TRUE, mode=c("default", "ratio" res } -maxdegree_impl <- function(graph, ..., v=V(graph), mode=c("all", "out", "in", "total"), loops=TRUE) { +maxdegree_impl <- function(graph, ..., v=V(graph), mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once")) { # Argument checks check_dots_empty() ensure_igraph(graph) v <- as_igraph_vs(graph, v) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- as.logical(loops) + loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1653,14 +1429,6 @@ mean_degree_impl <- function(graph, loops=TRUE) { feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "exact_ip")) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } algo <- switch(igraph.match.arg(algo), "exact_ip"=0L, "approx_eades"=1L) on.exit( .Call(R_igraph_finalizer) ) @@ -1675,14 +1443,6 @@ feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "e feedback_vertex_set_impl <- function(graph, weights=NULL, algo=c("exact_ip")) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% vertex_attr_names(graph)) { - weights <- V(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } algo <- switch(igraph.match.arg(algo), "exact_ip"=0L) on.exit( .Call(R_igraph_finalizer) ) @@ -1728,13 +1488,14 @@ is_acyclic_impl <- function(graph) { res } -is_simple_impl <- function(graph) { +is_simple_impl <- function(graph, directed=TRUE) { # Argument checks ensure_igraph(graph) + directed <- as.logical(directed) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_is_simple, graph) + res <- .Call(R_igraph_is_simple, graph, directed) res } @@ -1807,52 +1568,34 @@ is_perfect_impl <- function(graph) { res } -eigenvector_centrality_impl <- function(graph, directed=FALSE, scale=TRUE, weights=NULL, options=arpack_defaults()) { +eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total"), weights=NULL, options=arpack_defaults()) { # Argument checks ensure_igraph(graph) - directed <- as.logical(directed) - scale <- as.logical(scale) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } + mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) options <- modify_list(arpack_defaults(), options) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_eigenvector_centrality, graph, directed, scale, weights, options) + res <- .Call(R_igraph_eigenvector_centrality, graph, mode, weights, options) if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$vector) <- vertex_attr(graph, "name", V(graph)) + names(res$vector) <- vertex_attr(graph, "name") } res } -hub_and_authority_scores_impl <- function(graph, scale=TRUE, weights=NULL, options=arpack_defaults()) { +hub_and_authority_scores_impl <- function(graph, weights=NULL, options=arpack_defaults()) { # Argument checks ensure_igraph(graph) - scale <- as.logical(scale) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } options <- modify_list(arpack_defaults(), options) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_hub_and_authority_scores, graph, scale, weights, options) + res <- .Call(R_igraph_hub_and_authority_scores, graph, weights, options) if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$hub) <- vertex_attr(graph, "name", V(graph)) + names(res$hub.vector) <- vertex_attr(graph, "name") } if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$authority) <- vertex_attr(graph, "name", V(graph)) + names(res$authority.vector) <- vertex_attr(graph, "name") } res } @@ -1914,14 +1657,6 @@ avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all", vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) neighbor.degree.mode <- switch(igraph.match.arg(neighbor.degree.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1935,14 +1670,6 @@ avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all", degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } from.mode <- switch(igraph.match.arg(from.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) to.mode <- switch(igraph.match.arg(to.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) directed.neighbors <- as.logical(directed.neighbors) @@ -1954,20 +1681,27 @@ degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out res } -strength_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=TRUE, weights=NULL) { +rich_club_sequence_impl <- function(graph, weights=NULL, vertex.order, normalized=TRUE, loops=FALSE, directed=TRUE) { + # Argument checks + ensure_igraph(graph) + vertex.order <- as.numeric(vertex.order)-1 + normalized <- as.logical(normalized) + loops <- as.logical(loops) + directed <- as.logical(directed) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_rich_club_sequence, graph, weights, vertex.order, normalized, loops, directed) + + res +} + +strength_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once"), weights=NULL) { # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- as.logical(loops) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } + loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1992,11 +1726,11 @@ centralization_impl <- function(scores, theoretical.max=0, normalized=TRUE) { res } -centralization_degree_impl <- function(graph, mode=c("all", "out", "in", "total"), loops=TRUE, normalized=TRUE) { +centralization_degree_impl <- function(graph, mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once"), normalized=TRUE) { # Argument checks ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- as.logical(loops) + loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) @@ -2006,20 +1740,6 @@ centralization_degree_impl <- function(graph, mode=c("all", "out", "in", "total" res } -centralization_degree_tmax_impl <- function(graph=NULL, nodes=0, mode=c("all", "out", "in", "total"), loops) { - # Argument checks - if (!is.null(graph)) ensure_igraph(graph) - nodes <- as.numeric(nodes) - 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_centralization_degree_tmax, graph, nodes, mode, loops) - - res -} - centralization_betweenness_impl <- function(graph, directed=TRUE, normalized=TRUE) { # Argument checks ensure_igraph(graph) @@ -2072,31 +1792,29 @@ centralization_closeness_tmax_impl <- function(graph=NULL, nodes=0, mode=c("out" res } -centralization_eigenvector_centrality_impl <- function(graph, directed=FALSE, scale=TRUE, options=arpack_defaults(), normalized=TRUE) { +centralization_eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total"), options=arpack_defaults(), normalized=TRUE) { # Argument checks ensure_igraph(graph) - directed <- as.logical(directed) - scale <- as.logical(scale) + mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) options <- modify_list(arpack_defaults(), options) normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_centralization_eigenvector_centrality, graph, directed, scale, options, normalized) + res <- .Call(R_igraph_centralization_eigenvector_centrality, graph, mode, options, normalized) res } -centralization_eigenvector_centrality_tmax_impl <- function(graph=NULL, nodes=0, directed=FALSE, scale=TRUE) { +centralization_eigenvector_centrality_tmax_impl <- function(graph=NULL, nodes=0, mode=c("out", "in", "all", "total")) { # Argument checks if (!is.null(graph)) ensure_igraph(graph) nodes <- as.numeric(nodes) - directed <- as.logical(directed) - scale <- as.logical(scale) + 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_centralization_eigenvector_centrality_tmax, graph, nodes, directed, scale) + res <- .Call(R_igraph_centralization_eigenvector_centrality_tmax, graph, nodes, mode) res } @@ -2145,14 +1863,6 @@ assortativity_degree_impl <- function(graph, directed=TRUE) { joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=-1, max.in.degree=-1) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } max.out.degree <- as.numeric(max.out.degree) max.in.degree <- as.numeric(max.in.degree) @@ -2166,14 +1876,6 @@ joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=-1, max joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE, normalized=TRUE, max.from.degree=-1, max.to.degree=-1) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } from.mode <- switch(igraph.match.arg(from.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) to.mode <- switch(igraph.match.arg(to.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) directed.neighbors <- as.logical(directed.neighbors) @@ -2191,14 +1893,6 @@ joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out joint_type_distribution_impl <- function(graph, weights=NULL, from.types, to.types=NULL, directed=TRUE, normalized=TRUE) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } from.types <- as.numeric(from.types)-1 if (!is.null(to.types)) to.types <- as.numeric(to.types)-1 directed <- as.logical(directed) @@ -2224,75 +1918,36 @@ contract_vertices_impl <- function(graph, mapping, vertex.attr.comb=igraph_opt(" res } -eccentricity_dijkstra_impl <- function(graph, vids=V(graph), ..., weights=NULL, mode=c("all", "out", "in", "total")) { +eccentricity_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all", "out", "in", "total")) { # Argument checks - check_dots_empty() ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } vids <- as_igraph_vs(graph, vids) 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_eccentricity_dijkstra, graph, weights, vids-1, mode) + res <- .Call(R_igraph_eccentricity, graph, weights, vids-1, mode) if (igraph_opt("add.vertex.names") && is_named(graph)) { names(res) <- vertex_attr(graph, "name", vids) } res } -graph_center_dijkstra_impl <- function(graph, ..., weights=NULL, mode=c("all", "out", "in", "total")) { +graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")) { # Argument checks - check_dots_empty() ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(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_graph_center_dijkstra, graph, weights, mode) + res <- .Call(R_igraph_graph_center, graph, weights, mode) if (igraph_opt("return.vs.es")) { res <- create_vs(graph, res) } res } -radius_dijkstra_impl <- function(graph, ..., weights=NULL, mode=c("all", "out", "in", "total")) { - # Argument checks - check_dots_empty() - ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(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_radius_dijkstra, graph, weights, mode) - - res -} - -pseudo_diameter_impl <- function(graph, start.vid, directed=TRUE, unconnected=TRUE) { +pseudo_diameter_impl <- function(graph, weights=NULL, start.vid, directed=TRUE, unconnected=TRUE) { # Argument checks ensure_igraph(graph) start.vid <- as_igraph_vs(graph, start.vid) @@ -2304,32 +1959,7 @@ pseudo_diameter_impl <- function(graph, start.vid, directed=TRUE, unconnected=TR on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_pseudo_diameter, graph, start.vid-1, directed, unconnected) - - res -} - -pseudo_diameter_dijkstra_impl <- function(graph, weights=NULL, start.vid, directed=TRUE, unconnected=TRUE) { - # Argument checks - ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } - start.vid <- as_igraph_vs(graph, start.vid) - if (length(start.vid) == 0) { - stop("No vertex was specified") - } - directed <- as.logical(directed) - unconnected <- as.logical(unconnected) - - on.exit( .Call(R_igraph_finalizer) ) - # Function call - res <- .Call(R_igraph_pseudo_diameter_dijkstra, graph, weights, start.vid-1, directed, unconnected) + res <- .Call(R_igraph_pseudo_diameter, graph, weights, start.vid-1, directed, unconnected) res } @@ -2337,14 +1967,6 @@ pseudo_diameter_dijkstra_impl <- function(graph, weights=NULL, start.vid, direct diversity_impl <- function(graph, weights=NULL, vids=V(graph)) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } vids <- as_igraph_vs(graph, vids) on.exit( .Call(R_igraph_finalizer) ) @@ -2359,14 +1981,6 @@ diversity_impl <- function(graph, weights=NULL, vids=V(graph)) { random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "in", "all", "total"), stuck=c("return", "error")) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } start <- as_igraph_vs(graph, start) if (length(start) == 0) { stop("No vertex was specified") @@ -2390,14 +2004,6 @@ random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "i global_efficiency_impl <- function(graph, weights=NULL, directed=TRUE) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } directed <- as.logical(directed) on.exit( .Call(R_igraph_finalizer) ) @@ -2407,24 +2013,16 @@ global_efficiency_impl <- function(graph, weights=NULL, directed=TRUE) { res } -local_efficiency_impl <- function(graph, vids=V(graph), weights=NULL, directed=TRUE, mode=c("all", "out", "in", "total")) { +local_efficiency_impl <- function(graph, weights=NULL, vids=V(graph), directed=TRUE, mode=c("all", "out", "in", "total")) { # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } directed <- as.logical(directed) 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_local_efficiency, graph, vids-1, weights, directed, mode) + res <- .Call(R_igraph_local_efficiency, graph, weights, vids-1, directed, mode) if (igraph_opt("add.vertex.names") && is_named(graph)) { names(res) <- vertex_attr(graph, "name", vids) } @@ -2434,14 +2032,6 @@ local_efficiency_impl <- function(graph, vids=V(graph), weights=NULL, directed=T average_local_efficiency_impl <- function(graph, weights=NULL, directed=TRUE, mode=c("all", "out", "in", "total")) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } directed <- as.logical(directed) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -2452,17 +2042,6 @@ average_local_efficiency_impl <- function(graph, weights=NULL, directed=TRUE, mo res } -transitive_closure_dag_impl <- function(graph) { - # Argument checks - ensure_igraph(graph) - - on.exit( .Call(R_igraph_finalizer) ) - # Function call - res <- .Call(R_igraph_transitive_closure_dag, graph) - - res -} - transitive_closure_impl <- function(graph) { # Argument checks ensure_igraph(graph) @@ -2529,30 +2108,58 @@ bipartite_projection_size_impl <- function(graph, types=NULL) { res } -biadjacency_impl <- function(incidence, directed=FALSE, mode=c("all", "out", "in", "total"), multiple=FALSE) { +create_bipartite_impl <- function(types, edges, directed=FALSE) { # Argument checks - incidence[] <- as.numeric(incidence) + types <- handle_vertex_type_arg(types, graph) + edges <- as.numeric(edges) + directed <- as.logical(directed) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_create_bipartite, types, edges, directed) + + res +} + +biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", "out", "in", "total"), multiple=FALSE) { + # Argument checks + biadjmatrix[] <- as.numeric(biadjmatrix) directed <- as.logical(directed) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) multiple <- as.logical(multiple) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_biadjacency, incidence, directed, mode, multiple) + res <- .Call(R_igraph_biadjacency, biadjmatrix, directed, mode, multiple) if (igraph_opt("add.vertex.names") && is_named(graph)) { names(res$types) <- vertex_attr(graph, "name", V(graph)) } res } -get_biadjacency_impl <- function(graph, types) { +weighted_biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", "out", "in", "total")) { + # Argument checks + biadjmatrix[] <- as.numeric(biadjmatrix) + directed <- as.logical(directed) + 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_weighted_biadjacency, biadjmatrix, directed, mode) + if (igraph_opt("add.vertex.names") && is_named(graph)) { + names(res$types) <- vertex_attr(graph, "name") + } + res +} + +get_biadjacency_impl <- function(graph, types, weights=NULL) { # Argument checks ensure_igraph(graph) types <- handle_vertex_type_arg(types, graph) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_get_biadjacency, graph, types) + res <- .Call(R_igraph_get_biadjacency, graph, types, weights) res } @@ -2585,18 +2192,38 @@ bipartite_game_gnp_impl <- function(n1, n2, p, directed=FALSE, mode=c("all", "ou res } -bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "out", "in", "total")) { +bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "out", "in", "total"), multiple=FALSE) { # Argument checks n1 <- as.numeric(n1) n2 <- as.numeric(n2) m <- as.numeric(m) directed <- as.logical(directed) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + multiple <- as.logical(multiple) on.exit( .Call(R_igraph_finalizer) ) # Function call - 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) + if (igraph_opt("add.vertex.names") && is_named(graph)) { + names(res$types) <- vertex_attr(graph, "name") + } + res +} + +bipartite_iea_game_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "out", "in", "total")) { + # Argument checks + n1 <- as.numeric(n1) + n2 <- as.numeric(n2) + m <- as.numeric(m) + directed <- as.logical(directed) + 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_bipartite_iea_game, n1, n2, m, directed, mode) + if (igraph_opt("add.vertex.names") && is_named(graph)) { + names(res$types) <- vertex_attr(graph, "name") + } res } @@ -2605,14 +2232,6 @@ get_laplacian_impl <- function(graph, mode=c("out", "in", "all", "total"), norma ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) normalization <- switch(igraph.match.arg(normalization), "unnormalized"=0L, "symmetric"=1L, "left"=2L, "right"=3L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2626,14 +2245,6 @@ get_laplacian_sparse_impl <- function(graph, mode=c("out", "in", "all", "total") ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) normalization <- switch(igraph.match.arg(normalization), "unnormalized"=0L, "symmetric"=1L, "left"=2L, "right"=3L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2688,15 +2299,6 @@ biconnected_components_impl <- function(graph) { on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_biconnected_components, graph) - if (igraph_opt("return.vs.es")) { - res$tree.edges <- lapply(res$tree.edges, unsafe_create_es, graph = graph, es = E(graph)) - } - if (igraph_opt("return.vs.es")) { - res$component.edges <- lapply(res$component.edges, unsafe_create_es, graph = graph, es = E(graph)) - } - if (igraph_opt("return.vs.es")) { - res$components <- lapply(res$components, unsafe_create_vs, graph = graph, verts = V(graph)) - } if (igraph_opt("return.vs.es")) { res$articulation.points <- create_vs(graph, res$articulation.points) } @@ -2796,9 +2398,7 @@ cliques_impl <- function(graph, min=0, max=0) { on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_cliques, graph, min, max) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } @@ -2822,9 +2422,7 @@ largest_cliques_impl <- function(graph) { on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_largest_cliques, graph) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } @@ -2855,14 +2453,6 @@ clique_number_impl <- function(graph) { weighted_cliques_impl <- function(graph, vertex.weights=NULL, min.weight=0, max.weight=0, maximal=FALSE) { # Argument checks ensure_igraph(graph) - if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { - vertex.weights <- V(graph)$weight - } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { - vertex.weights <- as.numeric(vertex.weights) - } else { - vertex.weights <- NULL - } min.weight <- as.numeric(min.weight) max.weight <- as.numeric(max.weight) maximal <- as.logical(maximal) @@ -2870,44 +2460,24 @@ weighted_cliques_impl <- function(graph, vertex.weights=NULL, min.weight=0, max. on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_weighted_cliques, graph, vertex.weights, min.weight, max.weight, maximal) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } largest_weighted_cliques_impl <- function(graph, vertex.weights=NULL) { # Argument checks ensure_igraph(graph) - if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { - vertex.weights <- V(graph)$weight - } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { - vertex.weights <- as.numeric(vertex.weights) - } else { - vertex.weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_largest_weighted_cliques, graph, vertex.weights) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } weighted_clique_number_impl <- function(graph, vertex.weights=NULL) { # Argument checks ensure_igraph(graph) - if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { - vertex.weights <- V(graph)$weight - } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { - vertex.weights <- as.numeric(vertex.weights) - } else { - vertex.weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3006,24 +2576,52 @@ roots_for_tree_layout_impl <- function(graph, mode=c("out", "in", "all", "total" res } -layout_random_3d_impl <- function(graph) { +layout_random_3d_impl <- function(graph) { + # Argument checks + ensure_igraph(graph) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_layout_random_3d, graph) + + res +} + +layout_sphere_impl <- function(graph) { + # Argument checks + ensure_igraph(graph) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_layout_sphere, graph) + + res +} + +layout_drl_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$default, weights=NULL) { # Argument checks ensure_igraph(graph) + res[] <- as.numeric(res) + use.seed <- as.logical(use.seed) + options <- modify_list(drl_defaults$default, options) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_layout_random_3d, graph) + res <- .Call(R_igraph_layout_drl, graph, res, use.seed, options, weights) res } -layout_sphere_impl <- function(graph) { +layout_drl_3d_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$default, weights=NULL) { # Argument checks ensure_igraph(graph) + res[] <- as.numeric(res) + use.seed <- as.logical(use.seed) + options <- modify_list(drl_defaults$default, options) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_layout_sphere, graph) + res <- .Call(R_igraph_layout_drl_3d, graph, res, use.seed, options, weights) res } @@ -3035,14 +2633,6 @@ layout_sugiyama_impl <- function(graph, layers=NULL, hgap=1, vgap=1, maxiter=100 hgap <- as.numeric(hgap) vgap <- as.numeric(vgap) maxiter <- as.numeric(maxiter) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3176,16 +2766,17 @@ layout_align_impl <- function(graph, layout) { 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 } @@ -3230,16 +2821,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 } @@ -3288,14 +2880,6 @@ modularity_impl <- function(graph, membership, weights=NULL, resolution=1.0, dir # Argument checks ensure_igraph(graph) membership <- as.numeric(membership) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } resolution <- as.numeric(resolution) directed <- as.logical(directed) @@ -3309,14 +2893,6 @@ modularity_impl <- function(graph, membership, weights=NULL, resolution=1.0, dir modularity_matrix_impl <- function(graph, weights=NULL, resolution=1.0, directed=TRUE) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } resolution <- as.numeric(resolution) directed <- as.logical(directed) @@ -3339,24 +2915,18 @@ community_fluid_communities_impl <- function(graph, no.of.communities) { res } -community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", "total"), weights=NULL, initial=NULL, fixed=NULL) { +community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", "total"), weights=NULL, initial=NULL, fixed=NULL, lpa.variant) { # Argument checks ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } if (!is.null(initial)) initial <- as.numeric(initial)-1 if (!is.null(fixed)) fixed <- as.logical(fixed) + lpa.variant <- switch(igraph.match.arg(lpa.variant), + "dominance"=0L, "retention"=1L, "fast"=2L) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_community_label_propagation, graph, mode, weights, initial, fixed) + res <- .Call(R_igraph_community_label_propagation, graph, mode, weights, initial, fixed, lpa.variant) res } @@ -3364,14 +2934,6 @@ community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", " community_multilevel_impl <- function(graph, weights=NULL, resolution=1.0) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } resolution <- as.numeric(resolution) on.exit( .Call(R_igraph_finalizer) ) @@ -3381,44 +2943,21 @@ community_multilevel_impl <- function(graph, weights=NULL, resolution=1.0) { res } -community_optimal_modularity_impl <- function(graph, weights=NULL) { +community_optimal_modularity_impl <- function(graph, weights=NULL, resolution=1.0) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } + resolution <- as.numeric(resolution) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_community_optimal_modularity, graph, weights) + res <- .Call(R_igraph_community_optimal_modularity, graph, weights, resolution) res } -community_leiden_impl <- function(graph, weights=NULL, vertex.weights=NULL, resolution, beta=0.01, start, n.iterations=2, membership=NULL) { +community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, vertex.in.weights=NULL, resolution, beta=0.01, start, n.iterations=2, membership=NULL) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } - if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { - vertex.weights <- V(graph)$weight - } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { - vertex.weights <- as.numeric(vertex.weights) - } else { - vertex.weights <- NULL - } resolution <- as.numeric(resolution) beta <- as.numeric(beta) start <- as.logical(start) @@ -3427,7 +2966,7 @@ community_leiden_impl <- function(graph, weights=NULL, vertex.weights=NULL, reso on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_community_leiden, graph, weights, vertex.weights, resolution, beta, start, n.iterations, membership) + res <- .Call(R_igraph_community_leiden, graph, weights, vertex.out.weights, vertex.in.weights, resolution, beta, start, n.iterations, membership) res } @@ -3444,30 +2983,14 @@ split_join_distance_impl <- function(comm1, comm2) { res } -community_infomap_impl <- function(graph, e.weights=NULL, v.weights=NULL, nb.trials=10) { +community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL, nb.trials=10) { # Argument checks ensure_igraph(graph) - if (is.null(e.weights) && "weight" %in% edge_attr_names(graph)) { - e.weights <- E(graph)$weight - } - if (!is.null(e.weights) && any(!is.na(e.weights))) { - e.weights <- as.numeric(e.weights) - } else { - e.weights <- NULL - } - if (is.null(v.weights) && "weight" %in% vertex_attr_names(graph)) { - v.weights <- V(graph)$weight - } - if (!is.null(v.weights) && any(!is.na(v.weights))) { - v.weights <- as.numeric(v.weights) - } else { - v.weights <- NULL - } nb.trials <- as.numeric(nb.trials) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_community_infomap, graph, e.weights, v.weights, nb.trials) + res <- .Call(R_igraph_community_infomap, graph, edge.weights, vertex.weights, nb.trials) res } @@ -3475,22 +2998,12 @@ community_infomap_impl <- function(graph, e.weights=NULL, v.weights=NULL, nb.tri graphlets_impl <- function(graph, weights=NULL, niter=1000) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } niter <- as.numeric(niter) on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_graphlets, graph, weights, niter) - if (igraph_opt("return.vs.es")) { - res$cliques <- lapply(res$cliques, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } @@ -3656,14 +3169,6 @@ get_adjacency_sparse_impl <- function(graph, type=c("both", "upper", "lower"), w # Argument checks ensure_igraph(graph) type <- switch(igraph.match.arg(type), "upper"=0L, "lower"=1L, "both"=2L) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) on.exit( .Call(R_igraph_finalizer) ) @@ -3677,14 +3182,6 @@ get_stochastic_impl <- function(graph, column.wise=FALSE, weights=NULL) { # Argument checks ensure_igraph(graph) column.wise <- as.logical(column.wise) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3697,14 +3194,6 @@ get_stochastic_sparse_impl <- function(graph, column.wise=FALSE, weights=NULL) { # Argument checks ensure_igraph(graph) column.wise <- as.logical(column.wise) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3827,14 +3316,6 @@ count_triangles_impl <- function(graph) { local_scan_0_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3848,14 +3329,6 @@ local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "i # Argument checks ensure_igraph(us) ensure_igraph(them) - if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { - weights.them <- E(them)$weight - } - if (!is.null(weights.them) && any(!is.na(weights.them))) { - weights.them <- as.numeric(weights.them) - } else { - weights.them <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3868,14 +3341,6 @@ local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "i local_scan_1_ecount_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3889,14 +3354,6 @@ local_scan_1_ecount_them_impl <- function(us, them, weights.them=NULL, mode=c("o # Argument checks ensure_igraph(us) ensure_igraph(them) - if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { - weights.them <- E(them)$weight - } - if (!is.null(weights.them) && any(!is.na(weights.them))) { - weights.them <- as.numeric(weights.them) - } else { - weights.them <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3910,14 +3367,6 @@ local_scan_k_ecount_impl <- function(graph, k, weights=NULL, mode=c("out", "in", # Argument checks ensure_igraph(graph) k <- as.numeric(k) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3932,14 +3381,6 @@ local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c ensure_igraph(us) ensure_igraph(them) k <- as.numeric(k) - if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { - weights.them <- E(them)$weight - } - if (!is.null(weights.them) && any(!is.na(weights.them))) { - weights.them <- as.numeric(weights.them) - } else { - weights.them <- NULL - } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3952,14 +3393,6 @@ local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c local_scan_neighborhood_ecount_impl <- function(graph, weights=NULL, neighborhoods) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3971,14 +3404,6 @@ local_scan_neighborhood_ecount_impl <- function(graph, weights=NULL, neighborhoo local_scan_subset_ecount_impl <- function(graph, weights=NULL, subsets) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4050,6 +3475,22 @@ product_impl <- function(g1, g2, type=c("cartesian", "lexicographic", "strong", res } +rooted_product_impl <- function(g1, g2, root) { + # Argument checks + ensure_igraph(g1) + ensure_igraph(g2) + root <- as_igraph_vs(g2, root) + if (length(root) == 0) { + stop("No vertex was specified") + } + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_rooted_product, g1, g2, root-1) + + res +} + gomory_hu_tree_impl <- function(graph, capacity=NULL) { # Argument checks ensure_igraph(graph) @@ -4212,12 +3653,7 @@ all_st_cuts_impl <- function(graph, source, target) { on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_all_st_cuts, graph, source-1, target-1) - if (igraph_opt("return.vs.es")) { - res$cuts <- lapply(res$cuts, unsafe_create_es, graph = graph, es = E(graph)) - } - if (igraph_opt("return.vs.es")) { - res$partition1s <- lapply(res$partition1s, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } @@ -4244,12 +3680,7 @@ all_st_mincuts_impl <- function(graph, source, target, capacity=NULL) { on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_all_st_mincuts, graph, source-1, target-1, capacity) - if (igraph_opt("return.vs.es")) { - res$cuts <- lapply(res$cuts, unsafe_create_es, graph = graph, es = E(graph)) - } - if (igraph_opt("return.vs.es")) { - res$partition1s <- lapply(res$partition1s, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } @@ -4295,9 +3726,7 @@ all_minimal_st_separators_impl <- function(graph) { on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_all_minimal_st_separators, graph) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } @@ -4308,9 +3737,7 @@ minimum_size_separators_impl <- function(graph) { on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_minimum_size_separators, graph) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res } @@ -4337,6 +3764,48 @@ 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) + + 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_subgraph_impl <- function(graph, vids) { # Argument checks ensure_igraph(graph) @@ -4738,7 +4207,28 @@ get_subisomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, ver 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)) { @@ -4755,7 +4245,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 } @@ -4805,7 +4295,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)) { @@ -4822,12 +4312,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)) { @@ -4844,10 +4334,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) - if (igraph_opt("return.vs.es")) { - res$generators <- lapply(res$generators, unsafe_create_vs, graph = graph, verts = V(graph)) - } + res <- .Call(R_igraph_automorphism_group_bliss, graph, colors, sh) if (!details) { res <- res$generators } @@ -4907,14 +4394,6 @@ maximum_bipartite_matching_impl <- function(graph, types, weights=NULL, eps=.Mac # Argument checks ensure_igraph(graph) types <- handle_vertex_type_arg(types, graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } eps <- as.numeric(eps) on.exit( .Call(R_igraph_finalizer) ) @@ -4928,14 +4407,6 @@ adjacency_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" # Argument checks ensure_igraph(graph) no <- as.numeric(no) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } which <- switch(igraph.match.arg(which), "lm"=0L, "la"=2L, "sa"=3L) scaled <- as.logical(scaled) cvec <- as.numeric(cvec) @@ -4952,14 +4423,6 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" # Argument checks ensure_igraph(graph) no <- as.numeric(no) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } which <- switch(igraph.match.arg(which), "lm"=0L, "la"=2L, "sa"=3L) type <- switch(igraph.match.arg(type), "default"=if (is_directed(graph)) 3L else 0L, @@ -4975,7 +4438,7 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" res } -eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack"), which=list(), options=arpack_defaults()) { +eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack"), which=list(), options=arpack_defaults(), storage) { # Argument checks ensure_igraph(graph) algorithm <- switch(igraph.match.arg(algorithm), "auto"=0L, "lapack"=1L, @@ -4987,7 +4450,7 @@ eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack", on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_eigen_adjacency, graph, algorithm, which, options) + res <- .Call(R_igraph_eigen_adjacency, graph, algorithm, which, options, storage) res } @@ -5081,12 +4544,7 @@ simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), min.c on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_simple_cycles, graph, mode, min.cycle.length, max.cycle.length) - if (igraph_opt("return.vs.es")) { - res$vertices <- lapply(res$vertices, unsafe_create_vs, graph = graph, verts = V(graph)) - } - if (igraph_opt("return.vs.es")) { - res$edges <- lapply(res$edges, unsafe_create_es, graph = graph, es = E(graph)) - } + res } @@ -5133,7 +4591,7 @@ eulerian_cycle_impl <- function(graph) { res } -fundamental_cycles_impl <- function(graph, start=NULL, bfs.cutoff=-1, weights=NULL) { +fundamental_cycles_impl <- function(graph, start=-1, bfs.cutoff=-1, weights=NULL) { # Argument checks ensure_igraph(graph) if (!is.null(start)) start <- as_igraph_vs(graph, start) @@ -5141,21 +4599,11 @@ fundamental_cycles_impl <- function(graph, start=NULL, bfs.cutoff=-1, weights=NU stop("No vertex was specified") } bfs.cutoff <- as.numeric(bfs.cutoff) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_fundamental_cycles, graph, start-1, bfs.cutoff, weights) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_es, graph = graph, es = E(graph)) - } + res } @@ -5165,21 +4613,11 @@ minimum_cycle_basis_impl <- function(graph, bfs.cutoff=-1, complete=TRUE, use.cy bfs.cutoff <- as.numeric(bfs.cutoff) complete <- as.logical(complete) use.cycle.order <- as.logical(use.cycle.order) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_minimum_cycle_basis, graph, bfs.cutoff, complete, use.cycle.order, weights) - if (igraph_opt("return.vs.es")) { - res <- lapply(res, unsafe_create_es, graph = graph, es = E(graph)) - } + res } @@ -5267,7 +4705,7 @@ is_complete_impl <- function(graph) { res } -random_spanning_tree_impl <- function(graph, vid=0) { +random_spanning_tree_impl <- function(graph, vid=-1) { # Argument checks ensure_igraph(graph) if (!is.null(vid)) vid <- as_igraph_vs(graph, vid) @@ -5297,93 +4735,85 @@ tree_game_impl <- function(n, directed=FALSE, method=c("lerw", "prufer")) { res } -vertex_coloring_greedy_impl <- function(graph, heuristic=c("colored_neighbors", "dsatur")) { +nearest_neighbor_graph_impl <- function(points, metric, neighbors, cutoff, directed) { # Argument checks - ensure_igraph(graph) - heuristic <- switch(igraph.match.arg(heuristic), "colored_neighbors"=0L, "dsatur"=1L) + points[] <- as.numeric(points) + neighbors <- as.numeric(neighbors) + cutoff <- as.numeric(cutoff) + directed <- as.logical(directed) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_vertex_coloring_greedy, graph, heuristic) - res <- res+1 - if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res) <- vertex_attr(graph, "name") - } + res <- .Call(R_igraph_nearest_neighbor_graph, points, metric, neighbors, cutoff, directed) + res } -deterministic_optimal_imitation_impl <- function(graph, vid, optimality=c("maximum", "minimum"), quantities, strategies, mode=c("out", "in", "all", "total")) { +vertex_coloring_greedy_impl <- function(graph, heuristic=c("colored_neighbors", "dsatur")) { # Argument checks ensure_igraph(graph) - vid <- as_igraph_vs(graph, vid) - if (length(vid) == 0) { - stop("No vertex was specified") - } - optimality <- switch(igraph.match.arg(optimality), "minimum"=0L, "maximum"=1L) - strategies <- as.numeric(strategies) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + heuristic <- switch(igraph.match.arg(heuristic), "colored_neighbors"=0L, "dsatur"=1L) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_deterministic_optimal_imitation, graph, vid-1, optimality, quantities, strategies, mode) - + res <- .Call(R_igraph_vertex_coloring_greedy, graph, heuristic) + res <- res+1 + if (igraph_opt("add.vertex.names") && is_named(graph)) { + names(res) <- vertex_attr(graph, "name") + } res } -moran_process_impl <- function(graph, weights=NULL, quantities, strategies, mode=c("out", "in", "all", "total")) { +is_vertex_coloring_impl <- function(graph, types) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight + if (missing(types)) { + if ("color" %in% vertex_attr_names(graph)) { + types <- V(graph)$color + } else { + types <- NULL + } } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL + if (!is.null(types)) { + types <- as.numeric(types)-1 } - strategies <- as.numeric(strategies) - 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_moran_process, graph, weights, quantities, strategies, mode) - if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$quantities) <- vertex_attr(graph, "name", V(graph)) - } + res <- .Call(R_igraph_is_vertex_coloring, graph, types) + res } -roulette_wheel_imitation_impl <- function(graph, vid, is.local, quantities, strategies, mode=c("out", "in", "all", "total")) { +is_bipartite_coloring_impl <- function(graph, types) { # Argument checks ensure_igraph(graph) - vid <- as_igraph_vs(graph, vid) - if (length(vid) == 0) { - stop("No vertex was specified") - } - is.local <- as.logical(is.local) - strategies <- as.numeric(strategies) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + types <- handle_vertex_type_arg(types, graph) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_roulette_wheel_imitation, graph, vid-1, is.local, quantities, strategies, mode) + res <- .Call(R_igraph_is_bipartite_coloring, graph, types) res } -stochastic_imitation_impl <- function(graph, vid, algo, quantities, strategies, mode=c("out", "in", "all", "total")) { +is_edge_coloring_impl <- function(graph, types) { # Argument checks ensure_igraph(graph) - vid <- as_igraph_vs(graph, vid) - if (length(vid) == 0) { - stop("No vertex was specified") + if (missing(types)) { + if ("color" %in% edge_attr_names(graph)) { + types <- E(graph)$color + } else { + types <- NULL + } + } + if (!is.null(types)) { + types <- as.numeric(types)-1 } - strategies <- as.numeric(strategies) - 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_stochastic_imitation, graph, vid-1, algo, quantities, strategies, mode) + res <- .Call(R_igraph_is_edge_coloring, graph, types) res } @@ -5399,25 +4829,6 @@ invalidate_cache_impl <- function(graph) { res } -vertex_path_from_edge_path_impl <- function(graph, start=NULL, edge.path, mode=c("out", "in", "all", "total")) { - # Argument checks - ensure_igraph(graph) - if (!is.null(start)) start <- as_igraph_vs(graph, start) - if (length(start) == 0) { - stop("No vertex was specified") - } - edge.path <- as_igraph_es(graph, edge.path) - 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_vertex_path_from_edge_path, graph, start-1, edge.path-1, mode) - if (igraph_opt("return.vs.es")) { - res <- create_vs(graph, res) - } - res -} - version_impl <- function() { # Argument checks diff --git a/R/games.R b/R/games.R index 6661c7dcdc3..747e7797972 100644 --- a/R/games.R +++ b/R/games.R @@ -1081,7 +1081,8 @@ sample_gnm <- function(n, m, directed = FALSE, loops = FALSE) { as.numeric(n), as.numeric(m), as.logical(directed), - as.logical(loops) + as.logical(loops), + FALSE ) if (igraph_opt("add.params")) { diff --git a/R/paths.R b/R/paths.R index d6226beea90..ec85f1ac65f 100644 --- a/R/paths.R +++ b/R/paths.R @@ -376,8 +376,8 @@ radius <- function( #' graph_center(ring) #' #' @export -#' @cdocs igraph_graph_center_dijkstra -graph_center <- graph_center_dijkstra_impl +#' @cdocs igraph_graph_center +graph_center <- graph_center_impl #' @rdname distances #' @param directed Whether to consider directed paths in directed graphs, diff --git a/R/structural-properties.R b/R/structural-properties.R index e19173725e1..b276cce9c63 100644 --- a/R/structural-properties.R +++ b/R/structural-properties.R @@ -851,8 +851,8 @@ farthest_vertices <- function( #' @export #' @rdname distances -#' @cdocs igraph_average_path_length_dijkstra -mean_distance <- average_path_length_dijkstra_impl +#' @cdocs igraph_average_path_length +mean_distance <- average_path_length_impl #' Degree and degree distribution of the vertices diff --git a/R/trees.R b/R/trees.R index 5a0f135fe90..1ce7be9387c 100644 --- a/R/trees.R +++ b/R/trees.R @@ -152,4 +152,6 @@ to_prufer <- to_prufer_impl #' @family trees #' @export #' @cdocs igraph_random_spanning_tree -sample_spanning_tree <- random_spanning_tree_impl +sample_spanning_tree <- function(graph, vid = NULL) { + random_spanning_tree_impl(graph, vid) +} diff --git a/patch/0001-fix-include-quotes.patch b/patch/0001-fix-include-quotes.patch deleted file mode 100644 index e178d2a3964..00000000000 --- a/patch/0001-fix-include-quotes.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c6ff0ba179c304572cf0bc285201aebb963f89ae Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Kirill=20M=C3=BCller?= -Date: Wed, 8 Jan 2025 05:21:39 +0100 -Subject: [PATCH] fix include quotes - ---- - src/vendor/cigraph/vendor/plfit/lbfgs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/vendor/cigraph/vendor/plfit/lbfgs.c b/src/vendor/cigraph/vendor/plfit/lbfgs.c -index 6472a9aa26..c1b7fac28f 100644 ---- a/src/vendor/cigraph/vendor/plfit/lbfgs.c -+++ b/src/vendor/cigraph/vendor/plfit/lbfgs.c -@@ -70,7 +70,7 @@ licence. - #include - #include - --#include -+#include "lbfgs.h" - - #ifdef _MSC_VER - #define inline __inline --- -2.47.1 - diff --git a/patch/0002-upstream-deps.patch b/patch/0002-upstream-deps.patch deleted file mode 100644 index 34436e531fd..00000000000 --- a/patch/0002-upstream-deps.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 77f21dc92bc6717d8668140211c36620388014f0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Kirill=20M=C3=BCller?= -Date: Mon, 28 Jul 2025 21:25:09 +0200 -Subject: [PATCH] upstream-deps - ---- - src/vendor/cigraph/interfaces/functions.yaml | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml -index 633fa25425..f447f9afff 100644 ---- a/src/vendor/cigraph/interfaces/functions.yaml -+++ b/src/vendor/cigraph/interfaces/functions.yaml -@@ -1321,9 +1321,11 @@ igraph_count_reachable: - - igraph_bond_percolation: - PARAMS: GRAPH graph, OUT VECTOR_INT giant_size, OUT VECTOR_INT vetex_count, OPTIONAL EDGE_INDICES edge_order -+ DEPS: edge_order ON graph - - igraph_site_percolation: - PARAMS: GRAPH graph, OUT VECTOR_INT giant_size, OUT VECTOR_INT edge_count, OPTIONAL VERTEX_INDICES vertex_order -+ DEPS: vertex_order ON graph - - igraph_edgelist_percolation: - PARAMS: VERTEX_INDEX_PAIRS edges, OUT VECTOR_INT giant_size, OUT VECTOR_INT vertex_count --- -2.49.0 - diff --git a/patch/0003-Temporary-fix.patch b/patch/0003-Temporary-fix.patch deleted file mode 100644 index 106fa39f8a7..00000000000 --- a/patch/0003-Temporary-fix.patch +++ /dev/null @@ -1,25 +0,0 @@ -From ffced517fdd10884cf5c99cabc9b2f5587926f23 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Kirill=20M=C3=BCller?= -Date: Thu, 7 Aug 2025 17:10:17 +0200 -Subject: [PATCH] Temporary fix - ---- - src/vendor/cigraph/src/operators/permute.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/vendor/cigraph/src/operators/permute.c b/src/vendor/cigraph/src/operators/permute.c -index 60cbb08b12..f84ba6bc66 100644 ---- a/src/vendor/cigraph/src/operators/permute.c -+++ b/src/vendor/cigraph/src/operators/permute.c -@@ -24,7 +24,7 @@ - - #include "igraph_constructors.h" - #include "igraph_interface.h" --#include "igraph_isomorphism.h" -+#include "igraph_topology.h" - - #include "graph/attributes.h" - --- -2.49.0 - diff --git a/patch/0004-Tweak-function-definitions.patch b/patch/0004-Tweak-function-definitions.patch new file mode 100644 index 00000000000..1867fe30e0a --- /dev/null +++ b/patch/0004-Tweak-function-definitions.patch @@ -0,0 +1,154 @@ +From c8c9b9194093aa700f38a3e55cb76412eb54b851 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Kirill=20M=C3=BCller?= +Date: Sun, 17 Aug 2025 15:31:16 +0200 +Subject: [PATCH] Tweak function definitions + +--- + src/vendor/cigraph/interfaces/functions.yaml | 28 +++++++++++--------- + src/vendor/cigraph/interfaces/types.yaml | 7 ++++- + 2 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml +index c8b9ca948e..cee8b524c3 100644 +--- a/src/vendor/cigraph/interfaces/functions.yaml ++++ b/src/vendor/cigraph/interfaces/functions.yaml +@@ -230,8 +230,9 @@ igraph_adjlist: + + igraph_full_bipartite: + PARAMS: |- +- OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, INTEGER n1, ++ OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, INTEGER n1, + INTEGER n2, BOOLEAN directed=False, NEIMODE mode=ALL ++ DEPS: types ON graph + + igraph_full_multipartite: + PARAMS: |- +@@ -523,14 +524,14 @@ igraph_get_shortest_paths: + VERTEX from, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, + OPTIONAL OUT VECTOR_INT parents, + OPTIONAL OUT VECTOR_INT inbound_edges +- DEPS: weights ON graph, edges ON graph, from ON graph, to ON graph ++ DEPS: weights ON graph, vertices ON graph, edges ON graph, from ON graph, to ON graph + + igraph_get_all_shortest_paths: + PARAMS: |- + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + 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: weights ON graph, edges ON graph, from ON graph, to ON graph ++ DEPS: weights ON graph, vertices ON graph, edges ON graph, from ON graph, to ON graph + + igraph_distances_dijkstra: + PARAMS: |- +@@ -694,7 +695,7 @@ igraph_edge_betweenness_subset: + BOOLEAN directed=True, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, + OPTIONAL EDGE_WEIGHTS weights + DEPS: |- +- eids ON graph, weights ON graph, res ON graph, sources ON graph, targets ON graph ++ res ON graph eids, eids ON graph, sources ON graph, targets ON graph, weights ON graph + + igraph_harmonic_centrality: + PARAMS: |- +@@ -905,6 +906,7 @@ igraph_hub_and_authority_scores: + GRAPH graph, OUT ALL_VERTEX_QTY hub_vector, OUT ALL_VERTEX_QTY authority_vector, + OUT REAL value, OPTIONAL EDGE_WEIGHTS weights, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS ++ DEPS: weights ON graph, hub_vector ON graph, authority_vector ON graph + + igraph_unfold_tree: + PARAMS: |- +@@ -1187,6 +1189,7 @@ igraph_create_bipartite: + PARAMS: |- + OUT GRAPH graph, IN BIPARTITE_TYPES types, + VECTOR_INT edges, BOOLEAN directed=False ++ DEPS: types ON graph, edges ON graph + + igraph_biadjacency: + PARAMS: |- +@@ -1197,7 +1200,7 @@ igraph_biadjacency: + igraph_weighted_biadjacency: + PARAMS: |- + OUT GRAPH graph, +- OUT BIPARTITE_TYPES types, OUT EDGE_WEIGHTS weights, ++ OUT ALL_BIPARTITE_TYPES types, OUT EDGE_WEIGHTS weights, + MATRIX biadjmatrix, + BOOLEAN directed=False, NEIMODE mode=ALL + DEPS: |- +@@ -1221,17 +1224,17 @@ igraph_bipartite_game_gnp: + + igraph_bipartite_game_gnm: + PARAMS: |- +- OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, ++ OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, + INTEGER n1, INTEGER n2, INTEGER m, BOOLEAN directed=False, + NEIMODE mode=ALL, BOOLEAN multiple=False ++ DEPS: types ON graph + + igraph_bipartite_iea_game: + PARAMS: |- +- OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, ++ OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, + INTEGER n1, INTEGER n2, INTEGER m, + BOOLEAN directed=False, NEIMODE mode=ALL +- DEPS: |- +- types ON graph ++ DEPS: types ON graph + + ####################################### + # Spectral properties +@@ -2472,7 +2475,7 @@ igraph_maximum_bipartite_matching: + OPTIONAL OUT REAL matching_weight, + OUT INDEX_VECTOR matching, + OPTIONAL EDGE_WEIGHTS weights, REAL eps=.Machine$double.eps +- DEPS: types ON graph, weights ON graph ++ DEPS: types ON graph matching, weights ON graph + + ####################################### + # Embedding +@@ -2609,7 +2612,7 @@ igraph_eulerian_cycle: + + igraph_fundamental_cycles: + PARAMS: |- +- GRAPH graph, OUT EDGE_INDICES_LIST basis, OPTIONAL VERTEX start, ++ GRAPH graph, OUT EDGE_INDICES_LIST basis, OPTIONAL VERTEX start=-1, + INTEGER bfs_cutoff=-1, OPTIONAL EDGE_WEIGHTS weights + DEPS: weights ON graph, basis ON graph, start ON graph + +@@ -2649,7 +2652,7 @@ igraph_minimum_spanning_tree: + DEPS: res ON graph, weights ON graph + + igraph_random_spanning_tree: +- PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid ++ PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid=-1 + DEPS: res ON graph, vid ON graph + + igraph_tree_game: +@@ -2720,6 +2723,7 @@ igraph_vertex_path_from_edge_path: + PARAMS: |- + GRAPH graph, OPTIONAL VERTEX start, EDGE_INDICES edge_path, + OUT VERTEX_INDICES vertex_path, NEIMODE mode=OUT ++ DEPS: start ON graph, edge_path ON graph, vertex_path ON graph + + ####################################### + # Meta info +diff --git a/src/vendor/cigraph/interfaces/types.yaml b/src/vendor/cigraph/interfaces/types.yaml +index 3382fd4d14..3d4819fe2d 100644 +--- a/src/vendor/cigraph/interfaces/types.yaml ++++ b/src/vendor/cigraph/interfaces/types.yaml +@@ -169,7 +169,12 @@ VERTEX_SELECTOR: + + BIPARTITE_TYPES: + # A vector containing Booleans that define the two partitions of a +- # bipartite graph ++ # bipartite graph, for a set of vertices ++ CTYPE: igraph_vector_bool_t ++ FLAGS: BY_REF ++ ++ALL_BIPARTITE_TYPES: ++ # Same as BIPARTITE_TYPES, for all vertices of a graph + CTYPE: igraph_vector_bool_t + FLAGS: BY_REF + +-- +2.49.0 + diff --git a/patch/0004-chore-Fix-remaining-Stimulus-types.patch b/patch/0004-chore-Fix-remaining-Stimulus-types.patch deleted file mode 100644 index 2295e6b671b..00000000000 --- a/patch/0004-chore-Fix-remaining-Stimulus-types.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e1b3a867c2b8a7cb4499a5ff2a581127293a04e9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Kirill=20M=C3=BCller?= -Date: Sun, 17 Aug 2025 10:38:47 +0200 -Subject: [PATCH] chore: Fix remaining Stimulus types - ---- - src/vendor/cigraph/interfaces/functions.yaml | 7 ++++--- - src/vendor/cigraph/interfaces/types.yaml | 7 ++++++- - 2 files changed, 10 insertions(+), 4 deletions(-) - -diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml -index f447f9afff..d621d01fef 100644 ---- a/src/vendor/cigraph/interfaces/functions.yaml -+++ b/src/vendor/cigraph/interfaces/functions.yaml -@@ -203,8 +203,9 @@ igraph_adjlist: - - igraph_full_bipartite: - PARAMS: |- -- OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, INTEGER n1, -+ OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, INTEGER n1, - INTEGER n2, BOOLEAN directed=False, NEIMODE mode=ALL -+ DEPS: types ON graph - - igraph_full_multipartite: - PARAMS: |- -@@ -521,14 +522,14 @@ igraph_get_shortest_paths: - VERTEX from, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, - OPTIONAL OUT VECTOR_INT parents, - OPTIONAL OUT VECTOR_INT inbound_edges -- DEPS: edges ON graph, from ON graph, to ON graph -+ DEPS: vertices ON graph, edges ON graph, from ON graph, to ON graph - - igraph_get_all_shortest_paths: - PARAMS: |- - GRAPH graph, OPTIONAL OUT VERTEXSET_LIST vertices, - OPTIONAL OUT EDGESET_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 -+ DEPS: vertices ON graph, edges ON graph, from ON graph, to ON graph - - igraph_distances_dijkstra: - PARAMS: |- -diff --git a/src/vendor/cigraph/interfaces/types.yaml b/src/vendor/cigraph/interfaces/types.yaml -index bdb9dd08a8..0a95c14ff1 100644 ---- a/src/vendor/cigraph/interfaces/types.yaml -+++ b/src/vendor/cigraph/interfaces/types.yaml -@@ -173,7 +173,12 @@ VERTEX_SELECTOR: - - BIPARTITE_TYPES: - # A vector containing Booleans that define the two partitions of a -- # bipartite graph -+ # bipartite graph, for a set of vertices -+ CTYPE: igraph_vector_bool_t -+ FLAGS: BY_REF -+ -+ALL_BIPARTITE_TYPES: -+ # Same as BIPARTITE_TYPES, for all vertices of a graph - CTYPE: igraph_vector_bool_t - FLAGS: BY_REF - --- -2.49.0 - diff --git a/src/Makevars.in b/src/Makevars.in index a49ad9a17ff..8d340b8c3b0 100644 --- a/src/Makevars.in +++ b/src/Makevars.in @@ -22,10 +22,11 @@ PKG_CFLAGS=$(C_VISIBILITY) PKG_CXXFLAGS=$(CXX_VISIBILITY) PKG_FFLAGS=$(F_VISIBILITY) -PKG_CPPFLAGS=-DUSING_R -I. -Ivendor -Ivendor/cigraph/src -Ivendor/cigraph/include -Ivendor/cigraph/vendor -Ivendor/io/parsers @cflags@ \ +PKG_CPPFLAGS=-DUSING_R -I. -Ivendor -Ivendor/cigraph/src -Ivendor/cigraph/include -Ivendor/cigraph/vendor -Ivendor/io/parsers -Ivendor/cigraph/vendor/infomap/src @cflags@ \ -DNDEBUG -DNTIMER -DNPRINT -DIGRAPH_THREAD_LOCAL= \ -DPRPACK_IGRAPH_SUPPORT \ -DHAVE_GFORTRAN=1 \ + -DHAVE_INFOMAP=1 \ -D_GNU_SOURCE=1 PKG_LIBS = @libs@ $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) diff --git a/src/Makevars.ucrt b/src/Makevars.ucrt index 96071ea7722..86e8050f8bc 100644 --- a/src/Makevars.ucrt +++ b/src/Makevars.ucrt @@ -27,10 +27,11 @@ else PKG_LIBS = $(shell pkg-config --libs libxml-2.0 glpk) endif -PKG_CPPFLAGS += -DUSING_R -I. -Ivendor -Ivendor/cigraph/src -Ivendor/cigraph/include -Ivendor/cigraph/vendor -Ivendor/io/parsers -Ivendor/mini-gmp \ +PKG_CPPFLAGS += -DUSING_R -I. -Ivendor -Ivendor/cigraph/src -Ivendor/cigraph/include -Ivendor/cigraph/vendor -Ivendor/io/parsers -Ivendor/mini-gmp -Ivendor/cigraph/vendor/infomap/src \ -DNDEBUG -DNTIMER -DNPRINT -DIGRAPH_THREAD_LOCAL= \ -DPRPACK_IGRAPH_SUPPORT \ -DHAVE_GFORTRAN=1 \ + -DHAVE_INFOMAP=1 \ -D_GNU_SOURCE=1 \ -DHAVE_LIBXML diff --git a/src/Makevars.win b/src/Makevars.win index 16b9bbd9b85..4959aedc057 100644 --- a/src/Makevars.win +++ b/src/Makevars.win @@ -19,10 +19,11 @@ LIB_XML ?= $(MINGW_PREFIX) GLPK_HOME ?= $(MINGW_PREFIX) LIB_GMP ?= $(MINGW_PREFIX) -PKG_CPPFLAGS=-DUSING_R -I. -Ivendor -Ivendor/cigraph/src -Ivendor/cigraph/include -Ivendor/cigraph/vendor -Ivendor/io/parsers -Ivendor/mini-gmp \ +PKG_CPPFLAGS=-DUSING_R -I. -Ivendor -Ivendor/cigraph/src -Ivendor/cigraph/include -Ivendor/cigraph/vendor -Ivendor/io/parsers -Ivendor/mini-gmp -Ivendor/cigraph/vendor/infomap/src \ -DNDEBUG -DNTIMER -DNPRINT -DIGRAPH_THREAD_LOCAL= \ -DPRPACK_IGRAPH_SUPPORT \ -DHAVE_GFORTRAN=1 \ + -DHAVE_INFOMAP=1 \ -D_GNU_SOURCE=1 \ -DHAVE_LIBXML diff --git a/src/cpp11.cpp b/src/cpp11.cpp index a87ea44454b..40b2c6c1795 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -46,9 +46,10 @@ extern SEXP R_igraph_assortativity_degree(SEXP, SEXP); extern SEXP R_igraph_assortativity_nominal(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_asymmetric_preference_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_atlas(SEXP); -extern SEXP R_igraph_automorphism_group(SEXP, SEXP, SEXP); +extern SEXP R_igraph_automorphism_group(SEXP, SEXP); +extern SEXP R_igraph_automorphism_group_bliss(SEXP, SEXP, SEXP); extern SEXP R_igraph_average_local_efficiency(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_average_path_length_dijkstra(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_average_path_length(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_avg_nearest_neighbor_degree(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_barabasi_aging_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_barabasi_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); @@ -59,14 +60,16 @@ extern SEXP R_igraph_bfs_simple(SEXP, SEXP, SEXP); extern SEXP R_igraph_biadjacency(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bibcoupling(SEXP, SEXP); extern SEXP R_igraph_biconnected_components(SEXP); -extern SEXP R_igraph_bipartite_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_bipartite_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bipartite_game_gnp(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_bipartite_iea_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bipartite_projection(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bipartite_projection_size(SEXP, SEXP); extern SEXP R_igraph_bond_percolation(SEXP, SEXP); extern SEXP R_igraph_bridges(SEXP); extern SEXP R_igraph_callaway_traits_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_canonical_permutation(SEXP, SEXP, SEXP); +extern SEXP R_igraph_canonical_permutation(SEXP, SEXP); +extern SEXP R_igraph_canonical_permutation_bliss(SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization(SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization_betweenness(SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization_betweenness_tmax(SEXP, SEXP, SEXP); @@ -74,8 +77,8 @@ extern SEXP R_igraph_centralization_closeness(SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization_closeness_tmax(SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization_degree(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization_degree_tmax(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_centralization_eigenvector_centrality(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_centralization_eigenvector_centrality_tmax(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_centralization_eigenvector_centrality(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_centralization_eigenvector_centrality_tmax(SEXP, SEXP, SEXP); extern SEXP R_igraph_chung_lu_game(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_circulant(SEXP, SEXP, SEXP); extern SEXP R_igraph_cited_type_game(SEXP, SEXP, SEXP, SEXP, SEXP); @@ -92,11 +95,11 @@ extern SEXP R_igraph_community_edge_betweenness(SEXP, SEXP, SEXP, SEXP, SEXP, SE extern SEXP R_igraph_community_fastgreedy(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_fluid_communities(SEXP, SEXP); extern SEXP R_igraph_community_infomap(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_community_label_propagation(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_community_label_propagation(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_leading_eigenvector(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_community_leiden(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_community_leiden(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_multilevel(SEXP, SEXP, SEXP); -extern SEXP R_igraph_community_optimal_modularity(SEXP, SEXP); +extern SEXP R_igraph_community_optimal_modularity(SEXP, SEXP, SEXP); extern SEXP R_igraph_community_to_membership2(SEXP, SEXP, SEXP); extern SEXP R_igraph_compare_communities(SEXP, SEXP, SEXP); extern SEXP R_igraph_complementer(SEXP, SEXP); @@ -114,7 +117,8 @@ extern SEXP R_igraph_coreness(SEXP, SEXP); extern SEXP R_igraph_correlated_game(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_correlated_pair_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_count_adjacent_triangles(SEXP, SEXP); -extern SEXP R_igraph_count_automorphisms(SEXP, SEXP, SEXP); +extern SEXP R_igraph_count_automorphisms(SEXP, SEXP); +extern SEXP R_igraph_count_automorphisms_bliss(SEXP, SEXP, SEXP); extern SEXP R_igraph_count_isomorphisms_vf2(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_count_loops(SEXP); extern SEXP R_igraph_count_multiple(SEXP, SEXP); @@ -131,9 +135,8 @@ extern SEXP R_igraph_degree_correlation_vector(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_degree_sequence_game(SEXP, SEXP, SEXP); extern SEXP R_igraph_delete_edges(SEXP, SEXP); extern SEXP R_igraph_delete_vertices(SEXP, SEXP); -extern SEXP R_igraph_delete_vertices_idx(SEXP, SEXP); +extern SEXP R_igraph_delete_vertices_map(SEXP, SEXP); extern SEXP R_igraph_density(SEXP, SEXP); -extern SEXP R_igraph_deterministic_optimal_imitation(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_dfs(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_diameter(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_difference(SEXP, SEXP); @@ -144,7 +147,7 @@ extern SEXP R_igraph_dominator_tree(SEXP, SEXP, SEXP); extern SEXP R_igraph_dot_product_game(SEXP, SEXP); extern SEXP R_igraph_dyad_census(SEXP); extern SEXP R_igraph_ecc(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_eccentricity_dijkstra(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_eccentricity(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_ecount(SEXP); extern SEXP R_igraph_edge_betweenness(SEXP, SEXP, SEXP); extern SEXP R_igraph_edge_betweenness_cutoff(SEXP, SEXP, SEXP, SEXP); @@ -153,10 +156,10 @@ extern SEXP R_igraph_edge_connectivity(SEXP, SEXP); extern SEXP R_igraph_edge_disjoint_paths(SEXP, SEXP, SEXP); extern SEXP R_igraph_edgelist_percolation(SEXP); extern SEXP R_igraph_edges(SEXP, SEXP); -extern SEXP R_igraph_eigen_adjacency(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_eigenvector_centrality(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_eigen_adjacency(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_eigenvector_centrality(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_empty(SEXP, SEXP); -extern SEXP R_igraph_erdos_renyi_game_gnm(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_erdos_renyi_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_erdos_renyi_game_gnp(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_es_adj(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_es_pairs(SEXP, SEXP, SEXP); @@ -186,12 +189,12 @@ extern SEXP R_igraph_get_adjacency_sparse(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_adjedgelist(SEXP, SEXP, SEXP); extern SEXP R_igraph_get_adjlist(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_eids_between(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_get_all_shortest_paths(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_get_all_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_shortest_paths_dijkstra(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_get_all_simple_paths(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_get_all_simple_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_simple_paths_pp(SEXP); extern SEXP R_igraph_get_attr_mode(SEXP, SEXP); -extern SEXP R_igraph_get_biadjacency(SEXP, SEXP); +extern SEXP R_igraph_get_biadjacency(SEXP, SEXP, SEXP); extern SEXP R_igraph_get_diameter(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_edge(SEXP, SEXP); extern SEXP R_igraph_get_edgelist(SEXP, SEXP); @@ -202,7 +205,7 @@ extern SEXP R_igraph_get_isomorphisms_vf2_callback(SEXP, SEXP, SEXP, SEXP, SEXP, extern SEXP R_igraph_get_k_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_laplacian(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_laplacian_sparse(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_get_shortest_path(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_get_shortest_path(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_shortest_path_bellman_ford(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_shortest_path_dijkstra(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); @@ -214,7 +217,7 @@ extern SEXP R_igraph_get_widest_paths(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_girth(SEXP, SEXP); extern SEXP R_igraph_global_efficiency(SEXP, SEXP, SEXP); extern SEXP R_igraph_gomory_hu_tree(SEXP, SEXP); -extern SEXP R_igraph_graph_center_dijkstra(SEXP, SEXP, SEXP); +extern SEXP R_igraph_graph_center(SEXP, SEXP, SEXP); extern SEXP R_igraph_graph_count(SEXP, SEXP); extern SEXP R_igraph_graph_power(SEXP, SEXP, SEXP); extern SEXP R_igraph_graph_version(SEXP); @@ -238,10 +241,11 @@ extern SEXP R_igraph_hrg_sample_many(SEXP, SEXP); extern SEXP R_igraph_hrg_size(SEXP); extern SEXP R_igraph_hsbm_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_hsbm_list_game(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_hub_and_authority_scores(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_hub_and_authority_scores(SEXP, SEXP, SEXP); extern SEXP R_igraph_hypercube(SEXP, SEXP); extern SEXP R_igraph_i_levc_arp(SEXP, SEXP, SEXP); extern SEXP R_igraph_identical_graphs(SEXP, SEXP, SEXP); +extern SEXP R_igraph_iea_game(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_incident(SEXP, SEXP, SEXP); extern SEXP R_igraph_incident_edges(SEXP, SEXP, SEXP); extern SEXP R_igraph_independence_number(SEXP); @@ -253,12 +257,14 @@ extern SEXP R_igraph_invalidate_cache(SEXP); extern SEXP R_igraph_is_acyclic(SEXP); extern SEXP R_igraph_is_biconnected(SEXP); extern SEXP R_igraph_is_bipartite(SEXP); +extern SEXP R_igraph_is_bipartite_coloring(SEXP, SEXP); extern SEXP R_igraph_is_chordal(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_is_clique(SEXP, SEXP, SEXP); extern SEXP R_igraph_is_complete(SEXP); extern SEXP R_igraph_is_connected(SEXP, SEXP); extern SEXP R_igraph_is_dag(SEXP); extern SEXP R_igraph_is_directed(SEXP); +extern SEXP R_igraph_is_edge_coloring(SEXP, SEXP); extern SEXP R_igraph_is_eulerian(SEXP); extern SEXP R_igraph_is_forest(SEXP, SEXP); extern SEXP R_igraph_is_graphical(SEXP, SEXP, SEXP); @@ -271,8 +277,9 @@ extern SEXP R_igraph_is_multiple(SEXP, SEXP); extern SEXP R_igraph_is_mutual(SEXP, SEXP, SEXP); extern SEXP R_igraph_is_perfect(SEXP); extern SEXP R_igraph_is_separator(SEXP, SEXP); -extern SEXP R_igraph_is_simple(SEXP); +extern SEXP R_igraph_is_simple(SEXP, SEXP); extern SEXP R_igraph_is_tree(SEXP, SEXP); +extern SEXP R_igraph_is_vertex_coloring(SEXP, SEXP); extern SEXP R_igraph_isoclass(SEXP); extern SEXP R_igraph_isoclass_create(SEXP, SEXP, SEXP); extern SEXP R_igraph_isoclass_subgraph(SEXP, SEXP); @@ -317,7 +324,7 @@ extern SEXP R_igraph_layout_sugiyama(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_layout_umap(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_layout_umap_3d(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_layout_umap_compute_weights(SEXP, SEXP, SEXP); -extern SEXP R_igraph_lcf_vector(SEXP, SEXP, SEXP); +extern SEXP R_igraph_lcf(SEXP, SEXP, SEXP); extern SEXP R_igraph_linegraph(SEXP); extern SEXP R_igraph_list_triangles(SEXP); extern SEXP R_igraph_local_efficiency(SEXP, SEXP, SEXP, SEXP, SEXP); @@ -348,7 +355,6 @@ extern SEXP R_igraph_minimum_spanning_tree_prim(SEXP, SEXP); extern SEXP R_igraph_minimum_spanning_tree_unweighted(SEXP); extern SEXP R_igraph_modularity(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_modularity_matrix(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_moran_process(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_motifs_randesu(SEXP, SEXP, SEXP); extern SEXP R_igraph_motifs_randesu_estimate(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_motifs_randesu_no(SEXP, SEXP, SEXP); @@ -359,6 +365,7 @@ extern SEXP R_igraph_mybracket2_set(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_mybracket3_set(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_mycielski_graph(SEXP); extern SEXP R_igraph_mycielskian(SEXP, SEXP); +extern SEXP R_igraph_nearest_neighbor_graph(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_neighborhood(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_neighborhood_graphs(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_neighborhood_size(SEXP, SEXP, SEXP, SEXP, SEXP); @@ -373,9 +380,7 @@ extern SEXP R_igraph_power_law_fit(SEXP, SEXP, SEXP); extern SEXP R_igraph_power_law_fit_new(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_preference_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_product(SEXP, SEXP, SEXP); -extern SEXP R_igraph_pseudo_diameter(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_pseudo_diameter_dijkstra(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_radius_dijkstra(SEXP, SEXP, SEXP); +extern SEXP R_igraph_pseudo_diameter(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_random_sample(SEXP, SEXP, SEXP); extern SEXP R_igraph_random_spanning_tree(SEXP, SEXP); extern SEXP R_igraph_random_walk(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); @@ -399,21 +404,19 @@ extern SEXP R_igraph_reverse_residual_graph(SEXP, SEXP, SEXP); extern SEXP R_igraph_rewire(SEXP, SEXP, SEXP); extern SEXP R_igraph_rewire_directed_edges(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_rewire_edges(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_rich_club_sequence(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_ring(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_rooted_product(SEXP, SEXP, SEXP); extern SEXP R_igraph_roots_for_tree_layout(SEXP, SEXP, SEXP); -extern SEXP R_igraph_roulette_wheel_imitation(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_running_mean(SEXP, SEXP); -extern SEXP R_igraph_sample_dirichlet(SEXP, SEXP); -extern SEXP R_igraph_sample_sphere_surface(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_sample_sphere_volume(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_sbm_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_set_verbose(SEXP); extern SEXP R_igraph_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_similarity_dice(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_similarity_dice(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_dice_es(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_dice_pairs(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_inverse_log_weighted(SEXP, SEXP, SEXP); -extern SEXP R_igraph_similarity_jaccard(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_similarity_jaccard(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_jaccard_es(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_jaccard_pairs(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_simple_cycles(SEXP, SEXP, SEXP, SEXP); @@ -435,7 +438,6 @@ extern SEXP R_igraph_st_vertex_connectivity(SEXP, SEXP, SEXP); extern SEXP R_igraph_star(SEXP, SEXP, SEXP); extern SEXP R_igraph_static_fitness_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_static_power_law_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_stochastic_imitation(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_strength(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_subcomponent(SEXP, SEXP, SEXP); extern SEXP R_igraph_subgraph_from_edges(SEXP, SEXP, SEXP); @@ -448,7 +450,6 @@ extern SEXP R_igraph_to_prufer(SEXP); extern SEXP R_igraph_to_undirected(SEXP, SEXP, SEXP); extern SEXP R_igraph_topological_sorting(SEXP, SEXP); extern SEXP R_igraph_transitive_closure(SEXP); -extern SEXP R_igraph_transitive_closure_dag(SEXP); extern SEXP R_igraph_transitivity_avglocal_undirected(SEXP, SEXP); extern SEXP R_igraph_transitivity_barrat(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_transitivity_local_undirected(SEXP, SEXP, SEXP); @@ -467,7 +468,6 @@ extern SEXP R_igraph_version(void); extern SEXP R_igraph_vertex_coloring_greedy(SEXP, SEXP); extern SEXP R_igraph_vertex_connectivity(SEXP, SEXP); extern SEXP R_igraph_vertex_disjoint_paths(SEXP, SEXP, SEXP); -extern SEXP R_igraph_vertex_path_from_edge_path(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_voronoi(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_vs_adj(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_vs_nei(SEXP, SEXP, SEXP, SEXP); @@ -477,6 +477,7 @@ extern SEXP R_igraph_weak_ref_key(SEXP); extern SEXP R_igraph_weak_ref_run_finalizer(SEXP); extern SEXP R_igraph_weak_ref_value(SEXP); extern SEXP R_igraph_weighted_adjacency(SEXP, SEXP, SEXP); +extern SEXP R_igraph_weighted_biadjacency(SEXP, SEXP, SEXP); extern SEXP R_igraph_weighted_clique_number(SEXP, SEXP); extern SEXP R_igraph_weighted_cliques(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_wheel(SEXP, SEXP, SEXP); @@ -518,9 +519,10 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_assortativity_nominal", (DL_FUNC) &R_igraph_assortativity_nominal, 4}, {"R_igraph_asymmetric_preference_game", (DL_FUNC) &R_igraph_asymmetric_preference_game, 6}, {"R_igraph_atlas", (DL_FUNC) &R_igraph_atlas, 1}, - {"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_average_path_length", (DL_FUNC) &R_igraph_average_path_length, 4}, {"R_igraph_avg_nearest_neighbor_degree", (DL_FUNC) &R_igraph_avg_nearest_neighbor_degree, 5}, {"R_igraph_barabasi_aging_game", (DL_FUNC) &R_igraph_barabasi_aging_game, 12}, {"R_igraph_barabasi_game", (DL_FUNC) &R_igraph_barabasi_game, 9}, @@ -531,14 +533,16 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_biadjacency", (DL_FUNC) &R_igraph_biadjacency, 4}, {"R_igraph_bibcoupling", (DL_FUNC) &R_igraph_bibcoupling, 2}, {"R_igraph_biconnected_components", (DL_FUNC) &R_igraph_biconnected_components, 1}, - {"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_iea_game", (DL_FUNC) &R_igraph_bipartite_iea_game, 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_bond_percolation", (DL_FUNC) &R_igraph_bond_percolation, 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}, @@ -546,8 +550,8 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_centralization_closeness_tmax", (DL_FUNC) &R_igraph_centralization_closeness_tmax, 3}, {"R_igraph_centralization_degree", (DL_FUNC) &R_igraph_centralization_degree, 4}, {"R_igraph_centralization_degree_tmax", (DL_FUNC) &R_igraph_centralization_degree_tmax, 4}, - {"R_igraph_centralization_eigenvector_centrality", (DL_FUNC) &R_igraph_centralization_eigenvector_centrality, 5}, - {"R_igraph_centralization_eigenvector_centrality_tmax", (DL_FUNC) &R_igraph_centralization_eigenvector_centrality_tmax, 4}, + {"R_igraph_centralization_eigenvector_centrality", (DL_FUNC) &R_igraph_centralization_eigenvector_centrality, 4}, + {"R_igraph_centralization_eigenvector_centrality_tmax", (DL_FUNC) &R_igraph_centralization_eigenvector_centrality_tmax, 3}, {"R_igraph_chung_lu_game", (DL_FUNC) &R_igraph_chung_lu_game, 4}, {"R_igraph_circulant", (DL_FUNC) &R_igraph_circulant, 3}, {"R_igraph_cited_type_game", (DL_FUNC) &R_igraph_cited_type_game, 5}, @@ -564,11 +568,11 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_community_fastgreedy", (DL_FUNC) &R_igraph_community_fastgreedy, 5}, {"R_igraph_community_fluid_communities", (DL_FUNC) &R_igraph_community_fluid_communities, 2}, {"R_igraph_community_infomap", (DL_FUNC) &R_igraph_community_infomap, 4}, - {"R_igraph_community_label_propagation", (DL_FUNC) &R_igraph_community_label_propagation, 5}, + {"R_igraph_community_label_propagation", (DL_FUNC) &R_igraph_community_label_propagation, 6}, {"R_igraph_community_leading_eigenvector", (DL_FUNC) &R_igraph_community_leading_eigenvector, 9}, - {"R_igraph_community_leiden", (DL_FUNC) &R_igraph_community_leiden, 8}, + {"R_igraph_community_leiden", (DL_FUNC) &R_igraph_community_leiden, 9}, {"R_igraph_community_multilevel", (DL_FUNC) &R_igraph_community_multilevel, 3}, - {"R_igraph_community_optimal_modularity", (DL_FUNC) &R_igraph_community_optimal_modularity, 2}, + {"R_igraph_community_optimal_modularity", (DL_FUNC) &R_igraph_community_optimal_modularity, 3}, {"R_igraph_community_to_membership2", (DL_FUNC) &R_igraph_community_to_membership2, 3}, {"R_igraph_compare_communities", (DL_FUNC) &R_igraph_compare_communities, 3}, {"R_igraph_complementer", (DL_FUNC) &R_igraph_complementer, 2}, @@ -586,7 +590,8 @@ static const R_CallMethodDef CallEntries[] = { {"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_adjacent_triangles", (DL_FUNC) &R_igraph_count_adjacent_triangles, 2}, - {"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_loops", (DL_FUNC) &R_igraph_count_loops, 1}, {"R_igraph_count_multiple", (DL_FUNC) &R_igraph_count_multiple, 2}, @@ -603,9 +608,8 @@ 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}, {"R_igraph_diameter", (DL_FUNC) &R_igraph_diameter, 4}, {"R_igraph_difference", (DL_FUNC) &R_igraph_difference, 2}, @@ -616,7 +620,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_dot_product_game", (DL_FUNC) &R_igraph_dot_product_game, 2}, {"R_igraph_dyad_census", (DL_FUNC) &R_igraph_dyad_census, 1}, {"R_igraph_ecc", (DL_FUNC) &R_igraph_ecc, 5}, - {"R_igraph_eccentricity_dijkstra", (DL_FUNC) &R_igraph_eccentricity_dijkstra, 4}, + {"R_igraph_eccentricity", (DL_FUNC) &R_igraph_eccentricity, 4}, {"R_igraph_ecount", (DL_FUNC) &R_igraph_ecount, 1}, {"R_igraph_edge_betweenness", (DL_FUNC) &R_igraph_edge_betweenness, 3}, {"R_igraph_edge_betweenness_cutoff", (DL_FUNC) &R_igraph_edge_betweenness_cutoff, 4}, @@ -625,10 +629,10 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_edge_disjoint_paths", (DL_FUNC) &R_igraph_edge_disjoint_paths, 3}, {"R_igraph_edgelist_percolation", (DL_FUNC) &R_igraph_edgelist_percolation, 1}, {"R_igraph_edges", (DL_FUNC) &R_igraph_edges, 2}, - {"R_igraph_eigen_adjacency", (DL_FUNC) &R_igraph_eigen_adjacency, 4}, - {"R_igraph_eigenvector_centrality", (DL_FUNC) &R_igraph_eigenvector_centrality, 5}, + {"R_igraph_eigen_adjacency", (DL_FUNC) &R_igraph_eigen_adjacency, 5}, + {"R_igraph_eigenvector_centrality", (DL_FUNC) &R_igraph_eigenvector_centrality, 4}, {"R_igraph_empty", (DL_FUNC) &R_igraph_empty, 2}, - {"R_igraph_erdos_renyi_game_gnm", (DL_FUNC) &R_igraph_erdos_renyi_game_gnm, 4}, + {"R_igraph_erdos_renyi_game_gnm", (DL_FUNC) &R_igraph_erdos_renyi_game_gnm, 5}, {"R_igraph_erdos_renyi_game_gnp", (DL_FUNC) &R_igraph_erdos_renyi_game_gnp, 4}, {"R_igraph_es_adj", (DL_FUNC) &R_igraph_es_adj, 4}, {"R_igraph_es_pairs", (DL_FUNC) &R_igraph_es_pairs, 3}, @@ -658,12 +662,12 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_get_adjedgelist", (DL_FUNC) &R_igraph_get_adjedgelist, 3}, {"R_igraph_get_adjlist", (DL_FUNC) &R_igraph_get_adjlist, 4}, {"R_igraph_get_all_eids_between", (DL_FUNC) &R_igraph_get_all_eids_between, 4}, - {"R_igraph_get_all_shortest_paths", (DL_FUNC) &R_igraph_get_all_shortest_paths, 4}, + {"R_igraph_get_all_shortest_paths", (DL_FUNC) &R_igraph_get_all_shortest_paths, 5}, {"R_igraph_get_all_shortest_paths_dijkstra", (DL_FUNC) &R_igraph_get_all_shortest_paths_dijkstra, 5}, - {"R_igraph_get_all_simple_paths", (DL_FUNC) &R_igraph_get_all_simple_paths, 5}, + {"R_igraph_get_all_simple_paths", (DL_FUNC) &R_igraph_get_all_simple_paths, 6}, {"R_igraph_get_all_simple_paths_pp", (DL_FUNC) &R_igraph_get_all_simple_paths_pp, 1}, {"R_igraph_get_attr_mode", (DL_FUNC) &R_igraph_get_attr_mode, 2}, - {"R_igraph_get_biadjacency", (DL_FUNC) &R_igraph_get_biadjacency, 2}, + {"R_igraph_get_biadjacency", (DL_FUNC) &R_igraph_get_biadjacency, 3}, {"R_igraph_get_diameter", (DL_FUNC) &R_igraph_get_diameter, 4}, {"R_igraph_get_edge", (DL_FUNC) &R_igraph_get_edge, 2}, {"R_igraph_get_edgelist", (DL_FUNC) &R_igraph_get_edgelist, 2}, @@ -674,7 +678,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_get_k_shortest_paths", (DL_FUNC) &R_igraph_get_k_shortest_paths, 6}, {"R_igraph_get_laplacian", (DL_FUNC) &R_igraph_get_laplacian, 4}, {"R_igraph_get_laplacian_sparse", (DL_FUNC) &R_igraph_get_laplacian_sparse, 4}, - {"R_igraph_get_shortest_path", (DL_FUNC) &R_igraph_get_shortest_path, 4}, + {"R_igraph_get_shortest_path", (DL_FUNC) &R_igraph_get_shortest_path, 5}, {"R_igraph_get_shortest_path_bellman_ford", (DL_FUNC) &R_igraph_get_shortest_path_bellman_ford, 5}, {"R_igraph_get_shortest_path_dijkstra", (DL_FUNC) &R_igraph_get_shortest_path_dijkstra, 5}, {"R_igraph_get_shortest_paths", (DL_FUNC) &R_igraph_get_shortest_paths, 10}, @@ -686,7 +690,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_girth", (DL_FUNC) &R_igraph_girth, 2}, {"R_igraph_global_efficiency", (DL_FUNC) &R_igraph_global_efficiency, 3}, {"R_igraph_gomory_hu_tree", (DL_FUNC) &R_igraph_gomory_hu_tree, 2}, - {"R_igraph_graph_center_dijkstra", (DL_FUNC) &R_igraph_graph_center_dijkstra, 3}, + {"R_igraph_graph_center", (DL_FUNC) &R_igraph_graph_center, 3}, {"R_igraph_graph_count", (DL_FUNC) &R_igraph_graph_count, 2}, {"R_igraph_graph_power", (DL_FUNC) &R_igraph_graph_power, 3}, {"R_igraph_graph_version", (DL_FUNC) &R_igraph_graph_version, 1}, @@ -710,10 +714,11 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_hrg_size", (DL_FUNC) &R_igraph_hrg_size, 1}, {"R_igraph_hsbm_game", (DL_FUNC) &R_igraph_hsbm_game, 5}, {"R_igraph_hsbm_list_game", (DL_FUNC) &R_igraph_hsbm_list_game, 5}, - {"R_igraph_hub_and_authority_scores", (DL_FUNC) &R_igraph_hub_and_authority_scores, 4}, + {"R_igraph_hub_and_authority_scores", (DL_FUNC) &R_igraph_hub_and_authority_scores, 3}, {"R_igraph_hypercube", (DL_FUNC) &R_igraph_hypercube, 2}, {"R_igraph_i_levc_arp", (DL_FUNC) &R_igraph_i_levc_arp, 3}, {"R_igraph_identical_graphs", (DL_FUNC) &R_igraph_identical_graphs, 3}, + {"R_igraph_iea_game", (DL_FUNC) &R_igraph_iea_game, 4}, {"R_igraph_incident", (DL_FUNC) &R_igraph_incident, 3}, {"R_igraph_incident_edges", (DL_FUNC) &R_igraph_incident_edges, 3}, {"R_igraph_independence_number", (DL_FUNC) &R_igraph_independence_number, 1}, @@ -725,12 +730,14 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_is_acyclic", (DL_FUNC) &R_igraph_is_acyclic, 1}, {"R_igraph_is_biconnected", (DL_FUNC) &R_igraph_is_biconnected, 1}, {"R_igraph_is_bipartite", (DL_FUNC) &R_igraph_is_bipartite, 1}, + {"R_igraph_is_bipartite_coloring", (DL_FUNC) &R_igraph_is_bipartite_coloring, 2}, {"R_igraph_is_chordal", (DL_FUNC) &R_igraph_is_chordal, 5}, {"R_igraph_is_clique", (DL_FUNC) &R_igraph_is_clique, 3}, {"R_igraph_is_complete", (DL_FUNC) &R_igraph_is_complete, 1}, {"R_igraph_is_connected", (DL_FUNC) &R_igraph_is_connected, 2}, {"R_igraph_is_dag", (DL_FUNC) &R_igraph_is_dag, 1}, {"R_igraph_is_directed", (DL_FUNC) &R_igraph_is_directed, 1}, + {"R_igraph_is_edge_coloring", (DL_FUNC) &R_igraph_is_edge_coloring, 2}, {"R_igraph_is_eulerian", (DL_FUNC) &R_igraph_is_eulerian, 1}, {"R_igraph_is_forest", (DL_FUNC) &R_igraph_is_forest, 2}, {"R_igraph_is_graphical", (DL_FUNC) &R_igraph_is_graphical, 3}, @@ -743,8 +750,9 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_is_mutual", (DL_FUNC) &R_igraph_is_mutual, 3}, {"R_igraph_is_perfect", (DL_FUNC) &R_igraph_is_perfect, 1}, {"R_igraph_is_separator", (DL_FUNC) &R_igraph_is_separator, 2}, - {"R_igraph_is_simple", (DL_FUNC) &R_igraph_is_simple, 1}, + {"R_igraph_is_simple", (DL_FUNC) &R_igraph_is_simple, 2}, {"R_igraph_is_tree", (DL_FUNC) &R_igraph_is_tree, 2}, + {"R_igraph_is_vertex_coloring", (DL_FUNC) &R_igraph_is_vertex_coloring, 2}, {"R_igraph_isoclass", (DL_FUNC) &R_igraph_isoclass, 1}, {"R_igraph_isoclass_create", (DL_FUNC) &R_igraph_isoclass_create, 3}, {"R_igraph_isoclass_subgraph", (DL_FUNC) &R_igraph_isoclass_subgraph, 2}, @@ -789,7 +797,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_layout_umap", (DL_FUNC) &R_igraph_layout_umap, 7}, {"R_igraph_layout_umap_3d", (DL_FUNC) &R_igraph_layout_umap_3d, 7}, {"R_igraph_layout_umap_compute_weights", (DL_FUNC) &R_igraph_layout_umap_compute_weights, 3}, - {"R_igraph_lcf_vector", (DL_FUNC) &R_igraph_lcf_vector, 3}, + {"R_igraph_lcf", (DL_FUNC) &R_igraph_lcf, 3}, {"R_igraph_linegraph", (DL_FUNC) &R_igraph_linegraph, 1}, {"R_igraph_list_triangles", (DL_FUNC) &R_igraph_list_triangles, 1}, {"R_igraph_local_efficiency", (DL_FUNC) &R_igraph_local_efficiency, 5}, @@ -820,7 +828,6 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_minimum_spanning_tree_unweighted", (DL_FUNC) &R_igraph_minimum_spanning_tree_unweighted, 1}, {"R_igraph_modularity", (DL_FUNC) &R_igraph_modularity, 5}, {"R_igraph_modularity_matrix", (DL_FUNC) &R_igraph_modularity_matrix, 4}, - {"R_igraph_moran_process", (DL_FUNC) &R_igraph_moran_process, 5}, {"R_igraph_motifs_randesu", (DL_FUNC) &R_igraph_motifs_randesu, 3}, {"R_igraph_motifs_randesu_estimate", (DL_FUNC) &R_igraph_motifs_randesu_estimate, 5}, {"R_igraph_motifs_randesu_no", (DL_FUNC) &R_igraph_motifs_randesu_no, 3}, @@ -831,6 +838,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_mybracket3_set", (DL_FUNC) &R_igraph_mybracket3_set, 5}, {"R_igraph_mycielski_graph", (DL_FUNC) &R_igraph_mycielski_graph, 1}, {"R_igraph_mycielskian", (DL_FUNC) &R_igraph_mycielskian, 2}, + {"R_igraph_nearest_neighbor_graph", (DL_FUNC) &R_igraph_nearest_neighbor_graph, 5}, {"R_igraph_neighborhood", (DL_FUNC) &R_igraph_neighborhood, 5}, {"R_igraph_neighborhood_graphs", (DL_FUNC) &R_igraph_neighborhood_graphs, 5}, {"R_igraph_neighborhood_size", (DL_FUNC) &R_igraph_neighborhood_size, 5}, @@ -845,9 +853,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_power_law_fit_new", (DL_FUNC) &R_igraph_power_law_fit_new, 5}, {"R_igraph_preference_game", (DL_FUNC) &R_igraph_preference_game, 7}, {"R_igraph_product", (DL_FUNC) &R_igraph_product, 3}, - {"R_igraph_pseudo_diameter", (DL_FUNC) &R_igraph_pseudo_diameter, 4}, - {"R_igraph_pseudo_diameter_dijkstra", (DL_FUNC) &R_igraph_pseudo_diameter_dijkstra, 5}, - {"R_igraph_radius_dijkstra", (DL_FUNC) &R_igraph_radius_dijkstra, 3}, + {"R_igraph_pseudo_diameter", (DL_FUNC) &R_igraph_pseudo_diameter, 5}, {"R_igraph_random_sample", (DL_FUNC) &R_igraph_random_sample, 3}, {"R_igraph_random_spanning_tree", (DL_FUNC) &R_igraph_random_spanning_tree, 2}, {"R_igraph_random_walk", (DL_FUNC) &R_igraph_random_walk, 6}, @@ -871,21 +877,19 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_rewire", (DL_FUNC) &R_igraph_rewire, 3}, {"R_igraph_rewire_directed_edges", (DL_FUNC) &R_igraph_rewire_directed_edges, 4}, {"R_igraph_rewire_edges", (DL_FUNC) &R_igraph_rewire_edges, 4}, + {"R_igraph_rich_club_sequence", (DL_FUNC) &R_igraph_rich_club_sequence, 6}, {"R_igraph_ring", (DL_FUNC) &R_igraph_ring, 4}, + {"R_igraph_rooted_product", (DL_FUNC) &R_igraph_rooted_product, 3}, {"R_igraph_roots_for_tree_layout", (DL_FUNC) &R_igraph_roots_for_tree_layout, 3}, - {"R_igraph_roulette_wheel_imitation", (DL_FUNC) &R_igraph_roulette_wheel_imitation, 6}, {"R_igraph_running_mean", (DL_FUNC) &R_igraph_running_mean, 2}, - {"R_igraph_sample_dirichlet", (DL_FUNC) &R_igraph_sample_dirichlet, 2}, - {"R_igraph_sample_sphere_surface", (DL_FUNC) &R_igraph_sample_sphere_surface, 4}, - {"R_igraph_sample_sphere_volume", (DL_FUNC) &R_igraph_sample_sphere_volume, 4}, {"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_cycles", (DL_FUNC) &R_igraph_simple_cycles, 4}, @@ -907,7 +911,6 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_star", (DL_FUNC) &R_igraph_star, 3}, {"R_igraph_static_fitness_game", (DL_FUNC) &R_igraph_static_fitness_game, 5}, {"R_igraph_static_power_law_game", (DL_FUNC) &R_igraph_static_power_law_game, 7}, - {"R_igraph_stochastic_imitation", (DL_FUNC) &R_igraph_stochastic_imitation, 6}, {"R_igraph_strength", (DL_FUNC) &R_igraph_strength, 5}, {"R_igraph_subcomponent", (DL_FUNC) &R_igraph_subcomponent, 3}, {"R_igraph_subgraph_from_edges", (DL_FUNC) &R_igraph_subgraph_from_edges, 3}, @@ -920,7 +923,6 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_to_undirected", (DL_FUNC) &R_igraph_to_undirected, 3}, {"R_igraph_topological_sorting", (DL_FUNC) &R_igraph_topological_sorting, 2}, {"R_igraph_transitive_closure", (DL_FUNC) &R_igraph_transitive_closure, 1}, - {"R_igraph_transitive_closure_dag", (DL_FUNC) &R_igraph_transitive_closure_dag, 1}, {"R_igraph_transitivity_avglocal_undirected", (DL_FUNC) &R_igraph_transitivity_avglocal_undirected, 2}, {"R_igraph_transitivity_barrat", (DL_FUNC) &R_igraph_transitivity_barrat, 4}, {"R_igraph_transitivity_local_undirected", (DL_FUNC) &R_igraph_transitivity_local_undirected, 3}, @@ -939,7 +941,6 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_vertex_coloring_greedy", (DL_FUNC) &R_igraph_vertex_coloring_greedy, 2}, {"R_igraph_vertex_connectivity", (DL_FUNC) &R_igraph_vertex_connectivity, 2}, {"R_igraph_vertex_disjoint_paths", (DL_FUNC) &R_igraph_vertex_disjoint_paths, 3}, - {"R_igraph_vertex_path_from_edge_path", (DL_FUNC) &R_igraph_vertex_path_from_edge_path, 4}, {"R_igraph_voronoi", (DL_FUNC) &R_igraph_voronoi, 5}, {"R_igraph_vs_adj", (DL_FUNC) &R_igraph_vs_adj, 4}, {"R_igraph_vs_nei", (DL_FUNC) &R_igraph_vs_nei, 4}, @@ -949,6 +950,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_weak_ref_run_finalizer", (DL_FUNC) &R_igraph_weak_ref_run_finalizer, 1}, {"R_igraph_weak_ref_value", (DL_FUNC) &R_igraph_weak_ref_value, 1}, {"R_igraph_weighted_adjacency", (DL_FUNC) &R_igraph_weighted_adjacency, 3}, + {"R_igraph_weighted_biadjacency", (DL_FUNC) &R_igraph_weighted_biadjacency, 3}, {"R_igraph_weighted_clique_number", (DL_FUNC) &R_igraph_weighted_clique_number, 2}, {"R_igraph_weighted_cliques", (DL_FUNC) &R_igraph_weighted_cliques, 5}, {"R_igraph_wheel", (DL_FUNC) &R_igraph_wheel, 3}, diff --git a/src/rinterface.c b/src/rinterface.c index c4576fdb5c0..725059b995c 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -115,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; @@ -137,7 +137,7 @@ SEXP R_igraph_delete_vertices_idx(SEXP graph, SEXP vertices) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_invidx, 0)); 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)); @@ -239,7 +239,9 @@ SEXP R_igraph_adjacency(SEXP adjmatrix, SEXP mode, SEXP loops) { c_mode = (igraph_adjacency_t) Rf_asInteger(mode); c_loops = (igraph_loops_t) Rf_asInteger(loops); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_adjacency(&c_graph, &c_adjmatrix, c_mode, c_loops)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -274,7 +276,9 @@ SEXP R_igraph_weighted_adjacency(SEXP adjmatrix, SEXP mode, SEXP loops) { weights=R_GlobalEnv; /* hack to have a non-NULL value */ c_loops = (igraph_loops_t) Rf_asInteger(loops); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_weighted_adjacency(&c_graph, &c_adjmatrix, c_mode, &c_weights, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -316,7 +320,9 @@ SEXP R_igraph_wheel(SEXP n, SEXP mode, SEXP center) { IGRAPH_R_CHECK_INT(center); c_center = (igraph_integer_t) REAL(center)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_wheel(&c_graph, c_n, c_mode, c_center)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -346,7 +352,9 @@ SEXP R_igraph_hypercube(SEXP n, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hypercube(&c_graph, c_n, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -386,7 +394,9 @@ SEXP R_igraph_square_lattice(SEXP dimvector, SEXP nei, SEXP directed, SEXP mutua R_SEXP_to_vector_bool(periodic, &c_periodic); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_square_lattice(&c_graph, &c_dimvector, c_nei, c_directed, c_mutual, (Rf_isNull(periodic) ? 0 : &c_periodic))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_square_lattice(&c_graph, &c_dimvector, c_nei, c_directed, c_mutual, (Rf_isNull(periodic) ? NULL : &c_periodic))); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -421,7 +431,9 @@ SEXP R_igraph_triangular_lattice(SEXP dimvector, SEXP directed, SEXP mutual) { IGRAPH_R_CHECK_BOOL(mutual); c_mutual = LOGICAL(mutual)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_triangular_lattice(&c_graph, &c_dimvector, c_directed, c_mutual)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -456,7 +468,9 @@ SEXP R_igraph_path_graph(SEXP n, SEXP directed, SEXP mutual) { IGRAPH_R_CHECK_BOOL(mutual); c_mutual = LOGICAL(mutual)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_path_graph(&c_graph, c_n, c_directed, c_mutual)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -489,7 +503,9 @@ SEXP R_igraph_cycle_graph(SEXP n, SEXP directed, SEXP mutual) { IGRAPH_R_CHECK_BOOL(mutual); c_mutual = LOGICAL(mutual)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_cycle_graph(&c_graph, c_n, c_directed, c_mutual)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -518,7 +534,9 @@ SEXP R_igraph_symmetric_tree(SEXP branches, SEXP type) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_branches); c_type = (igraph_tree_mode_t) Rf_asInteger(type); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_symmetric_tree(&c_graph, &c_branches, c_type)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -552,7 +570,9 @@ SEXP R_igraph_regular_tree(SEXP h, SEXP k, SEXP type) { c_k = (igraph_integer_t) REAL(k)[0]; c_type = (igraph_tree_mode_t) Rf_asInteger(type); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_regular_tree(&c_graph, c_h, c_k, c_type)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -582,7 +602,9 @@ SEXP R_igraph_full_citation(SEXP n, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_full_citation(&c_graph, c_n, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -609,7 +631,9 @@ SEXP R_igraph_atlas(SEXP number) { IGRAPH_R_CHECK_INT(number); c_number = (igraph_integer_t) REAL(number)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_atlas(&c_graph, c_number)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -642,7 +666,9 @@ SEXP R_igraph_extended_chordal_ring(SEXP nodes, SEXP W, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_extended_chordal_ring(&c_graph, c_nodes, &c_W, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -676,7 +702,9 @@ SEXP R_igraph_graph_power(SEXP graph, SEXP order, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_graph_power(&c_graph, &c_res, c_order, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_res); @@ -702,7 +730,9 @@ SEXP R_igraph_linegraph(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_linegraph(&c_graph, &c_linegraph)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_linegraph); @@ -776,9 +806,9 @@ SEXP R_igraph_kautz(SEXP m, SEXP n) { } /*-------------------------------------------/ -/ igraph_lcf_vector / +/ igraph_lcf / /-------------------------------------------*/ -SEXP R_igraph_lcf_vector(SEXP n, SEXP shifts, SEXP repeats) { +SEXP R_igraph_lcf(SEXP n, SEXP shifts, SEXP repeats) { /* Declarations */ igraph_t c_graph; igraph_integer_t c_n; @@ -795,7 +825,9 @@ SEXP R_igraph_lcf_vector(SEXP n, SEXP shifts, SEXP repeats) { IGRAPH_R_CHECK_INT(repeats); c_repeats = (igraph_integer_t) REAL(repeats)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_lcf_vector(&c_graph, c_n, &c_shifts, c_repeats)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_lcf(&c_graph, c_n, &c_shifts, c_repeats)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -824,7 +856,9 @@ SEXP R_igraph_mycielski_graph(SEXP k) { IGRAPH_R_CHECK_INT(k); c_k = (igraph_integer_t) REAL(k)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_mycielski_graph(&c_graph, c_k)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -855,7 +889,9 @@ SEXP R_igraph_adjlist(SEXP adjlist, SEXP mode, SEXP duplicate) { IGRAPH_R_CHECK_BOOL(duplicate); c_duplicate = LOGICAL(duplicate)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_adjlist(&c_graph, &c_adjlist, c_mode, c_duplicate)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -895,7 +931,9 @@ SEXP R_igraph_full_bipartite(SEXP n1, SEXP n2, SEXP directed, SEXP mode) { c_directed = LOGICAL(directed)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_full_bipartite(&c_graph, &c_types, c_n1, c_n2, c_directed, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -941,7 +979,9 @@ SEXP R_igraph_full_multipartite(SEXP n, SEXP directed, SEXP mode) { c_directed = LOGICAL(directed)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_full_multipartite(&c_graph, &c_types, &c_n, c_directed, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -992,7 +1032,9 @@ SEXP R_igraph_realize_degree_sequence(SEXP out_deg, SEXP in_deg, SEXP allowed_ed c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); c_method = (igraph_realize_degseq_t) Rf_asInteger(method); /* Call igraph */ - IGRAPH_R_CHECK(igraph_realize_degree_sequence(&c_graph, &c_out_deg, (Rf_isNull(in_deg) ? 0 : &c_in_deg), c_allowed_edge_types, c_method)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_realize_degree_sequence(&c_graph, &c_out_deg, (Rf_isNull(in_deg) ? NULL : &c_in_deg), c_allowed_edge_types, c_method)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1030,7 +1072,9 @@ SEXP R_igraph_realize_bipartite_degree_sequence(SEXP degrees1, SEXP degrees2, SE c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); c_method = (igraph_realize_degseq_t) Rf_asInteger(method); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_realize_bipartite_degree_sequence(&c_graph, &c_degrees1, &c_degrees2, c_allowed_edge_types, c_method)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1067,7 +1111,9 @@ SEXP R_igraph_circulant(SEXP n, SEXP shifts, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_circulant(&c_graph, c_n, &c_shifts, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1099,7 +1145,9 @@ SEXP R_igraph_generalized_petersen(SEXP n, SEXP k) { IGRAPH_R_CHECK_INT(k); c_k = (igraph_integer_t) REAL(k)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_generalized_petersen(&c_graph, c_n, c_k)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1133,7 +1181,9 @@ SEXP R_igraph_turan(SEXP n, SEXP r) { IGRAPH_R_CHECK_INT(r); c_r = (igraph_integer_t) REAL(r)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_turan(&c_graph, &c_types, c_n, c_r)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -1179,7 +1229,9 @@ SEXP R_igraph_erdos_renyi_game_gnp(SEXP n, SEXP p, SEXP directed, SEXP loops) { IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_erdos_renyi_game_gnp(&c_graph, c_n, c_p, c_directed, c_loops)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1195,7 +1247,48 @@ SEXP R_igraph_erdos_renyi_game_gnp(SEXP n, SEXP p, SEXP directed, SEXP loops) { /*-------------------------------------------/ / igraph_erdos_renyi_game_gnm / /-------------------------------------------*/ -SEXP R_igraph_erdos_renyi_game_gnm(SEXP n, SEXP m, SEXP directed, SEXP loops) { +SEXP R_igraph_erdos_renyi_game_gnm(SEXP n, SEXP m, SEXP directed, SEXP loops, SEXP multiple) { + /* Declarations */ + igraph_t c_graph; + igraph_integer_t c_n; + igraph_integer_t c_m; + igraph_bool_t c_directed; + igraph_bool_t c_loops; + igraph_bool_t c_multiple; + SEXP graph; + + SEXP r_result; + /* Convert input */ + IGRAPH_R_CHECK_INT(n); + c_n = (igraph_integer_t) REAL(n)[0]; + IGRAPH_R_CHECK_INT(m); + c_m = (igraph_integer_t) REAL(m)[0]; + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + IGRAPH_R_CHECK_BOOL(loops); + c_loops = LOGICAL(loops)[0]; + IGRAPH_R_CHECK_BOOL(multiple); + c_multiple = LOGICAL(multiple)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_erdos_renyi_game_gnm(&c_graph, c_n, c_m, c_directed, c_loops, c_multiple)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + r_result = graph; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_iea_game / +/-------------------------------------------*/ +SEXP R_igraph_iea_game(SEXP n, SEXP m, SEXP directed, SEXP loops) { /* Declarations */ igraph_t c_graph; igraph_integer_t c_n; @@ -1215,7 +1308,9 @@ SEXP R_igraph_erdos_renyi_game_gnm(SEXP n, SEXP m, SEXP directed, SEXP loops) { IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_erdos_renyi_game_gnm(&c_graph, c_n, c_m, c_directed, c_loops)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_iea_game(&c_graph, c_n, c_m, c_directed, c_loops)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1251,7 +1346,9 @@ SEXP R_igraph_growing_random_game(SEXP n, SEXP m, SEXP directed, SEXP citation) IGRAPH_R_CHECK_BOOL(citation); c_citation = LOGICAL(citation)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_growing_random_game(&c_graph, c_n, c_m, c_directed, c_citation)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1298,7 +1395,9 @@ SEXP R_igraph_preference_game(SEXP nodes, SEXP types, SEXP type_dist, SEXP fixed IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_preference_game(&c_graph, c_nodes, c_types, &c_type_dist, c_fixed_sizes, &c_pref_matrix, &c_node_type_vec, c_directed, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -1356,7 +1455,9 @@ SEXP R_igraph_asymmetric_preference_game(SEXP nodes, SEXP out_types, SEXP in_typ IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_asymmetric_preference_game(&c_graph, c_nodes, c_out_types, c_in_types, &c_type_dist_matrix, &c_pref_matrix, &c_node_type_out_vec, &c_node_type_in_vec, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -1405,7 +1506,9 @@ SEXP R_igraph_rewire_edges(SEXP graph, SEXP prob, SEXP loops, SEXP multiple) { IGRAPH_R_CHECK_BOOL(multiple); c_multiple = LOGICAL(multiple)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_rewire_edges(&c_graph, c_prob, c_loops, c_multiple)); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -1437,7 +1540,9 @@ SEXP R_igraph_rewire_directed_edges(SEXP graph, SEXP prob, SEXP loops, SEXP mode c_loops = LOGICAL(loops)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_rewire_directed_edges(&c_graph, c_prob, c_loops, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -1475,7 +1580,9 @@ SEXP R_igraph_forest_fire_game(SEXP nodes, SEXP fw_prob, SEXP bw_factor, SEXP am IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_forest_fire_game(&c_graph, c_nodes, c_fw_prob, c_bw_factor, c_ambs, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1511,7 +1618,9 @@ SEXP R_igraph_simple_interconnected_islands_game(SEXP islands_n, SEXP islands_si IGRAPH_R_CHECK_INT(n_inter); c_n_inter = (igraph_integer_t) REAL(n_inter)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_simple_interconnected_islands_game(&c_graph, c_islands_n, c_islands_size, c_islands_pin, c_n_inter)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1546,7 +1655,9 @@ SEXP R_igraph_chung_lu_game(SEXP out_weights, SEXP in_weights, SEXP loops, SEXP c_loops = LOGICAL(loops)[0]; c_variant = (igraph_chung_lu_t) Rf_asInteger(variant); /* Call igraph */ - IGRAPH_R_CHECK(igraph_chung_lu_game(&c_graph, &c_out_weights, (Rf_isNull(in_weights) ? 0 : &c_in_weights), c_loops, c_variant)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_chung_lu_game(&c_graph, &c_out_weights, (Rf_isNull(in_weights) ? NULL : &c_in_weights), c_loops, c_variant)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1585,7 +1696,9 @@ SEXP R_igraph_static_fitness_game(SEXP no_of_edges, SEXP fitness_out, SEXP fitne IGRAPH_R_CHECK_BOOL(multiple); c_multiple = LOGICAL(multiple)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_static_fitness_game(&c_graph, c_no_of_edges, &c_fitness_out, (Rf_isNull(fitness_in) ? 0 : &c_fitness_in), c_loops, c_multiple)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_static_fitness_game(&c_graph, c_no_of_edges, &c_fitness_out, (Rf_isNull(fitness_in) ? NULL : &c_fitness_in), c_loops, c_multiple)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1630,7 +1743,9 @@ SEXP R_igraph_static_power_law_game(SEXP no_of_nodes, SEXP no_of_edges, SEXP exp IGRAPH_R_CHECK_BOOL(finite_size_correction); c_finite_size_correction = LOGICAL(finite_size_correction)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_static_power_law_game(&c_graph, c_no_of_nodes, c_no_of_edges, c_exponent_out, c_exponent_in, c_loops, c_multiple, c_finite_size_correction)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1666,7 +1781,9 @@ SEXP R_igraph_k_regular_game(SEXP no_of_nodes, SEXP k, SEXP directed, SEXP multi IGRAPH_R_CHECK_BOOL(multiple); c_multiple = LOGICAL(multiple)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_k_regular_game(&c_graph, c_no_of_nodes, c_k, c_directed, c_multiple)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1704,7 +1821,9 @@ SEXP R_igraph_sbm_game(SEXP n, SEXP pref_matrix, SEXP block_sizes, SEXP directed IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_sbm_game(&c_graph, c_n, &c_pref_matrix, &c_block_sizes, c_directed, c_loops)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1743,7 +1862,9 @@ SEXP R_igraph_hsbm_game(SEXP n, SEXP m, SEXP rho, SEXP C, SEXP p) { IGRAPH_R_CHECK_REAL(p); c_p = REAL(p)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hsbm_game(&c_graph, c_n, c_m, &c_rho, &c_C, c_p)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1780,7 +1901,9 @@ SEXP R_igraph_hsbm_list_game(SEXP n, SEXP mlist, SEXP rholist, SEXP Clist, SEXP IGRAPH_R_CHECK_REAL(p); c_p = REAL(p)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hsbm_list_game(&c_graph, c_n, &c_mlist, &c_rholist, &c_Clist, c_p)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1822,7 +1945,9 @@ SEXP R_igraph_correlated_game(SEXP old_graph, SEXP corr, SEXP p, SEXP permutatio IGRAPH_FINALLY(igraph_vector_int_destroy, &c_permutation); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_correlated_game(&c_old_graph, &c_new_graph, c_corr, c_p, (Rf_isNull(permutation) ? 0 : &c_permutation))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_correlated_game(&c_old_graph, &c_new_graph, c_corr, c_p, (Rf_isNull(permutation) ? NULL : &c_permutation))); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_new_graph); @@ -1870,7 +1995,9 @@ SEXP R_igraph_correlated_pair_game(SEXP n, SEXP corr, SEXP p, SEXP directed, SEX IGRAPH_FINALLY(igraph_vector_int_destroy, &c_permutation); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_correlated_pair_game(&c_graph1, &c_graph2, c_n, c_corr, c_p, c_directed, (Rf_isNull(permutation) ? 0 : &c_permutation))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_correlated_pair_game(&c_graph1, &c_graph2, c_n, c_corr, c_p, c_directed, (Rf_isNull(permutation) ? NULL : &c_permutation))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -1912,7 +2039,9 @@ SEXP R_igraph_dot_product_game(SEXP vecs, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_dot_product_game(&c_graph, &c_vecs, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -1925,110 +2054,6 @@ SEXP R_igraph_dot_product_game(SEXP vecs, SEXP directed) { return(r_result); } -/*-------------------------------------------/ -/ igraph_sample_sphere_surface / -/-------------------------------------------*/ -SEXP R_igraph_sample_sphere_surface(SEXP dim, SEXP n, SEXP radius, SEXP positive) { - /* Declarations */ - igraph_integer_t c_dim; - igraph_integer_t c_n; - igraph_real_t c_radius; - igraph_bool_t c_positive; - igraph_matrix_t c_res; - SEXP res; - - SEXP r_result; - /* Convert input */ - IGRAPH_R_CHECK_INT(dim); - c_dim = (igraph_integer_t) REAL(dim)[0]; - IGRAPH_R_CHECK_INT(n); - c_n = (igraph_integer_t) REAL(n)[0]; - IGRAPH_R_CHECK_REAL(radius); - c_radius = REAL(radius)[0]; - IGRAPH_R_CHECK_BOOL(positive); - c_positive = LOGICAL(positive)[0]; - IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); - IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - /* Call igraph */ - IGRAPH_R_CHECK(igraph_sample_sphere_surface(c_dim, c_n, c_radius, c_positive, &c_res)); - - /* Convert output */ - PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); - igraph_matrix_destroy(&c_res); - IGRAPH_FINALLY_CLEAN(1); - r_result = res; - - UNPROTECT(1); - return(r_result); -} - -/*-------------------------------------------/ -/ igraph_sample_sphere_volume / -/-------------------------------------------*/ -SEXP R_igraph_sample_sphere_volume(SEXP dim, SEXP n, SEXP radius, SEXP positive) { - /* Declarations */ - igraph_integer_t c_dim; - igraph_integer_t c_n; - igraph_real_t c_radius; - igraph_bool_t c_positive; - igraph_matrix_t c_res; - SEXP res; - - SEXP r_result; - /* Convert input */ - IGRAPH_R_CHECK_INT(dim); - c_dim = (igraph_integer_t) REAL(dim)[0]; - IGRAPH_R_CHECK_INT(n); - c_n = (igraph_integer_t) REAL(n)[0]; - IGRAPH_R_CHECK_REAL(radius); - c_radius = REAL(radius)[0]; - IGRAPH_R_CHECK_BOOL(positive); - c_positive = LOGICAL(positive)[0]; - IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); - IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - /* Call igraph */ - IGRAPH_R_CHECK(igraph_sample_sphere_volume(c_dim, c_n, c_radius, c_positive, &c_res)); - - /* Convert output */ - PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); - igraph_matrix_destroy(&c_res); - IGRAPH_FINALLY_CLEAN(1); - r_result = res; - - UNPROTECT(1); - return(r_result); -} - -/*-------------------------------------------/ -/ igraph_sample_dirichlet / -/-------------------------------------------*/ -SEXP R_igraph_sample_dirichlet(SEXP n, SEXP alpha) { - /* Declarations */ - igraph_integer_t c_n; - igraph_vector_t c_alpha; - igraph_matrix_t c_res; - SEXP res; - - SEXP r_result; - /* Convert input */ - IGRAPH_R_CHECK_INT(n); - c_n = (igraph_integer_t) REAL(n)[0]; - R_SEXP_to_vector(alpha, &c_alpha); - IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); - IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - /* Call igraph */ - IGRAPH_R_CHECK(igraph_sample_dirichlet(c_n, &c_alpha, &c_res)); - - /* Convert output */ - PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); - igraph_matrix_destroy(&c_res); - IGRAPH_FINALLY_CLEAN(1); - r_result = res; - - UNPROTECT(1); - return(r_result); -} - /*-------------------------------------------/ / igraph_are_adjacent / /-------------------------------------------*/ @@ -2046,7 +2071,9 @@ SEXP R_igraph_are_adjacent(SEXP graph, SEXP v1, SEXP v2) { c_v1 = (igraph_integer_t) REAL(v1)[0]; c_v2 = (igraph_integer_t) REAL(v2)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_are_adjacent(&c_graph, c_v1, c_v2, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -2090,7 +2117,9 @@ SEXP R_igraph_closeness(SEXP graph, SEXP vids, SEXP mode, SEXP weights, SEXP nor IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_closeness(&c_graph, &c_res, &c_reachable_count, &c_all_reachable, c_vids, c_mode, (Rf_isNull(weights) ? 0 : &c_weights), c_normalized)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_closeness(&c_graph, &c_res, &c_reachable_count, &c_all_reachable, c_vids, c_mode, (Rf_isNull(weights) ? NULL : &c_weights), c_normalized)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -2154,7 +2183,9 @@ SEXP R_igraph_closeness_cutoff(SEXP graph, SEXP vids, SEXP mode, SEXP weights, S IGRAPH_R_CHECK_REAL(cutoff); c_cutoff = REAL(cutoff)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_closeness_cutoff(&c_graph, &c_res, &c_reachable_count, &c_all_reachable, c_vids, c_mode, (Rf_isNull(weights) ? 0 : &c_weights), c_normalized, c_cutoff)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_closeness_cutoff(&c_graph, &c_res, &c_reachable_count, &c_all_reachable, c_vids, c_mode, (Rf_isNull(weights) ? NULL : &c_weights), c_normalized, c_cutoff)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -2185,9 +2216,10 @@ SEXP R_igraph_closeness_cutoff(SEXP graph, SEXP vids, SEXP mode, SEXP weights, S /*-------------------------------------------/ / igraph_get_shortest_path / /-------------------------------------------*/ -SEXP R_igraph_get_shortest_path(SEXP graph, SEXP from, SEXP to, SEXP mode) { +SEXP R_igraph_get_shortest_path(SEXP graph, SEXP weights, SEXP from, SEXP to, SEXP mode) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_int_t c_vertices; igraph_vector_int_t c_edges; igraph_integer_t c_from; @@ -2199,6 +2231,9 @@ SEXP R_igraph_get_shortest_path(SEXP graph, SEXP from, SEXP to, SEXP mode) { SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_int_init(&c_vertices, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertices); IGRAPH_R_CHECK(igraph_vector_int_init(&c_edges, 0)); @@ -2207,7 +2242,9 @@ SEXP R_igraph_get_shortest_path(SEXP graph, SEXP from, SEXP to, SEXP mode) { c_to = (igraph_integer_t) REAL(to)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_shortest_path(&c_graph, &c_vertices, &c_edges, c_from, c_to, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_shortest_path(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_vertices, &c_edges, c_from, c_to, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -2258,7 +2295,9 @@ SEXP R_igraph_get_shortest_path_bellman_ford(SEXP graph, SEXP from, SEXP to, SEX } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_shortest_path_bellman_ford(&c_graph, &c_vertices, &c_edges, c_from, c_to, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_shortest_path_bellman_ford(&c_graph, &c_vertices, &c_edges, c_from, c_to, (Rf_isNull(weights) ? NULL : &c_weights), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -2309,7 +2348,9 @@ SEXP R_igraph_get_shortest_path_dijkstra(SEXP graph, SEXP from, SEXP to, SEXP we } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_shortest_path_dijkstra(&c_graph, &c_vertices, &c_edges, c_from, c_to, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_shortest_path_dijkstra(&c_graph, &c_vertices, &c_edges, c_from, c_to, (Rf_isNull(weights) ? NULL : &c_weights), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -2334,9 +2375,10 @@ SEXP R_igraph_get_shortest_path_dijkstra(SEXP graph, SEXP from, SEXP to, SEXP we /*-------------------------------------------/ / igraph_get_all_shortest_paths / /-------------------------------------------*/ -SEXP R_igraph_get_all_shortest_paths(SEXP graph, SEXP from, SEXP to, SEXP mode) { +SEXP R_igraph_get_all_shortest_paths(SEXP graph, SEXP weights, SEXP from, SEXP to, SEXP mode) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_int_list_t c_vertices; igraph_vector_int_list_t c_edges; igraph_vector_int_t c_nrgeo; @@ -2350,10 +2392,17 @@ SEXP R_igraph_get_all_shortest_paths(SEXP graph, SEXP from, SEXP to, SEXP mode) SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_vertices, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_vertices); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_edges, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_edges); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } + if (0 != igraph_vector_int_list_init(&c_vertices, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_vertices); + if (0 != igraph_vector_int_list_init(&c_edges, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_edges); IGRAPH_R_CHECK(igraph_vector_int_init(&c_nrgeo, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_nrgeo); c_from = (igraph_integer_t) REAL(from)[0]; @@ -2361,7 +2410,9 @@ SEXP R_igraph_get_all_shortest_paths(SEXP graph, SEXP from, SEXP to, SEXP mode) R_SEXP_to_igraph_vs(to, &c_graph, &c_to, &c_to_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_all_shortest_paths(&c_graph, &c_vertices, &c_edges, &c_nrgeo, c_from, c_to, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_all_shortest_paths(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_vertices, &c_edges, &c_nrgeo, c_from, c_to, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -2410,10 +2461,14 @@ SEXP R_igraph_get_all_shortest_paths_dijkstra(SEXP graph, SEXP from, SEXP to, SE SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_vertices, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_vertices); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_edges, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_edges); + if (0 != igraph_vector_int_list_init(&c_vertices, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_vertices); + if (0 != igraph_vector_int_list_init(&c_edges, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_edges); IGRAPH_R_CHECK(igraph_vector_int_init(&c_nrgeo, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_nrgeo); c_from = (igraph_integer_t) REAL(from)[0]; @@ -2424,7 +2479,9 @@ SEXP R_igraph_get_all_shortest_paths_dijkstra(SEXP graph, SEXP from, SEXP to, SE } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_all_shortest_paths_dijkstra(&c_graph, &c_vertices, &c_edges, &c_nrgeo, c_from, c_to, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_all_shortest_paths_dijkstra(&c_graph, &c_vertices, &c_edges, &c_nrgeo, c_from, c_to, (Rf_isNull(weights) ? NULL : &c_weights), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -2483,7 +2540,9 @@ SEXP R_igraph_voronoi(SEXP graph, SEXP generators, SEXP weights, SEXP mode, SEXP c_mode = (igraph_neimode_t) Rf_asInteger(mode); c_tiebreaker = (igraph_voronoi_tiebreaker_t) Rf_asInteger(tiebreaker); /* Call igraph */ - IGRAPH_R_CHECK(igraph_voronoi(&c_graph, &c_membership, &c_distances, &c_generators, (Rf_isNull(weights) ? 0 : &c_weights), c_mode, c_tiebreaker)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_voronoi(&c_graph, &c_membership, &c_distances, &c_generators, (Rf_isNull(weights) ? NULL : &c_weights), c_mode, c_tiebreaker)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -2510,33 +2569,40 @@ SEXP R_igraph_voronoi(SEXP graph, SEXP generators, SEXP weights, SEXP mode, SEXP /*-------------------------------------------/ / igraph_get_all_simple_paths / /-------------------------------------------*/ -SEXP R_igraph_get_all_simple_paths(SEXP graph, SEXP from, SEXP to, SEXP cutoff, SEXP mode) { +SEXP R_igraph_get_all_simple_paths(SEXP graph, SEXP from, SEXP to, SEXP minlen, SEXP maxlen, SEXP mode) { /* Declarations */ igraph_t c_graph; - igraph_vector_int_t c_res; + igraph_vector_int_list_t c_res; igraph_integer_t c_from; igraph_vs_t c_to; - igraph_integer_t c_cutoff; + igraph_integer_t c_minlen; + igraph_integer_t c_maxlen; igraph_neimode_t c_mode; SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_init(&c_res, 0)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_res); + if (0 != igraph_vector_int_list_init(&c_res, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_res); c_from = (igraph_integer_t) REAL(from)[0]; igraph_vector_int_t c_to_data; R_SEXP_to_igraph_vs(to, &c_graph, &c_to, &c_to_data); - IGRAPH_R_CHECK_INT(cutoff); - c_cutoff = (igraph_integer_t) REAL(cutoff)[0]; + IGRAPH_R_CHECK_INT(minlen); + c_minlen = (igraph_integer_t) REAL(minlen)[0]; + IGRAPH_R_CHECK_INT(maxlen); + c_maxlen = (igraph_integer_t) REAL(maxlen)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_all_simple_paths(&c_graph, &c_res, c_from, c_to, c_cutoff, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_all_simple_paths(&c_graph, &c_res, c_from, c_to, c_minlen, c_maxlen, c_mode)); + PutRNGstate(); /* Convert output */ - PROTECT(res=R_igraph_vector_int_to_SEXPp1(&c_res)); - igraph_vector_int_destroy(&c_res); + PROTECT(res=R_igraph_vector_int_list_to_SEXPp1(&c_res)); + igraph_vector_int_list_destroy(&c_res); IGRAPH_FINALLY_CLEAN(1); igraph_vector_int_destroy(&c_to_data); igraph_vs_destroy(&c_to); @@ -2568,17 +2634,23 @@ SEXP R_igraph_get_k_shortest_paths(SEXP graph, SEXP weights, SEXP k, SEXP from, if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_vertex_paths, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_vertex_paths); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_edge_paths, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_edge_paths); + if (0 != igraph_vector_int_list_init(&c_vertex_paths, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_vertex_paths); + if (0 != igraph_vector_int_list_init(&c_edge_paths, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_edge_paths); IGRAPH_R_CHECK_INT(k); c_k = (igraph_integer_t) REAL(k)[0]; c_from = (igraph_integer_t) REAL(from)[0]; c_to = (igraph_integer_t) REAL(to)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_k_shortest_paths(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_vertex_paths, &c_edge_paths, c_k, c_from, c_to, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_k_shortest_paths(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_vertex_paths, &c_edge_paths, c_k, c_from, c_to, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -2627,7 +2699,9 @@ SEXP R_igraph_get_widest_path(SEXP graph, SEXP from, SEXP to, SEXP weights, SEXP R_SEXP_to_vector(weights, &c_weights); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_get_widest_path(&c_graph, &c_vertices, &c_edges, c_from, c_to, &c_weights, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -2671,10 +2745,14 @@ SEXP R_igraph_get_widest_paths(SEXP graph, SEXP from, SEXP to, SEXP weights, SEX SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_vertices, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_vertices); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_edges, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_edges); + if (0 != igraph_vector_int_list_init(&c_vertices, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_vertices); + if (0 != igraph_vector_int_list_init(&c_edges, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_edges); c_from = (igraph_integer_t) REAL(from)[0]; igraph_vector_int_t c_to_data; R_SEXP_to_igraph_vs(to, &c_graph, &c_to, &c_to_data); @@ -2685,7 +2763,9 @@ SEXP R_igraph_get_widest_paths(SEXP graph, SEXP from, SEXP to, SEXP weights, SEX IGRAPH_R_CHECK(igraph_vector_int_init(&c_inbound_edges, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_inbound_edges); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_get_widest_paths(&c_graph, &c_vertices, &c_edges, c_from, c_to, &c_weights, c_mode, &c_parents, &c_inbound_edges)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(4)); @@ -2744,7 +2824,9 @@ SEXP R_igraph_widest_path_widths_dijkstra(SEXP graph, SEXP from, SEXP to, SEXP w R_SEXP_to_vector(weights, &c_weights); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_widest_path_widths_dijkstra(&c_graph, &c_res, c_from, c_to, &c_weights, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -2785,7 +2867,9 @@ SEXP R_igraph_widest_path_widths_floyd_warshall(SEXP graph, SEXP from, SEXP to, R_SEXP_to_vector(weights, &c_weights); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_widest_path_widths_floyd_warshall(&c_graph, &c_res, c_from, c_to, &c_weights, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -2823,7 +2907,9 @@ SEXP R_igraph_spanner(SEXP graph, SEXP stretch, SEXP weights) { R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_spanner(&c_graph, &c_spanner, c_stretch, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_spanner(&c_graph, &c_spanner, c_stretch, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(spanner=R_igraph_vector_int_to_SEXPp1(&c_spanner)); @@ -2863,7 +2949,9 @@ SEXP R_igraph_betweenness_cutoff(SEXP graph, SEXP vids, SEXP directed, SEXP weig IGRAPH_R_CHECK_REAL(cutoff); c_cutoff = REAL(cutoff)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_betweenness_cutoff(&c_graph, &c_res, c_vids, c_directed, (Rf_isNull(weights) ? 0 : &c_weights), c_cutoff)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_betweenness_cutoff(&c_graph, &c_res, c_vids, c_directed, (Rf_isNull(weights) ? NULL : &c_weights), c_cutoff)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -2908,7 +2996,9 @@ SEXP R_igraph_betweenness_subset(SEXP graph, SEXP vids, SEXP directed, SEXP sour R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_betweenness_subset(&c_graph, &c_res, c_vids, c_directed, c_sources, c_targets, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_betweenness_subset(&c_graph, &c_res, c_vids, c_directed, c_sources, c_targets, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -2948,7 +3038,9 @@ SEXP R_igraph_edge_betweenness(SEXP graph, SEXP directed, SEXP weights) { R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_edge_betweenness(&c_graph, &c_res, c_directed, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_edge_betweenness(&c_graph, &c_res, c_directed, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -2985,7 +3077,9 @@ SEXP R_igraph_edge_betweenness_cutoff(SEXP graph, SEXP directed, SEXP weights, S IGRAPH_R_CHECK_REAL(cutoff); c_cutoff = REAL(cutoff)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_edge_betweenness_cutoff(&c_graph, &c_res, c_directed, (Rf_isNull(weights) ? 0 : &c_weights), c_cutoff)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_edge_betweenness_cutoff(&c_graph, &c_res, c_directed, (Rf_isNull(weights) ? NULL : &c_weights), c_cutoff)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -3028,7 +3122,9 @@ SEXP R_igraph_edge_betweenness_subset(SEXP graph, SEXP eids, SEXP directed, SEXP R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_edge_betweenness_subset(&c_graph, &c_res, c_eids, c_directed, c_sources, c_targets, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_edge_betweenness_subset(&c_graph, &c_res, c_eids, c_directed, c_sources, c_targets, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -3076,7 +3172,9 @@ SEXP R_igraph_harmonic_centrality_cutoff(SEXP graph, SEXP vids, SEXP mode, SEXP IGRAPH_R_CHECK_REAL(cutoff); c_cutoff = REAL(cutoff)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_harmonic_centrality_cutoff(&c_graph, &c_res, c_vids, c_mode, (Rf_isNull(weights) ? 0 : &c_weights), c_normalized, c_cutoff)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_harmonic_centrality_cutoff(&c_graph, &c_res, c_vids, c_mode, (Rf_isNull(weights) ? NULL : &c_weights), c_normalized, c_cutoff)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -3136,7 +3234,9 @@ SEXP R_igraph_personalized_pagerank(SEXP graph, SEXP algo, SEXP vids, SEXP direc } } /* Call igraph */ - IGRAPH_R_CHECK(igraph_personalized_pagerank(&c_graph, c_algo, &c_vector, &c_value, c_vids, c_directed, c_damping, (Rf_isNull(personalized) ? 0 : &c_personalized), (Rf_isNull(weights) ? 0 : &c_weights), c_options)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_personalized_pagerank(&c_graph, c_algo, &c_vector, &c_value, c_vids, c_directed, c_damping, (Rf_isNull(personalized) ? NULL : &c_personalized), (Rf_isNull(weights) ? NULL : &c_weights), c_options)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -3211,7 +3311,9 @@ SEXP R_igraph_personalized_pagerank_vs(SEXP graph, SEXP algo, SEXP vids, SEXP di } } /* Call igraph */ - IGRAPH_R_CHECK(igraph_personalized_pagerank_vs(&c_graph, c_algo, &c_vector, &c_value, c_vids, c_directed, c_damping, c_reset_vids, (Rf_isNull(weights) ? 0 : &c_weights), c_options)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_personalized_pagerank_vs(&c_graph, c_algo, &c_vector, &c_value, c_vids, c_directed, c_damping, c_reset_vids, (Rf_isNull(weights) ? NULL : &c_weights), c_options)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -3261,7 +3363,9 @@ SEXP R_igraph_induced_subgraph(SEXP graph, SEXP vids, SEXP impl) { R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); c_impl = (igraph_subgraph_implementation_t) Rf_asInteger(impl); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_induced_subgraph(&c_graph, &c_res, c_vids, c_impl)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_res); @@ -3295,7 +3399,9 @@ SEXP R_igraph_subgraph_from_edges(SEXP graph, SEXP eids, SEXP delete_vertices) { IGRAPH_R_CHECK_BOOL(delete_vertices); c_delete_vertices = LOGICAL(delete_vertices)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_subgraph_from_edges(&c_graph, &c_res, c_eids, c_delete_vertices)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_res); @@ -3325,7 +3431,9 @@ SEXP R_igraph_reverse_edges(SEXP graph, SEXP eids) { igraph_vector_int_t c_eids_data; IGRAPH_R_CHECK(R_SEXP_to_igraph_es(eids, &c_graph, &c_eids, &c_eids_data)); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_reverse_edges(&c_graph, c_eids)); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -3340,14 +3448,14 @@ SEXP R_igraph_reverse_edges(SEXP graph, SEXP eids) { } /*-------------------------------------------/ -/ igraph_average_path_length_dijkstra / +/ igraph_average_path_length / /-------------------------------------------*/ -SEXP R_igraph_average_path_length_dijkstra(SEXP graph, SEXP weights, SEXP directed, SEXP unconn) { +SEXP R_igraph_average_path_length(SEXP graph, SEXP weights, SEXP directed, SEXP unconn) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_real_t c_res; igraph_real_t c_unconn_pairs; - igraph_vector_t c_weights; igraph_bool_t c_directed; igraph_bool_t c_unconn; SEXP res; @@ -3364,7 +3472,9 @@ SEXP R_igraph_average_path_length_dijkstra(SEXP graph, SEXP weights, SEXP direct IGRAPH_R_CHECK_BOOL(unconn); c_unconn = LOGICAL(unconn)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_average_path_length_dijkstra(&c_graph, &c_res, &c_unconn_pairs, (Rf_isNull(weights) ? 0 : &c_weights), c_directed, c_unconn)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_average_path_length(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, &c_unconn_pairs, c_directed, c_unconn)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -3376,7 +3486,7 @@ SEXP R_igraph_average_path_length_dijkstra(SEXP graph, SEXP weights, SEXP direct SET_VECTOR_ELT(r_result, 0, res); SET_VECTOR_ELT(r_result, 1, unconn_pairs); SET_STRING_ELT(r_names, 0, Rf_mkChar("res")); - SET_STRING_ELT(r_names, 1, Rf_mkChar("unconnected")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("unconn_pairs")); SET_NAMES(r_result, r_names); UNPROTECT(3); @@ -3404,7 +3514,9 @@ SEXP R_igraph_path_length_hist(SEXP graph, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_path_length_hist(&c_graph, &c_res, &c_unconnected, c_directed)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -3446,7 +3558,9 @@ SEXP R_igraph_simplify(SEXP graph, SEXP remove_multiple, SEXP remove_loops, SEXP R_SEXP_to_attr_comb(edge_attr_comb, &c_edge_attr_comb); IGRAPH_FINALLY(igraph_attribute_combination_destroy, &c_edge_attr_comb); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_simplify(&c_graph, c_remove_multiple, c_remove_loops, &c_edge_attr_comb)); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -3475,7 +3589,9 @@ SEXP R_igraph_transitivity_undirected(SEXP graph, SEXP mode) { R_SEXP_to_igraph(graph, &c_graph); c_mode = (igraph_transitivity_mode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_transitivity_undirected(&c_graph, &c_res, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -3506,7 +3622,9 @@ SEXP R_igraph_transitivity_local_undirected(SEXP graph, SEXP vids, SEXP mode) { R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); c_mode = (igraph_transitivity_mode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_transitivity_local_undirected(&c_graph, &c_res, c_vids, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -3535,7 +3653,9 @@ SEXP R_igraph_transitivity_avglocal_undirected(SEXP graph, SEXP mode) { R_SEXP_to_igraph(graph, &c_graph); c_mode = (igraph_transitivity_mode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_transitivity_avglocal_undirected(&c_graph, &c_res, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -3570,7 +3690,9 @@ SEXP R_igraph_transitivity_barrat(SEXP graph, SEXP vids, SEXP weights, SEXP mode } c_mode = (igraph_transitivity_mode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_transitivity_barrat(&c_graph, &c_res, c_vids, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_transitivity_barrat(&c_graph, &c_res, c_vids, (Rf_isNull(weights) ? NULL : &c_weights), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -3611,7 +3733,9 @@ SEXP R_igraph_ecc(SEXP graph, SEXP eids, SEXP k, SEXP offset, SEXP normalize) { IGRAPH_R_CHECK_BOOL(normalize); c_normalize = LOGICAL(normalize)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_ecc(&c_graph, &c_res, c_eids, c_k, c_offset, c_normalize)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -3643,7 +3767,9 @@ SEXP R_igraph_reciprocity(SEXP graph, SEXP ignore_loops, SEXP mode) { c_ignore_loops = LOGICAL(ignore_loops)[0]; c_mode = (igraph_reciprocity_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_reciprocity(&c_graph, &c_res, c_ignore_loops, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -3663,7 +3789,7 @@ SEXP R_igraph_maxdegree(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { igraph_integer_t c_res; igraph_vs_t c_vids; igraph_neimode_t c_mode; - igraph_bool_t c_loops; + igraph_loops_t c_loops; SEXP res; SEXP r_result; @@ -3673,10 +3799,11 @@ SEXP R_igraph_maxdegree(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { igraph_vector_int_t c_vids_data; R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; + c_loops = (igraph_loops_t) Rf_asInteger(loops); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_maxdegree(&c_graph, &c_res, c_vids, c_mode, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -3705,7 +3832,9 @@ SEXP R_igraph_density(SEXP graph, SEXP loops) { IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_density(&c_graph, &c_res, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -3732,7 +3861,9 @@ SEXP R_igraph_mean_degree(SEXP graph, SEXP loops) { IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_mean_degree(&c_graph, &c_res, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -3764,7 +3895,9 @@ SEXP R_igraph_feedback_arc_set(SEXP graph, SEXP weights, SEXP algo) { } c_algo = (igraph_fas_algorithm_t) Rf_asInteger(algo); /* Call igraph */ - IGRAPH_R_CHECK(igraph_feedback_arc_set(&c_graph, &c_result, (Rf_isNull(weights) ? 0 : &c_weights), c_algo)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_feedback_arc_set(&c_graph, &c_result, (Rf_isNull(weights) ? NULL : &c_weights), c_algo)); + PutRNGstate(); /* Convert output */ PROTECT(result=R_igraph_vector_int_to_SEXPp1(&c_result)); @@ -3797,7 +3930,9 @@ SEXP R_igraph_feedback_vertex_set(SEXP graph, SEXP weights, SEXP algo) { } c_algo = (igraph_fvs_algorithm_t) Rf_asInteger(algo); /* Call igraph */ - IGRAPH_R_CHECK(igraph_feedback_vertex_set(&c_graph, &c_result, (Rf_isNull(weights) ? 0 : &c_weights), c_algo)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_feedback_vertex_set(&c_graph, &c_result, (Rf_isNull(weights) ? NULL : &c_weights), c_algo)); + PutRNGstate(); /* Convert output */ PROTECT(result=R_igraph_vector_int_to_SEXPp1(&c_result)); @@ -3827,7 +3962,9 @@ SEXP R_igraph_is_loop(SEXP graph, SEXP es) { igraph_vector_int_t c_es_data; IGRAPH_R_CHECK(R_SEXP_to_igraph_es(es, &c_graph, &c_es, &c_es_data)); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_loop(&c_graph, &c_res, c_es)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_bool_to_SEXP(&c_res)); @@ -3854,7 +3991,9 @@ SEXP R_igraph_is_dag(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_dag(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -3878,7 +4017,9 @@ SEXP R_igraph_is_acyclic(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_acyclic(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -3892,17 +4033,22 @@ SEXP R_igraph_is_acyclic(SEXP graph) { /*-------------------------------------------/ / igraph_is_simple / /-------------------------------------------*/ -SEXP R_igraph_is_simple(SEXP graph) { +SEXP R_igraph_is_simple(SEXP graph, SEXP directed) { /* Declarations */ igraph_t c_graph; igraph_bool_t c_res; + igraph_bool_t c_directed; SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_is_simple(&c_graph, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_is_simple(&c_graph, &c_res, c_directed)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -3931,7 +4077,9 @@ SEXP R_igraph_is_multiple(SEXP graph, SEXP es) { igraph_vector_int_t c_es_data; IGRAPH_R_CHECK(R_SEXP_to_igraph_es(es, &c_graph, &c_es, &c_es_data)); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_multiple(&c_graph, &c_res, c_es)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_bool_to_SEXP(&c_res)); @@ -3958,7 +4106,9 @@ SEXP R_igraph_has_loop(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_has_loop(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -3982,7 +4132,9 @@ SEXP R_igraph_has_multiple(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_has_multiple(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -4007,7 +4159,9 @@ SEXP R_igraph_count_loops(SEXP graph) { R_SEXP_to_igraph(graph, &c_graph); c_loop_count=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_count_loops(&c_graph, &c_loop_count)); + PutRNGstate(); /* Convert output */ PROTECT(loop_count=NEW_NUMERIC(1)); @@ -4036,7 +4190,9 @@ SEXP R_igraph_count_multiple(SEXP graph, SEXP es) { igraph_vector_int_t c_es_data; IGRAPH_R_CHECK(R_SEXP_to_igraph_es(es, &c_graph, &c_es, &c_es_data)); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_count_multiple(&c_graph, &c_res, c_es)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_to_SEXP(&c_res)); @@ -4063,7 +4219,9 @@ SEXP R_igraph_is_perfect(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_perfect(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -4077,13 +4235,12 @@ SEXP R_igraph_is_perfect(SEXP graph) { /*-------------------------------------------/ / igraph_eigenvector_centrality / /-------------------------------------------*/ -SEXP R_igraph_eigenvector_centrality(SEXP graph, SEXP directed, SEXP scale, SEXP weights, SEXP options) { +SEXP R_igraph_eigenvector_centrality(SEXP graph, SEXP mode, SEXP weights, SEXP options) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_vector; igraph_real_t c_value; - igraph_bool_t c_directed; - igraph_bool_t c_scale; + igraph_neimode_t c_mode; igraph_vector_t c_weights; igraph_arpack_options_t c_options; SEXP vector; @@ -4094,16 +4251,15 @@ SEXP R_igraph_eigenvector_centrality(SEXP graph, SEXP directed, SEXP scale, SEXP R_SEXP_to_igraph(graph, &c_graph); IGRAPH_R_CHECK(igraph_vector_init(&c_vector, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_vector); - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_BOOL(scale); - c_scale = LOGICAL(scale)[0]; + c_mode = (igraph_neimode_t) Rf_asInteger(mode); if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } R_SEXP_to_igraph_arpack_options(options, &c_options); /* Call igraph */ - IGRAPH_R_CHECK(igraph_eigenvector_centrality(&c_graph, &c_vector, &c_value, c_directed, c_scale, (Rf_isNull(weights) ? 0 : &c_weights), &c_options)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_eigenvector_centrality(&c_graph, &c_vector, &c_value, c_mode, (Rf_isNull(weights) ? NULL : &c_weights), &c_options)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -4130,53 +4286,52 @@ SEXP R_igraph_eigenvector_centrality(SEXP graph, SEXP directed, SEXP scale, SEXP /*-------------------------------------------/ / igraph_hub_and_authority_scores / /-------------------------------------------*/ -SEXP R_igraph_hub_and_authority_scores(SEXP graph, SEXP scale, SEXP weights, SEXP options) { +SEXP R_igraph_hub_and_authority_scores(SEXP graph, SEXP weights, SEXP options) { /* Declarations */ igraph_t c_graph; - igraph_vector_t c_hub; - igraph_vector_t c_authority; + igraph_vector_t c_hub_vector; + igraph_vector_t c_authority_vector; igraph_real_t c_value; - igraph_bool_t c_scale; igraph_vector_t c_weights; igraph_arpack_options_t c_options; - SEXP hub; - SEXP authority; + SEXP hub_vector; + SEXP authority_vector; SEXP value; SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_init(&c_hub, 0)); - IGRAPH_FINALLY(igraph_vector_destroy, &c_hub); - IGRAPH_R_CHECK(igraph_vector_init(&c_authority, 0)); - IGRAPH_FINALLY(igraph_vector_destroy, &c_authority); - IGRAPH_R_CHECK_BOOL(scale); - c_scale = LOGICAL(scale)[0]; + IGRAPH_R_CHECK(igraph_vector_init(&c_hub_vector, 0)); + IGRAPH_FINALLY(igraph_vector_destroy, &c_hub_vector); + IGRAPH_R_CHECK(igraph_vector_init(&c_authority_vector, 0)); + IGRAPH_FINALLY(igraph_vector_destroy, &c_authority_vector); if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } R_SEXP_to_igraph_arpack_options(options, &c_options); /* Call igraph */ - IGRAPH_R_CHECK(igraph_hub_and_authority_scores(&c_graph, &c_hub, &c_authority, &c_value, c_scale, (Rf_isNull(weights) ? 0 : &c_weights), &c_options)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_hub_and_authority_scores(&c_graph, &c_hub_vector, &c_authority_vector, &c_value, (Rf_isNull(weights) ? NULL : &c_weights), &c_options)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(4)); PROTECT(r_names=NEW_CHARACTER(4)); - PROTECT(hub=R_igraph_vector_to_SEXP(&c_hub)); - igraph_vector_destroy(&c_hub); + PROTECT(hub_vector=R_igraph_vector_to_SEXP(&c_hub_vector)); + igraph_vector_destroy(&c_hub_vector); IGRAPH_FINALLY_CLEAN(1); - PROTECT(authority=R_igraph_vector_to_SEXP(&c_authority)); - igraph_vector_destroy(&c_authority); + PROTECT(authority_vector=R_igraph_vector_to_SEXP(&c_authority_vector)); + igraph_vector_destroy(&c_authority_vector); IGRAPH_FINALLY_CLEAN(1); PROTECT(value=NEW_NUMERIC(1)); REAL(value)[0]=c_value; PROTECT(options=R_igraph_arpack_options_to_SEXP(&c_options)); - SET_VECTOR_ELT(r_result, 0, hub); - SET_VECTOR_ELT(r_result, 1, authority); + SET_VECTOR_ELT(r_result, 0, hub_vector); + SET_VECTOR_ELT(r_result, 1, authority_vector); SET_VECTOR_ELT(r_result, 2, value); SET_VECTOR_ELT(r_result, 3, options); - SET_STRING_ELT(r_names, 0, Rf_mkChar("hub")); - SET_STRING_ELT(r_names, 1, Rf_mkChar("authority")); + SET_STRING_ELT(r_names, 0, Rf_mkChar("hub_vector")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("authority_vector")); SET_STRING_ELT(r_names, 2, Rf_mkChar("value")); SET_STRING_ELT(r_names, 3, Rf_mkChar("options")); SET_NAMES(r_result, r_names); @@ -4208,7 +4363,9 @@ SEXP R_igraph_unfold_tree(SEXP graph, SEXP mode, SEXP roots) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_vertex_index, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_index); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_unfold_tree(&c_graph, &c_tree, c_mode, &c_roots, &c_vertex_index)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -4254,7 +4411,9 @@ SEXP R_igraph_is_mutual(SEXP graph, SEXP es, SEXP loops) { IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_mutual(&c_graph, &c_res, c_es, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_bool_to_SEXP(&c_res)); @@ -4284,7 +4443,9 @@ SEXP R_igraph_has_mutual(SEXP graph, SEXP loops) { IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_has_mutual(&c_graph, &c_res, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -4314,7 +4475,9 @@ SEXP R_igraph_maximum_cardinality_search(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_alpham1, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_alpham1); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_maximum_cardinality_search(&c_graph, &c_alpha, &c_alpham1)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -4366,7 +4529,9 @@ SEXP R_igraph_avg_nearest_neighbor_degree(SEXP graph, SEXP vids, SEXP mode, SEXP R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_avg_nearest_neighbor_degree(&c_graph, c_vids, c_mode, c_neighbor_degree_mode, &c_knn, &c_knnk, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_avg_nearest_neighbor_degree(&c_graph, c_vids, c_mode, c_neighbor_degree_mode, &c_knn, &c_knnk, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -4416,7 +4581,9 @@ SEXP R_igraph_degree_correlation_vector(SEXP graph, SEXP weights, SEXP from_mode IGRAPH_R_CHECK_BOOL(directed_neighbors); c_directed_neighbors = LOGICAL(directed_neighbors)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_degree_correlation_vector(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_knnk, c_from_mode, c_to_mode, c_directed_neighbors)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_degree_correlation_vector(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_knnk, c_from_mode, c_to_mode, c_directed_neighbors)); + PutRNGstate(); /* Convert output */ PROTECT(knnk=R_igraph_vector_to_SEXP(&c_knnk)); @@ -4428,6 +4595,53 @@ SEXP R_igraph_degree_correlation_vector(SEXP graph, SEXP weights, SEXP from_mode return(r_result); } +/*-------------------------------------------/ +/ igraph_rich_club_sequence / +/-------------------------------------------*/ +SEXP R_igraph_rich_club_sequence(SEXP graph, SEXP weights, SEXP vertex_order, SEXP normalized, SEXP loops, SEXP directed) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_t c_weights; + igraph_vector_t c_res; + igraph_vector_int_t c_vertex_order; + igraph_bool_t c_normalized; + igraph_bool_t c_loops; + igraph_bool_t c_directed; + SEXP res; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } + IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); + IGRAPH_FINALLY(igraph_vector_destroy, &c_res); + R_SEXP_to_vector_int_copy(vertex_order, &c_vertex_order); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_order); + IGRAPH_R_CHECK_BOOL(normalized); + c_normalized = LOGICAL(normalized)[0]; + IGRAPH_R_CHECK_BOOL(loops); + c_loops = LOGICAL(loops)[0]; + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_rich_club_sequence(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, &c_vertex_order, c_normalized, c_loops, c_directed)); + PutRNGstate(); + + /* Convert output */ + PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); + igraph_vector_destroy(&c_res); + IGRAPH_FINALLY_CLEAN(1); + igraph_vector_int_destroy(&c_vertex_order); + IGRAPH_FINALLY_CLEAN(1); + r_result = res; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_strength / /-------------------------------------------*/ @@ -4437,7 +4651,7 @@ SEXP R_igraph_strength(SEXP graph, SEXP vids, SEXP mode, SEXP loops, SEXP weight igraph_vector_t c_res; igraph_vs_t c_vids; igraph_neimode_t c_mode; - igraph_bool_t c_loops; + igraph_loops_t c_loops; igraph_vector_t c_weights; SEXP res; @@ -4449,13 +4663,14 @@ SEXP R_igraph_strength(SEXP graph, SEXP vids, SEXP mode, SEXP loops, SEXP weight igraph_vector_int_t c_vids_data; R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; + c_loops = (igraph_loops_t) Rf_asInteger(loops); if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_strength(&c_graph, &c_res, c_vids, c_mode, c_loops, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_strength(&c_graph, &c_res, c_vids, c_mode, c_loops, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -4486,7 +4701,9 @@ SEXP R_igraph_centralization(SEXP scores, SEXP theoretical_max, SEXP normalized) IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ + GetRNGstate(); c_result=igraph_centralization(&c_scores, c_theoretical_max, c_normalized); + PutRNGstate(); /* Convert output */ @@ -4505,7 +4722,7 @@ SEXP R_igraph_centralization_degree(SEXP graph, SEXP mode, SEXP loops, SEXP norm igraph_t c_graph; igraph_vector_t c_res; igraph_neimode_t c_mode; - igraph_bool_t c_loops; + igraph_loops_t c_loops; igraph_real_t c_centralization; igraph_real_t c_theoretical_max; igraph_bool_t c_normalized; @@ -4519,12 +4736,13 @@ SEXP R_igraph_centralization_degree(SEXP graph, SEXP mode, SEXP loops, SEXP norm IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); c_mode = (igraph_neimode_t) Rf_asInteger(mode); - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; + c_loops = (igraph_loops_t) Rf_asInteger(loops); IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_centralization_degree(&c_graph, &c_res, c_mode, c_loops, &c_centralization, &c_theoretical_max, c_normalized)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -4557,7 +4775,7 @@ SEXP R_igraph_centralization_degree_tmax(SEXP graph, SEXP nodes, SEXP mode, SEXP igraph_t c_graph; igraph_integer_t c_nodes; igraph_neimode_t c_mode; - igraph_bool_t c_loops; + igraph_loops_t c_loops; igraph_real_t c_res; SEXP res; @@ -4569,10 +4787,11 @@ SEXP R_igraph_centralization_degree_tmax(SEXP graph, SEXP nodes, SEXP mode, SEXP IGRAPH_R_CHECK_INT(nodes); c_nodes = (igraph_integer_t) REAL(nodes)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; + c_loops = (igraph_loops_t) Rf_asInteger(loops); /* Call igraph */ - IGRAPH_R_CHECK(igraph_centralization_degree_tmax((Rf_isNull(graph) ? 0 : &c_graph), c_nodes, c_mode, c_loops, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_centralization_degree_tmax((Rf_isNull(graph) ? NULL : &c_graph), c_nodes, c_mode, c_loops, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -4608,7 +4827,9 @@ SEXP R_igraph_centralization_betweenness(SEXP graph, SEXP directed, SEXP normali IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_centralization_betweenness(&c_graph, &c_res, c_directed, &c_centralization, &c_theoretical_max, c_normalized)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -4654,7 +4875,9 @@ SEXP R_igraph_centralization_betweenness_tmax(SEXP graph, SEXP nodes, SEXP direc IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_centralization_betweenness_tmax((Rf_isNull(graph) ? 0 : &c_graph), c_nodes, c_directed, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_centralization_betweenness_tmax((Rf_isNull(graph) ? NULL : &c_graph), c_nodes, c_directed, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -4689,7 +4912,9 @@ SEXP R_igraph_centralization_closeness(SEXP graph, SEXP mode, SEXP normalized) { IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_centralization_closeness(&c_graph, &c_res, c_mode, &c_centralization, &c_theoretical_max, c_normalized)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -4734,7 +4959,9 @@ SEXP R_igraph_centralization_closeness_tmax(SEXP graph, SEXP nodes, SEXP mode) { c_nodes = (igraph_integer_t) REAL(nodes)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_centralization_closeness_tmax((Rf_isNull(graph) ? 0 : &c_graph), c_nodes, c_mode, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_centralization_closeness_tmax((Rf_isNull(graph) ? NULL : &c_graph), c_nodes, c_mode, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -4748,13 +4975,12 @@ SEXP R_igraph_centralization_closeness_tmax(SEXP graph, SEXP nodes, SEXP mode) { /*-------------------------------------------/ / igraph_centralization_eigenvector_centrality / /-------------------------------------------*/ -SEXP R_igraph_centralization_eigenvector_centrality(SEXP graph, SEXP directed, SEXP scale, SEXP options, SEXP normalized) { +SEXP R_igraph_centralization_eigenvector_centrality(SEXP graph, SEXP mode, SEXP options, SEXP normalized) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_vector; igraph_real_t c_value; - igraph_bool_t c_directed; - igraph_bool_t c_scale; + igraph_neimode_t c_mode; igraph_arpack_options_t c_options; igraph_real_t c_centralization; igraph_real_t c_theoretical_max; @@ -4769,15 +4995,14 @@ SEXP R_igraph_centralization_eigenvector_centrality(SEXP graph, SEXP directed, S R_SEXP_to_igraph(graph, &c_graph); IGRAPH_R_CHECK(igraph_vector_init(&c_vector, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_vector); - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_BOOL(scale); - c_scale = LOGICAL(scale)[0]; + c_mode = (igraph_neimode_t) Rf_asInteger(mode); R_SEXP_to_igraph_arpack_options(options, &c_options); IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_centralization_eigenvector_centrality(&c_graph, &c_vector, &c_value, c_directed, c_scale, &c_options, &c_centralization, &c_theoretical_max, c_normalized)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_centralization_eigenvector_centrality(&c_graph, &c_vector, &c_value, c_mode, &c_options, &c_centralization, &c_theoretical_max, c_normalized)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(5)); @@ -4812,12 +5037,11 @@ SEXP R_igraph_centralization_eigenvector_centrality(SEXP graph, SEXP directed, S /*-------------------------------------------/ / igraph_centralization_eigenvector_centrality_tmax / /-------------------------------------------*/ -SEXP R_igraph_centralization_eigenvector_centrality_tmax(SEXP graph, SEXP nodes, SEXP directed, SEXP scale) { +SEXP R_igraph_centralization_eigenvector_centrality_tmax(SEXP graph, SEXP nodes, SEXP mode) { /* Declarations */ igraph_t c_graph; igraph_integer_t c_nodes; - igraph_bool_t c_directed; - igraph_bool_t c_scale; + igraph_neimode_t c_mode; igraph_real_t c_res; SEXP res; @@ -4828,12 +5052,11 @@ SEXP R_igraph_centralization_eigenvector_centrality_tmax(SEXP graph, SEXP nodes, } IGRAPH_R_CHECK_INT(nodes); c_nodes = (igraph_integer_t) REAL(nodes)[0]; - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_BOOL(scale); - c_scale = LOGICAL(scale)[0]; + c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_centralization_eigenvector_centrality_tmax((Rf_isNull(graph) ? 0 : &c_graph), c_nodes, c_directed, c_scale, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_centralization_eigenvector_centrality_tmax((Rf_isNull(graph) ? NULL : &c_graph), c_nodes, c_mode, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -4866,7 +5089,9 @@ SEXP R_igraph_assortativity_nominal(SEXP graph, SEXP types, SEXP directed, SEXP IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_assortativity_nominal(&c_graph, &c_types, &c_res, c_directed, c_normalized)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_types); @@ -4904,7 +5129,9 @@ SEXP R_igraph_assortativity(SEXP graph, SEXP values, SEXP values_in, SEXP direct IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_assortativity(&c_graph, &c_values, (Rf_isNull(values_in) ? 0 : &c_values_in), &c_res, c_directed, c_normalized)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_assortativity(&c_graph, &c_values, (Rf_isNull(values_in) ? NULL : &c_values_in), &c_res, c_directed, c_normalized)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -4931,7 +5158,9 @@ SEXP R_igraph_assortativity_degree(SEXP graph, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_assortativity_degree(&c_graph, &c_res, c_directed)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -4967,7 +5196,9 @@ SEXP R_igraph_joint_degree_matrix(SEXP graph, SEXP weights, SEXP max_out_degree, IGRAPH_R_CHECK_INT(max_in_degree); c_max_in_degree = (igraph_integer_t) REAL(max_in_degree)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_joint_degree_matrix(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_jdm, c_max_out_degree, c_max_in_degree)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_joint_degree_matrix(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_jdm, c_max_out_degree, c_max_in_degree)); + PutRNGstate(); /* Convert output */ PROTECT(jdm=R_igraph_matrix_to_SEXP(&c_jdm)); @@ -5014,7 +5245,9 @@ SEXP R_igraph_joint_degree_distribution(SEXP graph, SEXP weights, SEXP from_mode IGRAPH_R_CHECK_INT(max_to_degree); c_max_to_degree = (igraph_integer_t) REAL(max_to_degree)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_joint_degree_distribution(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_p, c_from_mode, c_to_mode, c_directed_neighbors, c_normalized, c_max_from_degree, c_max_to_degree)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_joint_degree_distribution(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_p, c_from_mode, c_to_mode, c_directed_neighbors, c_normalized, c_max_from_degree, c_max_to_degree)); + PutRNGstate(); /* Convert output */ PROTECT(p=R_igraph_matrix_to_SEXP(&c_p)); @@ -5062,7 +5295,9 @@ SEXP R_igraph_joint_type_distribution(SEXP graph, SEXP weights, SEXP from_types, IGRAPH_R_CHECK_BOOL(normalized); c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_joint_type_distribution(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_p, &c_from_types, (Rf_isNull(to_types) ? 0 : &c_to_types), c_directed, c_normalized)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_joint_type_distribution(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_p, &c_from_types, (Rf_isNull(to_types) ? NULL : &c_to_types), c_directed, c_normalized)); + PutRNGstate(); /* Convert output */ PROTECT(p=R_igraph_matrix_to_SEXP(&c_p)); @@ -5096,7 +5331,9 @@ SEXP R_igraph_contract_vertices(SEXP graph, SEXP mapping, SEXP vertex_attr_comb) R_SEXP_to_attr_comb(vertex_attr_comb, &c_vertex_attr_comb); IGRAPH_FINALLY(igraph_attribute_combination_destroy, &c_vertex_attr_comb); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_contract_vertices(&c_graph, &c_mapping, &c_vertex_attr_comb)); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -5113,9 +5350,9 @@ SEXP R_igraph_contract_vertices(SEXP graph, SEXP mapping, SEXP vertex_attr_comb) } /*-------------------------------------------/ -/ igraph_eccentricity_dijkstra / +/ igraph_eccentricity / /-------------------------------------------*/ -SEXP R_igraph_eccentricity_dijkstra(SEXP graph, SEXP weights, SEXP vids, SEXP mode) { +SEXP R_igraph_eccentricity(SEXP graph, SEXP weights, SEXP vids, SEXP mode) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_weights; @@ -5136,7 +5373,9 @@ SEXP R_igraph_eccentricity_dijkstra(SEXP graph, SEXP weights, SEXP vids, SEXP mo R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_eccentricity_dijkstra(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_res, c_vids, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_eccentricity(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_vids, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -5151,9 +5390,9 @@ SEXP R_igraph_eccentricity_dijkstra(SEXP graph, SEXP weights, SEXP vids, SEXP mo } /*-------------------------------------------/ -/ igraph_graph_center_dijkstra / +/ igraph_graph_center / /-------------------------------------------*/ -SEXP R_igraph_graph_center_dijkstra(SEXP graph, SEXP weights, SEXP mode) { +SEXP R_igraph_graph_center(SEXP graph, SEXP weights, SEXP mode) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_weights; @@ -5171,7 +5410,9 @@ SEXP R_igraph_graph_center_dijkstra(SEXP graph, SEXP weights, SEXP mode) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_res); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_graph_center_dijkstra(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_res, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_graph_center(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_to_SEXPp1(&c_res)); @@ -5183,91 +5424,10 @@ SEXP R_igraph_graph_center_dijkstra(SEXP graph, SEXP weights, SEXP mode) { return(r_result); } -/*-------------------------------------------/ -/ igraph_radius_dijkstra / -/-------------------------------------------*/ -SEXP R_igraph_radius_dijkstra(SEXP graph, SEXP weights, SEXP mode) { - /* Declarations */ - igraph_t c_graph; - igraph_vector_t c_weights; - igraph_real_t c_radius; - igraph_neimode_t c_mode; - SEXP radius; - - SEXP r_result; - /* Convert input */ - R_SEXP_to_igraph(graph, &c_graph); - 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_radius_dijkstra(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_radius, c_mode)); - - /* Convert output */ - PROTECT(radius=NEW_NUMERIC(1)); - REAL(radius)[0]=c_radius; - r_result = radius; - - UNPROTECT(1); - return(r_result); -} - /*-------------------------------------------/ / igraph_pseudo_diameter / /-------------------------------------------*/ -SEXP R_igraph_pseudo_diameter(SEXP graph, SEXP start_vid, SEXP directed, SEXP unconnected) { - /* Declarations */ - igraph_t c_graph; - igraph_real_t c_diameter; - igraph_integer_t c_start_vid; - igraph_integer_t c_from; - igraph_integer_t c_to; - igraph_bool_t c_directed; - igraph_bool_t c_unconnected; - SEXP diameter; - SEXP from; - SEXP to; - - SEXP r_result, r_names; - /* Convert input */ - R_SEXP_to_igraph(graph, &c_graph); - c_start_vid = (igraph_integer_t) REAL(start_vid)[0]; - c_from=0; - c_to=0; - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_BOOL(unconnected); - c_unconnected = LOGICAL(unconnected)[0]; - /* Call igraph */ - IGRAPH_R_CHECK(igraph_pseudo_diameter(&c_graph, &c_diameter, c_start_vid, &c_from, &c_to, c_directed, c_unconnected)); - - /* Convert output */ - PROTECT(r_result=NEW_LIST(3)); - PROTECT(r_names=NEW_CHARACTER(3)); - PROTECT(diameter=NEW_NUMERIC(1)); - REAL(diameter)[0]=c_diameter; - PROTECT(from=NEW_NUMERIC(1)); - REAL(from)[0]=(double) c_from; - PROTECT(to=NEW_NUMERIC(1)); - REAL(to)[0]=(double) c_to; - SET_VECTOR_ELT(r_result, 0, diameter); - SET_VECTOR_ELT(r_result, 1, from); - SET_VECTOR_ELT(r_result, 2, to); - SET_STRING_ELT(r_names, 0, Rf_mkChar("diameter")); - SET_STRING_ELT(r_names, 1, Rf_mkChar("from")); - SET_STRING_ELT(r_names, 2, Rf_mkChar("to")); - SET_NAMES(r_result, r_names); - UNPROTECT(4); - - UNPROTECT(1); - return(r_result); -} - -/*-------------------------------------------/ -/ igraph_pseudo_diameter_dijkstra / -/-------------------------------------------*/ -SEXP R_igraph_pseudo_diameter_dijkstra(SEXP graph, SEXP weights, SEXP start_vid, SEXP directed, SEXP unconnected) { +SEXP R_igraph_pseudo_diameter(SEXP graph, SEXP weights, SEXP start_vid, SEXP directed, SEXP unconnected) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_weights; @@ -5295,7 +5455,9 @@ SEXP R_igraph_pseudo_diameter_dijkstra(SEXP graph, SEXP weights, SEXP start_vid, IGRAPH_R_CHECK_BOOL(unconnected); c_unconnected = LOGICAL(unconnected)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_pseudo_diameter_dijkstra(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_diameter, c_start_vid, &c_from, &c_to, c_directed, c_unconnected)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_pseudo_diameter(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_diameter, c_start_vid, &c_from, &c_to, c_directed, c_unconnected)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -5341,7 +5503,9 @@ SEXP R_igraph_diversity(SEXP graph, SEXP weights, SEXP vids) { igraph_vector_int_t c_vids_data; R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); /* Call igraph */ - IGRAPH_R_CHECK(igraph_diversity(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_res, c_vids)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_diversity(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_vids)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -5387,7 +5551,9 @@ SEXP R_igraph_random_walk(SEXP graph, SEXP weights, SEXP start, SEXP mode, SEXP c_steps = (igraph_integer_t) REAL(steps)[0]; c_stuck = (igraph_random_walk_stuck_t) Rf_asInteger(stuck); /* Call igraph */ - IGRAPH_R_CHECK(igraph_random_walk(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_vertices, &c_edges, c_start, c_mode, c_steps, c_stuck)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_random_walk(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_vertices, &c_edges, c_start, c_mode, c_steps, c_stuck)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -5415,8 +5581,8 @@ SEXP R_igraph_random_walk(SEXP graph, SEXP weights, SEXP start, SEXP mode, SEXP SEXP R_igraph_global_efficiency(SEXP graph, SEXP weights, SEXP directed) { /* Declarations */ igraph_t c_graph; - igraph_real_t c_res; igraph_vector_t c_weights; + igraph_real_t c_res; igraph_bool_t c_directed; SEXP res; @@ -5429,7 +5595,9 @@ SEXP R_igraph_global_efficiency(SEXP graph, SEXP weights, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_global_efficiency(&c_graph, &c_res, (Rf_isNull(weights) ? 0 : &c_weights), c_directed)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_global_efficiency(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_directed)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -5443,12 +5611,12 @@ SEXP R_igraph_global_efficiency(SEXP graph, SEXP weights, SEXP directed) { /*-------------------------------------------/ / igraph_local_efficiency / /-------------------------------------------*/ -SEXP R_igraph_local_efficiency(SEXP graph, SEXP vids, SEXP weights, SEXP directed, SEXP mode) { +SEXP R_igraph_local_efficiency(SEXP graph, SEXP weights, SEXP vids, SEXP directed, SEXP mode) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_t c_res; igraph_vs_t c_vids; - igraph_vector_t c_weights; igraph_bool_t c_directed; igraph_neimode_t c_mode; SEXP res; @@ -5456,18 +5624,20 @@ SEXP R_igraph_local_efficiency(SEXP graph, SEXP vids, SEXP weights, SEXP directe SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); igraph_vector_int_t c_vids_data; R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_efficiency(&c_graph, &c_res, c_vids, (Rf_isNull(weights) ? 0 : &c_weights), c_directed, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_efficiency(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_vids, c_directed, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -5487,8 +5657,8 @@ SEXP R_igraph_local_efficiency(SEXP graph, SEXP vids, SEXP weights, SEXP directe SEXP R_igraph_average_local_efficiency(SEXP graph, SEXP weights, SEXP directed, SEXP mode) { /* Declarations */ igraph_t c_graph; - igraph_real_t c_res; igraph_vector_t c_weights; + igraph_real_t c_res; igraph_bool_t c_directed; igraph_neimode_t c_mode; SEXP res; @@ -5503,7 +5673,9 @@ SEXP R_igraph_average_local_efficiency(SEXP graph, SEXP weights, SEXP directed, c_directed = LOGICAL(directed)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_average_local_efficiency(&c_graph, &c_res, (Rf_isNull(weights) ? 0 : &c_weights), c_directed, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_average_local_efficiency(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_directed, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -5514,32 +5686,6 @@ SEXP R_igraph_average_local_efficiency(SEXP graph, SEXP weights, SEXP directed, return(r_result); } -/*-------------------------------------------/ -/ igraph_transitive_closure_dag / -/-------------------------------------------*/ -SEXP R_igraph_transitive_closure_dag(SEXP graph) { - /* Declarations */ - igraph_t c_graph; - igraph_t c_closure; - SEXP closure; - - SEXP r_result; - /* Convert input */ - R_SEXP_to_igraph(graph, &c_graph); - /* Call igraph */ - IGRAPH_R_CHECK(igraph_transitive_closure_dag(&c_graph, &c_closure)); - - /* Convert output */ - IGRAPH_FINALLY(igraph_destroy, &c_closure); - PROTECT(closure=R_igraph_to_SEXP(&c_closure)); - IGRAPH_I_DESTROY(&c_closure); - IGRAPH_FINALLY_CLEAN(1); - r_result = closure; - - UNPROTECT(1); - return(r_result); -} - /*-------------------------------------------/ / igraph_transitive_closure / /-------------------------------------------*/ @@ -5553,7 +5699,9 @@ SEXP R_igraph_transitive_closure(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_transitive_closure(&c_graph, &c_closure)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_closure); @@ -5581,7 +5729,9 @@ SEXP R_igraph_trussness(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_trussness, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_trussness); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_trussness(&c_graph, &c_trussness)); + PutRNGstate(); /* Convert output */ PROTECT(trussness=R_igraph_vector_int_to_SEXP(&c_trussness)); @@ -5617,7 +5767,9 @@ SEXP R_igraph_is_graphical(SEXP out_deg, SEXP in_deg, SEXP allowed_edge_types) { } c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); /* Call igraph */ - IGRAPH_R_CHECK(igraph_is_graphical(&c_out_deg, (Rf_isNull(in_deg) ? 0 : &c_in_deg), c_allowed_edge_types, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_is_graphical(&c_out_deg, (Rf_isNull(in_deg) ? NULL : &c_in_deg), c_allowed_edge_types, &c_res)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_out_deg); @@ -5659,7 +5811,9 @@ SEXP R_igraph_bfs_simple(SEXP graph, SEXP root, SEXP mode) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_parents, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_parents); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_bfs_simple(&c_graph, c_root, c_mode, &c_order, &c_layers, &c_parents)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -5711,7 +5865,9 @@ SEXP R_igraph_bipartite_projection_size(SEXP graph, SEXP types) { c_vcount2=0; c_ecount2=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_bipartite_projection_size(&c_graph, &c_types, &c_vcount1, &c_ecount1, &c_vcount2, &c_ecount2)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(4)); @@ -5758,7 +5914,9 @@ SEXP R_igraph_create_bipartite(SEXP types, SEXP edges, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_create_bipartite(&c_graph, &c_types, &c_edges, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -5776,11 +5934,11 @@ SEXP R_igraph_create_bipartite(SEXP types, SEXP edges, SEXP directed) { /*-------------------------------------------/ / igraph_biadjacency / /-------------------------------------------*/ -SEXP R_igraph_biadjacency(SEXP incidence, SEXP directed, SEXP mode, SEXP multiple) { +SEXP R_igraph_biadjacency(SEXP biadjmatrix, SEXP directed, SEXP mode, SEXP multiple) { /* Declarations */ igraph_t c_graph; igraph_vector_bool_t c_types; - igraph_matrix_t c_incidence; + igraph_matrix_t c_biadjmatrix; igraph_bool_t c_directed; igraph_neimode_t c_mode; igraph_bool_t c_multiple; @@ -5791,14 +5949,16 @@ SEXP R_igraph_biadjacency(SEXP incidence, SEXP directed, SEXP mode, SEXP multipl /* Convert input */ IGRAPH_R_CHECK(igraph_vector_bool_init(&c_types, 0)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &c_types); - R_SEXP_to_matrix(incidence, &c_incidence); + R_SEXP_to_matrix(biadjmatrix, &c_biadjmatrix); 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_biadjacency(&c_graph, &c_types, &c_incidence, c_directed, c_mode, c_multiple)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_biadjacency(&c_graph, &c_types, &c_biadjmatrix, c_directed, c_mode, c_multiple)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -5821,13 +5981,71 @@ SEXP R_igraph_biadjacency(SEXP incidence, SEXP directed, SEXP mode, SEXP multipl return(r_result); } +/*-------------------------------------------/ +/ igraph_weighted_biadjacency / +/-------------------------------------------*/ +SEXP R_igraph_weighted_biadjacency(SEXP biadjmatrix, SEXP directed, SEXP mode) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_bool_t c_types; + igraph_vector_t c_weights; + igraph_matrix_t c_biadjmatrix; + igraph_bool_t c_directed; + igraph_neimode_t c_mode; + SEXP graph; + SEXP types; + SEXP weights; + + SEXP r_result, r_names; + /* Convert input */ + IGRAPH_R_CHECK(igraph_vector_bool_init(&c_types, 0)); + IGRAPH_FINALLY(igraph_vector_bool_destroy, &c_types); + IGRAPH_R_CHECK(igraph_vector_init(&c_weights, 0)); + IGRAPH_FINALLY(igraph_vector_destroy, &c_weights); + weights=R_GlobalEnv; /* hack to have a non-NULL value */ + R_SEXP_to_matrix(biadjmatrix, &c_biadjmatrix); + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + c_mode = (igraph_neimode_t) Rf_asInteger(mode); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_weighted_biadjacency(&c_graph, &c_types, &c_weights, &c_biadjmatrix, c_directed, c_mode)); + PutRNGstate(); + + /* Convert output */ + PROTECT(r_result=NEW_LIST(3)); + PROTECT(r_names=NEW_CHARACTER(3)); + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(types=R_igraph_vector_bool_to_SEXP(&c_types)); + igraph_vector_bool_destroy(&c_types); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(weights=R_igraph_0orvector_to_SEXP(&c_weights)); + igraph_vector_destroy(&c_weights); + IGRAPH_FINALLY_CLEAN(1); + SET_VECTOR_ELT(r_result, 0, graph); + SET_VECTOR_ELT(r_result, 1, types); + SET_VECTOR_ELT(r_result, 2, weights); + SET_STRING_ELT(r_names, 0, Rf_mkChar("graph")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("types")); + SET_STRING_ELT(r_names, 2, Rf_mkChar("weights")); + SET_NAMES(r_result, r_names); + UNPROTECT(4); + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_get_biadjacency / /-------------------------------------------*/ -SEXP R_igraph_get_biadjacency(SEXP graph, SEXP types) { +SEXP R_igraph_get_biadjacency(SEXP graph, SEXP types, SEXP weights) { /* Declarations */ igraph_t c_graph; igraph_vector_bool_t c_types; + igraph_vector_t c_weights; igraph_matrix_t c_res; igraph_vector_int_t c_row_ids; igraph_vector_int_t c_col_ids; @@ -5839,6 +6057,9 @@ SEXP R_igraph_get_biadjacency(SEXP graph, SEXP types) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); R_SEXP_to_vector_bool(types, &c_types); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); IGRAPH_R_CHECK(igraph_vector_int_init(&c_row_ids, 0)); @@ -5846,7 +6067,9 @@ SEXP R_igraph_get_biadjacency(SEXP graph, SEXP types) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_col_ids, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_col_ids); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_biadjacency(&c_graph, &c_types, &c_res, &c_row_ids, &c_col_ids)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_biadjacency(&c_graph, &c_types, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, &c_row_ids, &c_col_ids)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -5890,7 +6113,9 @@ SEXP R_igraph_is_bipartite(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_bool_init(&c_type, 0)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &c_type); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_bipartite(&c_graph, &c_res, &c_type)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -5940,7 +6165,9 @@ SEXP R_igraph_bipartite_game_gnp(SEXP n1, SEXP n2, SEXP p, SEXP directed, SEXP m c_directed = LOGICAL(directed)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_bipartite_game_gnp(&c_graph, &c_types, c_n1, c_n2, c_p, c_directed, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -5966,7 +6193,64 @@ 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; + igraph_integer_t c_n1; + igraph_integer_t c_n2; + igraph_integer_t c_m; + igraph_bool_t c_directed; + igraph_neimode_t c_mode; + igraph_bool_t c_multiple; + SEXP graph; + SEXP types; + + SEXP r_result, r_names; + /* Convert input */ + IGRAPH_R_CHECK(igraph_vector_bool_init(&c_types, 0)); + IGRAPH_FINALLY(igraph_vector_bool_destroy, &c_types); + IGRAPH_R_CHECK_INT(n1); + c_n1 = (igraph_integer_t) REAL(n1)[0]; + IGRAPH_R_CHECK_INT(n2); + c_n2 = (igraph_integer_t) REAL(n2)[0]; + IGRAPH_R_CHECK_INT(m); + c_m = (igraph_integer_t) REAL(m)[0]; + 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 */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_bipartite_game_gnm(&c_graph, &c_types, c_n1, c_n2, c_m, c_directed, c_mode, c_multiple)); + PutRNGstate(); + + /* Convert output */ + PROTECT(r_result=NEW_LIST(2)); + PROTECT(r_names=NEW_CHARACTER(2)); + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(types=R_igraph_vector_bool_to_SEXP(&c_types)); + igraph_vector_bool_destroy(&c_types); + IGRAPH_FINALLY_CLEAN(1); + SET_VECTOR_ELT(r_result, 0, graph); + SET_VECTOR_ELT(r_result, 1, types); + SET_STRING_ELT(r_names, 0, Rf_mkChar("graph")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("types")); + SET_NAMES(r_result, r_names); + UNPROTECT(3); + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_bipartite_iea_game / +/-------------------------------------------*/ +SEXP R_igraph_bipartite_iea_game(SEXP n1, SEXP n2, SEXP m, SEXP directed, SEXP mode) { /* Declarations */ igraph_t c_graph; igraph_vector_bool_t c_types; @@ -5992,7 +6276,9 @@ SEXP R_igraph_bipartite_game_gnm(SEXP n1, SEXP n2, SEXP m, SEXP directed, SEXP m c_directed = LOGICAL(directed)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_bipartite_game_gnm(&c_graph, &c_types, c_n1, c_n2, c_m, c_directed, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_bipartite_iea_game(&c_graph, &c_types, c_n1, c_n2, c_m, c_directed, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -6038,7 +6324,9 @@ SEXP R_igraph_get_laplacian(SEXP graph, SEXP mode, SEXP normalization, SEXP weig R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_laplacian(&c_graph, &c_res, c_mode, c_normalization, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_laplacian(&c_graph, &c_res, c_mode, c_normalization, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -6073,7 +6361,9 @@ SEXP R_igraph_get_laplacian_sparse(SEXP graph, SEXP mode, SEXP normalization, SE R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_laplacian_sparse(&c_graph, &c_sparseres, c_mode, c_normalization, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_laplacian_sparse(&c_graph, &c_sparseres, c_mode, c_normalization, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(sparseres=R_igraph_sparsemat_to_SEXP(&c_sparseres)); @@ -6109,7 +6399,9 @@ SEXP R_igraph_connected_components(SEXP graph, SEXP mode) { c_no=0; c_mode = (igraph_connectedness_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_connected_components(&c_graph, &c_membership, &c_csize, &c_no, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -6150,7 +6442,9 @@ SEXP R_igraph_is_connected(SEXP graph, SEXP mode) { R_SEXP_to_igraph(graph, &c_graph); c_mode = (igraph_connectedness_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_connected(&c_graph, &c_res, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -6176,7 +6470,9 @@ SEXP R_igraph_articulation_points(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_articulation_points(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_to_SEXPp1(&c_res)); @@ -6209,16 +6505,24 @@ SEXP R_igraph_biconnected_components(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); c_no=0; - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_tree_edges, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_tree_edges); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_component_edges, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_component_edges); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_components, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_components); + if (0 != igraph_vector_int_list_init(&c_tree_edges, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_tree_edges); + if (0 != igraph_vector_int_list_init(&c_component_edges, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_component_edges); + if (0 != igraph_vector_int_list_init(&c_components, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_components); IGRAPH_R_CHECK(igraph_vector_int_init(&c_articulation_points, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_articulation_points); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_biconnected_components(&c_graph, &c_no, &c_tree_edges, &c_component_edges, &c_components, &c_articulation_points)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(5)); @@ -6269,7 +6573,9 @@ SEXP R_igraph_bridges(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_bridges(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_to_SEXPp1(&c_res)); @@ -6294,7 +6600,9 @@ SEXP R_igraph_is_biconnected(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_biconnected(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -6322,7 +6630,9 @@ SEXP R_igraph_count_reachable(SEXP graph, SEXP mode) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_counts); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_count_reachable(&c_graph, &c_counts, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(counts=R_igraph_vector_int_to_SEXP(&c_counts)); @@ -6361,7 +6671,9 @@ SEXP R_igraph_bond_percolation(SEXP graph, SEXP edge_order) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edge_order); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_bond_percolation(&c_graph, &c_giant_size, &c_vetex_count, (Rf_isNull(edge_order) ? 0 : &c_edge_order))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_bond_percolation(&c_graph, &c_giant_size, &c_vetex_count, (Rf_isNull(edge_order) ? NULL : &c_edge_order))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -6412,7 +6724,9 @@ SEXP R_igraph_site_percolation(SEXP graph, SEXP vertex_order) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_order); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_site_percolation(&c_graph, &c_giant_size, &c_edge_count, (Rf_isNull(vertex_order) ? 0 : &c_vertex_order))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_site_percolation(&c_graph, &c_giant_size, &c_edge_count, (Rf_isNull(vertex_order) ? NULL : &c_vertex_order))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -6456,7 +6770,9 @@ SEXP R_igraph_edgelist_percolation(SEXP edges) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_vertex_count, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_count); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_edgelist_percolation(&c_edges, &c_giant_size, &c_vertex_count)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -6499,7 +6815,9 @@ SEXP R_igraph_is_clique(SEXP graph, SEXP candidate, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_clique(&c_graph, c_candidate, c_directed, &c_res)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_candidate_data); @@ -6526,14 +6844,18 @@ SEXP R_igraph_cliques(SEXP graph, SEXP min_size, SEXP max_size) { SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_res, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_res); + if (0 != igraph_vector_int_list_init(&c_res, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_res); IGRAPH_R_CHECK_INT(min_size); c_min_size = (igraph_integer_t) REAL(min_size)[0]; IGRAPH_R_CHECK_INT(max_size); c_max_size = (igraph_integer_t) REAL(max_size)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_cliques(&c_graph, &c_res, c_min_size, c_max_size)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_list_to_SEXPp1(&c_res)); @@ -6566,7 +6888,9 @@ SEXP R_igraph_clique_size_hist(SEXP graph, SEXP min_size, SEXP max_size) { IGRAPH_R_CHECK_INT(max_size); c_max_size = (igraph_integer_t) REAL(max_size)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_clique_size_hist(&c_graph, &c_hist, c_min_size, c_max_size)); + PutRNGstate(); /* Convert output */ PROTECT(hist=R_igraph_vector_to_SEXP(&c_hist)); @@ -6590,10 +6914,14 @@ SEXP R_igraph_largest_cliques(SEXP graph) { SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_res, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_res); + if (0 != igraph_vector_int_list_init(&c_res, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_largest_cliques(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_list_to_SEXPp1(&c_res)); @@ -6626,7 +6954,9 @@ SEXP R_igraph_maximal_cliques_hist(SEXP graph, SEXP min_size, SEXP max_size) { IGRAPH_R_CHECK_INT(max_size); c_max_size = (igraph_integer_t) REAL(max_size)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_maximal_cliques_hist(&c_graph, &c_hist, c_min_size, c_max_size)); + PutRNGstate(); /* Convert output */ PROTECT(hist=R_igraph_vector_to_SEXP(&c_hist)); @@ -6652,7 +6982,9 @@ SEXP R_igraph_clique_number(SEXP graph) { R_SEXP_to_igraph(graph, &c_graph); c_no=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_clique_number(&c_graph, &c_no)); + PutRNGstate(); /* Convert output */ PROTECT(no=NEW_NUMERIC(1)); @@ -6682,8 +7014,10 @@ SEXP R_igraph_weighted_cliques(SEXP graph, SEXP vertex_weights, SEXP min_weight, if (!Rf_isNull(vertex_weights)) { R_SEXP_to_vector(vertex_weights, &c_vertex_weights); } - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_res, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_res); + if (0 != igraph_vector_int_list_init(&c_res, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_res); IGRAPH_R_CHECK_REAL(min_weight); c_min_weight = REAL(min_weight)[0]; IGRAPH_R_CHECK_REAL(max_weight); @@ -6691,7 +7025,9 @@ SEXP R_igraph_weighted_cliques(SEXP graph, SEXP vertex_weights, SEXP min_weight, IGRAPH_R_CHECK_BOOL(maximal); c_maximal = LOGICAL(maximal)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_weighted_cliques(&c_graph, (Rf_isNull(vertex_weights) ? 0 : &c_vertex_weights), &c_res, c_min_weight, c_max_weight, c_maximal)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_weighted_cliques(&c_graph, (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), &c_res, c_min_weight, c_max_weight, c_maximal)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_list_to_SEXPp1(&c_res)); @@ -6719,10 +7055,14 @@ SEXP R_igraph_largest_weighted_cliques(SEXP graph, SEXP vertex_weights) { if (!Rf_isNull(vertex_weights)) { R_SEXP_to_vector(vertex_weights, &c_vertex_weights); } - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_res, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_res); + if (0 != igraph_vector_int_list_init(&c_res, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_res); /* Call igraph */ - IGRAPH_R_CHECK(igraph_largest_weighted_cliques(&c_graph, (Rf_isNull(vertex_weights) ? 0 : &c_vertex_weights), &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_largest_weighted_cliques(&c_graph, (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_list_to_SEXPp1(&c_res)); @@ -6751,7 +7091,9 @@ SEXP R_igraph_weighted_clique_number(SEXP graph, SEXP vertex_weights) { R_SEXP_to_vector(vertex_weights, &c_vertex_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_weighted_clique_number(&c_graph, (Rf_isNull(vertex_weights) ? 0 : &c_vertex_weights), &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_weighted_clique_number(&c_graph, (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -6778,7 +7120,9 @@ SEXP R_igraph_is_independent_vertex_set(SEXP graph, SEXP candidate) { igraph_vector_int_t c_candidate_data; R_SEXP_to_igraph_vs(candidate, &c_graph, &c_candidate, &c_candidate_data); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_independent_vertex_set(&c_graph, c_candidate, &c_res)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_candidate_data); @@ -6806,7 +7150,9 @@ SEXP R_igraph_layout_random(SEXP graph) { IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_random(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -6836,7 +7182,9 @@ SEXP R_igraph_layout_circle(SEXP graph, SEXP order) { igraph_vector_int_t c_order_data; R_SEXP_to_igraph_vs(order, &c_graph, &c_order, &c_order_data); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_circle(&c_graph, &c_res, c_order)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -6875,7 +7223,9 @@ SEXP R_igraph_layout_star(SEXP graph, SEXP center, SEXP order) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_order); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_layout_star(&c_graph, &c_res, c_center, (Rf_isNull(order) ? 0 : &c_order))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_layout_star(&c_graph, &c_res, c_center, (Rf_isNull(order) ? NULL : &c_order))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -6907,7 +7257,9 @@ SEXP R_igraph_layout_grid(SEXP graph, SEXP width) { IGRAPH_R_CHECK_INT(width); c_width = (igraph_integer_t) REAL(width)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_grid(&c_graph, &c_res, c_width)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -6940,7 +7292,9 @@ SEXP R_igraph_layout_grid_3d(SEXP graph, SEXP width, SEXP height) { IGRAPH_R_CHECK_INT(height); c_height = (igraph_integer_t) REAL(height)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_grid_3d(&c_graph, &c_res, c_width, c_height)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -6971,7 +7325,9 @@ SEXP R_igraph_roots_for_tree_layout(SEXP graph, SEXP mode, SEXP heuristic) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_roots); c_heuristic = (igraph_root_choice_t) Rf_asInteger(heuristic); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_roots_for_tree_layout(&c_graph, c_mode, &c_roots, c_heuristic)); + PutRNGstate(); /* Convert output */ PROTECT(roots=R_igraph_vector_int_to_SEXPp1(&c_roots)); @@ -6998,7 +7354,9 @@ SEXP R_igraph_layout_random_3d(SEXP graph) { IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_random_3d(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7025,7 +7383,9 @@ SEXP R_igraph_layout_sphere(SEXP graph) { IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_sphere(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7060,7 +7420,9 @@ SEXP R_igraph_layout_drl(SEXP graph, SEXP res, SEXP use_seed, SEXP options, SEXP R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_layout_drl(&c_graph, &c_res, c_use_seed, &c_options, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_layout_drl(&c_graph, &c_res, c_use_seed, &c_options, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7095,7 +7457,9 @@ SEXP R_igraph_layout_drl_3d(SEXP graph, SEXP res, SEXP use_seed, SEXP options, S R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_layout_drl_3d(&c_graph, &c_res, c_use_seed, &c_options, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_layout_drl_3d(&c_graph, &c_res, c_use_seed, &c_options, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7149,7 +7513,9 @@ SEXP R_igraph_layout_sugiyama(SEXP graph, SEXP layers, SEXP hgap, SEXP vgap, SEX R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_layout_sugiyama(&c_graph, &c_res, &c_extd_graph, &c_extd_to_orig_eids, (Rf_isNull(layers) ? 0 : &c_layers), c_hgap, c_vgap, c_maxiter, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_layout_sugiyama(&c_graph, &c_res, &c_extd_graph, &c_extd_to_orig_eids, (Rf_isNull(layers) ? NULL : &c_layers), c_hgap, c_vgap, c_maxiter, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -7201,7 +7567,9 @@ SEXP R_igraph_layout_mds(SEXP graph, SEXP dist, SEXP dim) { IGRAPH_R_CHECK_INT(dim); c_dim = (igraph_integer_t) REAL(dim)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_layout_mds(&c_graph, &c_res, (Rf_isNull(dist) ? 0 : &c_dist), c_dim)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_layout_mds(&c_graph, &c_res, (Rf_isNull(dist) ? NULL : &c_dist), c_dim)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7239,7 +7607,9 @@ SEXP R_igraph_layout_bipartite(SEXP graph, SEXP types, SEXP hgap, SEXP vgap, SEX IGRAPH_R_CHECK_INT(maxiter); c_maxiter = (igraph_integer_t) REAL(maxiter)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_bipartite(&c_graph, &c_types, &c_res, c_hgap, c_vgap, c_maxiter)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7280,7 +7650,9 @@ SEXP R_igraph_layout_gem(SEXP graph, SEXP res, SEXP use_seed, SEXP maxiter, SEXP IGRAPH_R_CHECK_REAL(temp_init); c_temp_init = REAL(temp_init)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_gem(&c_graph, &c_res, c_use_seed, c_maxiter, c_temp_max, c_temp_min, c_temp_init)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7333,7 +7705,9 @@ SEXP R_igraph_layout_davidson_harel(SEXP graph, SEXP res, SEXP use_seed, SEXP ma IGRAPH_R_CHECK_REAL(weight_node_edge_dist); c_weight_node_edge_dist = REAL(weight_node_edge_dist)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_davidson_harel(&c_graph, &c_res, c_use_seed, c_maxiter, c_fineiter, c_cool_fact, c_weight_node_dist, c_weight_border, c_weight_edge_lengths, c_weight_edge_crossings, c_weight_node_edge_dist)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7375,7 +7749,9 @@ SEXP R_igraph_layout_umap(SEXP graph, SEXP res, SEXP use_seed, SEXP distances, S IGRAPH_R_CHECK_BOOL(distances_are_weights); c_distances_are_weights = LOGICAL(distances_are_weights)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_layout_umap(&c_graph, &c_res, c_use_seed, (Rf_isNull(distances) ? 0 : &c_distances), c_min_dist, c_epochs, c_distances_are_weights)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_layout_umap(&c_graph, &c_res, c_use_seed, (Rf_isNull(distances) ? NULL : &c_distances), c_min_dist, c_epochs, c_distances_are_weights)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7417,7 +7793,9 @@ SEXP R_igraph_layout_umap_3d(SEXP graph, SEXP res, SEXP use_seed, SEXP distances IGRAPH_R_CHECK_BOOL(distances_are_weights); c_distances_are_weights = LOGICAL(distances_are_weights)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_layout_umap_3d(&c_graph, &c_res, c_use_seed, (Rf_isNull(distances) ? 0 : &c_distances), c_min_dist, c_epochs, c_distances_are_weights)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_layout_umap_3d(&c_graph, &c_res, c_use_seed, (Rf_isNull(distances) ? NULL : &c_distances), c_min_dist, c_epochs, c_distances_are_weights)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7445,7 +7823,9 @@ SEXP R_igraph_layout_umap_compute_weights(SEXP graph, SEXP distances, SEXP weigh IGRAPH_R_CHECK(R_SEXP_to_vector_copy(weights, &c_weights)); IGRAPH_FINALLY(igraph_vector_destroy, &c_weights); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_umap_compute_weights(&c_graph, &c_distances, &c_weights)); + PutRNGstate(); /* Convert output */ PROTECT(weights=R_igraph_vector_to_SEXP(&c_weights)); @@ -7471,7 +7851,9 @@ SEXP R_igraph_layout_align(SEXP graph, SEXP layout) { IGRAPH_R_CHECK(R_SEXP_to_igraph_matrix_copy(layout, &c_layout)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_layout); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_layout_align(&c_graph, &c_layout)); + PutRNGstate(); /* Convert output */ PROTECT(layout=R_igraph_matrix_to_SEXP(&c_layout)); @@ -7486,11 +7868,12 @@ SEXP R_igraph_layout_align(SEXP graph, SEXP layout) { /*-------------------------------------------/ / 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; @@ -7500,20 +7883,26 @@ SEXP R_igraph_similarity_dice(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { R_SEXP_to_igraph(graph, &c_graph); IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); 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)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_similarity_dice(&c_graph, &c_res, c_vit_from, c_vit_to, c_mode, c_loops)); + PutRNGstate(); /* 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); @@ -7543,7 +7932,9 @@ SEXP R_igraph_similarity_dice_es(SEXP graph, SEXP es, SEXP mode, SEXP loops) { IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_similarity_dice_es(&c_graph, &c_res, c_es, c_mode, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -7580,7 +7971,9 @@ SEXP R_igraph_similarity_dice_pairs(SEXP graph, SEXP pairs, SEXP mode, SEXP loop IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_similarity_dice_pairs(&c_graph, &c_res, &c_pairs, c_mode, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -7614,7 +8007,9 @@ SEXP R_igraph_similarity_inverse_log_weighted(SEXP graph, SEXP vids, SEXP mode) R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_similarity_inverse_log_weighted(&c_graph, &c_res, c_vids, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -7631,11 +8026,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; @@ -7645,20 +8041,26 @@ SEXP R_igraph_similarity_jaccard(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { R_SEXP_to_igraph(graph, &c_graph); IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); 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)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_similarity_jaccard(&c_graph, &c_res, c_vit_from, c_vit_to, c_mode, c_loops)); + PutRNGstate(); /* 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); @@ -7688,7 +8090,9 @@ SEXP R_igraph_similarity_jaccard_es(SEXP graph, SEXP es, SEXP mode, SEXP loops) IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_similarity_jaccard_es(&c_graph, &c_res, c_es, c_mode, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -7725,7 +8129,9 @@ SEXP R_igraph_similarity_jaccard_pairs(SEXP graph, SEXP pairs, SEXP mode, SEXP l IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_similarity_jaccard_pairs(&c_graph, &c_res, &c_pairs, c_mode, c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -7758,7 +8164,9 @@ SEXP R_igraph_compare_communities(SEXP comm1, SEXP comm2, SEXP method) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_comm2); c_method = (igraph_community_comparison_t) Rf_asInteger(method); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_compare_communities(&c_comm1, &c_comm2, &c_res, c_method)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_comm1); @@ -7799,7 +8207,9 @@ SEXP R_igraph_modularity(SEXP graph, SEXP membership, SEXP weights, SEXP resolut IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_modularity(&c_graph, &c_membership, (Rf_isNull(weights) ? 0 : &c_weights), c_resolution, c_directed, &c_modularity)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_modularity(&c_graph, &c_membership, (Rf_isNull(weights) ? NULL : &c_weights), c_resolution, c_directed, &c_modularity)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_membership); @@ -7837,7 +8247,9 @@ SEXP R_igraph_modularity_matrix(SEXP graph, SEXP weights, SEXP resolution, SEXP IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_modularity_matrix(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), c_resolution, &c_modmat, c_directed)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_modularity_matrix(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), c_resolution, &c_modmat, c_directed)); + PutRNGstate(); /* Convert output */ PROTECT(modmat=R_igraph_matrix_to_SEXP(&c_modmat)); @@ -7867,7 +8279,9 @@ SEXP R_igraph_community_fluid_communities(SEXP graph, SEXP no_of_communities) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_membership, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_community_fluid_communities(&c_graph, c_no_of_communities, &c_membership)); + PutRNGstate(); /* Convert output */ PROTECT(membership=R_igraph_vector_int_to_SEXP(&c_membership)); @@ -7882,7 +8296,7 @@ SEXP R_igraph_community_fluid_communities(SEXP graph, SEXP no_of_communities) { /*-------------------------------------------/ / igraph_community_label_propagation / /-------------------------------------------*/ -SEXP R_igraph_community_label_propagation(SEXP graph, SEXP mode, SEXP weights, SEXP initial, SEXP fixed) { +SEXP R_igraph_community_label_propagation(SEXP graph, SEXP mode, SEXP weights, SEXP initial, SEXP fixed, SEXP lpa_variant) { /* Declarations */ igraph_t c_graph; igraph_vector_int_t c_membership; @@ -7890,6 +8304,7 @@ SEXP R_igraph_community_label_propagation(SEXP graph, SEXP mode, SEXP weights, S igraph_vector_t c_weights; igraph_vector_int_t c_initial; igraph_vector_bool_t c_fixed; + igraph_lpa_variant_t c_lpa_variant; SEXP membership; SEXP r_result; @@ -7911,8 +8326,11 @@ SEXP R_igraph_community_label_propagation(SEXP graph, SEXP mode, SEXP weights, S if (!Rf_isNull(fixed)) { R_SEXP_to_vector_bool(fixed, &c_fixed); } + c_lpa_variant = (igraph_lpa_variant_t) Rf_asInteger(lpa_variant); /* Call igraph */ - IGRAPH_R_CHECK(igraph_community_label_propagation(&c_graph, &c_membership, c_mode, (Rf_isNull(weights) ? 0 : &c_weights), (Rf_isNull(initial) ? 0 : &c_initial), (Rf_isNull(fixed) ? 0 : &c_fixed))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_community_label_propagation(&c_graph, &c_membership, c_mode, (Rf_isNull(weights) ? NULL : &c_weights), (Rf_isNull(initial) ? NULL : &c_initial), (Rf_isNull(fixed) ? NULL : &c_fixed), c_lpa_variant)); + PutRNGstate(); /* Convert output */ PROTECT(membership=R_igraph_vector_int_to_SEXP(&c_membership)); @@ -7956,7 +8374,9 @@ SEXP R_igraph_community_multilevel(SEXP graph, SEXP weights, SEXP resolution) { IGRAPH_R_CHECK(igraph_vector_init(&c_modularity, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_modularity); /* Call igraph */ - IGRAPH_R_CHECK(igraph_community_multilevel(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), c_resolution, &c_membership, &c_memberships, &c_modularity)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_community_multilevel(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), c_resolution, &c_membership, &c_memberships, &c_modularity)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -7986,25 +8406,30 @@ SEXP R_igraph_community_multilevel(SEXP graph, SEXP weights, SEXP resolution) { /*-------------------------------------------/ / igraph_community_optimal_modularity / /-------------------------------------------*/ -SEXP R_igraph_community_optimal_modularity(SEXP graph, SEXP weights) { +SEXP R_igraph_community_optimal_modularity(SEXP graph, SEXP weights, SEXP resolution) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; + igraph_real_t c_resolution; igraph_real_t c_modularity; igraph_vector_int_t c_membership; - igraph_vector_t c_weights; SEXP modularity; SEXP membership; SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_init(&c_membership, 0)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } + IGRAPH_R_CHECK_REAL(resolution); + c_resolution = REAL(resolution)[0]; + IGRAPH_R_CHECK(igraph_vector_int_init(&c_membership, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); /* Call igraph */ - IGRAPH_R_CHECK(igraph_community_optimal_modularity(&c_graph, &c_modularity, &c_membership, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_community_optimal_modularity(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), c_resolution, &c_modularity, &c_membership)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -8028,11 +8453,12 @@ SEXP R_igraph_community_optimal_modularity(SEXP graph, SEXP weights) { /*-------------------------------------------/ / igraph_community_leiden / /-------------------------------------------*/ -SEXP R_igraph_community_leiden(SEXP graph, SEXP weights, SEXP vertex_weights, SEXP resolution, SEXP beta, SEXP start, SEXP n_iterations, SEXP membership) { +SEXP R_igraph_community_leiden(SEXP graph, SEXP weights, SEXP vertex_out_weights, SEXP vertex_in_weights, SEXP resolution, SEXP beta, SEXP start, SEXP n_iterations, SEXP membership) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_weights; - igraph_vector_t c_vertex_weights; + igraph_vector_t c_vertex_out_weights; + igraph_vector_t c_vertex_in_weights; igraph_real_t c_resolution; igraph_real_t c_beta; igraph_bool_t c_start; @@ -8049,8 +8475,11 @@ SEXP R_igraph_community_leiden(SEXP graph, SEXP weights, SEXP vertex_weights, SE if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } - if (!Rf_isNull(vertex_weights)) { - R_SEXP_to_vector(vertex_weights, &c_vertex_weights); + if (!Rf_isNull(vertex_out_weights)) { + R_SEXP_to_vector(vertex_out_weights, &c_vertex_out_weights); + } + if (!Rf_isNull(vertex_in_weights)) { + R_SEXP_to_vector(vertex_in_weights, &c_vertex_in_weights); } IGRAPH_R_CHECK_REAL(resolution); c_resolution = REAL(resolution)[0]; @@ -8069,7 +8498,9 @@ SEXP R_igraph_community_leiden(SEXP graph, SEXP weights, SEXP vertex_weights, SE } c_nb_clusters=0; /* Call igraph */ - IGRAPH_R_CHECK(igraph_community_leiden(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), (Rf_isNull(vertex_weights) ? 0 : &c_vertex_weights), c_resolution, c_beta, c_start, c_n_iterations, &c_membership, &c_nb_clusters, &c_quality)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_community_leiden(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), (Rf_isNull(vertex_out_weights) ? NULL : &c_vertex_out_weights), (Rf_isNull(vertex_in_weights) ? NULL : &c_vertex_in_weights), c_resolution, c_beta, c_start, c_n_iterations, &c_membership, &c_nb_clusters, &c_quality)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -8115,7 +8546,9 @@ SEXP R_igraph_split_join_distance(SEXP comm1, SEXP comm2) { c_distance12=0; c_distance21=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_split_join_distance(&c_comm1, &c_comm2, &c_distance12, &c_distance21)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -8142,11 +8575,11 @@ SEXP R_igraph_split_join_distance(SEXP comm1, SEXP comm2) { /*-------------------------------------------/ / igraph_community_infomap / /-------------------------------------------*/ -SEXP R_igraph_community_infomap(SEXP graph, SEXP e_weights, SEXP v_weights, SEXP nb_trials) { +SEXP R_igraph_community_infomap(SEXP graph, SEXP edge_weights, SEXP vertex_weights, SEXP nb_trials) { /* Declarations */ igraph_t c_graph; - igraph_vector_t c_e_weights; - igraph_vector_t c_v_weights; + igraph_vector_t c_edge_weights; + igraph_vector_t c_vertex_weights; igraph_integer_t c_nb_trials; igraph_vector_int_t c_membership; igraph_real_t c_codelength; @@ -8156,18 +8589,20 @@ SEXP R_igraph_community_infomap(SEXP graph, SEXP e_weights, SEXP v_weights, SEXP SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - if (!Rf_isNull(e_weights)) { - R_SEXP_to_vector(e_weights, &c_e_weights); + if (!Rf_isNull(edge_weights)) { + R_SEXP_to_vector(edge_weights, &c_edge_weights); } - if (!Rf_isNull(v_weights)) { - R_SEXP_to_vector(v_weights, &c_v_weights); + if (!Rf_isNull(vertex_weights)) { + R_SEXP_to_vector(vertex_weights, &c_vertex_weights); } IGRAPH_R_CHECK_INT(nb_trials); c_nb_trials = (igraph_integer_t) REAL(nb_trials)[0]; IGRAPH_R_CHECK(igraph_vector_int_init(&c_membership, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); /* Call igraph */ - IGRAPH_R_CHECK(igraph_community_infomap(&c_graph, (Rf_isNull(e_weights) ? 0 : &c_e_weights), (Rf_isNull(v_weights) ? 0 : &c_v_weights), c_nb_trials, &c_membership, &c_codelength)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_community_infomap(&c_graph, (Rf_isNull(edge_weights) ? NULL : &c_edge_weights), (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), c_nb_trials, &c_membership, &c_codelength)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -8208,7 +8643,9 @@ SEXP R_igraph_hrg_fit(SEXP graph, SEXP hrg, SEXP start, SEXP steps) { IGRAPH_R_CHECK_INT(steps); c_steps = (igraph_integer_t) REAL(steps)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_fit(&c_graph, &c_hrg, c_start, c_steps)); + PutRNGstate(); /* Convert output */ PROTECT(hrg=R_igraph_hrg_to_SEXP(&c_hrg)); @@ -8234,7 +8671,9 @@ SEXP R_igraph_hrg_sample(SEXP hrg) { IGRAPH_R_CHECK(R_SEXP_to_hrg_copy(hrg, &c_hrg)); IGRAPH_FINALLY(igraph_hrg_destroy, &c_hrg); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_sample(&c_hrg, &c_sample)); + PutRNGstate(); /* Convert output */ igraph_hrg_destroy(&c_hrg); @@ -8268,7 +8707,9 @@ SEXP R_igraph_hrg_sample_many(SEXP hrg, SEXP num_samples) { IGRAPH_R_CHECK_INT(num_samples); c_num_samples = (igraph_integer_t) REAL(num_samples)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_sample_many(&c_hrg, &c_samples, c_num_samples)); + PutRNGstate(); /* Convert output */ igraph_hrg_destroy(&c_hrg); @@ -8296,7 +8737,9 @@ SEXP R_igraph_hrg_game(SEXP hrg) { IGRAPH_R_CHECK(R_SEXP_to_hrg_copy(hrg, &c_hrg)); IGRAPH_FINALLY(igraph_hrg_destroy, &c_hrg); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_game(&c_graph, &c_hrg)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -8339,7 +8782,9 @@ SEXP R_igraph_hrg_consensus(SEXP graph, SEXP hrg, SEXP start, SEXP num_samples) IGRAPH_R_CHECK_INT(num_samples); c_num_samples = (igraph_integer_t) REAL(num_samples)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_consensus(&c_graph, &c_parents, &c_weights, &c_hrg, c_start, c_num_samples)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -8397,7 +8842,9 @@ SEXP R_igraph_hrg_predict(SEXP graph, SEXP hrg, SEXP start, SEXP num_samples, SE IGRAPH_R_CHECK_INT(num_bins); c_num_bins = (igraph_integer_t) REAL(num_bins)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_predict(&c_graph, &c_edges, &c_prob, &c_hrg, c_start, c_num_samples, c_num_bins)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -8441,7 +8888,9 @@ SEXP R_igraph_hrg_create(SEXP graph, SEXP prob) { R_SEXP_to_igraph(graph, &c_graph); R_SEXP_to_vector(prob, &c_prob); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_create(&c_hrg, &c_graph, &c_prob)); + PutRNGstate(); /* Convert output */ PROTECT(hrg=R_igraph_hrg_to_SEXP(&c_hrg)); @@ -8468,7 +8917,9 @@ SEXP R_igraph_hrg_resize(SEXP hrg, SEXP newsize) { IGRAPH_R_CHECK_INT(newsize); c_newsize = (igraph_integer_t) REAL(newsize)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_hrg_resize(&c_hrg, c_newsize)); + PutRNGstate(); /* Convert output */ PROTECT(hrg=R_igraph_hrg_to_SEXP(&c_hrg)); @@ -8492,7 +8943,9 @@ SEXP R_igraph_hrg_size(SEXP hrg) { IGRAPH_R_CHECK(R_SEXP_to_hrg_copy(hrg, &c_hrg)); IGRAPH_FINALLY(igraph_hrg_destroy, &c_hrg); /* Call igraph */ + GetRNGstate(); c_result=igraph_hrg_size(&c_hrg); + PutRNGstate(); /* Convert output */ igraph_hrg_destroy(&c_hrg); @@ -8522,7 +8975,9 @@ SEXP R_igraph_from_hrg_dendrogram(SEXP hrg) { IGRAPH_R_CHECK(igraph_vector_init(&c_prob, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_prob); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_from_hrg_dendrogram(&c_graph, &c_hrg, &c_prob)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -8570,7 +9025,9 @@ SEXP R_igraph_get_adjacency_sparse(SEXP graph, SEXP type, SEXP weights, SEXP loo } c_loops = (igraph_loops_t) Rf_asInteger(loops); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_adjacency_sparse(&c_graph, &c_sparsemat, c_type, (Rf_isNull(weights) ? 0 : &c_weights), c_loops)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_adjacency_sparse(&c_graph, &c_sparsemat, c_type, (Rf_isNull(weights) ? NULL : &c_weights), c_loops)); + PutRNGstate(); /* Convert output */ PROTECT(sparsemat=R_igraph_sparsemat_to_SEXP(&c_sparsemat)); @@ -8604,7 +9061,9 @@ SEXP R_igraph_get_stochastic(SEXP graph, SEXP column_wise, SEXP weights) { R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_stochastic(&c_graph, &c_res, c_column_wise, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_stochastic(&c_graph, &c_res, c_column_wise, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -8638,7 +9097,9 @@ SEXP R_igraph_get_stochastic_sparse(SEXP graph, SEXP column_wise, SEXP weights) R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_stochastic_sparse(&c_graph, &c_sparsemat, c_column_wise, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_stochastic_sparse(&c_graph, &c_sparsemat, c_column_wise, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(sparsemat=R_igraph_sparsemat_to_SEXP(&c_sparsemat)); @@ -8664,7 +9125,9 @@ SEXP R_igraph_to_directed(SEXP graph, SEXP mode) { IGRAPH_FINALLY(igraph_destroy, &c_graph); c_mode = (igraph_to_directed_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_to_directed(&c_graph, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -8693,7 +9156,9 @@ SEXP R_igraph_to_undirected(SEXP graph, SEXP mode, SEXP edge_attr_comb) { R_SEXP_to_attr_comb(edge_attr_comb, &c_edge_attr_comb); IGRAPH_FINALLY(igraph_attribute_combination_destroy, &c_edge_attr_comb); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_to_undirected(&c_graph, c_mode, &c_edge_attr_comb)); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -8729,7 +9194,9 @@ SEXP R_igraph_motifs_randesu(SEXP graph, SEXP size, SEXP cut_prob) { R_SEXP_to_vector(cut_prob, &c_cut_prob); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_motifs_randesu(&c_graph, &c_hist, c_size, (Rf_isNull(cut_prob) ? 0 : &c_cut_prob))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_motifs_randesu(&c_graph, &c_hist, c_size, (Rf_isNull(cut_prob) ? NULL : &c_cut_prob))); + PutRNGstate(); /* Convert output */ PROTECT(hist=R_igraph_vector_to_SEXP(&c_hist)); @@ -8747,7 +9214,7 @@ SEXP R_igraph_motifs_randesu(SEXP graph, SEXP size, SEXP cut_prob) { SEXP R_igraph_motifs_randesu_estimate(SEXP graph, SEXP size, SEXP cut_prob, SEXP sample_size, SEXP sample) { /* Declarations */ igraph_t c_graph; - igraph_integer_t c_est; + igraph_real_t c_est; igraph_integer_t c_size; igraph_vector_t c_cut_prob; igraph_integer_t c_sample_size; @@ -8757,7 +9224,6 @@ SEXP R_igraph_motifs_randesu_estimate(SEXP graph, SEXP size, SEXP cut_prob, SEXP SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - c_est=0; IGRAPH_R_CHECK_INT(size); c_size = (igraph_integer_t) REAL(size)[0]; if (!Rf_isNull(cut_prob)) { @@ -8773,11 +9239,13 @@ SEXP R_igraph_motifs_randesu_estimate(SEXP graph, SEXP size, SEXP cut_prob, SEXP IGRAPH_FINALLY(igraph_vector_int_destroy, &c_sample); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_motifs_randesu_estimate(&c_graph, &c_est, c_size, (Rf_isNull(cut_prob) ? 0 : &c_cut_prob), c_sample_size, (Rf_isNull(sample) ? 0 : &c_sample))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_motifs_randesu_estimate(&c_graph, &c_est, c_size, (Rf_isNull(cut_prob) ? NULL : &c_cut_prob), c_sample_size, (Rf_isNull(sample) ? NULL : &c_sample))); + PutRNGstate(); /* Convert output */ PROTECT(est=NEW_NUMERIC(1)); - REAL(est)[0]=(double) c_est; + REAL(est)[0]=c_est; igraph_vector_int_destroy(&c_sample); IGRAPH_FINALLY_CLEAN(1); r_result = est; @@ -8792,7 +9260,7 @@ SEXP R_igraph_motifs_randesu_estimate(SEXP graph, SEXP size, SEXP cut_prob, SEXP SEXP R_igraph_motifs_randesu_no(SEXP graph, SEXP size, SEXP cut_prob) { /* Declarations */ igraph_t c_graph; - igraph_integer_t c_no; + igraph_real_t c_no; igraph_integer_t c_size; igraph_vector_t c_cut_prob; SEXP no; @@ -8800,18 +9268,19 @@ SEXP R_igraph_motifs_randesu_no(SEXP graph, SEXP size, SEXP cut_prob) { SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - c_no=0; IGRAPH_R_CHECK_INT(size); c_size = (igraph_integer_t) REAL(size)[0]; if (!Rf_isNull(cut_prob)) { R_SEXP_to_vector(cut_prob, &c_cut_prob); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_motifs_randesu_no(&c_graph, &c_no, c_size, (Rf_isNull(cut_prob) ? 0 : &c_cut_prob))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_motifs_randesu_no(&c_graph, &c_no, c_size, (Rf_isNull(cut_prob) ? NULL : &c_cut_prob))); + PutRNGstate(); /* Convert output */ PROTECT(no=NEW_NUMERIC(1)); - REAL(no)[0]=(double) c_no; + REAL(no)[0]=c_no; r_result = no; UNPROTECT(1); @@ -8835,7 +9304,9 @@ SEXP R_igraph_dyad_census(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_dyad_census(&c_graph, &c_mut, &c_asym, &c_null)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -8874,7 +9345,9 @@ SEXP R_igraph_triad_census(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_triad_census(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -8904,7 +9377,9 @@ SEXP R_igraph_count_adjacent_triangles(SEXP graph, SEXP vids) { igraph_vector_int_t c_vids_data; R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_count_adjacent_triangles(&c_graph, &c_res, c_vids)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -8931,7 +9406,9 @@ SEXP R_igraph_count_triangles(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_count_triangles(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_NUMERIC(1)); @@ -8963,7 +9440,9 @@ SEXP R_igraph_local_scan_0(SEXP graph, SEXP weights, SEXP mode) { } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_0(&c_graph, &c_res, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_0(&c_graph, &c_res, (Rf_isNull(weights) ? NULL : &c_weights), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -8998,7 +9477,9 @@ SEXP R_igraph_local_scan_0_them(SEXP us, SEXP them, SEXP weights_them, SEXP mode } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_0_them(&c_us, &c_them, &c_res, (Rf_isNull(weights_them) ? 0 : &c_weights_them), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_0_them(&c_us, &c_them, &c_res, (Rf_isNull(weights_them) ? NULL : &c_weights_them), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -9031,7 +9512,9 @@ SEXP R_igraph_local_scan_1_ecount(SEXP graph, SEXP weights, SEXP mode) { } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_1_ecount(&c_graph, &c_res, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_1_ecount(&c_graph, &c_res, (Rf_isNull(weights) ? NULL : &c_weights), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -9066,7 +9549,9 @@ SEXP R_igraph_local_scan_1_ecount_them(SEXP us, SEXP them, SEXP weights_them, SE } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_1_ecount_them(&c_us, &c_them, &c_res, (Rf_isNull(weights_them) ? 0 : &c_weights_them), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_1_ecount_them(&c_us, &c_them, &c_res, (Rf_isNull(weights_them) ? NULL : &c_weights_them), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -9102,7 +9587,9 @@ SEXP R_igraph_local_scan_k_ecount(SEXP graph, SEXP k, SEXP weights, SEXP mode) { } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_k_ecount(&c_graph, c_k, &c_res, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_k_ecount(&c_graph, c_k, &c_res, (Rf_isNull(weights) ? NULL : &c_weights), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -9140,7 +9627,9 @@ SEXP R_igraph_local_scan_k_ecount_them(SEXP us, SEXP them, SEXP k, SEXP weights_ } c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_k_ecount_them(&c_us, &c_them, c_k, &c_res, (Rf_isNull(weights_them) ? 0 : &c_weights_them), c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_k_ecount_them(&c_us, &c_them, c_k, &c_res, (Rf_isNull(weights_them) ? NULL : &c_weights_them), c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -9171,10 +9660,12 @@ SEXP R_igraph_local_scan_neighborhood_ecount(SEXP graph, SEXP weights, SEXP neig if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } - IGRAPH_R_CHECK(R_igraph_SEXP_to_vector_int_list(neighborhoods, &c_neighborhoods)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_neighborhoods); + R_igraph_SEXP_to_vector_int_list(neighborhoods, &c_neighborhoods); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_neighborhoods); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_neighborhood_ecount(&c_graph, &c_res, (Rf_isNull(weights) ? 0 : &c_weights), &c_neighborhoods)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_neighborhood_ecount(&c_graph, &c_res, (Rf_isNull(weights) ? NULL : &c_weights), &c_neighborhoods)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -9207,10 +9698,12 @@ SEXP R_igraph_local_scan_subset_ecount(SEXP graph, SEXP weights, SEXP subsets) { if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } - IGRAPH_R_CHECK(R_igraph_SEXP_to_vector_int_list(subsets, &c_subsets)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_subsets); + R_igraph_SEXP_to_vector_int_list(subsets, &c_subsets); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_subsets); /* Call igraph */ - IGRAPH_R_CHECK(igraph_local_scan_subset_ecount(&c_graph, &c_res, (Rf_isNull(weights) ? 0 : &c_weights), &c_subsets)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_local_scan_subset_ecount(&c_graph, &c_res, (Rf_isNull(weights) ? NULL : &c_weights), &c_subsets)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); @@ -9239,7 +9732,9 @@ SEXP R_igraph_list_triangles(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_list_triangles(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_to_SEXPp1(&c_res)); @@ -9266,7 +9761,9 @@ SEXP R_igraph_join(SEXP left, SEXP right) { R_SEXP_to_igraph(left, &c_left); R_SEXP_to_igraph(right, &c_right); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_join(&c_res, &c_left, &c_right)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_res); @@ -9305,7 +9802,9 @@ SEXP R_igraph_induced_subgraph_map(SEXP graph, SEXP vids, SEXP impl) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_invmap, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_invmap); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_induced_subgraph_map(&c_graph, &c_res, c_vids, c_impl, &c_map, &c_invmap)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -9351,7 +9850,9 @@ SEXP R_igraph_mycielskian(SEXP graph, SEXP k) { IGRAPH_R_CHECK_INT(k); c_k = (igraph_integer_t) REAL(k)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_mycielskian(&c_graph, &c_res, c_k)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_res); @@ -9381,7 +9882,41 @@ SEXP R_igraph_product(SEXP g1, SEXP g2, SEXP type) { R_SEXP_to_igraph(g2, &c_g2); c_type = (igraph_product_t) Rf_asInteger(type); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_product(&c_res, &c_g1, &c_g2, c_type)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_res); + PROTECT(res=R_igraph_to_SEXP(&c_res)); + IGRAPH_I_DESTROY(&c_res); + IGRAPH_FINALLY_CLEAN(1); + r_result = res; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_rooted_product / +/-------------------------------------------*/ +SEXP R_igraph_rooted_product(SEXP g1, SEXP g2, SEXP root) { + /* Declarations */ + igraph_t c_res; + igraph_t c_g1; + igraph_t c_g2; + igraph_integer_t c_root; + SEXP res; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(g1, &c_g1); + R_SEXP_to_igraph(g2, &c_g2); + c_root = (igraph_integer_t) REAL(root)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_rooted_product(&c_res, &c_g1, &c_g2, c_root)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_res); @@ -9415,7 +9950,9 @@ SEXP R_igraph_gomory_hu_tree(SEXP graph, SEXP capacity) { R_SEXP_to_vector(capacity, &c_capacity); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_gomory_hu_tree(&c_graph, &c_tree, &c_flows, (Rf_isNull(capacity) ? 0 : &c_capacity))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_gomory_hu_tree(&c_graph, &c_tree, &c_flows, (Rf_isNull(capacity) ? NULL : &c_capacity))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -9477,7 +10014,9 @@ SEXP R_igraph_maxflow(SEXP graph, SEXP source, SEXP target, SEXP capacity) { R_SEXP_to_vector(capacity, &c_capacity); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_maxflow(&c_graph, &c_value, &c_flow, &c_cut, &c_partition1, &c_partition2, c_source, c_target, (Rf_isNull(capacity) ? 0 : &c_capacity), &c_stats)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_maxflow(&c_graph, &c_value, &c_flow, &c_cut, &c_partition1, &c_partition2, c_source, c_target, (Rf_isNull(capacity) ? NULL : &c_capacity), &c_stats)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(6)); @@ -9538,7 +10077,9 @@ SEXP R_igraph_residual_graph(SEXP graph, SEXP capacity, SEXP flow) { residual_capacity=R_GlobalEnv; /* hack to have a non-NULL value */ R_SEXP_to_vector(flow, &c_flow); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_residual_graph(&c_graph, &c_capacity, &c_residual, &c_residual_capacity, &c_flow)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -9578,7 +10119,9 @@ SEXP R_igraph_reverse_residual_graph(SEXP graph, SEXP capacity, SEXP flow) { R_SEXP_to_vector(capacity, &c_capacity); R_SEXP_to_vector(flow, &c_flow); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_reverse_residual_graph(&c_graph, &c_capacity, &c_residual, &c_flow)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_residual); @@ -9624,7 +10167,9 @@ SEXP R_igraph_st_mincut(SEXP graph, SEXP source, SEXP target, SEXP capacity) { R_SEXP_to_vector(capacity, &c_capacity); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_st_mincut(&c_graph, &c_value, &c_cut, &c_partition1, &c_partition2, c_source, c_target, (Rf_isNull(capacity) ? 0 : &c_capacity))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_st_mincut(&c_graph, &c_value, &c_cut, &c_partition1, &c_partition2, c_source, c_target, (Rf_isNull(capacity) ? NULL : &c_capacity))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(4)); @@ -9680,7 +10225,9 @@ SEXP R_igraph_dominator_tree(SEXP graph, SEXP root, SEXP mode) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_leftout); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_dominator_tree(&c_graph, c_root, &c_dom, &c_domtree, &c_leftout, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -9724,14 +10271,20 @@ SEXP R_igraph_all_st_cuts(SEXP graph, SEXP source, SEXP target) { SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_cuts, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_cuts); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_partition1s, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_partition1s); + if (0 != igraph_vector_int_list_init(&c_cuts, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_cuts); + if (0 != igraph_vector_int_list_init(&c_partition1s, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_partition1s); c_source = (igraph_integer_t) REAL(source)[0]; c_target = (igraph_integer_t) REAL(target)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_all_st_cuts(&c_graph, &c_cuts, &c_partition1s, c_source, c_target)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -9772,17 +10325,23 @@ SEXP R_igraph_all_st_mincuts(SEXP graph, SEXP source, SEXP target, SEXP capacity SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_cuts, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_cuts); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_partition1s, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_partition1s); + if (0 != igraph_vector_int_list_init(&c_cuts, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_cuts); + if (0 != igraph_vector_int_list_init(&c_partition1s, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_partition1s); c_source = (igraph_integer_t) REAL(source)[0]; c_target = (igraph_integer_t) REAL(target)[0]; if (!Rf_isNull(capacity)) { R_SEXP_to_vector(capacity, &c_capacity); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_all_st_mincuts(&c_graph, &c_value, &c_cuts, &c_partition1s, c_source, c_target, (Rf_isNull(capacity) ? 0 : &c_capacity))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_all_st_mincuts(&c_graph, &c_value, &c_cuts, &c_partition1s, c_source, c_target, (Rf_isNull(capacity) ? NULL : &c_capacity))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -9826,7 +10385,9 @@ SEXP R_igraph_even_tarjan_reduction(SEXP graph) { IGRAPH_FINALLY(igraph_vector_destroy, &c_capacity); capacity=R_GlobalEnv; /* hack to have a non-NULL value */ /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_even_tarjan_reduction(&c_graph, &c_graphbar, &c_capacity)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -9865,7 +10426,9 @@ SEXP R_igraph_is_separator(SEXP graph, SEXP candidate) { igraph_vector_int_t c_candidate_data; R_SEXP_to_igraph_vs(candidate, &c_graph, &c_candidate, &c_candidate_data); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_separator(&c_graph, c_candidate, &c_res)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_candidate_data); @@ -9894,7 +10457,9 @@ SEXP R_igraph_is_minimal_separator(SEXP graph, SEXP candidate) { igraph_vector_int_t c_candidate_data; R_SEXP_to_igraph_vs(candidate, &c_graph, &c_candidate, &c_candidate_data); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_minimal_separator(&c_graph, c_candidate, &c_res)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_candidate_data); @@ -9919,10 +10484,14 @@ SEXP R_igraph_all_minimal_st_separators(SEXP graph) { SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_separators, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_separators); + if (0 != igraph_vector_int_list_init(&c_separators, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_separators); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_all_minimal_st_separators(&c_graph, &c_separators)); + PutRNGstate(); /* Convert output */ PROTECT(separators=R_igraph_vector_int_list_to_SEXPp1(&c_separators)); @@ -9946,10 +10515,14 @@ SEXP R_igraph_minimum_size_separators(SEXP graph) { SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_separators, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_separators); + if (0 != igraph_vector_int_list_init(&c_separators, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_separators); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_minimum_size_separators(&c_graph, &c_separators)); + PutRNGstate(); /* Convert output */ PROTECT(separators=R_igraph_vector_int_list_to_SEXPp1(&c_separators)); @@ -9975,7 +10548,9 @@ SEXP R_igraph_isoclass(SEXP graph) { R_SEXP_to_igraph(graph, &c_graph); c_isoclass=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_isoclass(&c_graph, &c_isoclass)); + PutRNGstate(); /* Convert output */ PROTECT(isoclass=NEW_NUMERIC(1)); @@ -10001,7 +10576,9 @@ SEXP R_igraph_isomorphic(SEXP graph1, SEXP graph2) { R_SEXP_to_igraph(graph1, &c_graph1); R_SEXP_to_igraph(graph2, &c_graph2); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_isomorphic(&c_graph1, &c_graph2, &c_iso)); + PutRNGstate(); /* Convert output */ PROTECT(iso=NEW_LOGICAL(1)); @@ -10012,6 +10589,81 @@ 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)) { + IGRAPH_R_CHECK(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_PV(igraph_vector_int_list_destroy, &c_generators); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_automorphism_group(&c_graph, (Rf_isNull(colors) ? NULL : &c_colors), &c_generators)); + PutRNGstate(); + + /* 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)) { + IGRAPH_R_CHECK(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 */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_count_automorphisms(&c_graph, (Rf_isNull(colors) ? NULL : &c_colors), &c_result)); + PutRNGstate(); + + /* 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 / /-------------------------------------------*/ @@ -10029,7 +10681,9 @@ SEXP R_igraph_isoclass_subgraph(SEXP graph, SEXP vids) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vids); c_isoclass=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_isoclass_subgraph(&c_graph, &c_vids, &c_isoclass)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_vids); @@ -10062,7 +10716,9 @@ SEXP R_igraph_isoclass_create(SEXP size, SEXP number, SEXP directed) { IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_isoclass_create(&c_graph, c_size, c_number, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -10129,7 +10785,9 @@ SEXP R_igraph_isomorphic_vf2(SEXP graph1, SEXP graph2, SEXP vertex_color1, SEXP IGRAPH_R_CHECK(igraph_vector_int_init(&c_map21, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_map21); /* Call igraph */ - IGRAPH_R_CHECK(igraph_isomorphic_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? 0 : &c_vertex_color1), (Rf_isNull(vertex_color2) ? 0 : &c_vertex_color2), (Rf_isNull(edge_color1) ? 0 : &c_edge_color1), (Rf_isNull(edge_color2) ? 0 : &c_edge_color2), &c_iso, &c_map12, &c_map21, 0, 0, 0)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_isomorphic_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? NULL : &c_vertex_color1), (Rf_isNull(vertex_color2) ? NULL : &c_vertex_color2), (Rf_isNull(edge_color1) ? NULL : &c_edge_color1), (Rf_isNull(edge_color2) ? NULL : &c_edge_color2), &c_iso, &c_map12, &c_map21, 0, 0, 0)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -10216,7 +10874,9 @@ SEXP R_igraph_get_isomorphisms_vf2_callback(SEXP graph1, SEXP graph2, SEXP verte IGRAPH_R_CHECK(igraph_vector_int_init(&c_map21, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_map21); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_isomorphisms_vf2_callback(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? 0 : &c_vertex_color1), (Rf_isNull(vertex_color2) ? 0 : &c_vertex_color2), (Rf_isNull(edge_color1) ? 0 : &c_edge_color1), (Rf_isNull(edge_color2) ? 0 : &c_edge_color2), &c_map12, &c_map21, 0, 0, 0, 0)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_isomorphisms_vf2_callback(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? NULL : &c_vertex_color1), (Rf_isNull(vertex_color2) ? NULL : &c_vertex_color2), (Rf_isNull(edge_color1) ? NULL : &c_edge_color1), (Rf_isNull(edge_color2) ? NULL : &c_edge_color2), &c_map12, &c_map21, 0, 0, 0, 0)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -10293,7 +10953,9 @@ SEXP R_igraph_count_isomorphisms_vf2(SEXP graph1, SEXP graph2, SEXP vertex_color IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edge_color2); c_count=0; /* Call igraph */ - IGRAPH_R_CHECK(igraph_count_isomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? 0 : &c_vertex_color1), (Rf_isNull(vertex_color2) ? 0 : &c_vertex_color2), (Rf_isNull(edge_color1) ? 0 : &c_edge_color1), (Rf_isNull(edge_color2) ? 0 : &c_edge_color2), &c_count, 0, 0, 0)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_count_isomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? NULL : &c_vertex_color1), (Rf_isNull(vertex_color2) ? NULL : &c_vertex_color2), (Rf_isNull(edge_color1) ? NULL : &c_edge_color1), (Rf_isNull(edge_color2) ? NULL : &c_edge_color2), &c_count, 0, 0, 0)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_vertex_color1); @@ -10360,7 +11022,9 @@ SEXP R_igraph_get_isomorphisms_vf2(SEXP graph1, SEXP graph2, SEXP vertex_color1, IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_maps, 0)); IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_maps); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_isomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? 0 : &c_vertex_color1), (Rf_isNull(vertex_color2) ? 0 : &c_vertex_color2), (Rf_isNull(edge_color1) ? 0 : &c_edge_color1), (Rf_isNull(edge_color2) ? 0 : &c_edge_color2), &c_maps, 0, 0, 0)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_isomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? NULL : &c_vertex_color1), (Rf_isNull(vertex_color2) ? NULL : &c_vertex_color2), (Rf_isNull(edge_color1) ? NULL : &c_edge_color1), (Rf_isNull(edge_color2) ? NULL : &c_edge_color2), &c_maps, 0, 0, 0)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_vertex_color1); @@ -10395,7 +11059,9 @@ SEXP R_igraph_subisomorphic(SEXP graph1, SEXP graph2) { R_SEXP_to_igraph(graph1, &c_graph1); R_SEXP_to_igraph(graph2, &c_graph2); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_subisomorphic(&c_graph1, &c_graph2, &c_iso)); + PutRNGstate(); /* Convert output */ PROTECT(iso=NEW_LOGICAL(1)); @@ -10460,7 +11126,9 @@ SEXP R_igraph_subisomorphic_vf2(SEXP graph1, SEXP graph2, SEXP vertex_color1, SE IGRAPH_R_CHECK(igraph_vector_int_init(&c_map21, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_map21); /* Call igraph */ - IGRAPH_R_CHECK(igraph_subisomorphic_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? 0 : &c_vertex_color1), (Rf_isNull(vertex_color2) ? 0 : &c_vertex_color2), (Rf_isNull(edge_color1) ? 0 : &c_edge_color1), (Rf_isNull(edge_color2) ? 0 : &c_edge_color2), &c_iso, &c_map12, &c_map21, 0, 0, 0)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_subisomorphic_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? NULL : &c_vertex_color1), (Rf_isNull(vertex_color2) ? NULL : &c_vertex_color2), (Rf_isNull(edge_color1) ? NULL : &c_edge_color1), (Rf_isNull(edge_color2) ? NULL : &c_edge_color2), &c_iso, &c_map12, &c_map21, 0, 0, 0)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -10541,7 +11209,9 @@ SEXP R_igraph_count_subisomorphisms_vf2(SEXP graph1, SEXP graph2, SEXP vertex_co IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edge_color2); c_count=0; /* Call igraph */ - IGRAPH_R_CHECK(igraph_count_subisomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? 0 : &c_vertex_color1), (Rf_isNull(vertex_color2) ? 0 : &c_vertex_color2), (Rf_isNull(edge_color1) ? 0 : &c_edge_color1), (Rf_isNull(edge_color2) ? 0 : &c_edge_color2), &c_count, 0, 0, 0)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_count_subisomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? NULL : &c_vertex_color1), (Rf_isNull(vertex_color2) ? NULL : &c_vertex_color2), (Rf_isNull(edge_color1) ? NULL : &c_edge_color1), (Rf_isNull(edge_color2) ? NULL : &c_edge_color2), &c_count, 0, 0, 0)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_vertex_color1); @@ -10608,7 +11278,9 @@ SEXP R_igraph_get_subisomorphisms_vf2(SEXP graph1, SEXP graph2, SEXP vertex_colo IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_maps, 0)); IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_maps); /* Call igraph */ - IGRAPH_R_CHECK(igraph_get_subisomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? 0 : &c_vertex_color1), (Rf_isNull(vertex_color2) ? 0 : &c_vertex_color2), (Rf_isNull(edge_color1) ? 0 : &c_edge_color1), (Rf_isNull(edge_color2) ? 0 : &c_edge_color2), &c_maps, 0, 0, 0)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_get_subisomorphisms_vf2(&c_graph1, &c_graph2, (Rf_isNull(vertex_color1) ? NULL : &c_vertex_color1), (Rf_isNull(vertex_color2) ? NULL : &c_vertex_color2), (Rf_isNull(edge_color1) ? NULL : &c_edge_color1), (Rf_isNull(edge_color2) ? NULL : &c_edge_color2), &c_maps, 0, 0, 0)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_vertex_color1); @@ -10631,7 +11303,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)) { + IGRAPH_R_CHECK(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); + IGRAPH_R_CHECK(igraph_vector_int_init(&c_labeling, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_labeling); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_canonical_permutation(&c_graph, (Rf_isNull(colors) ? NULL : &c_colors), &c_labeling)); + PutRNGstate(); + + /* 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; @@ -10654,7 +11364,9 @@ 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 : &c_colors), &c_labeling, c_sh, &c_info)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_canonical_permutation_bliss(&c_graph, (Rf_isNull(colors) ? NULL : &c_colors), &c_labeling, c_sh, &c_info)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -10693,7 +11405,9 @@ SEXP R_igraph_permute_vertices(SEXP graph, SEXP permutation) { R_SEXP_to_vector_int_copy(permutation, &c_permutation); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_permutation); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_permute_vertices(&c_graph, &c_res, &c_permutation)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_res); @@ -10751,7 +11465,9 @@ SEXP R_igraph_isomorphic_bliss(SEXP graph1, SEXP graph2, SEXP colors1, SEXP colo IGRAPH_FINALLY(igraph_vector_int_destroy, &c_map21); c_sh = (igraph_bliss_sh_t) Rf_asInteger(sh); /* Call igraph */ - IGRAPH_R_CHECK(igraph_isomorphic_bliss(&c_graph1, &c_graph2, (Rf_isNull(colors1) ? 0 : &c_colors1), (Rf_isNull(colors2) ? 0 : &c_colors2), &c_iso, &c_map12, &c_map21, c_sh, &c_info1, &c_info2)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_isomorphic_bliss(&c_graph1, &c_graph2, (Rf_isNull(colors1) ? NULL : &c_colors1), (Rf_isNull(colors2) ? NULL : &c_colors2), &c_iso, &c_map12, &c_map21, c_sh, &c_info1, &c_info2)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(5)); @@ -10790,9 +11506,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; @@ -10811,7 +11527,9 @@ 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 : &c_colors), c_sh, &c_info)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_count_automorphisms_bliss(&c_graph, (Rf_isNull(colors) ? NULL : &c_colors), c_sh, &c_info)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_colors); @@ -10825,9 +11543,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; @@ -10846,11 +11564,15 @@ SEXP R_igraph_automorphism_group(SEXP graph, SEXP colors, SEXP sh) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_colors, 0)); } IGRAPH_FINALLY(igraph_vector_int_destroy, &c_colors); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_generators, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_generators); + if (0 != igraph_vector_int_list_init(&c_generators, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(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 : &c_colors), &c_generators, c_sh, &c_info)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_automorphism_group_bliss(&c_graph, (Rf_isNull(colors) ? NULL : &c_colors), &c_generators, c_sh, &c_info)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -10894,7 +11616,9 @@ SEXP R_igraph_simplify_and_colorize(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_edge_color, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edge_color); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_simplify_and_colorize(&c_graph, &c_res, &c_vertex_color, &c_edge_color)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -10940,7 +11664,9 @@ SEXP R_igraph_graph_count(SEXP n, SEXP directed) { c_directed = LOGICAL(directed)[0]; c_count=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_graph_count(c_n, c_directed, &c_count)); + PutRNGstate(); /* Convert output */ PROTECT(count=NEW_NUMERIC(1)); @@ -10971,7 +11697,9 @@ SEXP R_igraph_is_matching(SEXP graph, SEXP types, SEXP matching) { R_SEXP_to_vector_int_copy(matching, &c_matching); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_matching); /* Call igraph */ - IGRAPH_R_CHECK(igraph_is_matching(&c_graph, (Rf_isNull(types) ? 0 : &c_types), &c_matching, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_is_matching(&c_graph, (Rf_isNull(types) ? NULL : &c_types), &c_matching, &c_res)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_matching); @@ -11004,7 +11732,9 @@ SEXP R_igraph_is_maximal_matching(SEXP graph, SEXP types, SEXP matching) { R_SEXP_to_vector_int_copy(matching, &c_matching); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_matching); /* Call igraph */ - IGRAPH_R_CHECK(igraph_is_maximal_matching(&c_graph, (Rf_isNull(types) ? 0 : &c_types), &c_matching, &c_res)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_is_maximal_matching(&c_graph, (Rf_isNull(types) ? NULL : &c_types), &c_matching, &c_res)); + PutRNGstate(); /* Convert output */ igraph_vector_int_destroy(&c_matching); @@ -11046,7 +11776,9 @@ SEXP R_igraph_maximum_bipartite_matching(SEXP graph, SEXP types, SEXP weights, S IGRAPH_R_CHECK_REAL(eps); c_eps = REAL(eps)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_maximum_bipartite_matching(&c_graph, &c_types, &c_matching_size, &c_matching_weight, &c_matching, (Rf_isNull(weights) ? 0 : &c_weights), c_eps)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_maximum_bipartite_matching(&c_graph, &c_types, &c_matching_size, &c_matching_weight, &c_matching, (Rf_isNull(weights) ? NULL : &c_weights), c_eps)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -11107,7 +11839,9 @@ SEXP R_igraph_eigen_adjacency(SEXP graph, SEXP algorithm, SEXP which, SEXP optio IGRAPH_FINALLY(igraph_matrix_complex_destroy, &c_cmplxvectors); cmplxvectors=R_GlobalEnv; /* hack to have a non-NULL value */ /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_eigen_adjacency(&c_graph, c_algorithm, &c_which, &c_options, 0, &c_values, &c_vectors, (Rf_isNull(cmplxvalues) ? NULL : &c_cmplxvalues), (Rf_isNull(cmplxvectors) ? NULL : &c_cmplxvectors))); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(5)); @@ -11161,7 +11895,9 @@ SEXP R_igraph_power_law_fit(SEXP data, SEXP xmin, SEXP force_continuous) { IGRAPH_R_CHECK_BOOL(force_continuous); c_force_continuous = LOGICAL(force_continuous)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_power_law_fit(&c_data, &c_res, c_xmin, c_force_continuous)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_plfit_result_to_SEXP(&c_res)); @@ -11195,7 +11931,9 @@ SEXP R_igraph_sir(SEXP graph, SEXP beta, SEXP gamma, SEXP no_sim) { IGRAPH_R_CHECK(igraph_vector_ptr_init(&c_res, 0)); IGRAPH_FINALLY(R_igraph_sirlist_destroy, &c_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_sir(&c_graph, c_beta, c_gamma, c_no_sim, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_sirlist_to_SEXP(&c_res)); @@ -11226,7 +11964,9 @@ SEXP R_igraph_convex_hull(SEXP data) { IGRAPH_R_CHECK(igraph_matrix_init(&c_rescoords, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_rescoords); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_convex_hull(&c_data, &c_resverts, &c_rescoords)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11262,7 +12002,9 @@ SEXP R_igraph_dim_select(SEXP sv) { R_SEXP_to_vector(sv, &c_sv); c_dim=0; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_dim_select(&c_sv, &c_dim)); + PutRNGstate(); /* Convert output */ PROTECT(dim=NEW_NUMERIC(1)); @@ -11291,7 +12033,9 @@ SEXP R_igraph_solve_lsap(SEXP c, SEXP n) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_p, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_p); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_solve_lsap(&c_c, c_n, &c_p)); + PutRNGstate(); /* Convert output */ PROTECT(p=R_igraph_vector_int_to_SEXP(&c_p)); @@ -11324,7 +12068,9 @@ SEXP R_igraph_find_cycle(SEXP graph, SEXP mode) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edges); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_find_cycle(&c_graph, &c_vertices, &c_edges, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11363,17 +12109,23 @@ SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP min_cycle_length, SEXP m SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_vertices, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_vertices); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_edges, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_edges); + if (0 != igraph_vector_int_list_init(&c_vertices, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_vertices); + if (0 != igraph_vector_int_list_init(&c_edges, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_edges); c_mode = (igraph_neimode_t) Rf_asInteger(mode); IGRAPH_R_CHECK_INT(min_cycle_length); c_min_cycle_length = (igraph_integer_t) REAL(min_cycle_length)[0]; IGRAPH_R_CHECK_INT(max_cycle_length); c_max_cycle_length = (igraph_integer_t) REAL(max_cycle_length)[0]; /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_simple_cycles(&c_graph, &c_vertices, &c_edges, c_mode, c_min_cycle_length, c_max_cycle_length)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11410,7 +12162,9 @@ SEXP R_igraph_is_eulerian(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_eulerian(&c_graph, &c_has_path, &c_has_cycle)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11449,7 +12203,9 @@ SEXP R_igraph_eulerian_path(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_vertex_res, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_eulerian_path(&c_graph, &c_edge_res, &c_vertex_res)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11490,7 +12246,9 @@ SEXP R_igraph_eulerian_cycle(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_vertex_res, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_res); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_eulerian_cycle(&c_graph, &c_edge_res, &c_vertex_res)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11527,8 +12285,10 @@ SEXP R_igraph_fundamental_cycles(SEXP graph, SEXP start, SEXP bfs_cutoff, SEXP w SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_basis, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_basis); + if (0 != igraph_vector_int_list_init(&c_basis, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_basis); if (!Rf_isNull(start)) { c_start = (igraph_integer_t) REAL(start)[0]; } @@ -11538,7 +12298,9 @@ SEXP R_igraph_fundamental_cycles(SEXP graph, SEXP start, SEXP bfs_cutoff, SEXP w R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_fundamental_cycles(&c_graph, &c_basis, (Rf_isNull(start) ? 0 : c_start), c_bfs_cutoff, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_fundamental_cycles(&c_graph, &c_basis, (Rf_isNull(start) ? -1 : c_start), c_bfs_cutoff, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(basis=R_igraph_vector_int_list_to_SEXPp1(&c_basis)); @@ -11566,8 +12328,10 @@ SEXP R_igraph_minimum_cycle_basis(SEXP graph, SEXP bfs_cutoff, SEXP complete, SE SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_basis, 0)); - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_basis); + if (0 != igraph_vector_int_list_init(&c_basis, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_basis); IGRAPH_R_CHECK_INT(bfs_cutoff); c_bfs_cutoff = (igraph_integer_t) REAL(bfs_cutoff)[0]; IGRAPH_R_CHECK_BOOL(complete); @@ -11578,7 +12342,9 @@ SEXP R_igraph_minimum_cycle_basis(SEXP graph, SEXP bfs_cutoff, SEXP complete, SE R_SEXP_to_vector(weights, &c_weights); } /* Call igraph */ - IGRAPH_R_CHECK(igraph_minimum_cycle_basis(&c_graph, &c_basis, c_bfs_cutoff, c_complete, c_use_cycle_order, (Rf_isNull(weights) ? 0 : &c_weights))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_minimum_cycle_basis(&c_graph, &c_basis, c_bfs_cutoff, c_complete, c_use_cycle_order, (Rf_isNull(weights) ? NULL : &c_weights))); + PutRNGstate(); /* Convert output */ PROTECT(basis=R_igraph_vector_int_list_to_SEXPp1(&c_basis)); @@ -11608,7 +12374,9 @@ SEXP R_igraph_is_tree(SEXP graph, SEXP mode) { c_root = -1; c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_tree(&c_graph, &c_res, &c_root, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11647,7 +12415,9 @@ SEXP R_igraph_is_forest(SEXP graph, SEXP mode) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_roots); c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_forest(&c_graph, &c_res, &c_roots, c_mode)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -11682,7 +12452,9 @@ SEXP R_igraph_from_prufer(SEXP prufer) { R_SEXP_to_vector_int_copy(prufer, &c_prufer); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_prufer); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_from_prufer(&c_graph, &c_prufer)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -11712,7 +12484,9 @@ SEXP R_igraph_to_prufer(SEXP graph) { IGRAPH_R_CHECK(igraph_vector_int_init(&c_prufer, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_prufer); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_to_prufer(&c_graph, &c_prufer)); + PutRNGstate(); /* Convert output */ PROTECT(prufer=R_igraph_vector_int_to_SEXPp1(&c_prufer)); @@ -11740,7 +12514,9 @@ SEXP R_igraph_tree_from_parent_vector(SEXP parents, SEXP type) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_parents); c_type = (igraph_tree_mode_t) Rf_asInteger(type); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_tree_from_parent_vector(&c_graph, &c_parents, c_type)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -11768,7 +12544,9 @@ SEXP R_igraph_is_complete(SEXP graph) { /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_is_complete(&c_graph, &c_res)); + PutRNGstate(); /* Convert output */ PROTECT(res=NEW_LOGICAL(1)); @@ -11798,7 +12576,9 @@ SEXP R_igraph_random_spanning_tree(SEXP graph, SEXP vid) { c_vid = (igraph_integer_t) REAL(vid)[0]; } /* Call igraph */ - IGRAPH_R_CHECK(igraph_random_spanning_tree(&c_graph, &c_res, (Rf_isNull(vid) ? 0 : c_vid))); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_random_spanning_tree(&c_graph, &c_res, (Rf_isNull(vid) ? -1 : c_vid))); + PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_int_to_SEXPp1(&c_res)); @@ -11829,7 +12609,48 @@ SEXP R_igraph_tree_game(SEXP n, SEXP directed, SEXP method) { c_directed = LOGICAL(directed)[0]; c_method = (igraph_random_tree_t) Rf_asInteger(method); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_tree_game(&c_graph, c_n, c_directed, c_method)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + r_result = graph; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_nearest_neighbor_graph / +/-------------------------------------------*/ +SEXP R_igraph_nearest_neighbor_graph(SEXP points, SEXP metric, SEXP neighbors, SEXP cutoff, SEXP directed) { + /* Declarations */ + igraph_t c_graph; + igraph_matrix_t c_points; + igraph_metric_t c_metric; + igraph_integer_t c_neighbors; + igraph_real_t c_cutoff; + igraph_bool_t c_directed; + SEXP graph; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_matrix(points, &c_points); + c_metric = (igraph_metric_t) Rf_asInteger(metric); + IGRAPH_R_CHECK_INT(neighbors); + c_neighbors = (igraph_integer_t) REAL(neighbors)[0]; + IGRAPH_R_CHECK_REAL(cutoff); + c_cutoff = REAL(cutoff)[0]; + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_nearest_neighbor_graph(&c_graph, &c_points, c_metric, c_neighbors, c_cutoff, c_directed)); + PutRNGstate(); /* Convert output */ IGRAPH_FINALLY(igraph_destroy, &c_graph); @@ -11859,7 +12680,9 @@ SEXP R_igraph_vertex_coloring_greedy(SEXP graph, SEXP heuristic) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_colors); c_heuristic = (igraph_coloring_greedy_t) Rf_asInteger(heuristic); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_vertex_coloring_greedy(&c_graph, &c_colors, c_heuristic)); + PutRNGstate(); /* Convert output */ PROTECT(colors=R_igraph_vector_int_to_SEXP(&c_colors)); @@ -11872,77 +12695,70 @@ SEXP R_igraph_vertex_coloring_greedy(SEXP graph, SEXP heuristic) { } /*-------------------------------------------/ -/ igraph_deterministic_optimal_imitation / +/ igraph_is_vertex_coloring / /-------------------------------------------*/ -SEXP R_igraph_deterministic_optimal_imitation(SEXP graph, SEXP vid, SEXP optimality, SEXP quantities, SEXP strategies, SEXP mode) { +SEXP R_igraph_is_vertex_coloring(SEXP graph, SEXP types) { /* Declarations */ igraph_t c_graph; - igraph_integer_t c_vid; - igraph_optimal_t c_optimality; - igraph_vector_t c_quantities; - igraph_vector_int_t c_strategies; - igraph_neimode_t c_mode; + igraph_vector_int_t c_types; + igraph_bool_t c_res; + SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - c_vid = (igraph_integer_t) REAL(vid)[0]; - c_optimality = (igraph_optimal_t) Rf_asInteger(optimality); - R_SEXP_to_vector(quantities, &c_quantities); - IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(strategies, &c_strategies)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_strategies); - c_mode = (igraph_neimode_t) Rf_asInteger(mode); + if (!Rf_isNull(types)) { + IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(types, &c_types)); + } else { + IGRAPH_R_CHECK(igraph_vector_int_init(&c_types, 0)); + } + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_types); /* Call igraph */ - IGRAPH_R_CHECK(igraph_deterministic_optimal_imitation(&c_graph, c_vid, c_optimality, &c_quantities, &c_strategies, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_is_vertex_coloring(&c_graph, &c_types, &c_res)); + PutRNGstate(); /* Convert output */ - PROTECT(strategies=R_igraph_vector_int_to_SEXP(&c_strategies)); - igraph_vector_int_destroy(&c_strategies); + igraph_vector_int_destroy(&c_types); IGRAPH_FINALLY_CLEAN(1); - r_result = strategies; + PROTECT(res=NEW_LOGICAL(1)); + LOGICAL(res)[0]=c_res; + r_result = res; UNPROTECT(1); return(r_result); } /*-------------------------------------------/ -/ igraph_moran_process / +/ igraph_is_bipartite_coloring / /-------------------------------------------*/ -SEXP R_igraph_moran_process(SEXP graph, SEXP weights, SEXP quantities, SEXP strategies, SEXP mode) { +SEXP R_igraph_is_bipartite_coloring(SEXP graph, SEXP types) { /* Declarations */ igraph_t c_graph; - igraph_vector_t c_weights; - igraph_vector_t c_quantities; - igraph_vector_int_t c_strategies; + igraph_vector_bool_t c_types; + igraph_bool_t c_res; igraph_neimode_t c_mode; + SEXP res; + SEXP mode; SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } - IGRAPH_R_CHECK(R_SEXP_to_vector_copy(quantities, &c_quantities)); - IGRAPH_FINALLY(igraph_vector_destroy, &c_quantities); - IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(strategies, &c_strategies)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_strategies); - c_mode = (igraph_neimode_t) Rf_asInteger(mode); + R_SEXP_to_vector_bool(types, &c_types); /* Call igraph */ - IGRAPH_R_CHECK(igraph_moran_process(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_quantities, &c_strategies, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_is_bipartite_coloring(&c_graph, &c_types, &c_res, NULL)); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); PROTECT(r_names=NEW_CHARACTER(2)); - PROTECT(quantities=R_igraph_vector_to_SEXP(&c_quantities)); - igraph_vector_destroy(&c_quantities); - IGRAPH_FINALLY_CLEAN(1); - PROTECT(strategies=R_igraph_vector_int_to_SEXP(&c_strategies)); - igraph_vector_int_destroy(&c_strategies); - IGRAPH_FINALLY_CLEAN(1); - SET_VECTOR_ELT(r_result, 0, quantities); - SET_VECTOR_ELT(r_result, 1, strategies); - SET_STRING_ELT(r_names, 0, Rf_mkChar("quantities")); - SET_STRING_ELT(r_names, 1, Rf_mkChar("strategies")); + PROTECT(res=NEW_LOGICAL(1)); + LOGICAL(res)[0]=c_res; + SET_VECTOR_ELT(r_result, 0, res); + SET_VECTOR_ELT(r_result, 1, mode); + SET_STRING_ELT(r_names, 0, Rf_mkChar("res")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("mode")); SET_NAMES(r_result, r_names); UNPROTECT(3); @@ -11951,69 +12767,35 @@ SEXP R_igraph_moran_process(SEXP graph, SEXP weights, SEXP quantities, SEXP stra } /*-------------------------------------------/ -/ igraph_roulette_wheel_imitation / -/-------------------------------------------*/ -SEXP R_igraph_roulette_wheel_imitation(SEXP graph, SEXP vid, SEXP is_local, SEXP quantities, SEXP strategies, SEXP mode) { - /* Declarations */ - igraph_t c_graph; - igraph_integer_t c_vid; - igraph_bool_t c_is_local; - igraph_vector_t c_quantities; - igraph_vector_int_t c_strategies; - igraph_neimode_t c_mode; - - SEXP r_result; - /* Convert input */ - R_SEXP_to_igraph(graph, &c_graph); - c_vid = (igraph_integer_t) REAL(vid)[0]; - IGRAPH_R_CHECK_BOOL(is_local); - c_is_local = LOGICAL(is_local)[0]; - R_SEXP_to_vector(quantities, &c_quantities); - IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(strategies, &c_strategies)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_strategies); - c_mode = (igraph_neimode_t) Rf_asInteger(mode); - /* Call igraph */ - IGRAPH_R_CHECK(igraph_roulette_wheel_imitation(&c_graph, c_vid, c_is_local, &c_quantities, &c_strategies, c_mode)); - - /* Convert output */ - PROTECT(strategies=R_igraph_vector_int_to_SEXP(&c_strategies)); - igraph_vector_int_destroy(&c_strategies); - IGRAPH_FINALLY_CLEAN(1); - r_result = strategies; - - UNPROTECT(1); - return(r_result); -} - -/*-------------------------------------------/ -/ igraph_stochastic_imitation / +/ igraph_is_edge_coloring / /-------------------------------------------*/ -SEXP R_igraph_stochastic_imitation(SEXP graph, SEXP vid, SEXP algo, SEXP quantities, SEXP strategies, SEXP mode) { +SEXP R_igraph_is_edge_coloring(SEXP graph, SEXP types) { /* Declarations */ igraph_t c_graph; - igraph_integer_t c_vid; - igraph_imitate_algorithm_t c_algo; - igraph_vector_t c_quantities; - igraph_vector_int_t c_strategies; - igraph_neimode_t c_mode; + igraph_vector_int_t c_types; + igraph_bool_t c_res; + SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - c_vid = (igraph_integer_t) REAL(vid)[0]; - c_algo = (igraph_imitate_algorithm_t) Rf_asInteger(algo); - R_SEXP_to_vector(quantities, &c_quantities); - IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(strategies, &c_strategies)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_strategies); - c_mode = (igraph_neimode_t) Rf_asInteger(mode); + if (!Rf_isNull(types)) { + IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(types, &c_types)); + } else { + IGRAPH_R_CHECK(igraph_vector_int_init(&c_types, 0)); + } + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_types); /* Call igraph */ - IGRAPH_R_CHECK(igraph_stochastic_imitation(&c_graph, c_vid, c_algo, &c_quantities, &c_strategies, c_mode)); + GetRNGstate(); + IGRAPH_R_CHECK(igraph_is_edge_coloring(&c_graph, &c_types, &c_res)); + PutRNGstate(); /* Convert output */ - PROTECT(strategies=R_igraph_vector_int_to_SEXP(&c_strategies)); - igraph_vector_int_destroy(&c_strategies); + igraph_vector_int_destroy(&c_types); IGRAPH_FINALLY_CLEAN(1); - r_result = strategies; + PROTECT(res=NEW_LOGICAL(1)); + LOGICAL(res)[0]=c_res; + r_result = res; UNPROTECT(1); return(r_result); @@ -12031,7 +12813,9 @@ SEXP R_igraph_expand_path_to_pairs(SEXP path) { R_SEXP_to_vector_int_copy(path, &c_path); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_path); /* Call igraph */ + GetRNGstate(); IGRAPH_R_CHECK(igraph_expand_path_to_pairs(&c_path)); + PutRNGstate(); /* Convert output */ PROTECT(path=R_igraph_vector_int_to_SEXPp1(&c_path)); @@ -12055,7 +12839,9 @@ SEXP R_igraph_invalidate_cache(SEXP graph) { R_SEXP_to_igraph_copy(graph, &c_graph); IGRAPH_FINALLY(igraph_destroy, &c_graph); /* Call igraph */ + GetRNGstate(); igraph_invalidate_cache(&c_graph); + PutRNGstate(); /* Convert output */ PROTECT(graph=R_igraph_to_SEXP(&c_graph)); @@ -12067,44 +12853,6 @@ SEXP R_igraph_invalidate_cache(SEXP graph) { return(r_result); } -/*-------------------------------------------/ -/ igraph_vertex_path_from_edge_path / -/-------------------------------------------*/ -SEXP R_igraph_vertex_path_from_edge_path(SEXP graph, SEXP start, SEXP edge_path, SEXP mode) { - /* Declarations */ - igraph_t c_graph; - igraph_integer_t c_start; - igraph_vector_int_t c_edge_path; - igraph_vector_int_t c_vertex_path; - igraph_neimode_t c_mode; - SEXP vertex_path; - - SEXP r_result; - /* Convert input */ - R_SEXP_to_igraph(graph, &c_graph); - if (!Rf_isNull(start)) { - c_start = (igraph_integer_t) REAL(start)[0]; - } - R_SEXP_to_vector_int_copy(edge_path, &c_edge_path); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edge_path); - IGRAPH_R_CHECK(igraph_vector_int_init(&c_vertex_path, 0)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_path); - c_mode = (igraph_neimode_t) Rf_asInteger(mode); - /* Call igraph */ - IGRAPH_R_CHECK(igraph_vertex_path_from_edge_path(&c_graph, (Rf_isNull(start) ? 0 : c_start), &c_edge_path, &c_vertex_path, c_mode)); - - /* Convert output */ - igraph_vector_int_destroy(&c_edge_path); - IGRAPH_FINALLY_CLEAN(1); - PROTECT(vertex_path=R_igraph_vector_int_to_SEXPp1(&c_vertex_path)); - igraph_vector_int_destroy(&c_vertex_path); - IGRAPH_FINALLY_CLEAN(1); - r_result = vertex_path; - - UNPROTECT(1); - return(r_result); -} - /*-------------------------------------------/ / igraph_version / /-------------------------------------------*/ @@ -12123,7 +12871,9 @@ SEXP R_igraph_version(void) { /* Convert input */ /* Call igraph */ + GetRNGstate(); igraph_version(&c_version_string, &c_major, &c_minor, &c_subminor); + PutRNGstate(); /* Convert output */ PROTECT(r_result=NEW_LIST(4)); diff --git a/src/rinterface.h b/src/rinterface.h index e80a49ff997..c80d3998497 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); @@ -80,6 +80,7 @@ void R_igraph_sirlist_destroy(igraph_vector_ptr_t *sl); SEXP R_igraph_arpack_options_to_SEXP(const igraph_arpack_options_t *opt); SEXP R_igraph_bliss_info_to_SEXP(const igraph_bliss_info_t *info); +// FIXME: Remove inconsistent prefix igraph_error_t R_igraph_SEXP_to_strvector(SEXP rval, igraph_strvector_t *sv); igraph_error_t R_igraph_SEXP_to_strvector_copy(SEXP rval, igraph_strvector_t *sv); void R_SEXP_to_vector(SEXP sv, igraph_vector_t *v); diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 461d2db0737..b54ec08f673 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -43,6 +43,11 @@ #include #endif + +#define RNG_BEGIN() GetRNGstate() +#define RNG_END() PutRNGstate() + + enum igraph_t_idx { igraph_t_idx_n = 0, igraph_t_idx_directed = 1, @@ -132,6 +137,11 @@ void igraph_vector_int_list_destroy_pv(void *pv_ptr) igraph_vector_int_list_destroy((igraph_vector_int_list_t*) pv_ptr); } +void igraph_es_destroy_pv(void* pv_ptr) +{ + igraph_es_destroy((igraph_es_t*) pv_ptr); +} + igraph_error_t R_get_int_scalar(SEXP sexp, R_xlen_t index, igraph_integer_t *res) { if (Rf_xlength(sexp) <= index) @@ -377,7 +387,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; @@ -404,12 +414,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 = 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 = 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 = 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))); @@ -487,22 +497,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__, @@ -525,13 +535,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; } @@ -540,7 +550,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; @@ -551,7 +561,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) { @@ -596,7 +606,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; @@ -612,7 +622,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; @@ -621,7 +631,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_PV(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)); } @@ -827,22 +837,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__, @@ -865,13 +875,15 @@ 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)); + case IGRAPH_ATTRIBUTE_STRING: + PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value.as_strvector)); + break; + default: break; } @@ -881,7 +893,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; @@ -893,7 +905,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) { @@ -930,7 +942,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; @@ -950,14 +962,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)); } @@ -1905,7 +1917,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", @@ -2079,7 +2091,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", @@ -2352,7 +2364,7 @@ void checkInterruptFn(void *dummy) { R_CheckUserInterrupt(); } -igraph_error_t R_igraph_interrupt_handler(void *data) { +igraph_bool_t R_igraph_interrupt_handler(void) { /* 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 @@ -2368,9 +2380,9 @@ igraph_error_t R_igraph_interrupt_handler(void *data) { */ if (R_ToplevelExec(checkInterruptFn, NULL) == FALSE) { IGRAPH_FINALLY_FREE(); - return IGRAPH_INTERRUPTED; + return true; } - return IGRAPH_SUCCESS; + return false; } igraph_error_t R_igraph_progress_handler(const char *message, double percent, @@ -3368,7 +3380,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; i Lucas Lopes Felipe
Lucas Lopes Felipe

💻 + Sarah Rashidi
Sarah Rashidi

💻 + Zara Zong
Zara Zong

💻 + Arnór Friðriksson
Arnór Friðriksson

💻 diff --git a/src/vendor/cigraph/CONTRIBUTORS.txt b/src/vendor/cigraph/CONTRIBUTORS.txt index 51db6a2a597..70fd5644106 100644 --- a/src/vendor/cigraph/CONTRIBUTORS.txt +++ b/src/vendor/cigraph/CONTRIBUTORS.txt @@ -71,6 +71,9 @@ Gulshan Kumar (@gulshan-123) Carlos Planelles (@carlos-planelles) Dev_Lohani (@devlohani99) Lucas Lopes Felipe (@lucaslopes) +Sarah Rashidi (@its-serah) +Zara Zong (@minifinity) +Arnór Friðriksson (@Zepeacedust) This project follows the [all-contributors][1] specification. Contributions of any kind welcome! diff --git a/src/vendor/cigraph/codecov.yml b/src/vendor/cigraph/codecov.yml index 2b1d197b4fa..6369e9ab134 100644 --- a/src/vendor/cigraph/codecov.yml +++ b/src/vendor/cigraph/codecov.yml @@ -28,4 +28,5 @@ comment: ignore: - "tests" - "examples" + - "vendor/infomap" - "vendor/pcg" diff --git a/src/vendor/cigraph/etc/cmake/cpack_install_script.cmake b/src/vendor/cigraph/etc/cmake/cpack_install_script.cmake index ba50ad5f508..48af65c65b6 100644 --- a/src/vendor/cigraph/etc/cmake/cpack_install_script.cmake +++ b/src/vendor/cigraph/etc/cmake/cpack_install_script.cmake @@ -79,4 +79,9 @@ if(CPACK_SOURCE_INSTALLED_DIRECTORIES) "${CPACK_PACKAGE_DIRECTORY}/doc/html" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc" ) + file( + INSTALL + "${CPACK_PACKAGE_DIRECTORY}/doc/igraph-docs.info" + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc" + ) endif() diff --git a/src/vendor/cigraph/etc/cmake/dependencies.cmake b/src/vendor/cigraph/etc/cmake/dependencies.cmake index 3e7df4ff069..f550308c49b 100644 --- a/src/vendor/cigraph/etc/cmake/dependencies.cmake +++ b/src/vendor/cigraph/etc/cmake/dependencies.cmake @@ -9,11 +9,11 @@ include(FindThreads) macro(find_dependencies) # Declare the list of dependencies that _may_ be vendored - set(VENDORABLE_DEPENDENCIES BLAS GLPK LAPACK ARPACK GMP PLFIT) + set(VENDORABLE_DEPENDENCIES BLAS GLPK LAPACK ARPACK GMP PLFIT INFOMAP) # Declare optional dependencies associated with IGRAPH_..._SUPPORT flags - # Note that GLPK is both vendorable and optional - set(OPTIONAL_DEPENDENCIES GLPK OpenMP) + # Note that GLPK and INFOMAP are both vendorable and optional + set(OPTIONAL_DEPENDENCIES GLPK OpenMP INFOMAP) # Declare configuration options for dependencies tristate(IGRAPH_USE_INTERNAL_GMP "Compile igraph with internal Mini-GMP" AUTO) @@ -23,6 +23,10 @@ macro(find_dependencies) tristate(IGRAPH_USE_INTERNAL_LAPACK "Compile igraph with internal LAPACK" AUTO) tristate(IGRAPH_USE_INTERNAL_PLFIT "Compile igraph with internal plfit" AUTO) + # Infomap currently does not support being built as an external library, so will + # only be supported through the internal vendored build + set(IGRAPH_USE_INTERNAL_INFOMAP ON) + # Declare dependencies set(REQUIRED_DEPENDENCIES "") set(OPTIONAL_DEPENDENCIES FLEX BISON OpenMP) @@ -46,7 +50,6 @@ macro(find_dependencies) set(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER} ON) endif() endif() - if(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER}) list(APPEND VENDORED_DEPENDENCIES ${DEPENDENCY}) else() @@ -87,6 +90,10 @@ macro(find_dependencies) endif() endif() + if(NOT IGRAPH_INFOMAP_SUPPORT) + list(REMOVE_ITEM VENDORED_DEPENDENCIES INFOMAP) + endif() + if(IGRAPH_GRAPHML_SUPPORT) list(APPEND REQUIRED_DEPENDENCIES LibXml2) endif() @@ -132,6 +139,7 @@ macro(find_dependencies) # Export some aliases that will be used in config.h set(HAVE_GLPK ${GLPK_FOUND}) + set(HAVE_INFOMAP ${INFOMAP_FOUND}) set(HAVE_GMP ${GMP_FOUND}) set(HAVE_LIBXML ${LIBXML2_FOUND}) diff --git a/src/vendor/cigraph/etc/cmake/features.cmake b/src/vendor/cigraph/etc/cmake/features.cmake index 66631025bac..0863f4fac42 100644 --- a/src/vendor/cigraph/etc/cmake/features.cmake +++ b/src/vendor/cigraph/etc/cmake/features.cmake @@ -4,6 +4,7 @@ include(tls) include(lto) option(IGRAPH_GLPK_SUPPORT "Compile igraph with GLPK support" ON) +option(IGRAPH_INFOMAP_SUPPORT "Compile igraph with Infomap support" ON) tristate(IGRAPH_GRAPHML_SUPPORT "Compile igraph with GraphML support" AUTO) tristate(IGRAPH_OPENMP_SUPPORT "Use OpenMP for parallelization" AUTO) diff --git a/src/vendor/cigraph/etc/cmake/packaging.cmake b/src/vendor/cigraph/etc/cmake/packaging.cmake index 4887b6c4b48..a45497400e6 100644 --- a/src/vendor/cigraph/etc/cmake/packaging.cmake +++ b/src/vendor/cigraph/etc/cmake/packaging.cmake @@ -4,7 +4,7 @@ set(CPACK_PACKAGE_VENDOR "The igraph development team") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING") -if(TARGET html) +if(TARGET html AND TARGET info) # Alias "dist" to "package_source" add_custom_target(dist COMMAND "${CMAKE_COMMAND}" @@ -14,13 +14,13 @@ if(TARGET html) USES_TERMINAL ) - # We want to include the HTML docs in the source package so add a dependency - add_dependencies(dist html) + # Add dependencies to "dist" + add_dependencies(dist html info) else() add_custom_target(dist COMMAND "${CMAKE_COMMAND}" -E false COMMENT - "Cannot build source tarball since the HTML documentation was not built." + "Cannot build source tarball since the HTML or the Texinfo documentation was not built." VERBATIM USES_TERMINAL ) diff --git a/src/vendor/cigraph/include/igraph.h b/src/vendor/cigraph/include/igraph.h index 30c88267f3e..e50df3de8a0 100644 --- a/src/vendor/cigraph/include/igraph.h +++ b/src/vendor/cigraph/include/igraph.h @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2003-2024 The igraph development team + Copyright (C) 2003-2025 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 @@ -13,9 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + along with this program. If not, see . */ #ifndef IGRAPH_H @@ -26,13 +24,13 @@ #include "igraph_error.h" #include "igraph_random.h" #include "igraph_progress.h" +#include "igraph_setup.h" #include "igraph_statusbar.h" #include "igraph_types.h" #include "igraph_complex.h" #include "igraph_vector.h" #include "igraph_matrix.h" -#include "igraph_array.h" #include "igraph_bitset.h" #include "igraph_dqueue.h" #include "igraph_stack.h" @@ -51,14 +49,13 @@ #include "igraph_interface.h" #include "igraph_constructors.h" #include "igraph_games.h" -#include "igraph_microscopic_update.h" #include "igraph_centrality.h" #include "igraph_paths.h" #include "igraph_components.h" #include "igraph_structural.h" #include "igraph_transitivity.h" #include "igraph_neighborhood.h" -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "igraph_bipartite.h" #include "igraph_cliques.h" #include "igraph_layout.h" @@ -94,5 +91,7 @@ #include "igraph_graphicality.h" #include "igraph_cycles.h" #include "igraph_reachability.h" +#include "igraph_spatial.h" +#include "igraph_sampling.h" #endif diff --git a/src/vendor/cigraph/include/igraph_adjlist.h b/src/vendor/cigraph/include/igraph_adjlist.h index e6125fab4c2..0a9885ac9a0 100644 --- a/src/vendor/cigraph/include/igraph_adjlist.h +++ b/src/vendor/cigraph/include/igraph_adjlist.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,22 +13,19 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_ADJLIST_H #define IGRAPH_ADJLIST_H #include "igraph_decls.h" +#include "igraph_datatype.h" #include "igraph_constants.h" #include "igraph_error.h" #include "igraph_types.h" -#include "igraph_datatype.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef struct igraph_adjlist_t { igraph_integer_t length; @@ -44,13 +39,13 @@ typedef struct igraph_inclist_t { IGRAPH_EXPORT igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, - igraph_multiple_t multiple); + igraph_bool_t multiple); IGRAPH_EXPORT igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_integer_t no_of_nodes); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_adjlist_size(const igraph_adjlist_t *al); IGRAPH_EXPORT igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, - igraph_bool_t loops); + igraph_loops_t loops); IGRAPH_EXPORT igraph_error_t igraph_adjlist_init_from_inclist( const igraph_t *graph, igraph_adjlist_t *al, const igraph_inclist_t *il); IGRAPH_EXPORT void igraph_adjlist_destroy(igraph_adjlist_t *al); @@ -112,14 +107,14 @@ typedef struct igraph_lazy_adjlist_t { igraph_vector_int_t **adjs; igraph_neimode_t mode; igraph_loops_t loops; - igraph_multiple_t multiple; + igraph_bool_t multiple; } igraph_lazy_adjlist_t; IGRAPH_EXPORT igraph_error_t igraph_lazy_adjlist_init(const igraph_t *graph, igraph_lazy_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, - igraph_multiple_t multiple); + igraph_bool_t multiple); IGRAPH_EXPORT void igraph_lazy_adjlist_destroy(igraph_lazy_adjlist_t *al); IGRAPH_EXPORT void igraph_lazy_adjlist_clear(igraph_lazy_adjlist_t *al); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_adjlist_size(const igraph_lazy_adjlist_t *al); @@ -220,6 +215,6 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_inclist_size(con : (igraph_i_lazy_inclist_get_real(il,no))) IGRAPH_EXPORT igraph_vector_int_t *igraph_i_lazy_inclist_get_real(igraph_lazy_inclist_t *il, igraph_integer_t no); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_arpack.h b/src/vendor/cigraph/include/igraph_arpack.h index 348e23dcd76..9f1d2adb6fd 100644 --- a/src/vendor/cigraph/include/igraph_arpack.h +++ b/src/vendor/cigraph/include/igraph_arpack.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_ARPACK_H @@ -30,7 +25,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \section about_arpack ARPACK interface in igraph @@ -291,6 +286,67 @@ typedef struct igraph_arpack_storage_t { igraph_real_t *workev; } igraph_arpack_storage_t; +/** + * \typedef igraph_arpack_error_t + * \brief Error codes from ARPACK. + * + * These error codes represent error conditions returned from ARPACK. + * They are used internally to format error messages when igraph itself + * returns an \c IGRAPH_EARPACK error code from an ARPACK-related function. + * + * \enumval IGRAPH_ARPACK_NO_ERROR No error was encountered in ARPACK. + * \enumval IGRAPH_ARPACK_PROD Matrix-vector product failed (not used any more). + * \enumval IGRAPH_ARPACK_NPOS N must be positive. + * \enumval IGRAPH_ARPACK_NEVNPOS NEV must be positive. + * \enumval IGRAPH_ARPACK_NCVSMALL NCV must be bigger. + * \enumval IGRAPH_ARPACK_NONPOSI Maximum number of iterations should be positive. + * \enumval IGRAPH_ARPACK_WHICHINV Invalid WHICH parameter. + * \enumval IGRAPH_ARPACK_BMATINV Invalid BMAT parameter. + * \enumval IGRAPH_ARPACK_WORKLSMALL WORKL is too small. + * \enumval IGRAPH_ARPACK_TRIDERR LAPACK error in tridiagonal eigenvalue calculation. + * \enumval IGRAPH_ARPACK_ZEROSTART Starting vector is zero. + * \enumval IGRAPH_ARPACK_MODEINV MODE is invalid. + * \enumval IGRAPH_ARPACK_MODEBMAT MODE and BMAT are not compatible. + * \enumval IGRAPH_ARPACK_ISHIFT ISHIFT must be 0 or 1. + * \enumval IGRAPH_ARPACK_NEVBE NEV and WHICH='BE' are incompatible. + * \enumval IGRAPH_ARPACK_NOFACT Could not build an Arnoldi factorization. + * \enumval IGRAPH_ARPACK_FAILED No eigenvalues to sufficient accuracy. + * \enumval IGRAPH_ARPACK_HOWMNY HOWMNY is invalid. + * \enumval IGRAPH_ARPACK_HOWMNYS HOWMNY='S' is not implemented. + * \enumval IGRAPH_ARPACK_EVDIFF Different number of converged Ritz values. + * \enumval IGRAPH_ARPACK_SHUR Error from calculation of a real Schur form. + * \enumval IGRAPH_ARPACK_LAPACK LAPACK (dtrevc) error for calculating eigenvectors. + * \enumval IGRAPH_ARPACK_UNKNOWN Unknown ARPACK error. + */ +typedef enum { + IGRAPH_ARPACK_NO_ERROR = 0, + IGRAPH_ARPACK_PROD = 15, + IGRAPH_ARPACK_NPOS = 16, + IGRAPH_ARPACK_NEVNPOS = 17, + IGRAPH_ARPACK_NCVSMALL = 18, + IGRAPH_ARPACK_NONPOSI = 19, + IGRAPH_ARPACK_WHICHINV = 20, + IGRAPH_ARPACK_BMATINV = 21, + IGRAPH_ARPACK_WORKLSMALL = 22, + IGRAPH_ARPACK_TRIDERR = 23, + IGRAPH_ARPACK_ZEROSTART = 24, + IGRAPH_ARPACK_MODEINV = 25, + IGRAPH_ARPACK_MODEBMAT = 26, + IGRAPH_ARPACK_ISHIFT = 27, + IGRAPH_ARPACK_NEVBE = 28, + IGRAPH_ARPACK_NOFACT = 29, + IGRAPH_ARPACK_FAILED = 30, + IGRAPH_ARPACK_HOWMNY = 31, + IGRAPH_ARPACK_HOWMNYS = 32, + IGRAPH_ARPACK_EVDIFF = 33, + IGRAPH_ARPACK_SHUR = 34, + IGRAPH_ARPACK_LAPACK = 35, + IGRAPH_ARPACK_UNKNOWN = 36, + IGRAPH_ARPACK_MAXIT = 39, + IGRAPH_ARPACK_NOSHIFT = 40, + IGRAPH_ARPACK_REORDER = 41, +} igraph_arpack_error_t; + IGRAPH_EXPORT void igraph_arpack_options_init(igraph_arpack_options_t *o); IGRAPH_EXPORT igraph_arpack_options_t* igraph_arpack_options_get_default(void); @@ -331,6 +387,9 @@ IGRAPH_EXPORT igraph_error_t igraph_arpack_rnsolve(igraph_arpack_function_t *fun IGRAPH_EXPORT igraph_error_t igraph_arpack_unpack_complex(igraph_matrix_t *vectors, igraph_matrix_t *values, igraph_integer_t nev); -__END_DECLS +IGRAPH_EXPORT const char* igraph_arpack_error_to_string(igraph_arpack_error_t error); +IGRAPH_EXPORT igraph_arpack_error_t igraph_arpack_get_last_error(void); + +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_array.h b/src/vendor/cigraph/include/igraph_array.h deleted file mode 100644 index 1f098d0a3c3..00000000000 --- a/src/vendor/cigraph/include/igraph_array.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- mode: C -*- */ -/* - IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#ifndef IGRAPH_ARRAY_H -#define IGRAPH_ARRAY_H - -#include "igraph_decls.h" -#include "igraph_error.h" -#include "igraph_vector.h" - -__BEGIN_DECLS - -/* -------------------------------------------------- */ -/* 3D array */ -/* -------------------------------------------------- */ - -#define BASE_IGRAPH_REAL -#include "igraph_pmt.h" -#include "igraph_array_pmt.h" -#include "igraph_pmt_off.h" -#undef BASE_IGRAPH_REAL - -#define BASE_INT -#include "igraph_pmt.h" -#include "igraph_array_pmt.h" -#include "igraph_pmt_off.h" -#undef BASE_INT - -#define BASE_CHAR -#include "igraph_pmt.h" -#include "igraph_array_pmt.h" -#include "igraph_pmt_off.h" -#undef BASE_CHAR - -#define BASE_BOOL -#include "igraph_pmt.h" -#include "igraph_array_pmt.h" -#include "igraph_pmt_off.h" -#undef BASE_BOOL - -__END_DECLS - -#endif diff --git a/src/vendor/cigraph/include/igraph_array_pmt.h b/src/vendor/cigraph/include/igraph_array_pmt.h deleted file mode 100644 index 8cbcfb43376..00000000000 --- a/src/vendor/cigraph/include/igraph_array_pmt.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- mode: C -*- */ -/* - IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -typedef struct TYPE(igraph_array3) { - TYPE(igraph_vector) data; - igraph_integer_t n1, n2, n3, n1n2; -} TYPE(igraph_array3); - -#ifndef IGRAPH_ARRAY3_INIT_FINALLY -#define IGRAPH_ARRAY3_INIT_FINALLY(a, n1, n2, n3) \ - do { IGRAPH_CHECK(igraph_array3_init(a, n1, n2, n3)); \ - IGRAPH_FINALLY(igraph_array3_destroy, a); } while (0) -#endif - -#ifndef ARRAY3 - #define ARRAY3(m,i,j,k) ((m).data.stor_begin[(m).n1n2*(k)+(m).n1*(j)+(i)]) -#endif - -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_array3, init)( - TYPE(igraph_array3) *a, igraph_integer_t n1, igraph_integer_t n2, - igraph_integer_t n3); -IGRAPH_DEPRECATED IGRAPH_EXPORT void FUNCTION(igraph_array3, destroy)(TYPE(igraph_array3) *a); -IGRAPH_DEPRECATED IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_array3, size)(const TYPE(igraph_array3) *a); -IGRAPH_DEPRECATED IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_array3, n)( - const TYPE(igraph_array3) *a, igraph_integer_t idx); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_array3, resize)( - TYPE(igraph_array3) *a, igraph_integer_t n1, igraph_integer_t n2, - igraph_integer_t n3); -IGRAPH_DEPRECATED IGRAPH_EXPORT void FUNCTION(igraph_array3, null)(TYPE(igraph_array3) *a); -IGRAPH_DEPRECATED IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_array3, sum)(const TYPE(igraph_array3) *a); -IGRAPH_DEPRECATED IGRAPH_EXPORT void FUNCTION(igraph_array3, scale)(TYPE(igraph_array3) *a, BASE by); -IGRAPH_DEPRECATED IGRAPH_EXPORT void FUNCTION(igraph_array3, fill)(TYPE(igraph_array3) *a, BASE e); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_array3, update)(TYPE(igraph_array3) *to, - const TYPE(igraph_array3) *from); diff --git a/src/vendor/cigraph/include/igraph_attributes.h b/src/vendor/cigraph/include/igraph_attributes.h index 985b55a3aa4..de9c5343357 100644 --- a/src/vendor/cigraph/include/igraph_attributes.h +++ b/src/vendor/cigraph/include/igraph_attributes.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2005-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2005-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_ATTRIBUTES_H @@ -34,114 +29,140 @@ #include "igraph_vector_ptr.h" #include "igraph_iterators.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Attributes */ /* -------------------------------------------------- */ -/** - * \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_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_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 @@ -206,6 +227,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. @@ -217,54 +254,71 @@ 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 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 - * argument. 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 structure 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 a 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, after the + * base data structure was modified. The number of vertices that were added is + * supplied as an argument. The function is supposed to set up default values + * for each vertex attribute that is currently registered on the graph, for + * all the newly added vertices. Expected to return an error code. * \member permute_vertices Called when a new graph is created based on an * existing one such that there is a mapping from the vertices of the new * graph back to the vertices of the old graph (e.g. if vertices are removed * from a graph). The supplied index vector defines which old vertex - * a new vertex corresponds to. Its length must be the same as the - * number of vertices in the new graph. Note that the old and the new graph - * may be the same. If the two graph instances are \em not the same, implementors - * may safely assume that the new graph has no vertex attributes yet (but it - * may already have graph or edge attributes by the time this function is - * called). + * a new vertex corresponds to. Its length is the same as the number of + * vertices in the new graph, and for each new vertex it provides the ID + * of the corresponding vertex in the old graph. The function is supposed to + * set up the values of the vertex attributes of the new graph based on the + * attributes of the old graph and the provided index vector. Note that the + * old and the new graph \em may be the same, in which case it is the + * responsibility of the function to ensure that the operation can safely be + * performed in-place. If the two graph instances are \em not the same, + * implementors may safely assume that the new graph has no vertex attributes + * yet (but it may already have graph or edge attributes by the time this + * function is called). * \member combine_vertices This function is called when the creation * of a new graph involves a merge (contraction, etc.) of vertices - * from another graph. The function is after the new graph was created. + * from another graph. The function is called after the new graph was created. * An argument specifies how several vertices from the old graph map to a * single vertex in the new graph. It is guaranteed that the old and the * new graph instances are different when this callback is called. * Implementors may safely assume that the new graph has no vertex attributes * yet (but it may already have graph or edge attributes by the time this * function is called). - * \member add_edges Called when new edges have been added. The number - * of new edges are supplied as well. It is expected to return an - * error code. - * \member permute_edges Called when a new graph is created and - * some of the new edges should carry the attributes of some of the - * old edges. The idx vector shows the mapping between the old edges and - * the new ones. Its length is the same as the number of edges in the new - * graph, and for each edge it gives the ID of the old edge (the edge in - * the old graph). Note that the old and the new graph instances \em may - * be the same. If the two graph instances are \em not the same, implementors - * may safely assume that the new graph has no edge attributes yet (but it - * may already have graph or vertex attributes by the time this function is - * called). + * \member add_edges Called when new edges are added to a graph, after the + * base data structure was modified. A vector containing the endpoints of the + * new edges are supplied as an argument. The function is supposed to set up + * default values for each edge attribute that is currently registered on the + * graph, for all the newly added edges. Expected to return an error code. + * \member permute_edges Called when a new graph is created based on an + * existing one such that some of the edges in the new graph should copy the + * attributes of some edges from the old graph (this also includes the + * deletion of edges). The supplied index vector defines which old edge a new + * edge corresponds to. Its length is the same as the number of edges in the + * new graph, and for each edge it provides the ID of the corresponding edge + * in the old graph. The function is supposed to set up the values of the + * edge attributes of the new graph based on the attributes of the old graph + * and the provided index vector. Note that the old and the new graph \em may + * be the same, in which case it is the responsibility of the function to + * ensure that the operation can safely be performed in-place. If the two + * graph instances are \em not the same, implementors may safely assume that + * the new graph has no edge attributes yet (but it may already have graph or + * vertex attributes by the time this function is called). * \member combine_edges This function is called when the creation * of a new graph involves a merge (contraction, etc.) of edges * from another graph. The function is after the new graph was created. @@ -278,43 +332,60 @@ IGRAPH_EXPORT igraph_error_t igraph_attribute_combination_query(const igraph_att * types should be returned. * \member has_attr Check whether a graph has the named * graph/vertex/edge attribute. - * \member gettype Query the type of a graph/vertex/edge attribute. + * \member get_type Query the type of a graph/vertex/edge attribute. * \member get_numeric_graph_attr Query a numeric graph attribute. The - * value should be placed as the first element of the \p value - * vector. + * value should be appended to the provided \p value vector. No assumptions + * should be made about the initial contents of the \p value vector and it is + * not guaranteed to be empty. * \member get_string_graph_attr Query a string graph attribute. The - * value should be placed as the first element of the \p value - * string vector. + * value should be appended to the provided \p value vector. No assumptions + * should be made about the initial contents of the \p value vector and it is + * not guaranteed to be empty. * \member get_bool_graph_attr Query a boolean graph attribute. The - * value should be placed as the first element of the \p value - * boolean vector. + * value should be appended to the provided \p value vector. No assumptions + * should be made about the initial contents of the \p value vector and it is + * not guaranteed to be empty. * \member get_numeric_vertex_attr Query a numeric vertex attribute, - * for the vertices included in \p vs. + * for the vertices included in \p vs. The attribute values should be + * appended to the provided \p value vector. No assumptions should be made + * about the initial contents of the \p value vector and it is not guaranteed + * to be empty. * \member get_string_vertex_attr Query a string vertex attribute, - * for the vertices included in \p vs. + * for the vertices included in \p vs. The attribute values should be + * appended to the provided \p value vector. No assumptions should be made + * about the initial contents of the \p value vector and it is not guaranteed + * to be empty. * \member get_bool_vertex_attr Query a boolean vertex attribute, - * for the vertices included in \p vs. + * for the vertices included in \p vs. The attribute values should be + * appended to the provided \p value vector. No assumptions should be made + * about the initial contents of the \p value vector and it is not guaranteed + * to be empty. * \member get_numeric_edge_attr Query a numeric edge attribute, for - * the edges included in \p es. + * the edges included in \p es. The attribute values should be appended + * to the provided \p value vector. No assumptions should be made + * about the initial contents of the \p value vector and it is not guaranteed + * to be empty. * \member get_string_edge_attr Query a string edge attribute, for the - * edges included in \p es. + * the edges included in \p es. The attribute values should be appended + * to the provided \p value vector. No assumptions should be made + * about the initial contents of the \p value vector and it is not guaranteed + * to be empty. * \member get_bool_edge_attr Query a boolean edge attribute, for the - * edges included in \p es. - * - * Note that the get_*_*_attr are allowed to - * convert the attributes to numeric or string. E.g. if a vertex attribute - * is a GNU R complex data type, then - * get_string_vertex_attribute may serialize it - * into a string, but this probably makes sense only if - * add_vertices is able to deserialize it. + * the edges included in \p es. The attribute values should be appended + * to the provided \p value vector. No assumptions should be made + * about the initial contents of the \p value vector and it is not guaranteed + * to be empty. */ 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); @@ -322,8 +393,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, @@ -336,7 +409,7 @@ typedef struct igraph_attribute_table_t { igraph_strvector_t *enames, igraph_vector_int_t *etypes); igraph_bool_t (*has_attr)(const igraph_t *graph, igraph_attribute_elemtype_t type, const char *name); - igraph_error_t (*gettype)(const igraph_t *graph, igraph_attribute_type_t *type, + igraph_error_t (*get_type)(const igraph_t *graph, igraph_attribute_type_t *type, igraph_attribute_elemtype_t elemtype, const char *name); igraph_error_t (*get_numeric_graph_attr)(const igraph_t *graph, const char *name, igraph_vector_t *value); @@ -364,7 +437,6 @@ typedef struct igraph_attribute_table_t { igraph_vector_bool_t *value); } igraph_attribute_table_t; -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_attribute_table_t * igraph_i_set_attribute_table(const igraph_attribute_table_t * table); IGRAPH_EXPORT igraph_attribute_table_t * igraph_set_attribute_table(const igraph_attribute_table_t * table); IGRAPH_EXPORT igraph_bool_t igraph_has_attribute_table(void); @@ -854,6 +926,6 @@ IGRAPH_EXPORT void igraph_cattribute_remove_all(igraph_t *graph, igraph_bool_t g */ #define DELALL(graph) (igraph_cattribute_remove_all((graph),1,1,1)) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_bipartite.h b/src/vendor/cigraph/include/igraph_bipartite.h index f32fe8aa7fb..923951a27fb 100644 --- a/src/vendor/cigraph/include/igraph_bipartite.h +++ b/src/vendor/cigraph/include/igraph_bipartite.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_BIPARTITE_H @@ -32,7 +27,7 @@ #include "igraph_vector.h" #include "igraph_matrix.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Bipartite networks */ @@ -63,15 +58,28 @@ IGRAPH_EXPORT igraph_error_t igraph_bipartite_projection(const igraph_t *graph, igraph_vector_int_t *multiplicity2, igraph_integer_t probe1); -IGRAPH_EXPORT igraph_error_t igraph_biadjacency(igraph_t *graph, igraph_vector_bool_t *types, - const igraph_matrix_t *input, igraph_bool_t directed, - igraph_neimode_t mode, igraph_bool_t multiple); +IGRAPH_EXPORT igraph_error_t igraph_biadjacency( + igraph_t *graph, + igraph_vector_bool_t *types, + const igraph_matrix_t *biadjmatrix, + igraph_bool_t directed, + igraph_neimode_t mode, + igraph_bool_t multiple); + +IGRAPH_EXPORT igraph_error_t igraph_weighted_biadjacency( + igraph_t *graph, + igraph_vector_bool_t *types, + igraph_vector_t *weights, + const igraph_matrix_t *biadjmatrix, + igraph_bool_t directed, + igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_get_biadjacency(const igraph_t *graph, - const igraph_vector_bool_t *types, - igraph_matrix_t *res, - igraph_vector_int_t *row_ids, - igraph_vector_int_t *col_ids); + const igraph_vector_bool_t *types, + const igraph_vector_t *weights, + igraph_matrix_t *res, + igraph_vector_int_t *row_ids, + igraph_vector_int_t *col_ids); IGRAPH_EXPORT igraph_error_t igraph_is_bipartite(const igraph_t *graph, igraph_bool_t *res, @@ -85,28 +93,13 @@ 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); - -/* Deprecated functions: */ - -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_incidence( - igraph_t *graph, igraph_vector_bool_t *types, const igraph_matrix_t *incidence, - igraph_bool_t directed, igraph_neimode_t mode, igraph_bool_t multiple -); - -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_get_incidence( - const igraph_t *graph, const igraph_vector_bool_t *types, igraph_matrix_t *res, - igraph_vector_int_t *row_ids, igraph_vector_int_t *col_ids -); + igraph_neimode_t mode, igraph_bool_t multiple); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_bipartite_game( +IGRAPH_EXPORT igraph_error_t igraph_bipartite_iea_game( igraph_t *graph, igraph_vector_bool_t *types, - igraph_erdos_renyi_t type, - igraph_integer_t n1, igraph_integer_t n2, - igraph_real_t p, igraph_integer_t m, - igraph_bool_t directed, igraph_neimode_t mode -); + igraph_integer_t n1, igraph_integer_t n2, igraph_integer_t m, + igraph_bool_t directed, igraph_neimode_t mode); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_bitset.h b/src/vendor/cigraph/include/igraph_bitset.h index a1e028409ea..0d847730856 100644 --- a/src/vendor/cigraph/include/igraph_bitset.h +++ b/src/vendor/cigraph/include/igraph_bitset.h @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2024 The igraph development team + Copyright (C) 2024-2025 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 @@ -13,9 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + along with this program. If not, see . */ #ifndef IGRAPH_BITSET_H @@ -24,13 +22,14 @@ #include "igraph_decls.h" #include "igraph_error.h" #include "igraph_vector.h" +#include "igraph_types.h" /* Required for MSVC intrinsics such as __popcnt and __popcnt64 */ #ifdef _MSC_VER #include "intrin.h" #endif -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \ingroup bitset @@ -261,6 +260,6 @@ IGRAPH_EXPORT igraph_error_t igraph_bitset_print(const igraph_bitset_t *bitset); do { IGRAPH_CHECK(igraph_bitset_init(bitset, size)); \ IGRAPH_FINALLY(igraph_bitset_destroy, bitset); } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_BITSET_H */ diff --git a/src/vendor/cigraph/include/igraph_bitset_list.h b/src/vendor/cigraph/include/igraph_bitset_list.h index 68629d73d83..c837dc8c4fc 100644 --- a/src/vendor/cigraph/include/igraph_bitset_list.h +++ b/src/vendor/cigraph/include/igraph_bitset_list.h @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2024 The igraph development team + Copyright (C) 2024-2025 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 @@ -13,9 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + along with this program. If not, see . */ #ifndef IGRAPH_BITSET_LIST_H @@ -24,9 +22,8 @@ #include "igraph_bitset.h" #include "igraph_decls.h" #include "igraph_error.h" -#include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* List of graphs */ @@ -44,6 +41,6 @@ __BEGIN_DECLS do { IGRAPH_CHECK(igraph_bitset_list_init(v, size)); \ IGRAPH_FINALLY(igraph_bitset_list_destroy, v); } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_blas.h b/src/vendor/cigraph/include/igraph_blas.h index ae7daa47d24..40de616bf19 100644 --- a/src/vendor/cigraph/include/igraph_blas.h +++ b/src/vendor/cigraph/include/igraph_blas.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_BLAS_H @@ -30,7 +25,7 @@ #include "igraph_vector.h" #include "igraph_matrix.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \section about_blas BLAS interface in igraph @@ -67,6 +62,6 @@ IGRAPH_EXPORT igraph_real_t igraph_blas_dnrm2(const igraph_vector_t *v); IGRAPH_EXPORT igraph_error_t igraph_blas_ddot(const igraph_vector_t *v1, const igraph_vector_t *v2, igraph_real_t *res); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_centrality.h b/src/vendor/cigraph/include/igraph_centrality.h index 816815b135a..13891b7eaf8 100644 --- a/src/vendor/cigraph/include/igraph_centrality.h +++ b/src/vendor/cigraph/include/igraph_centrality.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,24 +13,21 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_CENTRALITY_H #define IGRAPH_CENTRALITY_H #include "igraph_decls.h" +#include "igraph_arpack.h" #include "igraph_constants.h" -#include "igraph_error.h" -#include "igraph_types.h" #include "igraph_datatype.h" #include "igraph_iterators.h" -#include "igraph_arpack.h" +#include "igraph_error.h" +#include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Centrality */ @@ -40,30 +35,30 @@ __BEGIN_DECLS IGRAPH_EXPORT igraph_error_t igraph_closeness(const igraph_t *graph, igraph_vector_t *res, igraph_vector_int_t *reachable_count, igraph_bool_t *all_reachable, - const igraph_vs_t vids, igraph_neimode_t mode, + igraph_vs_t vids, igraph_neimode_t mode, const igraph_vector_t *weights, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_closeness_cutoff(const igraph_t *graph, igraph_vector_t *res, igraph_vector_int_t *reachable_count, igraph_bool_t *all_reachable, - const igraph_vs_t vids, igraph_neimode_t mode, + igraph_vs_t vids, igraph_neimode_t mode, const igraph_vector_t *weights, igraph_bool_t normalized, igraph_real_t cutoff); IGRAPH_EXPORT igraph_error_t igraph_harmonic_centrality(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, + igraph_vs_t vids, igraph_neimode_t mode, const igraph_vector_t *weights, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_harmonic_centrality_cutoff(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, + igraph_vs_t vids, igraph_neimode_t mode, const igraph_vector_t *weights, igraph_bool_t normalized, igraph_real_t cutoff); IGRAPH_EXPORT igraph_error_t igraph_betweenness(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_bool_t directed, + igraph_vs_t vids, igraph_bool_t directed, const igraph_vector_t *weights); IGRAPH_EXPORT igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_bool_t directed, + igraph_vs_t vids, igraph_bool_t directed, const igraph_vector_t *weights, igraph_real_t cutoff); IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness(const igraph_t *graph, igraph_vector_t *result, igraph_bool_t directed, @@ -72,12 +67,12 @@ IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *grap igraph_bool_t directed, const igraph_vector_t *weights, igraph_real_t cutoff); IGRAPH_EXPORT igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_bool_t directed, - const igraph_vs_t sources, const igraph_vs_t targets, + igraph_vs_t vids, igraph_bool_t directed, + igraph_vs_t sources, igraph_vs_t targets, const igraph_vector_t *weights); IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vector_t *res, - const igraph_es_t eids, igraph_bool_t directed, - const igraph_vs_t sources, const igraph_vs_t targets, + igraph_es_t eids, igraph_bool_t directed, + igraph_vs_t sources, igraph_vs_t targets, const igraph_vector_t *weights); /** @@ -99,34 +94,34 @@ typedef enum { IGRAPH_EXPORT igraph_error_t igraph_pagerank(const igraph_t *graph, igraph_pagerank_algo_t algo, igraph_vector_t *vector, - igraph_real_t *value, const igraph_vs_t vids, + igraph_real_t *value, igraph_vs_t vids, igraph_bool_t directed, igraph_real_t damping, const igraph_vector_t *weights, igraph_arpack_options_t *options); IGRAPH_EXPORT igraph_error_t igraph_personalized_pagerank(const igraph_t *graph, igraph_pagerank_algo_t algo, igraph_vector_t *vector, - igraph_real_t *value, const igraph_vs_t vids, + igraph_real_t *value, igraph_vs_t vids, igraph_bool_t directed, igraph_real_t damping, const igraph_vector_t *reset, const igraph_vector_t *weights, igraph_arpack_options_t *options); IGRAPH_EXPORT igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph, igraph_pagerank_algo_t algo, igraph_vector_t *vector, - igraph_real_t *value, const igraph_vs_t vids, + igraph_real_t *value, igraph_vs_t vids, igraph_bool_t directed, igraph_real_t damping, igraph_vs_t reset_vids, const igraph_vector_t *weights, igraph_arpack_options_t *options); IGRAPH_EXPORT igraph_error_t igraph_eigenvector_centrality(const igraph_t *graph, igraph_vector_t *vector, - igraph_real_t *value, - igraph_bool_t directed, igraph_bool_t scale, - const igraph_vector_t *weights, - igraph_arpack_options_t *options); + igraph_real_t *value, + igraph_neimode_t mode, + const igraph_vector_t *weights, + igraph_arpack_options_t *options); IGRAPH_EXPORT igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, igraph_vector_t *hub_vector, - igraph_vector_t *authority_vector, - igraph_real_t *value, igraph_bool_t scale, - const igraph_vector_t *weights, - igraph_arpack_options_t *options); + igraph_vector_t *authority_vector, + igraph_real_t *value, + const igraph_vector_t *weights, + igraph_arpack_options_t *options); IGRAPH_EXPORT igraph_error_t igraph_constraint(const igraph_t *graph, igraph_vector_t *res, igraph_vs_t vids, const igraph_vector_t *weights); @@ -139,14 +134,14 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_centralization(const igr igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_vector_t *res, - igraph_neimode_t mode, igraph_bool_t loops, + igraph_neimode_t mode, igraph_loops_t loops, igraph_real_t *centralization, igraph_real_t *theoretical_max, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_centralization_degree_tmax(const igraph_t *graph, igraph_integer_t nodes, igraph_neimode_t mode, - igraph_bool_t loops, + igraph_loops_t loops, igraph_real_t *res); IGRAPH_EXPORT igraph_error_t igraph_centralization_betweenness(const igraph_t *graph, @@ -171,34 +166,19 @@ IGRAPH_EXPORT igraph_error_t igraph_centralization_closeness_tmax(const igraph_t igraph_neimode_t mode, igraph_real_t *res); -IGRAPH_EXPORT igraph_error_t igraph_centralization_eigenvector_centrality( - const igraph_t *graph, - igraph_vector_t *vector, - igraph_real_t *value, - igraph_bool_t directed, - igraph_bool_t scale, - igraph_arpack_options_t *options, - igraph_real_t *centralization, - igraph_real_t *theoretical_max, - igraph_bool_t normalized); -IGRAPH_EXPORT igraph_error_t igraph_centralization_eigenvector_centrality_tmax( - const igraph_t *graph, - igraph_integer_t nodes, - igraph_bool_t directed, - igraph_bool_t scale, - igraph_real_t *res); - -/* Deprecated functions: */ - -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_hub_score(const igraph_t *graph, igraph_vector_t *vector, - igraph_real_t *value, igraph_bool_t scale, - const igraph_vector_t *weights, - igraph_arpack_options_t *options); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_authority_score(const igraph_t *graph, igraph_vector_t *vector, - igraph_real_t *value, igraph_bool_t scale, - const igraph_vector_t *weights, - igraph_arpack_options_t *options); - -__END_DECLS +IGRAPH_EXPORT igraph_error_t igraph_centralization_eigenvector_centrality(const igraph_t *graph, + igraph_vector_t *vector, + igraph_real_t *value, + igraph_neimode_t mode, + igraph_arpack_options_t *options, + igraph_real_t *centralization, + igraph_real_t *theoretical_max, + igraph_bool_t normalized); +IGRAPH_EXPORT igraph_error_t igraph_centralization_eigenvector_centrality_tmax(const igraph_t *graph, + igraph_integer_t nodes, + igraph_neimode_t mode, + igraph_real_t *res); + +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_cliques.h b/src/vendor/cigraph/include/igraph_cliques.h index 141dd261f23..019f6ffb1cf 100644 --- a/src/vendor/cigraph/include/igraph_cliques.h +++ b/src/vendor/cigraph/include/igraph_cliques.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_CLIQUES_H @@ -30,7 +25,7 @@ #include "igraph_datatype.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Cliques, maximal independent vertex sets */ @@ -111,6 +106,6 @@ IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_callback(const igraph_t *gra igraph_integer_t min_size, igraph_integer_t max_size); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_cocitation.h b/src/vendor/cigraph/include/igraph_cocitation.h index 4dfd406ab94..23baa8607b1 100644 --- a/src/vendor/cigraph/include/igraph_cocitation.h +++ b/src/vendor/cigraph/include/igraph_cocitation.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_COCITATION_H @@ -31,37 +26,37 @@ #include "igraph_datatype.h" #include "igraph_iterators.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Cocitation and other similarity measures */ /* -------------------------------------------------- */ IGRAPH_EXPORT igraph_error_t igraph_cocitation(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t vids); + igraph_vs_t vids); IGRAPH_EXPORT igraph_error_t igraph_bibcoupling(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t vids); + 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); + igraph_vs_t vit_from, 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_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); + igraph_vs_t vit_from, 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, - const igraph_es_t es, igraph_neimode_t mode, igraph_bool_t loops); + igraph_es_t es, igraph_neimode_t mode, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_similarity_inverse_log_weighted(const igraph_t *graph, - igraph_matrix_t *res, const igraph_vs_t vids, + igraph_matrix_t *res, igraph_vs_t vids, igraph_neimode_t mode); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_cohesive_blocks.h b/src/vendor/cigraph/include/igraph_cohesive_blocks.h index a52cf68f733..372a4a476e3 100644 --- a/src/vendor/cigraph/include/igraph_cohesive_blocks.h +++ b/src/vendor/cigraph/include/igraph_cohesive_blocks.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_COHESIVE_BLOCKS_H @@ -30,7 +25,7 @@ #include "igraph_vector.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, igraph_vector_int_list_t *blocks, @@ -38,6 +33,6 @@ IGRAPH_EXPORT igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, igraph_vector_int_t *parent, igraph_t *block_tree); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_coloring.h b/src/vendor/cigraph/include/igraph_coloring.h index 845cd77d359..c64423b3cca 100644 --- a/src/vendor/cigraph/include/igraph_coloring.h +++ b/src/vendor/cigraph/include/igraph_coloring.h @@ -1,21 +1,19 @@ /* - Heuristic graph coloring algorithms. - Copyright (C) 2017 Szabolcs Horvat - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + IGraph library. + Copyright (C) 2017-2025 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 . */ #ifndef IGRAPH_COLORING_H @@ -25,7 +23,7 @@ #include "igraph_datatype.h" #include "igraph_error.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \typedef igraph_coloring_greedy_t @@ -50,6 +48,10 @@ typedef enum { IGRAPH_EXPORT igraph_error_t igraph_vertex_coloring_greedy(const igraph_t *graph, igraph_vector_int_t *colors, igraph_coloring_greedy_t heuristic); -__END_DECLS +IGRAPH_EXPORT igraph_error_t igraph_is_vertex_coloring(const igraph_t *graph, const igraph_vector_int_t *types, igraph_bool_t *res); +IGRAPH_EXPORT igraph_error_t igraph_is_bipartite_coloring(const igraph_t *graph, const igraph_vector_bool_t *types, igraph_bool_t *res, igraph_neimode_t *mode); +IGRAPH_EXPORT igraph_error_t igraph_is_edge_coloring(const igraph_t *graph, const igraph_vector_int_t *types, igraph_bool_t *res); + +IGRAPH_END_C_DECLS #endif /* IGRAPH_COLORING_H */ diff --git a/src/vendor/cigraph/include/igraph_community.h b/src/vendor/cigraph/include/igraph_community.h index c38cef130b2..1e8be0aa9f3 100644 --- a/src/vendor/cigraph/include/igraph_community.h +++ b/src/vendor/cigraph/include/igraph_community.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_COMMUNITY_H @@ -33,7 +28,7 @@ #include "igraph_types.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* K-Cores and K-Truss */ @@ -53,9 +48,10 @@ IGRAPH_EXPORT igraph_error_t igraph_trussness( /* TODO: */ IGRAPH_EXPORT igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, - igraph_real_t *modularity, - igraph_vector_int_t *membership, - const igraph_vector_t *weights); + const igraph_vector_t *weights, + igraph_real_t resolution, + igraph_real_t *modularity, + igraph_vector_int_t *membership); IGRAPH_EXPORT igraph_error_t igraph_community_spinglass(const igraph_t *graph, const igraph_vector_t *weights, @@ -79,8 +75,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); @@ -92,9 +88,9 @@ IGRAPH_EXPORT igraph_error_t igraph_community_walktrap(const igraph_t *graph, igraph_vector_t *modularity, igraph_vector_int_t *membership); -IGRAPH_EXPORT igraph_error_t igraph_community_infomap(const igraph_t * graph, - const igraph_vector_t *e_weights, - const igraph_vector_t *v_weights, +IGRAPH_EXPORT igraph_error_t igraph_community_infomap(const igraph_t *graph, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_weights, igraph_integer_t nb_trials, igraph_vector_int_t *membership, igraph_real_t *codelength); @@ -107,9 +103,10 @@ IGRAPH_EXPORT igraph_error_t igraph_community_edge_betweenness(const igraph_t *g igraph_vector_t *modularity, igraph_vector_int_t *membership, igraph_bool_t directed, - const igraph_vector_t *weights); + const igraph_vector_t *weights, + const igraph_vector_t *lengths); IGRAPH_EXPORT igraph_error_t igraph_community_eb_get_merges(const igraph_t *graph, - const igraph_bool_t directed, + igraph_bool_t directed, const igraph_vector_int_t *edges, const igraph_vector_t *weights, igraph_matrix_int_t *merges, @@ -142,13 +139,13 @@ IGRAPH_EXPORT igraph_error_t igraph_community_voronoi( IGRAPH_EXPORT igraph_error_t igraph_modularity(const igraph_t *graph, const igraph_vector_int_t *membership, const igraph_vector_t *weights, - const igraph_real_t resolution, - const igraph_bool_t directed, + igraph_real_t resolution, + igraph_bool_t directed, igraph_real_t *modularity); IGRAPH_EXPORT igraph_error_t igraph_modularity_matrix(const igraph_t *graph, const igraph_vector_t *weights, - const igraph_real_t resolution, + igraph_real_t resolution, igraph_matrix_t *modmat, igraph_bool_t directed); @@ -209,7 +206,7 @@ IGRAPH_EXPORT igraph_error_t igraph_community_leading_eigenvector(const igraph_t igraph_bool_t start, igraph_vector_t *eigenvalues, igraph_vector_list_t *eigenvectors, - igraph_vector_t *history, + igraph_vector_int_t *history, igraph_community_leading_eigenvector_callback_t *callback, void *callback_extra); @@ -217,30 +214,34 @@ IGRAPH_EXPORT igraph_error_t igraph_community_fluid_communities(const igraph_t * igraph_integer_t no_of_communities, igraph_vector_int_t *membership); + IGRAPH_EXPORT igraph_error_t igraph_community_label_propagation(const igraph_t *graph, igraph_vector_int_t *membership, igraph_neimode_t mode, const igraph_vector_t *weights, const igraph_vector_int_t *initial, - const igraph_vector_bool_t *fixed); + const igraph_vector_bool_t *fixed, + igraph_lpa_variant_t variant); IGRAPH_EXPORT igraph_error_t igraph_community_multilevel(const igraph_t *graph, const igraph_vector_t *weights, - const igraph_real_t resolution, + igraph_real_t resolution, igraph_vector_int_t *membership, igraph_matrix_int_t *memberships, igraph_vector_t *modularity); -IGRAPH_EXPORT igraph_error_t igraph_community_leiden(const igraph_t *graph, - const igraph_vector_t *edge_weights, - const igraph_vector_t *node_weights, - const igraph_real_t resolution_parameter, - const igraph_real_t beta, - const igraph_bool_t start, - const igraph_integer_t n_iterations, - igraph_vector_int_t *membership, - igraph_integer_t *nb_clusters, - igraph_real_t *quality); +IGRAPH_EXPORT igraph_error_t igraph_community_leiden( + const igraph_t *graph, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_out_weights, + const igraph_vector_t *vertex_in_weights, + igraph_real_t resolution, + igraph_real_t beta, + igraph_bool_t start, + igraph_integer_t n_iterations, + igraph_vector_int_t *membership, + igraph_integer_t *nb_clusters, igraph_real_t *quality); + /* -------------------------------------------------- */ /* Community Structure Comparison */ /* -------------------------------------------------- */ @@ -254,6 +255,6 @@ IGRAPH_EXPORT igraph_error_t igraph_split_join_distance(const igraph_vector_int_ igraph_integer_t* distance12, igraph_integer_t* distance21); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_complex.h b/src/vendor/cigraph/include/igraph_complex.h index 6288d6576ad..4295bc8dda6 100644 --- a/src/vendor/cigraph/include/igraph_complex.h +++ b/src/vendor/cigraph/include/igraph_complex.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_COMPLEX_H @@ -27,7 +22,7 @@ #include "igraph_decls.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef struct igraph_complex_t { igraph_real_t dat[2]; @@ -40,13 +35,9 @@ typedef struct igraph_complex_t { IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_complex_t igraph_complex(igraph_real_t x, igraph_real_t y); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_complex_t igraph_complex_polar(igraph_real_t r, igraph_real_t theta); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_bool_t igraph_complex_eq_tol(igraph_complex_t z1, - igraph_complex_t z2, - igraph_real_t tol); - IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_bool_t igraph_complex_almost_equals(igraph_complex_t z1, - igraph_complex_t z2, - igraph_real_t eps); + igraph_complex_t z2, + igraph_real_t eps); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_real_t igraph_complex_arg(igraph_complex_t z); @@ -108,6 +99,6 @@ IGRAPH_EXPORT int igraph_complex_printf_aligned(int width, igraph_complex_t val) IGRAPH_EXPORT int igraph_complex_fprintf_aligned(FILE *file, int width, igraph_complex_t val); IGRAPH_EXPORT int igraph_complex_snprintf(char *str, size_t size, igraph_complex_t val); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_components.h b/src/vendor/cigraph/include/igraph_components.h index c00c4f675b0..79fffa8dc33 100644 --- a/src/vendor/cigraph/include/igraph_components.h +++ b/src/vendor/cigraph/include/igraph_components.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_COMPONENTS_H @@ -33,18 +28,13 @@ #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 +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Components */ /* -------------------------------------------------- */ -/* Deprecated alias to igraph_connected_components; will be removed in 0.11 */ -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_clusters(const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no, - igraph_connectedness_t mode); IGRAPH_EXPORT igraph_error_t igraph_connected_components(const igraph_t *graph, igraph_vector_int_t *membership, igraph_vector_int_t *csize, igraph_integer_t *no, igraph_connectedness_t mode); @@ -79,10 +69,6 @@ IGRAPH_EXPORT igraph_error_t igraph_edgelist_percolation( igraph_vector_int_t *giant_size, igraph_vector_int_t *vertex_count); -/* 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 +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_config.h.in b/src/vendor/cigraph/include/igraph_config.h.in index 99e6feeecf9..697dbfebc37 100644 --- a/src/vendor/cigraph/include/igraph_config.h.in +++ b/src/vendor/cigraph/include/igraph_config.h.in @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2011-2022 The igraph development team + Copyright (C) 2011-2025 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 @@ -14,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_CONFIG_H @@ -25,7 +21,7 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \define IGRAPH_INTEGER_SIZE @@ -50,6 +46,6 @@ __BEGIN_DECLS */ #define IGRAPH_BOOL_TYPE bool -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_constants.h b/src/vendor/cigraph/include/igraph_constants.h index 33f5e6b6e26..2205ee1fbdc 100644 --- a/src/vendor/cigraph/include/igraph_constants.h +++ b/src/vendor/cigraph/include/igraph_constants.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,25 +13,23 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_CONSTANTS_H #define IGRAPH_CONSTANTS_H -#include "igraph_config.h" #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Constants */ /* -------------------------------------------------- */ -typedef enum { IGRAPH_UNDIRECTED = 0, IGRAPH_DIRECTED = 1 } igraph_i_directed_t; +/* These constants are meant to be used for sake of readability */ +enum { IGRAPH_UNDIRECTED = 0, IGRAPH_DIRECTED = 1 }; +enum { IGRAPH_NO_MULTIPLE = 0, IGRAPH_MULTIPLE = 1 }; /* Note for the enum below: yes, IGRAPH_LOOPS_TWICE is 1, and IGRAPH_LOOPS_ONCE * is 2. This is intentional, for the sake of backwards compatibility with @@ -41,12 +37,8 @@ typedef enum { IGRAPH_UNDIRECTED = 0, IGRAPH_DIRECTED = 1 } igraph_i_directed_t; * IGRAPH_LOOPS_TWICE */ typedef enum { IGRAPH_NO_LOOPS = 0, IGRAPH_LOOPS = 1, IGRAPH_LOOPS_TWICE = 1, IGRAPH_LOOPS_ONCE = 2 } igraph_loops_t; -typedef enum { IGRAPH_NO_MULTIPLE = 0, IGRAPH_MULTIPLE = 1 } igraph_multiple_t; - typedef enum { IGRAPH_ASCENDING = 0, IGRAPH_DESCENDING = 1 } igraph_order_t; -typedef enum { IGRAPH_MINIMUM = 0, IGRAPH_MAXIMUM = 1 } igraph_optimal_t; - /* Do not renumber the following values! Some internal code treats them as bitmasks * and assumes that IGRAPH_ALL == IGRAPH_IN | IGRAPH_OUT and IGRAPH_IN & IGRAPH_OUT == 0. */ typedef enum { IGRAPH_OUT = 1, IGRAPH_IN = 2, IGRAPH_ALL = 3 } igraph_neimode_t; @@ -82,10 +74,6 @@ typedef enum { IGRAPH_TREE_OUT = 0, IGRAPH_TREE_IN, IGRAPH_TREE_UNDIRECTED } igraph_tree_mode_t; -typedef enum { IGRAPH_ERDOS_RENYI_GNP = 0, - IGRAPH_ERDOS_RENYI_GNM - } igraph_erdos_renyi_t; - typedef enum { IGRAPH_GET_ADJACENCY_UPPER = 0, IGRAPH_GET_ADJACENCY_LOWER, IGRAPH_GET_ADJACENCY_BOTH @@ -96,11 +84,6 @@ typedef enum { IGRAPH_DEGSEQ_CONFIGURATION = 0, /* Configuration model, allo IGRAPH_DEGSEQ_FAST_HEUR_SIMPLE, /* Fast heuristic, generates simple graphs */ IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE, /* Configuration model, generates simple graphs */ IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE, /* Edge-switching MCMC, generates simple graphs */ - - /* Deprecated, kept for backwards compatibility: */ - IGRAPH_DEGSEQ_SIMPLE IGRAPH_DEPRECATED_ENUMVAL = IGRAPH_DEGSEQ_CONFIGURATION, - IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE IGRAPH_DEPRECATED_ENUMVAL = IGRAPH_DEGSEQ_FAST_HEUR_SIMPLE, - IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE_UNIFORM IGRAPH_DEPRECATED_ENUMVAL = IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE } igraph_degseq_t; typedef enum { IGRAPH_REALIZE_DEGSEQ_SMALLEST = 0, @@ -112,17 +95,6 @@ typedef enum { IGRAPH_RANDOM_TREE_PRUFER = 0, IGRAPH_RANDOM_TREE_LERW } igraph_random_tree_t; -typedef enum { IGRAPH_FILEFORMAT_EDGELIST = 0, - IGRAPH_FILEFORMAT_NCOL, - IGRAPH_FILEFORMAT_PAJEK, - IGRAPH_FILEFORMAT_LGL, - IGRAPH_FILEFORMAT_GRAPHML - } igraph_fileformat_type_t; - -typedef enum { IGRAPH_REWIRING_SIMPLE = 0, - IGRAPH_REWIRING_SIMPLE_LOOPS - } igraph_rewiring_t; - typedef enum { IGRAPH_EDGEORDER_ID = 0, IGRAPH_EDGEORDER_FROM, IGRAPH_EDGEORDER_TO @@ -149,10 +121,6 @@ typedef enum { IGRAPH_SPINCOMM_UPDATE_SIMPLE = 0, IGRAPH_SPINCOMM_UPDATE_CONFIG } igraph_spincomm_update_t; -typedef enum { IGRAPH_DONT_SIMPLIFY = 0, - IGRAPH_SIMPLIFY - } igraph_lazy_adlist_simplify_t; - typedef enum { IGRAPH_TRANSITIVITY_NAN = 0, IGRAPH_TRANSITIVITY_ZERO } igraph_transitivity_mode_t; @@ -192,11 +160,6 @@ typedef enum { IGRAPH_SUBGRAPH_AUTO = 0, IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH } igraph_subgraph_implementation_t; -typedef enum { IGRAPH_IMITATE_AUGMENTED = 0, - IGRAPH_IMITATE_BLIND, - IGRAPH_IMITATE_CONTRACTED - } igraph_imitate_algorithm_t; - typedef enum { IGRAPH_LAYOUT_GRID = 0, IGRAPH_LAYOUT_NOGRID, IGRAPH_LAYOUT_AUTOGRID @@ -220,12 +183,34 @@ typedef enum { IGRAPH_ROW_MAJOR = 0, IGRAPH_COLUMN_MAJOR = 1 } igraph_matrix_storage_t; +typedef enum { IGRAPH_MST_AUTOMATIC = 0, + IGRAPH_MST_UNWEIGHTED, + IGRAPH_MST_PRIM, + IGRAPH_MST_KRUSKAL + } igraph_mst_algorithm_t; + typedef enum { IGRAPH_PRODUCT_CARTESIAN = 0, IGRAPH_PRODUCT_LEXICOGRAPHIC, IGRAPH_PRODUCT_STRONG, IGRAPH_PRODUCT_TENSOR, + IGRAPH_PRODUCT_MODULAR } igraph_product_t; -__END_DECLS +/** + * \typedef igraph_lpa_variant_t + * \brief Label propagation algorithm variants of implementation + * + * Variants to run the label propagation algorithm. + * \enumval IGRAPH_LPA_DOMINANCE Check for dominance of all nodes after each iteration + * \enumval IGRAPH_LPA_RETENTION Keep current label if among dominant labels, only check if labels changed + * \enumval IGRAPH_LPA_FAST Sample from dominant labels, only check neighbors + */ +typedef enum { + IGRAPH_LPA_DOMINANCE = 0, // Sample from dominant labels, check for dominance after each iteration + IGRAPH_LPA_RETENTION, // Keep current label if among dominant labels, only check if labels changed + IGRAPH_LPA_FAST // Sample from dominant labels, only check neighbors +} igraph_lpa_variant_t; + +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_constructors.h b/src/vendor/cigraph/include/igraph_constructors.h index 895eb309c87..c42907523e4 100644 --- a/src/vendor/cigraph/include/igraph_constructors.h +++ b/src/vendor/cigraph/include/igraph_constructors.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_CONSTRUCTORS_H @@ -33,7 +28,7 @@ #include "igraph_graphicality.h" #include "igraph_sparsemat.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Constructors, deterministic */ @@ -57,8 +52,6 @@ IGRAPH_EXPORT igraph_error_t igraph_wheel(igraph_t *graph, igraph_integer_t n, i igraph_integer_t center); IGRAPH_EXPORT igraph_error_t igraph_hypercube(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_lattice(igraph_t *graph, const igraph_vector_int_t *dimvector, igraph_integer_t nei, - igraph_bool_t directed, igraph_bool_t mutual, igraph_bool_t circular); IGRAPH_EXPORT igraph_error_t igraph_square_lattice(igraph_t *graph, const igraph_vector_int_t *dimvector, igraph_integer_t nei, igraph_bool_t directed, igraph_bool_t mutual, const igraph_vector_bool_t *circular); IGRAPH_EXPORT igraph_error_t igraph_ring(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, @@ -69,8 +62,6 @@ IGRAPH_EXPORT igraph_error_t igraph_path_graph( IGRAPH_EXPORT igraph_error_t igraph_cycle_graph( igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, igraph_bool_t mutual); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_tree(igraph_t *graph, igraph_integer_t n, igraph_integer_t children, - igraph_tree_mode_t type); IGRAPH_EXPORT igraph_error_t igraph_kary_tree(igraph_t *graph, igraph_integer_t n, igraph_integer_t children, igraph_tree_mode_t type); IGRAPH_EXPORT igraph_error_t igraph_symmetric_tree(igraph_t *graph, const igraph_vector_int_t *branches, @@ -96,19 +87,20 @@ IGRAPH_EXPORT igraph_error_t igraph_circulant(igraph_t *graph, igraph_integer_t IGRAPH_EXPORT igraph_error_t igraph_generalized_petersen(igraph_t *graph, igraph_integer_t n, igraph_integer_t k); IGRAPH_EXPORT igraph_error_t igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_t n); IGRAPH_EXPORT igraph_error_t igraph_famous(igraph_t *graph, const char *name); -IGRAPH_EXPORT igraph_error_t igraph_lcf_vector(igraph_t *graph, igraph_integer_t n, - const igraph_vector_int_t *shifts, - igraph_integer_t repeats); -IGRAPH_EXPORT igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, ...); +IGRAPH_EXPORT igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, + const igraph_vector_int_t *shifts, + igraph_integer_t repeats); +IGRAPH_EXPORT igraph_error_t igraph_lcf_small(igraph_t *graph, igraph_integer_t n, ...); IGRAPH_EXPORT igraph_error_t igraph_realize_degree_sequence(igraph_t *graph, const igraph_vector_int_t *outdeg, const igraph_vector_int_t *indeg, igraph_edge_type_sw_t allowed_edge_types, igraph_realize_degseq_t method); IGRAPH_EXPORT igraph_error_t igraph_triangular_lattice(igraph_t *graph, const igraph_vector_int_t *dims, igraph_bool_t directed, igraph_bool_t mutual); IGRAPH_EXPORT igraph_error_t igraph_hexagonal_lattice(igraph_t *graph, const igraph_vector_int_t *dims, igraph_bool_t directed, igraph_bool_t mutual); +IGRAPH_EXPORT igraph_error_t igraph_realize_bipartite_degree_sequence(igraph_t *graph, const igraph_vector_int_t *deg1, const igraph_vector_int_t *deg2, igraph_edge_type_sw_t allowed_edge_types, igraph_realize_degseq_t method); IGRAPH_EXPORT igraph_error_t igraph_realize_bipartite_degree_sequence(igraph_t *graph, const igraph_vector_int_t *deg1, const igraph_vector_int_t *deg2, const igraph_edge_type_sw_t allowed_edge_types, const igraph_realize_degseq_t method); IGRAPH_EXPORT igraph_error_t igraph_mycielski_graph(igraph_t *graph, igraph_integer_t k); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_conversion.h b/src/vendor/cigraph/include/igraph_conversion.h index d47d7f677d9..8915dc9d69f 100644 --- a/src/vendor/cigraph/include/igraph_conversion.h +++ b/src/vendor/cigraph/include/igraph_conversion.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_CONVERSION_H @@ -33,7 +28,7 @@ #include "igraph_sparsemat.h" #include "igraph_attributes.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Conversion */ @@ -58,14 +53,6 @@ IGRAPH_EXPORT igraph_error_t igraph_get_stochastic_sparse( const igraph_vector_t *weights ); -/* Deprecated, will be removed in 0.11. Use igraph_get_adjacency_sparse() instead, paying attention to differences. */ -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_get_sparsemat(const igraph_t *graph, igraph_sparsemat_t *res); - -/* Deprecated, will be removed in 0.11. Use igraph_get_stochastic_sparse() instead, paying attention to differences. */ -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_get_stochastic_sparsemat(const igraph_t *graph, - igraph_sparsemat_t *res, - igraph_bool_t column_wise); - IGRAPH_EXPORT igraph_error_t igraph_get_edgelist(const igraph_t *graph, igraph_vector_int_t *res, igraph_bool_t bycol); IGRAPH_EXPORT igraph_error_t igraph_to_directed(igraph_t *graph, @@ -75,6 +62,6 @@ IGRAPH_EXPORT igraph_error_t igraph_to_undirected(igraph_t *graph, const igraph_attribute_combination_t *edge_comb); IGRAPH_EXPORT igraph_error_t igraph_to_prufer(const igraph_t *graph, igraph_vector_int_t *prufer); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_cycles.h b/src/vendor/cigraph/include/igraph_cycles.h index 2f38aa8d147..94d4d7568ec 100644 --- a/src/vendor/cigraph/include/igraph_cycles.h +++ b/src/vendor/cigraph/include/igraph_cycles.h @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2022-2024 The igraph development team + Copyright (C) 2022-2025 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 @@ -13,9 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + along with this program. If not, see . */ #ifndef IGRAPH_CYCLES_H @@ -28,7 +26,20 @@ #include "igraph_types.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS + +/* -------------------------------------------------- */ +/* Directed acyclic graphs */ +/* -------------------------------------------------- */ + +IGRAPH_EXPORT igraph_error_t igraph_topological_sorting( + const igraph_t *graph, igraph_vector_int_t *res, igraph_neimode_t mode); + +IGRAPH_EXPORT igraph_error_t igraph_is_dag(const igraph_t *graph, igraph_bool_t *res); + +/* -------------------------------------------------- */ +/* Cycle bases */ +/* -------------------------------------------------- */ IGRAPH_EXPORT igraph_error_t igraph_fundamental_cycles( const igraph_t *graph, @@ -84,6 +95,6 @@ IGRAPH_EXPORT igraph_error_t igraph_simple_cycles( igraph_integer_t min_cycle_length, igraph_integer_t max_cycle_length); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_datatype.h b/src/vendor/cigraph/include/igraph_datatype.h index c0ee080e864..50617599c89 100644 --- a/src/vendor/cigraph/include/igraph_datatype.h +++ b/src/vendor/cigraph/include/igraph_datatype.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_DATATYPE_H @@ -28,7 +23,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS struct igraph_i_property_cache_t; typedef struct igraph_i_property_cache_t igraph_i_property_cache_t; @@ -107,7 +102,7 @@ typedef enum { * The storage requirements for a graph with \c |V| vertices * and \c |E| edges is \c O(|E|+|V|). */ -typedef struct igraph_s { +typedef struct { igraph_integer_t n; igraph_bool_t directed; igraph_vector_int_t from; @@ -122,6 +117,6 @@ typedef struct igraph_s { IGRAPH_EXPORT void igraph_invalidate_cache(const igraph_t* graph); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_decls.h b/src/vendor/cigraph/include/igraph_decls.h index 3ce51ec98f0..ee39fed2c55 100644 --- a/src/vendor/cigraph/include/igraph_decls.h +++ b/src/vendor/cigraph/include/igraph_decls.h @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2016-2024 The igraph development team + Copyright (C) 2016-2025 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 @@ -13,19 +13,17 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + along with this program. If not, see . */ -#undef __BEGIN_DECLS -#undef __END_DECLS +#undef IGRAPH_BEGIN_C_DECLS +#undef IGRAPH_END_C_DECLS #ifdef __cplusplus - #define __BEGIN_DECLS extern "C" { - #define __END_DECLS } + #define IGRAPH_BEGIN_C_DECLS extern "C" { + #define IGRAPH_END_C_DECLS } #else - #define __BEGIN_DECLS /* empty */ - #define __END_DECLS /* empty */ + #define IGRAPH_BEGIN_C_DECLS /* empty */ + #define IGRAPH_END_C_DECLS /* empty */ #endif /* This is to eliminate gcc warnings about unused parameters */ diff --git a/src/vendor/cigraph/include/igraph_dqueue.h b/src/vendor/cigraph/include/igraph_dqueue.h index 53c8b0e4ba7..571152eaad8 100644 --- a/src/vendor/cigraph/include/igraph_dqueue.h +++ b/src/vendor/cigraph/include/igraph_dqueue.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_DQUEUE_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* double ended queue, very useful */ @@ -66,6 +61,6 @@ __BEGIN_DECLS do { IGRAPH_CHECK(igraph_dqueue_int_init(q, capacity)); \ IGRAPH_FINALLY(igraph_dqueue_int_destroy, q); } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_dqueue_pmt.h b/src/vendor/cigraph/include/igraph_dqueue_pmt.h index 1db6cd64fdd..6f2224b9472 100644 --- a/src/vendor/cigraph/include/igraph_dqueue_pmt.h +++ b/src/vendor/cigraph/include/igraph_dqueue_pmt.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ /** @@ -47,4 +42,3 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, push)(TYPE(igraph_dqueue)* IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, print)(const TYPE(igraph_dqueue)* q); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, fprint)(const TYPE(igraph_dqueue)* q, FILE *file); IGRAPH_EXPORT BASE FUNCTION(igraph_dqueue, get)(const TYPE(igraph_dqueue) *q, igraph_integer_t idx); -IGRAPH_DEPRECATED IGRAPH_EXPORT BASE FUNCTION(igraph_dqueue, e)(const TYPE(igraph_dqueue) *q, igraph_integer_t idx); diff --git a/src/vendor/cigraph/include/igraph_eigen.h b/src/vendor/cigraph/include/igraph_eigen.h index 122eeb8a3a8..935200cd4b8 100644 --- a/src/vendor/cigraph/include/igraph_eigen.h +++ b/src/vendor/cigraph/include/igraph_eigen.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_EIGEN_H @@ -30,7 +25,7 @@ #include "igraph_lapack.h" #include "igraph_sparsemat.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef enum { IGRAPH_EIGEN_AUTO = 0, IGRAPH_EIGEN_LAPACK, @@ -96,6 +91,6 @@ IGRAPH_EXPORT igraph_error_t igraph_eigen_adjacency(const igraph_t *graph, igraph_vector_complex_t *cmplxvalues, igraph_matrix_complex_t *cmplxvectors); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_embedding.h b/src/vendor/cigraph/include/igraph_embedding.h index 2462b010c88..7312b584c4f 100644 --- a/src/vendor/cigraph/include/igraph_embedding.h +++ b/src/vendor/cigraph/include/igraph_embedding.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2013 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2013-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_EMBEDDING_H @@ -30,7 +25,7 @@ #include "igraph_arpack.h" #include "igraph_eigen.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_adjacency_spectral_embedding(const igraph_t *graph, igraph_integer_t no, @@ -63,6 +58,6 @@ IGRAPH_EXPORT igraph_error_t igraph_laplacian_spectral_embedding(const igraph_t IGRAPH_EXPORT igraph_error_t igraph_dim_select(const igraph_vector_t *sv, igraph_integer_t *dim); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_epidemics.h b/src/vendor/cigraph/include/igraph_epidemics.h index a13f8cbcd0f..c86efeea010 100644 --- a/src/vendor/cigraph/include/igraph_epidemics.h +++ b/src/vendor/cigraph/include/igraph_epidemics.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2014 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2014-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_EPIDEMICS_H @@ -30,7 +25,7 @@ #include "igraph_vector.h" #include "igraph_vector_ptr.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \struct igraph_sir_t @@ -63,6 +58,6 @@ IGRAPH_EXPORT igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t bet igraph_real_t gamma, igraph_integer_t no_sim, igraph_vector_ptr_t *result); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_error.h b/src/vendor/cigraph/include/igraph_error.h index 430aa99c667..4ccbb44e773 100644 --- a/src/vendor/cigraph/include/igraph_error.h +++ b/src/vendor/cigraph/include/igraph_error.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2003-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2003-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_ERROR_H @@ -29,7 +24,7 @@ #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* This file contains the igraph error handling. * Most bits are taken literally from the GSL library (with the GSL_ @@ -254,61 +249,22 @@ __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. * \enumval IGRAPH_UNIMPLEMENTED Attempted to call an unimplemented or * disabled (at compile-time) function. * \enumval IGRAPH_DIVERGED A numeric algorithm failed to converge. - * \enumval IGRAPH_ARPACK_PROD Matrix-vector product failed (not used any more). - * \enumval IGRAPH_ARPACK_NPOS N must be positive. - * \enumval IGRAPH_ARPACK_NEVNPOS NEV must be positive. - * \enumval IGRAPH_ARPACK_NCVSMALL NCV must be bigger. - * \enumval IGRAPH_ARPACK_NONPOSI Maximum number of iterations should be positive. - * \enumval IGRAPH_ARPACK_WHICHINV Invalid WHICH parameter. - * \enumval IGRAPH_ARPACK_BMATINV Invalid BMAT parameter. - * \enumval IGRAPH_ARPACK_WORKLSMALL WORKL is too small. - * \enumval IGRAPH_ARPACK_TRIDERR LAPACK error in tridiagonal eigenvalue calculation. - * \enumval IGRAPH_ARPACK_ZEROSTART Starting vector is zero. - * \enumval IGRAPH_ARPACK_MODEINV MODE is invalid. - * \enumval IGRAPH_ARPACK_MODEBMAT MODE and BMAT are not compatible. - * \enumval IGRAPH_ARPACK_ISHIFT ISHIFT must be 0 or 1. - * \enumval IGRAPH_ARPACK_NEVBE NEV and WHICH='BE' are incompatible. - * \enumval IGRAPH_ARPACK_NOFACT Could not build an Arnoldi factorization. - * \enumval IGRAPH_ARPACK_FAILED No eigenvalues to sufficient accuracy. - * \enumval IGRAPH_ARPACK_HOWMNY HOWMNY is invalid. - * \enumval IGRAPH_ARPACK_HOWMNYS HOWMNY='S' is not implemented. - * \enumval IGRAPH_ARPACK_EVDIFF Different number of converged Ritz values. - * \enumval IGRAPH_ARPACK_SHUR Error from calculation of a real Schur form. - * \enumval IGRAPH_ARPACK_LAPACK LAPACK (dtrevc) error for calculating eigenvectors. - * \enumval IGRAPH_ARPACK_UNKNOWN Unknown ARPACK error. + * \enumval IGRAPH_ARPACK An error happened inside a calculation implemented + * in ARPACK. The calculation involved is most likely an eigenvector-related + * calculation. * \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). - * \enumval IGRAPH_GLP_ENODFS GLPK error (GLP_ENODFS). - * \enumval IGRAPH_GLP_EFAIL GLPK error (GLP_EFAIL). - * \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. * \enumval IGRAPH_EUNDERFLOW Integer or double underflow. * \enumval IGRAPH_ERWSTUCK Random walk got stuck. * \enumval IGRAPH_ERANGE Maximum vertex or edge count exceeded. @@ -322,57 +278,35 @@ 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, IGRAPH_INTERRUPTED = 13, IGRAPH_DIVERGED = 14, - IGRAPH_ARPACK_PROD = 15, /* unused, reserved */ - IGRAPH_ARPACK_NPOS = 16, - IGRAPH_ARPACK_NEVNPOS = 17, - IGRAPH_ARPACK_NCVSMALL = 18, - IGRAPH_ARPACK_NONPOSI = 19, - IGRAPH_ARPACK_WHICHINV = 20, - IGRAPH_ARPACK_BMATINV = 21, - IGRAPH_ARPACK_WORKLSMALL = 22, - IGRAPH_ARPACK_TRIDERR = 23, - IGRAPH_ARPACK_ZEROSTART = 24, - IGRAPH_ARPACK_MODEINV = 25, - IGRAPH_ARPACK_MODEBMAT = 26, - IGRAPH_ARPACK_ISHIFT = 27, - IGRAPH_ARPACK_NEVBE = 28, - IGRAPH_ARPACK_NOFACT = 29, - IGRAPH_ARPACK_FAILED = 30, - IGRAPH_ARPACK_HOWMNY = 31, - IGRAPH_ARPACK_HOWMNYS = 32, - IGRAPH_ARPACK_EVDIFF = 33, - IGRAPH_ARPACK_SHUR = 34, - IGRAPH_ARPACK_LAPACK = 35, - IGRAPH_ARPACK_UNKNOWN = 36, + IGRAPH_EARPACK = 15, + /* ARPACK error codes from 15 to 36 were moved to igraph_arpack_error_t in 1.0 */ IGRAPH_ENEGLOOP = 37, IGRAPH_EINTERNAL = 38, - IGRAPH_ARPACK_MAXIT = 39, - IGRAPH_ARPACK_NOSHIFT = 40, - IGRAPH_ARPACK_REORDER = 41, - IGRAPH_EDIVZERO = 42, - IGRAPH_GLP_EBOUND = 43, - IGRAPH_GLP_EROOT = 44, - IGRAPH_GLP_ENOPFS = 45, - IGRAPH_GLP_ENODFS = 46, - IGRAPH_GLP_EFAIL = 47, - IGRAPH_GLP_EMIPGAP = 48, - IGRAPH_GLP_ETMLIM = 49, - IGRAPH_GLP_ESTOP = 50, - IGRAPH_EATTRIBUTES = 51, + /* ARPACK error codes from 39 to 41 were moved to igraph_arpack_error_t in 1.0 */ + /* IGRAPH_EDIVZERO = 42, */ /* removed in 1.0 */ + /* IGRAPH_GLP_EBOUND = 43, */ /* removed in 1.0 */ + /* IGRAPH_GLP_EROOT = 44, */ /* removed in 1.0 */ + /* IGRAPH_GLP_ENOPFS = 45, */ /* removed in 1.0 */ + /* IGRAPH_GLP_ENODFS = 46, */ /* removed in 1.0 */ + /* IGRAPH_GLP_EFAIL = 47, */ /* removed in 1.0 */ + /* IGRAPH_GLP_EMIPGAP = 48, */ /* removed in 1.0 */ + /* IGRAPH_GLP_ETMLIM = 49, */ /* removed in 1.0 */ + /* IGRAPH_GLP_ESTOP = 50, */ /* removed in 1.0 */ + /* IGRAPH_EATTRIBUTES = 51, */ /* removed in 1.0 */ IGRAPH_EATTRCOMBINE = 52, - IGRAPH_ELAPACK = 53, - IGRAPH_EDRL IGRAPH_DEPRECATED_ENUMVAL = 54, + /* IGRAPH_ELAPACK = 53, */ /* removed in 1.0 */ + /* IGRAPH_EDRL = 54, */ /* deprecated in 0.10.2, removed in 1.0 */ IGRAPH_EOVERFLOW = 55, - IGRAPH_EGLP = 56, - IGRAPH_CPUTIME = 57, + /* IGRAPH_EGLP = 56, */ /* removed in 1.0 */ + /* IGRAPH_CPUTIME = 57, */ /* removed in 1.0 */ IGRAPH_EUNDERFLOW = 58, IGRAPH_ERWSTUCK = 59, IGRAPH_STOP = 60, @@ -543,7 +477,7 @@ IGRAPH_EXPORT igraph_error_t igraph_errorvf(const char *reason, const char *file int line, igraph_error_t igraph_errno, va_list ap); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE const char *igraph_strerror(const igraph_error_t igraph_errno); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE const char *igraph_strerror(igraph_error_t igraph_errno); #define IGRAPH_ERROR_SELECT_2(a,b) ((a) != IGRAPH_SUCCESS ? (a) : ((b) != IGRAPH_SUCCESS ? (b) : IGRAPH_SUCCESS)) #define IGRAPH_ERROR_SELECT_3(a,b,c) ((a) != IGRAPH_SUCCESS ? (a) : IGRAPH_ERROR_SELECT_2(b,c)) @@ -993,6 +927,6 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_NORETURN void igraph_fatalf(const char *reason, } \ } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_eulerian.h b/src/vendor/cigraph/include/igraph_eulerian.h index bb9a089a7b4..e5f5e4ec5fb 100644 --- a/src/vendor/cigraph/include/igraph_eulerian.h +++ b/src/vendor/cigraph/include/igraph_eulerian.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2020-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_EULERIAN_H @@ -28,12 +23,12 @@ #include "igraph_datatype.h" #include "igraph_error.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_is_eulerian(const igraph_t *graph, igraph_bool_t *has_path, igraph_bool_t *has_cycle); IGRAPH_EXPORT igraph_error_t igraph_eulerian_path(const igraph_t *graph, igraph_vector_int_t *edge_res, igraph_vector_int_t *vertex_res); IGRAPH_EXPORT igraph_error_t igraph_eulerian_cycle(const igraph_t *graph, igraph_vector_int_t *edge_res, igraph_vector_int_t *vertex_res); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_flow.h b/src/vendor/cigraph/include/igraph_flow.h index 354f29f7e7b..143890a6a04 100644 --- a/src/vendor/cigraph/include/igraph_flow.h +++ b/src/vendor/cigraph/include/igraph_flow.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2003-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2003-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_FLOW_H @@ -31,7 +26,7 @@ #include "igraph_datatype.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Maximum flows, minimum cuts & such */ @@ -153,6 +148,6 @@ IGRAPH_EXPORT igraph_error_t igraph_gomory_hu_tree(const igraph_t *graph, igraph_vector_t *flows, const igraph_vector_t *capacity); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_foreign.h b/src/vendor/cigraph/include/igraph_foreign.h index a0625cba62b..790679d7ba5 100644 --- a/src/vendor/cigraph/include/igraph_foreign.h +++ b/src/vendor/cigraph/include/igraph_foreign.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_FOREIGN_H @@ -33,7 +28,7 @@ #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Read and write foreign formats */ @@ -50,13 +45,6 @@ IGRAPH_EXPORT igraph_error_t igraph_read_graph_lgl(igraph_t *graph, FILE *instre IGRAPH_EXPORT igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream); IGRAPH_EXPORT igraph_error_t igraph_read_graph_graphml(igraph_t *graph, FILE *instream, igraph_integer_t index); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_read_graph_dimacs(igraph_t *graph, FILE *instream, - igraph_strvector_t *problem, - igraph_vector_int_t *label, - igraph_integer_t *source, - igraph_integer_t *target, - igraph_vector_t *capacity, - igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_read_graph_dimacs_flow(igraph_t *graph, FILE *instream, igraph_strvector_t *problem, igraph_vector_int_t *label, @@ -86,9 +74,6 @@ IGRAPH_EXPORT igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE IGRAPH_EXPORT igraph_error_t igraph_write_graph_graphml(const igraph_t *graph, FILE *outstream, igraph_bool_t prefixattr); IGRAPH_EXPORT igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_write_graph_dimacs(const igraph_t *graph, FILE *outstream, - igraph_integer_t source, igraph_integer_t target, - const igraph_vector_t *capacity); IGRAPH_EXPORT igraph_error_t igraph_write_graph_dimacs_flow(const igraph_t *graph, FILE *outstream, igraph_integer_t source, igraph_integer_t target, const igraph_vector_t *capacity); @@ -108,6 +93,6 @@ typedef struct igraph_safelocale_s *igraph_safelocale_t; IGRAPH_EXPORT igraph_error_t igraph_enter_safelocale(igraph_safelocale_t *loc); IGRAPH_EXPORT void igraph_exit_safelocale(igraph_safelocale_t *loc); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_games.h b/src/vendor/cigraph/include/igraph_games.h index 3c4cbdb5aec..72bfc8a3a1c 100644 --- a/src/vendor/cigraph/include/igraph_games.h +++ b/src/vendor/cigraph/include/igraph_games.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_GAMES_H @@ -30,11 +25,12 @@ #include "igraph_error.h" #include "igraph_matrix.h" #include "igraph_matrix_list.h" +#include "igraph_random.h" #include "igraph_types.h" #include "igraph_vector.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Constructors, games (=stochastic) */ @@ -52,7 +48,10 @@ 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_iea_game(igraph_t *graph, + igraph_integer_t n, igraph_integer_t m, + igraph_bool_t directed, igraph_bool_t loops); 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); @@ -210,26 +209,6 @@ IGRAPH_EXPORT igraph_error_t igraph_tree_game(igraph_t *graph, igraph_integer_t IGRAPH_EXPORT igraph_error_t igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *vecs, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_sample_sphere_surface(igraph_integer_t dim, igraph_integer_t n, - igraph_real_t radius, - igraph_bool_t positive, - igraph_matrix_t *res); - -IGRAPH_EXPORT igraph_error_t igraph_sample_sphere_volume(igraph_integer_t dim, igraph_integer_t n, - igraph_real_t radius, - igraph_bool_t positive, - igraph_matrix_t *res); - -IGRAPH_EXPORT igraph_error_t igraph_sample_dirichlet(igraph_integer_t n, const igraph_vector_t *alpha, - igraph_matrix_t *res); - -/* Deprecated functions: */ - -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_erdos_renyi_game( - igraph_t *graph, igraph_erdos_renyi_t type, igraph_integer_t n, - igraph_real_t p_or_m, igraph_bool_t directed, igraph_bool_t loops -); - -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_graph_list.h b/src/vendor/cigraph/include/igraph_graph_list.h index 7f8232621a0..fea672a14f3 100644 --- a/src/vendor/cigraph/include/igraph_graph_list.h +++ b/src/vendor/cigraph/include/igraph_graph_list.h @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2022 The igraph development team + Copyright (C) 2022-2025 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 @@ -14,22 +13,18 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_GRAPH_LIST_H #define IGRAPH_GRAPH_LIST_H -#include "igraph_datatype.h" #include "igraph_decls.h" +#include "igraph_datatype.h" #include "igraph_error.h" #include "igraph_types.h" -#include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* List of graphs */ @@ -55,6 +50,6 @@ void igraph_graph_list_set_directed(igraph_graph_list_t* list, igraph_bool_t dir do { IGRAPH_CHECK(igraph_graph_list_init(v, size)); \ IGRAPH_FINALLY(igraph_graph_list_destroy, v); } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_graphicality.h b/src/vendor/cigraph/include/igraph_graphicality.h index f639217b5b1..2a4c04a9831 100644 --- a/src/vendor/cigraph/include/igraph_graphicality.h +++ b/src/vendor/cigraph/include/igraph_graphicality.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. - Copyright (C) 2009-2020 Gabor Csardi + Copyright (C) 2020-2025 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 @@ -25,7 +23,7 @@ #include "igraph_error.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef unsigned int igraph_edge_type_sw_t; @@ -42,14 +40,14 @@ enum { IGRAPH_EXPORT igraph_error_t igraph_is_graphical(const igraph_vector_int_t *out_degrees, const igraph_vector_int_t *in_degrees, - const igraph_edge_type_sw_t allowed_edge_types, + igraph_edge_type_sw_t allowed_edge_types, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_is_bigraphical(const igraph_vector_int_t *degrees1, const igraph_vector_int_t *degrees2, - const igraph_edge_type_sw_t allowed_edge_types, + igraph_edge_type_sw_t allowed_edge_types, igraph_bool_t *res); -__END_DECLS +IGRAPH_END_C_DECLS #endif // IGRAPH_GRAPHICALITY_H diff --git a/src/vendor/cigraph/include/igraph_graphlets.h b/src/vendor/cigraph/include/igraph_graphlets.h index b80165a6966..3639dfad701 100644 --- a/src/vendor/cigraph/include/igraph_graphlets.h +++ b/src/vendor/cigraph/include/igraph_graphlets.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2013 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2013-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_GRAPHLETS_H @@ -30,7 +25,7 @@ #include "igraph_error.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_graphlets_candidate_basis(const igraph_t *graph, const igraph_vector_t *weights, @@ -48,6 +43,6 @@ IGRAPH_EXPORT igraph_error_t igraph_graphlets(const igraph_t *graph, igraph_vector_int_list_t *cliques, igraph_vector_t *Mu, igraph_integer_t niter); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_heap.h b/src/vendor/cigraph/include/igraph_heap.h index 3eb81c2f972..e5b57a112f4 100644 --- a/src/vendor/cigraph/include/igraph_heap.h +++ b/src/vendor/cigraph/include/igraph_heap.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_HEAP_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Heap */ @@ -80,6 +75,6 @@ __BEGIN_DECLS #define IGRAPH_HEAP_NULL { 0,0,0 } -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_heap_pmt.h b/src/vendor/cigraph/include/igraph_heap_pmt.h index d501700d34b..8f8106ee30a 100644 --- a/src/vendor/cigraph/include/igraph_heap_pmt.h +++ b/src/vendor/cigraph/include/igraph_heap_pmt.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,17 +13,13 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ 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_hrg.h b/src/vendor/cigraph/include/igraph_hrg.h index 6ceeb4cac24..87abfbd5258 100644 --- a/src/vendor/cigraph/include/igraph_hrg.h +++ b/src/vendor/cigraph/include/igraph_hrg.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_HRG_H @@ -31,7 +26,7 @@ #include "igraph_graph_list.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \struct igraph_hrg_t @@ -127,6 +122,6 @@ IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_hrg_dendrogram( igraph_t *graph, const igraph_hrg_t *hrg ); -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_HRG_H */ diff --git a/src/vendor/cigraph/include/igraph_interface.h b/src/vendor/cigraph/include/igraph_interface.h index 27c642a3e1c..6efae000c27 100644 --- a/src/vendor/cigraph/include/igraph_interface.h +++ b/src/vendor/cigraph/include/igraph_interface.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,54 +13,65 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_INTERFACE_H #define IGRAPH_INTERFACE_H #include "igraph_decls.h" -#include "igraph_types.h" +#include "igraph_attributes.h" #include "igraph_datatype.h" #include "igraph_error.h" #include "igraph_iterators.h" +#include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Interface */ /* -------------------------------------------------- */ 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(igraph_t *graph, igraph_vs_t vertices); +IGRAPH_EXPORT igraph_error_t igraph_delete_vertices_map( + igraph_t *graph, 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, - igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_neighbors( + const igraph_t *graph, igraph_vector_int_t *neis, igraph_integer_t vid, + igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple +); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_is_directed(const igraph_t *graph); -IGRAPH_EXPORT igraph_error_t igraph_degree_1(const igraph_t *graph, igraph_integer_t *deg, - igraph_integer_t vid, igraph_neimode_t mode, igraph_bool_t loops); -IGRAPH_EXPORT igraph_error_t igraph_degree(const igraph_t *graph, igraph_vector_int_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, - igraph_bool_t loops); +IGRAPH_EXPORT igraph_error_t igraph_degree_1( + const igraph_t *graph, igraph_integer_t *deg, igraph_integer_t vid, + igraph_neimode_t mode, igraph_loops_t loops +); +IGRAPH_EXPORT igraph_error_t igraph_degree( + const igraph_t *graph, igraph_vector_int_t *res, igraph_vs_t vids, + igraph_neimode_t mode, igraph_loops_t loops +); IGRAPH_EXPORT igraph_error_t igraph_edge(const igraph_t *graph, igraph_integer_t eid, igraph_integer_t *from, igraph_integer_t *to); IGRAPH_EXPORT igraph_error_t igraph_edges(const igraph_t *graph, igraph_es_t eids, - igraph_vector_int_t *edges); + igraph_vector_int_t *edges, igraph_bool_t bycol); IGRAPH_EXPORT igraph_error_t igraph_get_eid(const igraph_t *graph, igraph_integer_t *eid, igraph_integer_t from, igraph_integer_t to, igraph_bool_t directed, igraph_bool_t error); @@ -71,8 +80,10 @@ IGRAPH_EXPORT igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vecto igraph_bool_t directed, igraph_bool_t error); IGRAPH_EXPORT igraph_error_t igraph_get_all_eids_between(const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t source, igraph_integer_t target, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_incident(const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t vid, - igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_incident( + const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t pnode, + igraph_neimode_t mode, igraph_loops_t loops +); IGRAPH_EXPORT igraph_error_t igraph_is_same_graph(const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *res); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_i_property_cache_get_bool(const igraph_t *graph, igraph_cached_property_t prop); @@ -134,6 +145,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)))) -__END_DECLS +IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_delete_vertices_idx( + igraph_t *graph, igraph_vs_t vertices, igraph_vector_int_t *idx, + igraph_vector_int_t *invidx +); + +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_interrupt.h b/src/vendor/cigraph/include/igraph_interrupt.h index 6d8fb85ca8a..239b9741603 100644 --- a/src/vendor/cigraph/include/igraph_interrupt.h +++ b/src/vendor/cigraph/include/igraph_interrupt.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2003-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2003-2025 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 @@ -15,19 +13,16 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_INTERRUPT_H #define IGRAPH_INTERRUPT_H #include "igraph_decls.h" -#include "igraph_error.h" +#include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* This file contains the igraph interruption handling. */ @@ -102,11 +97,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,14 +110,14 @@ 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); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_topology.h b/src/vendor/cigraph/include/igraph_isomorphism.h similarity index 83% rename from src/vendor/cigraph/include/igraph_topology.h rename to src/vendor/cigraph/include/igraph_isomorphism.h index baff051b239..0c581f197bd 100644 --- a/src/vendor/cigraph/include/igraph_topology.h +++ b/src/vendor/cigraph/include/igraph_isomorphism.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,33 +13,20 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ -#ifndef IGRAPH_TOPOLOGY_H -#define IGRAPH_TOPOLOGY_H +#ifndef IGRAPH_ISOMORPHISM_H +#define IGRAPH_ISOMORPHISM_H #include "igraph_decls.h" -#include "igraph_constants.h" #include "igraph_datatype.h" #include "igraph_error.h" #include "igraph_types.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS -/* -------------------------------------------------- */ -/* Directed acyclic graphs */ -/* -------------------------------------------------- */ - -IGRAPH_EXPORT igraph_error_t igraph_topological_sorting( - const igraph_t *graph, igraph_vector_int_t *res, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_is_dag(const igraph_t *graph, igraph_bool_t *res); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_transitive_closure_dag(const igraph_t *graph, - igraph_t *closure); /* -------------------------------------------------- */ /* Graph isomorphisms */ @@ -59,12 +44,23 @@ 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( const igraph_t *pattern, const igraph_t *target, const igraph_vector_int_list_t *domains, igraph_bool_t *iso, igraph_vector_int_t *map, igraph_vector_int_list_t *maps, - igraph_bool_t induced, igraph_integer_t time_limit + igraph_bool_t induced ); /* VF2 family*/ @@ -157,17 +153,6 @@ IGRAPH_EXPORT igraph_error_t igraph_get_isomorphisms_vf2_callback( igraph_isohandler_t *isohandler_fn, igraph_isocompat_t *node_compat_fn, igraph_isocompat_t *edge_compat_fn, void *arg ); - -/* Deprecated alias to igraph_get_isomorphisms_vf2_callback(), will be removed in 0.11 */ -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_isomorphic_function_vf2( - const igraph_t *graph1, const igraph_t *graph2, - const igraph_vector_int_t *vertex_color1, const igraph_vector_int_t *vertex_color2, - const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_vector_int_t *map12, igraph_vector_int_t *map21, - igraph_isohandler_t *isohandler_fn, igraph_isocompat_t *node_compat_fn, - igraph_isocompat_t *edge_compat_fn, void *arg -); - IGRAPH_EXPORT igraph_error_t igraph_subisomorphic_vf2(const igraph_t *graph1, const igraph_t *graph2, const igraph_vector_int_t *vertex_color1, const igraph_vector_int_t *vertex_color2, @@ -207,16 +192,6 @@ IGRAPH_EXPORT igraph_error_t igraph_get_subisomorphisms_vf2_callback( igraph_isocompat_t *edge_compat_fn, void *arg ); -/* Deprecated alias to igraph_get_subisomorphisms_vf2_callback(), will be removed in 0.11 */ -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_subisomorphic_function_vf2( - const igraph_t *graph1, const igraph_t *graph2, - const igraph_vector_int_t *vertex_color1, const igraph_vector_int_t *vertex_color2, - const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_vector_int_t *map12, igraph_vector_int_t *map21, - igraph_isohandler_t *isohandler_fn, igraph_isocompat_t *node_compat_fn, - igraph_isocompat_t *edge_compat_fn, void *arg -); - /* BLISS family */ /** * \struct igraph_bliss_info_t @@ -266,7 +241,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, @@ -274,7 +249,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, @@ -283,15 +258,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( +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_DEPRECATED 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); - -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 @@ -306,12 +276,6 @@ IGRAPH_EXPORT igraph_error_t igraph_isoclass_create(igraph_t *graph, igraph_inte IGRAPH_EXPORT igraph_error_t igraph_graph_count(igraph_integer_t n, igraph_bool_t directed, igraph_integer_t *count); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_isomorphic_34( - const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *iso -); - - - -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_iterators.h b/src/vendor/cigraph/include/igraph_iterators.h index 144b435e8e5..48ffdf74d0f 100644 --- a/src/vendor/cigraph/include/igraph_iterators.h +++ b/src/vendor/cigraph/include/igraph_iterators.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_ITERATORS_H @@ -31,7 +26,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Vertex selectors */ @@ -56,6 +51,8 @@ typedef struct igraph_vs_t { struct { igraph_integer_t vid; igraph_neimode_t mode; + igraph_loops_t loops; + igraph_bool_t multiple; } adj; /* adjacent vertices */ struct { igraph_integer_t start; /* first index (inclusive) */ @@ -67,8 +64,10 @@ typedef struct igraph_vs_t { IGRAPH_EXPORT igraph_error_t igraph_vs_all(igraph_vs_t *vs); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_all(void); -IGRAPH_EXPORT igraph_error_t igraph_vs_adj(igraph_vs_t *vs, - igraph_integer_t vid, igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_vs_adj( + igraph_vs_t *vs, igraph_integer_t vid, igraph_neimode_t mode, + igraph_loops_t loops, igraph_bool_t multiple +); IGRAPH_EXPORT igraph_error_t igraph_vs_nonadj(igraph_vs_t *vs, igraph_integer_t vid, igraph_neimode_t mode); @@ -88,9 +87,6 @@ IGRAPH_EXPORT igraph_error_t igraph_vs_vector_small(igraph_vs_t *vs, ...); IGRAPH_EXPORT igraph_error_t igraph_vs_vector_copy(igraph_vs_t *vs, const igraph_vector_int_t *v); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_vs_seq(igraph_vs_t *vs, igraph_integer_t from, igraph_integer_t to); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_vs_t igraph_vss_seq(igraph_integer_t from, igraph_integer_t to); - IGRAPH_EXPORT igraph_error_t igraph_vs_range(igraph_vs_t *vs, igraph_integer_t start, igraph_integer_t end); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_range(igraph_integer_t start, igraph_integer_t end); @@ -240,7 +236,6 @@ typedef enum { IGRAPH_ES_RANGE, IGRAPH_ES_PAIRS, IGRAPH_ES_PATH, - IGRAPH_ES_UNUSED_WAS_MULTIPAIRS, /* placeholder for deprecated IGRAPH_ES_MULTIPAIRS from igraph 0.10 */ IGRAPH_ES_ALL_BETWEEN, } igraph_es_type_t; @@ -253,6 +248,7 @@ typedef struct igraph_es_t { struct { igraph_integer_t vid; igraph_neimode_t mode; + igraph_loops_t loops; } incident; struct { igraph_integer_t start; /* first index (inclusive) */ @@ -274,8 +270,10 @@ IGRAPH_EXPORT igraph_error_t igraph_es_all(igraph_es_t *es, igraph_edgeorder_type_t order); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_all(igraph_edgeorder_type_t order); -IGRAPH_EXPORT igraph_error_t igraph_es_incident(igraph_es_t *es, - igraph_integer_t vid, igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_es_incident( + igraph_es_t *es, igraph_integer_t vid, igraph_neimode_t mode, + igraph_loops_t loops +); IGRAPH_EXPORT igraph_error_t igraph_es_none(igraph_es_t *es); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_none(void); @@ -290,9 +288,6 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_es_t igraph_ess_vector(const igraph_ve IGRAPH_EXPORT igraph_error_t igraph_es_range(igraph_es_t *es, igraph_integer_t from, igraph_integer_t to); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_range(igraph_integer_t from, igraph_integer_t to); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_es_seq(igraph_es_t *es, igraph_integer_t from, igraph_integer_t to); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_es_t igraph_ess_seq(igraph_integer_t from, igraph_integer_t to); - IGRAPH_EXPORT igraph_error_t igraph_es_vector_copy(igraph_es_t *es, const igraph_vector_int_t *v); IGRAPH_EXPORT igraph_error_t igraph_es_pairs(igraph_es_t *es, const igraph_vector_int_t *v, @@ -416,6 +411,6 @@ IGRAPH_EXPORT void igraph_eit_destroy(const igraph_eit_t *eit); IGRAPH_EXPORT igraph_error_t igraph_eit_as_vector(const igraph_eit_t *eit, igraph_vector_int_t *v); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_lapack.h b/src/vendor/cigraph/include/igraph_lapack.h index 76b30f37dd0..7b2f8dbfaed 100644 --- a/src/vendor/cigraph/include/igraph_lapack.h +++ b/src/vendor/cigraph/include/igraph_lapack.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_LAPACK_H @@ -29,7 +24,7 @@ #include "igraph_vector.h" #include "igraph_matrix.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \section about_lapack LAPACK interface in igraph @@ -107,6 +102,6 @@ IGRAPH_EXPORT igraph_error_t igraph_lapack_dgehrd(const igraph_matrix_t *A, int ilo, int ihi, igraph_matrix_t *result); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_layout.h b/src/vendor/cigraph/include/igraph_layout.h index 7c50781ffc3..912744e9dfa 100644 --- a/src/vendor/cigraph/include/igraph_layout.h +++ b/src/vendor/cigraph/include/igraph_layout.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_LAYOUT_H @@ -36,7 +31,7 @@ #include "igraph_vector_ptr.h" #include "igraph_matrix.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \section about_layouts @@ -294,6 +289,6 @@ IGRAPH_EXPORT igraph_error_t igraph_roots_for_tree_layout( IGRAPH_EXPORT igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layout); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_lsap.h b/src/vendor/cigraph/include/igraph_lsap.h index 61898d40ca5..80bce0aedfe 100644 --- a/src/vendor/cigraph/include/igraph_lsap.h +++ b/src/vendor/cigraph/include/igraph_lsap.h @@ -1,3 +1,20 @@ +/* + IGraph library. + Copyright (C) 2014-2025 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 . +*/ #ifndef IGRAPH_LSAP_H #define IGRAPH_LSAP_H @@ -8,11 +25,11 @@ #include "igraph_vector.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_solve_lsap(const igraph_matrix_t *c, igraph_integer_t n, igraph_vector_int_t *p); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_matching.h b/src/vendor/cigraph/include/igraph_matching.h index 44b9082f488..dbce7b02ecf 100644 --- a/src/vendor/cigraph/include/igraph_matching.h +++ b/src/vendor/cigraph/include/igraph_matching.h @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2012 Tamas Nepusz + Copyright (C) 2012-2025 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 @@ -14,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_MATCHING_H @@ -29,7 +25,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Matchings in graphs */ @@ -47,6 +43,6 @@ IGRAPH_EXPORT igraph_error_t igraph_maximum_bipartite_matching(const igraph_t* g igraph_real_t* matching_weight, igraph_vector_int_t* matching, const igraph_vector_t* weights, igraph_real_t eps); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_matrix.h b/src/vendor/cigraph/include/igraph_matrix.h index f092d7a0789..8ce91346b84 100644 --- a/src/vendor/cigraph/include/igraph_matrix.h +++ b/src/vendor/cigraph/include/igraph_matrix.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_MATRIX_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Matrix, very similar to vector */ @@ -87,9 +82,6 @@ __BEGIN_DECLS */ #define MATRIX(m,i,j) ((m).data.stor_begin[(m).nrow*(j)+(i)]) -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_bool_t igraph_matrix_all_e_tol(const igraph_matrix_t *lhs, - const igraph_matrix_t *rhs, - igraph_real_t tol); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_matrix_all_almost_e(const igraph_matrix_t *lhs, const igraph_matrix_t *rhs, @@ -98,6 +90,6 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_matrix_all_almost_e(cons IGRAPH_EXPORT igraph_error_t igraph_matrix_zapsmall(igraph_matrix_t *m, igraph_real_t tol); IGRAPH_EXPORT igraph_error_t igraph_matrix_complex_zapsmall(igraph_matrix_complex_t *m, igraph_real_t tol); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_matrix_list.h b/src/vendor/cigraph/include/igraph_matrix_list.h index 1e44cf8d405..34a8b85548b 100644 --- a/src/vendor/cigraph/include/igraph_matrix_list.h +++ b/src/vendor/cigraph/include/igraph_matrix_list.h @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2022 The igraph development team + Copyright (C) 2022-2025 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 @@ -14,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_MATRIX_LIST_H @@ -28,7 +24,7 @@ #include "igraph_matrix.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Flexible list of matrices */ @@ -54,6 +50,6 @@ __BEGIN_DECLS do { IGRAPH_CHECK(igraph_matrix_list_init(v, size)); \ IGRAPH_FINALLY(igraph_matrix_list_destroy, v); } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_matrix_pmt.h b/src/vendor/cigraph/include/igraph_matrix_pmt.h index 32697530ee9..4ceb157d605 100644 --- a/src/vendor/cigraph/include/igraph_matrix_pmt.h +++ b/src/vendor/cigraph/include/igraph_matrix_pmt.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ typedef struct TYPE(igraph_matrix) { @@ -39,18 +34,11 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, init_copy)( IGRAPH_EXPORT void FUNCTION(igraph_matrix, destroy)(TYPE(igraph_matrix) *m); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_matrix, capacity)(const TYPE(igraph_matrix) *m); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t FUNCTION(igraph_matrix, copy)( - TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from); - /*--------------------*/ /* Accessing elements */ /*--------------------*/ /* MATRIX */ -IGRAPH_EXPORT IGRAPH_DEPRECATED BASE FUNCTION(igraph_matrix, e)( - const TYPE(igraph_matrix) *m, igraph_integer_t row, igraph_integer_t col); -IGRAPH_EXPORT IGRAPH_DEPRECATED BASE* FUNCTION(igraph_matrix, e_ptr)( - const TYPE(igraph_matrix) *m, igraph_integer_t row, igraph_integer_t col); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_matrix, get)( const TYPE(igraph_matrix) *m, igraph_integer_t row, igraph_integer_t col); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE* FUNCTION(igraph_matrix, get_ptr)( @@ -88,7 +76,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 46048b41706..90c5e7fd09e 100644 --- a/src/vendor/cigraph/include/igraph_memory.h +++ b/src/vendor/cigraph/include/igraph_memory.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2003-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2003-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_MEMORY_H @@ -29,7 +24,7 @@ #include #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* Helper macro to check if n*sizeof(t) overflows in IGRAPH_CALLOC and IGRAPH_REALLOC */ #define IGRAPH_I_ALLOC_CHECK_OVERFLOW(n,t,expr) \ @@ -40,17 +35,11 @@ __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); IGRAPH_EXPORT void igraph_free(void *ptr); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_microscopic_update.h b/src/vendor/cigraph/include/igraph_microscopic_update.h deleted file mode 100644 index b400468b7b0..00000000000 --- a/src/vendor/cigraph/include/igraph_microscopic_update.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- mode: C -*- */ -/* - Microscopic update rules for dealing with agent-level strategy revision. - Copyright (C) 2011 Minh Van Nguyen - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#ifndef IGRAPH_MICROSCOPIC_UPDATE_H -#define IGRAPH_MICROSCOPIC_UPDATE_H - -#include "igraph_decls.h" -#include "igraph_constants.h" -#include "igraph_datatype.h" -#include "igraph_error.h" -#include "igraph_iterators.h" -#include "igraph_types.h" -#include "igraph_vector.h" - -__BEGIN_DECLS - -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_deterministic_optimal_imitation(const igraph_t *graph, - igraph_integer_t vid, - igraph_optimal_t optimality, - const igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_moran_process(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_roulette_wheel_imitation(const igraph_t *graph, - igraph_integer_t vid, - igraph_bool_t islocal, - const igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_stochastic_imitation(const igraph_t *graph, - igraph_integer_t vid, - igraph_imitate_algorithm_t algo, - const igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode); - -__END_DECLS - -#endif diff --git a/src/vendor/cigraph/include/igraph_mixing.h b/src/vendor/cigraph/include/igraph_mixing.h index b69a6c8f777..7317caa892b 100644 --- a/src/vendor/cigraph/include/igraph_mixing.h +++ b/src/vendor/cigraph/include/igraph_mixing.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_MIXING_H @@ -31,7 +26,7 @@ #include "igraph_vector.h" #include "igraph_matrix.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, const igraph_vector_int_t *types, @@ -68,6 +63,6 @@ IGRAPH_EXPORT igraph_error_t igraph_joint_type_distribution( const igraph_vector_int_t *from_types, const igraph_vector_int_t *to_types, igraph_bool_t directed, igraph_bool_t normalized); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_motifs.h b/src/vendor/cigraph/include/igraph_motifs.h index 74de61a9c27..754abd540ae 100644 --- a/src/vendor/cigraph/include/igraph_motifs.h +++ b/src/vendor/cigraph/include/igraph_motifs.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_MOTIFS_H @@ -30,7 +25,7 @@ #include "igraph_error.h" #include "igraph_iterators.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Graph motifs */ @@ -78,11 +73,11 @@ IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_callback(const igraph_t *grap igraph_motifs_handler_t *callback, void* extra); -IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_integer_t *est, +IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real_t *est, igraph_integer_t size, const igraph_vector_t *cut_prob, igraph_integer_t sample_size, const igraph_vector_int_t *sample); -IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t *no, +IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_real_t *no, igraph_integer_t size, const igraph_vector_t *cut_prob); IGRAPH_EXPORT igraph_error_t igraph_dyad_census(const igraph_t *graph, igraph_real_t *mut, @@ -91,17 +86,13 @@ IGRAPH_EXPORT igraph_error_t igraph_triad_census(const igraph_t *igraph, igraph_ IGRAPH_EXPORT igraph_error_t igraph_count_adjacent_triangles(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids); - -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_adjacent_triangles(const igraph_t *graph, - igraph_vector_t *res, - const igraph_vs_t vids); + igraph_vs_t vids); IGRAPH_EXPORT igraph_error_t igraph_list_triangles(const igraph_t *graph, igraph_vector_int_t *res); IGRAPH_EXPORT igraph_error_t igraph_count_triangles(const igraph_t *graph, igraph_real_t *res); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_neighborhood.h b/src/vendor/cigraph/include/igraph_neighborhood.h index d96d22c9cf9..35a0a9b204a 100644 --- a/src/vendor/cigraph/include/igraph_neighborhood.h +++ b/src/vendor/cigraph/include/igraph_neighborhood.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_NEIGHBORHOOD_H @@ -31,7 +26,7 @@ #include "igraph_iterators.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int_t *res, igraph_vs_t vids, igraph_integer_t order, @@ -44,6 +39,6 @@ IGRAPH_EXPORT igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, i igraph_neimode_t mode, igraph_integer_t mindist); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_nongraph.h b/src/vendor/cigraph/include/igraph_nongraph.h index 63aa3749894..226bbaa7b90 100644 --- a/src/vendor/cigraph/include/igraph_nongraph.h +++ b/src/vendor/cigraph/include/igraph_nongraph.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_NONGRAPH_H @@ -30,7 +25,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \def IGRAPH_SHORTEST_PATH_EPSILON @@ -40,13 +35,6 @@ __BEGIN_DECLS */ #define IGRAPH_SHORTEST_PATH_EPSILON 1e-10 -typedef igraph_real_t igraph_scalar_function_t(const igraph_vector_t *var, - const igraph_vector_t *par, - void* extra); -typedef void igraph_vector_function_t(const igraph_vector_t *var, - const igraph_vector_t *par, - igraph_vector_t* res, void* extra); - /* -------------------------------------------------- */ /* Other, not graph related */ /* -------------------------------------------------- */ @@ -105,11 +93,6 @@ IGRAPH_EXPORT igraph_error_t igraph_plfit_result_calculate_p_value( const igraph_plfit_result_t* model, igraph_real_t* result, igraph_real_t precision ); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_zeroin( - igraph_real_t *ax, igraph_real_t *bx, igraph_real_t (*f)(igraph_real_t x, void *info), - void *info, igraph_real_t *Tol, int *Maxit, igraph_real_t *res -); - -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_operators.h b/src/vendor/cigraph/include/igraph_operators.h index f087dd2b003..a50ee07b920 100644 --- a/src/vendor/cigraph/include/igraph_operators.h +++ b/src/vendor/cigraph/include/igraph_operators.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_OPERATORS_H @@ -30,11 +25,12 @@ #include "igraph_constants.h" #include "igraph_datatype.h" #include "igraph_error.h" +#include "igraph_graphicality.h" #include "igraph_types.h" #include "igraph_vector_list.h" #include "igraph_vector_ptr.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Graph operators */ @@ -73,34 +69,32 @@ IGRAPH_EXPORT igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_graph_power(const igraph_t *graph, igraph_t *res, igraph_integer_t order, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewiring_t mode); +IGRAPH_EXPORT igraph_error_t igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_edge_type_sw_t allowed_edge_types); IGRAPH_EXPORT igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t remove_multiple, igraph_bool_t remove_loops, const igraph_attribute_combination_t *edge_comb); IGRAPH_EXPORT igraph_error_t igraph_induced_subgraph_map(const igraph_t *graph, igraph_t *res, - const igraph_vs_t vids, + igraph_vs_t vids, igraph_subgraph_implementation_t impl, igraph_vector_int_t *map, igraph_vector_int_t *invmap); IGRAPH_EXPORT igraph_error_t igraph_induced_subgraph(const igraph_t *graph, igraph_t *res, - const igraph_vs_t vids, igraph_subgraph_implementation_t impl); + igraph_vs_t vids, igraph_subgraph_implementation_t impl); IGRAPH_EXPORT igraph_error_t igraph_induced_subgraph_edges( const igraph_t *graph, igraph_vs_t vids, igraph_vector_int_t *edges); IGRAPH_EXPORT igraph_error_t igraph_subgraph_from_edges(const igraph_t *graph, igraph_t *res, - const igraph_es_t eids, igraph_bool_t delete_vertices); -IGRAPH_EXPORT igraph_error_t igraph_reverse_edges(igraph_t *graph, const igraph_es_t eids); - + igraph_es_t eids, igraph_bool_t delete_vertices); +IGRAPH_EXPORT igraph_error_t igraph_reverse_edges(igraph_t *graph, igraph_es_t eids); IGRAPH_EXPORT igraph_error_t igraph_product(igraph_t *res, const igraph_t *g1, const igraph_t *g2, igraph_product_t type); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_subgraph_edges( - const igraph_t *graph, igraph_t *res, const igraph_es_t eids, - igraph_bool_t delete_vertices -); - +IGRAPH_EXPORT igraph_error_t igraph_rooted_product(igraph_t *res, + const igraph_t *g1, + const igraph_t *g2, + const igraph_integer_t root); IGRAPH_EXPORT igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_integer_t k); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_paths.h b/src/vendor/cigraph/include/igraph_paths.h index 015c489866c..f047777f083 100644 --- a/src/vendor/cigraph/include/igraph_paths.h +++ b/src/vendor/cigraph/include/igraph_paths.h @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2021 The igraph development team + Copyright (C) 2009-2025 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 @@ -14,9 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + along with this program. If not, see . */ #ifndef IGRAPH_PATHS_H @@ -32,7 +29,7 @@ #include "igraph_vector.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \typedef igraph_astar_heuristic_func_t @@ -71,50 +68,35 @@ typedef enum { IGRAPH_FLOYD_WARSHALL_TREE = 2 } igraph_floyd_warshall_algorithm_t; -IGRAPH_EXPORT igraph_error_t igraph_diameter(const igraph_t *graph, igraph_real_t *res, - igraph_integer_t *from, igraph_integer_t *to, - igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path, - igraph_bool_t directed, igraph_bool_t unconn); -IGRAPH_EXPORT igraph_error_t igraph_diameter_dijkstra(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_real_t *res, - igraph_integer_t *from, - igraph_integer_t *to, - igraph_vector_int_t *vertex_path, - igraph_vector_int_t *edge_path, - igraph_bool_t directed, - igraph_bool_t unconn); - -IGRAPH_EXPORT igraph_error_t igraph_distances_cutoff(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode, igraph_real_t cutoff); -IGRAPH_EXPORT igraph_error_t igraph_distances(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_diameter( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_integer_t *from, igraph_integer_t *to, + igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path, + igraph_bool_t directed, igraph_bool_t unconn +); + +IGRAPH_EXPORT igraph_error_t igraph_distances( + const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, igraph_neimode_t mode +); IGRAPH_EXPORT igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, + igraph_vs_t from, + igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode, - igraph_real_t cutoff); IGRAPH_EXPORT igraph_error_t igraph_distances_dijkstra(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, + igraph_vs_t from, + igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode); 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); + igraph_vs_t from, + igraph_vs_t to, + 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, @@ -122,34 +104,22 @@ IGRAPH_EXPORT igraph_error_t igraph_distances_floyd_warshall(const igraph_t *gra const igraph_vector_t *weights, igraph_neimode_t mode, igraph_floyd_warshall_algorithm_t method); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_shortest_paths(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_shortest_paths_bellman_ford(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_shortest_paths_dijkstra(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_shortest_paths_johnson(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights); -IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths(const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, - igraph_integer_t from, const igraph_vs_t to, - igraph_neimode_t mode, - igraph_vector_int_t *parents, - igraph_vector_int_t *inbound_edges); +IGRAPH_EXPORT igraph_error_t igraph_distances_cutoff( + const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, igraph_neimode_t mode, igraph_real_t cutoff +); +IGRAPH_EXPORT igraph_error_t igraph_distances_dijkstra_cutoff( + const igraph_t *graph, igraph_matrix_t *res, igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, igraph_neimode_t mode, igraph_real_t cutoff +); + +IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, + igraph_integer_t from, igraph_vs_t to, igraph_neimode_t mode, + igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges +); IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, @@ -169,12 +139,11 @@ IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t * igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges); -IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path(const igraph_t *graph, - igraph_vector_int_t *vertices, - igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, - igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_t *vertices, igraph_vector_int_t *edges, + igraph_integer_t from, igraph_integer_t to, igraph_neimode_t mode +); IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path_bellman_ford(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, @@ -200,12 +169,12 @@ IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path_astar(const igraph_t *grap igraph_astar_heuristic_func_t *heuristic, void *extra); -IGRAPH_EXPORT igraph_error_t igraph_get_all_shortest_paths(const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, - igraph_vector_int_t *nrgeo, - igraph_integer_t from, const igraph_vs_t to, - igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_get_all_shortest_paths( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, + igraph_vector_int_t *nrgeo, igraph_integer_t from, igraph_vs_t to, + igraph_neimode_t mode +); IGRAPH_EXPORT igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, @@ -214,74 +183,55 @@ IGRAPH_EXPORT igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph const igraph_vector_t *weights, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_average_path_length(const igraph_t *graph, - igraph_real_t *res, igraph_real_t *unconn_pairs, - igraph_bool_t directed, igraph_bool_t unconn); -IGRAPH_EXPORT igraph_error_t igraph_average_path_length_dijkstra(const igraph_t *graph, - igraph_real_t *res, igraph_real_t *unconn_pairs, - const igraph_vector_t *weights, - igraph_bool_t directed, igraph_bool_t unconn); +IGRAPH_EXPORT igraph_error_t igraph_average_path_length( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_real_t *unconn_pairs, igraph_bool_t directed, igraph_bool_t unconn +); IGRAPH_EXPORT igraph_error_t igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *res, igraph_real_t *unconnected, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_global_efficiency(const igraph_t *graph, igraph_real_t *res, - const igraph_vector_t *weights, - igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_local_efficiency(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, - const igraph_vector_t *weights, - igraph_bool_t directed, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_average_local_efficiency(const igraph_t *graph, igraph_real_t *res, - const igraph_vector_t *weights, - igraph_bool_t directed, igraph_neimode_t mode); - -IGRAPH_EXPORT igraph_error_t igraph_eccentricity(const igraph_t *graph, - igraph_vector_t *res, - igraph_vs_t vids, - igraph_neimode_t mode); - -IGRAPH_EXPORT igraph_error_t igraph_eccentricity_dijkstra(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_vector_t *res, - igraph_vs_t vids, - igraph_neimode_t mode); - -IGRAPH_EXPORT igraph_error_t igraph_radius(const igraph_t *graph, igraph_real_t *radius, - igraph_neimode_t mode); - -IGRAPH_EXPORT igraph_error_t igraph_radius_dijkstra(const igraph_t *graph, const igraph_vector_t *weights, - igraph_real_t *radius, igraph_neimode_t mode); - -IGRAPH_EXPORT igraph_error_t igraph_graph_center(const igraph_t *graph, - igraph_vector_int_t *res, - igraph_neimode_t mode); - -IGRAPH_EXPORT igraph_error_t igraph_graph_center_dijkstra( +IGRAPH_EXPORT igraph_error_t igraph_global_efficiency( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_bool_t directed +); +IGRAPH_EXPORT igraph_error_t igraph_local_efficiency( + const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, + igraph_vs_t vids, igraph_bool_t directed, igraph_neimode_t mode +); +IGRAPH_EXPORT igraph_error_t igraph_average_local_efficiency( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_bool_t directed, igraph_neimode_t mode +); + +IGRAPH_EXPORT igraph_error_t igraph_eccentricity( + const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, + igraph_vs_t vids, igraph_neimode_t mode +); + +IGRAPH_EXPORT igraph_error_t igraph_radius( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *radius, + igraph_neimode_t mode +); + +IGRAPH_EXPORT igraph_error_t igraph_graph_center( const igraph_t *graph, const igraph_vector_t *weights, - igraph_vector_int_t *res, igraph_neimode_t mode); + igraph_vector_int_t *res, igraph_neimode_t mode +); -IGRAPH_EXPORT igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, - igraph_real_t *diameter, - igraph_integer_t vid_start, - igraph_integer_t *from, - igraph_integer_t *to, - igraph_bool_t directed, - igraph_bool_t unconn); -IGRAPH_EXPORT igraph_error_t igraph_pseudo_diameter_dijkstra(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_real_t *diameter, - igraph_integer_t vid_start, - igraph_integer_t *from, - igraph_integer_t *to, - igraph_bool_t directed, - igraph_bool_t unconn); +IGRAPH_EXPORT igraph_error_t igraph_pseudo_diameter( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_real_t *diameter, igraph_integer_t vid_start, + igraph_integer_t *from, igraph_integer_t *to, + igraph_bool_t directed, igraph_bool_t unconn +); IGRAPH_EXPORT igraph_error_t igraph_get_all_simple_paths(const igraph_t *graph, - igraph_vector_int_t *res, - igraph_integer_t from, - const igraph_vs_t to, - igraph_integer_t cutoff, - igraph_neimode_t mode); + igraph_vector_int_list_t *res, + igraph_integer_t from, + igraph_vs_t to, + igraph_integer_t minlen, + igraph_integer_t maxlen, + igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_random_walk(const igraph_t *graph, const igraph_vector_t *weights, @@ -324,14 +274,14 @@ IGRAPH_EXPORT igraph_error_t igraph_get_widest_path(const igraph_t *graph, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, + igraph_vs_t from, + igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, + igraph_vs_t from, + igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_voronoi(const igraph_t *graph, @@ -349,16 +299,6 @@ IGRAPH_EXPORT igraph_error_t igraph_vertex_path_from_edge_path( const igraph_vector_int_t *edge_path, igraph_vector_int_t *vertex_path, igraph_neimode_t mode); -/* Deprecated functions: */ - -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_random_edge_walk(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_vector_int_t *edgewalk, - igraph_integer_t start, - igraph_neimode_t mode, - igraph_integer_t steps, - igraph_random_walk_stuck_t stuck); - -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_pmt.h b/src/vendor/cigraph/include/igraph_pmt.h index de90c1ee3da..bcdee2a11c2 100644 --- a/src/vendor/cigraph/include/igraph_pmt.h +++ b/src/vendor/cigraph/include/igraph_pmt.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #define CONCAT2x(a,b) a ## _ ## b @@ -116,6 +111,9 @@ #elif defined(BASE_GRAPH) #define BASE igraph_t +#elif defined(BASE_ATTRIBUTE_RECORD) + #define BASE igraph_attribute_record_t + #elif defined(BASE_BITSET) #define BASE igraph_bitset_t @@ -159,11 +157,14 @@ #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 #elif defined(BITSET_LIST) #define FUNCTION(c) CONCAT2x(igraph_bitset_list,c) #define INTERNAL_FUNCTION(c) CONCAT2x(igraph_i_bitset_list,c) #define TYPE igraph_bitset_list_t - #else #if defined(BASE_IGRAPH_REAL) #define FUNCTION(a,c) CONCAT2(a,c) diff --git a/src/vendor/cigraph/include/igraph_pmt_off.h b/src/vendor/cigraph/include/igraph_pmt_off.h index 03ef43c7fd3..f0ed85fdad8 100644 --- a/src/vendor/cigraph/include/igraph_pmt_off.h +++ b/src/vendor/cigraph/include/igraph_pmt_off.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifdef ATOMIC diff --git a/src/vendor/cigraph/include/igraph_progress.h b/src/vendor/cigraph/include/igraph_progress.h index f85139a412d..19bc2fb4aa6 100644 --- a/src/vendor/cigraph/include/igraph_progress.h +++ b/src/vendor/cigraph/include/igraph_progress.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_PROGRESS_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \section about_progress_handlers About progress handlers @@ -138,9 +133,8 @@ __BEGIN_DECLS * reporting, and then pass some meaningfull context here. * \return If the return value of the progress handler is not * \c IGRAPH_SUCCESS, then \ref igraph_progress() returns the - * error code \c IGRAPH_INTERRUPTED. The \ref IGRAPH_PROGRESS() - * macro frees all memory and finishes the igraph function with - * error code \c IGRAPH_INTERRUPTED in this case. + * error code from the progress handler intact. The \ref IGRAPH_PROGRESS() + * macro also frees all allocated memory. */ typedef igraph_error_t igraph_progress_handler_t(const char *message, igraph_real_t percent, @@ -157,7 +151,7 @@ IGRAPH_EXPORT igraph_error_t igraph_progressf(const char *message, igraph_real_t /** * \define IGRAPH_PROGRESS - * \brief Report progress. + * \brief Report the progress of a calculation from an igraph function (macro variant). * * The standard way to report progress from an igraph function * \param message A string, a textual message that references the @@ -165,20 +159,39 @@ IGRAPH_EXPORT igraph_error_t igraph_progressf(const char *message, igraph_real_t * \param percent Numeric scalar, the percentage that is complete. * \param data User-defined data, this can be used in user-defined * progress handler functions, from user-written igraph functions. - * \return If the progress handler returns with \c IGRAPH_INTERRUPTED, - * then this macro frees up the igraph allocated memory for - * temporary data and returns to the caller with \c - * IGRAPH_INTERRUPTED. + * \return If the return value of the progress handler is not + * \c IGRAPH_SUCCESS, then \ref igraph_progress() returns the + * error code from the progress handler intact. The \ref IGRAPH_PROGRESS() + * macro also frees all allocated memory. */ #define IGRAPH_PROGRESS(message, percent, data) \ do { \ - if (igraph_progress((message), (percent), (data)) != IGRAPH_SUCCESS) { \ - IGRAPH_FINALLY_FREE(); \ - return IGRAPH_INTERRUPTED; \ - } \ + IGRAPH_CHECK(igraph_progress((message), (percent), (data))); \ + } while (0) + +/** + * \define IGRAPH_PROGRESSF + * \brief Report the progress of a calculation from an igraph function, printf-like (macro variant). + * + * This is the more flexible version of \ref IGRAPH_PROGRESS(), + * having a printf-like syntax. As this macro takes variable + * number of arguments, they must be all supplied as a single + * argument, enclosed in parentheses. \ref igraph_progressf() is then + * called with the given arguments. + * + * \param args The arguments to pass to \ref igraph_progressf(). + * \return If the progress handler returns with a value other than + * \c IGRAPH_SUCCESS, then the function that called this + * macro returns as well, with the same error code, after + * cleaning up all allocated memory as needed. + */ + +#define IGRAPH_PROGRESSF(args) \ + do { \ + IGRAPH_CHECK(igraph_progressf args); \ } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_psumtree.h b/src/vendor/cigraph/include/igraph_psumtree.h index 2588680f7af..3811c203cc7 100644 --- a/src/vendor/cigraph/include/igraph_psumtree.h +++ b/src/vendor/cigraph/include/igraph_psumtree.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_PSUMTREE_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef struct { igraph_vector_t v; @@ -47,6 +42,6 @@ IGRAPH_EXPORT igraph_error_t igraph_psumtree_update(igraph_psumtree_t *t, igraph igraph_real_t new_value); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_psumtree_sum(const igraph_psumtree_t *t); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_qsort.h b/src/vendor/cigraph/include/igraph_qsort.h index 94e5e7f6777..e32362a3215 100644 --- a/src/vendor/cigraph/include/igraph_qsort.h +++ b/src/vendor/cigraph/include/igraph_qsort.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard st, Cambridge, MA 02139, USA + Copyright (C) 2011-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_QSORT_H @@ -28,13 +23,13 @@ #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT void igraph_qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *)); IGRAPH_EXPORT void igraph_qsort_r(void *base, size_t nel, size_t width, void *thunk, int (*compar)(void *, const void *, const void *)); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_random.h b/src/vendor/cigraph/include/igraph_random.h index 6d8af083b23..ff60b1eacd6 100644 --- a/src/vendor/cigraph/include/igraph_random.h +++ b/src/vendor/cigraph/include/igraph_random.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2003-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2003-2025 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 @@ -15,24 +13,21 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_RANDOM_H #define IGRAPH_RANDOM_H #include "igraph_decls.h" +#include "igraph_error.h" #include "igraph_types.h" -#include "igraph_vector.h" #include #include #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* The new RNG interface is (somewhat) modelled on the GSL */ @@ -141,8 +136,6 @@ IGRAPH_EXPORT igraph_real_t igraph_rng_get_gamma( igraph_rng_t *rng, igraph_real_t shape, igraph_real_t scale ); IGRAPH_EXPORT igraph_real_t igraph_rng_get_pois(igraph_rng_t *rng, igraph_real_t rate); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_rng_get_dirichlet( - igraph_rng_t *rng, const igraph_vector_t *alpha, igraph_vector_t *result); /* --------------------------------- */ @@ -152,28 +145,10 @@ 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); /* --------------------------------- */ -#ifdef USING_R - -void GetRNGstate(void); -void PutRNGstate(void); -#define RNG_BEGIN() GetRNGstate() -#define RNG_END() PutRNGstate() - -#else - -#define RNG_BEGIN() \ - do { if (!igraph_rng_default()->is_seeded) { \ - igraph_rng_seed(igraph_rng_default(), time(0)); \ - igraph_rng_default()->is_seeded = true; \ - } } while (0) -#define RNG_END() \ - do { /* nothing */ } while (0) -#endif - #define RNG_BOOL() (igraph_rng_get_bool(igraph_rng_default())) #define RNG_INTEGER(l,h) (igraph_rng_get_integer(igraph_rng_default(),(l),(h))) #define RNG_NORMAL(m,s) (igraph_rng_get_normal(igraph_rng_default(),(m),(s))) @@ -186,6 +161,6 @@ void PutRNGstate(void); #define RNG_GAMMA(shape, scale) \ (igraph_rng_get_gamma(igraph_rng_default(), (shape), (scale))) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_reachability.h b/src/vendor/cigraph/include/igraph_reachability.h index 472655e8b9a..8c99fd8502c 100644 --- a/src/vendor/cigraph/include/igraph_reachability.h +++ b/src/vendor/cigraph/include/igraph_reachability.h @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2024 The igraph development team + Copyright (C) 2024-2025 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 @@ -25,7 +25,7 @@ #include "igraph_error.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_reachability( const igraph_t *graph, @@ -44,6 +44,6 @@ IGRAPH_EXPORT igraph_error_t igraph_count_reachable( IGRAPH_EXPORT igraph_error_t igraph_transitive_closure(const igraph_t *graph, igraph_t* closure); -__END_DECLS +IGRAPH_END_C_DECLS #endif // IGRAPH_REACHABILITY_H diff --git a/src/vendor/cigraph/include/igraph_sampling.h b/src/vendor/cigraph/include/igraph_sampling.h new file mode 100644 index 00000000000..a9a5725ccbd --- /dev/null +++ b/src/vendor/cigraph/include/igraph_sampling.h @@ -0,0 +1,45 @@ +/* + IGraph library. + Copyright (C) 2003-2025 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 . +*/ + +#ifndef IGRAPH_SAMPLING_H +#define IGRAPH_SAMPLING_H + +#include "igraph_decls.h" +#include "igraph_error.h" +#include "igraph_matrix.h" +#include "igraph_random.h" + +IGRAPH_BEGIN_C_DECLS + +IGRAPH_EXPORT igraph_error_t igraph_rng_sample_sphere_surface( + igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_bool_t positive, igraph_matrix_t *res +); + +IGRAPH_EXPORT igraph_error_t igraph_rng_sample_sphere_volume( + igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_bool_t positive, igraph_matrix_t *res +); + +IGRAPH_EXPORT igraph_error_t igraph_rng_sample_dirichlet( + igraph_rng_t* rng, igraph_integer_t n, const igraph_vector_t *alpha, igraph_matrix_t *res +); + +IGRAPH_END_C_DECLS + +#endif diff --git a/src/vendor/cigraph/include/igraph_scan.h b/src/vendor/cigraph/include/igraph_scan.h index bfc47c46626..60199f05d7e 100644 --- a/src/vendor/cigraph/include/igraph_scan.h +++ b/src/vendor/cigraph/include/igraph_scan.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2013 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2013-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_SCAN_H @@ -30,7 +25,7 @@ #include "igraph_error.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_local_scan_0(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_t *weights, igraph_neimode_t mode); @@ -67,6 +62,6 @@ IGRAPH_EXPORT igraph_error_t igraph_local_scan_subset_ecount(const igraph_t *gra igraph_vector_t *res, const igraph_vector_t *weights, const igraph_vector_int_list_t *neighborhoods); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_separators.h b/src/vendor/cigraph/include/igraph_separators.h index 7008d9261b1..5e2a16abe37 100644 --- a/src/vendor/cigraph/include/igraph_separators.h +++ b/src/vendor/cigraph/include/igraph_separators.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_SEPARATORS_H @@ -32,22 +27,22 @@ #include "igraph_types.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_is_separator(const igraph_t *graph, - const igraph_vs_t candidate, + igraph_vs_t candidate, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_all_minimal_st_separators(const igraph_t *graph, igraph_vector_int_list_t *separators); IGRAPH_EXPORT igraph_error_t igraph_is_minimal_separator(const igraph_t *graph, - const igraph_vs_t candidate, + igraph_vs_t candidate, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_minimum_size_separators(const igraph_t *graph, igraph_vector_int_list_t *separators); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_setup.h b/src/vendor/cigraph/include/igraph_setup.h new file mode 100644 index 00000000000..58e2ab41da2 --- /dev/null +++ b/src/vendor/cigraph/include/igraph_setup.h @@ -0,0 +1,31 @@ +/* + IGraph library. + Copyright (C) 2003-2025 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 . +*/ + +#ifndef IGRAPH_SETUP_H +#define IGRAPH_SETUP_H + +#include "igraph_decls.h" +#include "igraph_error.h" + +IGRAPH_BEGIN_C_DECLS + +IGRAPH_EXPORT igraph_error_t igraph_setup(void); + +IGRAPH_END_C_DECLS + +#endif diff --git a/src/vendor/cigraph/include/igraph_sparsemat.h b/src/vendor/cigraph/include/igraph_sparsemat.h index f054a1d4038..b390fa1d78b 100644 --- a/src/vendor/cigraph/include/igraph_sparsemat.h +++ b/src/vendor/cigraph/include/igraph_sparsemat.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_SPARSEMAT_H @@ -33,7 +28,7 @@ #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* * These types are private to igraph, and customized to use igraph_integer_t. @@ -156,13 +151,6 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_lusol(const igraph_sparsemat_t *A, IGRAPH_EXPORT igraph_error_t igraph_sparsemat_print(const igraph_sparsemat_t *A, FILE *outstream); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_sparsemat(igraph_t *graph, const igraph_sparsemat_t *A, - igraph_bool_t directed); - -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_weighted_sparsemat(igraph_t *graph, const igraph_sparsemat_t *A, - igraph_bool_t directed, const char *attr, - igraph_bool_t loops); - IGRAPH_EXPORT igraph_error_t igraph_matrix_as_sparsemat(igraph_sparsemat_t *res, const igraph_matrix_t *mat, igraph_real_t tol); @@ -298,15 +286,6 @@ IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_iterator_idx(const igraph_sparse IGRAPH_EXPORT igraph_real_t igraph_sparsemat_iterator_get(const igraph_sparsemat_iterator_t *it); IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_iterator_next(igraph_sparsemat_iterator_t *it); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_sparsemat_copy( - igraph_sparsemat_t *to, const igraph_sparsemat_t *from); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_sparsemat_diag( - igraph_sparsemat_t *A, igraph_integer_t nzmax, const igraph_vector_t *values, - igraph_bool_t compress); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_sparsemat_eye( - igraph_sparsemat_t *A, igraph_integer_t n, igraph_integer_t nzmax, - igraph_real_t value, igraph_bool_t compress); - -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_spatial.h b/src/vendor/cigraph/include/igraph_spatial.h new file mode 100644 index 00000000000..a4eeb0b1a08 --- /dev/null +++ b/src/vendor/cigraph/include/igraph_spatial.h @@ -0,0 +1,55 @@ +/* + IGraph library. + Copyright (C) 2025 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 . +*/ + +#ifndef IGRAPH_SPATIAL_H +#define IGRAPH_SPATIAL_H + +#include "igraph_datatype.h" +#include "igraph_decls.h" +#include "igraph_types.h" +#include "igraph_error.h" +#include "igraph_matrix.h" + +IGRAPH_BEGIN_C_DECLS + +/** + * \typedef igraph_metric_t + * \brief Metric functions for use with spatial computation. + * + * \enumval IGRAPH_METRIC_EUCLIDEAN The Euclidean distance, i.e. L2 metric. + * \enumval IGRAPH_METRIC_MANHATTAN The Manhattan distance, i.e. L1 metric. + */ +typedef enum { + IGRAPH_METRIC_EUCLIDEAN = 0, + IGRAPH_METRIC_L2 = IGRAPH_METRIC_EUCLIDEAN, + IGRAPH_METRIC_MANHATTAN = 1, + IGRAPH_METRIC_L1 = IGRAPH_METRIC_MANHATTAN +} igraph_metric_t; + +IGRAPH_EXPORT igraph_error_t igraph_nearest_neighbor_graph( + igraph_t *graph, + const igraph_matrix_t *points, + igraph_metric_t metric, + igraph_integer_t neighbors, + igraph_real_t cutoff, + igraph_bool_t directed +); + +IGRAPH_END_C_DECLS + +#endif diff --git a/src/vendor/cigraph/include/igraph_stack.h b/src/vendor/cigraph/include/igraph_stack.h index 30f9b44ac28..616231b245f 100644 --- a/src/vendor/cigraph/include/igraph_stack.h +++ b/src/vendor/cigraph/include/igraph_stack.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_STACK_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Plain stack */ @@ -66,6 +61,6 @@ __BEGIN_DECLS do { IGRAPH_CHECK(igraph_stack_int_init(s, capacity)); \ IGRAPH_FINALLY(igraph_stack_int_destroy, s); } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_stack_pmt.h b/src/vendor/cigraph/include/igraph_stack_pmt.h index d0a5a25e096..fc0fcfbd516 100644 --- a/src/vendor/cigraph/include/igraph_stack_pmt.h +++ b/src/vendor/cigraph/include/igraph_stack_pmt.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #include diff --git a/src/vendor/cigraph/include/igraph_statusbar.h b/src/vendor/cigraph/include/igraph_statusbar.h index c6069bfb309..d9b1e532640 100644 --- a/src/vendor/cigraph/include/igraph_statusbar.h +++ b/src/vendor/cigraph/include/igraph_statusbar.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_STATUSBAR_H @@ -27,7 +22,7 @@ #include "igraph_decls.h" #include "igraph_error.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \section about_status_handlers Status reporting @@ -86,16 +81,13 @@ IGRAPH_EXPORT igraph_error_t igraph_status(const char *message, void *data); * Existing igraph functions pass a null pointer here. * \return If the status handler returns with a value other than * \c IGRAPH_SUCCESS, then the function that called this - * macro returns as well, with error code - * \c IGRAPH_INTERRUPTED. + * macro returns as well, with the same error code, after + * cleaning up all allocated memory as needed. */ #define IGRAPH_STATUS(message, data) \ do { \ - if (igraph_status((message), (data)) != IGRAPH_SUCCESS) { \ - IGRAPH_FINALLY_FREE(); \ - return IGRAPH_INTERRUPTED; \ - } \ + IGRAPH_CHECK(igraph_status((message), (data))); \ } while (0) IGRAPH_EXPORT igraph_error_t igraph_statusf(const char *message, void *data, ...); @@ -107,23 +99,21 @@ IGRAPH_EXPORT igraph_error_t igraph_statusf(const char *message, void *data, ... * This is the more flexible version of \ref IGRAPH_STATUS(), * having a printf-like syntax. As this macro takes variable * number of arguments, they must be all supplied as a single - * argument, enclosed in parentheses. Then \ref igraph_statusf() - * is called with the given arguments. + * argument, enclosed in parentheses. \ref igraph_statusf() is then + * called with the given arguments. + * * \param args The arguments to pass to \ref igraph_statusf(). * \return If the status handler returns with a value other than * \c IGRAPH_SUCCESS, then the function that called this - * macro returns as well, with error code - * \c IGRAPH_INTERRUPTED. + * macro returns as well, with the same error code, after + * cleaning up all allocated memory as needed. */ #define IGRAPH_STATUSF(args) \ do { \ - if (igraph_statusf args != IGRAPH_SUCCESS) { \ - IGRAPH_FINALLY_FREE(); \ - return IGRAPH_INTERRUPTED; \ - } \ + IGRAPH_CHECK(igraph_statusf args); \ } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_structural.h b/src/vendor/cigraph/include/igraph_structural.h index 1ff600b164e..5508a111f12 100644 --- a/src/vendor/cigraph/include/igraph_structural.h +++ b/src/vendor/cigraph/include/igraph_structural.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_STRUCTURAL_H @@ -34,20 +29,19 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Basic query functions */ /* -------------------------------------------------- */ IGRAPH_EXPORT igraph_error_t igraph_are_adjacent(const igraph_t *graph, igraph_integer_t v1, igraph_integer_t v2, igraph_bool_t *res); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_are_connected(const igraph_t *graph, igraph_integer_t v1, igraph_integer_t v2, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_count_multiple(const igraph_t *graph, igraph_vector_int_t *res, igraph_es_t es); IGRAPH_EXPORT igraph_error_t igraph_count_multiple_1(const igraph_t *graph, igraph_integer_t *res, igraph_integer_t eid); IGRAPH_EXPORT igraph_error_t igraph_density(const igraph_t *graph, igraph_real_t *res, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_diversity(const igraph_t *graph, const igraph_vector_t *weights, - igraph_vector_t *res, const igraph_vs_t vs); + igraph_vector_t *res, igraph_vs_t vs); IGRAPH_EXPORT igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth, igraph_vector_int_t *circle); IGRAPH_EXPORT igraph_error_t igraph_has_loop(const igraph_t *graph, igraph_bool_t *res); @@ -59,29 +53,28 @@ IGRAPH_EXPORT igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_ve igraph_es_t es); IGRAPH_EXPORT igraph_error_t igraph_is_mutual(const igraph_t *graph, igraph_vector_bool_t *res, igraph_es_t es, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_has_mutual(const igraph_t *graph, igraph_bool_t *res, igraph_bool_t loops); -IGRAPH_EXPORT igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res); +IGRAPH_EXPORT igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res, igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_integer_t *root, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_is_acyclic(const igraph_t *graph, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_is_forest(const igraph_t *graph, igraph_bool_t *res, igraph_vector_int_t *roots, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_maxdegree(const igraph_t *graph, igraph_integer_t *res, igraph_vs_t vids, igraph_neimode_t mode, - igraph_bool_t loops); + igraph_loops_t loops); IGRAPH_EXPORT igraph_error_t igraph_mean_degree(const igraph_t *graph, igraph_real_t *res, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_reciprocity(const igraph_t *graph, igraph_real_t *res, igraph_bool_t ignore_loops, igraph_reciprocity_t mode); -IGRAPH_EXPORT igraph_error_t igraph_strength(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, - igraph_bool_t loops, const igraph_vector_t *weights); -IGRAPH_EXPORT igraph_error_t igraph_sort_vertex_ids_by_degree(const igraph_t *graph, - igraph_vector_int_t *outvids, - igraph_vs_t vids, - igraph_neimode_t mode, - igraph_bool_t loops, - igraph_order_t order, - igraph_bool_t only_indices); +IGRAPH_EXPORT igraph_error_t igraph_strength( + const igraph_t *graph, igraph_vector_t *res, igraph_vs_t vids, + igraph_neimode_t mode, igraph_loops_t loops, const igraph_vector_t *weights +); +IGRAPH_EXPORT igraph_error_t igraph_sort_vertex_ids_by_degree( + const igraph_t *graph, igraph_vector_int_t *outvids, igraph_vs_t vids, + igraph_neimode_t mode, igraph_loops_t loops, igraph_order_t order, + igraph_bool_t only_indices +); IGRAPH_EXPORT igraph_error_t igraph_is_perfect(const igraph_t *graph, igraph_bool_t *perfect); /* -------------------------------------------------- */ @@ -93,12 +86,9 @@ IGRAPH_EXPORT igraph_error_t igraph_is_clique(const igraph_t *graph, igraph_vs_t igraph_bool_t directed, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_is_independent_vertex_set(const igraph_t *graph, igraph_vs_t candidate, igraph_bool_t *res); -IGRAPH_EXPORT igraph_error_t igraph_minimum_spanning_tree(const igraph_t *graph, igraph_vector_int_t *res, - const igraph_vector_t *weights); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_minimum_spanning_tree_unweighted(const igraph_t *graph, - igraph_t *mst); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_minimum_spanning_tree_prim(const igraph_t *graph, igraph_t *mst, - const igraph_vector_t *weights); +IGRAPH_EXPORT igraph_error_t igraph_minimum_spanning_tree( + const igraph_t *graph, igraph_vector_int_t *res, + const igraph_vector_t *weights, igraph_mst_algorithm_t method); IGRAPH_EXPORT igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_int_t *res, igraph_integer_t vid); @@ -139,6 +129,16 @@ IGRAPH_EXPORT igraph_error_t igraph_feedback_vertex_set( const igraph_t *graph, igraph_vector_int_t *result, const igraph_vector_t *vertex_weights, igraph_fvs_algorithm_t algo); +IGRAPH_EXPORT igraph_error_t igraph_rich_club_sequence( + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_vector_t *res, + const igraph_vector_int_t *vertex_order, + igraph_bool_t normalized, + igraph_bool_t loops, + igraph_bool_t directed); + + /* -------------------------------------------------- */ /* Spectral Properties */ /* -------------------------------------------------- */ @@ -175,11 +175,7 @@ IGRAPH_EXPORT igraph_error_t igraph_get_laplacian_sparse( igraph_laplacian_normalization_t normalization, const igraph_vector_t *weights ); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_laplacian( - const igraph_t *graph, igraph_matrix_t *res, igraph_sparsemat_t *sparseres, - igraph_bool_t normalized, const igraph_vector_t *weights -); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_strvector.h b/src/vendor/cigraph/include/igraph_strvector.h index c01b695d3b0..bbd7f03160a 100644 --- a/src/vendor/cigraph/include/igraph_strvector.h +++ b/src/vendor/cigraph/include/igraph_strvector.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_STRVECTOR_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * Vector of strings @@ -37,9 +32,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; /** @@ -51,7 +46,7 @@ typedef struct s_igraph_strvector { * element. Use \ref igraph_strvector_set() to set an element instead. * * \param sv The string vector - * \param i The the index of the element. + * \param i The index of the element. * \return The element at position \p i. * * Time complexity: O(1). @@ -87,15 +82,20 @@ 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 void igraph_strvector_resize_min(igraph_strvector_t *sv); IGRAPH_EXPORT igraph_error_t igraph_strvector_push_back(igraph_strvector_t *v, const char *value); IGRAPH_EXPORT igraph_error_t igraph_strvector_push_back_len(igraph_strvector_t *v, - const char *value, igraph_integer_t len); -IGRAPH_EXPORT igraph_error_t igraph_strvector_print(const igraph_strvector_t *v, FILE *file, - const char *sep); + const char *value, size_t len); +IGRAPH_EXPORT igraph_error_t igraph_strvector_fprint(const igraph_strvector_t *v, FILE *file, + const char *sep); +IGRAPH_EXPORT igraph_error_t igraph_strvector_print(const igraph_strvector_t *v, + const char *sep); IGRAPH_EXPORT igraph_error_t igraph_strvector_index(const igraph_strvector_t *v, igraph_strvector_t *newv, @@ -107,13 +107,6 @@ IGRAPH_EXPORT igraph_error_t igraph_strvector_reserve(igraph_strvector_t *sv, IGRAPH_EXPORT void igraph_strvector_swap_elements(igraph_strvector_t *sv, igraph_integer_t i, igraph_integer_t j); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_strvector_add(igraph_strvector_t *v, const char *value); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_strvector_copy( - igraph_strvector_t *to, const igraph_strvector_t *from); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_strvector_set2( - igraph_strvector_t *sv, igraph_integer_t idx, const char *value, size_t len -); - -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_threading.h.in b/src/vendor/cigraph/include/igraph_threading.h.in index 1ddeb118d3f..555b7ff39e9 100644 --- a/src/vendor/cigraph/include/igraph_threading.h.in +++ b/src/vendor/cigraph/include/igraph_threading.h.in @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2011-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_THREADING_H @@ -26,7 +21,7 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \define IGRAPH_THREAD_SAFE @@ -42,6 +37,6 @@ __BEGIN_DECLS #cmakedefine01 IGRAPH_THREAD_SAFE -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_transitivity.h b/src/vendor/cigraph/include/igraph_transitivity.h index 9566561f6a2..d830171f70f 100644 --- a/src/vendor/cigraph/include/igraph_transitivity.h +++ b/src/vendor/cigraph/include/igraph_transitivity.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_TRANSITIVITY_H @@ -30,23 +25,23 @@ #include "igraph_error.h" #include "igraph_iterators.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_transitivity_undirected(const igraph_t *graph, igraph_real_t *res, igraph_transitivity_mode_t mode); IGRAPH_EXPORT igraph_error_t igraph_transitivity_local_undirected(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, + igraph_vs_t vids, igraph_transitivity_mode_t mode); IGRAPH_EXPORT igraph_error_t igraph_transitivity_avglocal_undirected(const igraph_t *graph, igraph_real_t *res, igraph_transitivity_mode_t mode); IGRAPH_EXPORT igraph_error_t igraph_transitivity_barrat(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, + igraph_vs_t vids, const igraph_vector_t *weights, - const igraph_transitivity_mode_t mode); + igraph_transitivity_mode_t mode); IGRAPH_EXPORT igraph_error_t igraph_ecc(const igraph_t *graph, igraph_vector_t *res, igraph_es_t eids, @@ -54,6 +49,6 @@ IGRAPH_EXPORT igraph_error_t igraph_ecc(const igraph_t *graph, igraph_bool_t offset, igraph_bool_t normalize); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_typed_list_pmt.h b/src/vendor/cigraph/include/igraph_typed_list_pmt.h index 2110d5558d1..a4036907a69 100644 --- a/src/vendor/cigraph/include/igraph_typed_list_pmt.h +++ b/src/vendor/cigraph/include/igraph_typed_list_pmt.h @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2021 The igraph development team + Copyright (C) 2021-2025 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 @@ -14,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #if defined(VECTOR_LIST) @@ -51,6 +47,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); /*--------------------*/ @@ -102,8 +99,8 @@ IGRAPH_EXPORT void FUNCTION(remove_consecutive_duplicates)(TYPE *v, igraph_bool_ IGRAPH_EXPORT igraph_error_t FUNCTION(permute)(TYPE *v, const igraph_vector_int_t *index); IGRAPH_EXPORT igraph_error_t FUNCTION(reverse)(TYPE *v); -IGRAPH_EXPORT igraph_error_t FUNCTION(swap)(TYPE *v1, TYPE *v2); -IGRAPH_EXPORT igraph_error_t FUNCTION(swap_elements)(TYPE* v, igraph_integer_t i, igraph_integer_t j); +IGRAPH_EXPORT void FUNCTION(swap)(TYPE *v1, TYPE *v2); +IGRAPH_EXPORT void FUNCTION(swap_elements)(TYPE* v, igraph_integer_t i, igraph_integer_t j); /*-----------*/ /* Sorting */ diff --git a/src/vendor/cigraph/include/igraph_types.h b/src/vendor/cigraph/include/igraph_types.h index 81f22cfe5f9..19e93338b35 100644 --- a/src/vendor/cigraph/include/igraph_types.h +++ b/src/vendor/cigraph/include/igraph_types.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2003-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2003-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_TYPES_H @@ -26,7 +21,7 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS #ifdef __cplusplus #define __STDC_FORMAT_MACROS /* needed for PRId32 and PRId64 from inttypes.h on Linux */ @@ -54,6 +49,8 @@ typedef uint32_t igraph_uint_t; # error "Invalid igraph integer size; check the value of IGRAPH_INTEGER_SIZE when compiling" #endif +typedef igraph_integer_t igraph_int_t; + typedef double igraph_real_t; /* IGRAPH_BOOL_TYPE is set to 'bool' by default, and it is not meant to be @@ -138,19 +135,8 @@ IGRAPH_EXPORT int igraph_real_fprintf_precise(FILE *file, igraph_real_t val); IGRAPH_EXPORT int igraph_real_snprintf_precise(char *str, size_t size, igraph_real_t val); #define IGRAPH_INFINITY ((double)INFINITY) -#define IGRAPH_POSINFINITY IGRAPH_INFINITY -#define IGRAPH_NEGINFINITY (-IGRAPH_INFINITY) - -IGRAPH_DEPRECATED IGRAPH_EXPORT int igraph_finite(double x); -#define IGRAPH_FINITE(x) igraph_finite(x) - -IGRAPH_DEPRECATED IGRAPH_EXPORT int igraph_is_nan(double x); -IGRAPH_DEPRECATED IGRAPH_EXPORT int igraph_is_inf(double x); -IGRAPH_DEPRECATED IGRAPH_EXPORT int igraph_is_posinf(double x); -IGRAPH_DEPRECATED IGRAPH_EXPORT int igraph_is_neginf(double x); - #define IGRAPH_NAN ((double)NAN) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_vector.h b/src/vendor/cigraph/include/igraph_vector.h index 24e86529093..463b79ec632 100644 --- a/src/vendor/cigraph/include/igraph_vector.h +++ b/src/vendor/cigraph/include/igraph_vector.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_VECTOR_H @@ -30,7 +25,7 @@ #include "igraph_error.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Flexible vector */ @@ -132,13 +127,9 @@ __BEGIN_DECLS IGRAPH_EXPORT igraph_error_t igraph_vector_floor(const igraph_vector_t *from, igraph_vector_int_t *to); IGRAPH_EXPORT igraph_error_t igraph_vector_round(const igraph_vector_t *from, igraph_vector_int_t *to); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_bool_t igraph_vector_e_tol(const igraph_vector_t *lhs, - const igraph_vector_t *rhs, - igraph_real_t tol); - IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_vector_all_almost_e(const igraph_vector_t *lhs, - const igraph_vector_t *rhs, - igraph_real_t eps); + const igraph_vector_t *rhs, + igraph_real_t eps); IGRAPH_EXPORT igraph_error_t igraph_vector_zapsmall(igraph_vector_t *v, igraph_real_t tol); IGRAPH_EXPORT igraph_error_t igraph_vector_complex_zapsmall(igraph_vector_complex_t *v, igraph_real_t tol) ; @@ -148,18 +139,20 @@ IGRAPH_EXPORT igraph_error_t igraph_vector_is_nan(const igraph_vector_t *v, IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_vector_is_any_nan(const igraph_vector_t *v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_vector_is_all_finite(const igraph_vector_t *v); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_vector_order2(igraph_vector_t *v); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_vector_rank(const igraph_vector_t *v, igraph_vector_int_t *res, - igraph_integer_t nodes); - IGRAPH_EXPORT igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, const igraph_vector_int_t *v2, igraph_vector_int_t* res, igraph_integer_t maxval); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_vector_int_order1(const igraph_vector_int_t* v, - igraph_vector_int_t* res, igraph_integer_t maxval); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_vector_int_rank(const igraph_vector_int_t *v, igraph_vector_int_t *res, - igraph_integer_t nodes); +/* For internal use only: */ + +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_vector_int_order( + const igraph_vector_int_t* v, + igraph_vector_int_t* res, + igraph_integer_t maxval); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_vector_int_rank( + const igraph_vector_int_t *v, + igraph_vector_int_t *res, + igraph_integer_t maxval); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_vector_list.h b/src/vendor/cigraph/include/igraph_vector_list.h index dc45323b18d..8fff22fd509 100644 --- a/src/vendor/cigraph/include/igraph_vector_list.h +++ b/src/vendor/cigraph/include/igraph_vector_list.h @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2022 The igraph development team + Copyright (C) 2022-2025 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 @@ -14,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_VECTOR_LIST_H @@ -27,7 +23,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Flexible list of vectors */ @@ -62,6 +58,6 @@ __BEGIN_DECLS do { IGRAPH_CHECK(igraph_vector_int_list_init(v, size)); \ IGRAPH_FINALLY(igraph_vector_int_list_destroy, v); } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_vector_pmt.h b/src/vendor/cigraph/include/igraph_vector_pmt.h index 3cedc0eb351..43a708b8043 100644 --- a/src/vendor/cigraph/include/igraph_vector_pmt.h +++ b/src/vendor/cigraph/include/igraph_vector_pmt.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2007-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ /*--------------------*/ @@ -34,11 +29,8 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_copy)( #ifndef NOTORDERED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_range)(TYPE(igraph_vector)*v, BASE start, BASE end); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t FUNCTION(igraph_vector, init_seq)(TYPE(igraph_vector)*v, BASE from, BASE to); #endif -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t FUNCTION(igraph_vector, copy)( - TYPE(igraph_vector) *to, const TYPE(igraph_vector) *from); IGRAPH_EXPORT void FUNCTION(igraph_vector, destroy)(TYPE(igraph_vector) *v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, capacity)(const TYPE(igraph_vector)*v); @@ -68,8 +60,6 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, capa #define VECTOR(v) ((v).stor_begin) #endif -IGRAPH_EXPORT IGRAPH_DEPRECATED BASE FUNCTION(igraph_vector, e)(const TYPE(igraph_vector) *v, igraph_integer_t pos); -IGRAPH_EXPORT IGRAPH_DEPRECATED BASE* FUNCTION(igraph_vector, e_ptr)(const TYPE(igraph_vector) *v, igraph_integer_t pos); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_vector, get)(const TYPE(igraph_vector) *v, igraph_integer_t pos); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE* FUNCTION(igraph_vector, get_ptr)(const TYPE(igraph_vector) *v, igraph_integer_t pos); IGRAPH_EXPORT void FUNCTION(igraph_vector, set)(TYPE(igraph_vector) *v, igraph_integer_t pos, BASE value); @@ -103,22 +93,22 @@ 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 */ /*-----------------------*/ -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, swap_elements)( +IGRAPH_EXPORT void FUNCTION(igraph_vector, swap_elements)( TYPE(igraph_vector) *v, igraph_integer_t i, igraph_integer_t j); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v); +IGRAPH_EXPORT void FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v); IGRAPH_EXPORT void FUNCTION(igraph_vector, reverse_section)( TYPE(igraph_vector) *v, igraph_integer_t from, igraph_integer_t to); IGRAPH_EXPORT void FUNCTION(igraph_vector, rotate_left)( TYPE(igraph_vector) *v, igraph_integer_t n); 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 */ @@ -216,8 +206,6 @@ IGRAPH_EXPORT igraph_bool_t FUNCTION(igraph_vector, binsearch_slice)( IGRAPH_EXPORT igraph_bool_t FUNCTION(igraph_vector, binsearch)( const TYPE(igraph_vector) *v, BASE what, igraph_integer_t *pos); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_vector, contains_sorted)( - const TYPE(igraph_vector) *v, BASE what); -IGRAPH_DEPRECATED IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_vector, binsearch2)( const TYPE(igraph_vector) *v, BASE what); #endif @@ -253,9 +241,6 @@ IGRAPH_EXPORT void FUNCTION(igraph_vector, reverse_sort)(TYPE(igraph_vector) *v) IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, sort_ind)( const TYPE(igraph_vector) *v, igraph_vector_int_t *inds, igraph_order_t order); -IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, qsort_ind)( - const TYPE(igraph_vector) *v, igraph_vector_int_t *inds, igraph_order_t order); - #endif /*-----------*/ @@ -303,9 +288,6 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_int_end)(TYPE(igraph_v IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, move_interval)( TYPE(igraph_vector) *v, igraph_integer_t begin, igraph_integer_t end, igraph_integer_t to); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t FUNCTION(igraph_vector, move_interval2)( - TYPE(igraph_vector) *v, igraph_integer_t begin, igraph_integer_t end, - igraph_integer_t to); #ifndef NOTORDERED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, filter_smaller)(TYPE(igraph_vector) *v, BASE elem); #endif @@ -324,6 +306,5 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, inte IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, index)(const TYPE(igraph_vector) *v, TYPE(igraph_vector) *newv, const igraph_vector_int_t *idx); - -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, index_int)(TYPE(igraph_vector) *v, +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, index_in_place)(TYPE(igraph_vector) *v, const igraph_vector_int_t *idx); diff --git a/src/vendor/cigraph/include/igraph_vector_ptr.h b/src/vendor/cigraph/include/igraph_vector_ptr.h index 77ba89cb70c..9bd4b6d3105 100644 --- a/src/vendor/cigraph/include/igraph_vector_ptr.h +++ b/src/vendor/cigraph/include/igraph_vector_ptr.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_VECTOR_PTR_H @@ -28,7 +23,7 @@ #include "igraph_error.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Flexible vector, storing pointers */ @@ -60,8 +55,10 @@ IGRAPH_EXPORT void igraph_vector_ptr_destroy(igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_free_all(igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_destroy_all(igraph_vector_ptr_t* v); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_integer_t capacity); +IGRAPH_EXPORT void igraph_vector_ptr_resize_min(igraph_vector_ptr_t* v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_vector_ptr_empty(const igraph_vector_ptr_t* v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_vector_ptr_capacity(const igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_clear(igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_null(igraph_vector_ptr_t* v); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_push_back(igraph_vector_ptr_t* v, void* e); @@ -69,8 +66,7 @@ IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_append(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from); IGRAPH_EXPORT void *igraph_vector_ptr_pop_back(igraph_vector_ptr_t *v); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_insert(igraph_vector_ptr_t *v, igraph_integer_t pos, void* e); -IGRAPH_EXPORT IGRAPH_DEPRECATED void* igraph_vector_ptr_e(const igraph_vector_ptr_t* v, igraph_integer_t pos); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE void* igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_integer_t pos); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_integer_t pos); IGRAPH_EXPORT void igraph_vector_ptr_set(igraph_vector_ptr_t* v, igraph_integer_t pos, void* value); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_resize(igraph_vector_ptr_t* v, igraph_integer_t newsize); IGRAPH_EXPORT void igraph_vector_ptr_copy_to(const igraph_vector_ptr_t *v, void** to); @@ -84,8 +80,6 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_finally_func_t* igraph_vector_ptr_get_ IGRAPH_EXPORT igraph_finally_func_t* igraph_vector_ptr_set_item_destructor(igraph_vector_ptr_t *v, igraph_finally_func_t *func); -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_vector_ptr_copy(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from); - /** * \define IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR * \brief Sets the item destructor for this pointer vector (macro version). @@ -100,6 +94,6 @@ IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_vector_ptr_copy(igraph_vec #define IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(v, func) \ igraph_vector_ptr_set_item_destructor((v), (igraph_finally_func_t*)(func)) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_vector_type.h b/src/vendor/cigraph/include/igraph_vector_type.h index fef9d9ff735..05a77855a8d 100644 --- a/src/vendor/cigraph/include/igraph_vector_type.h +++ b/src/vendor/cigraph/include/igraph_vector_type.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2013 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2013-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ /** diff --git a/src/vendor/cigraph/include/igraph_version.h.in b/src/vendor/cigraph/include/igraph_version.h.in index fda42278d82..477b390d4c3 100644 --- a/src/vendor/cigraph/include/igraph_version.h.in +++ b/src/vendor/cigraph/include/igraph_version.h.in @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_VERSION_H @@ -26,7 +21,7 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS #define IGRAPH_VERSION "@PACKAGE_VERSION@" #define IGRAPH_VERSION_MAJOR @PACKAGE_VERSION_MAJOR@ @@ -39,6 +34,6 @@ IGRAPH_EXPORT void igraph_version(const char **version_string, int *minor, int *subminor); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_visitor.h b/src/vendor/cigraph/include/igraph_visitor.h index 358467e3bf0..9f5f931a714 100644 --- a/src/vendor/cigraph/include/igraph_visitor.h +++ b/src/vendor/cigraph/include/igraph_visitor.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2009-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2009-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_VISITOR_H @@ -30,7 +25,7 @@ #include "igraph_types.h" #include "igraph_datatype.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Visitor-like functions */ @@ -134,6 +129,6 @@ IGRAPH_EXPORT igraph_error_t igraph_dfs(const igraph_t *graph, igraph_integer_t igraph_dfshandler_t *out_callback, void *extra); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml index d621d01fef0..cee8b524c3e 100644 --- a/src/vendor/cigraph/interfaces/functions.yaml +++ b/src/vendor/cigraph/interfaces/functions.yaml @@ -12,84 +12,106 @@ igraph_empty: PARAMS: OUT GRAPH graph, INTEGER n=0, BOOLEAN directed=True + FLAGS: no_rng igraph_add_edges: PARAMS: INOUT GRAPH graph, VERTEX_INDEX_PAIRS edges, ATTRIBUTES attr DEPS: edges ON graph + FLAGS: no_rng igraph_empty_attrs: PARAMS: OUT GRAPH graph, INTEGER n, BOOLEAN directed, ATTRIBUTES attr + FLAGS: no_rng igraph_add_vertices: PARAMS: INOUT GRAPH graph, INTEGER nv, ATTRIBUTES attr + FLAGS: no_rng igraph_copy: PARAMS: OUT GRAPH to, IN GRAPH from + FLAGS: no_rng igraph_delete_edges: PARAMS: INOUT GRAPH graph, EDGE_SELECTOR edges DEPS: edges ON graph + FLAGS: no_rng igraph_delete_vertices: PARAMS: INOUT GRAPH graph, VERTEX_SELECTOR vertices DEPS: vertices ON graph + FLAGS: no_rng -igraph_delete_vertices_idx: +igraph_delete_vertices_map: PARAMS: |- INOUT GRAPH graph, VERTEX_SELECTOR vertices, OPTIONAL OUT VECTOR_INT idx, OPTIONAL OUT VECTOR_INT invidx DEPS: vertices ON graph + FLAGS: no_rng igraph_vcount: PARAMS: GRAPH graph RETURN: INTEGER + FLAGS: no_rng igraph_ecount: PARAMS: GRAPH graph RETURN: INTEGER + FLAGS: no_rng igraph_neighbors: - PARAMS: GRAPH graph, OUT VERTEX_INDICES neis, VERTEX vid, NEIMODE mode=ALL + PARAMS: |- + GRAPH graph, OUT VERTEX_INDICES neis, VERTEX vid, NEIMODE mode=ALL, + LOOPS loops=TWICE, BOOLEAN multiple=True + FLAGS: no_rng igraph_is_directed: PARAMS: GRAPH graph RETURN: BOOLEAN + FLAGS: no_rng igraph_degree: PARAMS: |- GRAPH graph, OUT VECTOR_INT res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL, - BOOLEAN loops=True + LOOPS loops=TWICE DEPS: vids ON graph + FLAGS: no_rng igraph_edge: PARAMS: GRAPH graph, INTEGER eid, OUT INTEGER from, OUT INTEGER to + FLAGS: no_rng igraph_edges: - PARAMS: GRAPH graph, EDGE_SELECTOR eids, OUT VECTOR_INT edges + PARAMS: GRAPH graph, EDGE_SELECTOR eids, OUT VECTOR_INT edges, BOOLEAN bycol=False DEPS: eids ON graph + FLAGS: no_rng igraph_get_eid: PARAMS: |- GRAPH graph, OUT EDGE eid, VERTEX from, VERTEX to, BOOLEAN directed=True, BOOLEAN error=True + FLAGS: no_rng igraph_get_eids: PARAMS: |- GRAPH graph, OUT EDGE_INDICES eids, VERTEX_INDEX_PAIRS pairs, BOOLEAN directed=True, BOOLEAN error=True DEPS: pairs ON graph + FLAGS: no_rng igraph_get_all_eids_between: PARAMS: |- GRAPH graph, OUT EDGE_INDICES eids, VERTEX from, VERTEX to, BOOLEAN directed=True + FLAGS: no_rng igraph_incident: - PARAMS: GRAPH graph, OUT EDGE_INDICES eids, VERTEX vid, NEIMODE mode=ALL + PARAMS: GRAPH graph, OUT EDGE_INDICES eids, VERTEX vid, NEIMODE mode=ALL, LOOPS loops=TWICE + FLAGS: no_rng igraph_is_same_graph: PARAMS: GRAPH graph1, GRAPH graph2, OUT BOOLEAN res + FLAGS: no_rng ####################################### # Constructors, deterministic @@ -97,6 +119,7 @@ igraph_is_same_graph: igraph_create: PARAMS: OUT GRAPH graph, VECTOR_INT edges, INTEGER n=0, BOOLEAN directed=True + FLAGS: no_rng igraph_adjacency: PARAMS: |- @@ -113,12 +136,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 @@ -162,6 +185,7 @@ igraph_regular_tree: igraph_full: PARAMS: OUT GRAPH graph, INTEGER n, BOOLEAN directed=False, BOOLEAN loops=False + FLAGS: no_rng igraph_full_citation: PARAMS: OUT GRAPH graph, INTEGER n, BOOLEAN directed=True @@ -183,14 +207,17 @@ igraph_linegraph: igraph_de_bruijn: PARAMS: OUT GRAPH graph, INTEGER m, INTEGER n + FLAGS: no_rng igraph_kautz: PARAMS: OUT GRAPH graph, INTEGER m, INTEGER n + FLAGS: no_rng igraph_famous: PARAMS: OUT GRAPH graph, CSTRING name + FLAGS: no_rng -igraph_lcf_vector: +igraph_lcf: PARAMS: OUT GRAPH graph, INTEGER n, VECTOR_INT shifts, INTEGER repeats=1 igraph_mycielski_graph: @@ -232,10 +259,6 @@ igraph_turan: PARAMS: |- OUT GRAPH graph, OPTIONAL OUT INDEX_VECTOR types, INTEGER n, INTEGER r -igraph_weighted_sparsemat: - PARAMS: |- - OUT GRAPH graph, SPARSEMAT A, BOOLEAN directed, CSTRING attr, BOOLEAN loops=False - ####################################### # Constructors, games ####################################### @@ -251,6 +274,9 @@ 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, BOOLEAN multiple=False + +igraph_iea_game: PARAMS: OUT GRAPH graph, INTEGER n, INTEGER m, BOOLEAN directed=False, BOOLEAN loops=False igraph_degree_sequence_game: @@ -409,19 +435,6 @@ igraph_correlated_pair_game: igraph_dot_product_game: PARAMS: OUT GRAPH graph, MATRIX vecs, BOOLEAN directed=False -igraph_sample_sphere_surface: - PARAMS: |- - INTEGER dim, INTEGER n=1, REAL radius=1, - BOOLEAN positive=True, OUT MATRIX res - -igraph_sample_sphere_volume: - PARAMS: |- - INTEGER dim, INTEGER n=1, REAL radius=1, - BOOLEAN positive=True, OUT MATRIX res - -igraph_sample_dirichlet: - PARAMS: INTEGER n, VECTOR alpha, OUT MATRIX res - ####################################### # Basic query functions ####################################### @@ -430,24 +443,13 @@ igraph_are_adjacent: PARAMS: GRAPH graph, VERTEX v1, VERTEX v2, OUT BOOLEAN res DEPS: v1 ON graph, v2 ON graph -igraph_are_connected: - PARAMS: GRAPH graph, VERTEX v1, VERTEX v2, OUT BOOLEAN res - DEPS: v1 ON graph, v2 ON graph - ####################################### # Structural properties ####################################### igraph_diameter: PARAMS: |- - GRAPH graph, OUT REAL res, OUT INTEGER from, - OUT INTEGER to, OPTIONAL OUT VECTOR_INT vertex_path, - OPTIONAL OUT VECTOR_INT edge_path, - BOOLEAN directed=True, BOOLEAN unconnected=True - -igraph_diameter_dijkstra: - PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT REAL res, OUT INTEGER from, OUT INTEGER to, OPTIONAL OUT VECTOR_INT vertex_path, OPTIONAL OUT VECTOR_INT edge_path, @@ -460,7 +462,7 @@ igraph_closeness: OPTIONAL OUT VECTOR_INT reachable_count, OPTIONAL OUT BOOLEAN all_reachable, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=OUT, OPTIONAL EDGEWEIGHTS weights, + NEIMODE mode=OUT, OPTIONAL EDGE_WEIGHTS weights, BOOLEAN normalized=False DEPS: vids ON graph, weights ON graph, res ON graph vids @@ -470,84 +472,84 @@ igraph_closeness_cutoff: OPTIONAL OUT VECTOR_INT reachable_count, OPTIONAL OUT BOOLEAN all_reachable, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=OUT, OPTIONAL EDGEWEIGHTS weights, + NEIMODE mode=OUT, OPTIONAL EDGE_WEIGHTS weights, BOOLEAN normalized=False, REAL cutoff=-1 DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_distances: PARAMS: |- - GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT - DEPS: from ON graph, to ON graph + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX res, + VERTEX_SELECTOR from=ALL, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT + DEPS: weights ON graph, from ON graph, to ON graph igraph_distances_cutoff: PARAMS: |- - GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, REAL cutoff=-1 - DEPS: from ON graph, to ON graph + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX res, + VERTEX_SELECTOR from=ALL, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, REAL cutoff=-1 + DEPS: weights ON graph, from ON graph, to ON graph igraph_get_shortest_path: PARAMS: |- - GRAPH graph, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OPTIONAL OUT VERTEX_INDICES vertices, OPTIONAL OUT EDGE_INDICES edges, VERTEX from, VERTEX to, NEIMODE mode=OUT - DEPS: from ON graph, to ON graph, vertices ON graph, edges ON graph + DEPS: weights ON graph, from ON graph, to ON graph, vertices ON graph, edges ON graph 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, NEIMODE mode=OUT + VERTEX from, VERTEX to, OPTIONAL EDGE_WEIGHTS weights, 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, NEIMODE mode=OUT + VERTEX from, VERTEX to, OPTIONAL EDGE_WEIGHTS weights, 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, NEIMODE mode=OUT, + VERTEX from, VERTEX to, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, OPTIONAL ASTAR_HEURISTIC_FUNC heuristic, OPTIONAL EXTRA extra 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, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + 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 - DEPS: vertices ON graph, edges ON graph, from ON graph, to ON graph + DEPS: weights ON graph, vertices ON graph, edges ON graph, from ON graph, to ON graph igraph_get_all_shortest_paths: PARAMS: |- - GRAPH graph, OPTIONAL OUT VERTEXSET_LIST vertices, - OPTIONAL OUT EDGESET_LIST edges, OPTIONAL OUT VECTOR_INT nrgeo, - VERTEX from, VERTEX_SELECTOR to, NEIMODE mode=OUT - DEPS: vertices ON graph, edges ON graph, from ON graph, to ON graph + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + 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: weights ON graph, vertices ON graph, 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, OPTIONAL EDGEWEIGHTS weights, NEIMODE mode=OUT + VERTEX_SELECTOR to=ALL, OPTIONAL 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, OPTIONAL EDGEWEIGHTS weights, NEIMODE mode=OUT, REAL cutoff=-1 + VERTEX_SELECTOR to=ALL, OPTIONAL 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, - OPTIONAL EDGEWEIGHTS weights, NEIMODE mode=OUT, + GRAPH graph, OPTIONAL OUT VERTEX_INDICES_LIST vertices, + OPTIONAL OUT EDGE_INDICES_LIST edges, VERTEX from, VERTEX_SELECTOR to=ALL, + OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents, OPTIONAL OUT VECTOR_INT inbound_edges DEPS: |- @@ -556,9 +558,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, - OPTIONAL EDGEWEIGHTS weights, NEIMODE mode=OUT, + GRAPH graph, OPTIONAL OUT VERTEX_INDICES_LIST vertices, + OPTIONAL OUT EDGE_INDICES_LIST edges, VERTEX from, VERTEX_SELECTOR to=ALL, + OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents, OPTIONAL OUT VECTOR_INT inbound_edges DEPS: |- @@ -567,9 +569,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, OPTIONAL 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, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: |- weights ON graph, from ON graph, to ON graph, vertices ON graph, edges ON graph @@ -577,39 +579,39 @@ igraph_get_all_shortest_paths_dijkstra: igraph_distances_bellman_ford: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, OPTIONAL EDGEWEIGHTS weights, NEIMODE mode=OUT + VERTEX_SELECTOR to=ALL, OPTIONAL 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, OPTIONAL EDGEWEIGHTS weights + VERTEX_SELECTOR to=ALL, OPTIONAL EDGE_WEIGHTS weights, 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, OPTIONAL EDGEWEIGHTS weights, NEIMODE mode=OUT, + VERTEX_SELECTOR to=ALL, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, FWALGORITHM method=AUTOMATIC 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, OPTIONAL EDGEWEIGHTS weights, NEIMODE mode=OUT, VORONOI_TIEBREAKER tiebreaker=RANDOM + VERTEX_INDICES generators, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, VORONOI_TIEBREAKER tiebreaker=RANDOM DEPS: weights ON graph, generators ON graph igraph_get_all_simple_paths: PARAMS: |- - GRAPH graph, OUT VERTEX_INDICES res, VERTEX from, - VERTEX_SELECTOR to=ALL, INTEGER cutoff=-1, NEIMODE mode=OUT + GRAPH graph, OUT VERTEX_INDICES_LIST res, VERTEX from, + VERTEX_SELECTOR to=ALL, INTEGER minlen=-1, INTEGER maxlen=-1, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, res ON graph 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 @@ -618,15 +620,15 @@ igraph_get_widest_path: PARAMS: |- GRAPH graph, OPTIONAL OUT VERTEX_INDICES vertices, OPTIONAL OUT EDGE_INDICES edges, - VERTEX from, VERTEX to, EDGEWEIGHTS weights, NEIMODE mode=OUT + VERTEX from, VERTEX to, EDGE_WEIGHTS weights, 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, + OPTIONAL OUT VERTEX_INDICES_LIST vertices, OPTIONAL OUT EDGE_INDICES_LIST edges, + VERTEX from, VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents, OPTIONAL OUT VECTOR_INT inbound_edges DEPS: |- @@ -636,18 +638,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: @@ -657,13 +659,13 @@ igraph_subcomponent: igraph_betweenness: PARAMS: |- GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - BOOLEAN directed=True, OPTIONAL EDGEWEIGHTS weights + BOOLEAN directed=True, OPTIONAL EDGE_WEIGHTS weights 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, OPTIONAL EDGEWEIGHTS weights, + BOOLEAN directed=True, OPTIONAL EDGE_WEIGHTS weights, REAL cutoff=-1 DEPS: vids ON graph, weights ON graph, res ON graph vids @@ -671,40 +673,40 @@ igraph_betweenness_subset: PARAMS: |- GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, - OPTIONAL EDGEWEIGHTS weights + OPTIONAL EDGE_WEIGHTS weights DEPS: |- vids ON graph, weights ON graph, res ON graph vids, sources ON graph, targets ON graph igraph_edge_betweenness: PARAMS: |- GRAPH graph, OUT VECTOR res, BOOLEAN directed=True, - OPTIONAL EDGEWEIGHTS weights + OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph igraph_edge_betweenness_cutoff: PARAMS: |- GRAPH graph, OUT VECTOR res, BOOLEAN directed=True, - OPTIONAL EDGEWEIGHTS weights, REAL cutoff=-1 + OPTIONAL EDGE_WEIGHTS weights, 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_QTY res, EDGE_SELECTOR eids=ALL, BOOLEAN directed=True, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, - OPTIONAL EDGEWEIGHTS weights + OPTIONAL EDGE_WEIGHTS weights DEPS: |- - eids ON graph, weights ON graph, res ON graph, sources ON graph, targets ON graph + res ON graph eids, eids ON graph, sources ON graph, targets ON graph, weights ON graph igraph_harmonic_centrality: PARAMS: |- GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=OUT, OPTIONAL EDGEWEIGHTS weights, BOOLEAN normalized=False + NEIMODE mode=OUT, OPTIONAL EDGE_WEIGHTS weights, 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, OPTIONAL EDGEWEIGHTS weights, BOOLEAN normalized=False, + NEIMODE mode=OUT, OPTIONAL EDGE_WEIGHTS weights, BOOLEAN normalized=False, REAL cutoff=-1 DEPS: vids ON graph, weights ON graph, res ON graph vids @@ -713,7 +715,7 @@ igraph_pagerank: GRAPH graph, PAGERANKALGO algo=PRPACK, OUT VERTEX_QTY vector, OUT REAL value, VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, - REAL damping=0.85, OPTIONAL EDGEWEIGHTS weights, + REAL damping=0.85, OPTIONAL EDGE_WEIGHTS weights, OPTIONAL INOUT PAGERANKOPT options DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, @@ -725,7 +727,7 @@ igraph_personalized_pagerank: OUT VERTEX_QTY 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, OPTIONAL INOUT PAGERANKOPT options DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, @@ -738,14 +740,14 @@ igraph_personalized_pagerank_vs: VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, REAL damping=0.85, VERTEX_SELECTOR reset_vids, - OPTIONAL EDGEWEIGHTS weights, + OPTIONAL EDGE_WEIGHTS weights, OPTIONAL INOUT PAGERANKOPT options DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, options ON algo igraph_rewire: - PARAMS: INOUT GRAPH rewire, INTEGER n, REWIRING_MODE mode=SIMPLE + PARAMS: INOUT GRAPH rewire, INTEGER n, EDGE_TYPE_SW allowed_edge_types=SIMPLE igraph_induced_subgraph: PARAMS: GRAPH graph, OUT GRAPH res, VERTEX_SELECTOR vids, SUBGRAPH_IMPL impl=AUTO @@ -760,12 +762,8 @@ igraph_reverse_edges: DEPS: eids ON graph igraph_average_path_length: - PARAMS: GRAPH graph, PRIMARY OUT REAL res, OPTIONAL OUT REAL unconn_pairs, - BOOLEAN directed=True, BOOLEAN unconn=True - -igraph_average_path_length_dijkstra: - PARAMS: GRAPH graph, PRIMARY OUT REAL res, OPTIONAL OUT REAL unconn_pairs, - OPTIONAL EDGEWEIGHTS weights, BOOLEAN directed=True, BOOLEAN unconn=True + PARAMS: GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, PRIMARY OUT REAL res, + OPTIONAL OUT REAL unconn_pairs, BOOLEAN directed=True, BOOLEAN unconn=True DEPS: weights ON graph igraph_path_length_hist: @@ -792,7 +790,7 @@ igraph_transitivity_avglocal_undirected: igraph_transitivity_barrat: PARAMS: |- GRAPH graph, OUT VECTOR res, VERTEX_SELECTOR vids=ALL, - OPTIONAL EDGEWEIGHTS weights, TRANSITIVITY_MODE mode=NAN + OPTIONAL EDGE_WEIGHTS weights, TRANSITIVITY_MODE mode=NAN DEPS: res ON graph, vids ON graph, weights ON graph igraph_ecc: @@ -807,13 +805,13 @@ 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: PARAMS: |- GRAPH graph, OUT INTEGER res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL, - BOOLEAN loops=True + LOOPS loops=TWICE DEPS: vids ON graph igraph_density: @@ -830,7 +828,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 @@ -848,11 +846,11 @@ 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, OPTIONAL EDGEWEIGHTS weights, FAS_ALGORITHM algo=APPROX_EADES + PARAMS: GRAPH graph, OUT EDGE_INDICES result, OPTIONAL EDGE_WEIGHTS weights, FAS_ALGORITHM algo=APPROX_EADES DEPS: result ON graph, weights ON graph igraph_feedback_vertex_set: - PARAMS: GRAPH graph, OUT VERTEX_INDICES result, OPTIONAL VERTEXWEIGHTS weights, FVS_ALGORITHM algo=EXACT_IP + PARAMS: GRAPH graph, OUT VERTEX_INDICES result, OPTIONAL VERTEX_WEIGHTS weights, FVS_ALGORITHM algo=EXACT_IP DEPS: result ON graph, weights ON graph igraph_is_loop: @@ -866,7 +864,7 @@ igraph_is_acyclic: PARAMS: GRAPH graph, OUT BOOLEAN res igraph_is_simple: - PARAMS: GRAPH graph, OUT BOOLEAN res + PARAMS: GRAPH graph, OUT BOOLEAN res, BOOLEAN directed=True igraph_is_multiple: PARAMS: GRAPH graph, OUT VECTOR_BOOL res, EDGE_SELECTOR es=ALL @@ -898,30 +896,17 @@ igraph_add_edge: igraph_eigenvector_centrality: PARAMS: |- GRAPH graph, OUT ALL_VERTEX_QTY vector, OUT REAL value, - BOOLEAN directed=False, BOOLEAN scale=True, - OPTIONAL EDGEWEIGHTS weights, - INOUT ARPACKOPT options=ARPACK_DEFAULTS - DEPS: weights ON graph, vector ON graph - -igraph_hub_score: - PARAMS: |- - GRAPH graph, OUT ALL_VERTEX_QTY vector, OUT REAL value, - BOOLEAN scale=True, OPTIONAL EDGEWEIGHTS weights, - INOUT ARPACKOPT options=ARPACK_DEFAULTS - DEPS: weights ON graph, vector ON graph - -igraph_authority_score: - PARAMS: |- - GRAPH graph, OUT ALL_VERTEX_QTY vector, OUT REAL value, - BOOLEAN scale=True, OPTIONAL EDGEWEIGHTS weights, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + NEIMODE mode=OUT, + OPTIONAL EDGE_WEIGHTS weights, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS DEPS: weights ON graph, vector ON graph igraph_hub_and_authority_scores: PARAMS: |- GRAPH graph, OUT ALL_VERTEX_QTY hub_vector, OUT ALL_VERTEX_QTY authority_vector, - OUT REAL value, BOOLEAN scale=True, OPTIONAL EDGEWEIGHTS weights, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + OUT REAL value, OPTIONAL EDGE_WEIGHTS weights, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS + DEPS: weights ON graph, hub_vector ON graph, authority_vector ON graph igraph_unfold_tree: PARAMS: |- @@ -951,21 +936,31 @@ igraph_avg_nearest_neighbor_degree: GRAPH graph, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL, NEIMODE neighbor_degree_mode=ALL, OPTIONAL OUT VERTEX_QTY knn, OPTIONAL OUT VECTOR knnk, - OPTIONAL EDGEWEIGHTS weights + OPTIONAL EDGE_WEIGHTS weights DEPS: vids ON graph, weights ON graph, knn ON graph vids igraph_degree_correlation_vector: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VECTOR knnk, NEIMODE from_mode=OUT, NEIMODE to_mode=IN, BOOLEAN directed_neighbors=True DEPS: weights ON graph +igraph_rich_club_sequence: + PARAMS: |- + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + OUT VECTOR res, + INDEX_VECTOR vertex_order, + BOOLEAN normalized=True, + BOOLEAN loops=False, + BOOLEAN directed=True + DEPS: weights ON graph + igraph_strength: PARAMS: |- GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=ALL, BOOLEAN loops=True, OPTIONAL EDGEWEIGHTS weights + NEIMODE mode=ALL, LOOPS loops=TWICE, OPTIONAL EDGE_WEIGHTS weights DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_centralization: @@ -975,7 +970,7 @@ igraph_centralization: igraph_centralization_degree: PARAMS: |- GRAPH graph, OUT VECTOR res, - NEIMODE mode=ALL, BOOLEAN loops=True, + NEIMODE mode=ALL, LOOPS loops=TWICE, OUT REAL centralization, OUT REAL theoretical_max, BOOLEAN normalized=True @@ -985,7 +980,7 @@ igraph_centralization_degree_tmax: # https://github.com/igraph/rigraph/issues/369#issuecomment-939893681 PARAMS: |- OPTIONAL GRAPH graph, INTEGER nodes=0, NEIMODE mode=ALL, - BOOLEAN loops, OUT REAL res + LOOPS loops, OUT REAL res igraph_centralization_betweenness: PARAMS: |- @@ -1015,15 +1010,15 @@ igraph_centralization_closeness_tmax: igraph_centralization_eigenvector_centrality: PARAMS: |- GRAPH graph, OUT VECTOR vector, OUT REAL value, - BOOLEAN directed=False, BOOLEAN scale=True, - INOUT ARPACKOPT options=ARPACK_DEFAULTS, + NEIMODE mode=OUT, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS, OUT REAL centralization, OUT REAL theoretical_max, BOOLEAN normalized=True igraph_centralization_eigenvector_centrality_tmax: PARAMS: |- OPTIONAL GRAPH graph, INTEGER nodes=0, - BOOLEAN directed=False, BOOLEAN scale=True, + NEIMODE mode=OUT, OUT REAL res igraph_assortativity_nominal: @@ -1041,14 +1036,14 @@ igraph_assortativity_degree: igraph_joint_degree_matrix: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX jdm, INTEGER max_out_degree=-1, INTEGER max_in_degree=-1 DEPS: weights ON graph igraph_joint_degree_distribution: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX p, NEIMODE from_mode=OUT, NEIMODE to_mode=IN, BOOLEAN directed_neighbors=True, @@ -1058,7 +1053,7 @@ igraph_joint_degree_distribution: igraph_joint_type_distribution: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX p, INDEX_VECTOR from_types, OPTIONAL INDEX_VECTOR to_types, BOOLEAN directed=True, @@ -1072,43 +1067,23 @@ igraph_contract_vertices: igraph_eccentricity: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=ALL - DEPS: vids ON graph, res ON graph vids - -igraph_eccentricity_dijkstra: - PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL DEPS: weights ON graph, vids ON graph, res ON graph vids igraph_graph_center: PARAMS: |- - GRAPH graph, OUT VERTEX_INDICES res, NEIMODE mode=ALL - DEPS: res ON graph - -igraph_graph_center_dijkstra: - PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, OUT VERTEX_INDICES res, NEIMODE mode=ALL + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, 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, OPTIONAL EDGEWEIGHTS weights, OUT REAL radius, NEIMODE mode=ALL + PARAMS: GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT REAL radius, NEIMODE mode=ALL DEPS: weights ON graph igraph_pseudo_diameter: PARAMS: |- - GRAPH graph, OUT REAL diameter, VERTEX start_vid, - OPTIONAL OUT INTEGER from, OPTIONAL OUT INTEGER to, - BOOLEAN directed=True, BOOLEAN unconnected=True - -igraph_pseudo_diameter_dijkstra: - PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT REAL diameter, VERTEX start_vid, OPTIONAL OUT INTEGER from, OPTIONAL OUT INTEGER to, BOOLEAN directed=True, BOOLEAN unconnected=True @@ -1116,41 +1091,32 @@ igraph_pseudo_diameter_dijkstra: igraph_diversity: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, OUT VERTEX_QTY res, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL DEPS: weights ON graph, vids ON graph, res ON graph vids igraph_random_walk: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, OUT VERTEX_INDICES vertices, OUT EDGE_INDICES edges, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, 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, OPTIONAL EDGEWEIGHTS weights, 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, OPTIONAL EDGEWEIGHTS weights, BOOLEAN directed=True + PARAMS: GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT REAL res, BOOLEAN directed=True DEPS: weights ON graph igraph_local_efficiency: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - OPTIONAL EDGEWEIGHTS weights, BOOLEAN directed=True, NEIMODE mode=ALL + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY res, + VERTEX_SELECTOR vids=ALL, 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, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT REAL res, BOOLEAN directed=True, NEIMODE mode=ALL DEPS: weights ON graph -igraph_transitive_closure_dag: - PARAMS: GRAPH graph, OUT GRAPH closure - igraph_transitive_closure: PARAMS: GRAPH graph, OUT GRAPH closure @@ -1223,18 +1189,29 @@ igraph_create_bipartite: PARAMS: |- OUT GRAPH graph, IN BIPARTITE_TYPES types, VECTOR_INT edges, BOOLEAN directed=False + DEPS: types ON graph, edges ON graph igraph_biadjacency: PARAMS: |- - OUT GRAPH graph, OUT BIPARTITE_TYPES types, MATRIX incidence, + OUT GRAPH graph, OUT BIPARTITE_TYPES types, MATRIX biadjmatrix, BOOLEAN directed=False, NEIMODE mode=ALL, BOOLEAN multiple=False +igraph_weighted_biadjacency: + PARAMS: |- + OUT GRAPH graph, + OUT ALL_BIPARTITE_TYPES types, OUT EDGE_WEIGHTS weights, + MATRIX biadjmatrix, + BOOLEAN directed=False, NEIMODE mode=ALL + DEPS: |- + weights ON graph, biadjmatrix ON graph, types ON graph + igraph_get_biadjacency: PARAMS: |- - GRAPH graph, BIPARTITE_TYPES types, OUT MATRIX res, + GRAPH graph, BIPARTITE_TYPES types, OPTIONAL EDGE_WEIGHTS weights, + OUT MATRIX res, OPTIONAL OUT INDEX_VECTOR row_ids, OPTIONAL OUT INDEX_VECTOR col_ids - DEPS: types ON graph + DEPS: types ON graph, weights ON graph igraph_is_bipartite: PARAMS: GRAPH graph, OUT BOOLEAN res, OPTIONAL OUT BIPARTITE_TYPES types @@ -1247,16 +1224,17 @@ igraph_bipartite_game_gnp: igraph_bipartite_game_gnm: PARAMS: |- - OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, + OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, INTEGER n1, INTEGER n2, INTEGER m, BOOLEAN directed=False, - NEIMODE mode=ALL + NEIMODE mode=ALL, BOOLEAN multiple=False + DEPS: types ON graph -igraph_bipartite_game: +igraph_bipartite_iea_game: PARAMS: |- - OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, - ERDOS_RENYI_TYPE type, INTEGER n1, INTEGER n2, REAL p=0.0, - INTEGER m=0, BOOLEAN directed=False, NEIMODE mode=ALL - + OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, + INTEGER n1, INTEGER n2, INTEGER m, + BOOLEAN directed=False, NEIMODE mode=ALL + DEPS: types ON graph ####################################### # Spectral properties @@ -1265,13 +1243,13 @@ igraph_bipartite_game: igraph_get_laplacian: PARAMS: |- GRAPH graph, OUT MATRIX res, NEIMODE mode=OUT, - LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, OPTIONAL EDGEWEIGHTS weights + LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph igraph_get_laplacian_sparse: PARAMS: |- GRAPH graph, OUT SPARSEMAT sparseres, NEIMODE mode=OUT, - LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, OPTIONAL EDGEWEIGHTS weights + LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph ####################################### @@ -1298,9 +1276,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, @@ -1343,7 +1321,7 @@ igraph_is_clique: 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 @@ -1357,16 +1335,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, OPTIONAL OUTFILE outfile, INTEGER min_size=0, INTEGER max_size=0 DEPS: subset ON graph, res ON graph @@ -1392,17 +1370,17 @@ igraph_clique_number: igraph_weighted_cliques: PARAMS: |- - GRAPH graph, OPTIONAL VERTEXWEIGHTS vertex_weights, OUT VERTEXSET_LIST res, + GRAPH graph, OPTIONAL VERTEX_WEIGHTS vertex_weights, 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, OPTIONAL VERTEXWEIGHTS vertex_weights, OUT VERTEXSET_LIST res + GRAPH graph, OPTIONAL VERTEX_WEIGHTS vertex_weights, OUT VERTEX_INDICES_LIST res DEPS: vertex_weights ON graph, res ON graph igraph_weighted_clique_number: - PARAMS: GRAPH graph, OPTIONAL VERTEXWEIGHTS vertex_weights, OUT REAL res + PARAMS: GRAPH graph, OPTIONAL VERTEX_WEIGHTS vertex_weights, OUT REAL res DEPS: vertex_weights ON graph igraph_is_independent_vertex_set: @@ -1411,16 +1389,16 @@ igraph_is_independent_vertex_set: 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: @@ -1454,7 +1432,7 @@ igraph_layout_fruchterman_reingold: GRAPH graph, OPTIONAL INOUT MATRIX coords, BOOLEAN use_seed=False, INTEGER niter=500, REAL start_temp=sqrt(vcount(graph)), - LAYOUT_GRID grid=AUTO, OPTIONAL EDGEWEIGHTS weights, + LAYOUT_GRID grid=AUTO, OPTIONAL EDGE_WEIGHTS weights, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy, DEPRECATED coolexp, DEPRECATED maxdelta, DEPRECATED area, @@ -1465,7 +1443,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), OPTIONAL EDGEWEIGHTS weights, + REAL kkconst=vcount(graph), OPTIONAL EDGE_WEIGHTS weights, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy DEPS: weights ON graph @@ -1502,7 +1480,7 @@ igraph_layout_fruchterman_reingold_3d: GRAPH graph, OPTIONAL INOUT MATRIX coords, BOOLEAN use_seed=False, INTEGER niter=500, REAL start_temp=sqrt(vcount(graph)), - OPTIONAL EDGEWEIGHTS weights, + OPTIONAL EDGE_WEIGHTS weights, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy, OPTIONAL VECTOR minz, OPTIONAL VECTOR maxz, @@ -1514,7 +1492,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), OPTIONAL EDGEWEIGHTS weights, + REAL kkconst=vcount(graph), OPTIONAL EDGE_WEIGHTS weights, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy, OPTIONAL VECTOR minz, OPTIONAL VECTOR maxz @@ -1530,12 +1508,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 @@ -1546,7 +1524,7 @@ igraph_layout_sugiyama: OPTIONAL OUT INDEX_VECTOR extd_to_orig_eids, OPTIONAL INDEX_VECTOR layers, REAL hgap=1, REAL vgap=1, INTEGER maxiter=100, - OPTIONAL EDGEWEIGHTS weights + OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph igraph_layout_mds: @@ -1610,9 +1588,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: |- @@ -1632,9 +1610,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: |- @@ -1658,7 +1636,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, @@ -1667,15 +1645,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 @@ -1684,19 +1662,20 @@ 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 - DEPS: weights ON graph + BOOLEAN directed=True, + OPTIONAL EDGE_WEIGHTS weights, OPTIONAL EDGE_LENGTHS lengths + DEPS: weights ON graph, lengths ON graph, edge_betweenness 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 @@ -1712,14 +1691,14 @@ igraph_le_community_to_membership: igraph_modularity: PARAMS: |- - GRAPH graph, VECTOR_INT membership, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, VECTOR_INT membership, OPTIONAL EDGE_WEIGHTS weights, 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 @@ -1732,15 +1711,18 @@ igraph_reindex_membership: igraph_community_leading_eigenvector: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, - OPTIONAL OUT MATRIX_INT merges, OPTIONAL OUT VECTOR_INT membership, + GRAPH graph, + OPTIONAL EDGE_WEIGHTS weights, + OPTIONAL OUT MATRIX_INT merges, + OPTIONAL OUT VECTOR_INT membership, INTEGER steps=-1, - INOUT ARPACKOPT options=ARPACK_DEFAULTS, - OPTIONAL OUT REAL modularity, BOOLEAN start=False, + 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, - OPTIONAL LEVCFUNC callback, + OPTIONAL OUT VECTOR_INT history, + OPTIONAL LEVC_FUNC callback, OPTIONAL EXTRA callback_extra igraph_community_fluid_communities: @@ -1750,31 +1732,32 @@ 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 VECTOR_BOOL fixed + OPTIONAL EDGE_WEIGHTS weights, OPTIONAL INDEX_VECTOR initial, + OPTIONAL VECTOR_BOOL fixed, IN LPA_VARIANT lpa_variant 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 igraph_community_optimal_modularity: PARAMS: |- - GRAPH graph, OUT REAL modularity, OPTIONAL OUT VECTOR_INT membership, - OPTIONAL EDGEWEIGHTS weights + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, REAL resolution=1.0, + OPTIONAL OUT REAL modularity, OPTIONAL OUT VECTOR_INT membership 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_out_weights, + OPTIONAL VERTEX_WEIGHTS vertex_in_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 - DEPS: weights ON graph, vertex_weights ON graph + DEPS: weights ON graph, vertex_out_weights ON graph, vertex_in_weights ON graph igraph_split_join_distance: PARAMS: |- @@ -1783,10 +1766,10 @@ igraph_split_join_distance: igraph_community_infomap: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS e_weights, - OPTIONAL VERTEXWEIGHTS v_weights, INTEGER nb_trials=10, - OUT VECTOR_INT membership, OUT REAL codelength - DEPS: e_weights ON graph, v_weights ON graph + GRAPH graph, OPTIONAL EDGE_WEIGHTS edge_weights, + OPTIONAL VERTEX_WEIGHTS vertex_weights, INTEGER nb_trials=10, + OPTIONAL OUT VECTOR_INT membership, OPTIONAL OUT REAL codelength + DEPS: edge_weights ON graph, vertex_weights ON graph igraph_community_voronoi: PARAMS: |- @@ -1794,7 +1777,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 @@ -1804,20 +1787,20 @@ igraph_community_voronoi: igraph_graphlets: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, - OUT VERTEXSET_LIST cliques, OUT VECTOR Mu, INTEGER niter=1000 + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + 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, OPTIONAL EDGEWEIGHTS weights, - OUT VERTEXSET_LIST cliques, OUT VECTOR thresholds + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + OUT VERTEX_INDICES_LIST cliques, OUT VECTOR thresholds DEPS: weights ON graph, cliques ON graph igraph_graphlets_project: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, - VERTEXSET_LIST cliques, INOUT VECTOR Muc, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + VERTEX_INDICES_LIST cliques, INOUT VECTOR Muc, BOOLEAN startMu=False, INTEGER niter=1000 DEPS: weights ON graph @@ -1873,16 +1856,14 @@ igraph_from_hrg_dendrogram: igraph_get_adjacency: PARAMS: |- GRAPH graph, OUT MATRIX res, GETADJACENCY type=BOTH, - OPTIONAL EDGEWEIGHTS weights, LOOPS loops=ONCE - DEPS: - weights ON graph + OPTIONAL EDGE_WEIGHTS weights, LOOPS loops=ONCE + DEPS: weights ON graph igraph_get_adjacency_sparse: PARAMS: |- GRAPH graph, OUT SPARSEMAT sparsemat, GETADJACENCY type=BOTH, - OPTIONAL EDGEWEIGHTS weights, LOOPS loops=ONCE - DEPS: - weights ON graph + OPTIONAL EDGE_WEIGHTS weights, LOOPS loops=ONCE + DEPS: weights ON graph igraph_get_edgelist: PARAMS: GRAPH graph, OUT VECTOR_INT res, BOOLEAN bycol=False @@ -1890,16 +1871,14 @@ igraph_get_edgelist: igraph_get_stochastic: PARAMS: |- GRAPH graph, OUT MATRIX res, BOOLEAN column_wise=False, - OPTIONAL EDGEWEIGHTS weights - DEPS: - weights ON graph + OPTIONAL EDGE_WEIGHTS weights + DEPS: weights ON graph igraph_get_stochastic_sparse: PARAMS: |- GRAPH graph, OUT SPARSEMAT sparsemat, BOOLEAN column_wise=False, - OPTIONAL EDGEWEIGHTS weights - DEPS: - weights ON graph + OPTIONAL EDGE_WEIGHTS weights + DEPS: weights ON graph igraph_to_directed: PARAMS: INOUT GRAPH graph, TODIRECTED mode=MUTUAL @@ -1988,11 +1967,11 @@ igraph_motifs_randesu: igraph_motifs_randesu_estimate: PARAMS: |- - GRAPH graph, OUT INTEGER est, INTEGER size=3, OPTIONAL VECTOR cut_prob, + GRAPH graph, OUT REAL est, INTEGER size=3, OPTIONAL VECTOR cut_prob, INTEGER sample_size, OPTIONAL VECTOR_INT sample igraph_motifs_randesu_no: - PARAMS: GRAPH graph, OUT INTEGER no, INTEGER size=3, OPTIONAL VECTOR cut_prob + PARAMS: GRAPH graph, OUT REAL no, INTEGER size=3, OPTIONAL VECTOR cut_prob igraph_dyad_census: PARAMS: GRAPH graph, OUT REAL mut, OUT REAL asym, OUT REAL null @@ -2011,50 +1990,50 @@ igraph_count_triangles: igraph_local_scan_0: PARAMS: |- - GRAPH graph, OUT VECTOR res, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OUT VECTOR res, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: weights ON graph igraph_local_scan_0_them: PARAMS: |- GRAPH us, GRAPH them, OUT VECTOR res, - OPTIONAL EDGEWEIGHTS weights_them, NEIMODE mode=OUT + OPTIONAL EDGE_WEIGHTS weights_them, NEIMODE mode=OUT DEPS: weights_them ON them igraph_local_scan_1_ecount: PARAMS: |- - GRAPH graph, OUT VECTOR res, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, OUT VECTOR res, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: weights ON graph igraph_local_scan_1_ecount_them: PARAMS: |- GRAPH us, GRAPH them, OUT VECTOR res, - OPTIONAL EDGEWEIGHTS weights_them, NEIMODE mode=OUT + OPTIONAL EDGE_WEIGHTS weights_them, NEIMODE mode=OUT DEPS: weights_them ON them igraph_local_scan_k_ecount: PARAMS: |- - GRAPH graph, INTEGER k, OUT VECTOR res, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, INTEGER k, OUT VECTOR res, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: weights ON graph igraph_local_scan_k_ecount_them: PARAMS: |- GRAPH us, GRAPH them, INTEGER k, OUT VECTOR res, - OPTIONAL EDGEWEIGHTS weights_them, NEIMODE mode=OUT + OPTIONAL EDGE_WEIGHTS weights_them, NEIMODE mode=OUT DEPS: weights_them ON them igraph_local_scan_neighborhood_ecount: PARAMS: |- - GRAPH graph, OUT VECTOR res, OPTIONAL EDGEWEIGHTS weights, - VERTEXSET_LIST neighborhoods + GRAPH graph, OUT VECTOR res, OPTIONAL EDGE_WEIGHTS weights, + VERTEX_INDICES_LIST neighborhoods DEPS: weights ON graph igraph_local_scan_subset_ecount: PARAMS: |- - GRAPH graph, OUT VECTOR res, OPTIONAL EDGEWEIGHTS weights, - VERTEXSET_LIST subsets + GRAPH graph, OUT VECTOR res, OPTIONAL EDGE_WEIGHTS weights, + VERTEX_INDICES_LIST subsets DEPS: weights ON graph igraph_list_triangles: @@ -2118,12 +2097,17 @@ igraph_product: PARAMS: |- OUT GRAPH res, GRAPH g1, GRAPH g2, GRAPH_PRODUCT_TYPE type=CARTESIAN +igraph_rooted_product: + PARAMS: |- + OUT GRAPH res, GRAPH g1, GRAPH g2, VERTEX root + DEPS: root ON g2 + ####################################### # Maximum flows, minimum cuts ####################################### 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: @@ -2131,7 +2115,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, @@ -2140,30 +2124,29 @@ 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 - DEPS: - capacity ON graph + 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 @@ -2172,7 +2155,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 @@ -2180,7 +2163,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: @@ -2226,8 +2209,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, @@ -2236,15 +2219,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 @@ -2257,16 +2240,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 @@ -2288,6 +2271,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 @@ -2298,10 +2291,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, @@ -2314,8 +2307,8 @@ igraph_isomorphic_vf2: igraph_get_isomorphisms_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, @@ -2328,8 +2321,8 @@ igraph_get_isomorphisms_vf2_callback: igraph_count_isomorphisms_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 INTEGER count, OPTIONAL ISOCOMPAT_FUNC node_compat_fn, OPTIONAL ISOCOMPAT_FUNC edge_compat_fn, @@ -2341,8 +2334,8 @@ igraph_count_isomorphisms_vf2: igraph_get_isomorphisms_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 VECTOR_INT_LIST maps, OPTIONAL ISOCOMPAT_FUNC node_compat_fn, OPTIONAL ISOCOMPAT_FUNC edge_compat_fn, @@ -2357,8 +2350,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, @@ -2371,8 +2364,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, @@ -2385,8 +2378,8 @@ igraph_get_subisomorphisms_vf2_callback: igraph_count_subisomorphisms_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 INTEGER count, OPTIONAL ISOCOMPAT_FUNC node_compat_fn, OPTIONAL ISOCOMPAT_FUNC edge_compat_fn, @@ -2398,8 +2391,8 @@ igraph_count_subisomorphisms_vf2: igraph_get_subisomorphisms_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 VECTOR_INT_LIST maps, OPTIONAL ISOCOMPAT_FUNC node_compat_fn, OPTIONAL ISOCOMPAT_FUNC edge_compat_fn, @@ -2410,7 +2403,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 @@ -2420,28 +2419,28 @@ 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 + OPTIONAL OUT VECTOR_INT_LIST maps, BOOLEAN induced igraph_simplify_and_colorize: # Despite their names, vertex_color and edge_color are not really colors @@ -2475,8 +2474,8 @@ 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 - DEPS: types ON graph, weights ON graph + OPTIONAL EDGE_WEIGHTS weights, REAL eps=.Machine$double.eps + DEPS: types ON graph matching, weights ON graph ####################################### # Embedding @@ -2484,20 +2483,20 @@ igraph_maximum_bipartite_matching: igraph_adjacency_spectral_embedding: PARAMS: |- - GRAPH graph, INTEGER no, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, INTEGER no, OPTIONAL EDGE_WEIGHTS weights, 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, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, INTEGER no, OPTIONAL EDGE_WEIGHTS weights, 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 ####################################### @@ -2508,8 +2507,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 ####################################### @@ -2556,15 +2555,15 @@ igraph_cmp_epsilon: igraph_eigen_matrix: PARAMS: |- - MATRIX A, SPARSEMAT sA, ARPACKFUNC fun, INT n, OPTIONAL 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, OPTIONAL 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, OPTIONAL 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, OPTIONAL 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 @@ -2582,7 +2581,7 @@ igraph_find_cycle: igraph_simple_cycles: 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, NEIMODE mode=OUT, INTEGER min_cycle_length=-1, INTEGER max_cycle_length=-1 DEPS: vertices ON graph, edges ON graph @@ -2613,15 +2612,15 @@ igraph_eulerian_cycle: igraph_fundamental_cycles: PARAMS: |- - GRAPH graph, OUT EDGESET_LIST basis, OPTIONAL VERTEX start, - INTEGER bfs_cutoff=-1, OPTIONAL EDGEWEIGHTS weights + GRAPH graph, OUT EDGE_INDICES_LIST basis, OPTIONAL VERTEX start=-1, + INTEGER bfs_cutoff=-1, OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph, basis ON graph, start ON graph igraph_minimum_cycle_basis: PARAMS: |- - GRAPH graph, OUT EDGESET_LIST basis, INTEGER bfs_cutoff=-1, + GRAPH graph, OUT EDGE_INDICES_LIST basis, INTEGER bfs_cutoff=-1, BOOLEAN complete=True, BOOLEAN use_cycle_order=True, - OPTIONAL EDGEWEIGHTS weights + OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph, basis ON graph ####################################### @@ -2649,58 +2648,41 @@ igraph_is_complete: PARAMS: GRAPH graph, OUT BOOLEAN res igraph_minimum_spanning_tree: - PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL EDGEWEIGHTS weights + PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL EDGE_WEIGHTS weights, MSTALGORITHM method=AUTOMATIC 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 - DEPS: weights ON graph - igraph_random_spanning_tree: - PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid + PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid=-1 DEPS: res ON graph, vid ON graph igraph_tree_game: PARAMS: OUT GRAPH graph, INTEGER n, BOOLEAN directed=False, RANDOM_TREE_METHOD method=LERW ####################################### -# Coloring +# Spatial ####################################### - -igraph_vertex_coloring_greedy: - PARAMS: GRAPH graph, OUT VERTEX_COLOR colors, GREEDY_COLORING_HEURISTIC heuristic=NEIGHBORS - DEPS: colors ON graph +igraph_nearest_neighbor_graph: + PARAMS: OUT GRAPH graph, MATRIX points, METRIC metric, INTEGER neighbors, REAL cutoff, BOOLEAN directed ####################################### -# Microscopic update +# Coloring ####################################### -igraph_deterministic_optimal_imitation: - PARAMS: |- - GRAPH graph, VERTEX vid, OPTIMALITY optimality=MAXIMUM, ALL_VERTEX_QTY quantities, - INOUT VECTOR_INT strategies, NEIMODE mode=OUT - DEPS: vid ON graph, quantities ON graph, strategies ON graph +igraph_vertex_coloring_greedy: + PARAMS: GRAPH graph, OUT VERTEX_COLORS colors, GREEDY_COLORING_HEURISTIC heuristic=NEIGHBORS + DEPS: colors ON graph -igraph_moran_process: - PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, INOUT ALL_VERTEX_QTY quantities, - INOUT VECTOR_INT strategies, NEIMODE mode=OUT - DEPS: weights ON graph, quantities ON graph, strategies ON graph +igraph_is_vertex_coloring: + PARAMS: GRAPH graph, VERTEX_COLORS types, OUT BOOLEAN res + DEPS: types ON graph -igraph_roulette_wheel_imitation: - PARAMS: |- - GRAPH graph, VERTEX vid, BOOLEAN is_local, ALL_VERTEX_QTY quantities, - INOUT VECTOR_INT strategies, NEIMODE mode=OUT - DEPS: vid ON graph, quantities ON graph, strategies ON graph +igraph_is_bipartite_coloring: + PARAMS: GRAPH graph, BIPARTITE_TYPES types, OUT BOOLEAN res, OPTIONAL OUT NEIMODE mode + DEPS: types ON graph -igraph_stochastic_imitation: - PARAMS: |- - GRAPH graph, VERTEX vid, IMITATE_ALGORITHM algo, ALL_VERTEX_QTY quantities, - INOUT VECTOR_INT strategies, NEIMODE mode=OUT - DEPS: vid ON graph, quantities ON graph, strategies ON graph +igraph_is_edge_coloring: + PARAMS: GRAPH graph, EDGE_COLORS types, OUT BOOLEAN res + DEPS: types ON graph ####################################### # Other, (yet) undocumented functions @@ -2741,6 +2723,7 @@ igraph_vertex_path_from_edge_path: PARAMS: |- GRAPH graph, OPTIONAL VERTEX start, EDGE_INDICES edge_path, OUT VERTEX_INDICES vertex_path, NEIMODE mode=OUT + DEPS: start ON graph, edge_path ON graph, vertex_path ON graph ####################################### # Meta info diff --git a/src/vendor/cigraph/interfaces/types.yaml b/src/vendor/cigraph/interfaces/types.yaml index 0a95c14ff19..3d4819fe2dc 100644 --- a/src/vendor/cigraph/interfaces/types.yaml +++ b/src/vendor/cigraph/interfaces/types.yaml @@ -38,10 +38,6 @@ INT: # A C integer CTYPE: int -LONGINT: - # A C long integer - CTYPE: long int - CSTRING: # A null-terminated immutable C string CTYPE: const char* @@ -182,12 +178,12 @@ ALL_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 @@ -197,12 +193,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 @@ -238,18 +234,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 @@ -332,13 +328,6 @@ EIGENWHICHPOS: CTYPE: igraph_eigen_which_position_t FLAGS: ENUM -ERDOS_RENYI_TYPE: - # Enum that says wheter a GNM (n vertices, m edges) or - # GNP (n vertices, every edge exists with probability p) - # graph is created - CTYPE: igraph_erdos_renyi_t - FLAGS: ENUM - FAS_ALGORITHM: # Enum representing feedback arc set algorithms CTYPE: igraph_fas_algorithm_t @@ -365,11 +354,6 @@ GREEDY_COLORING_HEURISTIC: CTYPE: igraph_coloring_greedy_t FLAGS: ENUM -IMITATE_ALGORITHM: - # This enum controls which algorithm to use in stochastic imitation - CTYPE: igraph_imitate_algorithm_t - FLAGS: ENUM - LAPLACIAN_NORMALIZATION: # Enum representing the possible normalization methods of a Laplacian # matrix @@ -396,17 +380,22 @@ LSETYPE: CTYPE: igraph_laplacian_spectral_embedding_type_t FLAGS: ENUM +METRIC: + # Enum that describes the metric to be used for spatial algorithms + CTYPE: igraph_metric_t + FLAGS: ENUM + +MSTALGORITHM: + # Enum that describes the algorithm for computing a minimum spanning tree + CTYPE: igraph_mst_algorithm_t + FLAGS: ENUM + NEIMODE: # Enum that describes how a particular function should take into account # the neighbors of vertices CTYPE: igraph_neimode_t FLAGS: ENUM -OPTIMALITY: - # This enum controls which algorithm to use in deterministic optimal imitation - CTYPE: igraph_optimal_t - FLAGS: ENUM - ORDER: # Whether ordering should be ascending or descending CTYPE: igraph_order_t @@ -439,11 +428,6 @@ RECIP: CTYPE: igraph_reciprocity_t FLAGS: ENUM -REWIRING_MODE: - # Enum for the rewiring modes of igraph_rewire() - CTYPE: igraph_rewiring_t - FLAGS: ENUM - ROOTCHOICE: # Enum for the heuristic of igraph_roots_for_tree_layout() CTYPE: igraph_root_choice_t @@ -514,10 +498,15 @@ VORONOI_TIEBREAKER: FLAGS: ENUM WHEEL_MODE: - # Enum that describes how a star graph should be constructed + # Enum that describes how a wheel graph should be constructed CTYPE: igraph_wheel_mode_t FLAGS: ENUM +LPA_VARIANT: + # Enum that describes the label propagation algorithm variant + CTYPE: igraph_lpa_variant_t + FLAGS: ENUM + ############################################################################### # Switches / flags / bits ############################################################################### @@ -537,7 +526,7 @@ WRITE_GML_SW: # Callbacks ############################################################################### -ARPACKFUNC: +ARPACK_FUNC: # ARPACK matrix multiplication function. CTYPE: igraph_arpack_function_t @@ -571,7 +560,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 @@ -580,12 +569,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 @@ -596,10 +585,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/CMakeLists.txt b/src/vendor/cigraph/src/CMakeLists.txt index 21281e9d91c..f2032db3e8f 100644 --- a/src/vendor/cigraph/src/CMakeLists.txt +++ b/src/vendor/cigraph/src/CMakeLists.txt @@ -39,7 +39,6 @@ add_custom_target(parsersources SOURCES ${PARSER_SOURCES}) # Declare the files needed to compile the igraph library add_library( igraph - core/array.c core/bitset.c core/bitset_list.c core/buckets.c @@ -61,6 +60,7 @@ add_library( core/progress.c core/psumtree.c core/set.c + core/setup.c core/sparsemat.c core/stack.c core/statusbar.c @@ -80,10 +80,12 @@ add_library( linalg/lapack.c random/random.c + random/random_device.cpp random/rng_glibc2.c random/rng_mt19937.c random/rng_pcg32.c random/rng_pcg64.c + random/sampling.c graph/adjlist.c graph/attributes.c @@ -113,7 +115,6 @@ add_library( constructors/regular.c constructors/trees.c - games/barabasi.c games/callaway_traits.c games/chung_lu.c @@ -159,14 +160,12 @@ add_library( community/edge_betweenness.c community/fast_modularity.c community/fluid.c - community/infomap/infomap_FlowGraph.cc - community/infomap/infomap_Greedy.cc - community/infomap/infomap.cc community/label_propagation.c community/leading_eigenvector.c community/leiden.c community/louvain.c community/modularity.c + community/infomap.cpp community/optimal_modularity.c community/spinglass/clustertool.cpp community/spinglass/NetDataTypes.cpp @@ -280,6 +279,7 @@ add_library( properties/multiplicity.c properties/neighborhood.c properties/perfect.c + properties/rich_club.c properties/spectral.c properties/trees.c properties/triangles.c @@ -302,7 +302,6 @@ add_library( misc/feedback_arc_set.c misc/graphicality.c misc/matching.c - misc/microscopic_update.c misc/mixing.c misc/motifs.c misc/order_cycle.cpp @@ -312,13 +311,14 @@ add_library( misc/sir.c misc/spanning_trees.c + spatial/nearest_neighbor.cpp + internal/glpk_support.c internal/hacks.c internal/lsap.c internal/qsort_r.c internal/qsort.c internal/utils.c - internal/zeroin.c version.c @@ -327,6 +327,7 @@ add_library( $,$,> $,$,> $,$,> + $,$,> $,$,> $,$,> $,$,> @@ -372,10 +373,12 @@ target_include_directories( # Vendored library include paths "$<$:$>" + "$<$:$>" "$<$:$>" # Include paths for dependencies "$<$:${GLPK_INCLUDE_DIR}>" + "$<$:${INFOMAP_INCLUDE_DIR}>" "$<$:${GMP_INCLUDE_DIR}>" "$<$:${LIBXML2_INCLUDE_DIRS}>" "$<$:${PLFIT_INCLUDE_DIRS}>" @@ -397,6 +400,10 @@ if(GLPK_LIBRARIES) target_link_libraries(igraph PRIVATE ${GLPK_LIBRARIES}) endif() +if(INFOMAP_LIBRARIES) + target_link_libraries(igraph PRIVATE ${INFOMAP_LIBRARIES}) +endif() + if(GMP_LIBRARIES) target_link_libraries(igraph PRIVATE ${GMP_LIBRARIES}) endif() diff --git a/src/vendor/cigraph/src/centrality/betweenness.c b/src/vendor/cigraph/src/centrality/betweenness.c index 8f7c355ed32..4971da8c193 100644 --- a/src/vendor/cigraph/src/centrality/betweenness.c +++ b/src/vendor/cigraph/src/centrality/betweenness.c @@ -480,10 +480,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 @@ -526,10 +524,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/centrality/centrality_internal.h b/src/vendor/cigraph/src/centrality/centrality_internal.h index 4479a3466ae..6afb24687ef 100644 --- a/src/vendor/cigraph/src/centrality/centrality_internal.h +++ b/src/vendor/cigraph/src/centrality/centrality_internal.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -28,10 +27,11 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS igraph_bool_t igraph_i_vector_mostly_negative(const igraph_vector_t *vector); +void igraph_i_vector_scale_by_max_abs(igraph_vector_t *vec); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/centrality/centrality_other.c b/src/vendor/cigraph/src/centrality/centrality_other.c index 6130b253b0c..71d7ec2617e 100644 --- a/src/vendor/cigraph/src/centrality/centrality_other.c +++ b/src/vendor/cigraph/src/centrality/centrality_other.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2021 The igraph development team @@ -14,8 +12,8 @@ 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "centrality/centrality_internal.h" @@ -50,3 +48,25 @@ igraph_bool_t igraph_i_vector_mostly_negative(const igraph_vector_t *vector) { /* is the most negative value larger in magnitude than the most positive? */ return (-mi/ma > 1); } + +/* Normalizes a vector of real numbers such that the largest value, as well as + * the largest value by magnitude, are 1.0. This is used by functions that + * produce eigenvector-like centrality values, scaling the largest centrality + * to 1.0. */ +void igraph_i_vector_scale_by_max_abs(igraph_vector_t *vec) { + const igraph_integer_t n = igraph_vector_size(vec); + igraph_real_t amax = 0; + igraph_integer_t which = 0; + + for (igraph_integer_t i = 0; i < n; i++) { + igraph_real_t tmp; + tmp = fabs(VECTOR(*vec)[i]); + if (tmp > amax) { + amax = tmp; + which = i; + } + } + if (amax != 0) { + igraph_vector_scale(vec, 1 / VECTOR(*vec)[which]); + } +} diff --git a/src/vendor/cigraph/src/centrality/centralization.c b/src/vendor/cigraph/src/centrality/centralization.c index d08a95da7a4..75cc5f304ef 100644 --- a/src/vendor/cigraph/src/centrality/centralization.c +++ b/src/vendor/cigraph/src/centrality/centralization.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2020 The igraph development team @@ -14,8 +12,8 @@ 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "igraph_centrality.h" @@ -114,8 +112,11 @@ igraph_real_t igraph_centralization(const igraph_vector_t *scores, * \param mode Constant the specifies the type of degree for directed * graphs. Possible values: \c IGRAPH_IN, \c IGRAPH_OUT and \c * IGRAPH_ALL. This argument is ignored for undirected graphs. - * \param loops Boolean, whether to consider loop edges when - * calculating the degree (and the centralization). + * \param loops Specifies how to treat loop edges when calculating the + * degree (and the centralization). \c IGRAPH_NO_LOOPS ignores loop + * edges; \c IGRAPH_LOOPS_ONCE counts each loop edge only once; + * \c IGRAPH_LOOPS_TWICE counts each loop edge twice in undirected + * graphs and once in directed graphs. * \param centralization Pointer to a real number, the centralization * score is placed here. * \param theoretical_max Pointer to real number or a null pointer. If @@ -134,11 +135,11 @@ igraph_real_t igraph_centralization(const igraph_vector_t *scores, * score. */ -igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_vector_t *res, - igraph_neimode_t mode, igraph_bool_t loops, - igraph_real_t *centralization, - igraph_real_t *theoretical_max, - igraph_bool_t normalized) { +igraph_error_t igraph_centralization_degree( + const igraph_t *graph, igraph_vector_t *res, igraph_neimode_t mode, + igraph_loops_t loops, igraph_real_t *centralization, + igraph_real_t *theoretical_max, igraph_bool_t normalized +) { igraph_vector_t myscores; igraph_vector_t *scores = res; @@ -200,8 +201,11 @@ igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_vector * or total degree (\c IGRAPH_ALL). This is ignored if * the \p graph argument is not a null pointer and the * given graph is undirected. - * \param loops Boolean, whether to consider loop edges in the - * calculation. + * \param loops Specifies how to treat loop edges when calculating the + * degree (and the centralization). \c IGRAPH_NO_LOOPS ignores loop + * edges; \c IGRAPH_LOOPS_ONCE counts each loop edge only once; + * \c IGRAPH_LOOPS_TWICE counts each loop edge twice in undirected + * graphs and once in directed graphs. * \param res Pointer to a real variable, the result is stored here. * \return Error code. * @@ -211,11 +215,10 @@ igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_vector * igraph_centralization(). */ -igraph_error_t igraph_centralization_degree_tmax(const igraph_t *graph, - igraph_integer_t nodes, - igraph_neimode_t mode, - igraph_bool_t loops, - igraph_real_t *res) { +igraph_error_t igraph_centralization_degree_tmax( + const igraph_t *graph, igraph_integer_t nodes, igraph_neimode_t mode, + igraph_loops_t loops, igraph_real_t *res +) { igraph_bool_t directed = (mode != IGRAPH_ALL); igraph_real_t real_nodes; @@ -240,14 +243,14 @@ igraph_error_t igraph_centralization_degree_tmax(const igraph_t *graph, switch (mode) { case IGRAPH_IN: case IGRAPH_OUT: - if (!loops) { + if (loops == IGRAPH_NO_LOOPS) { *res = (real_nodes - 1) * (real_nodes - 1); } else { *res = (real_nodes - 1) * real_nodes; } break; case IGRAPH_ALL: - if (!loops) { + if (loops == IGRAPH_NO_LOOPS) { *res = 2 * (real_nodes - 1) * (real_nodes - 2); } else { *res = 2 * (real_nodes - 1) * (real_nodes - 1); @@ -255,8 +258,10 @@ igraph_error_t igraph_centralization_degree_tmax(const igraph_t *graph, break; } } else { - if (!loops) { + if (loops == IGRAPH_NO_LOOPS) { *res = (real_nodes - 1) * (real_nodes - 2); + } else if (loops == IGRAPH_LOOPS_ONCE) { + *res = (real_nodes - 1) * (real_nodes - 1); } else { *res = (real_nodes - 1) * real_nodes; } @@ -549,7 +554,7 @@ igraph_error_t igraph_centralization_closeness_tmax(const igraph_t *graph, * \brief Calculate eigenvector centrality scores and graph centralization. * * This function calculates the eigenvector centrality of the vertices - * by passing its arguments to \ref igraph_eigenvector_centrality); + * by passing its arguments to \ref igraph_eigenvector_centrality(); * and it calculates the graph level centralization index based on the * results by calling \ref igraph_centralization(). * @@ -570,10 +575,9 @@ igraph_error_t igraph_centralization_closeness_tmax(const igraph_t *graph, * centrality scores, or a null pointer otherwise. * \param value If not a null pointer, then the leading eigenvalue is * stored here. - * \param directed Boolean scalar, whether to consider edge directions - * in a directed graph. It is ignored for undirected graphs. - * \param scale This parameter is deprecated and ignored since igraph 0.10.14. - * Vertex-level centrality scores are always scaled to have a maximum of one. + * \param mode How to consider edge directions in directed graphs. + * See \ref igraph_eigenvector_centrality() for details. Ignored + * for directed graphs. * \param options Options to ARPACK. See \ref igraph_arpack_options_t * for details. Note that the function overwrites the * n (number of vertices) parameter and @@ -601,8 +605,7 @@ igraph_error_t igraph_centralization_eigenvector_centrality( const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, - igraph_bool_t directed, - igraph_bool_t scale, + igraph_neimode_t mode, igraph_arpack_options_t *options, igraph_real_t *centralization, igraph_real_t *theoretical_max, @@ -613,14 +616,6 @@ igraph_error_t igraph_centralization_eigenvector_centrality( igraph_real_t realvalue, *myvalue = value; igraph_real_t *tmax = theoretical_max, mytmax; - if (! scale) { - scale = true; - IGRAPH_WARNING("Computing eigenvector centralization requires normalized " - "eigenvector centrality scores. Normalizing eigenvector centralities " - "by their maximum even though 'scale=false' was requested. The 'scale' " - "parameter will be removed in the future."); - } - if (!tmax) { tmax = &mytmax; } @@ -633,14 +628,12 @@ igraph_error_t igraph_centralization_eigenvector_centrality( myvalue = &realvalue; } - IGRAPH_CHECK(igraph_eigenvector_centrality(graph, scores, myvalue, directed, - scale, /*weights=*/ 0, + IGRAPH_CHECK(igraph_eigenvector_centrality(graph, scores, myvalue, mode, + /*weights=*/ NULL, options)); IGRAPH_CHECK(igraph_centralization_eigenvector_centrality_tmax( - graph, 0, directed, - scale, - tmax)); + graph, 0, mode, tmax)); *centralization = igraph_centralization(scores, *tmax, normalized); @@ -664,45 +657,26 @@ igraph_error_t igraph_centralization_eigenvector_centrality( * graph as the \p graph argument, and then the number of * vertices is taken from this object, and its directedness is * considered as well. The \p nodes argument is ignored in - * this case. The \p directed argument is also ignored if the + * this case. The \p mode argument is also ignored if the * supplied graph is undirected. * * - * The other way is to supply a null pointer as the \p graph - * argument. In this case the \p nodes and \p directed - * arguments are considered. + * The other way is to supply a null pointer as the \p graph. argument. + * In this case the \p nodes and \p mode arguments are considered. * * - * The most centralized directed structure is assumed to bethe in-star. - * The most centralized undirected structure is assumed to be the graph - * with a single edge. igraph continues to implement these choices for - * historical reason. Keep in mind that neither of these two structures - * is connected, which makes their use debatable in the context of - * eigenvector centrality calculations. Eigenvector centrality is not - * uniquely defined for disconnected structures. - * - * - * Note that vertex-level eigenvector centrality scores do not have - * a natural scale. As with any eigenvector, their interpretation is - * invariant to scaling by a constant factor. However, due to how - * graph-level \em centralization is defined, its value depends on the - * specific scale/normalization used for vertex-level scores. Moreover, - * which of two graphs will have a higher eigenvector \em centralization - * also depends on the choice of normalization for centralities. This - * function makes the specific choice of scaling vertex-level centrality - * scores by their maximum (i.e. it uses the ∞-norm). Other normalization - * choices, such as the 1-norm or 2-norm are not currently implemented. + * The most centralized directed structure is the in-star with \p mode + * set to \c IGRAPH_OUT, and the out-star with \p mode set to \c IGRAPH_IN. + * The most centralized undirected structure is the graph with a single edge. * * \param graph A graph object or a null pointer, see the description * above. * \param nodes The number of nodes. This is ignored if the * \p graph argument is not a null pointer. - * \param directed Boolean, whether to consider edge - * directions. This argument is ignored if - * \p graph is not a null pointer and it is undirected. - * \param scale This parameter is deprecated and ignored since igraph 0.10.14. - * Vertex-level centrality scores are always assumed to be scaled to - * have a maximum of one. + * \param mode How to consider edge directions in directed graphs. + * See \ref igraph_eigenvector_centrality() for details. This argument + * is ignored if \p graph is not a null pointer and it is + * undirected. * \param res Pointer to a real variable, the result is stored here. * \return Error code. * @@ -715,22 +689,14 @@ igraph_error_t igraph_centralization_eigenvector_centrality( igraph_error_t igraph_centralization_eigenvector_centrality_tmax( const igraph_t *graph, igraph_integer_t nodes, - igraph_bool_t directed, - igraph_bool_t scale, + igraph_neimode_t mode, igraph_real_t *res) { - if (! scale) { - scale = true; - IGRAPH_WARNING("Theoretical maximum for eigenvector centralization can " - "only be computed with normalized eigenvector centrality " - "scores. Assuming that eigenvector centralities are normalized " - "by their maximum even though 'scale=false' was passed. The 'scale' " - "parameter will be removed in the future."); - } - if (graph) { nodes = igraph_vcount(graph); - directed = directed && igraph_is_directed(graph); + if (! igraph_is_directed(graph)) { + mode = IGRAPH_ALL; + } } else { if (nodes < 0) { IGRAPH_ERROR("Number of vertices must not be negative.", IGRAPH_EINVAL); @@ -747,14 +713,10 @@ igraph_error_t igraph_centralization_eigenvector_centrality_tmax( return IGRAPH_SUCCESS; } - if (directed) { + if (mode != IGRAPH_ALL) { *res = nodes - 1; } else { - if (scale) { - *res = nodes - 2; - } else { - *res = (nodes - 2.0) / M_SQRT2; - } + *res = nodes - 2; } return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/centrality/closeness.c b/src/vendor/cigraph/src/centrality/closeness.c index debba1e65cf..0e176a5821a 100644 --- a/src/vendor/cigraph/src/centrality/closeness.c +++ b/src/vendor/cigraph/src/centrality/closeness.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2020 The igraph development team @@ -14,8 +12,8 @@ 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "igraph_centrality.h" diff --git a/src/vendor/cigraph/src/centrality/coreness.c b/src/vendor/cigraph/src/centrality/coreness.c index e48d18f15be..324cea3cbac 100644 --- a/src/vendor/cigraph/src/centrality/coreness.c +++ b/src/vendor/cigraph/src/centrality/coreness.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2023 The igraph development team @@ -85,7 +84,7 @@ igraph_error_t igraph_coreness(const igraph_t *graph, IGRAPH_FINALLY(igraph_free, pos); /* maximum degree + degree of vertices */ - IGRAPH_CHECK(igraph_degree(graph, cores, igraph_vss_all(), mode, /* loops= */ true)); + IGRAPH_CHECK(igraph_degree(graph, cores, igraph_vss_all(), mode, IGRAPH_LOOPS)); /* null graph was already handled earlier, 'cores' is not empty */ maxdeg = igraph_vector_int_max(cores); @@ -123,7 +122,9 @@ igraph_error_t igraph_coreness(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, maxdeg); for (igraph_integer_t i = 0; i < no_of_nodes; i++) { igraph_integer_t v = vert[i]; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, omode)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, omode, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); igraph_integer_t nei_count = igraph_vector_int_size(&neis); for (igraph_integer_t j = 0; j < nei_count; j++) { igraph_integer_t u = VECTOR(neis)[j]; diff --git a/src/vendor/cigraph/src/centrality/eigenvector.c b/src/vendor/cigraph/src/centrality/eigenvector.c index e9d017e261d..3154614ea96 100644 --- a/src/vendor/cigraph/src/centrality/eigenvector.c +++ b/src/vendor/cigraph/src/centrality/eigenvector.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2021 The igraph development team @@ -14,21 +12,23 @@ 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "igraph_centrality.h" #include "igraph_adjlist.h" +#include "igraph_cycles.h" #include "igraph_interface.h" #include "igraph_random.h" #include "igraph_structural.h" -#include "igraph_topology.h" #include "centrality/centrality_internal.h" +#include #include +#include /* Multiplies vector 'from' by the unweighted adjacency matrix and stores the result in 'to'. */ static igraph_error_t adjmat_mul_unweighted(igraph_real_t *to, const igraph_real_t *from, @@ -82,8 +82,32 @@ static igraph_error_t adjmat_mul_weighted(igraph_real_t *to, const igraph_real_t return IGRAPH_SUCCESS; } +/* Checks if any eigenvector centrality values are zero. If they are, it indicates that the + * graph is not (strongly) connected. Eigenvector centrality is not meaningful for such graphs. + * To account for numerical inaccuracies, a threshold of 'eps' is used when testing for zero. + * This function is intended to be used with eigenvector centrality values scaled such that + * the maximum is 1. 'eps' is chosen accordinly. + */ +static void warn_zero_entries(const igraph_vector_t *evcent) { + /* This is a conservative tolerance that will still catch most values + * which should be zero without being triggered by small yet truly + * nonzero values. + * See https://github.com/igraph/igraph/pull/2592 */ + const igraph_real_t tol = 10 * DBL_EPSILON; + const igraph_integer_t n = igraph_vector_size(evcent); + + for (igraph_integer_t i=0; i < n; i++) { + igraph_real_t x = VECTOR(*evcent)[i]; + if (-tol < x && x < tol) { + IGRAPH_WARNING("Some eigenvector centralities are nearly zero, indicating that the graph may not be (strongly) connected. " + "Eigenvector centrality is not meaningful for disconnected graphs."); + return; + } + } +} + static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t *graph, igraph_vector_t *vector, - igraph_real_t *value, igraph_bool_t scale, + igraph_real_t *value, const igraph_vector_t *weights, igraph_arpack_options_t *options) { @@ -92,13 +116,14 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t igraph_vector_t degree; igraph_integer_t i; igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_bool_t negative_weights = false; if (no_of_nodes > INT_MAX) { IGRAPH_ERROR("Graph has too many vertices for ARPACK.", IGRAPH_EOVERFLOW); } - if (igraph_ecount(graph) == 0) { + if (no_of_edges == 0) { /* special case: empty graph */ if (value) { *value = 0; @@ -107,16 +132,20 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t IGRAPH_CHECK(igraph_vector_resize(vector, igraph_vcount(graph))); igraph_vector_fill(vector, 1); } + if (no_of_nodes > 1) { + IGRAPH_WARNING("The graph has no edges and is disconnected. " + "Eigenvector centrality is not meaningful for disconnected graphs."); + } return IGRAPH_SUCCESS; } if (weights) { igraph_real_t min, max; - if (igraph_vector_size(weights) != igraph_ecount(graph)) { + if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERRORF("Weights vector length (%" IGRAPH_PRId ") not equal to " "number of edges (%" IGRAPH_PRId ").", IGRAPH_EINVAL, - igraph_vector_size(weights), igraph_ecount(graph)); + igraph_vector_size(weights), no_of_edges); } /* Safe to call minmax, ecount == 0 case was caught earlier */ igraph_vector_minmax(weights, &min, &max); @@ -129,6 +158,10 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t IGRAPH_CHECK(igraph_vector_resize(vector, igraph_vcount(graph))); igraph_vector_fill(vector, 1); } + if (no_of_nodes > 1) { + IGRAPH_WARNING("All edge weights are zero, making the graph effectively disconnected. " + "Eigenvector centrality is not meaningful for disconnected graphs."); + } return IGRAPH_SUCCESS; } @@ -148,16 +181,24 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t IGRAPH_VECTOR_INIT_FINALLY(°ree, no_of_nodes); IGRAPH_CHECK(igraph_strength(graph, °ree, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, weights)); - RNG_BEGIN(); + for (i = 0; i < no_of_nodes; i++) { if (VECTOR(degree)[i]) { /* Note: Keep random perturbation non-negative. */ MATRIX(vectors, i, 0) = VECTOR(degree)[i] + RNG_UNIF(0, 1e-4); + } else if (! negative_weights) { + /* The eigenvector centrality of zero degree vertices is also zero. */ + MATRIX(vectors, i, 0) = 0.0; } else { - MATRIX(vectors, i, 0) = 0.01; + /* When negative weights are present, a zero strength may occur even + * if the degree is not zero, and some edges have non-zero weight. */ + igraph_integer_t deg; + IGRAPH_CHECK(igraph_degree_1(graph, °, i, IGRAPH_ALL, IGRAPH_LOOPS)); + MATRIX(vectors, i, 0) = deg == 0 ? 0.0 : 1.0; } + } - RNG_END(); + igraph_vector_destroy(°ree); IGRAPH_FINALLY_CLEAN(1); @@ -200,41 +241,28 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t } if (vector) { - igraph_real_t amax = 0; - igraph_integer_t which = 0; IGRAPH_CHECK(igraph_vector_resize(vector, no_of_nodes)); - if (!negative_weights && VECTOR(values)[0] <= 0) { - /* Pathological case: largest eigenvalue is zero, therefore all the - * scores can also be zeros, this will be a valid eigenvector. - * This usually happens with graphs that have lots of sinks and - * sources only. */ - igraph_vector_fill(vector, 0); - VECTOR(values)[0] = 0; - } else { + /* Note: With non-negative weights, a zero eigenvalue should only occur + * when there are no edges, or all edge have zero weight. This case is + * caught earlier. Thus we do not handle the case of zero eigenvalues here .*/ + + for (i = 0; i < no_of_nodes; i++) { + VECTOR(*vector)[i] = MATRIX(vectors, i, 0); + } + + /* Scale result so that the largest value is 1.0. */ + igraph_i_vector_scale_by_max_abs(vector); + + /* Correction for numeric inaccuracies (eliminating -0.0) */ + if (! negative_weights) { for (i = 0; i < no_of_nodes; i++) { - igraph_real_t tmp; - VECTOR(*vector)[i] = MATRIX(vectors, i, 0); - tmp = fabs(VECTOR(*vector)[i]); - if (tmp > amax) { - amax = tmp; - which = i; + if (VECTOR(*vector)[i] < 0) { + VECTOR(*vector)[i] = 0; } } - if (scale && amax != 0) { - igraph_vector_scale(vector, 1 / VECTOR(*vector)[which]); - } else if (igraph_i_vector_mostly_negative(vector)) { - igraph_vector_scale(vector, -1.0); - } - /* Correction for numeric inaccuracies (eliminating -0.0) */ - if (! negative_weights) { - for (i = 0; i < no_of_nodes; i++) { - if (VECTOR(*vector)[i] < 0) { - VECTOR(*vector)[i] = 0; - } - } - } + warn_zero_entries(vector); } } @@ -254,7 +282,8 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t } static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *graph, igraph_vector_t *vector, - igraph_real_t *value, igraph_bool_t scale, + igraph_real_t *value, + igraph_neimode_t mode, const igraph_vector_t *weights, igraph_arpack_options_t *options) { @@ -263,10 +292,12 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g igraph_vector_t indegree; igraph_bool_t dag; igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i; + igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_bool_t negative_weights = false; - if (igraph_ecount(graph) == 0) { + mode = IGRAPH_REVERSE_MODE(mode); + + if (no_of_edges == 0) { /* special case: empty graph */ if (value) { *value = 0; @@ -275,16 +306,20 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g IGRAPH_CHECK(igraph_vector_resize(vector, igraph_vcount(graph))); igraph_vector_fill(vector, 1); } + if (no_of_nodes > 1) { + IGRAPH_WARNING("The graph has no edges and is disconnected. " + "Eigenvector centrality is not meaningful for disconnected graphs."); + } return IGRAPH_SUCCESS; } if (weights) { igraph_real_t min, max; - if (igraph_vector_size(weights) != igraph_ecount(graph)) { + if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERRORF("Weights vector length (%" IGRAPH_PRId ") not equal to " "number of edges (%" IGRAPH_PRId ").", IGRAPH_EINVAL, - igraph_vector_size(weights), igraph_ecount(graph)); + igraph_vector_size(weights), no_of_edges); } /* Safe to call minmax, ecount == 0 case was caught earlier */ @@ -305,6 +340,10 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g IGRAPH_CHECK(igraph_vector_resize(vector, igraph_vcount(graph))); igraph_vector_fill(vector, 1); } + if (no_of_nodes > 1) { + IGRAPH_WARNING("All edge weights are zero, making the graph effectively disconnected. " + "Eigenvector centrality is not meaningful for disconnected graphs."); + } return IGRAPH_SUCCESS; } } @@ -339,8 +378,11 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g *value = 0; } if (vector) { - IGRAPH_CHECK(igraph_strength(graph, vector, igraph_vss_all(), IGRAPH_OUT, true, weights)); - for (i=0; i < no_of_nodes; i++) { + IGRAPH_CHECK(igraph_strength( + graph, vector, igraph_vss_all(), IGRAPH_REVERSE_MODE(mode), + IGRAPH_LOOPS, weights + )); + for (igraph_integer_t i=0; i < no_of_nodes; i++) { if (VECTOR(*vector)[i] == 0) { VECTOR(*vector)[i] = 1; } else { @@ -372,24 +414,31 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g IGRAPH_VECTOR_INIT_FINALLY(&indegree, no_of_nodes); IGRAPH_CHECK(igraph_strength(graph, &indegree, igraph_vss_all(), - IGRAPH_IN, IGRAPH_LOOPS, weights)); - RNG_BEGIN(); - for (i = 0; i < no_of_nodes; i++) { + mode, IGRAPH_LOOPS, weights)); + + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { if (VECTOR(indegree)[i]) { /* Note: Keep random perturbation non-negative. */ MATRIX(vectors, i, 0) = VECTOR(indegree)[i] + RNG_UNIF(0, 1e-4); + } else if (! negative_weights) { + /* The eigenvector centrality of zero in-degree vertices is also zero. */ + MATRIX(vectors, i, 0) = 0.0; } else { - MATRIX(vectors, i, 0) = 0.01; + /* When negative weights are present, a zero in-strength may occur even + * if the in-degree is not zero, and some in-edges have non-zero weight. */ + igraph_integer_t deg; + IGRAPH_CHECK(igraph_degree_1(graph, °, i, mode, IGRAPH_LOOPS)); + MATRIX(vectors, i, 0) = deg == 0 ? 0.0 : 1.0; } } - RNG_END(); + igraph_vector_destroy(&indegree); IGRAPH_FINALLY_CLEAN(1); if (!weights) { igraph_adjlist_t adjlist; - IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE)); + IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); IGRAPH_CHECK(igraph_arpack_rnsolve(adjmat_mul_unweighted, @@ -406,7 +455,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g data.inclist = &inclist; data.weights = weights; - IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, IGRAPH_IN, IGRAPH_LOOPS_ONCE)); + IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, mode, IGRAPH_LOOPS_ONCE)); IGRAPH_FINALLY(igraph_inclist_destroy, &inclist); IGRAPH_CHECK(igraph_arpack_rnsolve(adjmat_mul_weighted, @@ -417,9 +466,6 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g } if (vector) { - igraph_real_t amax = 0; - igraph_integer_t which = 0; - IGRAPH_CHECK(igraph_vector_resize(vector, options->n)); if (!negative_weights && MATRIX(values, 0, 0) <= 0) { @@ -430,29 +476,23 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g igraph_vector_fill(vector, 0); MATRIX(values, 0, 0) = 0; } else { - for (i = 0; i < no_of_nodes; i++) { - igraph_real_t tmp; + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { VECTOR(*vector)[i] = MATRIX(vectors, i, 0); - tmp = fabs(VECTOR(*vector)[i]); - if (tmp > amax) { - amax = tmp; - which = i; - } - } - if (scale && amax != 0) { - igraph_vector_scale(vector, 1 / VECTOR(*vector)[which]); - } else if (igraph_i_vector_mostly_negative(vector)) { - igraph_vector_scale(vector, -1.0); } + + /* Scale result so that the largest value is 1.0. */ + igraph_i_vector_scale_by_max_abs(vector); } /* Correction for numeric inaccuracies (eliminating -0.0) */ if (! negative_weights) { - for (i = 0; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { if (VECTOR(*vector)[i] < 0) { VECTOR(*vector)[i] = 0; } } + + warn_zero_entries(vector); } } @@ -483,7 +523,13 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g * vertex is proportional to the sum of eigenvector centralities of its * neighbors. In practice, the centralities are determined by calculating the * eigenvector corresponding to the largest positive eigenvalue of the - * adjacency matrix. In the undirected case, this function considers + * adjacency matrix. This is motivated by the fact that the principal + * eigenvector is guaranteed to be non-negative, assuming that edge weights + * are also non-negative. In fact, in connected undirected graphs, this is + * the \em only non-negative eigenvector. + * + * + * In the undirected case, this function considers * the diagonal entries of the adjacency matrix to be \em twice the number of * self-loops on the corresponding vertex. * @@ -495,35 +541,35 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g * are added up. * * - * The centrality scores returned by igraph can be normalized - * (using the \p scale parameter) such that the largest eigenvector centrality - * score is 1 (with one exception, see below). - * - * - * In the directed case, the left eigenvector of the adjacency matrix is - * calculated. In other words, the centrality of a vertex is proportional - * to the sum of centralities of vertices pointing to it. + * The centrality scores returned by igraph are normalized such that the largest + * eigenvector centrality score is 1, unless all scores are zeros. * * * Eigenvector centrality is meaningful only for (strongly) connected graphs. * Undirected graphs that are not connected should be decomposed into connected * components, and the eigenvector centrality calculated for each separately. - * The scores between components will not be comparable. - * This function does not verify that the graph is connected. If it is not, - * in the undirected case the scores of all but one component will be zeros. + * This function does not directly verify that the graph is connected. If it is + * not, in the undirected case the scores of all but one component will typically + * be zeros. When zeros are detected, a warning is issued. * * * Also note that the adjacency matrix of a directed acyclic graph or the * adjacency matrix of an empty graph does not possess positive eigenvalues, * therefore the eigenvector centrality is not meaningful for these graphs. * igraph will return an eigenvalue of zero in such cases. The returned - * eigenvector centralities will all be equal for vertices with zero out-degree, + * eigenvector centralities will all be equal for vertices with zero out-degree + * or zero in-degrees (depending on whether \p mode is \c IGRAPH_OUT or \c IGRAPH_IN) * and zeros for other vertices. Such pathological cases can be detected * by asking igraph to calculate the eigenvalue as well (using the \p value * parameter, see below) and checking whether the eigenvalue is very close * to zero. * * + * Eigenvector centrality was developed for networks with non-negative edge + * weights. While igraph does not refuse to carry out the calculation with + * negative weights, it will issue a warning. + * + * * When working with directed graphs, consider using hub and authority * scores instead, see \ref igraph_hub_and_authority_scores(). * @@ -533,10 +579,22 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g * be a null pointer, then it is ignored. * \param value If not a null pointer, then the eigenvalue * corresponding to the found eigenvector is stored here. - * \param directed Boolean scalar, whether to consider edge directions - * in a directed graph. It is ignored for undirected graphs. - * \param scale If not zero then the result will be scaled such that - * the absolute value of the maximum centrality is one. + * \param mode How to consider edge directions in directed graphs. + * It is ignored for undirected graphs. Possible values: + * \clist + * \cli IGRAPH_OUT + * the left eigenvector of the adjacency matrix is calculated, + * i.e. the centrality of a vertex is proportional to the sum + * of centralities of vertices pointing to it. This is the standard + * eigenvector centrality. + * \cli IGRAPH_IN + * the right eigenvector of the adjacency matrix is calculated, + * i.e. the centrality of a vertex is proportional to the sum + * of centralities of vertices it points to. + * \cli IGRAPH_ALL + * edge directions are ignored, and the unweighted eigenvector + * centrality is calculated. + * \endclist * \param weights A null pointer (indicating no edge weights), or a vector * giving the weights of the edges. Weights should be positive to guarantee * a meaningful result. The algorithm might produce complex numbers when some @@ -562,7 +620,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g igraph_error_t igraph_eigenvector_centrality(const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, - igraph_bool_t directed, igraph_bool_t scale, + igraph_neimode_t mode, const igraph_vector_t *weights, igraph_arpack_options_t *options) { @@ -570,11 +628,19 @@ igraph_error_t igraph_eigenvector_centrality(const igraph_t *graph, options = igraph_arpack_options_get_default(); } - if (directed && igraph_is_directed(graph)) { - return igraph_i_eigenvector_centrality_directed(graph, vector, value, - scale, weights, options); - } else { + if (mode != IGRAPH_ALL && mode != IGRAPH_OUT && mode != IGRAPH_IN) { + IGRAPH_ERROR("Invalid mode for eigenvector centrality.", IGRAPH_EINVAL); + } + + if (! igraph_is_directed(graph)) { + mode = IGRAPH_ALL; + } + + if (mode == IGRAPH_ALL) { return igraph_i_eigenvector_centrality_undirected(graph, vector, value, - scale, weights, options); + weights, options); + } else { + return igraph_i_eigenvector_centrality_directed(graph, vector, value, + mode, weights, options); } } diff --git a/src/vendor/cigraph/src/centrality/hub_authority.c b/src/vendor/cigraph/src/centrality/hub_authority.c index a034c926a38..4587cee7673 100644 --- a/src/vendor/cigraph/src/centrality/hub_authority.c +++ b/src/vendor/cigraph/src/centrality/hub_authority.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2021 The igraph development team @@ -14,20 +12,20 @@ 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "igraph_centrality.h" #include "igraph_adjlist.h" -#include "igraph_blas.h" #include "igraph_interface.h" -#include "igraph_random.h" #include "igraph_structural.h" +#include "igraph_random.h" #include "centrality/centrality_internal.h" +#include #include /* struct for the unweighted variant of the HITS algorithm */ @@ -46,6 +44,47 @@ typedef struct igraph_i_kleinberg_data2_t { const igraph_vector_t *weights; } igraph_i_kleinberg_data2_t; +/* Checks if at least a certain fraction of HITS centrality scores are zero. + * Any zero value indicates that the graphs corresponding to A A^T and A^T A are + * not connected, and therefore the solution is not unique. However, this situation + * is fairly common, and difficult to control. Thefore we only warn if the number + * of zero values exceeds a certain fraction. + * + * To account for numerical inaccuracies, a threshold of 'eps' is used when testing for zero. + * This function is intended to be used with centrality values scaled such that + * the maximum is 1. 'eps' is chosen accordinly. + * + * See the analogous function used in igraph_eigenvector_centrality() for details + * on the choice of 'eps'. + */ +static void warn_zero_entries(const igraph_vector_t *cent) { + const igraph_real_t tol = 10 * DBL_EPSILON; + const igraph_real_t frac = 0.3; /* warn if at least this fraction of centralities is zero */ + const igraph_integer_t n = igraph_vector_size(cent); + + /* Skip check for small graphs */ + if (n < 10) { + return; + } + + const igraph_integer_t max_zero_cnt = (igraph_integer_t) frac*n; + igraph_integer_t zero_cnt = 0; + + for (igraph_integer_t i=0; i < n; i++) { + igraph_real_t x = VECTOR(*cent)[i]; + if (-tol < x && x < tol) { + if (++zero_cnt > max_zero_cnt) { + IGRAPH_WARNINGF( + "More than %d%% of hub or authority scores are zeros. The presence of zero values " + "indicates that the solution is not unique, thus the returned result may not be meaningful.", + (int) (frac * 100) + ); + return; + } + } + } +} + static igraph_error_t igraph_i_kleinberg_unweighted_hub_to_auth( igraph_integer_t n, igraph_vector_t *to, const igraph_real_t *from, igraph_adjlist_t *in) { @@ -151,48 +190,64 @@ static igraph_error_t igraph_i_kleinberg_weighted(igraph_real_t *to, * The hub and authority scores of the vertices are defined as the principal * eigenvectors of A A^T and A^T A, respectively, * where A is the adjacency matrix of the graph and A^T - * is its transposed. + * is its transpose. The motivation for choosing the principal eigenvector + * is that it is guaranteed to be non-negative when edge weights are also + * non-negative. * * - * If vector \c h and \c a contain hub and authority scores, then the two - * scores are related by h = Aa and a = A^T h. + * If vectors \c h and \c a contain hub and authority scores, then the two + * scores are related by h = A a and a = A^T h. * When the principal eigenvalue of A A^T is degenerate, there * is no unique solution to the hub- and authority-score problem. * igraph guarantees that the scores that are returned are matching, i.e. are * related by these formulas, even in this situation. * * + * Note that hub and authority scores are not well behaved in extremely sparse + * graphs where no single connected component dominates the undirected graphs + * corresponding to A A^T and A^T A. In these cases, + * there are many different non-negative eigenvectors, all reasonable solutions + * to the HITS equations. The symptom of such a situation is that a large + * fraction of the scores are zeros. igraph issues a warning when this is + * detected. + * + * + * Results are scaled so that the largest hub and authority scores are both 1. + * + * * The concept of hub and authority scores were developed for \em directed graphs. * In undirected graphs, both the hub and authority scores are equal to the * eigenvector centrality, which can be computed using * \ref igraph_eigenvector_centrality(). * * + * HITS scores were developed for networks with non-negative edge weights. + * While igraph does not refuse to carry out the calculation with negative + * weights, it will issue a warning. + * + * * See the following reference on the meaning of this score: * J. Kleinberg. Authoritative sources in a hyperlinked * environment. \emb Proc. 9th ACM-SIAM Symposium on Discrete * Algorithms, \eme 1998. Extended version in \emb Journal of the - * ACM \eme 46(1999). + * ACM \eme 46 (1999). * https://doi.org/10.1145/324133.324140 - * Also appears as IBM Research Report RJ 10076, May - * 1997. + * Also appears as IBM Research Report RJ 10076, May 1997. * * \param graph The input graph. Can be directed and undirected. * \param hub_vector Pointer to an initialized vector, the hub scores are * stored here. If a null pointer then it is ignored. - * \param authority_vector Pointer to an initialized vector, the authority scores are - * stored here. If a null pointer then it is ignored. + * \param authority_vector Pointer to an initialized vector, the authority + * scores are stored here. If a null pointer then it is ignored. * \param value If not a null pointer then the eigenvalue * corresponding to the calculated eigenvectors is stored here. - * \param scale If not zero then the result will be scaled such that - * the absolute value of the maximum centrality is one. * \param weights A null pointer (meaning no edge weights), or a vector * giving the weights of the edges. * \param options Options to ARPACK. See \ref igraph_arpack_options_t - * for details. Supply \c NULL here to use the defaults. Note that the function - * overwrites the n (number of vertices) parameter and - * it always starts the calculation from a vector calculated based - * on the degree of the vertices. + * for details. Supply \c NULL here to use the defaults. Note that the + * function overwrites the n (number of vertices) parameter + * and it always starts the calculation from a vector calculated based on + * the degree of the vertices. * \return Error code. * * Time complexity: depends on the input graph, usually it is O(|V|), @@ -204,7 +259,7 @@ static igraph_error_t igraph_i_kleinberg_weighted(igraph_real_t *to, */ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, igraph_vector_t *hub_vector, igraph_vector_t *authority_vector, - igraph_real_t *value, igraph_bool_t scale, + igraph_real_t *value, const igraph_vector_t *weights, igraph_arpack_options_t *options) { /* The current implementation computes hub scores, i.e the principal @@ -223,10 +278,43 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, igraph_vector_t my_hub_vector; igraph_bool_t negative_weights = false; + if (! igraph_is_directed(graph)) { + /* In undirected graphs, hub and authority scores are the same as eigenvector + * centralities. We issue a warning to avoid user confusion. + * If Ax = lambda x then A^2 x = lambda^2 x. Therefore the principal + * eigenvector of A is also a principal eigenvector of A^2. However, + * if both lambda and -lambda are eigenvalues of A, then the lambda^2 + * eigenvalue of A^2 will be degenerate. This happens for example in + * an even cycle graph where 2 and -2 are the largest eigenvalues in magnitude, + * therefore 4 is a degenerate eigenvalue of A^2, with eigenspace spanned by + * (0, 1, 0, 1, ...) and (1, 0, 1, ...). The vector (1, 1, ...), which + * would be expected by users based on symmetry considerations, may not be + * returned. We avoid such issues by falling back to igraph_eigenvector_centrality() */ + + IGRAPH_WARNING("Hub and authority scores requested for undirected graph. " + "These are the same as eigenvector centralities."); + if (! hub_vector) { + IGRAPH_VECTOR_INIT_FINALLY(&my_hub_vector, no_of_nodes); + my_hub_vector_p = &my_hub_vector; + } else { + my_hub_vector_p = hub_vector; + } + IGRAPH_CHECK(igraph_eigenvector_centrality(graph, my_hub_vector_p, value, IGRAPH_ALL, weights, options)); + *value = (*value) * (*value); /* adjust the eigenvalue, see comment at top */ + if (authority_vector) { + IGRAPH_CHECK(igraph_vector_update(authority_vector, my_hub_vector_p)); + } + if (! hub_vector) { + igraph_vector_destroy(&my_hub_vector); + IGRAPH_FINALLY_CLEAN(1); + } + return IGRAPH_SUCCESS; + } + if (igraph_ecount(graph) == 0) { /* special case: empty graph */ if (value) { - *value = igraph_ecount(graph) ? 1.0 : IGRAPH_NAN; + *value = 0; } if (hub_vector) { IGRAPH_CHECK(igraph_vector_resize(hub_vector, no_of_nodes)); @@ -236,6 +324,9 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_resize(authority_vector, no_of_nodes)); igraph_vector_fill(authority_vector, 1.0); } + if (no_of_nodes > 1) { + IGRAPH_WARNING("The graph has no edges. Hub and authority scores are not meaningful."); + } return IGRAPH_SUCCESS; } @@ -267,7 +358,7 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, if (min == 0 && max == 0) { /* special case: all weights are zeros */ if (value) { - *value = IGRAPH_NAN; + *value = 0; } if (hub_vector) { IGRAPH_CHECK(igraph_vector_resize(hub_vector, no_of_nodes)); @@ -277,12 +368,13 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_resize(authority_vector, no_of_nodes)); igraph_vector_fill(authority_vector, 1); } + IGRAPH_WARNING("All edge weights are zero. Hub and authority scores are not meaningful."); return IGRAPH_SUCCESS; } } if (no_of_nodes > INT_MAX) { - IGRAPH_ERROR("Graph has too many vertices for ARPACK", IGRAPH_EOVERFLOW); + IGRAPH_ERROR("Graph has too many vertices for ARPACK.", IGRAPH_EOVERFLOW); } if (!options) { @@ -308,17 +400,25 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, IGRAPH_FINALLY(igraph_inclist_destroy, &outinclist); } + /* We calculate hub scores, which correlate with out-degrees / out-strengths. + * Thus we use out-strengths as starting values. */ IGRAPH_CHECK(igraph_strength(graph, &tmp, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, weights)); - RNG_BEGIN(); + for (igraph_integer_t i = 0; i < options->n; i++) { if (VECTOR(tmp)[i] != 0) { /* Note: Keep random perturbation non-negative. */ MATRIX(vectors, i, 0) = VECTOR(tmp)[i] + RNG_UNIF(0, 1e-4); + } else if (! negative_weights) { + /* The hub score of zero out-degree vertices is also zero. */ + MATRIX(vectors, i, 0) = 0.0; } else { - MATRIX(vectors, i, 0) = 0.01; + /* When negative weights are present, a zero out-strength may occur even + * if the out-degree is not zero, and some out-edges have non-zero weight. */ + igraph_integer_t deg; + IGRAPH_CHECK(igraph_degree_1(graph, °, i, IGRAPH_OUT, /* loops */ true)); + MATRIX(vectors, i, 0) = deg == 0 ? 0.0 : 1.0; } } - RNG_END(); extra.in = &inadjlist; extra.out = &outadjlist; extra.tmp = &tmp; extra2.in = &ininclist; extra2.out = &outinclist; extra2.tmp = &tmp; @@ -336,7 +436,6 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, options, 0, &values, &vectors)); } - if (value) { *value = VECTOR(values)[0]; } @@ -348,25 +447,14 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, } else { my_hub_vector_p = hub_vector; } - igraph_real_t amax = 0; - igraph_integer_t which = 0; IGRAPH_CHECK(igraph_vector_resize(my_hub_vector_p, options->n)); for (igraph_integer_t i = 0; i < options->n; i++) { - igraph_real_t tmp; VECTOR(*my_hub_vector_p)[i] = MATRIX(vectors, i, 0); - tmp = fabs(VECTOR(*my_hub_vector_p)[i]); - if (tmp > amax) { - amax = tmp; - which = i; - } - } - if (scale && amax != 0) { - igraph_vector_scale(my_hub_vector_p, 1 / VECTOR(*my_hub_vector_p)[which]); - } else if (igraph_i_vector_mostly_negative(my_hub_vector_p)) { - igraph_vector_scale(my_hub_vector_p, -1.0); } + igraph_i_vector_scale_by_max_abs(my_hub_vector_p); + /* Correction for numeric inaccuracies (eliminating -0.0) */ if (! negative_weights) { for (igraph_integer_t i = 0; i < options->n; i++) { @@ -375,6 +463,8 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, } } } + + warn_zero_entries(my_hub_vector_p); } if (options->info) { @@ -385,7 +475,6 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, IGRAPH_FINALLY_CLEAN(2); if (authority_vector) { - igraph_real_t norm; IGRAPH_CHECK(igraph_vector_resize(authority_vector, no_of_nodes)); igraph_vector_null(authority_vector); if (weights == NULL) { @@ -393,12 +482,7 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, } else { igraph_i_kleinberg_weighted_hub_to_auth(no_of_nodes, authority_vector, &VECTOR(*my_hub_vector_p)[0], &ininclist, graph, weights); } - if (!scale) { - norm = 1.0 / igraph_blas_dnrm2(authority_vector); - } else { - norm = 1.0 / igraph_vector_max(authority_vector); - } - igraph_vector_scale(authority_vector, norm); + igraph_i_vector_scale_by_max_abs(authority_vector); } if (!hub_vector && authority_vector) { @@ -419,105 +503,3 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, return IGRAPH_SUCCESS; } - -/** - * \function igraph_hub_score - * \brief Kleinberg's hub scores. - * - * \deprecated-by igraph_hub_and_authority_scores 0.10.5 - * - * The hub scores of the vertices are defined as the principal - * eigenvector of A A^T, where A is the adjacency - * matrix of the graph, A^T is its transposed. - * - * - * See the following reference on the meaning of this score: - * J. Kleinberg. Authoritative sources in a hyperlinked - * environment. \emb Proc. 9th ACM-SIAM Symposium on Discrete - * Algorithms, \eme 1998. Extended version in \emb Journal of the - * ACM \eme 46(1999). Also appears as IBM Research Report RJ 10076, May - * 1997. - * - * \param graph The input graph. Can be directed and undirected. - * \param vector Pointer to an initialized vector, the result is - * stored here. If a null pointer then it is ignored. - * \param value If not a null pointer then the eigenvalue - * corresponding to the calculated eigenvector is stored here. - * \param scale If not zero then the result will be scaled such that - * the absolute value of the maximum centrality is one. - * \param weights A null pointer (=no edge weights), or a vector - * giving the weights of the edges. - * \param options Options to ARPACK. See \ref igraph_arpack_options_t - * for details. Note that the function overwrites the - * n (number of vertices) parameter and - * it always starts the calculation from a non-random vector - * calculated based on the degree of the vertices. - * \return Error code. - * - * Time complexity: depends on the input graph, usually it is O(|V|), - * the number of vertices. - * - * \sa \ref igraph_hub_and_authority_scores() to compute - * hub and authrotity scores efficiently at the same time, - * \ref igraph_authority_score() for the companion measure, - * \ref igraph_pagerank(), \ref igraph_personalized_pagerank(), - * \ref igraph_eigenvector_centrality() for similar measures. - */ - -igraph_error_t igraph_hub_score(const igraph_t *graph, igraph_vector_t *vector, - igraph_real_t *value, igraph_bool_t scale, - const igraph_vector_t *weights, - igraph_arpack_options_t *options) { - return igraph_hub_and_authority_scores(graph, vector, NULL, value, scale, weights, options); -} - -/** - * \function igraph_authority_score - * \brief Kleinberg's authority scores. - * - * \deprecated-by igraph_hub_and_authority_scores 0.10.5 - * - * The authority scores of the vertices are defined as the principal - * eigenvector of A^T A, where A is the adjacency - * matrix of the graph, A^T is its transposed. - * - * - * See the following reference on the meaning of this score: - * J. Kleinberg. Authoritative sources in a hyperlinked - * environment. \emb Proc. 9th ACM-SIAM Symposium on Discrete - * Algorithms, \eme 1998. Extended version in \emb Journal of the - * ACM \eme 46(1999). Also appears as IBM Research Report RJ 10076, May - * 1997. - * - * \param graph The input graph. Can be directed and undirected. - * \param vector Pointer to an initialized vector, the result is - * stored here. If a null pointer then it is ignored. - * \param value If not a null pointer then the eigenvalue - * corresponding to the calculated eigenvector is stored here. - * \param scale If not zero then the result will be scaled such that - * the absolute value of the maximum centrality is one. - * \param weights A null pointer (=no edge weights), or a vector - * giving the weights of the edges. - * \param options Options to ARPACK. See \ref igraph_arpack_options_t - * for details. Note that the function overwrites the - * n (number of vertices) parameter and - * it always starts the calculation from a non-random vector - * calculated based on the degree of the vertices. - * \return Error code. - * - * Time complexity: depends on the input graph, usually it is O(|V|), - * the number of vertices. - * - * \sa \ref igraph_hub_and_authority_scores() to compute - * hub and authrotity scores efficiently at the same time, - * \ref igraph_hub_score() for the companion measure, - * \ref igraph_pagerank(), \ref igraph_personalized_pagerank(), - * \ref igraph_eigenvector_centrality() for similar measures. - */ - -igraph_error_t igraph_authority_score(const igraph_t *graph, igraph_vector_t *vector, - igraph_real_t *value, igraph_bool_t scale, - const igraph_vector_t *weights, - igraph_arpack_options_t *options) { - return igraph_hub_and_authority_scores(graph, NULL, vector, value, scale, weights, options); -} diff --git a/src/vendor/cigraph/src/centrality/pagerank.c b/src/vendor/cigraph/src/centrality/pagerank.c index 04115c21fe5..e0511edf88f 100644 --- a/src/vendor/cigraph/src/centrality/pagerank.c +++ b/src/vendor/cigraph/src/centrality/pagerank.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2021 The igraph development team @@ -14,8 +12,8 @@ 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "igraph_centrality.h" @@ -597,8 +595,6 @@ static igraph_error_t igraph_i_personalized_pagerank_arpack(const igraph_t *grap IGRAPH_VECTOR_INIT_FINALLY(&outdegree, options->n); IGRAPH_VECTOR_INIT_FINALLY(&tmp, options->n); - RNG_BEGIN(); - if (reset) { /* Normalize reset vector so the sum is 1 */ IGRAPH_CHECK(igraph_vector_init_copy(&normalized_reset, reset)); @@ -612,8 +608,8 @@ static igraph_error_t igraph_i_personalized_pagerank_arpack(const igraph_t *grap IGRAPH_CHECK(igraph_strength(graph, &indegree, igraph_vss_all(), directed ? IGRAPH_IN : IGRAPH_ALL, IGRAPH_LOOPS, weights)); - /* Set up an appropriate starting vector. We start from the (possibly weight) in-degrees - * plus some small random noise to avoid convergence problems. */ + /* Set up an appropriate starting vector. We start from the (possibly weighted) + * in-degrees plus some small random noise to avoid convergence problems. */ for (i = 0; i < no_of_nodes; i++) { if (VECTOR(indegree)[i] > 0) { /* Note: Keep random perturbation non-negative. */ @@ -667,8 +663,6 @@ static igraph_error_t igraph_i_personalized_pagerank_arpack(const igraph_t *grap IGRAPH_FINALLY_CLEAN(1); } - RNG_END(); - if (reset) { igraph_vector_destroy(&normalized_reset); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/centrality/prpack.cpp b/src/vendor/cigraph/src/centrality/prpack.cpp index ad3c73a284a..2ba52f362e4 100644 --- a/src/vendor/cigraph/src/centrality/prpack.cpp +++ b/src/vendor/cigraph/src/centrality/prpack.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2021 The igraph development team diff --git a/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp b/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp index fa84057660d..622213e4f29 100644 --- a/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp +++ b/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp @@ -103,7 +103,7 @@ igraph_error_t prpack_igraph_graph::convert_from_igraph( IGRAPH_FINALLY(igraph_vector_int_destroy, &neis); for (int i = 0; i < num_vs; i++) { - IGRAPH_CHECK(igraph_incident(g, &neis, i, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(g, &neis, i, IGRAPH_ALL, IGRAPH_LOOPS)); int temp = igraph_vector_int_size(&neis); diff --git a/src/vendor/cigraph/src/centrality/prpack_internal.h b/src/vendor/cigraph/src/centrality/prpack_internal.h index 938a41e63ed..50a240f7373 100644 --- a/src/vendor/cigraph/src/centrality/prpack_internal.h +++ b/src/vendor/cigraph/src/centrality/prpack_internal.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -31,7 +30,7 @@ #include "igraph_interface.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_personalized_pagerank_prpack(const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, const igraph_vs_t vids, @@ -39,6 +38,6 @@ igraph_error_t igraph_i_personalized_pagerank_prpack(const igraph_t *graph, igra const igraph_vector_t *reset, const igraph_vector_t *weights); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/centrality/truss.cpp b/src/vendor/cigraph/src/centrality/truss.cpp index b4fbc60b6be..76e96478c32 100644 --- a/src/vendor/cigraph/src/centrality/truss.cpp +++ b/src/vendor/cigraph/src/centrality/truss.cpp @@ -25,9 +25,6 @@ */ -#include -#include - #include "igraph_community.h" #include "igraph_adjlist.h" @@ -39,6 +36,9 @@ #include "core/exceptions.h" #include "core/interruption.h" +#include +#include + using std::vector; using std::unordered_set; diff --git a/src/vendor/cigraph/src/cliques/cliquer_internal.h b/src/vendor/cigraph/src/cliques/cliquer_internal.h index 93e9897978e..ecd440a8a2f 100644 --- a/src/vendor/cigraph/src/cliques/cliquer_internal.h +++ b/src/vendor/cigraph/src/cliques/cliquer_internal.h @@ -22,7 +22,7 @@ #include "igraph_decls.h" #include "igraph_cliques.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_cliquer_cliques(const igraph_t *graph, igraph_vector_int_list_t *res, igraph_integer_t min_size, igraph_integer_t max_size); @@ -44,6 +44,6 @@ igraph_error_t igraph_i_largest_weighted_cliques(const igraph_t *graph, igraph_error_t igraph_i_weighted_clique_number(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_real_t *res); -__END_DECLS +IGRAPH_END_C_DECLS #endif // IGRAPH_CLIQUER_H diff --git a/src/vendor/cigraph/src/cliques/cliques.c b/src/vendor/cigraph/src/cliques/cliques.c index 63606b18e2f..216d22c517d 100644 --- a/src/vendor/cigraph/src/cliques/cliques.c +++ b/src/vendor/cigraph/src/cliques/cliques.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2023 The igraph development team @@ -1008,7 +1007,7 @@ static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets(const igrap clqdata.keep_only_largest = keep_only_largest; if (complementer) { - IGRAPH_CHECK(igraph_adjlist_init_complementer(graph, &clqdata.adj_list, IGRAPH_ALL, 0)); + IGRAPH_CHECK(igraph_adjlist_init_complementer(graph, &clqdata.adj_list, IGRAPH_ALL, IGRAPH_NO_LOOPS)); } else { IGRAPH_CHECK(igraph_adjlist_init( graph, &clqdata.adj_list, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE diff --git a/src/vendor/cigraph/src/cliques/glet.c b/src/vendor/cigraph/src/cliques/glet.c index d400e51d241..a87a62e5ec1 100644 --- a/src/vendor/cigraph/src/cliques/glet.c +++ b/src/vendor/cigraph/src/cliques/glet.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2013 Gabor Csardi @@ -201,7 +200,7 @@ static igraph_error_t igraph_i_subclique_next(const igraph_t *graph, for (v = 0; v < clsize; v++) { igraph_integer_t i, neilen, node = VECTOR(*clique)[v]; - IGRAPH_CHECK(igraph_incident(graph, &neis, node, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &neis, node, IGRAPH_ALL, IGRAPH_LOOPS)); neilen = igraph_vector_int_size(&neis); VECTOR(mark)[node] = c + 1; for (i = 0; i < neilen; i++) { @@ -558,19 +557,10 @@ igraph_error_t igraph_graphlets_candidate_basis(const igraph_t *graph, IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_is_simple(graph, &simple)); + IGRAPH_CHECK(igraph_is_simple(graph, &simple, IGRAPH_UNDIRECTED)); if (!simple) { IGRAPH_ERROR("Graphlets work on simple graphs only", IGRAPH_EINVAL); } - if (igraph_is_directed(graph)) { - /* When the graph is directed, mutual edges are effectively multi-edges as we - * are ignoring edge directions. */ - igraph_bool_t has_mutual; - IGRAPH_CHECK(igraph_has_mutual(graph, &has_mutual, false)); - if (has_mutual) { - IGRAPH_ERROR("Graphlets work on simple graphs only", IGRAPH_EINVAL); - } - } /* Internally, we will still use igraph_vector_ptr_t instead of * igraph_vector_int_list_t to manage the list of cliques; this is because @@ -641,19 +631,10 @@ igraph_error_t igraph_i_graphlets_project( if (niter < 0) { IGRAPH_ERROR("Number of iterations must be non-negative", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_is_simple(graph, &simple)); + IGRAPH_CHECK(igraph_is_simple(graph, &simple, IGRAPH_UNDIRECTED)); if (!simple) { IGRAPH_ERROR("Graphlets work on simple graphs only", IGRAPH_EINVAL); } - if (igraph_is_directed(graph)) { - /* When the graph is directed, mutual edges are effectively multi-edges as we - * are ignoring edge directions. */ - igraph_bool_t has_mutual; - IGRAPH_CHECK(igraph_has_mutual(graph, &has_mutual, false)); - if (has_mutual) { - IGRAPH_ERROR("Graphlets work on simple graphs only", IGRAPH_EINVAL); - } - } if (!startMu) { IGRAPH_CHECK(igraph_vector_resize(Mu, no_cliques)); @@ -891,7 +872,7 @@ igraph_error_t igraph_graphlets(const igraph_t *graph, igraph_i_graphlets_order_cmp); IGRAPH_CHECK(igraph_vector_int_list_permute(cliques, &order)); - IGRAPH_CHECK(igraph_vector_index_int(Mu, &order)); + IGRAPH_CHECK(igraph_vector_index_in_place(Mu, &order)); igraph_vector_int_destroy(&order); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/cliques/maximal_cliques.c b/src/vendor/cigraph/src/cliques/maximal_cliques.c index f676fe5b245..d392465e3e9 100644 --- a/src/vendor/cigraph/src/cliques/maximal_cliques.c +++ b/src/vendor/cigraph/src/cliques/maximal_cliques.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2013 Gabor Csardi diff --git a/src/vendor/cigraph/src/cliques/maximal_cliques_template.h b/src/vendor/cigraph/src/cliques/maximal_cliques_template.h index 699b0317b1c..63d18c17c79 100644 --- a/src/vendor/cigraph/src/cliques/maximal_cliques_template.h +++ b/src/vendor/cigraph/src/cliques/maximal_cliques_template.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2013 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/edge_betweenness.c b/src/vendor/cigraph/src/community/edge_betweenness.c index 67bc2e82acc..622cc705c14 100644 --- a/src/vendor/cigraph/src/community/edge_betweenness.c +++ b/src/vendor/cigraph/src/community/edge_betweenness.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2020 The igraph development team @@ -24,6 +22,7 @@ #include "igraph_community.h" #include "igraph_adjlist.h" +#include "igraph_bitset.h" #include "igraph_components.h" #include "igraph_dqueue.h" #include "igraph_interface.h" @@ -234,7 +233,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 " @@ -316,19 +318,24 @@ igraph_error_t igraph_community_eb_get_merges(const igraph_t *graph, return IGRAPH_SUCCESS; } -/* Find the smallest active element in the vector */ -static igraph_integer_t igraph_i_vector_which_max_not_null(const igraph_vector_t *v, - const bool *passive) { - igraph_integer_t which, i = 0, size = igraph_vector_size(v); - igraph_real_t max; - while (passive[i]) { - i++; - } - which = i; - max = VECTOR(*v)[which]; - for (i++; i < size; i++) { - igraph_real_t elem = VECTOR(*v)[i]; - if (!passive[i] && elem > max) { +/* Find the index i for which v[i] / w[i] is the largest + * and the corresponding element is active (i.e. !passive[i]). + * If w is a null pointer then all w[i] are assumed to be 1, + * and the ranking is done solely based on v. + * + * This function requires that at least one element is active. */ +static igraph_integer_t igraph_i_which_max_active_ratio( + const igraph_vector_t *v, + const igraph_vector_t *w, + igraph_bitset_t *passive) { + + const igraph_integer_t size = igraph_vector_size(v); + igraph_integer_t which = igraph_bitset_countr_one(passive); /* start with first active element */ + igraph_real_t max = VECTOR(*v)[which] / (w ? VECTOR(*w)[which] : 1.0); + + for (igraph_integer_t i = which+1; i < size; i++) { + igraph_real_t elem = VECTOR(*v)[i] / (w ? VECTOR(*w)[i] : 1.0); + if (! IGRAPH_BIT_TEST(*passive, i) && elem > max) { max = elem; which = i; } @@ -342,18 +349,18 @@ static igraph_integer_t igraph_i_vector_which_max_not_null(const igraph_vector_t * \brief Community finding based on edge betweenness. * * Community structure detection based on the betweenness of the edges - * in the network, known as the Grivan-Newman algorithm. + * in the network. This method is also known as the Girvan-Newman + * algorithm. * * - * The idea is that the betweenness of the edges connecting two - * communities is typically high, as many of the shortest paths - * between nodes in separate communities go through them. So we - * gradually remove the edge with highest betweenness from the - * network, and recalculate edge betweenness after every removal. - * This way sooner or later the network splits into two components, - * then after a while one of these components splits again into two smaller - * components, and so on until all edges are removed. This is a divisive - * hierarchical approach, the result of which is a dendrogram. + * The idea behind this method is that the betweenness of the edges connecting + * two communities is typically high, as many of the shortest paths between + * vertices in separate communities pass through them. The algorithm + * successively removes edges with the highest betweenness, recalculating + * betweenness values after each removal. This way eventually the network splits + * into two components, then one of these components splits again, and so on, + * until all edges are removed. The resulting hierarhical partitioning of the + * vertices can be encoded as a dendrogram. * * * In directed graphs, when \p directed is set to true, the directed version @@ -361,22 +368,46 @@ static igraph_integer_t igraph_i_vector_which_max_not_null(const igraph_vector_t * \em weakly connected components are detected. * * - * Reference: + * When edge weights are given, the ratio of betweenness and weight values + * is used to choose which edges to remove first, as described in + * M. E. J. Newman: Analysis of Weighted Networks (2004), Section C. + * Thus, edges with large weights are treated as strong connections, + * and will be removed later than weak connections having similar betweenness. + * Weights are also used for calculating modularity. + * + * + * If lengths are given, they will be considered for shortest path length + * calculations while computing betweenness values. + * + * + * Note: In igraph 0.10, this function interpreted weights in a different, + * erroneous way, and issued a warning when weights were used. Please + * see https://github.com/igraph/igraph/issues/2229 for additional details. * * - * M. Girvan and M. E. J. Newman: - * Community structure in social and biological networks. - * Proc. Nat. Acad. Sci. USA 99, 7821-7826 (2002). + * References: + * + * + * M. Girvan and M. E. J. Newman, + * Community Structure in Social and Biological Networks, PNAS 99, 7821 (2002). * https://doi.org/10.1073/pnas.122653799 * + * + * M. E. J. Newman, + * Analysis of Weighted Networks, Phys. Rev. E 70, 9 (2004). + * https://doi.org/10.1103/PhysRevE.70.056131 + * * \param graph The input graph. - * \param removed_edges Pointer to an initialized vector, the result will be - * stored here, the IDs of the removed edges in the order of their - * removal. It will be resized as needed. It may be \c NULL if + * \param removed_edges Pointer to an initialized integer vector, which will + * be resized as needed. The IDs of the removed edges in the order of their + * removal will be stored here. This vector is suitable as input to + * \ref igraph_community_eb_get_merges(). This parameter may be \c NULL if * the edge IDs are not needed by the caller. * \param edge_betweenness Pointer to an initialized vector or * \c NULL. In the former case the edge betweenness of the removed - * edge is stored here. The vector will be resized as needed. + * edges is stored here. The vector will be resized as needed. + * Note that the betweenness values stored here are \em not divided + * by weights. * \param merges Pointer to an initialized matrix or \c NULL. If not \c NULL * then merges performed by the algorithm are stored here. Even if * this is a divisive algorithm, we can replay it backwards and @@ -397,10 +428,12 @@ static igraph_integer_t igraph_i_vector_which_max_not_null(const igraph_vector_t * betweenness (i.e. directed paths) for directed graphs, and whether * to use the directed version of modularity. It is ignored for undirected * graphs. - * \param weights An optional vector containing edge weights. If null, - * the unweighted edge betweenness scores will be calculated and - * used. If not null, the weighted edge betweenness scores will be - * calculated and used. + * \param weights An optional vector containing edge weights. If not \c NULL, + * the weights will be used to divide the edge betweenness scores, + * as well as for the calculation of modularity. + * \param lengths An optional vector containing edge lengths. If not \c NULL, + * path lengths used in the betweenness calculation will take these + * lengths into account. * \return Error code. * * \sa \ref igraph_community_eb_get_merges(), \ref @@ -419,7 +452,8 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, igraph_vector_t *modularity, igraph_vector_int_t *membership, igraph_bool_t directed, - const igraph_vector_t *weights) { + const igraph_vector_t *weights, + const igraph_vector_t *lengths) { const igraph_integer_t no_of_nodes = igraph_vcount(graph); const igraph_integer_t no_of_edges = igraph_ecount(graph); @@ -436,8 +470,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, igraph_bool_t result_owned = false; igraph_stack_int_t stack; igraph_real_t steps, steps_done; - - bool *passive; + igraph_bitset_t passive; /* Needed only for the unweighted case */ igraph_dqueue_int_t q; @@ -480,9 +513,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, IGRAPH_CHECK_OOM(tmpscore, "Insufficient memory for edge betweenness-based community detection."); IGRAPH_FINALLY(igraph_free, tmpscore); - if (weights == NULL) { - IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100); - } else { + if (weights) { if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERROR("Weight vector length must agree with number of edges.", IGRAPH_EINVAL); } @@ -498,17 +529,25 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, IGRAPH_ERROR("Weights must not be NaN.", IGRAPH_EINVAL); } } + } - if (membership != NULL) { - IGRAPH_WARNING("Membership vector will be selected based on the highest " - "modularity score."); + if (lengths == NULL) { + IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100); + } else { + if (igraph_vector_size(lengths) != no_of_edges) { + IGRAPH_ERROR("Edge length vector size must agree with number of edges.", IGRAPH_EINVAL); } - if (modularity != NULL || membership != NULL) { - IGRAPH_WARNING("Modularity calculation with weighted edge betweenness " - "community detection might not make sense -- modularity treats edge " - "weights as similarities while edge betwenness treats them as " - "distances."); + if (no_of_edges > 0) { + /* Must not call vector_min on empty vector */ + igraph_real_t minlength = igraph_vector_min(lengths); + if (minlength <= 0) { + IGRAPH_ERROR("Edge lengths must be strictly positive.", IGRAPH_EINVAL); + } + + if (isnan(minlength)) { + IGRAPH_ERROR("Edge lengths must not be NaN.", IGRAPH_EINVAL); + } } IGRAPH_CHECK(igraph_2wheap_init(&heap, no_of_nodes)); @@ -528,10 +567,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, } IGRAPH_VECTOR_INIT_FINALLY(&eb, no_of_edges); - - passive = IGRAPH_CALLOC(no_of_edges, bool); - IGRAPH_CHECK_OOM(passive, "Insufficient memory for edge betweenness-based community detection."); - IGRAPH_FINALLY(igraph_free, passive); + IGRAPH_BITSET_INIT_FINALLY(&passive, no_of_edges); /* Estimate the number of steps to be taken. * It is assumed that one iteration is O(|E||V|), but |V| is constant @@ -548,7 +584,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, igraph_vector_null(&eb); - if (weights == NULL) { + if (lengths == NULL) { /* Unweighted variant follows */ /* The following for loop is copied almost intact from @@ -648,7 +684,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, for (igraph_integer_t i = 0; i < neino; i++) { igraph_integer_t edge = VECTOR(*neip)[i]; igraph_integer_t to = IGRAPH_OTHER(graph, edge, minnei); - igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; + igraph_real_t altdist = mindist + VECTOR(*lengths)[edge]; igraph_real_t curdist = distance[to]; igraph_vector_int_t *v; @@ -704,7 +740,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, /* Now look for the smallest edge betweenness */ /* and eliminate that edge from the network */ - maxedge = igraph_i_vector_which_max_not_null(&eb, passive); + maxedge = igraph_i_which_max_active_ratio(&eb, weights, &passive); VECTOR(*removed_edges)[e] = maxedge; if (edge_betweenness) { VECTOR(*edge_betweenness)[e] = VECTOR(eb)[maxedge]; @@ -712,7 +748,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, VECTOR(*edge_betweenness)[e] /= 2.0; } } - passive[maxedge] = true; + IGRAPH_BIT_SET(passive, maxedge); IGRAPH_CHECK(igraph_edge(graph, maxedge, &from, &to)); neip = igraph_inclist_get(elist_in_p, to); @@ -730,12 +766,12 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, IGRAPH_PROGRESS("Edge betweenness community detection: ", 100.0, NULL); - IGRAPH_FREE(passive); + igraph_bitset_destroy(&passive); igraph_vector_destroy(&eb); igraph_stack_int_destroy(&stack); IGRAPH_FINALLY_CLEAN(3); - if (weights == NULL) { + if (lengths == NULL) { igraph_dqueue_int_destroy(&q); IGRAPH_FINALLY_CLEAN(1); } else { diff --git a/src/vendor/cigraph/src/community/fast_modularity.c b/src/vendor/cigraph/src/community/fast_modularity.c index cc3bb750c1e..b4b92ea7346 100644 --- a/src/vendor/cigraph/src/community/fast_modularity.c +++ b/src/vendor/cigraph/src/community/fast_modularity.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -34,24 +33,11 @@ /* #define IGRAPH_FASTCOMM_DEBUG */ -#ifdef _MSC_VER -/* MSVC does not support variadic macros */ -#include -void debug(const char *fmt, ...) { - va_list args; - va_start(args, fmt); -#ifdef IGRAPH_FASTCOMM_DEBUG - vfprintf(stderr, fmt, args); -#endif - va_end(args); -} -#else #ifdef IGRAPH_FASTCOMM_DEBUG #define debug(...) fprintf(stderr, __VA_ARGS__) #else #define debug(...) #endif -#endif /* * Implementation of the community structure algorithm originally published @@ -696,7 +682,7 @@ igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, } else { debug("Calculating degrees\n"); IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_ALL, true)); + IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); for (i = 0; i < no_of_nodes; i++) { VECTOR(a)[i] = VECTOR(degrees)[i]; } @@ -1072,7 +1058,7 @@ igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, no_of_nodes, /*steps=*/ best_no_of_joins, membership, - /*csize=*/ 0)); + /*csize=*/ NULL)); } if (merges == &merges_local) { diff --git a/src/vendor/cigraph/src/community/fluid.c b/src/vendor/cigraph/src/community/fluid.c index 70d13ef68ca..c94800af9d6 100644 --- a/src/vendor/cigraph/src/community/fluid.c +++ b/src/vendor/cigraph/src/community/fluid.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2020 The igraph development team @@ -57,21 +55,30 @@ * * Time complexity: O(|E|) */ -igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, - igraph_integer_t no_of_communities, - igraph_vector_int_t *membership) { - /* Declaration of variables */ - igraph_integer_t no_of_nodes, i, j, k, kv1; +igraph_error_t igraph_community_fluid_communities( + const igraph_t *graph, + igraph_integer_t no_of_communities, + igraph_vector_int_t *membership) { + + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_integer_t i, j, k, kv1; igraph_adjlist_t al; igraph_real_t max_density; igraph_bool_t is_simple, is_connected, running; igraph_vector_t density, label_counters; igraph_vector_int_t dominant_labels, node_order, com_to_numvertices; - /* Initialization of variables needed for initial checking */ - no_of_nodes = igraph_vcount(graph); - /* Checking input values */ + if (igraph_is_directed(graph)) { + IGRAPH_WARNING("Edge directions are ignored by fluid community detection."); + } + IGRAPH_CHECK(igraph_is_simple(graph, &is_simple, IGRAPH_UNDIRECTED)); + if (!is_simple) { + IGRAPH_ERROR("Fluid community detection supports only simple graphs.", IGRAPH_EINVAL); + } + + /* This must come before the connectedness check so we can support the null + * graph (considered disconnected) for purposes of convenience. */ if (no_of_nodes < 2) { if (membership) { IGRAPH_CHECK(igraph_vector_int_resize(membership, no_of_nodes)); @@ -79,33 +86,20 @@ igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, } return IGRAPH_SUCCESS; } + if (no_of_communities < 1) { - IGRAPH_ERROR("Number of requested communities must be greater than zero.", IGRAPH_EINVAL); + IGRAPH_ERROR("Number of requested communities must be positive.", IGRAPH_EINVAL); } + if (no_of_communities > no_of_nodes) { IGRAPH_ERROR("Number of requested communities must not be greater than the number of nodes.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_is_simple(graph, &is_simple)); - if (!is_simple) { - IGRAPH_ERROR("Fluid community detection supports only simple graphs.", IGRAPH_EINVAL); - } - if (igraph_is_directed(graph)) { - /* When the graph is directed, mutual edges are effectively multi-edges as we - * are ignoring edge directions. */ - igraph_bool_t has_mutual; - IGRAPH_CHECK(igraph_has_mutual(graph, &has_mutual, false)); - if (has_mutual) { - IGRAPH_ERROR("Fluid community detection supports only simple graphs.", IGRAPH_EINVAL); - } - } + IGRAPH_CHECK(igraph_is_connected(graph, &is_connected, IGRAPH_WEAK)); if (!is_connected) { IGRAPH_ERROR("Fluid community detection supports only connected graphs.", IGRAPH_EINVAL); } - if (igraph_is_directed(graph)) { - IGRAPH_WARNING("Edge directions are ignored by fluid community detection."); - } /* Internal variables initialization */ max_density = 1.0; @@ -129,7 +123,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*/ @@ -148,8 +142,6 @@ igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_init(&label_counters, no_of_communities)); IGRAPH_FINALLY(igraph_vector_destroy, &label_counters); - RNG_BEGIN(); - /* running is the convergence boolean variable */ running = true; while (running) { @@ -162,7 +154,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 */ @@ -236,8 +228,6 @@ igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, } } - RNG_END(); - /* Shift back the membership vector */ /* There must be no 0 labels in membership vector at this point */ for (i = 0; i < no_of_nodes; i++) { @@ -246,14 +236,12 @@ igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, } igraph_adjlist_destroy(&al); - IGRAPH_FINALLY_CLEAN(1); - igraph_vector_int_destroy(&node_order); igraph_vector_destroy(&density); igraph_vector_int_destroy(&com_to_numvertices); igraph_vector_destroy(&label_counters); igraph_vector_int_destroy(&dominant_labels); - IGRAPH_FINALLY_CLEAN(5); + IGRAPH_FINALLY_CLEAN(6); return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/community/infomap.cpp b/src/vendor/cigraph/src/community/infomap.cpp new file mode 100644 index 00000000000..31d8370dc1e --- /dev/null +++ b/src/vendor/cigraph/src/community/infomap.cpp @@ -0,0 +1,258 @@ +/* + IGraph library. + Copyright (C) 2011-2025 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 . +*/ + +#include "igraph_community.h" + +#include "igraph_error.h" +#include "igraph_interface.h" +#include "igraph_interrupt.h" + +#include "core/exceptions.h" + +#include "config.h" + +#ifdef HAVE_INFOMAP + #include "Infomap.h" +#endif + +#include +#include + +static igraph_error_t infomap_get_membership(infomap::InfomapBase &infomap, igraph_vector_int_t *membership) { + igraph_integer_t n = infomap.numLeafNodes(); + + IGRAPH_CHECK(igraph_vector_int_resize(membership, n)); + + for (auto it(infomap.iterTreePhysical(1)); !it.isEnd(); ++it) { + infomap::InfoNode &node = *it; + if (node.isLeaf()) { + // Note: We must use moduleIndex() and not moduleId(), as the latter + // may be >= vcount, which causes igraph_reindex_membership() to fail. + VECTOR(*membership)[node.physicalId] = it.moduleIndex(); + } + } + + // Re-index membership + IGRAPH_CHECK(igraph_reindex_membership(membership, NULL, NULL)); + + return IGRAPH_SUCCESS; +} + +static igraph_error_t convert_igraph_to_infomap(const igraph_t *graph, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_weights, + infomap::Network &network) { + + igraph_integer_t vcount = igraph_vcount(graph); + igraph_integer_t ecount = igraph_ecount(graph); + + if (vcount > UINT_MAX) { + IGRAPH_ERROR("Graph has too many vertices for Infomap.", IGRAPH_EINVAL); + } + + for (igraph_integer_t v = 0; v < vcount; v++) { + if (vertex_weights) { + double weight = VECTOR(*vertex_weights)[v]; + if (weight < 0) { + IGRAPH_ERRORF("Vertex weights must not be negative, got %g.", + IGRAPH_EINVAL, weight); + } + if (! std::isfinite(weight)) { + IGRAPH_ERRORF("Vertex weights must not be infinite or NaN, got %g.", + IGRAPH_EINVAL, weight); + } + network.addNode(v, weight); + } else { + network.addNode(v); + } + } + + for (igraph_integer_t e = 0; e < ecount; e++) { + igraph_integer_t v1 = IGRAPH_FROM(graph, e); + igraph_integer_t v2 = IGRAPH_TO(graph, e); + + if (edge_weights) { + double weight = VECTOR(*edge_weights)[e]; + if (weight < 0) { + IGRAPH_ERRORF("Edge weights must not be negative, got %g.", + IGRAPH_EINVAL, weight); + } + if (! std::isfinite(weight)) { + IGRAPH_ERRORF("Edge weights must not be infinite or NaN, got %g.", + IGRAPH_EINVAL, weight); + } + network.addLink(v1, v2, weight); + } else { + network.addLink(v1, v2); + } + } + + return IGRAPH_SUCCESS; +} + +// Needed in case C++'s bool is not compatible with igraph's igraph_bool_t +// which may happen in some configurations on some platforms, notable with R/igraph. +static bool infomap_allow_interruption() { + return igraph_allow_interruption(); +} + +/** + * \function igraph_community_infomap + * \brief Community structure that minimizes the expected description length of a random walker trajectory. + * + * Implementation of the Infomap community detection algorithm of + * Martin Rosvall and Carl T. Bergstrom. This algorithm takes edge directions + * into account. For more details, see the visualization of the math and the + * map generator at https://www.mapequation.org. + * + * + * Infomap is based on a random walker model similar to PageRank: the walker + * either chooses out-edges to follow with probabilities proportional to edge + * weights, or teleports to a random vertex with probability 0.15. Vertex weights + * can be given to control the probability of choosing different vertices as + * the target of the teleportation. + * + * + * As of igraph 1.0, the Infomap library written by Daniel Edler, Anton Holmgren + * and Martin Rosvall is used. See https://github.com/mapequation/infomap/. + * + * + * If you want to specify a random seed (as in the original + * implementation) you can use \ref igraph_rng_seed(). + * + * + * References: + * + * + * M. Rosvall and C. T. Bergstrom: + * Maps of information flow reveal community structure in complex networks, + * PNAS 105, 1118 (2008). + * https://dx.doi.org/10.1073/pnas.0706851105, https://arxiv.org/abs/0707.0609 + * + * + * M. Rosvall, D. Axelsson, and C. T. Bergstrom: + * The map equation, + * Eur. Phys. J. Special Topics 178, 13 (2009). + * https://dx.doi.org/10.1140/epjst/e2010-01179-1, https://arxiv.org/abs/0906.1405 + * + * \param graph The input graph. Edge directions are taken into account. + * \param edge_weights Numeric vector giving the weights of the edges. + * The random walker will favour edges with high weights over + * edges with low weights; the probability of picking a particular + * outbound edge from a node is directly proportional to its weight. + * If it is \c NULL then all edges will have equal + * weights. The weights are expected to be non-negative. + * \param vertex_weights Numeric vector giving the weights of the vertices. + * Vertices with higher weights are favoured by the random walker + * when it teleports to a new vertex. The probability of picking a vertex + * when the random walker teleports is directly proportional to the weight + * of the vertex. If this argument is \c NULL then all vertices will have + * equal weights. Weights are expected to be positive. + * \param nb_trials The number of attempts to partition the network + * (can be any integer value equal to or larger than 1). + * \param membership Pointer to a vector. The membership vector is + * stored here. \c NULL means that the caller is not interested in the + * membership vector. + * \param codelength Pointer to a real. If not \c NULL the code length of the + * partition is stored here. + * \return Error code. + * + * \sa \ref igraph_community_spinglass(), \ref + * igraph_community_edge_betweenness(), \ref igraph_community_walktrap(). + * + * Time complexity: TODO. + */ + +igraph_error_t igraph_community_infomap( + const igraph_t *graph, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_weights, + igraph_integer_t nb_trials, + igraph_vector_int_t *membership, + igraph_real_t *codelength) { + +#ifndef HAVE_INFOMAP + IGRAPH_ERROR("Infomap is not available.", IGRAPH_UNIMPLEMENTED); +#else + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_integer_t ecount = igraph_ecount(graph); + + if (edge_weights) { + if (igraph_vector_size(edge_weights) != ecount) { + IGRAPH_ERROR("Length of edge weight vector does not match edge count.", + IGRAPH_EINVAL); + } + } + + if (vertex_weights) { + if (igraph_vector_size(vertex_weights) != vcount) { + IGRAPH_ERROR("Length of vertex weight vector does not match edge count.", + IGRAPH_EINVAL); + } + } + + if (nb_trials < 1) { + IGRAPH_ERRORF("Number of trials must be at least 1, got %" IGRAPH_PRId ".", + IGRAPH_EINVAL, + nb_trials); + } + + // Handle null graph + if (vcount == 0) { + if (membership) { + IGRAPH_CHECK(igraph_vector_int_resize(membership, 0)); + } + + if (codelength) { + *codelength = IGRAPH_NAN; + } + + return IGRAPH_SUCCESS; + } + + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; + + // Configure infomap + infomap::Config conf; + conf.twoLevel = true; + conf.numTrials = nb_trials; + conf.silent = true; + conf.directed = igraph_is_directed(graph); + conf.interruptionHandler = &infomap_allow_interruption; + + infomap::InfomapBase infomap(conf); + + IGRAPH_CHECK(convert_igraph_to_infomap(graph, edge_weights, vertex_weights, infomap.network())); + + infomap.run(); + + if (membership) { + IGRAPH_CHECK(infomap_get_membership(infomap, membership)); + } + + if (codelength) { + *codelength = infomap.codelength(); + } + + IGRAPH_HANDLE_EXCEPTIONS_END; + + return IGRAPH_SUCCESS; + +#endif +} diff --git a/src/vendor/cigraph/src/community/infomap/infomap.cc b/src/vendor/cigraph/src/community/infomap/infomap.cc deleted file mode 100644 index 88bb2ac2ca7..00000000000 --- a/src/vendor/cigraph/src/community/infomap/infomap.cc +++ /dev/null @@ -1,323 +0,0 @@ -/* -*- mode: C -*- */ -/* - IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - - ---- - The original version of this file was written by Martin Rosvall - email: martin.rosvall@physics.umu.se - homePage: http://www.tp.umu.se/~rosvall/ - - It was integrated in igraph by Emmanuel Navarro - email: navarro@irit.fr - homePage: http://www.irit.fr/~Emmanuel.Navarro/ -*/ - -#include "igraph_community.h" - -#include "core/exceptions.h" -#include "core/interruption.h" - -#include "infomap_Node.h" -#include "infomap_FlowGraph.h" -#include "infomap_Greedy.h" - -#include -#include - -// This is necessary for GCC 5 and earlier, where including -// makes isnan() unusable without the std:: prefix, even if -// was included as well. -using std::isnan; - -/****************************************************************************/ -static igraph_error_t infomap_partition(FlowGraph &fgraph, bool rcall) { - - // save the original graph - FlowGraph cpy_fgraph(fgraph); - - igraph_integer_t Nnode = cpy_fgraph.Nnode; - // "real" number of vertex, ie. number of vertex of the graph - - igraph_integer_t iteration = 0; - double outer_oldCodeLength, newCodeLength; - - std::vector initial_move; - bool initial_move_done = true; - - // re-use vector in loop for better performance - std::vector subMoveTo; - - do { // Main loop - outer_oldCodeLength = fgraph.codeLength; - - if (iteration > 0) { - /**********************************************************************/ - // FIRST PART: re-split the network (if need) - // =========================================== - - // intial_move indicate current clustering - initial_move.resize(Nnode); - // new_cluster_id --> old_cluster_id (save curent clustering state) - - initial_move_done = false; - - subMoveTo.clear(); // enventual new partitionment of original graph - - if ((iteration % 2 == 0) && (fgraph.Nnode > 1)) { - // 0/ Submodule movements : partition each module of the - // current partition (rec. call) - - subMoveTo.resize(Nnode); - // vid_cpy_fgraph --> new_cluster_id (new partition) - - igraph_integer_t subModIndex = 0; - - for (igraph_integer_t i = 0 ; i < fgraph.Nnode ; i++) { - // partition each non trivial module - size_t sub_Nnode = fgraph.node[i].members.size(); - if (sub_Nnode > 1) { // If the module is not trivial - const std::vector &sub_members = fgraph.node[i].members; - - // extraction of the subgraph - FlowGraph sub_fgraph(cpy_fgraph, sub_members); - sub_fgraph.initiate(); - - // recursif call of partitionment on the subgraph - infomap_partition(sub_fgraph, true); - - // Record membership changes - for (igraph_integer_t j = 0; j < sub_fgraph.Nnode; j++) { - for (const auto &v : sub_fgraph.node[j].members) { - subMoveTo[sub_members[v]] = subModIndex; - } - initial_move[subModIndex] = i; - subModIndex++; - } - } else { - subMoveTo[fgraph.node[i].members[0]] = subModIndex; - initial_move[subModIndex] = i; - subModIndex++; - } - } - } else { - // 1/ Single-node movements : allows each node to move (again) - // save current modules - for (igraph_integer_t i = 0; i < fgraph.Nnode; i++) { // for each module - for (const auto &v : fgraph.node[i].members) { // for each vertex (of the module) - initial_move[v] = i; - } - } - } - - fgraph.back_to(cpy_fgraph); - if (! subMoveTo.empty()) { - Greedy cpy_greedy(&fgraph); - - cpy_greedy.setMove(subMoveTo); - cpy_greedy.apply(false); - } - } - /**********************************************************************/ - // SECOND PART: greedy optimizing it self - // =========================================== - double oldCodeLength; - - do { - // greedy optimizing object creation - Greedy greedy(&fgraph); - - // Initial move to apply ? - if (!initial_move_done && ! initial_move.empty()) { - initial_move_done = true; - greedy.setMove(initial_move); - } - - oldCodeLength = greedy.codeLength; - bool moved = true; - double inner_oldCodeLength = 1000; - - while (moved) { // main greedy optimizing loop - inner_oldCodeLength = greedy.codeLength; - moved = greedy.optimize(); - - if (fabs(greedy.codeLength - inner_oldCodeLength) < 1.0e-10) - // if the move does'n reduce the codelenght -> exit ! - { - moved = false; - } - } - - // transform the network to network of modules: - greedy.apply(true); - newCodeLength = greedy.codeLength; - } while (oldCodeLength - newCodeLength > 1.0e-10); - // while there is some improvement - - iteration++; - if (!rcall) { - IGRAPH_ALLOW_INTERRUPTION(); - } - } while (outer_oldCodeLength - newCodeLength > 1.0e-10); - - return IGRAPH_SUCCESS; -} - - -/** - * \function igraph_community_infomap - * \brief Find community structure that minimizes the expected description length of a random walker trajectory. - * - * Implementation of the Infomap community detection algorithm of - * Martin Rosvall and Carl T. Bergstrom. This algorithm takes edge directions - * into account. - * - * - * For more details, see the visualization of the math and the map generator - * at https://www.mapequation.org . The original paper describing the algorithm - * is: M. Rosvall and C. T. Bergstrom, Maps of information flow reveal community - * structure in complex networks, PNAS 105, 1118 (2008) - * (https://dx.doi.org/10.1073/pnas.0706851105, https://arxiv.org/abs/0707.0609). - * A more detailed paper about the algorithm is: M. Rosvall, D. Axelsson, and - * C. T. Bergstrom, The map equation, Eur. Phys. J. Special Topics 178, 13 (2009). - * (https://dx.doi.org/10.1140/epjst/e2010-01179-1, https://arxiv.org/abs/0906.1405) - - * - * The original C++ implementation of Martin Rosvall is used, - * see http://www.tp.umu.se/~rosvall/downloads/infomap_undir.tgz . - * Integration in igraph was done by Emmanuel Navarro (who is grateful to - * Martin Rosvall and Carl T. Bergstrom for providing this source code). - * - * - * Note that the graph must not contain isolated vertices. - * - * - * If you want to specify a random seed (as in the original - * implementation) you can use \ref igraph_rng_seed(). - * - * \param graph The input graph. Edge directions are taken into account. - * \param e_weights Numeric vector giving the weights of the edges. - * The random walker will favour edges with high weights over - * edges with low weights; the probability of picking a particular - * outbound edge from a node is directly proportional to its weight. - * If it is \c NULL then all edges will have equal - * weights. The weights are expected to be non-negative. - * \param v_weights Numeric vector giving the weights of the vertices. - * Vertices with higher weights are favoured by the random walker - * when it needs to "teleport" to a new node after getting stuck in - * a sink node (i.e. a node with no outbound edges). The probability - * of picking a vertex when the random walker teleports is directly - * proportional to the weight of the vertex. If this argument is \c NULL - * then all vertices will have equal weights. Weights are expected - * to be positive. - * \param nb_trials The number of attempts to partition the network - * (can be any integer value equal or larger than 1). - * \param membership Pointer to a vector. The membership vector is - * stored here. - * \param codelength Pointer to a real. If not NULL the code length of the - * partition is stored here. - * \return Error code. - * - * \sa \ref igraph_community_spinglass(), \ref - * igraph_community_edge_betweenness(), \ref igraph_community_walktrap(). - * - * Time complexity: TODO. - */ -igraph_error_t igraph_community_infomap(const igraph_t * graph, - const igraph_vector_t *e_weights, - const igraph_vector_t *v_weights, - igraph_integer_t nb_trials, - igraph_vector_int_t *membership, - igraph_real_t *codelength) { - - IGRAPH_HANDLE_EXCEPTIONS_BEGIN; - - if (e_weights) { - const igraph_integer_t ecount = igraph_ecount(graph); - if (igraph_vector_size(e_weights) != ecount) { - IGRAPH_ERROR("Invalid edge weight vector length.", IGRAPH_EINVAL); - } - if (ecount > 0) { - /* Allow both positive and zero weights. - * The conversion to Infomap format will simply skip zero-weight edges/ */ - igraph_real_t minweight = igraph_vector_min(e_weights); - if (minweight < 0) { - IGRAPH_ERROR("Edge weights must not be negative.", IGRAPH_EINVAL); - } else if (isnan(minweight)) { - IGRAPH_ERROR("Edge weights must not be NaN values.", IGRAPH_EINVAL); - } - } - } - - if (v_weights) { - const igraph_integer_t vcount = igraph_vcount(graph); - if (igraph_vector_size(v_weights) != vcount) { - IGRAPH_ERROR("Invalid vertex weight vector length.", IGRAPH_EINVAL); - } - if (vcount > 0) { - /* TODO: Currently we require strictly positive. Can this be - * relaxed to non-negative values? */ - igraph_real_t minweight = igraph_vector_min(v_weights); - if (minweight <= 0) { - IGRAPH_ERROR("Vertex weights must be positive.", IGRAPH_EINVAL); - } else if (isnan(minweight)) { - IGRAPH_ERROR("Vertex weights must not be NaN values.", IGRAPH_EINVAL); - } - } - } - - FlowGraph fgraph(graph, e_weights, v_weights); - - // compute stationary distribution - fgraph.initiate(); - - double shortestCodeLength = 1000.0; - - // create membership vector - igraph_integer_t Nnode = fgraph.Nnode; - IGRAPH_CHECK(igraph_vector_int_resize(membership, Nnode)); - - for (igraph_integer_t trial = 0; trial < nb_trials; trial++) { - FlowGraph cpy_fgraph(fgraph); - - //partition the network - IGRAPH_CHECK(infomap_partition(cpy_fgraph, false)); - - // if better than the better... - if (cpy_fgraph.codeLength < shortestCodeLength) { - shortestCodeLength = cpy_fgraph.codeLength; - // ... store the partition - for (igraph_integer_t i = 0 ; i < cpy_fgraph.Nnode ; i++) { - size_t Nmembers = cpy_fgraph.node[i].members.size(); - for (size_t k = 0; k < Nmembers; k++) { - //cluster[ cpy_fgraph->node[i].members[k] ] = i; - VECTOR(*membership)[cpy_fgraph.node[i].members[k]] = i; - } - } - } - } - - *codelength = shortestCodeLength / log(2.0); - - IGRAPH_CHECK(igraph_reindex_membership(membership, NULL, NULL)); - - return IGRAPH_SUCCESS; - - IGRAPH_HANDLE_EXCEPTIONS_END; -} diff --git a/src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.cc b/src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.cc deleted file mode 100644 index 405dc6a1da0..00000000000 --- a/src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.cc +++ /dev/null @@ -1,382 +0,0 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ -/* - IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#include "infomap_FlowGraph.h" - -using namespace std; - -void FlowGraph::init(igraph_integer_t n, const igraph_vector_t *v_weights) { - alpha = 0.15; - beta = 1.0 - alpha; - Nnode = n; - node.reserve(Nnode); - if (v_weights) { - for (igraph_integer_t i = 0; i < Nnode; i++) { - node.emplace_back(i, VECTOR(*v_weights)[i]); - } - } else { - for (igraph_integer_t i = 0; i < Nnode; i++) { - node.emplace_back(i, 1.0); - } - } -} - -FlowGraph::FlowGraph(igraph_integer_t n) { - init(n, nullptr); -} - -/* Build the graph from igraph_t object */ -FlowGraph::FlowGraph(const igraph_t *graph, - const igraph_vector_t *e_weights, - const igraph_vector_t *v_weights) { - - igraph_integer_t n = igraph_vcount(graph); - init(n, v_weights); - - bool directed = igraph_is_directed(graph); - - double linkWeight = 1.0; - igraph_integer_t from, to; - - igraph_integer_t Nlinks = igraph_ecount(graph); - if (!directed) { - Nlinks = Nlinks * 2 ; - } - for (igraph_integer_t i = 0; i < Nlinks; i++) { - if (!directed) { // not directed - if (i % 2 == 0) { - linkWeight = e_weights ? VECTOR(*e_weights)[i / 2] : 1.0; - igraph_edge(graph, i / 2, &from, &to); - } else { - igraph_edge(graph, (i - 1) / 2, &to, &from); - } - } else { // directed - linkWeight = e_weights ? VECTOR(*e_weights)[i] : 1.0; - igraph_edge(graph, i, &from, &to); - } - - // Populate node from igraph_graph - // Negative edge weights were checked for already. - // We skip adding zero-weight edges. - if (linkWeight > 0.0) { - if (from != to) { - node[from].outLinks.emplace_back(to, linkWeight); - node[to].inLinks.emplace_back(from, linkWeight); - } - } - } -} - -FlowGraph::FlowGraph(const FlowGraph &fgraph) { - igraph_integer_t n = fgraph.Nnode; - init(n, nullptr); - for (igraph_integer_t i = 0; i < n; i++) { - node[i] = fgraph.node[i]; - } - - //XXX: quid de danglings et Ndanglings? - - alpha = fgraph.alpha ; - beta = fgraph.beta ; - - exit = fgraph.exit; - exitFlow = fgraph.exitFlow; - exit_log_exit = fgraph.exit_log_exit; - size_log_size = fgraph.size_log_size ; - nodeSize_log_nodeSize = fgraph.nodeSize_log_nodeSize; - - codeLength = fgraph.codeLength; -} - -/** construct a graph by extracting a subgraph from the given graph - */ -FlowGraph::FlowGraph(const FlowGraph &fgraph, const vector &sub_members) { - igraph_integer_t sub_Nnode = sub_members.size(); - - init(sub_Nnode, nullptr); - - //XXX: use set of integer to ensure that elements are sorted - set sub_mem(sub_members.begin(), sub_members.end()); - - auto it_mem = sub_mem.begin(); - - vector sub_renumber(fgraph.Nnode, -1); - // id --> sub_id - - for (igraph_integer_t j = 0; j < sub_Nnode; j++) { - igraph_integer_t orig_nr = (*it_mem); - - node[j].teleportWeight = fgraph.node[orig_nr].teleportWeight; - node[j].selfLink = fgraph.node[orig_nr].selfLink; - // Take care of self-link - - size_t orig_NoutLinks = fgraph.node[orig_nr].outLinks.size(); - size_t orig_NinLinks = fgraph.node[orig_nr].inLinks.size(); - - sub_renumber[orig_nr] = j; - - for (size_t k = 0; k < orig_NoutLinks; k++) { - igraph_integer_t to = fgraph.node[orig_nr].outLinks[k].first; - igraph_integer_t to_newnr = sub_renumber[to]; - double link_weight = fgraph.node[orig_nr].outLinks[k].second; - - if (to < orig_nr) { - // we add links if the destination (to) has already be seen - // (ie. smaller than current id) => orig - - if (sub_mem.find(to) != sub_mem.end()) { - // printf("%2d | %4d to %4d\n", j, orig_nr, to); - // printf("from %4d (%4d:%1.5f) to %4d (%4d)\n", j, orig_nr, - // node[j].selfLink, to_newnr, to); - node[j].outLinks.emplace_back(to_newnr, link_weight); - node[to_newnr].inLinks.emplace_back(j, link_weight); - } - } - } - - for (size_t k = 0; k < orig_NinLinks; k++) { - igraph_integer_t to = fgraph.node[orig_nr].inLinks[k].first; - igraph_integer_t to_newnr = sub_renumber[to]; - double link_weight = fgraph.node[orig_nr].inLinks[k].second; - if (to < orig_nr) { - if (sub_mem.find(to) != sub_mem.end()) { - node[j].inLinks.emplace_back(to_newnr, link_weight); - node[to_newnr].outLinks.emplace_back(j, link_weight); - } - } - } - it_mem++; - } -} - - -/** Swap the graph with the one given - the graph is "re" calibrate - but NOT the given one. - */ -void FlowGraph::swap(FlowGraph &fgraph) noexcept { - node.swap(fgraph.node); - - igraph_integer_t Nnode_tmp = fgraph.Nnode; - fgraph.Nnode = Nnode; - Nnode = Nnode_tmp; - - calibrate(); -} - -/** Initialisation of the graph, compute the flow inside the graph - * - count danglings nodes - * - normalized edge weights - * - Call eigenvector() to compute steady state distribution - * - call calibrate to compute codelenght - */ -void FlowGraph::initiate() { - // Take care of dangling nodes, normalize outLinks, and calculate - // total teleport weight - Ndanglings = 0; - double totTeleportWeight = 0.0; - for (igraph_integer_t i = 0; i < Nnode; i++) { - totTeleportWeight += node[i].teleportWeight; - } - - for (igraph_integer_t i = 0; i < Nnode; i++) { - node[i].teleportWeight /= totTeleportWeight; - // normalize teleportation weight - - if (node[i].outLinks.empty() && (node[i].selfLink <= 0.0)) { - danglings.push_back(i); - Ndanglings++; - } else { // Normalize the weights - size_t NoutLinks = node[i].outLinks.size(); - double sum = node[i].selfLink; // Take care of self-links - for (size_t j = 0; j < NoutLinks; j++) { - sum += node[i].outLinks[j].second; - } - node[i].selfLink /= sum; - for (size_t j = 0; j < NoutLinks; j++) { - node[i].outLinks[j].second /= sum; - } - } - } - - // Calculate steady state matrix - eigenvector(); - - // Update links to represent flow - for (igraph_integer_t i = 0; i < Nnode; i++) { - node[i].selfLink = beta * node[i].size * node[i].selfLink; - // (1 - \tau) * \pi_i * P_{ii} - - if (!node[i].outLinks.empty()) { - size_t NoutLinks = node[i].outLinks.size(); - for (size_t j = 0; j < NoutLinks; j++) { - node[i].outLinks[j].second = beta * node[i].size * - node[i].outLinks[j].second; - // (1 - \tau) * \pi_i * P_{ij} - } - - // Update values for corresponding inlink - for (size_t j = 0; j < NoutLinks; j++) { - size_t NinLinks = node[node[i].outLinks[j].first].inLinks.size(); - for (size_t k = 0; k < NinLinks; k++) { - if (node[node[i].outLinks[j].first].inLinks[k].first == i) { - node[node[i].outLinks[j].first].inLinks[k].second = - node[i].outLinks[j].second; - k = NinLinks; - } - } - } - } - } - - // To be able to handle dangling nodes efficiently - for (igraph_integer_t i = 0; i < Nnode; i++) - if (node[i].outLinks.empty() && (node[i].selfLink <= 0.0)) { - node[i].danglingSize = node[i].size; - } else { - node[i].danglingSize = 0.0; - } - - nodeSize_log_nodeSize = 0.0 ; - // The exit flow from each node at initiation - for (igraph_integer_t i = 0; i < Nnode; i++) { - node[i].exit = node[i].size // Proba to be on i - - (alpha * node[i].size + beta * node[i].danglingSize) * - node[i].teleportWeight // Proba teleport back to i - - node[i].selfLink; // Proba stay on i - - // node[i].exit == q_{i\exit} - nodeSize_log_nodeSize += plogp(node[i].size); - } - - calibrate(); -} - - -/* Compute steady state distribution (ie. PageRank) over the network - * (for all i update node[i].size) - */ -void FlowGraph::eigenvector() { - vector size_tmp(Nnode, 1.0 / Nnode); - - int Niterations = 0; - double danglingSize; - - double sqdiff = 1.0; - double sqdiff_old; - double sum; - do { - // Calculate dangling size - danglingSize = 0.0; - for (igraph_integer_t i = 0; i < Ndanglings; i++) { - danglingSize += size_tmp[danglings[i]]; - } - - // Flow from teleportation - for (igraph_integer_t i = 0; i < Nnode; i++) { - node[i].size = (alpha + beta * danglingSize) * node[i].teleportWeight; - } - - // Flow from network steps - for (igraph_integer_t i = 0; i < Nnode; i++) { - node[i].size += beta * node[i].selfLink * size_tmp[i]; - size_t Nlinks = node[i].outLinks.size(); - for (size_t j = 0; j < Nlinks; j++) - node[node[i].outLinks[j].first].size += beta * - node[i].outLinks[j].second * size_tmp[i]; - } - - // Normalize - sum = 0.0; - for (igraph_integer_t i = 0; i < Nnode; i++) { - sum += node[i].size; - } - sqdiff_old = sqdiff; - sqdiff = 0.0; - for (igraph_integer_t i = 0; i < Nnode; i++) { - node[i].size /= sum; - sqdiff += fabs(node[i].size - size_tmp[i]); - size_tmp[i] = node[i].size; - } - Niterations++; - - if (sqdiff == sqdiff_old) { - alpha += 1.0e-10; - beta = 1.0 - alpha; - } - - } while ((Niterations < 200) && (sqdiff > 1.0e-15 || Niterations < 50)); - - danglingSize = 0.0; - for (igraph_integer_t i = 0; i < Ndanglings; i++) { - danglingSize += size_tmp[danglings[i]]; - } - // cout << "done! (the error is " << sqdiff << " after " << Niterations - // << " iterations)" << endl; -} - - -/* Compute the codeLength of the given network - * note: (in **node, one node == one module) - */ -void FlowGraph::calibrate() noexcept { - exit_log_exit = 0.0; - exitFlow = 0.0; - size_log_size = 0.0; - - for (igraph_integer_t i = 0; i < Nnode; i++) { // For each module - // own node/module codebook - size_log_size += plogp(node[i].exit + node[i].size); - - // use of index codebook - exitFlow += node[i].exit; - exit_log_exit += plogp(node[i].exit); - } - - exit = plogp(exitFlow); - - codeLength = exit - 2.0 * exit_log_exit + size_log_size - - nodeSize_log_nodeSize; -} - - -/* Restore the data from the given FlowGraph object - */ -void FlowGraph::back_to(const FlowGraph &fgraph) { - // delete current nodes and copy original ones - Nnode = fgraph.Nnode; - node = fgraph.node; - - // restore atributs - alpha = fgraph.alpha ; - beta = fgraph.beta ; - - exit = fgraph.exit; - exitFlow = fgraph.exitFlow; - exit_log_exit = fgraph.exit_log_exit; - size_log_size = fgraph.size_log_size ; - nodeSize_log_nodeSize = fgraph.nodeSize_log_nodeSize; - - codeLength = fgraph.codeLength; -} diff --git a/src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.h b/src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.h deleted file mode 100644 index 6364d5d0ce6..00000000000 --- a/src/vendor/cigraph/src/community/infomap/infomap_FlowGraph.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ -/* - IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#ifndef INFOMAP_FLOWGRAPH_H -#define INFOMAP_FLOWGRAPH_H - -#include "infomap_Node.h" - -#include "igraph_datatype.h" -#include "igraph_types.h" -#include "igraph_vector.h" - -#include -#include -#include - -inline double plogp(double x) { - return x > 0.0 ? x*std::log(x) : 0.0; -} - -class FlowGraph { -private: - void init(igraph_integer_t n, const igraph_vector_t *nodeWeights); - -public: - explicit FlowGraph(igraph_integer_t n); - - FlowGraph(const FlowGraph &fgraph); - FlowGraph(const FlowGraph &fgraph, const std::vector &sub_members); - - FlowGraph(const igraph_t *graph, const igraph_vector_t *e_weights, - const igraph_vector_t *v_weights); - - void swap(FlowGraph &fgraph) noexcept; - - void initiate(); - void eigenvector(); - void calibrate() noexcept; - - void back_to(const FlowGraph &fgraph); - - /*************************************************************************/ - std::vector node; - igraph_integer_t Nnode; - - double alpha, beta; - - igraph_integer_t Ndanglings; - std::vector danglings; // id of dangling nodes - - double exit; // - double exitFlow; // - double exit_log_exit; // - double size_log_size; // - double nodeSize_log_nodeSize; // \sum_{v in V} p log(p) - - double codeLength; -}; - -#endif // INFOMAP_FLOWGRAPH_H diff --git a/src/vendor/cigraph/src/community/infomap/infomap_Greedy.cc b/src/vendor/cigraph/src/community/infomap/infomap_Greedy.cc deleted file mode 100644 index 954e9169717..00000000000 --- a/src/vendor/cigraph/src/community/infomap/infomap_Greedy.cc +++ /dev/null @@ -1,522 +0,0 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ -/* - IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#include "infomap_Greedy.h" - -#include -#include -#include - -using namespace std; - -Greedy::Greedy(FlowGraph *fgraph) : - graph(fgraph), - Nnode(graph->Nnode), - alpha(graph->alpha), // teleportation probability - beta(1.0 - alpha), // probability to take normal step - - node_index(Nnode), - - mod_empty(Nnode), - mod_exit(Nnode), - mod_size(Nnode), - mod_danglingSize(Nnode), - mod_teleportWeight(Nnode), - mod_members(Nnode) -{ - nodeSize_log_nodeSize = graph->nodeSize_log_nodeSize; - exit_log_exit = graph->exit_log_exit; - size_log_size = graph->size_log_size; - exitFlow = graph->exitFlow; - - const std::vector &node = graph->node; - for (igraph_integer_t i = 0; i < Nnode; i++) { // For each module - node_index[i] = i; - mod_exit[i] = node[i].exit; - mod_size[i] = node[i].size; - - mod_danglingSize[i] = node[i].danglingSize; - mod_teleportWeight[i] = node[i].teleportWeight; - mod_members[i] = node[i].members.size(); - } - - exit = plogp(exitFlow); - - codeLength = exit - 2.0 * exit_log_exit + size_log_size - nodeSize_log_nodeSize; -} - - -/** Greedy optimizing (as in Blodel and Al.) : - * for each vertex (selected in a random order) compute the best possible move within neighborhood - */ -bool Greedy::optimize() { - bool moved = false; - const std::vector &node = graph->node; - - RNG_BEGIN(); - - // Generate random enumeration of nodes - vector randomOrder(Nnode); - for (igraph_integer_t i = 0; i < Nnode; i++) { - randomOrder[i] = i; - } - - for (igraph_integer_t i = 0; i < Nnode - 1; i++) { - igraph_integer_t randPos = RNG_INTEGER(i, Nnode - 1); - // swap i & randPos - igraph_integer_t tmp = randomOrder[i]; - randomOrder[i] = randomOrder[randPos]; - randomOrder[randPos] = tmp; - } - - igraph_uint_t offset = 1; - vector redirect(Nnode, 0); - vector > > flowNtoM(Nnode); - - for (igraph_integer_t k = 0; k < Nnode; k++) { - - // Pick nodes in random order - igraph_integer_t flip = randomOrder[k]; - igraph_integer_t oldM = node_index[flip]; - - // Reset offset when igraph_integer_t overflows - if (offset > IGRAPH_INTEGER_MAX) { - for (igraph_integer_t j = 0; j < Nnode; j++) { - redirect[j] = 0; - } - offset = 1; - } - // Size of vector with module links - igraph_integer_t NmodLinks = 0; - // For all outLinks - size_t NoutLinks = node[flip].outLinks.size(); - if (NoutLinks == 0) { //dangling node, add node to calculate flow below - redirect[oldM] = offset + NmodLinks; - flowNtoM[NmodLinks].first = oldM; - flowNtoM[NmodLinks].second.first = 0.0; - flowNtoM[NmodLinks].second.second = 0.0; - NmodLinks++; - } else { - for (size_t j = 0; j < NoutLinks; j++) { - igraph_integer_t nb_M = node_index[node[flip].outLinks[j].first]; - // index destination du lien - double nb_flow = node[flip].outLinks[j].second; - // wgt du lien - if (redirect[nb_M] >= offset) { - flowNtoM[redirect[nb_M] - offset].second.first += nb_flow; - } else { - redirect[nb_M] = offset + NmodLinks; - flowNtoM[NmodLinks].first = nb_M; - flowNtoM[NmodLinks].second.first = nb_flow; - flowNtoM[NmodLinks].second.second = 0.0; - NmodLinks++; - } - } - } - // For all inLinks - size_t NinLinks = node[flip].inLinks.size(); - for (size_t j = 0; j < NinLinks; j++) { - igraph_integer_t nb_M = node_index[node[flip].inLinks[j].first]; - double nb_flow = node[flip].inLinks[j].second; - - if (redirect[nb_M] >= offset) { - flowNtoM[redirect[nb_M] - offset].second.second += nb_flow; - } else { - redirect[nb_M] = offset + NmodLinks; - flowNtoM[NmodLinks].first = nb_M; - flowNtoM[NmodLinks].second.first = 0.0; - flowNtoM[NmodLinks].second.second = nb_flow; - NmodLinks++; - } - } - - // For teleportation and dangling nodes - for (igraph_integer_t j = 0; j < NmodLinks; j++) { - igraph_integer_t newM = flowNtoM[j].first; - if (newM == oldM) { - flowNtoM[j].second.first += - (alpha * node[flip].size + beta * node[flip].danglingSize) * - (mod_teleportWeight[oldM] - node[flip].teleportWeight); - flowNtoM[j].second.second += - (alpha * (mod_size[oldM] - node[flip].size) + - beta * (mod_danglingSize[oldM] - node[flip].danglingSize)) * - node[flip].teleportWeight; - } else { - flowNtoM[j].second.first += - (alpha * node[flip].size + beta * node[flip].danglingSize) * - mod_teleportWeight[newM]; - flowNtoM[j].second.second += - (alpha * mod_size[newM] + beta * mod_danglingSize[newM] ) * - node[flip].teleportWeight; - } - } - - // Calculate flow to/from own module (default value if no link to - // own module) - double outFlowOldM = - (alpha * node[flip].size + beta * node[flip].danglingSize) * - (mod_teleportWeight[oldM] - node[flip].teleportWeight) ; - double inFlowOldM = - (alpha * (mod_size[oldM] - node[flip].size) + - beta * (mod_danglingSize[oldM] - node[flip].danglingSize)) * - node[flip].teleportWeight; - if (redirect[oldM] >= offset) { - outFlowOldM = flowNtoM[redirect[oldM] - offset].second.first; - inFlowOldM = flowNtoM[redirect[oldM] - offset].second.second; - } - - // Option to move to empty module (if node not already alone) - if (mod_members[oldM] > node[flip].members.size()) { - if (Nempty > 0) { - flowNtoM[NmodLinks].first = mod_empty[Nempty - 1]; - flowNtoM[NmodLinks].second.first = 0.0; - flowNtoM[NmodLinks].second.second = 0.0; - NmodLinks++; - } - } - - // Randomize link order for optimized search - for (igraph_integer_t j = 0; j < NmodLinks - 1; j++) { - igraph_integer_t randPos = RNG_INTEGER(j, NmodLinks - 1); - igraph_integer_t tmp_M = flowNtoM[j].first; - double tmp_outFlow = flowNtoM[j].second.first; - double tmp_inFlow = flowNtoM[j].second.second; - flowNtoM[j].first = flowNtoM[randPos].first; - flowNtoM[j].second.first = flowNtoM[randPos].second.first; - flowNtoM[j].second.second = flowNtoM[randPos].second.second; - flowNtoM[randPos].first = tmp_M; - flowNtoM[randPos].second.first = tmp_outFlow; - flowNtoM[randPos].second.second = tmp_inFlow; - } - - igraph_integer_t bestM = oldM; - double best_outFlow = 0.0; - double best_inFlow = 0.0; - double best_delta = 0.0; - - // Find the move that minimizes the description length - for (igraph_integer_t j = 0; j < NmodLinks; j++) { - - igraph_integer_t newM = flowNtoM[j].first; - double outFlowNewM = flowNtoM[j].second.first; - double inFlowNewM = flowNtoM[j].second.second; - - if (newM != oldM) { - - double delta_exit = plogp(exitFlow + outFlowOldM + inFlowOldM - - outFlowNewM - inFlowNewM) - exit; - - double delta_exit_log_exit = - plogp(mod_exit[oldM]) - - plogp(mod_exit[newM]) + - plogp(mod_exit[oldM] - node[flip].exit + outFlowOldM + inFlowOldM) - + plogp(mod_exit[newM] + node[flip].exit - outFlowNewM - - inFlowNewM); - - double delta_size_log_size = - plogp(mod_exit[oldM] + mod_size[oldM]) - - plogp(mod_exit[newM] + mod_size[newM]) - + plogp(mod_exit[oldM] + mod_size[oldM] - node[flip].exit - - node[flip].size + outFlowOldM + inFlowOldM) - + plogp(mod_exit[newM] + mod_size[newM] + node[flip].exit + - node[flip].size - outFlowNewM - inFlowNewM); - - double deltaL = delta_exit - 2.0 * delta_exit_log_exit + - delta_size_log_size; - - if (deltaL - best_delta < -1e-10) { - bestM = newM; - best_outFlow = outFlowNewM; - best_inFlow = inFlowNewM; - best_delta = deltaL; - } - } - } - - // Make best possible move - if (bestM != oldM) { - //Update empty module vector - if (mod_members[bestM] == 0) { - Nempty--; - } - if (mod_members[oldM] == node[flip].members.size()) { - mod_empty[Nempty] = oldM; - Nempty++; - } - - exitFlow -= mod_exit[oldM] + mod_exit[bestM]; - - exit_log_exit -= plogp(mod_exit[oldM]) + plogp(mod_exit[bestM]); - size_log_size -= plogp(mod_exit[oldM] + mod_size[oldM]) + - plogp(mod_exit[bestM] + mod_size[bestM]); - - mod_exit[oldM] -= node[flip].exit - outFlowOldM - - inFlowOldM; - mod_size[oldM] -= node[flip].size; - mod_danglingSize[oldM] -= node[flip].danglingSize; - mod_teleportWeight[oldM] -= node[flip].teleportWeight; - mod_members[oldM] -= node[flip].members.size(); - - mod_exit[bestM] += node[flip].exit - best_outFlow - - best_inFlow; - mod_size[bestM] += node[flip].size; - mod_danglingSize[bestM] += node[flip].danglingSize; - mod_teleportWeight[bestM] += node[flip].teleportWeight; - mod_members[bestM] += node[flip].members.size(); - - exitFlow += mod_exit[oldM] + mod_exit[bestM]; - - // Update terms in map equation - - exit_log_exit += plogp(mod_exit[oldM]) + plogp(mod_exit[bestM]); - size_log_size += plogp(mod_exit[oldM] + mod_size[oldM]) + - plogp(mod_exit[bestM] + mod_size[bestM]); - exit = plogp(exitFlow); - - // Update code length - - codeLength = exit - 2.0 * exit_log_exit + size_log_size - - nodeSize_log_nodeSize; - - node_index[flip] = bestM; - moved = true; - } - offset += Nnode; - } - - RNG_END(); - - return moved; -} - -/** Apply the move to the given network - */ -void Greedy::apply(bool sort) { - - //old fct prepare(sort) - vector modSnode; // will give IDs of no-empty modules (nodes) - modSnode.reserve(Nnode); - - igraph_integer_t Nmod = 0; - for (igraph_integer_t i = 0; i < Nnode; i++) { - if (mod_members[i] > 0) { - Nmod++; - modSnode.push_back(i); - } - } - - if (sort) { - // sort by mod_size - std::sort(modSnode.begin(), modSnode.end(), - [&](size_t a, size_t b) { return mod_size[a] > mod_size[b]; } ); - } - - // Create the new graph - FlowGraph tmp_fgraph(Nmod); - vector &node_tmp = tmp_fgraph.node ; - - const vector &node = graph->node; - - vector nodeInMod(Nnode); - - // creation of new nodes - for (igraph_integer_t i = 0; i < Nmod; i++) { - node_tmp[i].members.clear(); // clear membership - node_tmp[i].exit = mod_exit[modSnode[i]]; - node_tmp[i].size = mod_size[modSnode[i]]; - node_tmp[i].danglingSize = mod_danglingSize[modSnode[i]]; - node_tmp[i].teleportWeight = mod_teleportWeight[modSnode[i]]; - - nodeInMod[modSnode[i]] = i; - } - - // Calculate outflow of links to different modules - vector > outFlowNtoM(Nmod); - - for (igraph_integer_t i = 0; i < Nnode; i++) { - igraph_integer_t i_M = nodeInMod[node_index[i]]; //final id of the module of the node i - // add node members to the module - copy( node[i].members.begin(), node[i].members.end(), - back_inserter( node_tmp[i_M].members ) ); - - for (const auto &link : node[i].outLinks) { - igraph_integer_t nb = link.first; - igraph_integer_t nb_M = nodeInMod[node_index[nb]]; - double nb_flow = link.second; - if (nb != i) { - // inserts key nb_M if it does not exist - outFlowNtoM[i_M][nb_M] += nb_flow; - } - } - } - - // Create outLinks at new level - for (igraph_integer_t i = 0; i < Nmod; i++) { - for (const auto &item : outFlowNtoM[i]) { - if (item.first != i) { - node_tmp[i].outLinks.emplace_back(item); - } - } - } - - // Calculate inflow of links from different modules - vector > inFlowNtoM(Nmod); - - for (igraph_integer_t i = 0; i < Nnode; i++) { - igraph_integer_t i_M = nodeInMod[node_index[i]]; - for (const auto &inLink : node[i].inLinks) { - igraph_integer_t nb = inLink.first; - igraph_integer_t nb_M = nodeInMod[node_index[nb]]; - double nb_flow = inLink.second; - if (nb != i) { - // inserts key nb_M if it does not exist - inFlowNtoM[i_M][nb_M] += nb_flow; - } - } - } - - // Create inLinks at new level - for (igraph_integer_t i = 0; i < Nmod; i++) { - for (const auto &item : inFlowNtoM[i]) { - if (item.first != i) { - node_tmp[i].inLinks.emplace_back(item); - } - } - } - - // Option to move to empty module - mod_empty.clear(); - Nempty = 0; - - //swap node between tmp_graph and graph, then destroy tmp_fgraph - graph->swap(tmp_fgraph); - Nnode = Nmod; -} - - -/** - * RAZ et recalcul : - * - mod_exit - * - mod_size - * - mod_danglingSize - * - mod_teleportWeight - * - mod_members - * and - * - exit_log_exit - * - size_log_size - * - exitFlow - * - exit - * - codeLength - * according to **node / node[i]->index - */ - - -/* Compute the new CodeSize if modules are merged as indicated by moveTo - */ -void Greedy::setMove(const std::vector &moveTo) { - const std::vector &node = graph->node; - for (igraph_integer_t i = 0 ; i < Nnode ; i++) { // pour chaque module - igraph_integer_t oldM = i; - igraph_integer_t newM = moveTo[i]; - //printf("old -> new : %d -> %d \n", oldM, newM); - if (newM != oldM) { - - // Si je comprend bien : - // outFlow... : c'est le "flow" de i-> autre sommet du meme module - // inFlow... : c'est le "flow" depuis un autre sommet du meme module --> i - double outFlowOldM = (alpha * node[i].size + beta * node[i].danglingSize) * - (mod_teleportWeight[oldM] - node[i].teleportWeight); - double inFlowOldM = (alpha * (mod_size[oldM] - node[i].size) + - beta * (mod_danglingSize[oldM] - - node[i].danglingSize)) * - node[i].teleportWeight; - double outFlowNewM = (alpha * node[i].size + beta * node[i].danglingSize) - * mod_teleportWeight[newM]; - double inFlowNewM = (alpha * mod_size[newM] + - beta * mod_danglingSize[newM]) * - node[i].teleportWeight; - - // For all outLinks - for (const auto &outLink : node[i].outLinks) { - igraph_integer_t nb_M = node_index[outLink.first]; - double nb_flow = outLink.second; - if (nb_M == oldM) { - outFlowOldM += nb_flow; - } else if (nb_M == newM) { - outFlowNewM += nb_flow; - } - } - - // For all inLinks - for (const auto &inLink : node[i].inLinks) { - igraph_integer_t nb_M = node_index[inLink.first]; - double nb_flow = inLink.second; - if (nb_M == oldM) { - inFlowOldM += nb_flow; - } else if (nb_M == newM) { - inFlowNewM += nb_flow; - } - } - - // Update empty module vector - // RAZ de mod_empty et Nempty ds calibrate() - if (mod_members[newM] == 0) { - // si le nouveau etait vide, on a un vide de moins... - Nempty--; - } - if (mod_members[oldM] == node[i].members.size()) { - // si l'ancien avait la taille de celui qui bouge, un vide de plus - mod_empty[Nempty] = oldM; - Nempty++; - } - - exitFlow -= mod_exit[oldM] + mod_exit[newM]; - exit_log_exit -= plogp(mod_exit[oldM]) + plogp(mod_exit[newM]); - size_log_size -= plogp(mod_exit[oldM] + mod_size[oldM]) + - plogp(mod_exit[newM] + mod_size[newM]); - - mod_exit[oldM] -= node[i].exit - outFlowOldM - inFlowOldM; - mod_size[oldM] -= node[i].size; - mod_danglingSize[oldM] -= node[i].danglingSize; - mod_teleportWeight[oldM] -= node[i].teleportWeight; - mod_members[oldM] -= node[i].members.size(); - mod_exit[newM] += node[i].exit - outFlowNewM - inFlowNewM; - mod_size[newM] += node[i].size; - mod_danglingSize[newM] += node[i].danglingSize; - mod_teleportWeight[newM] += node[i].teleportWeight; - mod_members[newM] += node[i].members.size(); - - exitFlow += mod_exit[oldM] + mod_exit[newM]; - exit_log_exit += plogp(mod_exit[oldM]) + plogp(mod_exit[newM]); - size_log_size += plogp(mod_exit[oldM] + mod_size[oldM]) + - plogp(mod_exit[newM] + mod_size[newM]); - exit = plogp(exitFlow); - - codeLength = exit - 2.0 * exit_log_exit + size_log_size - - nodeSize_log_nodeSize; - - node_index[i] = newM; - - } - - } -} diff --git a/src/vendor/cigraph/src/community/infomap/infomap_Greedy.h b/src/vendor/cigraph/src/community/infomap/infomap_Greedy.h deleted file mode 100644 index 87bf0b53cc9..00000000000 --- a/src/vendor/cigraph/src/community/infomap/infomap_Greedy.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ -/* - IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#ifndef INFOMAP_GREEDY_H -#define INFOMAP_GREEDY_H - -#include "infomap_Node.h" -#include "infomap_FlowGraph.h" - -#include "igraph_random.h" - -#include - -class Greedy { -public: - explicit Greedy(FlowGraph *fgraph); - // initialise les attributs par rapport au graph - - void setMove(const std::vector &moveTo); - bool optimize(); - void apply(bool sort); - - /**************************************************************************/ - -public: - double codeLength; - -private: - FlowGraph * graph; - igraph_integer_t Nnode; - - double exit; - double exitFlow; - double exit_log_exit; - double size_log_size; - double nodeSize_log_nodeSize; - - double alpha, beta; - // local copy of fgraph alpha, beta (=alpha - Nnode = graph->Nnode;1) - - std::vector node_index; // module number of each node - - igraph_integer_t Nempty = 0; - std::vector mod_empty; - - std::vector mod_exit; // version tmp de node - std::vector mod_size; - std::vector mod_danglingSize; - std::vector mod_teleportWeight; - std::vector mod_members; -}; - -#endif // INFOMAP_GREEDY_H diff --git a/src/vendor/cigraph/src/community/infomap/infomap_Node.h b/src/vendor/cigraph/src/community/infomap/infomap_Node.h deleted file mode 100644 index c3ef8c685ef..00000000000 --- a/src/vendor/cigraph/src/community/infomap/infomap_Node.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ -/* - IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#ifndef INFOMAP_NODE_H -#define INFOMAP_NODE_H - -#include "igraph_interface.h" - -#include - -struct Node { - - Node() = default; - Node(igraph_integer_t modulenr, double tpweight) : - teleportWeight(tpweight) - { - members.push_back(modulenr); // members = [nodenr] - } - - std::vector members; - std::vector< std::pair > inLinks; - std::vector< std::pair > outLinks; - double selfLink = 0.0; - - double teleportWeight = 0.0; - double danglingSize = 0.0; - double exit = 0.0; - double size = 0.0; -}; - -#endif // INFOMAP_NODE_H diff --git a/src/vendor/cigraph/src/community/label_propagation.c b/src/vendor/cigraph/src/community/label_propagation.c index 1fc537ad4ef..587b3d05cd9 100644 --- a/src/vendor/cigraph/src/community/label_propagation.c +++ b/src/vendor/cigraph/src/community/label_propagation.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2022 The igraph development team @@ -28,15 +26,437 @@ #include "core/interruption.h" +static igraph_error_t community_label_propagation( + const igraph_t *graph, + igraph_vector_int_t *membership, + igraph_neimode_t mode, + const igraph_vector_t *weights, + const igraph_vector_bool_t *fixed, + igraph_bool_t retention) { + + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_integer_t no_of_not_fixed_nodes = 0; + igraph_integer_t i, j, k; + igraph_adjlist_t al; + igraph_inclist_t il; + igraph_bool_t running, control_iteration; + + igraph_vector_t label_weights; + igraph_vector_int_t dominant_labels, nonzero_labels, node_order; + igraph_neimode_t reverse_mode; + int iter = 0; /* interruption counter */ + + reverse_mode = IGRAPH_REVERSE_MODE(mode); + + /* Create an adjacency/incidence list representation for efficiency. + * For the unweighted case, the adjacency list is enough. For the + * weighted case, we need the incidence list */ + if (weights) { + IGRAPH_CHECK(igraph_inclist_init(graph, &il, reverse_mode, IGRAPH_LOOPS_ONCE)); + IGRAPH_FINALLY(igraph_inclist_destroy, &il); + } else { + IGRAPH_CHECK(igraph_adjlist_init(graph, &al, reverse_mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE)); + IGRAPH_FINALLY(igraph_adjlist_destroy, &al); + } + + /* Create storage space for counting distinct labels and dominant ones */ + IGRAPH_VECTOR_INIT_FINALLY(&label_weights, no_of_nodes); + IGRAPH_VECTOR_INT_INIT_FINALLY(&dominant_labels, 0); + IGRAPH_VECTOR_INT_INIT_FINALLY(&nonzero_labels, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&dominant_labels, 2)); + + /* Initialize node ordering vector with only the not fixed nodes */ + if (fixed) { + IGRAPH_VECTOR_INT_INIT_FINALLY(&node_order, no_of_nodes); + for (i = 0; i < no_of_nodes; i++) { + if (!VECTOR(*fixed)[i]) { + VECTOR(node_order)[no_of_not_fixed_nodes] = i; + no_of_not_fixed_nodes++; + } + } + IGRAPH_CHECK(igraph_vector_int_resize(&node_order, no_of_not_fixed_nodes)); + } else { + IGRAPH_CHECK(igraph_vector_int_init_range(&node_order, 0, no_of_nodes)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &node_order); + no_of_not_fixed_nodes = no_of_nodes; + } + + /* There are two modes of operation in this implementation: retention or + * dominance. When using retention, we prefer to keep the current label of a node. + * Only if the current label is not among the dominant labels will we + * update the label. If a label changes, we will continue to iterate + * over all nodes. + * + * When not using retention we check for dominance after each iteration. This + * is implemented as two alternating types of iterations, one for changing + * labels and the other one for checking the end condition - every vertex in the + * graph has a label to which the maximum number of its neighbors belongs. If + * control_iteration is true, we are just checking the end condition and not + * relabeling nodes. + */ + + control_iteration = true; + running = true; + while (running) { + igraph_integer_t v1, num_neis; + igraph_real_t max_count; + igraph_vector_int_t *neis; + igraph_vector_int_t *ineis; + igraph_bool_t was_zero; + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); + + if (retention) { + /* We stop in this iteration by default, unless a label changes */ + running = false; + /* Shuffle the node ordering vector */ + igraph_vector_int_shuffle(&node_order); + } else { + if (control_iteration) { + /* If we are in the control iteration, we expect in the beginning of + the iteration that all vertices meet the end condition, so 'running' is false. + If some of them does not, 'running' is set to true later in the code. */ + running = false; + } else { + /* Shuffle the node ordering vector if we are in the label updating iteration */ + igraph_vector_int_shuffle(&node_order); + } + } + + /* In the prescribed order, loop over the vertices and reassign labels */ + for (i = 0; i < no_of_not_fixed_nodes; i++) { + v1 = VECTOR(node_order)[i]; + + /* Count the weights corresponding to different labels */ + igraph_vector_int_clear(&dominant_labels); + igraph_vector_int_clear(&nonzero_labels); + max_count = 0.0; + if (weights) { + + ineis = igraph_inclist_get(&il, v1); + num_neis = igraph_vector_int_size(ineis); + + for (j = 0; j < num_neis; j++) { + k = VECTOR(*membership)[IGRAPH_OTHER(graph, VECTOR(*ineis)[j], v1)]; + if (k < 0) { + continue; /* skip if it has no label yet */ + } + was_zero = (VECTOR(label_weights)[k] == 0); + VECTOR(label_weights)[k] += VECTOR(*weights)[VECTOR(*ineis)[j]]; + + if (was_zero && VECTOR(label_weights)[k] != 0) { + /* weights just became nonzero */ + IGRAPH_CHECK(igraph_vector_int_push_back(&nonzero_labels, k)); + } + + if (max_count < VECTOR(label_weights)[k]) { + max_count = VECTOR(label_weights)[k]; + IGRAPH_CHECK(igraph_vector_int_resize(&dominant_labels, 1)); + VECTOR(dominant_labels)[0] = k; + } else if (max_count == VECTOR(label_weights)[k]) { + IGRAPH_CHECK(igraph_vector_int_push_back(&dominant_labels, k)); + } + } + } else { + + neis = igraph_adjlist_get(&al, v1); + num_neis = igraph_vector_int_size(neis); + + for (j = 0; j < num_neis; j++) { + + k = VECTOR(*membership)[VECTOR(*neis)[j]]; + if (k < 0) { + continue; /* skip if it has no label yet */ + } + VECTOR(label_weights)[k]++; + + if (VECTOR(label_weights)[k] == 1) { + /* weights just became nonzero */ + IGRAPH_CHECK(igraph_vector_int_push_back(&nonzero_labels, k)); + } + + if (max_count < VECTOR(label_weights)[k]) { + max_count = VECTOR(label_weights)[k]; + IGRAPH_CHECK(igraph_vector_int_resize(&dominant_labels, 1)); + VECTOR(dominant_labels)[0] = k; + } else if (max_count == VECTOR(label_weights)[k]) { + IGRAPH_CHECK(igraph_vector_int_push_back(&dominant_labels, k)); + } + } + } + + if (igraph_vector_int_size(&dominant_labels) > 0) { + if (retention) { + /* If we are using retention, we first check if the current label + is among the maximum label. */ + j = (long)VECTOR(*membership)[v1]; + if (j < 0 || /* Doesn't have a label yet */ + VECTOR(label_weights)[j] == 0 || /* Label not present in neighbors */ + VECTOR(label_weights)[j] < max_count /* Label not dominant */) { + /* Select randomly from the dominant labels */ + k = RNG_INTEGER(0, igraph_vector_int_size(&dominant_labels) - 1); + k = VECTOR(dominant_labels)[(long int)k]; + /* If label changes, we will continue running */ + if (k != j) { + running = true; + } + /* Actually change label */ + VECTOR(*membership)[v1] = k; + } + } else { + /* We are not using retention, so check if we should do a control iteration + or an update iteration. */ + if (control_iteration) { + /* Check if the _current_ label of the node is also dominant */ + k = VECTOR(*membership)[v1]; + if (k < 0 || /* No label assigned yet or */ + VECTOR(label_weights)[k] < max_count /* Label is not maximum */ + ) { + /* Nope, we need at least one more iteration */ + running = true; + } + } else { + /* Select randomly from the dominant labels */ + k = RNG_INTEGER(0, igraph_vector_int_size(&dominant_labels) - 1); + VECTOR(*membership)[v1] = VECTOR(dominant_labels)[k]; + } + } + } + + /* Clear the nonzero elements in label_weights */ + num_neis = igraph_vector_int_size(&nonzero_labels); + for (j = 0; j < num_neis; j++) { + VECTOR(label_weights)[VECTOR(nonzero_labels)[j]] = 0; + } + } + + /* Alternating between control iterations and label updating iterations */ + if (!retention) { + control_iteration = !control_iteration; + } + } + + if (weights) { + igraph_inclist_destroy(&il); + } else { + igraph_adjlist_destroy(&al); + } + IGRAPH_FINALLY_CLEAN(1); + + igraph_vector_int_destroy(&node_order); + igraph_vector_int_destroy(&nonzero_labels); + igraph_vector_int_destroy(&dominant_labels); + igraph_vector_destroy(&label_weights); + IGRAPH_FINALLY_CLEAN(4); + + return IGRAPH_SUCCESS; +} + +static igraph_error_t community_fast_label_propagation( + const igraph_t *graph, + igraph_vector_int_t *membership, + igraph_neimode_t mode, + const igraph_vector_t *weights, + const igraph_vector_bool_t *fixed) { + + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_integer_t no_of_not_fixed_nodes = 0; + igraph_integer_t i, j, k; + igraph_inclist_t il; + igraph_adjlist_t al; + + igraph_vector_t label_weights; + igraph_vector_int_t dominant_labels, nonzero_labels, node_order; + igraph_dqueue_int_t queue; + igraph_vector_bool_t in_queue; + igraph_neimode_t reverse_mode; + int iter = 0; /* interruption counter */ + + reverse_mode = IGRAPH_REVERSE_MODE(mode); + + if (weights) { + IGRAPH_CHECK(igraph_inclist_init(graph, &il, reverse_mode, IGRAPH_LOOPS_ONCE)); + IGRAPH_FINALLY(igraph_inclist_destroy, &il); + } else { + IGRAPH_CHECK(igraph_adjlist_init(graph, &al, reverse_mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE)); + IGRAPH_FINALLY(igraph_adjlist_destroy, &al); + } + + /* Create storage space for counting distinct labels and dominant ones */ + IGRAPH_VECTOR_INIT_FINALLY(&label_weights, no_of_nodes); + IGRAPH_VECTOR_INT_INIT_FINALLY(&dominant_labels, 0); + IGRAPH_VECTOR_INT_INIT_FINALLY(&nonzero_labels, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&dominant_labels, 2)); + + /* Initialize node ordering vector with only the not fixed nodes */ + IGRAPH_DQUEUE_INT_INIT_FINALLY(&queue, no_of_nodes); + IGRAPH_VECTOR_BOOL_INIT_FINALLY(&in_queue, no_of_nodes); + + /* Initialize node ordering vector with only the not fixed nodes */ + if (fixed) { + IGRAPH_VECTOR_INT_INIT_FINALLY(&node_order, no_of_nodes); + for (i = 0; i < no_of_nodes; i++) { + if (!VECTOR(*fixed)[i]) { + VECTOR(node_order)[no_of_not_fixed_nodes] = i; + no_of_not_fixed_nodes++; + } + } + IGRAPH_CHECK(igraph_vector_int_resize(&node_order, no_of_not_fixed_nodes)); + } else { + IGRAPH_CHECK(igraph_vector_int_init_range(&node_order, 0, no_of_nodes)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &node_order); + no_of_not_fixed_nodes = no_of_nodes; + } + + for (i = 0; i < no_of_not_fixed_nodes; i++) { + IGRAPH_CHECK(igraph_dqueue_int_push(&queue, VECTOR(node_order)[i])); + VECTOR(in_queue)[VECTOR(node_order)[i]] = true; + } + igraph_vector_int_destroy(&node_order); + IGRAPH_FINALLY_CLEAN(1); + + while (!igraph_dqueue_int_empty(&queue)) { + igraph_integer_t v1, v2, e = -1, num_neis; + igraph_real_t max_count; + igraph_vector_int_t *neis; + igraph_bool_t was_zero; + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); + + v1 = igraph_dqueue_int_pop(&queue); + VECTOR(in_queue)[v1] = false; + + /* Count the weights corresponding to different labels */ + igraph_vector_int_clear(&dominant_labels); + igraph_vector_int_clear(&nonzero_labels); + max_count = 0.0; + if (weights) { + neis = igraph_inclist_get(&il, v1); + } else { + neis = igraph_adjlist_get(&al, v1); + } + + num_neis = igraph_vector_int_size(neis); + for (j = 0; j < num_neis; j++) { + if (weights) { + e = VECTOR(*neis)[j]; + v2 = IGRAPH_OTHER(graph, e, v1); + } else { + v2 = VECTOR(*neis)[j]; + } + k = VECTOR(*membership)[v2]; + if (k < 0) { + continue; /* skip if it has no label yet */ + } + was_zero = (VECTOR(label_weights)[k] == 0); + VECTOR(label_weights)[k] += (weights ? VECTOR(*weights)[e] : 1); + + if (was_zero && VECTOR(label_weights)[k] >= 0) { + /* counter just became non-negative */ + IGRAPH_CHECK(igraph_vector_int_push_back(&nonzero_labels, k)); + } + + if (max_count < VECTOR(label_weights)[k]) { + max_count = VECTOR(label_weights)[k]; + IGRAPH_CHECK(igraph_vector_int_resize(&dominant_labels, 1)); + VECTOR(dominant_labels)[0] = k; + } else if (max_count == VECTOR(label_weights)[k]) { + IGRAPH_CHECK(igraph_vector_int_push_back(&dominant_labels, k)); + } + } + + if (igraph_vector_int_size(&dominant_labels) > 0) { + igraph_integer_t current_label = VECTOR(*membership)[v1]; + + /* Select randomly from the dominant labels */ + k = RNG_INTEGER(0, igraph_vector_int_size(&dominant_labels) - 1); + igraph_integer_t new_label = VECTOR(dominant_labels)[k]; /* a dominant label */ + + /* Check if the _current_ label of the node is not the same */ + if (new_label != current_label) { + /* We still need to consider its neighbors not in the new community */ + for (j = 0; j < num_neis; j++) { + if (weights) { + e = VECTOR(*neis)[j]; + v2 = IGRAPH_OTHER(graph, e, v1); + } else { + v2 = VECTOR(*neis)[j]; + } + if (!VECTOR(in_queue)[v2]) { + igraph_integer_t neigh_label = VECTOR(*membership)[v2]; /* neighbor community */ + if (neigh_label != new_label && /* not in new community */ + (fixed == NULL || !VECTOR(*fixed)[v2]) ) { /* not fixed */ + IGRAPH_CHECK(igraph_dqueue_int_push(&queue, v2)); + VECTOR(in_queue)[v2] = true; + } + } + } + } + VECTOR(*membership)[v1] = new_label; + } + + /* Clear the nonzero elements in label_weights */ + num_neis = igraph_vector_int_size(&nonzero_labels); + for (j = 0; j < num_neis; j++) { + VECTOR(label_weights)[VECTOR(nonzero_labels)[j]] = 0; + } + } + + if (weights) { + igraph_inclist_destroy(&il); + } else { + igraph_adjlist_destroy(&al); + } + IGRAPH_FINALLY_CLEAN(1); + + igraph_vector_bool_destroy(&in_queue); + igraph_dqueue_int_destroy(&queue); + igraph_vector_destroy(&label_weights); + igraph_vector_int_destroy(&dominant_labels); + igraph_vector_int_destroy(&nonzero_labels); + IGRAPH_FINALLY_CLEAN(5); + + return IGRAPH_SUCCESS; +} + /** * \ingroup communities * \function igraph_community_label_propagation * \brief Community detection based on label propagation. * * This function implements the label propagation-based community detection - * algorithm described by Raghavan, Albert and Kumara. This version extends + * algorithm described by Raghavan, Albert and Kumara (2007). This version extends * the original method by the ability to take edge weights into consideration - * and also by allowing some labels to be fixed. + * and also by allowing some labels to be fixed. In addition, it implements + * the fast label propagation alternative introduced by Traag and Šubelj (2023). + * + * + * The algorithm works by iterating over nodes and updating the label of a node + * based on the labels of its neighbors. The labels that are most frequent among + * the neighbors are said to be dominant labels. The label of a node is always + * updated to a dominant label. The algorithm guarantees that the label for each + * is dominant when it terminates. + * + * + * There are several variants implemented, which work slightly differently with + * the dominance of labels. Nodes with a dominant label might no longer have a + * dominant label if one of their neighbors change label. In \c + * IGRAPH_LPA_DOMINANCE an additional iteration over all nodes is made after + * updating all labels to double check whether all nodes indeed have a dominant + * label. When updating the label of a node, labels are always sampled from + * among all dominant labels. The algorithm stops when all nodes have dominant + * labels. In \c IGRAPH_LPA_RETENTION instead labels are only updated when they + * are not dominant. That is, they retain their current label whenever the + * current label is already dominant. The algorithm does not make an additional + * iteration to check for dominance. Instead, it simply keeps track whether a + * label has been updated, and terminates if no updates have been made. In \c + * IGRAPH_LPA_FAST labels are sampled from among all dominant labels, similar to + * \c IGRAPH_LPA_DOMINANCE. Instead of iterating over all nodes, it keeps track + * of a queue of nodes that should be considered. Nodes are popped from the + * queue when they are considered for update. When the label of a node is + * updated, the node's neighbors are added to the queue again (if they weren't + * already in the queue). The algorithm terminates when the queue is empty. All + * variants guarantee that the labels for all nodes are dominant. * * * Weights are taken into account as follows: when the new label of node @@ -57,10 +477,9 @@ * References: * * - * Raghavan, U.N. and Albert, R. and Kumara, S.: - * Near linear time algorithm to detect community structures in large-scale networks. - * Phys Rev E 76, 036106 (2007). - * https://doi.org/10.1103/PhysRevE.76.036106 + * Raghavan, U.N. and Albert, R. and Kumara, S.: Near linear time algorithm to + * detect community structures in large-scale networks. Phys Rev E 76, 036106 + * (2007). https://doi.org/10.1103/PhysRevE.76.036106 * * * Šubelj, L.: Label propagation for clustering. Chapter in "Advances in @@ -69,7 +488,13 @@ * https://doi.org/10.1002/9781119483298.ch5 * https://arxiv.org/abs/1709.05634 * - * \param graph The input graph. Note that the algorithm wsa originally + * + * Traag, V. A., and Šubelj, L.: Large network community detection by fast + * label propagation. Scientific Reports, 13:1, (2023). + * https://doi.org/10.1038/s41598-023-29610-z + * https://arxiv.org/abs/2209.13338 + * + * \param graph The input graph. Note that the algorithm was originally * defined for undirected graphs. You are advised to set \p mode to * \c IGRAPH_ALL if you pass a directed graph here to treat it as * undirected. @@ -105,6 +530,15 @@ * and igraph may renumber labels. However, co-membership constraints * will be respected: two vertices can be fixed to be in the same or in * different communities. + * \param lpa_variant Which variant of the label propagation algorithm to run. + * \clist + * \cli IGRAPH_LPA_DOMINANCE + * check for dominance of all nodes after each iteration. + * \cli IGRAPH_LPA_RETENTION + * keep current label if among dominant labels, only check if labels changed. + * \cli IGRAPH_LPA_FAST + * sample from dominant labels, only check neighbors. + * \endclist * \return Error code. * * Time complexity: O(m+n) @@ -112,35 +546,26 @@ * \example examples/simple/igraph_community_label_propagation.c */ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, - igraph_vector_int_t *membership, - igraph_neimode_t mode, - const igraph_vector_t *weights, - const igraph_vector_int_t *initial, - const igraph_vector_bool_t *fixed) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_vector_int_t *membership, + igraph_neimode_t mode, + const igraph_vector_t *weights, + const igraph_vector_int_t *initial, + const igraph_vector_bool_t *fixed, + igraph_lpa_variant_t lpa_variant) { + + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_integer_t no_of_not_fixed_nodes = no_of_nodes; igraph_integer_t i, j, k; - igraph_adjlist_t al; - igraph_inclist_t il; - igraph_bool_t running, control_iteration; igraph_bool_t unlabelled_left; - igraph_neimode_t reversed_mode; - int iter = 0; /* interruption counter */ - - igraph_vector_t label_counters; /* real type, stores weight sums */ - igraph_vector_int_t dominant_labels, nonzero_labels, node_order; /* We make a copy of 'fixed' as a pointer into 'fixed_copy' after casting * away the constness, and promise ourselves that we will make a proper * copy of 'fixed' into 'fixed_copy' as soon as we start mutating it */ igraph_vector_bool_t *fixed_copy = (igraph_vector_bool_t *) fixed; - /* The implementation uses a trick to avoid negative array indexing: - * elements of the membership vector are increased by 1 at the start - * of the algorithm; this to allow us to denote unlabeled vertices - * (if any) by zeroes. The membership vector is shifted back in the end - */ + /* Unlabelled nodes are represented with -1. */ +#define IS_UNLABELLED(x) (VECTOR(*membership)[x] < 0) /* Do some initial checks */ if (fixed && igraph_vector_bool_size(fixed) != no_of_nodes) { @@ -173,25 +598,22 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, /* Check if the labels used are valid, initialize membership vector */ for (i = 0; i < no_of_nodes; i++) { if (VECTOR(*initial)[i] < 0) { - VECTOR(*membership)[i] = 0; + VECTOR(*membership)[i] = -1; } else { - VECTOR(*membership)[i] = VECTOR(*initial)[i] + 1; + VECTOR(*membership)[i] = VECTOR(*initial)[i]; } } if (fixed) { for (i = 0; i < no_of_nodes; i++) { if (VECTOR(*fixed)[i]) { - if (VECTOR(*membership)[i] == 0) { + if (IS_UNLABELLED(i)) { IGRAPH_WARNING("Fixed nodes cannot be unlabeled, ignoring them."); /* We cannot modify 'fixed' because it is const, so we make a copy and * modify 'fixed_copy' instead */ if (fixed_copy == fixed) { fixed_copy = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (fixed_copy == 0) { - IGRAPH_ERROR("Failed to copy 'fixed' vector.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - + IGRAPH_CHECK_OOM(fixed_copy, "Insufficient memory for label propagation."); IGRAPH_FINALLY(igraph_free, fixed_copy); IGRAPH_CHECK(igraph_vector_bool_init_copy(fixed_copy, fixed)); IGRAPH_FINALLY(igraph_vector_bool_destroy, fixed_copy); @@ -211,173 +633,46 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, } } else { for (i = 0; i < no_of_nodes; i++) { - VECTOR(*membership)[i] = i + 1; + VECTOR(*membership)[i] = i; } } - reversed_mode = IGRAPH_REVERSE_MODE(mode); - /* From this point onwards we use 'fixed_copy' instead of 'fixed' */ + switch (lpa_variant) { + case IGRAPH_LPA_FAST: + IGRAPH_CHECK(community_fast_label_propagation(graph, membership, mode, weights, fixed_copy)); + break; - /* Create an adjacency/incidence list representation for efficiency. - * For the unweighted case, the adjacency list is enough. For the - * weighted case, we need the incidence list */ - if (weights) { - IGRAPH_CHECK(igraph_inclist_init(graph, &il, reversed_mode, IGRAPH_LOOPS_ONCE)); - IGRAPH_FINALLY(igraph_inclist_destroy, &il); - } else { - IGRAPH_CHECK(igraph_adjlist_init(graph, &al, reversed_mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE)); - IGRAPH_FINALLY(igraph_adjlist_destroy, &al); - } - - /* Create storage space for counting distinct labels and dominant ones */ - IGRAPH_VECTOR_INIT_FINALLY(&label_counters, no_of_nodes + 1); - IGRAPH_VECTOR_INT_INIT_FINALLY(&dominant_labels, 0); - IGRAPH_VECTOR_INT_INIT_FINALLY(&nonzero_labels, 0); - IGRAPH_CHECK(igraph_vector_int_reserve(&dominant_labels, 2)); - - /* Initialize node ordering vector with only the not fixed nodes */ - if (fixed_copy) { - IGRAPH_VECTOR_INT_INIT_FINALLY(&node_order, no_of_not_fixed_nodes); - for (i = 0, j = 0; i < no_of_nodes; i++) { - if (!VECTOR(*fixed_copy)[i]) { - VECTOR(node_order)[j] = i; - j++; - } - } - } else { - IGRAPH_CHECK(igraph_vector_int_init_range(&node_order, 0, no_of_nodes)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &node_order); - } - - /* There are two alternating types of iterations, one for changing labels and - the other one for checking the end condition - every vertex in the graph has - a label to which the maximum number of its neighbors belongs. If control_iteration - is true, we are just checking the end condition and not relabeling nodes. */ - control_iteration = true; - running = true; - while (running) { - igraph_integer_t v1, num_neis; - igraph_real_t max_count; - igraph_vector_int_t *neis; - igraph_vector_int_t *ineis; - igraph_bool_t was_zero; + case IGRAPH_LPA_RETENTION: + IGRAPH_CHECK(community_label_propagation(graph, membership, mode, weights, fixed_copy, /* retention */ true )); + break; - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); + case IGRAPH_LPA_DOMINANCE: + IGRAPH_CHECK(community_label_propagation(graph, membership, mode, weights, fixed_copy, /* retention */ false)); + break; - if (control_iteration) { - /* If we are in the control iteration, we expect in the beginning of - the iteration that all vertices meet the end condition, so 'running' is false. - If some of them does not, 'running' is set to true later in the code. */ - running = false; - } else { - /* Shuffle the node ordering vector if we are in the label updating iteration */ - IGRAPH_CHECK(igraph_vector_int_shuffle(&node_order)); - } - - RNG_BEGIN(); - /* In the prescribed order, loop over the vertices and reassign labels */ - for (i = 0; i < no_of_not_fixed_nodes; i++) { - v1 = VECTOR(node_order)[i]; - - /* Count the weights corresponding to different labels */ - igraph_vector_int_clear(&dominant_labels); - igraph_vector_int_clear(&nonzero_labels); - max_count = 0.0; - if (weights) { - ineis = igraph_inclist_get(&il, v1); - num_neis = igraph_vector_int_size(ineis); - for (j = 0; j < num_neis; j++) { - k = VECTOR(*membership)[IGRAPH_OTHER(graph, VECTOR(*ineis)[j], v1)]; - if (k == 0) { - continue; /* skip if it has no label yet */ - } - was_zero = (VECTOR(label_counters)[k] == 0); - VECTOR(label_counters)[k] += VECTOR(*weights)[VECTOR(*ineis)[j]]; - if (was_zero && VECTOR(label_counters)[k] != 0) { - /* counter just became nonzero */ - IGRAPH_CHECK(igraph_vector_int_push_back(&nonzero_labels, k)); - } - if (max_count < VECTOR(label_counters)[k]) { - max_count = VECTOR(label_counters)[k]; - IGRAPH_CHECK(igraph_vector_int_resize(&dominant_labels, 1)); - VECTOR(dominant_labels)[0] = k; - } else if (max_count == VECTOR(label_counters)[k]) { - IGRAPH_CHECK(igraph_vector_int_push_back(&dominant_labels, k)); - } - } - } else { - neis = igraph_adjlist_get(&al, v1); - num_neis = igraph_vector_int_size(neis); - for (j = 0; j < num_neis; j++) { - k = VECTOR(*membership)[VECTOR(*neis)[j]]; - if (k == 0) { - continue; /* skip if it has no label yet */ - } - VECTOR(label_counters)[k]++; - if (VECTOR(label_counters)[k] == 1) { - /* counter just became nonzero */ - IGRAPH_CHECK(igraph_vector_int_push_back(&nonzero_labels, k)); - } - if (max_count < VECTOR(label_counters)[k]) { - max_count = VECTOR(label_counters)[k]; - IGRAPH_CHECK(igraph_vector_int_resize(&dominant_labels, 1)); - VECTOR(dominant_labels)[0] = k; - } else if (max_count == VECTOR(label_counters)[k]) { - IGRAPH_CHECK(igraph_vector_int_push_back(&dominant_labels, k)); - } - } - } - - if (igraph_vector_int_size(&dominant_labels) > 0) { - if (control_iteration) { - /* Check if the _current_ label of the node is also dominant */ - if (VECTOR(label_counters)[VECTOR(*membership)[v1]] != max_count) { - /* Nope, we need at least one more iteration */ - running = true; - } - } - else { - /* Select randomly from the dominant labels */ - k = RNG_INTEGER(0, igraph_vector_int_size(&dominant_labels) - 1); - VECTOR(*membership)[v1] = VECTOR(dominant_labels)[k]; - } - } - - /* Clear the nonzero elements in label_counters */ - num_neis = igraph_vector_int_size(&nonzero_labels); - for (j = 0; j < num_neis; j++) { - VECTOR(label_counters)[VECTOR(nonzero_labels)[j]] = 0; - } - } - RNG_END(); - - /* Alternating between control iterations and label updating iterations */ - control_iteration = !control_iteration; + default: + IGRAPH_ERROR("Invalid igraph_lpa_variant_t.", IGRAPH_EINVAL); } - if (weights) { - igraph_inclist_destroy(&il); - } else { - igraph_adjlist_destroy(&al); - } - IGRAPH_FINALLY_CLEAN(1); + /* Permute labels in increasing order */ + igraph_vector_int_t relabel_label; + IGRAPH_CHECK(igraph_vector_int_init(&relabel_label, no_of_nodes)); + igraph_vector_int_fill(&relabel_label, -1); + IGRAPH_FINALLY(igraph_vector_int_destroy, &relabel_label); - /* Shift back the membership vector, permute labels in increasing order */ - /* We recycle label_counters here :) and use it as an integer vector from now on */ - igraph_vector_fill(&label_counters, -1); j = 0; unlabelled_left = false; for (i = 0; i < no_of_nodes; i++) { - k = VECTOR(*membership)[i] - 1; + k = VECTOR(*membership)[i]; if (k >= 0) { - if (VECTOR(label_counters)[k] == -1) { + if (VECTOR(relabel_label)[k] == -1) { /* We have seen this label for the first time */ - VECTOR(label_counters)[k] = j; + VECTOR(relabel_label)[k] = j; k = j; j++; } else { - k = (igraph_integer_t) VECTOR(label_counters)[k]; + k = VECTOR(relabel_label)[k]; } } else { /* This is an unlabeled vertex */ @@ -386,9 +681,6 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, VECTOR(*membership)[i] = k; } - /* From this point on, unlabelled nodes are represented with -1 (no longer 0). */ -#define IS_UNLABELLED(x) (VECTOR(*membership)[x] < 0) - /* If any nodes are left unlabelled, we assign the remaining labels to them, * as well as to all unlabelled nodes reachable from them. * @@ -401,9 +693,25 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, igraph_dqueue_int_t q; igraph_vector_int_t neis; - /* 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_t node_order; + /* Initialize node ordering vector with only the not fixed nodes */ + if (fixed) { + no_of_not_fixed_nodes = 0; + IGRAPH_VECTOR_INT_INIT_FINALLY(&node_order, no_of_nodes); + for (i = 0; i < no_of_nodes; i++) { + if (!VECTOR(*fixed)[i]) { + VECTOR(node_order)[no_of_not_fixed_nodes] = i; + no_of_not_fixed_nodes++; + } + } + IGRAPH_CHECK(igraph_vector_int_resize(&node_order, no_of_not_fixed_nodes)); + } else { + IGRAPH_CHECK(igraph_vector_int_init_range(&node_order, 0, no_of_nodes)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &node_order); + no_of_not_fixed_nodes = no_of_nodes; + } + /* Shuffle the node ordering vector */ + igraph_vector_int_shuffle(&node_order); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); @@ -417,13 +725,13 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, if (IS_UNLABELLED(v)) { /* If yes, we label it, and do a BFS to apply the same label * to all other unlabelled nodes reachable from it */ - igraph_dqueue_int_push(&q, v); + IGRAPH_CHECK(igraph_dqueue_int_push(&q, v)); VECTOR(*membership)[v] = j; while (!igraph_dqueue_int_empty(&q)) { igraph_integer_t ni, num_neis; igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); num_neis = igraph_vector_int_size(&neis); for (ni = 0; ni < num_neis; ++ni) { @@ -440,14 +748,12 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, igraph_vector_int_destroy(&neis); igraph_dqueue_int_destroy(&q); - IGRAPH_FINALLY_CLEAN(2); + igraph_vector_int_destroy(&node_order); + IGRAPH_FINALLY_CLEAN(3); } - igraph_vector_int_destroy(&node_order); - igraph_vector_destroy(&label_counters); - igraph_vector_int_destroy(&dominant_labels); - igraph_vector_int_destroy(&nonzero_labels); - IGRAPH_FINALLY_CLEAN(4); + igraph_vector_int_destroy(&relabel_label); + IGRAPH_FINALLY_CLEAN(1); if (fixed != fixed_copy) { igraph_vector_bool_destroy(fixed_copy); diff --git a/src/vendor/cigraph/src/community/leading_eigenvector.c b/src/vendor/cigraph/src/community/leading_eigenvector.c index 074dd6ccd93..2d188a34b9c 100644 --- a/src/vendor/cigraph/src/community/leading_eigenvector.c +++ b/src/vendor/cigraph/src/community/leading_eigenvector.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2020 The igraph development team @@ -244,12 +242,11 @@ static void igraph_i_error_handler_none(const char *reason, const char *file, * https://doi.org/10.1103/PhysRevE.74.036104 * * \param graph The input graph. Edge directions will be ignored. - * \param weights The weights of the edges, or a null pointer for - * unweighted graphs. + * \param weights The weights of the edges, or \c NULL for unweighted graphs. * \param merges The result of the algorithm, a matrix containing the * information about the splits performed. The matrix is built in * the opposite way however, it is like the result of an - * agglomerative algorithm. Unlike with most other hierarchicaly + * agglomerative algorithm. Unlike with most other hierarchical * community detection functions in igraph, the integers in this matrix * represent community indices, not vertex indices. If at the end of * the algorithm (after \p steps steps was done) there are p @@ -266,7 +263,7 @@ static void igraph_i_error_handler_none(const char *reason, const char *file, * This argument is ignored if it is \c NULL. This argument can * also be used to supply a starting configuration for the community * finding, in the format of a membership vector. In this case the - * \p start argument must be set to 1. + * \p start argument must be set to \c true. * \param steps The maximum number of steps to perform. It might * happen that some component (or the whole network) has no * underlying community structure and no further steps can be @@ -342,7 +339,7 @@ igraph_error_t igraph_community_leading_eigenvector( igraph_bool_t start, igraph_vector_t *eigenvalues, igraph_vector_list_t *eigenvectors, - igraph_vector_t *history, + igraph_vector_int_t *history, igraph_community_leading_eigenvector_callback_t *callback, void *callback_extra) { @@ -381,7 +378,7 @@ igraph_error_t igraph_community_leading_eigenvector( if (start && membership && igraph_vector_int_size(membership) != no_of_nodes) { - IGRAPH_ERROR("Supplied memberhsip vector length does not match number of vertices.", + IGRAPH_ERROR("Supplied membership vector length does not match number of vertices.", IGRAPH_EINVAL); } @@ -415,19 +412,19 @@ igraph_error_t igraph_community_leading_eigenvector( if (!start) { /* Calculate the weakly connected components in the graph and use them as * an initial split */ - IGRAPH_CHECK(igraph_connected_components(graph, mymembership, &idx, 0, IGRAPH_WEAK)); + IGRAPH_CHECK(igraph_connected_components(graph, mymembership, &idx, NULL, IGRAPH_WEAK)); communities = igraph_vector_int_size(&idx); if (history) { - IGRAPH_CHECK(igraph_vector_push_back(history, + IGRAPH_CHECK(igraph_vector_int_push_back(history, IGRAPH_LEVC_HIST_START_FULL)); } } else { /* Just create the idx vector for the given membership vector */ communities = igraph_vector_int_max(mymembership) + 1; if (history) { - IGRAPH_CHECK(igraph_vector_push_back(history, + IGRAPH_CHECK(igraph_vector_int_push_back(history, IGRAPH_LEVC_HIST_START_GIVEN)); - IGRAPH_CHECK(igraph_vector_push_back(history, communities)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, communities)); } IGRAPH_CHECK(igraph_vector_int_resize(&idx, communities)); igraph_vector_int_null(&idx); @@ -457,8 +454,8 @@ igraph_error_t igraph_community_leading_eigenvector( IGRAPH_CHECK(igraph_vector_list_push_back_new(eigenvectors, NULL)); } if (history) { - IGRAPH_CHECK(igraph_vector_push_back(history, IGRAPH_LEVC_HIST_SPLIT)); - IGRAPH_CHECK(igraph_vector_push_back(history, i - 1)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, IGRAPH_LEVC_HIST_SPLIT)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, i - 1)); } } staken = communities - 1; @@ -541,27 +538,33 @@ igraph_error_t igraph_community_leading_eigenvector( * convergence in most cases. */ options->start = 1; options->mxiter = options->mxiter > 10000 ? options->mxiter : 10000; /* use more iterations, we've had convergence problems with 3000 */ - RNG_BEGIN(); + for (i = 0; i < options->n; i++) { storage.resid[i] = (i % 2 ? 1 : -1) + RNG_UNIF(-0.1, 0.1); } - 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; igraph_error_handler_t *errh = igraph_set_error_handler(igraph_i_error_handler_none); - retval = igraph_arpack_rssolve(arpcb1, &extra, options, &storage, /*values=*/ 0, /*vectors=*/ 0); + retval = igraph_arpack_rssolve(arpcb1, &extra, options, &storage, /*values=*/ NULL, /*vectors=*/ NULL); igraph_set_error_handler(errh); - if (retval != IGRAPH_SUCCESS && retval != IGRAPH_ARPACK_MAXIT && retval != IGRAPH_ARPACK_NOSHIFT) { - IGRAPH_ERROR("ARPACK call failed", retval); + if (retval == IGRAPH_EARPACK) { + /* TODO(ntamas): get last ARPACK error code. Some errors are OK. */ + igraph_arpack_error_t arpack_error = igraph_arpack_get_last_error(); + if (arpack_error != IGRAPH_ARPACK_MAXIT && arpack_error != IGRAPH_ARPACK_NOSHIFT) { + IGRAPH_ERROR(igraph_arpack_error_to_string(arpack_error), IGRAPH_EARPACK); + } + } else if (retval != IGRAPH_SUCCESS) { + IGRAPH_ERROR("Leading eigenvector calculation failed.", retval); } } if (options->nconv < 1) { - IGRAPH_ERROR("ARPACK did not converge", IGRAPH_ARPACK_FAILED); + IGRAPH_ERROR(igraph_arpack_error_to_string(IGRAPH_ARPACK_FAILED), IGRAPH_EARPACK); } /* Ok, we have the leading eigenvector of the modularity matrix */ @@ -628,9 +631,9 @@ igraph_error_t igraph_community_leading_eigenvector( if (storage.d[0] <= 0) { if (history) { - IGRAPH_CHECK(igraph_vector_push_back(history, + IGRAPH_CHECK(igraph_vector_int_push_back(history, IGRAPH_LEVC_HIST_FAILED)); - IGRAPH_CHECK(igraph_vector_push_back(history, comm)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, comm)); } continue; } @@ -647,9 +650,9 @@ igraph_error_t igraph_community_leading_eigenvector( } if (l == 0 || l == size) { if (history) { - IGRAPH_CHECK(igraph_vector_push_back(history, + IGRAPH_CHECK(igraph_vector_int_push_back(history, IGRAPH_LEVC_HIST_FAILED)); - IGRAPH_CHECK(igraph_vector_push_back(history, comm)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, comm)); } continue; } @@ -662,9 +665,9 @@ igraph_error_t igraph_community_leading_eigenvector( } if (mod <= 1e-8) { if (history) { - IGRAPH_CHECK(igraph_vector_push_back(history, + IGRAPH_CHECK(igraph_vector_int_push_back(history, IGRAPH_LEVC_HIST_FAILED)); - IGRAPH_CHECK(igraph_vector_push_back(history, comm)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, comm)); } continue; } @@ -683,8 +686,8 @@ igraph_error_t igraph_community_leading_eigenvector( IGRAPH_CHECK(igraph_vector_push_back(&mymerges, comm)); IGRAPH_CHECK(igraph_vector_push_back(&mymerges, communities - 1)); if (history) { - IGRAPH_CHECK(igraph_vector_push_back(history, IGRAPH_LEVC_HIST_SPLIT)); - IGRAPH_CHECK(igraph_vector_push_back(history, comm)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, IGRAPH_LEVC_HIST_SPLIT)); + IGRAPH_CHECK(igraph_vector_int_push_back(history, comm)); } /* Store the resulting communities in the queue if needed */ @@ -817,7 +820,7 @@ igraph_error_t igraph_le_community_to_membership(const igraph_matrix_int_t *merg } } - IGRAPH_CHECK(igraph_community_to_membership(merges, components, steps, &fake_memb, 0)); + IGRAPH_CHECK(igraph_community_to_membership(merges, components, steps, &fake_memb, NULL)); /* Ok, now we have the membership of the initial components, rewrite the original membership vector. */ diff --git a/src/vendor/cigraph/src/community/leiden.c b/src/vendor/cigraph/src/community/leiden.c index 1231c5ce851..ed02fed9bec 100644 --- a/src/vendor/cigraph/src/community/leiden.c +++ b/src/vendor/cigraph/src/community/leiden.c @@ -1,9 +1,6 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2020-2025 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 @@ -16,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #include "igraph_community.h" @@ -37,73 +31,84 @@ #include "core/interruption.h" -/* Move nodes in order to improve the quality of a partition. +/* Move vertices in order to improve the quality of a partition. * - * This function considers each node and greedily moves it to a neighboring + * This function considers each vertex and greedily moves it to a neighboring * community that maximizes the improvement in the quality of a partition. * Only moves that strictly improve the quality are considered. * - * The nodes are examined in a queue, and initially all nodes are put in the - * queue in a random order. Nodes are popped from the queue when they are - * examined, and only neighbors of nodes that are moved (which are not part of - * the cluster the node was moved to) are pushed to the queue again. + * The vertices are examined in a queue, and initially all vertices are put in the + * queue in a random order. Vertices are popped from the queue when they are + * examined, and only neighbors of vertices that are moved (which are not part of + * the cluster the vertex was moved to) are pushed to the queue again. * - * The \c membership vector is used as the starting point to move around nodes, + * The \p membership vector is used as the starting point to move around vertices, * and is updated in-place. * */ -static igraph_error_t igraph_i_community_leiden_fastmovenodes( +static igraph_error_t leiden_fastmove_vertices( const igraph_t *graph, - const igraph_inclist_t *edges_per_node, - const igraph_vector_t *edge_weights, const igraph_vector_t *node_weights, - const igraph_real_t resolution_parameter, + const igraph_inclist_t *edges_per_vertex, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_out_weights, + const igraph_vector_t *vertex_in_weights, + const igraph_real_t resolution, igraph_integer_t *nb_clusters, igraph_vector_int_t *membership, igraph_bool_t *changed) { - igraph_dqueue_int_t unstable_nodes; - igraph_real_t max_diff = 0.0, diff = 0.0; const igraph_integer_t n = igraph_vcount(graph); - igraph_bitset_t neighbor_cluster_added, node_is_stable; - igraph_vector_t cluster_weights, edge_weights_per_cluster; + const igraph_bool_t directed = (vertex_in_weights != NULL); + igraph_dqueue_int_t unstable_vertices; + igraph_real_t max_diff, diff; + igraph_bitset_t neighbor_cluster_added, vertex_is_stable; + igraph_vector_t cluster_out_weights, cluster_in_weights; + igraph_vector_t edge_weights_per_cluster; igraph_vector_int_t neighbor_clusters; - igraph_vector_int_t node_order; - igraph_vector_int_t nb_nodes_per_cluster; + igraph_vector_int_t vertex_order; + igraph_vector_int_t nb_vertices_per_cluster; igraph_stack_int_t empty_clusters; igraph_integer_t c, nb_neigh_clusters; int iter = 0; - /* Initialize queue of unstable nodes and whether node is stable. Only - * unstable nodes are in the queue. */ - IGRAPH_BITSET_INIT_FINALLY(&node_is_stable, n); + /* Initialize queue of unstable vertices and whether vertex is stable. Only + * unstable vertices are in the queue. */ + IGRAPH_BITSET_INIT_FINALLY(&vertex_is_stable, n); - IGRAPH_DQUEUE_INT_INIT_FINALLY(&unstable_nodes, n); + IGRAPH_DQUEUE_INT_INIT_FINALLY(&unstable_vertices, n); - /* 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)); + /* Shuffle vertices */ + IGRAPH_CHECK(igraph_vector_int_init_range(&vertex_order, 0, n)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &vertex_order); + igraph_vector_int_shuffle(&vertex_order); /* Add to the queue */ for (igraph_integer_t i = 0; i < n; i++) { - IGRAPH_CHECK(igraph_dqueue_int_push(&unstable_nodes, VECTOR(node_order)[i])); + IGRAPH_CHECK(igraph_dqueue_int_push(&unstable_vertices, VECTOR(vertex_order)[i])); } - /* Initialize cluster weights and nb nodes */ - IGRAPH_VECTOR_INIT_FINALLY(&cluster_weights, n); - IGRAPH_VECTOR_INT_INIT_FINALLY(&nb_nodes_per_cluster, n); + /* Initialize cluster weights and nb vertices */ + IGRAPH_VECTOR_INIT_FINALLY(&cluster_out_weights, n); + if (directed) { + IGRAPH_VECTOR_INIT_FINALLY(&cluster_in_weights, n); + } + IGRAPH_VECTOR_INT_INIT_FINALLY(&nb_vertices_per_cluster, n); for (igraph_integer_t i = 0; i < n; i++) { c = VECTOR(*membership)[i]; - VECTOR(cluster_weights)[c] += VECTOR(*node_weights)[i]; - VECTOR(nb_nodes_per_cluster)[c] += 1; + VECTOR(cluster_out_weights)[c] += VECTOR(*vertex_out_weights)[i]; + if (directed) { + VECTOR(cluster_in_weights)[c] += VECTOR(*vertex_in_weights)[i]; + } + VECTOR(nb_vertices_per_cluster)[c] += 1; } /* Initialize empty clusters */ IGRAPH_STACK_INT_INIT_FINALLY(&empty_clusters, n); - for (c = 0; c < n; c++) - if (VECTOR(nb_nodes_per_cluster)[c] == 0) { + for (c = 0; c < n; c++) { + if (VECTOR(nb_vertices_per_cluster)[c] == 0) { IGRAPH_CHECK(igraph_stack_int_push(&empty_clusters, c)); } + } /* Initialize vectors to be used in calculating differences */ IGRAPH_VECTOR_INIT_FINALLY(&edge_weights_per_cluster, n); @@ -113,16 +118,19 @@ static igraph_error_t igraph_i_community_leiden_fastmovenodes( IGRAPH_VECTOR_INT_INIT_FINALLY(&neighbor_clusters, n); /* Iterate while the queue is not empty */ - while (!igraph_dqueue_int_empty(&unstable_nodes)) { - igraph_integer_t v = igraph_dqueue_int_pop(&unstable_nodes); + while (!igraph_dqueue_int_empty(&unstable_vertices)) { + igraph_integer_t v = igraph_dqueue_int_pop(&unstable_vertices); igraph_integer_t best_cluster, current_cluster = VECTOR(*membership)[v]; igraph_integer_t degree; igraph_vector_int_t *edges; - /* Remove node from current cluster */ - VECTOR(cluster_weights)[current_cluster] -= VECTOR(*node_weights)[v]; - VECTOR(nb_nodes_per_cluster)[current_cluster]--; - if (VECTOR(nb_nodes_per_cluster)[current_cluster] == 0) { + /* Remove vertex from current cluster */ + VECTOR(cluster_out_weights)[current_cluster] -= VECTOR(*vertex_out_weights)[v]; + if (directed) { + VECTOR(cluster_in_weights)[current_cluster] -= VECTOR(*vertex_in_weights)[v]; + } + VECTOR(nb_vertices_per_cluster)[current_cluster]--; + if (VECTOR(nb_vertices_per_cluster)[current_cluster] == 0) { IGRAPH_CHECK(igraph_stack_int_push(&empty_clusters, current_cluster)); } @@ -133,7 +141,7 @@ static igraph_error_t igraph_i_community_leiden_fastmovenodes( nb_neigh_clusters = 1; /* Determine the edge weight to each neighboring cluster */ - edges = igraph_inclist_get(edges_per_node, v); + edges = igraph_inclist_get(edges_per_vertex, v); degree = igraph_vector_int_size(edges); for (igraph_integer_t i = 0; i < degree; i++) { igraph_integer_t e = VECTOR(*edges)[i]; @@ -150,10 +158,23 @@ static igraph_error_t igraph_i_community_leiden_fastmovenodes( /* Calculate maximum diff */ best_cluster = current_cluster; - max_diff = VECTOR(edge_weights_per_cluster)[current_cluster] - VECTOR(*node_weights)[v] * VECTOR(cluster_weights)[current_cluster] * resolution_parameter; + max_diff = VECTOR(edge_weights_per_cluster)[current_cluster]; + if (directed) { + max_diff -= + (VECTOR(*vertex_in_weights)[v] * VECTOR(cluster_out_weights)[current_cluster] + + VECTOR(*vertex_out_weights)[v] * VECTOR(cluster_in_weights)[current_cluster]) * resolution; + } else { + max_diff -= VECTOR(*vertex_out_weights)[v] * VECTOR(cluster_out_weights)[current_cluster] * resolution; + } for (igraph_integer_t i = 0; i < nb_neigh_clusters; i++) { c = VECTOR(neighbor_clusters)[i]; - diff = VECTOR(edge_weights_per_cluster)[c] - VECTOR(*node_weights)[v] * VECTOR(cluster_weights)[c] * resolution_parameter; + diff = VECTOR(edge_weights_per_cluster)[c]; + if (directed) { + diff -= (VECTOR(*vertex_out_weights)[v] * VECTOR(cluster_in_weights)[c] + + VECTOR(*vertex_in_weights)[v] * VECTOR(cluster_out_weights)[c]) * resolution; + } else { + diff -= VECTOR(*vertex_out_weights)[v] * VECTOR(cluster_out_weights)[c] * resolution; + } /* Only consider strictly improving moves. * Note that this is important in considering convergence. */ @@ -165,15 +186,18 @@ static igraph_error_t igraph_i_community_leiden_fastmovenodes( IGRAPH_BIT_CLEAR(neighbor_cluster_added, c); } - /* Move node to best cluster */ - VECTOR(cluster_weights)[best_cluster] += VECTOR(*node_weights)[v]; - VECTOR(nb_nodes_per_cluster)[best_cluster]++; + /* Move vertex to best cluster */ + VECTOR(cluster_out_weights)[best_cluster] += VECTOR(*vertex_out_weights)[v]; + if (directed) { + VECTOR(cluster_in_weights)[best_cluster] += VECTOR(*vertex_in_weights)[v]; + } + VECTOR(nb_vertices_per_cluster)[best_cluster]++; if (best_cluster == igraph_stack_int_top(&empty_clusters)) { igraph_stack_int_pop(&empty_clusters); } - /* Mark node as stable */ - IGRAPH_BIT_SET(node_is_stable, v); + /* Mark vertex as stable */ + IGRAPH_BIT_SET(vertex_is_stable, v); /* Add stable neighbours that are not part of the new cluster to the queue */ if (best_cluster != current_cluster) { @@ -183,9 +207,9 @@ static igraph_error_t igraph_i_community_leiden_fastmovenodes( for (igraph_integer_t i = 0; i < degree; i++) { igraph_integer_t e = VECTOR(*edges)[i]; igraph_integer_t u = IGRAPH_OTHER(graph, e, v); - if (IGRAPH_BIT_TEST(node_is_stable, u) && VECTOR(*membership)[u] != best_cluster) { - IGRAPH_CHECK(igraph_dqueue_int_push(&unstable_nodes, u)); - IGRAPH_BIT_CLEAR(node_is_stable, u); + if (IGRAPH_BIT_TEST(vertex_is_stable, u) && VECTOR(*membership)[u] != best_cluster) { + IGRAPH_CHECK(igraph_dqueue_int_push(&unstable_vertices, u)); + IGRAPH_BIT_CLEAR(vertex_is_stable, u); } } } @@ -199,30 +223,36 @@ static igraph_error_t igraph_i_community_leiden_fastmovenodes( igraph_bitset_destroy(&neighbor_cluster_added); igraph_vector_destroy(&edge_weights_per_cluster); igraph_stack_int_destroy(&empty_clusters); - igraph_vector_int_destroy(&nb_nodes_per_cluster); - igraph_vector_destroy(&cluster_weights); - igraph_vector_int_destroy(&node_order); - igraph_dqueue_int_destroy(&unstable_nodes); - igraph_bitset_destroy(&node_is_stable); - IGRAPH_FINALLY_CLEAN(9); + igraph_vector_int_destroy(&nb_vertices_per_cluster); + if (directed) igraph_vector_destroy(&cluster_in_weights); + igraph_vector_destroy(&cluster_out_weights); + igraph_vector_int_destroy(&vertex_order); + igraph_dqueue_int_destroy(&unstable_vertices); + igraph_bitset_destroy(&vertex_is_stable); + if (directed) { + IGRAPH_FINALLY_CLEAN(10); + } else { + IGRAPH_FINALLY_CLEAN(9); + } return IGRAPH_SUCCESS; } /* Clean a refined membership vector. * - * This function examines all nodes in \c node_subset and updates \c - * refined_membership to ensure that the clusters are numbered consecutively, - * starting from \c nb_refined_clusters. The \c nb_refined_clusters is also - * updated itself. If C is the initial \c nb_refined_clusters and C' the - * resulting \c nb_refined_clusters, then nodes in \c node_subset are numbered + * This function examines all vertices in \p vertex_subset and updates + * \p refined_membership to ensure that the clusters are numbered consecutively, + * starting from \p nb_refined_clusters. The \p nb_refined_clusters is also + * updated itself. If C is the initial \p nb_refined_clusters and C' the + * resulting \p nb_refined_clusters, then vertices in \p vertex_subset are numbered * C, C + 1, ..., C' - 1. */ -static igraph_error_t igraph_i_community_leiden_clean_refined_membership( - const igraph_vector_int_t* node_subset, +static igraph_error_t leiden_clean_refined_membership( + const igraph_vector_int_t* vertex_subset, igraph_vector_int_t *refined_membership, igraph_integer_t* nb_refined_clusters) { - const igraph_integer_t n = igraph_vector_int_size(node_subset); + + const igraph_integer_t n = igraph_vector_int_size(vertex_subset); igraph_vector_int_t new_cluster; IGRAPH_VECTOR_INT_INIT_FINALLY(&new_cluster, n); @@ -231,7 +261,7 @@ static igraph_error_t igraph_i_community_leiden_clean_refined_membership( * indicates that no membership was assigned yet. */ *nb_refined_clusters += 1; for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(*node_subset)[i]; + igraph_integer_t v = VECTOR(*vertex_subset)[i]; igraph_integer_t c = VECTOR(*refined_membership)[v]; if (VECTOR(new_cluster)[c] == 0) { VECTOR(new_cluster)[c] = *nb_refined_clusters; @@ -241,7 +271,7 @@ static igraph_error_t igraph_i_community_leiden_clean_refined_membership( /* Assign new cluster */ for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(*node_subset)[i]; + igraph_integer_t v = VECTOR(*vertex_subset)[i]; igraph_integer_t c = VECTOR(*refined_membership)[v]; VECTOR(*refined_membership)[v] = VECTOR(new_cluster)[c] - 1; } @@ -254,17 +284,17 @@ static igraph_error_t igraph_i_community_leiden_clean_refined_membership( return IGRAPH_SUCCESS; } -/* Merge nodes for a subset of the nodes. This is used to refine a partition. +/* Merge vertices for a subset of the vertices. This is used to refine a partition. * - * The nodes included in \c node_subset are assumed to be the nodes i for which + * The vertices included in \p vertex_subset are assumed to be the vertices i for which * membership[i] = cluster_subset. * - * All nodes in \c node_subset are initialized to a singleton partition in \c + * All vertices in \p vertex_subset are initialized to a singleton partition in \p * refined_membership. Only singleton clusters can be merged if they are - * sufficiently well connected to the current subgraph induced by \c - * node_subset. + * sufficiently well connected to the current subgraph induced by \p + * vertex_subset. * - * We only examine each node once. Instead of greedily choosing the maximum + * We only examine each vertex once. Instead of greedily choosing the maximum * possible cluster to merge with, the cluster is chosen randomly among all * possibilities that do not decrease the quality of the partition. The * probability of choosing a certain cluster is proportional to exp(diff/beta). @@ -272,57 +302,70 @@ static igraph_error_t igraph_i_community_leiden_clean_refined_membership( * improvement. For beta to infinity this converges to a uniform distribution * among all eligible clusters. * - * The \c refined_membership is updated for node in \c node_subset. The number - * of refined clusters, \c nb_refined_clusters is used to set the actual refined + * The \p refined_membership is updated for vertex in \p vertex_subset. The number + * of refined clusters, \p nb_refined_clusters is used to set the actual refined * cluster membership and is updated after this routine. Within each cluster - * (i.e. for a given \c node_subset), the refined membership is initially simply - * set to 0, ..., n - 1 (for n nodes in \c node_subset). However, for each \c - * node_subset the refined membership should of course be unique. Hence, after - * merging, the refined membership starts with \c nb_refined_clusters, which is - * also updated to ensure that the resulting \c nb_refined_clusters counts all + * (i.e. for a given \p vertex_subset), the refined membership is initially simply + * set to 0, ..., n - 1 (for n vertices in \p vertex_subset). However, for each \p + * vertex_subset the refined membership should of course be unique. Hence, after + * merging, the refined membership starts with \p nb_refined_clusters, which is + * also updated to ensure that the resulting \p nb_refined_clusters counts all * refined clusters that have already been processed. See - * igraph_i_community_leiden_clean_refined_membership for more information about + * leiden_clean_refined_membership for more information about * this aspect. */ -static igraph_error_t igraph_i_community_leiden_mergenodes( +static igraph_error_t leiden_merge_vertices( const igraph_t *graph, - const igraph_inclist_t *edges_per_node, - const igraph_vector_t *edge_weights, const igraph_vector_t *node_weights, - const igraph_vector_int_t *node_subset, + const igraph_inclist_t *edges_per_vertex, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_out_weights, + const igraph_vector_t *vertex_in_weights, + const igraph_vector_int_t *vertex_subset, const igraph_vector_int_t *membership, const igraph_integer_t cluster_subset, - const igraph_real_t resolution_parameter, + const igraph_real_t resolution, const igraph_real_t beta, igraph_integer_t *nb_refined_clusters, igraph_vector_int_t *refined_membership) { - igraph_vector_int_t node_order; + + const igraph_bool_t directed = (vertex_in_weights != NULL); + igraph_vector_int_t vertex_order; igraph_bitset_t non_singleton_cluster, neighbor_cluster_added; - igraph_real_t max_diff, total_cum_trans_diff, diff = 0.0, total_node_weight = 0.0; - const igraph_integer_t n = igraph_vector_int_size(node_subset); - igraph_vector_t cluster_weights, cum_trans_diff, edge_weights_per_cluster, external_edge_weight_per_cluster_in_subset; + igraph_real_t max_diff, total_cum_trans_diff, diff; + igraph_real_t total_vertex_out_weight = 0.0, total_vertex_in_weight = 0.0; + const igraph_integer_t n = igraph_vector_int_size(vertex_subset); + igraph_vector_t cluster_out_weights, cluster_in_weights; + igraph_vector_t cum_trans_diff, edge_weights_per_cluster, external_edge_weight_per_cluster_in_subset; igraph_vector_int_t neighbor_clusters; - igraph_vector_int_t *edges, nb_nodes_per_cluster; + igraph_vector_int_t *edges, nb_vertices_per_cluster; igraph_integer_t degree, nb_neigh_clusters; /* Initialize cluster weights */ - IGRAPH_VECTOR_INIT_FINALLY(&cluster_weights, n); + IGRAPH_VECTOR_INIT_FINALLY(&cluster_out_weights, n); + if (directed) { + IGRAPH_VECTOR_INIT_FINALLY(&cluster_in_weights, n); + } - /* Initialize number of nodes per cluster */ - IGRAPH_VECTOR_INT_INIT_FINALLY(&nb_nodes_per_cluster, n); + /* Initialize number of vertices per cluster */ + IGRAPH_VECTOR_INT_INIT_FINALLY(&nb_vertices_per_cluster, n); /* Initialize external edge weight per cluster in subset */ IGRAPH_VECTOR_INIT_FINALLY(&external_edge_weight_per_cluster_in_subset, n); /* Initialize administration for a singleton partition */ for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(*node_subset)[i]; + igraph_integer_t v = VECTOR(*vertex_subset)[i]; VECTOR(*refined_membership)[v] = i; - VECTOR(cluster_weights)[i] += VECTOR(*node_weights)[v]; - VECTOR(nb_nodes_per_cluster)[i] += 1; - total_node_weight += VECTOR(*node_weights)[v]; + VECTOR(cluster_out_weights)[i] += VECTOR(*vertex_out_weights)[v]; + total_vertex_out_weight += VECTOR(*vertex_out_weights)[v]; + if (directed) { + VECTOR(cluster_in_weights)[i] += VECTOR(*vertex_in_weights)[v]; + total_vertex_in_weight += VECTOR(*vertex_in_weights)[v]; + } + VECTOR(nb_vertices_per_cluster)[i] += 1; /* Find out neighboring clusters */ - edges = igraph_inclist_get(edges_per_node, v); + edges = igraph_inclist_get(edges_per_vertex, v); degree = igraph_vector_int_size(edges); for (igraph_integer_t j = 0; j < degree; j++) { igraph_integer_t e = VECTOR(*edges)[j]; @@ -333,10 +376,10 @@ 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)); + /* Shuffle vertices */ + IGRAPH_CHECK(igraph_vector_int_init_copy(&vertex_order, vertex_subset)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &vertex_order); + igraph_vector_int_shuffle(&vertex_order); /* Initialize non singleton clusters */ IGRAPH_BITSET_INIT_FINALLY(&non_singleton_cluster, n); @@ -351,22 +394,32 @@ static igraph_error_t igraph_i_community_leiden_mergenodes( /* Initialize cumulative transformed difference */ IGRAPH_VECTOR_INIT_FINALLY(&cum_trans_diff, n); - RNG_BEGIN(); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(node_order)[i]; + igraph_integer_t v = VECTOR(vertex_order)[i]; igraph_integer_t chosen_cluster, best_cluster, current_cluster = VECTOR(*refined_membership)[v]; + igraph_real_t vertex_weight_prod; + + if (directed) { + vertex_weight_prod = + VECTOR(cluster_out_weights)[current_cluster] * (total_vertex_in_weight - VECTOR(cluster_in_weights)[current_cluster]) + + VECTOR(cluster_in_weights)[current_cluster] * (total_vertex_out_weight - VECTOR(cluster_out_weights)[current_cluster]); + } else { + vertex_weight_prod = VECTOR(cluster_out_weights)[current_cluster] * (total_vertex_out_weight - VECTOR(cluster_out_weights)[current_cluster]); + } if (!IGRAPH_BIT_TEST(non_singleton_cluster, current_cluster) && (VECTOR(external_edge_weight_per_cluster_in_subset)[current_cluster] >= - VECTOR(cluster_weights)[current_cluster] * (total_node_weight - VECTOR(cluster_weights)[current_cluster]) * resolution_parameter)) { - /* Remove node from current cluster, which is then a singleton by + vertex_weight_prod * resolution)) { + /* Remove vertex from current cluster, which is then a singleton by * definition. */ - VECTOR(cluster_weights)[current_cluster] = 0.0; - VECTOR(nb_nodes_per_cluster)[current_cluster] = 0; + VECTOR(cluster_out_weights)[current_cluster] = 0.0; + if (directed) { + VECTOR(cluster_in_weights)[current_cluster] = 0.0; + } + VECTOR(nb_vertices_per_cluster)[current_cluster] = 0; /* Find out neighboring clusters */ - edges = igraph_inclist_get(edges_per_node, v); + edges = igraph_inclist_get(edges_per_vertex, v); degree = igraph_vector_int_size(edges); /* Also add current cluster to ensure it can be chosen. */ @@ -392,8 +445,24 @@ static igraph_error_t igraph_i_community_leiden_mergenodes( total_cum_trans_diff = 0.0; for (igraph_integer_t j = 0; j < nb_neigh_clusters; j++) { igraph_integer_t c = VECTOR(neighbor_clusters)[j]; - if (VECTOR(external_edge_weight_per_cluster_in_subset)[c] >= VECTOR(cluster_weights)[c] * (total_node_weight - VECTOR(cluster_weights)[c]) * resolution_parameter) { - diff = VECTOR(edge_weights_per_cluster)[c] - VECTOR(*node_weights)[v] * VECTOR(cluster_weights)[c] * resolution_parameter; + + if (directed) { + vertex_weight_prod = + VECTOR(cluster_out_weights)[c] * (total_vertex_in_weight - VECTOR(cluster_in_weights)[c]) + + VECTOR(cluster_in_weights)[c] * (total_vertex_out_weight - VECTOR(cluster_out_weights)[c]); + } else { + vertex_weight_prod = VECTOR(cluster_out_weights)[c] * (total_vertex_out_weight - VECTOR(cluster_out_weights)[c]); + } + + if (VECTOR(external_edge_weight_per_cluster_in_subset)[c] >= vertex_weight_prod * resolution) { + diff = VECTOR(edge_weights_per_cluster)[c]; + if (directed) { + diff -= (VECTOR(*vertex_out_weights)[v] * VECTOR(cluster_in_weights)[c] + + VECTOR(*vertex_in_weights)[v] * VECTOR(cluster_out_weights)[c]) * resolution; + } else { + diff -= VECTOR(*vertex_out_weights)[v] * VECTOR(cluster_out_weights)[c] * resolution; + } + if (diff > max_diff) { best_cluster = c; @@ -412,7 +481,7 @@ static igraph_error_t igraph_i_community_leiden_mergenodes( IGRAPH_BIT_CLEAR(neighbor_cluster_added, c); } - /* Determine the neighboring cluster to which the currently selected node + /* Determine the neighboring cluster to which the currently selected vertex * will be moved. */ if (total_cum_trans_diff < IGRAPH_INFINITY) { @@ -424,9 +493,12 @@ static igraph_error_t igraph_i_community_leiden_mergenodes( chosen_cluster = best_cluster; } - /* Move node to randomly chosen cluster */ - VECTOR(cluster_weights)[chosen_cluster] += VECTOR(*node_weights)[v]; - VECTOR(nb_nodes_per_cluster)[chosen_cluster]++; + /* Move vertex to randomly chosen cluster */ + VECTOR(cluster_out_weights)[chosen_cluster] += VECTOR(*vertex_out_weights)[v]; + if (directed) { + VECTOR(cluster_in_weights)[chosen_cluster] += VECTOR(*vertex_in_weights)[v]; + } + VECTOR(nb_vertices_per_cluster)[chosen_cluster]++; for (igraph_integer_t j = 0; j < degree; j++) { igraph_integer_t e = VECTOR(*edges)[j]; @@ -449,20 +521,23 @@ static igraph_error_t igraph_i_community_leiden_mergenodes( } /* end if singleton and may be merged */ } - RNG_END(); - - IGRAPH_CHECK(igraph_i_community_leiden_clean_refined_membership(node_subset, refined_membership, nb_refined_clusters)); + IGRAPH_CHECK(leiden_clean_refined_membership(vertex_subset, refined_membership, nb_refined_clusters)); igraph_vector_destroy(&cum_trans_diff); igraph_vector_int_destroy(&neighbor_clusters); igraph_bitset_destroy(&neighbor_cluster_added); igraph_vector_destroy(&edge_weights_per_cluster); igraph_bitset_destroy(&non_singleton_cluster); - igraph_vector_int_destroy(&node_order); + igraph_vector_int_destroy(&vertex_order); igraph_vector_destroy(&external_edge_weight_per_cluster_in_subset); - igraph_vector_int_destroy(&nb_nodes_per_cluster); - igraph_vector_destroy(&cluster_weights); - IGRAPH_FINALLY_CLEAN(9); + igraph_vector_int_destroy(&nb_vertices_per_cluster); + if (directed) igraph_vector_destroy(&cluster_in_weights); + igraph_vector_destroy(&cluster_out_weights); + if (directed) { + IGRAPH_FINALLY_CLEAN(10); + } else { + IGRAPH_FINALLY_CLEAN(9); + } return IGRAPH_SUCCESS; } @@ -474,39 +549,53 @@ static igraph_error_t igraph_i_community_leiden_mergenodes( * in the membership vector), and that each item in the list of integer vectors * is empty. */ -static igraph_error_t igraph_i_community_get_clusters(const igraph_vector_int_t *membership, igraph_vector_int_list_t *clusters) { - igraph_integer_t n = igraph_vector_int_size(membership); - igraph_vector_int_t *cluster; +static igraph_error_t leiden_get_clusters( + const igraph_vector_int_t *membership, + igraph_vector_int_list_t *clusters) { + + const igraph_integer_t n = igraph_vector_int_size(membership); for (igraph_integer_t i = 0; i < n; i++) { - /* Get cluster for node i */ - cluster = igraph_vector_int_list_get_ptr(clusters, VECTOR(*membership)[i]); + /* Get cluster for vertex i */ + igraph_vector_int_t *cluster = igraph_vector_int_list_get_ptr(clusters, VECTOR(*membership)[i]); - /* Add node i to cluster vector */ + /* Add vertex i to cluster vector */ IGRAPH_CHECK(igraph_vector_int_push_back(cluster, i)); } return IGRAPH_SUCCESS; } -/* Aggregate the graph based on the \c refined membership while setting the - * membership of each aggregated node according to the \c membership. +/* Aggregate the graph based on the \p refined membership while setting the + * membership of each aggregated vertex according to the \p membership. * * Technically speaking we have that - * aggregated_membership[refined_membership[v]] = membership[v] for each node v. + * aggregated_membership[refined_membership[v]] = membership[v] for each vertex v. * - * The new aggregated graph is returned in \c aggregated_graph. This graph - * object should not yet be initialized, `igraph_create` is called on it, and + * The new aggregated graph is returned in \p aggregated_graph. This graph + * object should not yet be initialized, igraph_create() is called on it, and * responsibility for destroying the object lies with the calling method * - * The remaining results, aggregated_edge_weights, aggregate_node_weights and + * The remaining results, aggregated_edge_weights, aggregate_vertex_weights and * aggregated_membership are all expected to be initialized. * */ -static igraph_error_t igraph_i_community_leiden_aggregate( - const igraph_t *graph, const igraph_inclist_t *edges_per_node, const igraph_vector_t *edge_weights, const igraph_vector_t *node_weights, - const igraph_vector_int_t *membership, const igraph_vector_int_t *refined_membership, const igraph_integer_t nb_refined_clusters, - igraph_t *aggregated_graph, igraph_vector_t *aggregated_edge_weights, igraph_vector_t *aggregated_node_weights, igraph_vector_int_t *aggregated_membership) { +static igraph_error_t leiden_aggregate( + const igraph_t *graph, + const igraph_inclist_t *edges_per_vertex, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_out_weights, + const igraph_vector_t *vertex_in_weights, + const igraph_vector_int_t *membership, + const igraph_vector_int_t *refined_membership, + const igraph_integer_t nb_refined_clusters, + igraph_t *aggregated_graph, + igraph_vector_t *aggregated_edge_weights, + igraph_vector_t *aggregated_vertex_out_weights, + igraph_vector_t *aggregated_vertex_in_weights, + igraph_vector_int_t *aggregated_membership) { + + const igraph_bool_t directed = (vertex_in_weights != NULL); igraph_vector_int_t aggregated_edges; igraph_vector_t edge_weight_to_cluster; igraph_vector_int_list_t refined_clusters; @@ -517,15 +606,18 @@ static igraph_error_t igraph_i_community_leiden_aggregate( /* Get refined clusters */ IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(&refined_clusters, nb_refined_clusters); - IGRAPH_CHECK(igraph_i_community_get_clusters(refined_membership, &refined_clusters)); + IGRAPH_CHECK(leiden_get_clusters(refined_membership, &refined_clusters)); /* Initialize new edges */ IGRAPH_VECTOR_INT_INIT_FINALLY(&aggregated_edges, 0); /* We clear the aggregated edge weights, we will push each new edge weight */ igraph_vector_clear(aggregated_edge_weights); - /* Simply resize the aggregated node weights and membership, they can be set directly */ - IGRAPH_CHECK(igraph_vector_resize(aggregated_node_weights, nb_refined_clusters)); + /* Simply resize the aggregated vertex weights and membership, they can be set directly */ + IGRAPH_CHECK(igraph_vector_resize(aggregated_vertex_out_weights, nb_refined_clusters)); + if (directed) { + IGRAPH_CHECK(igraph_vector_resize(aggregated_vertex_in_weights, nb_refined_clusters)); + } IGRAPH_CHECK(igraph_vector_int_resize(aggregated_membership, nb_refined_clusters)); IGRAPH_VECTOR_INIT_FINALLY(&edge_weight_to_cluster, nb_refined_clusters); @@ -541,11 +633,14 @@ static igraph_error_t igraph_i_community_leiden_aggregate( igraph_integer_t v = -1; /* Calculate the total edge weight to other clusters */ - VECTOR(*aggregated_node_weights)[c] = 0.0; + VECTOR(*aggregated_vertex_out_weights)[c] = 0.0; + if (directed) { + VECTOR(*aggregated_vertex_in_weights)[c] = 0.0; + } nb_neigh_clusters = 0; for (igraph_integer_t i = 0; i < n_c; i++) { v = VECTOR(*refined_cluster)[i]; - incident_edges = igraph_inclist_get(edges_per_node, v); + incident_edges = igraph_inclist_get(edges_per_vertex, v); degree = igraph_vector_int_size(incident_edges); for (igraph_integer_t j = 0; j < degree; j++) { @@ -562,7 +657,10 @@ static igraph_error_t igraph_i_community_leiden_aggregate( } } - VECTOR(*aggregated_node_weights)[c] += VECTOR(*node_weights)[v]; + VECTOR(*aggregated_vertex_out_weights)[c] += VECTOR(*vertex_out_weights)[v]; + if (directed) { + VECTOR(*aggregated_vertex_in_weights)[c] += VECTOR(*vertex_in_weights)[v]; + } } /* Add actual edges from this cluster to the other clusters */ @@ -592,7 +690,7 @@ static igraph_error_t igraph_i_community_leiden_aggregate( igraph_destroy(aggregated_graph); IGRAPH_CHECK(igraph_create(aggregated_graph, &aggregated_edges, nb_refined_clusters, - IGRAPH_UNDIRECTED)); + directed)); igraph_vector_int_destroy(&aggregated_edges); IGRAPH_FINALLY_CLEAN(1); @@ -604,13 +702,17 @@ static igraph_error_t igraph_i_community_leiden_aggregate( * * The quality is defined as * - * 1 / 2m sum_ij (A_ij - gamma n_i n_j)d(s_i, s_j) + * 1 / 2m sum_ij (A_ij - gamma n_i n_j) d(s_i, s_j) + * + * for undirected graphs and as + * + * 1 / m sum_ij (A_ij - gamma n^out_i n^in_j) d(s_i, s_j) * * where m is the total edge weight, A_ij is the weight of edge (i, j), gamma is - * the so-called resolution parameter, n_i is the node weight of node i, s_i is - * the cluster of node i and d(x, y) = 1 if and only if x = y and 0 otherwise. + * the so-called resolution parameter, n_i is the vertex weight of vertex i, s_i is + * the cluster of vertex i and d(x, y) = 1 if and only if x = y and 0 otherwise. * - * Note that by setting n_i = k_i the degree of node i and dividing gamma by 2m, + * Note that by setting n_i = k_i the degree of vertex i and dividing gamma by 2m, * we effectively optimize modularity. By setting n_i = 1 we optimize the * Constant Potts Model. * @@ -618,113 +720,148 @@ static igraph_error_t igraph_i_community_leiden_aggregate( * * 1 / 2m sum_c (e_c - gamma N_c^2) * - * where e_c = sum_ij A_ij d(s_i, c)d(s_j, c) is (twice) the internal edge - * weight in cluster c and N_c = sum_i n_i d(s_i, c) is the sum of the node - * weights inside cluster c. This is how the quality is calculated in practice. - * + * where e_c = sum_ij A_ij d(s_i, c)d(s_j, c) is the internal edge weight + * in cluster c (or twice this value if undirected) and + * N_c = sum_i n_i d(s_i, c) is the sum of the vertex weights inside cluster c. + * This is how the quality is calculated in practice. */ -static igraph_error_t igraph_i_community_leiden_quality( - const igraph_t *graph, const igraph_vector_t *edge_weights, const igraph_vector_t *node_weights, - const igraph_vector_int_t *membership, const igraph_integer_t nb_comms, const igraph_real_t resolution_parameter, +static igraph_error_t leiden_quality( + const igraph_t *graph, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_out_weights, + const igraph_vector_t *vertex_in_weights, + const igraph_vector_int_t *membership, + const igraph_integer_t nb_clusters, + const igraph_real_t resolution, igraph_real_t *quality) { - igraph_vector_t cluster_weights; + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_bool_t directed = (vertex_in_weights != NULL); + const igraph_real_t directed_multiplier = directed ? 1.0 : 2.0; + igraph_vector_t cluster_out_weights, cluster_in_weights; igraph_real_t total_edge_weight = 0.0; - igraph_eit_t eit; - igraph_integer_t i, c, n = igraph_vcount(graph); *quality = 0.0; - /* Create the edgelist */ - IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), &eit)); - IGRAPH_FINALLY(igraph_eit_destroy, &eit); - - while (!IGRAPH_EIT_END(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); - igraph_integer_t from = IGRAPH_FROM(graph, e), to = IGRAPH_TO(graph, e); + for (igraph_integer_t e=0; e < ecount; e++) { + igraph_integer_t from = IGRAPH_FROM(graph, e); + igraph_integer_t to = IGRAPH_TO(graph, e); total_edge_weight += VECTOR(*edge_weights)[e]; - /* We add the internal edge weights */ + + /* We add the internal edge weights. */ if (VECTOR(*membership)[from] == VECTOR(*membership)[to]) { - *quality += 2 * VECTOR(*edge_weights)[e]; + *quality += directed_multiplier * VECTOR(*edge_weights)[e]; } - IGRAPH_EIT_NEXT(eit); } - igraph_eit_destroy(&eit); - IGRAPH_FINALLY_CLEAN(1); - /* Initialize cluster weights and nb nodes */ - IGRAPH_VECTOR_INIT_FINALLY(&cluster_weights, n); - for (i = 0; i < n; i++) { - c = VECTOR(*membership)[i]; - VECTOR(cluster_weights)[c] += VECTOR(*node_weights)[i]; + /* Initialize and compute cluster weights. */ + + IGRAPH_VECTOR_INIT_FINALLY(&cluster_out_weights, vcount); + if (directed) { + IGRAPH_VECTOR_INIT_FINALLY(&cluster_in_weights, vcount); + } + + for (igraph_integer_t i = 0; i < vcount; i++) { + igraph_integer_t c = VECTOR(*membership)[i]; + VECTOR(cluster_out_weights)[c] += VECTOR(*vertex_out_weights)[i]; + if (directed) { + VECTOR(cluster_in_weights)[c] += VECTOR(*vertex_in_weights)[i]; + } } - /* We subtract gamma * N_c^2 */ - for (c = 0; c < nb_comms; c++) { - *quality -= resolution_parameter * VECTOR(cluster_weights)[c] * VECTOR(cluster_weights)[c]; + /* We subtract gamma * N^out_c * N^in_c */ + + for (igraph_integer_t c = 0; c < nb_clusters; c++) { + if (directed) { + *quality -= resolution * VECTOR(cluster_out_weights)[c] * VECTOR(cluster_in_weights)[c]; + } else { + *quality -= resolution * VECTOR(cluster_out_weights)[c] * VECTOR(cluster_out_weights)[c]; + } } - igraph_vector_destroy(&cluster_weights); + if (directed) { + igraph_vector_destroy(&cluster_in_weights); + IGRAPH_FINALLY_CLEAN(1); + } + igraph_vector_destroy(&cluster_out_weights); IGRAPH_FINALLY_CLEAN(1); - /* We normalise by 2m */ - *quality /= (2.0 * total_edge_weight); + /* We normalise by m or 2m depending on directedness */ + *quality /= (directed_multiplier * total_edge_weight); return IGRAPH_SUCCESS; } /* This is the core of the Leiden algorithm and relies on subroutines to - * perform the three different phases: (1) local moving of nodes, (2) + * perform the three different phases: (1) local moving of vertices, (2) * refinement of the partition and (3) aggregation of the network based on the * refined partition, using the non-refined partition to create an initial * partition for the aggregate network. */ -static igraph_error_t igraph_i_community_leiden( +static igraph_error_t community_leiden( const igraph_t *graph, - igraph_vector_t *edge_weights, igraph_vector_t *node_weights, - const igraph_real_t resolution_parameter, const igraph_real_t beta, - igraph_vector_int_t *membership, igraph_integer_t *nb_clusters, igraph_real_t *quality, + igraph_vector_t *edge_weights, + igraph_vector_t *vertex_out_weights, + igraph_vector_t *vertex_in_weights, + igraph_real_t resolution, + igraph_real_t beta, + igraph_vector_int_t *membership, + igraph_integer_t *nb_clusters, + igraph_real_t *quality, igraph_bool_t *changed) { + + const igraph_integer_t n = igraph_vcount(graph); + const igraph_bool_t directed = (vertex_in_weights != NULL); igraph_integer_t nb_refined_clusters; - igraph_integer_t i, c, n = igraph_vcount(graph); + igraph_integer_t i, c; igraph_t aggregated_graph, *i_graph; - igraph_vector_t aggregated_edge_weights, aggregated_node_weights; + igraph_vector_t aggregated_edge_weights; + igraph_vector_t aggregated_vertex_out_weights, aggregated_vertex_in_weights; igraph_vector_int_t aggregated_membership; - igraph_vector_t *i_edge_weights, *i_node_weights; + igraph_vector_t *i_edge_weights; + igraph_vector_t *i_vertex_out_weights, *i_vertex_in_weights; igraph_vector_int_t *i_membership; - igraph_vector_t tmp_edge_weights, tmp_node_weights; + igraph_vector_t tmp_edge_weights, tmp_vertex_out_weights, tmp_vertex_in_weights; igraph_vector_int_t tmp_membership; igraph_vector_int_t refined_membership; - igraph_vector_int_t aggregate_node; + igraph_vector_int_t aggregate_vertex; igraph_vector_int_list_t clusters; - igraph_inclist_t edges_per_node; + igraph_inclist_t edges_per_vertex; igraph_bool_t continue_clustering; igraph_integer_t level = 0; /* Initialize temporary weights and membership to be used in aggregation */ IGRAPH_VECTOR_INIT_FINALLY(&tmp_edge_weights, 0); - IGRAPH_VECTOR_INIT_FINALLY(&tmp_node_weights, 0); + IGRAPH_VECTOR_INIT_FINALLY(&tmp_vertex_out_weights, 0); + if (directed) { + IGRAPH_VECTOR_INIT_FINALLY(&tmp_vertex_in_weights, 0); + } IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp_membership, 0); /* Initialize clusters */ IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(&clusters, n); - /* Initialize aggregate nodes, which initially is identical to simply the - * nodes in the graph. */ - IGRAPH_CHECK(igraph_vector_int_init_range(&aggregate_node, 0, n)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &aggregate_node); + /* Initialize aggregate vertices, which initially is identical to simply the + * vertices in the graph. */ + IGRAPH_CHECK(igraph_vector_int_init_range(&aggregate_vertex, 0, n)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &aggregate_vertex); /* Initialize refined membership */ IGRAPH_VECTOR_INT_INIT_FINALLY(&refined_membership, 0); /* Initialize aggregated graph */ - IGRAPH_CHECK(igraph_empty(&aggregated_graph, 0, IGRAPH_UNDIRECTED)); + IGRAPH_CHECK(igraph_empty(&aggregated_graph, 0, directed)); IGRAPH_FINALLY(igraph_destroy, &aggregated_graph); /* Initialize aggregated edge weights */ IGRAPH_VECTOR_INIT_FINALLY(&aggregated_edge_weights, 0); - /* Initialize aggregated node weights */ - IGRAPH_VECTOR_INIT_FINALLY(&aggregated_node_weights, 0); + /* Initialize aggregated vertex weights */ + IGRAPH_VECTOR_INIT_FINALLY(&aggregated_vertex_out_weights, 0); + if (directed) { + IGRAPH_VECTOR_INIT_FINALLY(&aggregated_vertex_in_weights, 0); + } /* Initialize aggregated membership */ IGRAPH_VECTOR_INT_INIT_FINALLY(&aggregated_membership, 0); @@ -732,36 +869,33 @@ static igraph_error_t igraph_i_community_leiden( /* Set actual graph, weights and membership to be used. */ i_graph = (igraph_t*)graph; i_edge_weights = edge_weights; - i_node_weights = node_weights; + i_vertex_out_weights = vertex_out_weights; + i_vertex_in_weights = directed ? vertex_in_weights : NULL; i_membership = membership; - /* Clean membership and count number of *clusters */ - + /* Clean membership: ensure that cluster indices are 0 <= c < n. */ IGRAPH_CHECK(igraph_reindex_membership(i_membership, NULL, nb_clusters)); - if (*nb_clusters > n) { - IGRAPH_ERROR("Too many communities in membership vector.", IGRAPH_EINVAL); - } - - /* We start out with no changes, whenever a node is moved, this will be set to true. */ + /* We start out with no changes, whenever a vertex is moved, this will be set to true. */ *changed = false; do { /* Get incidence list for fast iteration */ - IGRAPH_CHECK(igraph_inclist_init( i_graph, &edges_per_node, IGRAPH_ALL, IGRAPH_LOOPS_TWICE)); - IGRAPH_FINALLY(igraph_inclist_destroy, &edges_per_node); - - /* Move around the nodes in order to increase the quality */ - IGRAPH_CHECK(igraph_i_community_leiden_fastmovenodes(i_graph, - &edges_per_node, - i_edge_weights, i_node_weights, - resolution_parameter, - nb_clusters, - i_membership, - changed)); + IGRAPH_CHECK(igraph_inclist_init( i_graph, &edges_per_vertex, IGRAPH_ALL, IGRAPH_LOOPS_TWICE)); + IGRAPH_FINALLY(igraph_inclist_destroy, &edges_per_vertex); + + /* Move around the vertices in order to increase the quality */ + IGRAPH_CHECK(leiden_fastmove_vertices(i_graph, + &edges_per_vertex, + i_edge_weights, + i_vertex_out_weights, i_vertex_in_weights, + resolution, + nb_clusters, + i_membership, + changed)); /* We only continue clustering if not all clusters are represented by a - * single node yet + * single vertex yet */ continue_clustering = (*nb_clusters < igraph_vcount(i_graph)); @@ -769,13 +903,13 @@ static igraph_error_t igraph_i_community_leiden( /* Set original membership */ if (level > 0) { for (i = 0; i < n; i++) { - igraph_integer_t v_aggregate = VECTOR(aggregate_node)[i]; + igraph_integer_t v_aggregate = VECTOR(aggregate_vertex)[i]; VECTOR(*membership)[i] = VECTOR(*i_membership)[v_aggregate]; } } - /* Get node sets for each cluster. */ - IGRAPH_CHECK(igraph_i_community_get_clusters(i_membership, &clusters)); + /* Get vertex sets for each cluster. */ + IGRAPH_CHECK(leiden_get_clusters(i_membership, &clusters)); /* Ensure refined membership is correct size */ IGRAPH_CHECK(igraph_vector_int_resize(&refined_membership, igraph_vcount(i_graph))); @@ -784,12 +918,13 @@ static igraph_error_t igraph_i_community_leiden( nb_refined_clusters = 0; for (c = 0; c < *nb_clusters; c++) { igraph_vector_int_t* cluster = igraph_vector_int_list_get_ptr(&clusters, c); - IGRAPH_CHECK(igraph_i_community_leiden_mergenodes(i_graph, - &edges_per_node, - i_edge_weights, i_node_weights, - cluster, i_membership, c, - resolution_parameter, beta, - &nb_refined_clusters, &refined_membership)); + IGRAPH_CHECK(leiden_merge_vertices(i_graph, + &edges_per_vertex, + i_edge_weights, + i_vertex_out_weights, i_vertex_in_weights, + cluster, i_membership, c, + resolution, beta, + &nb_refined_clusters, &refined_membership)); /* Empty cluster */ igraph_vector_int_clear(cluster); } @@ -801,20 +936,26 @@ static igraph_error_t igraph_i_community_leiden( nb_refined_clusters = *nb_clusters; } - /* Keep track of aggregate node. */ + /* Keep track of aggregate vertex. */ for (i = 0; i < n; i++) { - /* Current aggregate node */ - igraph_integer_t v_aggregate = VECTOR(aggregate_node)[i]; - /* New aggregate node */ - VECTOR(aggregate_node)[i] = VECTOR(refined_membership)[v_aggregate]; + /* Current aggregate vertex */ + igraph_integer_t v_aggregate = VECTOR(aggregate_vertex)[i]; + /* New aggregate vertex */ + VECTOR(aggregate_vertex)[i] = VECTOR(refined_membership)[v_aggregate]; } - IGRAPH_CHECK(igraph_i_community_leiden_aggregate( - i_graph, &edges_per_node, i_edge_weights, i_node_weights, - i_membership, &refined_membership, nb_refined_clusters, - &aggregated_graph, &tmp_edge_weights, &tmp_node_weights, &tmp_membership)); - - /* On the lowest level, the actual graph and node and edge weights and + IGRAPH_CHECK(leiden_aggregate( + i_graph, + &edges_per_vertex, + i_edge_weights, + i_vertex_out_weights, i_vertex_in_weights, + i_membership, &refined_membership, nb_refined_clusters, + &aggregated_graph, + &tmp_edge_weights, + &tmp_vertex_out_weights, directed ? &tmp_vertex_in_weights : NULL, + &tmp_membership)); + + /* On the lowest level, the actual graph and vertex and edge weights and * membership are used. On higher levels, we will use the aggregated graph * and associated vectors. */ @@ -822,42 +963,58 @@ static igraph_error_t igraph_i_community_leiden( /* Set actual graph, weights and membership to be used. */ i_graph = &aggregated_graph; i_edge_weights = &aggregated_edge_weights; - i_node_weights = &aggregated_node_weights; + i_vertex_out_weights = &aggregated_vertex_out_weights; + if (directed) { + i_vertex_in_weights = &aggregated_vertex_in_weights; + } i_membership = &aggregated_membership; } /* Update the aggregated administration. */ IGRAPH_CHECK(igraph_vector_update(i_edge_weights, &tmp_edge_weights)); - IGRAPH_CHECK(igraph_vector_update(i_node_weights, &tmp_node_weights)); + IGRAPH_CHECK(igraph_vector_update(i_vertex_out_weights, &tmp_vertex_out_weights)); + if (directed) { + IGRAPH_CHECK(igraph_vector_update(i_vertex_in_weights, &tmp_vertex_in_weights)); + } IGRAPH_CHECK(igraph_vector_int_update(i_membership, &tmp_membership)); level += 1; } /* We are done iterating, so we destroy the incidence list */ - igraph_inclist_destroy(&edges_per_node); + igraph_inclist_destroy(&edges_per_vertex); IGRAPH_FINALLY_CLEAN(1); } while (continue_clustering); /* Free aggregated graph and associated vectors */ igraph_vector_int_destroy(&aggregated_membership); - igraph_vector_destroy(&aggregated_node_weights); + if (directed) igraph_vector_destroy(&aggregated_vertex_in_weights); + igraph_vector_destroy(&aggregated_vertex_out_weights); igraph_vector_destroy(&aggregated_edge_weights); igraph_destroy(&aggregated_graph); - IGRAPH_FINALLY_CLEAN(4); /* Free remaining memory */ igraph_vector_int_destroy(&refined_membership); - igraph_vector_int_destroy(&aggregate_node); + igraph_vector_int_destroy(&aggregate_vertex); igraph_vector_int_list_destroy(&clusters); igraph_vector_int_destroy(&tmp_membership); - igraph_vector_destroy(&tmp_node_weights); + igraph_vector_destroy(&tmp_vertex_out_weights); + if (directed) igraph_vector_destroy(&tmp_vertex_in_weights); igraph_vector_destroy(&tmp_edge_weights); - IGRAPH_FINALLY_CLEAN(6); + + if (directed) { + IGRAPH_FINALLY_CLEAN(12); + } else { + IGRAPH_FINALLY_CLEAN(10); + } /* Calculate quality */ if (quality) { - IGRAPH_CHECK(igraph_i_community_leiden_quality(graph, edge_weights, node_weights, membership, *nb_clusters, resolution_parameter, quality)); + IGRAPH_CHECK(leiden_quality(graph, + edge_weights, vertex_out_weights, vertex_in_weights, + membership, + *nb_clusters, resolution, + quality)); } return IGRAPH_SUCCESS; @@ -875,29 +1032,29 @@ static igraph_error_t igraph_i_community_leiden( * It is similar to the multilevel algorithm, often called the Louvain * algorithm, but it is faster and yields higher quality solutions. It can * optimize both modularity and the Constant Potts Model, which does not suffer - * from the resolution-limit (see Tragg, Van Dooren & Nesterov). + * from the resolution-limit (see Traag, Van Dooren & Nesterov). * * - * The Leiden algorithm consists of three phases: (1) local moving of nodes, (2) + * The Leiden algorithm consists of three phases: (1) local moving of vertices, (2) * refinement of the partition and (3) aggregation of the network based on the * refined partition, using the non-refined partition to create an initial * partition for the aggregate network. In the local move procedure in the - * Leiden algorithm, only nodes whose neighborhood has changed are visited. Only + * Leiden algorithm, only vertices whose neighborhood has changed are visited. Only * moves that strictly improve the quality function are made. The refinement is * done by restarting from a singleton partition within each cluster and * gradually merging the subclusters. When aggregating, a single cluster may - * then be represented by several nodes (which are the subclusters identified in + * then be represented by several vertices (which are the subclusters identified in * the refinement). * * * The Leiden algorithm provides several guarantees. The Leiden algorithm is * typically iterated: the output of one iteration is used as the input for the - * next iteration. At each iteration all clusters are guaranteed to be + * next iteration. At each iteration all clusters are guaranteed to be (weakly) * connected and well-separated. After an iteration in which nothing has - * changed, all nodes and some parts are guaranteed to be locally optimally + * changed, all vertices and some parts are guaranteed to be locally optimally * assigned. Note that even if a single iteration did not result in any change, * it is still possible that a subsequent iteration might find some - * improvement. Each iteration explores different subsets of nodes to consider + * improvement. Each iteration explores different subsets of vertices to consider * for moving from one cluster to another. Finally, asymptotically, all subsets * of all clusters are guaranteed to be locally optimally assigned. For more * details, please see Traag, Waltman & van Eck (2019). @@ -909,15 +1066,24 @@ static igraph_error_t igraph_i_community_leiden( * 1 / 2m sum_ij (A_ij - γ n_i n_j) δ(s_i, s_j) * * - * where m is the total edge weight, A_ij is the weight of edge + * in the undirected case and + * + * + * 1 / m sum_ij (A_ij - γ n^out_i n^in_j) δ(s_i, s_j) + * + * + * in the directed case. + * Here \c m is the total edge weight, A_ij is the weight of edge * (i, j), \c γ is the so-called resolution parameter, n_i - * is the node weight of node \c i, s_i is the cluster of node + * is the vertex weight of vertex \c i (separate out- and in-weights are used + * with directed graphs), s_i is the cluster of vertex * \c i and δ(x, y) = 1 if and only if x = y and 0 - * otherwise. By setting n_i = k_i, the degree of node \c i, and - * dividing \c γ by 2m, we effectively obtain an expression for - * modularity. Hence, the standard modularity will be optimized when you supply - * the degrees as \c node_weights and by supplying as a resolution parameter - * 1/(2m), with \c m the number of edges. + * otherwise. By setting n_i = k_i, the degree of vertex \c i, and + * dividing \c γ by 2m (by \c m in the directed case), we effectively + * obtain an expression for modularity. Hence, the standard modularity will be + * optimized when you supply the degrees (out- and in-degrees with directed graphs) + * as the vertex weights and by supplying as a resolution parameter + * 1/(2m) (1/m with directed graphs). * * * References: @@ -934,13 +1100,18 @@ static igraph_error_t igraph_i_community_leiden( * Phys. Rev. E 84, 016114 (2011). * https://doi.org/10.1103/PhysRevE.84.016114 * - * \param graph The input graph. It must be an undirected graph. - * \param edge_weights Numeric vector containing edge weights. If \c NULL, every edge - * has equal weight of 1. The weights need not be non-negative. - * \param node_weights Numeric vector containing node weights. If \c NULL, every node - * has equal weight of 1. - * \param resolution_parameter The resolution parameter used, which is - * represented by gamma in the objective function mentioned in the + * \param graph The input graph. + * \param edge_weights Numeric vector containing edge weights. If \c NULL, + * every edge has equal weight of 1. The weights need not be non-negative. + * \param vertex_out_weights Numeric vector containing vertex weights, or vertex + * out-weights for directed graphs. If \c NULL, every vertex has equal + * weight of 1. + * \param vertex_in_weights Numeric vector containing vertex in-weights for + * directed graphs. If set to \c NULL, in-weights are assumed to be the same + * as out-weights, which effectively ignores edge directions. + * Must be \c NULL for undirected graphs. + * \param resolution The resolution parameter used, which is + * represented by γ in the objective function mentioned in the * documentation. * \param beta The randomness used in the refinement step when merging. A small * amount of randomness (\c beta = 0.01) typically works well. @@ -955,7 +1126,7 @@ static igraph_error_t igraph_i_community_leiden( * must hence be properly initialized. When finding clusters from scratch it * is typically started using a singleton clustering. This can be achieved * using \ref igraph_vector_int_init_range(). - * \param nb_clusters The number of clusters contained in \c membership. + * \param nb_clusters The number of clusters contained in the final \p membership. * If \c NULL, the number of clusters will not be returned. * \param quality The quality of the partition, in terms of the objective * function as included in the documentation. If \c NULL the quality will @@ -966,14 +1137,24 @@ static igraph_error_t igraph_i_community_leiden( * * \example examples/simple/igraph_community_leiden.c */ -igraph_error_t igraph_community_leiden(const igraph_t *graph, - const igraph_vector_t *edge_weights, const igraph_vector_t *node_weights, - const igraph_real_t resolution_parameter, const igraph_real_t beta, const igraph_bool_t start, - const igraph_integer_t n_iterations, - igraph_vector_int_t *membership, igraph_integer_t *nb_clusters, igraph_real_t *quality) { - igraph_vector_t *i_edge_weights, *i_node_weights; +igraph_error_t igraph_community_leiden( + const igraph_t *graph, + const igraph_vector_t *edge_weights, + const igraph_vector_t *vertex_out_weights, + const igraph_vector_t *vertex_in_weights, + igraph_real_t resolution, + igraph_real_t beta, + igraph_bool_t start, + igraph_integer_t n_iterations, + igraph_vector_int_t *membership, + igraph_integer_t *nb_clusters, + igraph_real_t *quality) { + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_bool_t directed = igraph_is_directed(graph); + igraph_vector_t *i_edge_weights, *i_vertex_out_weights, *i_vertex_in_weights; igraph_integer_t i_nb_clusters; - igraph_integer_t n = igraph_vcount(graph); if (!nb_clusters) { nb_clusters = &i_nb_clusters; @@ -984,23 +1165,18 @@ igraph_error_t igraph_community_leiden(const igraph_t *graph, IGRAPH_ERROR("Cannot start optimization if membership is missing.", IGRAPH_EINVAL); } - if (igraph_vector_int_size(membership) != n) { - IGRAPH_ERROR("Initial membership length does not equal the number of vertices.", IGRAPH_EINVAL); + if (igraph_vector_int_size(membership) != vcount) { + IGRAPH_ERROR("Membership vector length does not equal the number of vertices.", IGRAPH_EINVAL); } } else { if (!membership) IGRAPH_ERROR("Membership vector should be supplied and initialized, " "even when not starting optimization from it.", IGRAPH_EINVAL); - IGRAPH_CHECK(igraph_vector_int_range(membership, 0, n)); + IGRAPH_CHECK(igraph_vector_int_range(membership, 0, vcount)); } - - if (igraph_is_directed(graph)) { - IGRAPH_ERROR("Leiden algorithm is only implemented for undirected graphs.", IGRAPH_EINVAL); - } - - /* Check edge weights to possibly use default */ + /* Check edge weights to possibly use default. */ if (!edge_weights) { i_edge_weights = IGRAPH_CALLOC(1, igraph_vector_t); IGRAPH_CHECK_OOM(i_edge_weights, "Leiden algorithm failed, could not allocate memory for edge weights."); @@ -1009,19 +1185,51 @@ igraph_error_t igraph_community_leiden(const igraph_t *graph, IGRAPH_FINALLY(igraph_vector_destroy, i_edge_weights); igraph_vector_fill(i_edge_weights, 1); } else { + if (igraph_vector_size(edge_weights) != ecount) { + IGRAPH_ERRORF("Edge weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, igraph_vector_size(edge_weights), ecount); + } i_edge_weights = (igraph_vector_t*)edge_weights; } - /* Check edge weights to possibly use default */ - if (!node_weights) { - i_node_weights = IGRAPH_CALLOC(1, igraph_vector_t); - IGRAPH_CHECK_OOM(i_node_weights, "Leiden algorithm failed, could not allocate memory for node weights."); - IGRAPH_FINALLY(igraph_free, i_node_weights); - IGRAPH_CHECK(igraph_vector_init(i_node_weights, n)); - IGRAPH_FINALLY(igraph_vector_destroy, i_node_weights); - igraph_vector_fill(i_node_weights, 1); + /* Check vertex out-weights to possibly use default. */ + if (!vertex_out_weights) { + i_vertex_out_weights = IGRAPH_CALLOC(1, igraph_vector_t); + IGRAPH_CHECK_OOM(i_vertex_out_weights, "Leiden algorithm failed, could not allocate memory for vertex weights."); + IGRAPH_FINALLY(igraph_free, i_vertex_out_weights); + IGRAPH_VECTOR_INIT_FINALLY(i_vertex_out_weights, vcount); + igraph_vector_fill(i_vertex_out_weights, 1); } else { - i_node_weights = (igraph_vector_t*)node_weights; + if (igraph_vector_size(vertex_out_weights) != vcount) { + IGRAPH_ERRORF("Vertex %sweight vector length (%" IGRAPH_PRId ") does not match number of vertices (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, + directed ? "out-" : "", + igraph_vector_size(vertex_out_weights), vcount); + } + i_vertex_out_weights = (igraph_vector_t*)vertex_out_weights; + } + + if (directed) { + /* When in-weights are not given for a directed graph, + * assume that they are the same as the out-weights. + * This effectively ignores edge directions. */ + if (vertex_in_weights) { + if (igraph_vector_size(vertex_in_weights) != vcount) { + IGRAPH_ERRORF("Vertex in-weight vector length (%" IGRAPH_PRId ") does not match number of vertices (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, + igraph_vector_size(vertex_in_weights), vcount); + } + i_vertex_in_weights = (igraph_vector_t*)vertex_in_weights; + } else { + i_vertex_in_weights = i_vertex_out_weights; + } + } else { + /* In-weights must be NULL in the undirected case. */ + if (vertex_in_weights) { + IGRAPH_ERROR("Vertex in-weights must not be given for undirected graphs.", IGRAPH_EINVAL); + } else { + i_vertex_in_weights = NULL; + } } /* Perform actual Leiden algorithm iteratively. We either @@ -1029,15 +1237,16 @@ igraph_error_t igraph_community_leiden(const igraph_t *graph, * iterations until the quality remains unchanged. Even if * a single iteration did not change anything, a subsequent * iteration may still find some improvement. This is because - * each iteration explores different subsets of nodes. + * each iteration explores different subsets of vertices. */ igraph_bool_t changed = true; for (igraph_integer_t itr = 0; n_iterations < 0 ? changed : itr < n_iterations; itr++) { - IGRAPH_CHECK(igraph_i_community_leiden(graph, i_edge_weights, i_node_weights, - resolution_parameter, beta, - membership, nb_clusters, quality, &changed)); + IGRAPH_CHECK(community_leiden(graph, + i_edge_weights, i_vertex_out_weights, i_vertex_in_weights, + resolution, beta, + membership, nb_clusters, quality, &changed)); } if (!edge_weights) { @@ -1046,9 +1255,9 @@ igraph_error_t igraph_community_leiden(const igraph_t *graph, IGRAPH_FINALLY_CLEAN(2); } - if (!node_weights) { - igraph_vector_destroy(i_node_weights); - IGRAPH_FREE(i_node_weights); + if (!vertex_out_weights) { + igraph_vector_destroy(i_vertex_out_weights); + IGRAPH_FREE(i_vertex_out_weights); IGRAPH_FINALLY_CLEAN(2); } diff --git a/src/vendor/cigraph/src/community/louvain.c b/src/vendor/cigraph/src/community/louvain.c index 72e3035100b..94dbf82b26e 100644 --- a/src/vendor/cigraph/src/community/louvain.c +++ b/src/vendor/cigraph/src/community/louvain.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2020 The igraph development team @@ -191,7 +189,7 @@ static igraph_error_t igraph_i_multilevel_community_links( igraph_vector_clear(links_weight); /* Get the list of incident edges */ - IGRAPH_CHECK(igraph_incident(graph, edges, vertex, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, edges, vertex, IGRAPH_ALL, IGRAPH_LOOPS)); n = igraph_vector_int_size(edges); links = IGRAPH_CALLOC(n, igraph_i_multilevel_community_link); @@ -385,7 +383,6 @@ static igraph_error_t igraph_i_community_multilevel_step( q = igraph_i_multilevel_community_modularity(&communities, resolution); /* pass = 1; */ - RNG_BEGIN(); do { /* Pass begin */ igraph_integer_t temp_communities_no = communities.communities_no; @@ -489,7 +486,6 @@ static igraph_error_t igraph_i_community_multilevel_step( IGRAPH_ALLOW_INTERRUPTION(); } while (changed && (q > pass_q)); /* Pass end */ - RNG_END(); if (modularity) { *modularity = q; diff --git a/src/vendor/cigraph/src/community/modularity.c b/src/vendor/cigraph/src/community/modularity.c index 0945a63c8ad..9c709113336 100644 --- a/src/vendor/cigraph/src/community/modularity.c +++ b/src/vendor/cigraph/src/community/modularity.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2020 The igraph development team diff --git a/src/vendor/cigraph/src/community/optimal_modularity.c b/src/vendor/cigraph/src/community/optimal_modularity.c index f91a330a849..9a530d82827 100644 --- a/src/vendor/cigraph/src/community/optimal_modularity.c +++ b/src/vendor/cigraph/src/community/optimal_modularity.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -58,14 +56,18 @@ * with a couple of hundred vertices might be possible. * * \param graph The input graph. It may be undirected or directed. + * \param weights Vector giving the weights of the edges. If it is + * \c NULL then each edge is supposed to have the same weight. + * \param resolution Resolution parameter. Must be greater than or equal to 0. + * Lower values favor fewer, larger communities; higher values favor more, + * smaller communities. Set it to 1 to use the classical definition of + * modularity. * \param modularity Pointer to a real number, or a null pointer. * If it is not a null pointer, then a optimal modularity value * is returned here. * \param membership Pointer to a vector, or a null pointer. If not a * null pointer, then the membership vector of the optimal * community structure is stored here. - * \param weights Vector giving the weights of the edges. If it is - * \c NULL then each edge is supposed to have the same weight. * \return Error code. * When GLPK is not available, \c IGRAPH_UNIMPLEMENTED is returned. * @@ -78,9 +80,10 @@ */ igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, - igraph_real_t *modularity, - igraph_vector_int_t *membership, - const igraph_vector_t *weights) { + const igraph_vector_t *weights, + const igraph_real_t resolution, + igraph_real_t *modularity, + igraph_vector_int_t *membership) { #ifndef HAVE_GLPK IGRAPH_ERROR("GLPK is not available.", IGRAPH_UNIMPLEMENTED); @@ -101,6 +104,10 @@ igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, glp_prob *ip; glp_iocp parm; + if (resolution < 0.0) { + IGRAPH_ERRORF("Resolution must be positive, got %g.", IGRAPH_EINVAL, resolution); + } + if (weights) { if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERROR("Weight vector length must agree with number of edges.", IGRAPH_EINVAL); @@ -132,7 +139,7 @@ igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, igraph_vector_int_null(pmembership); if (modularity) { - IGRAPH_CHECK(igraph_modularity(graph, pmembership, NULL, 1, igraph_is_directed(graph), modularity)); + IGRAPH_CHECK(igraph_modularity(graph, pmembership, NULL, resolution, igraph_is_directed(graph), modularity)); } if (! membership) { @@ -237,10 +244,12 @@ igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, for (j = i + 1; j < no_of_nodes; j++) { c = -VECTOR(indegree)[i] * VECTOR(outdegree)[j] / total_weight \ -VECTOR(outdegree)[i] * VECTOR(indegree)[j] / total_weight; + c *= resolution; glp_set_obj_coef(ip, st + IDX(i, j), c); } /* special case for (i,i) */ c = -VECTOR(indegree)[i] * VECTOR(outdegree)[i] / total_weight; + c *= resolution; glp_set_obj_coef(ip, st + IDX(i, i), c); } diff --git a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp index fecfacd670f..8cb83deb39b 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp +++ b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h index 0e8dbef6364..6a5222e46db 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h +++ b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp b/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp index 67e4298bab8..d4242f22b17 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp +++ b/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/spinglass/NetRoutines.h b/src/vendor/cigraph/src/community/spinglass/NetRoutines.h index 98fd5fef453..6d042777a99 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetRoutines.h +++ b/src/vendor/cigraph/src/community/spinglass/NetRoutines.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/spinglass/clustertool.cpp b/src/vendor/cigraph/src/community/spinglass/clustertool.cpp index 5aaccb43e83..64361496d14 100644 --- a/src/vendor/cigraph/src/community/spinglass/clustertool.cpp +++ b/src/vendor/cigraph/src/community/spinglass/clustertool.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -303,9 +302,6 @@ static igraph_error_t igraph_i_community_spinglass_orig( PottsModel pm(&net, spins, update_rule); - /* initialize the random number generator */ - RNG_BEGIN(); - if ((stoptemp == 0.0) && (starttemp == 0.0)) { zeroT = true; } else { @@ -355,8 +351,6 @@ static igraph_error_t igraph_i_community_spinglass_orig( pm.WriteClusters(modularity, temperature, csize, membership, kT, gamma); - RNG_END(); - return IGRAPH_SUCCESS; } @@ -387,11 +381,12 @@ static igraph_error_t igraph_i_community_spinglass_orig( * cohesion index of the community will be stored here. * \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. - * \param outer_links Pointer to an integer, if not \c NULL the + * \param inner_links Pointer to a real, if not \c NULL the + * number of edges within the community (or the sum of their weights) + * is stored here. + * \param outer_links Pointer to a real, 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. @@ -426,8 +421,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) { @@ -472,9 +467,6 @@ igraph_error_t igraph_community_spinglass_single(const igraph_t *graph, PottsModel pm(&net, spins, update_rule); - /* initialize the random number generator */ - RNG_BEGIN(); - /* to be expected, if we want to find the community around a particular node*/ /* the initial conf is needed, because otherwise, the degree of the nodes is not in the weight property, stupid!!! */ @@ -482,8 +474,6 @@ igraph_error_t igraph_community_spinglass_single(const igraph_t *graph, snprintf(startnode, sizeof(startnode) / sizeof(startnode[0]), "%" IGRAPH_PRId "", vertex + 1); pm.FindCommunityFromStart(gamma, startnode, community, cohesion, adhesion, inner_links, outer_links); - - RNG_END(); ); return IGRAPH_SUCCESS; @@ -602,9 +592,6 @@ static igraph_error_t igraph_i_community_spinglass_negative( PottsModelN pm(&net, spins, directed); - /* initialize the random number generator */ - RNG_BEGIN(); - if ((stoptemp == 0.0) && (starttemp == 0.0)) { zeroT = true; } else { @@ -641,7 +628,5 @@ static igraph_error_t igraph_i_community_spinglass_negative( igraph_matrix_destroy(&adhesion); IGRAPH_FINALLY_CLEAN(2); - RNG_END(); - return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp index 355f19a608f..3707b7a9799 100644 --- a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp +++ b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -773,8 +772,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..1b742ed01e2 100644 --- a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h +++ b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -110,8 +109,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/community/voronoi.c b/src/vendor/cigraph/src/community/voronoi.c index fc3fabeefb7..fa3ba2df57a 100644 --- a/src/vendor/cigraph/src/community/voronoi.c +++ b/src/vendor/cigraph/src/community/voronoi.c @@ -536,21 +536,10 @@ igraph_error_t igraph_community_voronoi( IGRAPH_ERROR("Edge length vector size does not match edge count.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_is_simple(graph, &simple)); + IGRAPH_CHECK(igraph_is_simple(graph, &simple, mode == IGRAPH_ALL ? IGRAPH_UNDIRECTED : IGRAPH_DIRECTED)); if (! simple) { IGRAPH_ERROR("The graph must be simple for Voronoi communities.", IGRAPH_EINVAL); } - if (igraph_is_directed(graph) && mode == IGRAPH_ALL) { - igraph_bool_t has_mutual; - /* When the graph is directed but edge directions are ignored, - * mutual edges are effectively multi-edges. */ - IGRAPH_CHECK(igraph_has_mutual(graph, &has_mutual, false)); - if (has_mutual) { - IGRAPH_ERROR("The graph must be simple for Voronoi communities. " - "Mutual directed edges are effectively multi-edges when ignoring edge directions.", - IGRAPH_EINVAL); - } - } if (no_of_edges == 0) { /* Also handles no_of_nodes <= 1 */ diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap.cpp index 4efadc9d804..69c2d457b3e 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp index 8b363dda164..93cdb9fedd8 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h index 6017c3a20fd..ce9426c462b 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp index 56e31fc5668..be02efc53c6 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h index 2347e8cff83..43a480673e5 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp index dcb0518f18a..e165b219ea5 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h index 90b4f31f69b..b55f7f1c9f5 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/config.h.in b/src/vendor/cigraph/src/config.h.in index ca06c907829..953e3e4393a 100644 --- a/src/vendor/cigraph/src/config.h.in +++ b/src/vendor/cigraph/src/config.h.in @@ -26,6 +26,7 @@ #cmakedefine HAVE_GLPK 1 #cmakedefine HAVE_LIBXML 1 +#cmakedefine HAVE_INFOMAP 1 #cmakedefine INTERNAL_BLAS 1 #cmakedefine INTERNAL_LAPACK 1 diff --git a/src/vendor/cigraph/src/connectivity/cohesive_blocks.c b/src/vendor/cigraph/src/connectivity/cohesive_blocks.c index 7850d0e24df..d11e93a709e 100644 --- a/src/vendor/cigraph/src/connectivity/cohesive_blocks.c +++ b/src/vendor/cigraph/src/connectivity/cohesive_blocks.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -87,7 +86,9 @@ static igraph_error_t igraph_i_cb_components(igraph_t *graph, while (!igraph_dqueue_int_empty(Q)) { igraph_integer_t node = igraph_dqueue_int_pop(Q); igraph_integer_t j, n; - IGRAPH_CHECK(igraph_neighbors(graph, neis, node, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, neis, node, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(neis); for (j = 0; j < n; j++) { igraph_integer_t v = VECTOR(*neis)[j]; @@ -243,7 +244,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_is_simple(graph, &is_simple)); + IGRAPH_CHECK(igraph_is_simple(graph, &is_simple, IGRAPH_DIRECTED)); if (!is_simple) { IGRAPH_ERROR("Cohesive blocking only works on simple graphs.", IGRAPH_EINVAL); diff --git a/src/vendor/cigraph/src/connectivity/components.c b/src/vendor/cigraph/src/connectivity/components.c index b9009a01eef..459b286856b 100644 --- a/src/vendor/cigraph/src/connectivity/components.c +++ b/src/vendor/cigraph/src/connectivity/components.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -27,7 +26,6 @@ #include "igraph_bitset.h" #include "igraph_dqueue.h" #include "igraph_interface.h" -#include "igraph_memory.h" #include "igraph_progress.h" #include "igraph_stack.h" #include "igraph_structural.h" @@ -45,20 +43,6 @@ static igraph_error_t igraph_i_connected_components_strong( igraph_vector_int_t *csize, igraph_integer_t *no ); -/** - * \ingroup structural - * \function igraph_clusters - * \brief Calculates the (weakly or strongly) connected components in a graph (deprecated alias). - * - * \deprecated-by igraph_connected_components 0.10 - */ - -igraph_error_t igraph_clusters(const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no, - igraph_connectedness_t mode) { - return igraph_connected_components(graph, membership, csize, no, mode); -} - /** * \ingroup structural * \function igraph_connected_components @@ -174,7 +158,9 @@ static igraph_error_t igraph_i_connected_components_weak( while ( !igraph_dqueue_int_empty(&q) ) { igraph_integer_t act_node = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, act_node, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, act_node, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); igraph_integer_t nei_count = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < nei_count; i++) { igraph_integer_t neighbor = VECTOR(neis)[i]; @@ -530,7 +516,9 @@ static igraph_error_t igraph_i_is_connected_weak(const igraph_t *graph, igraph_b const igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, actnode, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); const igraph_integer_t nei_count = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < nei_count; i++) { @@ -571,34 +559,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); @@ -685,6 +645,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, @@ -710,7 +671,9 @@ static igraph_error_t igraph_i_decompose_weak(const igraph_t *graph, while (!igraph_dqueue_int_empty(&q) ) { /* pop from the queue of this component */ igraph_integer_t actvert = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actvert, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, actvert, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); igraph_integer_t nei_count = igraph_vector_int_size(&neis); /* iterate over the neighbors */ for (i = 0; i < nei_count; i++) { @@ -735,7 +698,7 @@ static igraph_error_t igraph_i_decompose_weak(const igraph_t *graph, IGRAPH_CHECK(igraph_i_induced_subgraph_map( graph, &newg, igraph_vss_vector(&verts), IGRAPH_SUBGRAPH_AUTO, &vids_old2new, - /* invmap = */ 0, /* map_is_prepared = */ 1 + /* invmap = */ NULL, /* map_is_prepared = */ true )); IGRAPH_FINALLY(igraph_destroy, &newg); IGRAPH_CHECK(igraph_graph_list_push_back(components, &newg)); @@ -792,6 +755,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); @@ -1265,8 +1230,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. * @@ -1622,7 +1585,7 @@ igraph_error_t igraph_subcomponent( IGRAPH_ALLOW_INTERRUPTION(); - IGRAPH_CHECK(igraph_neighbors(graph, &tmp, actnode, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &tmp, actnode, mode, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE)); vsize = igraph_vector_int_size(&tmp); for (i = 0; i < vsize; i++) { igraph_integer_t neighbor = VECTOR(tmp)[i]; diff --git a/src/vendor/cigraph/src/connectivity/percolation.c b/src/vendor/cigraph/src/connectivity/percolation.c index d28b481031d..cdadd960e87 100644 --- a/src/vendor/cigraph/src/connectivity/percolation.c +++ b/src/vendor/cigraph/src/connectivity/percolation.c @@ -225,7 +225,7 @@ igraph_error_t igraph_bond_percolation( if (edge_order == NULL) { IGRAPH_CHECK(igraph_vector_int_init_range(&i_edge_order, 0, igraph_ecount(graph))); IGRAPH_FINALLY(igraph_vector_int_destroy, &i_edge_order); - IGRAPH_CHECK(igraph_vector_int_shuffle(&i_edge_order)); + igraph_vector_int_shuffle(&i_edge_order); p_edge_order = &i_edge_order; } else { // Verify that there are no duplicates. @@ -247,7 +247,7 @@ igraph_error_t igraph_bond_percolation( // Initialize edge list. igraph_edges() will validate edge IDs. IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2 * igraph_vector_int_size(p_edge_order)); - IGRAPH_CHECK(igraph_edges(graph, igraph_ess_vector(p_edge_order), &edges)); + IGRAPH_CHECK(igraph_edges(graph, igraph_ess_vector(p_edge_order), &edges, /* bycol = */ 0)); // Defer to igraph_edgelist_percolation() IGRAPH_CHECK(igraph_edgelist_percolation(&edges, giant_size, vertex_count)); @@ -278,7 +278,7 @@ static igraph_error_t percolate_site(const igraph_t *graph, VECTOR(*sizes)[vertex] = 1; - IGRAPH_CHECK(igraph_neighbors(graph, neighbors, vertex, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors(graph, neighbors, vertex, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); igraph_integer_t neighbor_count = igraph_vector_int_size(neighbors); for (igraph_integer_t i = 0; i < neighbor_count; i++) { @@ -340,7 +340,7 @@ igraph_error_t igraph_site_percolation( if (vertex_order == NULL) { IGRAPH_CHECK(igraph_vector_int_init_range(&i_vertex_order, 0, vcount)); IGRAPH_FINALLY(igraph_vector_int_destroy, &i_vertex_order); - IGRAPH_CHECK(igraph_vector_int_shuffle(&i_vertex_order)); + igraph_vector_int_shuffle(&i_vertex_order); p_vertex_order = &i_vertex_order; } else { p_vertex_order = vertex_order; diff --git a/src/vendor/cigraph/src/connectivity/reachability.c b/src/vendor/cigraph/src/connectivity/reachability.c index 1b5560f36a8..9fa4e51c247 100644 --- a/src/vendor/cigraph/src/connectivity/reachability.c +++ b/src/vendor/cigraph/src/connectivity/reachability.c @@ -211,8 +211,6 @@ igraph_error_t igraph_count_reachable(const igraph_t *graph, * \function igraph_transitive_closure * \brief Computes the transitive closure of a graph. * - * \experimental - * * The resulting graph will have an edge from vertex \c i to vertex \c j * if \c j is reachable from \c i. * diff --git a/src/vendor/cigraph/src/connectivity/separators.c b/src/vendor/cigraph/src/connectivity/separators.c index ece42ecfc13..8f22b5ca8ae 100644 --- a/src/vendor/cigraph/src/connectivity/separators.c +++ b/src/vendor/cigraph/src/connectivity/separators.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -150,7 +149,9 @@ static igraph_error_t igraph_i_is_separator( } SET_VISITED(v); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); const igraph_integer_t dv = igraph_vector_int_size(&neis); @@ -231,7 +232,9 @@ static igraph_error_t igraph_i_is_separator( for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { const igraph_integer_t u = IGRAPH_VIT_GET(vit); - IGRAPH_CHECK(igraph_neighbors(graph, &Sneis, u, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &Sneis, u, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); const igraph_integer_t du = igraph_vector_int_size(&Sneis); for (igraph_integer_t i=0; i < du; i++) { @@ -250,7 +253,9 @@ static igraph_error_t igraph_i_is_separator( } SET_VISITED(v); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); const igraph_integer_t dv = igraph_vector_int_size(&neis); @@ -695,7 +700,7 @@ static igraph_error_t igraph_i_minimum_size_separators_topkdeg( * faster IGRAPH_LOOPS here instead of the slower IGRAPH_NO_LOOPS. */ IGRAPH_CHECK(igraph_degree(graph, °, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); - IGRAPH_CHECK(igraph_vector_int_order1(°, &order, no_of_nodes)); + IGRAPH_CHECK(igraph_i_vector_int_order(°, &order, no_of_nodes)); IGRAPH_CHECK(igraph_vector_int_resize(res, k)); for (igraph_integer_t i = 0; i < k; i++) { VECTOR(*res)[i] = VECTOR(order)[no_of_nodes - 1 - i]; @@ -716,6 +721,14 @@ static igraph_error_t igraph_i_minimum_size_separators_topkdeg( * A vertex set is a separator if its removal disconnects the graph. * * + * If the graph is already disconnected, no separators are returned. + * Note that this convention differs from that used by some other + * funtions such as \ref igraph_all_minimal_st_separators(). + * + * + * Complete graphs have no vertex separators. + * + * * The implementation is based on the following paper: * Arkady Kanevsky: Finding all minimum-size separating vertex sets in * a graph, Networks 23, 533--541, 1993. @@ -723,7 +736,7 @@ static igraph_error_t igraph_i_minimum_size_separators_topkdeg( * * \param graph The input graph, which must be undirected. * \param separators An initialized list of integer vectors, the separators - * are stored here. It is a list of pointers to igraph_vector_int_t + * are stored here. It is a list of pointers to \type igraph_vector_int_t * objects. Each vector will contain the IDs of the vertices in * the separator. The separators are returned in an arbitrary order. * \return Error code. @@ -762,8 +775,9 @@ igraph_error_t igraph_minimum_size_separators( k = conn; /* Special cases for low connectivity, two exits here! */ - if (conn == 0) { - /* Nothing to do */ + if (conn == 0 || conn == no_of_nodes - 1) { + /* Nothing to do on disconnected or complete graphs: + * there are no separators. */ return IGRAPH_SUCCESS; } else if (conn == 1) { igraph_vector_int_t ap; @@ -778,18 +792,6 @@ igraph_error_t igraph_minimum_size_separators( igraph_vector_int_destroy(&ap); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; - } else if (conn == no_of_nodes - 1) { - IGRAPH_CHECK(igraph_vector_int_list_resize(separators, no_of_nodes)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(separators, i); - IGRAPH_CHECK(igraph_vector_int_resize(v, no_of_nodes - 1)); - for (igraph_integer_t j = 0, k = 0; j < no_of_nodes; j++) { - if (j != i) { - VECTOR(*v)[k++] = j; - } - } - } - return IGRAPH_SUCCESS; } /* Work on a copy of 'graph' */ diff --git a/src/vendor/cigraph/src/constructors/adjacency.c b/src/vendor/cigraph/src/constructors/adjacency.c index 9b7ff671e26..694425dbc0f 100644 --- a/src/vendor/cigraph/src/constructors/adjacency.c +++ b/src/vendor/cigraph/src/constructors/adjacency.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -26,9 +25,9 @@ #include "igraph_interface.h" #include "igraph_sparsemat.h" -static igraph_error_t igraph_i_adjacency_directed( +static igraph_error_t igraph_i_adjacency_directed_or_plus( const igraph_matrix_t *adjmatrix, igraph_vector_int_t *edges, - igraph_loops_t loops + igraph_adjacency_t mode, igraph_loops_t loops ); static igraph_error_t igraph_i_adjacency_max( const igraph_matrix_t *adjmatrix, igraph_vector_int_t *edges, @@ -74,21 +73,25 @@ static igraph_error_t igraph_i_adjust_loop_edge_count( return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_adjacency_directed( +static igraph_error_t igraph_i_adjacency_directed_or_plus( const igraph_matrix_t *adjmatrix, igraph_vector_int_t *edges, - igraph_loops_t loops + igraph_adjacency_t mode, igraph_loops_t loops ) { + const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j, k; + /* For sake of consistency with the rest of the library, IGRAPH_LOOPS_TWICE + * is treated as IGRAPH_LOOPS_ONCE for directed graphs */ + if (mode == IGRAPH_ADJ_DIRECTED && loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } - for (i = 0; i < no_of_nodes; i++) { - for (j = 0; j < no_of_nodes; j++) { + for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { igraph_integer_t M = MATRIX(*adjmatrix, i, j); if (i == j) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); } - for (k = 0; k < M; k++) { + for (igraph_integer_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } @@ -152,25 +155,35 @@ static igraph_error_t igraph_i_adjacency_upper( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j, k, M; + const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_integer_t M; + + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } - for (i = 0; i < no_of_nodes; i++) { - /* do the loops first */ - M = MATRIX(*adjmatrix, i, i); - if (M) { - IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); - for (k = 0; k < M; k++) { - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_integer_t i = 0; i < j; i++) { + M = MATRIX(*adjmatrix, i, j); + for (igraph_integer_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } } - /* then the rest */ - for (j = i + 1; j < no_of_nodes; j++) { - M = MATRIX(*adjmatrix, i, j); - for (k = 0; k < M; k++) { - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + /* do the loops as well */ + M = MATRIX(*adjmatrix, j, j); + if (M) { + IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); + for (igraph_integer_t k = 0; k < M; k++) { + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } } @@ -183,25 +196,36 @@ static igraph_error_t igraph_i_adjacency_lower( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j, k, M; + const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_integer_t M; + + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } - for (i = 0; i < no_of_nodes; i++) { - for (j = 0; j < i; j++) { - M = MATRIX(*adjmatrix, i, j); - for (k = 0; k < M; k++) { - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + /* do the loops first */ + M = MATRIX(*adjmatrix, j, j); + if (M) { + IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); + for (igraph_integer_t k = 0; k < M; k++) { + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } } - /* do the loops as well */ - M = MATRIX(*adjmatrix, i, i); - if (M) { - IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); - for (k = 0; k < M; k++) { - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + for (igraph_integer_t i = j+1; i < no_of_nodes; i++) { + M = MATRIX(*adjmatrix, i, j); + for (igraph_integer_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } } } @@ -253,7 +277,9 @@ static igraph_error_t igraph_i_adjacency_min( * * The order of the vertices in the matrix is preserved, i.e. the vertex * corresponding to the first row/column will be vertex with id 0, the - * next row is for vertex 1, etc. + * next row is for vertex 1, etc. No guarantees are given about the ordering + * of edges. + * * \param graph Pointer to an uninitialized graph object. * \param adjmatrix The adjacency matrix. How it is interpreted * depends on the \p mode argument. @@ -262,35 +288,31 @@ static igraph_error_t igraph_i_adjacency_min( * row i and column j in the adjacency matrix \p adjmatrix): * \clist * \cli IGRAPH_ADJ_DIRECTED - * The graph will be directed and - * an element gives the number of edges between two vertices. + * The graph will be directed and an element gives the number of edges + * between two vertices. * \cli IGRAPH_ADJ_UNDIRECTED - * The graph will be undirected and - * an element gives the number of edges between two vertices. - * If the input matrix is not symmetric, an error is thrown. + * The graph will be undirected and an element gives the number of + * edges between two vertices. If the input matrix is not symmetric, + * an error is thrown. * \cli IGRAPH_ADJ_MAX - * An undirected graph will be created - * and the number of edges between vertices - * i and j is max(A(i,j), A(j,i)). + * An undirected graph will be created and the number of edges between + * vertices i and j is max(A(i,j), A(j,i)). * \cli IGRAPH_ADJ_MIN - * An undirected graph will be created - * with min(A(i,j), A(j,i)) - * edges between vertices i and j. + * An undirected graph will be created with min(A(i,j), A(j,i)) edges + * between vertices i and j. * \cli IGRAPH_ADJ_PLUS - * An undirected graph will be created - * with A(i,j)+A(j,i) edges + * An undirected graph will be created with A(i,j)+A(j,i) edges * between vertices i and j. * \cli IGRAPH_ADJ_UPPER - * An undirected graph will be created. - * Only the upper right triangle (including the diagonal) is - * used for the number of edges. + * An undirected graph will be created. Only the upper right triangle + * (including the diagonal) is used for the number of edges. * \cli IGRAPH_ADJ_LOWER - * An undirected graph will be created. - * Only the lower left triangle (including the diagonal) is - * used for the number of edges. + * An undirected graph will be created. Only the lower left triangle + * (including the diagonal) is used for the number of edges. * \endclist * \param loops Constant to specify how the diagonal of the matrix should be - * treated when creating loop edges. + * treated when creating loop edges. Ignored for modes + * \c IGRAPH_ADJ_DIRECTED, \c IGRAPH_ADJ_UPPER and \c IGRAPH_ADJ_LOWER. * \clist * \cli IGRAPH_NO_LOOPS * Ignore the diagonal of the input matrix and do not create loops. @@ -303,9 +325,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 +344,7 @@ igraph_error_t igraph_adjacency( /* Some checks */ if (igraph_matrix_nrow(adjmatrix) != igraph_matrix_ncol(adjmatrix)) { - IGRAPH_ERROR("Adjacency matrices must be square.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Adjacency matrices must be square.", IGRAPH_EINVAL); } if (no_of_nodes != 0 && igraph_matrix_min(adjmatrix) < 0) { @@ -336,7 +358,8 @@ igraph_error_t igraph_adjacency( no_of_nodes = igraph_matrix_nrow(adjmatrix); switch (mode) { case IGRAPH_ADJ_DIRECTED: - IGRAPH_CHECK(igraph_i_adjacency_directed(adjmatrix, &edges, loops)); + case IGRAPH_ADJ_PLUS: + IGRAPH_CHECK(igraph_i_adjacency_directed_or_plus(adjmatrix, &edges, mode, loops)); break; case IGRAPH_ADJ_MAX: IGRAPH_CHECK(igraph_i_adjacency_max(adjmatrix, &edges, loops)); @@ -353,9 +376,6 @@ igraph_error_t igraph_adjacency( case IGRAPH_ADJ_MIN: IGRAPH_CHECK(igraph_i_adjacency_min(adjmatrix, &edges, loops)); break; - case IGRAPH_ADJ_PLUS: - IGRAPH_CHECK(igraph_i_adjacency_directed(adjmatrix, &edges, loops)); - break; default: IGRAPH_ERROR("Invalid adjacency mode.", IGRAPH_EINVAL); } @@ -427,11 +447,16 @@ static igraph_error_t igraph_i_weighted_adjacency_directed( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j; + const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - for (i = 0; i < no_of_nodes; i++) { - for (j = 0; j < no_of_nodes; j++) { + /* For sake of consistency with the rest of the library, IGRAPH_LOOPS_TWICE + * is treated as IGRAPH_LOOPS_ONCE for directed graphs */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + + for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { igraph_real_t M = MATRIX(*adjmatrix, i, j); if (M != 0.0) { if (i == j) { @@ -534,20 +559,35 @@ static igraph_error_t igraph_i_weighted_adjacency_undirected( /* We do not use igraph_matrix_is_symmetric() for this check, as we need to * allow symmetric matrices with NaN values. igraph_matrix_is_symmetric() * returns false for these as NaN != NaN. */ - igraph_integer_t n = igraph_matrix_nrow(adjmatrix); + const igraph_integer_t n = igraph_matrix_nrow(adjmatrix); for (igraph_integer_t i=0; i < n; i++) { + /* do the loops first */ + if (loops) { + igraph_real_t M = MATRIX(*adjmatrix, i, i); + if (M != 0.0) { + igraph_i_adjust_loop_edge_weight(&M, loops); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + IGRAPH_CHECK(igraph_vector_push_back(weights, M)); + } + } + for (igraph_integer_t j=0; j < i; j++) { - igraph_real_t a1 = MATRIX(*adjmatrix, i, j); - igraph_real_t a2 = MATRIX(*adjmatrix, j, i); - if (a1 != a2 && ! (isnan(a1) && isnan(a2))) { + igraph_real_t M1 = MATRIX(*adjmatrix, i, j); + igraph_real_t M2 = MATRIX(*adjmatrix, j, i); + if (IGRAPH_UNLIKELY(M1 != M2 && ! (isnan(M1) && isnan(M2)))) { IGRAPH_ERROR( "Adjacency matrix should be symmetric to produce an undirected graph.", IGRAPH_EINVAL - ); + ); + } else if (M1 != 0.0) { + IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); + IGRAPH_CHECK(igraph_vector_push_back(weights, M1)); } } } - return igraph_i_weighted_adjacency_max(adjmatrix, edges, weights, loops); + return IGRAPH_SUCCESS; } @@ -558,27 +598,36 @@ static igraph_error_t igraph_i_weighted_adjacency_upper( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j; + const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); igraph_real_t M; - for (i = 0; i < no_of_nodes; i++) { - /* do the loops first */ - if (loops) { - M = MATRIX(*adjmatrix, i, i); + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + + for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_integer_t i = 0; i < j; i++) { + igraph_real_t M = MATRIX(*adjmatrix, i, j); if (M != 0.0) { - igraph_i_adjust_loop_edge_weight(&M, loops); - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_push_back(weights, M)); } } - /* then the rest */ - for (j = i + 1; j < no_of_nodes; j++) { - igraph_real_t M = MATRIX(*adjmatrix, i, j); + /* do the loops as well */ + if (loops) { + M = MATRIX(*adjmatrix, j, j); if (M != 0.0) { - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + igraph_i_adjust_loop_edge_weight(&M, loops); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_push_back(weights, M)); } @@ -594,27 +643,37 @@ static igraph_error_t igraph_i_weighted_adjacency_lower( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j; + const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); igraph_real_t M; - for (i = 0; i < no_of_nodes; i++) { - for (j = 0; j < i; j++) { - M = MATRIX(*adjmatrix, i, j); + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + + for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + /* do the loops first */ + if (loops) { + M = MATRIX(*adjmatrix, j, j); if (M != 0.0) { - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + igraph_i_adjust_loop_edge_weight(&M, loops); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_push_back(weights, M)); } } - /* do the loops as well */ - if (loops) { - M = MATRIX(*adjmatrix, i, i); + for (igraph_integer_t i = j+1; i < no_of_nodes; i++) { + M = MATRIX(*adjmatrix, i, j); if (M != 0.0) { - igraph_i_adjust_loop_edge_weight(&M, loops); - IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_push_back(weights, M)); } } @@ -670,55 +729,43 @@ static igraph_error_t igraph_i_weighted_adjacency_min( * * The order of the vertices in the matrix is preserved, i.e. the vertex * corresponding to the first row/column will be vertex with id 0, the - * next row is for vertex 1, etc. + * next row is for vertex 1, etc. No guarantees are given for the ordering + * of edges. + * * \param graph Pointer to an uninitialized graph object. * \param adjmatrix The weighted adjacency matrix. How it is interpreted * depends on the \p mode argument. The common feature is that * edges with zero weights are considered nonexistent (however, * negative weights are permitted). * \param mode Constant to specify how the given matrix is interpreted - * as an adjacency matrix. Possible values - * (A(i,j) - * is the element in row i and column - * j in the adjacency matrix - * \p adjmatrix): + * as an adjacency matrix. Possible values (A(i,j) is the element in row + * i and column j in the adjacency matrix \p adjmatrix): * \clist * \cli IGRAPH_ADJ_DIRECTED - * the graph will be directed and - * an element gives the weight of the edge between two vertices. + * The graph will be directed and an element specifies the weight of the + * edge between two vertices. * \cli IGRAPH_ADJ_UNDIRECTED - * this is the same as \c IGRAPH_ADJ_MAX, - * for convenience. + * This is the same as \c IGRAPH_ADJ_MAX, for convenience. * \cli IGRAPH_ADJ_MAX - * undirected graph will be created - * and the weight of the edge between vertices - * i and - * j is - * max(A(i,j), A(j,i)). + * An undirected graph will be created and the weight of the edge between + * vertices i and j is max(A(i,j), A(j,i)). * \cli IGRAPH_ADJ_MIN - * undirected graph will be created - * with edge weight min(A(i,j), A(j,i)) - * between vertices - * i and - * j. + * An undirected graph will be created and the weight of the edge between + * vertices i and j is min(A(i,j), A(j,i)). * \cli IGRAPH_ADJ_PLUS - * undirected graph will be created - * with edge weight A(i,j)+A(j,i) - * between vertices - * i and - * j. + * An undirected graph will be created and the weight of the edge between + * vertices i and j is A(i,j)+A(j,i). * \cli IGRAPH_ADJ_UPPER - * undirected graph will be created, - * only the upper right triangle (including the diagonal) is - * used for the edge weights. + * An undirected graph will be created. Only the upper right triangle + * (including the diagonal) is used for the edge weights. * \cli IGRAPH_ADJ_LOWER - * undirected graph will be created, - * only the lower left triangle (including the diagonal) is - * used for the edge weights. + * An undirected graph will be created. Only the lower left triangle + * (including the diagonal) is used for the edge weights. * \endclist * \param weights Pointer to an initialized vector, the weights will be stored here. * \param loops Constant to specify how the diagonal of the matrix should be - * treated when creating loop edges. + * treated when creating loop edges. Ignored for modes + * \c IGRAPH_ADJ_DIRECTED, \c IGRAPH_ADJ_UPPER and \c IGRAPH_ADJ_LOWER. * \clist * \cli IGRAPH_NO_LOOPS * Ignore the diagonal of the input matrix and do not create loops. @@ -730,7 +777,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. @@ -747,7 +794,7 @@ igraph_error_t igraph_weighted_adjacency( /* Some checks */ if (igraph_matrix_nrow(adjmatrix) != igraph_matrix_ncol(adjmatrix)) { - IGRAPH_ERROR("Adjacency matrices must be square.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Adjacency matrices must be square.", IGRAPH_EINVAL); } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); @@ -906,13 +953,19 @@ igraph_error_t igraph_adjlist(igraph_t *graph, const igraph_adjlist_t *adjlist, return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_sparse_adjacency_directed( +static igraph_error_t igraph_i_sparse_adjacency_directed_or_plus( igraph_sparsemat_t *adjmatrix, igraph_vector_int_t *edges, - igraph_loops_t loops + igraph_adjacency_t mode, igraph_loops_t loops ) { igraph_sparsemat_iterator_t it; igraph_sparsemat_iterator_init(&it, adjmatrix); + /* For sake of consistency with the rest of the library, IGRAPH_LOOPS_TWICE + * is treated as IGRAPH_LOOPS_ONCE for directed graphs */ + if (mode == IGRAPH_ADJ_DIRECTED && loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { igraph_integer_t from = igraph_sparsemat_iterator_row(&it); igraph_integer_t to = igraph_sparsemat_iterator_col(&it); @@ -994,6 +1047,17 @@ static igraph_error_t igraph_i_sparse_adjacency_upper( ) { igraph_sparsemat_iterator_t it; + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { igraph_integer_t from = igraph_sparsemat_iterator_row(&it); @@ -1020,6 +1084,17 @@ static igraph_error_t igraph_i_sparse_adjacency_lower( ) { igraph_sparsemat_iterator_t it; + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { igraph_integer_t from = igraph_sparsemat_iterator_row(&it); @@ -1052,7 +1127,7 @@ static igraph_error_t igraph_i_sparse_adjacency_undirected( IGRAPH_EINVAL ); } - return igraph_i_sparse_adjacency_upper(adjmatrix, edges, loops); + return igraph_i_sparse_adjacency_max(adjmatrix, edges, loops); } /** @@ -1081,7 +1156,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) { @@ -1115,7 +1190,8 @@ igraph_error_t igraph_sparse_adjacency(igraph_t *graph, igraph_sparsemat_t *adjm /* Collect the edges */ switch (mode) { case IGRAPH_ADJ_DIRECTED: - IGRAPH_CHECK(igraph_i_sparse_adjacency_directed(adjmatrix, &edges, loops)); + case IGRAPH_ADJ_PLUS: + IGRAPH_CHECK(igraph_i_sparse_adjacency_directed_or_plus(adjmatrix, &edges, mode, loops)); break; case IGRAPH_ADJ_MAX: IGRAPH_CHECK(igraph_i_sparse_adjacency_max(adjmatrix, &edges, loops)); @@ -1132,9 +1208,6 @@ igraph_error_t igraph_sparse_adjacency(igraph_t *graph, igraph_sparsemat_t *adjm case IGRAPH_ADJ_MIN: IGRAPH_CHECK(igraph_i_sparse_adjacency_min(adjmatrix, &edges, loops)); break; - case IGRAPH_ADJ_PLUS: - IGRAPH_CHECK(igraph_i_sparse_adjacency_directed(adjmatrix, &edges, loops)); - break; default: IGRAPH_ERROR("Invalid adjacency mode.", IGRAPH_EINVAL); } @@ -1256,6 +1329,17 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_upper( igraph_sparsemat_iterator_init(&it, adjmatrix); igraph_integer_t e = 0; + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { igraph_integer_t from = igraph_sparsemat_iterator_row(&it); igraph_integer_t to = igraph_sparsemat_iterator_col(&it); @@ -1286,6 +1370,17 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_lower( igraph_sparsemat_iterator_init(&it, adjmatrix); igraph_integer_t e = 0; + /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense + * for loops to appear twice in the adjacency matrix when the lower triangle + * is empty; double-counting of loops in undirected graphs happens because + * the upper and the lower triangle are added on top of each other on the + * diagonal. See discussion in #2501: + * + * https://github.com/igraph/igraph/issues/2501#issuecomment-1949345675 */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { igraph_integer_t from = igraph_sparsemat_iterator_row(&it); igraph_integer_t to = igraph_sparsemat_iterator_col(&it); @@ -1321,7 +1416,7 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_undirected ( IGRAPH_EINVAL ); } - return igraph_i_sparse_weighted_adjacency_upper(adjmatrix, edges, weights, loops); + return igraph_i_sparse_weighted_adjacency_max(adjmatrix, edges, weights, loops); } @@ -1333,6 +1428,12 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_directed( igraph_sparsemat_iterator_init(&it, adjmatrix); igraph_integer_t e = 0; + /* For sake of consistency with the rest of the library, IGRAPH_LOOPS_TWICE + * is treated as IGRAPH_LOOPS_ONCE for directed graphs */ + if (loops == IGRAPH_LOOPS_TWICE) { + loops = IGRAPH_LOOPS_ONCE; + } + for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { igraph_integer_t from = igraph_sparsemat_iterator_row(&it); igraph_integer_t to = igraph_sparsemat_iterator_col(&it); @@ -1378,7 +1479,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/atlas-edges.h b/src/vendor/cigraph/src/constructors/atlas-edges.h index 6faceda6f0b..c22560b58de 100644 --- a/src/vendor/cigraph/src/constructors/atlas-edges.h +++ b/src/vendor/cigraph/src/constructors/atlas-edges.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -27,7 +26,7 @@ #include "igraph_decls.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS const igraph_integer_t igraph_i_atlas_edges[] = { 0, 0, @@ -1287,6 +1286,6 @@ const igraph_integer_t igraph_i_atlas_edges[] = { const igraph_integer_t igraph_i_atlas_edges_pos[] = {0, 2, 4, 6, 10, 12, 16, 22, 30, 32, 36, 42, 48, 56, 64, 72, 82, 92, 104, 118, 120, 124, 130, 136, 144, 152, 160, 168, 178, 188, 198, 208, 218, 228, 240, 252, 264, 276, 288, 300, 314, 328, 342, 356, 370, 384, 400, 416, 432, 448, 466, 484, 504, 526, 528, 532, 538, 544, 552, 560, 568, 576, 584, 594, 604, 614, 624, 634, 644, 654, 664, 674, 686, 698, 710, 722, 734, 746, 758, 770, 782, 794, 806, 818, 830, 842, 854, 868, 882, 896, 910, 924, 938, 952, 966, 980, 994, 1008, 1022, 1036, 1050, 1064, 1078, 1092, 1106, 1120, 1134, 1148, 1164, 1180, 1196, 1212, 1228, 1244, 1260, 1276, 1292, 1308, 1324, 1340, 1356, 1372, 1388, 1404, 1420, 1436, 1452, 1468, 1484, 1500, 1516, 1532, 1550, 1568, 1586, 1604, 1622, 1640, 1658, 1676, 1694, 1712, 1730, 1748, 1766, 1784, 1802, 1820, 1838, 1856, 1874, 1892, 1910, 1928, 1946, 1964, 1984, 2004, 2024, 2044, 2064, 2084, 2104, 2124, 2144, 2164, 2184, 2204, 2224, 2244, 2264, 2284, 2304, 2324, 2344, 2364, 2384, 2406, 2428, 2450, 2472, 2494, 2516, 2538, 2560, 2582, 2604, 2626, 2648, 2670, 2692, 2714, 2738, 2762, 2786, 2810, 2834, 2858, 2882, 2906, 2930, 2956, 2982, 3008, 3034, 3060, 3088, 3116, 3146, 3178, 3180, 3184, 3190, 3196, 3204, 3212, 3220, 3228, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, 3326, 3336, 3348, 3360, 3372, 3384, 3396, 3408, 3420, 3432, 3444, 3456, 3468, 3480, 3492, 3504, 3516, 3528, 3540, 3552, 3564, 3576, 3588, 3602, 3616, 3630, 3644, 3658, 3672, 3686, 3700, 3714, 3728, 3742, 3756, 3770, 3784, 3798, 3812, 3826, 3840, 3854, 3868, 3882, 3896, 3910, 3924, 3938, 3952, 3966, 3980, 3994, 4008, 4022, 4036, 4050, 4064, 4078, 4092, 4106, 4120, 4134, 4148, 4162, 4178, 4194, 4210, 4226, 4242, 4258, 4274, 4290, 4306, 4322, 4338, 4354, 4370, 4386, 4402, 4418, 4434, 4450, 4466, 4482, 4498, 4514, 4530, 4546, 4562, 4578, 4594, 4610, 4626, 4642, 4658, 4674, 4690, 4706, 4722, 4738, 4754, 4770, 4786, 4802, 4818, 4834, 4850, 4866, 4882, 4898, 4914, 4930, 4946, 4962, 4978, 4994, 5010, 5026, 5042, 5058, 5074, 5090, 5106, 5122, 5138, 5154, 5170, 5186, 5202, 5220, 5238, 5256, 5274, 5292, 5310, 5328, 5346, 5364, 5382, 5400, 5418, 5436, 5454, 5472, 5490, 5508, 5526, 5544, 5562, 5580, 5598, 5616, 5634, 5652, 5670, 5688, 5706, 5724, 5742, 5760, 5778, 5796, 5814, 5832, 5850, 5868, 5886, 5904, 5922, 5940, 5958, 5976, 5994, 6012, 6030, 6048, 6066, 6084, 6102, 6120, 6138, 6156, 6174, 6192, 6210, 6228, 6246, 6264, 6282, 6300, 6318, 6336, 6354, 6372, 6390, 6408, 6426, 6444, 6462, 6480, 6498, 6516, 6534, 6552, 6570, 6588, 6606, 6624, 6642, 6660, 6678, 6696, 6714, 6732, 6750, 6768, 6786, 6804, 6822, 6840, 6858, 6876, 6894, 6912, 6930, 6948, 6968, 6988, 7008, 7028, 7048, 7068, 7088, 7108, 7128, 7148, 7168, 7188, 7208, 7228, 7248, 7268, 7288, 7308, 7328, 7348, 7368, 7388, 7408, 7428, 7448, 7468, 7488, 7508, 7528, 7548, 7568, 7588, 7608, 7628, 7648, 7668, 7688, 7708, 7728, 7748, 7768, 7788, 7808, 7828, 7848, 7868, 7888, 7908, 7928, 7948, 7968, 7988, 8008, 8028, 8048, 8068, 8088, 8108, 8128, 8148, 8168, 8188, 8208, 8228, 8248, 8268, 8288, 8308, 8328, 8348, 8368, 8388, 8408, 8428, 8448, 8468, 8488, 8508, 8528, 8548, 8568, 8588, 8608, 8628, 8648, 8668, 8688, 8708, 8728, 8748, 8768, 8788, 8808, 8828, 8848, 8868, 8888, 8908, 8928, 8948, 8968, 8988, 9008, 9028, 9048, 9068, 9088, 9108, 9128, 9148, 9168, 9188, 9208, 9228, 9248, 9268, 9288, 9308, 9328, 9348, 9368, 9388, 9408, 9428, 9448, 9468, 9488, 9508, 9528, 9548, 9568, 9590, 9612, 9634, 9656, 9678, 9700, 9722, 9744, 9766, 9788, 9810, 9832, 9854, 9876, 9898, 9920, 9942, 9964, 9986, 10008, 10030, 10052, 10074, 10096, 10118, 10140, 10162, 10184, 10206, 10228, 10250, 10272, 10294, 10316, 10338, 10360, 10382, 10404, 10426, 10448, 10470, 10492, 10514, 10536, 10558, 10580, 10602, 10624, 10646, 10668, 10690, 10712, 10734, 10756, 10778, 10800, 10822, 10844, 10866, 10888, 10910, 10932, 10954, 10976, 10998, 11020, 11042, 11064, 11086, 11108, 11130, 11152, 11174, 11196, 11218, 11240, 11262, 11284, 11306, 11328, 11350, 11372, 11394, 11416, 11438, 11460, 11482, 11504, 11526, 11548, 11570, 11592, 11614, 11636, 11658, 11680, 11702, 11724, 11746, 11768, 11790, 11812, 11834, 11856, 11878, 11900, 11922, 11944, 11966, 11988, 12010, 12032, 12054, 12076, 12098, 12120, 12142, 12164, 12186, 12208, 12230, 12252, 12274, 12296, 12318, 12340, 12362, 12384, 12406, 12428, 12450, 12472, 12494, 12516, 12538, 12560, 12582, 12604, 12626, 12648, 12670, 12692, 12714, 12736, 12758, 12780, 12802, 12824, 12848, 12872, 12896, 12920, 12944, 12968, 12992, 13016, 13040, 13064, 13088, 13112, 13136, 13160, 13184, 13208, 13232, 13256, 13280, 13304, 13328, 13352, 13376, 13400, 13424, 13448, 13472, 13496, 13520, 13544, 13568, 13592, 13616, 13640, 13664, 13688, 13712, 13736, 13760, 13784, 13808, 13832, 13856, 13880, 13904, 13928, 13952, 13976, 14000, 14024, 14048, 14072, 14096, 14120, 14144, 14168, 14192, 14216, 14240, 14264, 14288, 14312, 14336, 14360, 14384, 14408, 14432, 14456, 14480, 14504, 14528, 14552, 14576, 14600, 14624, 14648, 14672, 14696, 14720, 14744, 14768, 14792, 14816, 14840, 14864, 14888, 14912, 14936, 14960, 14984, 15008, 15032, 15056, 15080, 15104, 15128, 15152, 15176, 15200, 15224, 15248, 15272, 15296, 15320, 15344, 15368, 15392, 15416, 15440, 15464, 15488, 15512, 15536, 15560, 15584, 15608, 15632, 15656, 15680, 15704, 15728, 15752, 15776, 15800, 15824, 15848, 15872, 15896, 15920, 15944, 15968, 15992, 16016, 16040, 16064, 16088, 16112, 16136, 16160, 16184, 16208, 16232, 16256, 16280, 16304, 16328, 16352, 16376, 16402, 16428, 16454, 16480, 16506, 16532, 16558, 16584, 16610, 16636, 16662, 16688, 16714, 16740, 16766, 16792, 16818, 16844, 16870, 16896, 16922, 16948, 16974, 17000, 17026, 17052, 17078, 17104, 17130, 17156, 17182, 17208, 17234, 17260, 17286, 17312, 17338, 17364, 17390, 17416, 17442, 17468, 17494, 17520, 17546, 17572, 17598, 17624, 17650, 17676, 17702, 17728, 17754, 17780, 17806, 17832, 17858, 17884, 17910, 17936, 17962, 17988, 18014, 18040, 18066, 18092, 18118, 18144, 18170, 18196, 18222, 18248, 18274, 18300, 18326, 18352, 18378, 18404, 18430, 18456, 18482, 18508, 18534, 18560, 18586, 18612, 18638, 18664, 18690, 18716, 18742, 18768, 18794, 18820, 18846, 18872, 18898, 18924, 18950, 18976, 19002, 19028, 19054, 19080, 19106, 19132, 19158, 19184, 19210, 19236, 19262, 19288, 19314, 19340, 19366, 19392, 19418, 19444, 19470, 19496, 19522, 19548, 19574, 19600, 19626, 19652, 19678, 19704, 19730, 19756, 19782, 19810, 19838, 19866, 19894, 19922, 19950, 19978, 20006, 20034, 20062, 20090, 20118, 20146, 20174, 20202, 20230, 20258, 20286, 20314, 20342, 20370, 20398, 20426, 20454, 20482, 20510, 20538, 20566, 20594, 20622, 20650, 20678, 20706, 20734, 20762, 20790, 20818, 20846, 20874, 20902, 20930, 20958, 20986, 21014, 21042, 21070, 21098, 21126, 21154, 21182, 21210, 21238, 21266, 21294, 21322, 21350, 21378, 21406, 21434, 21462, 21490, 21518, 21546, 21574, 21602, 21630, 21658, 21686, 21714, 21742, 21770, 21798, 21826, 21854, 21882, 21910, 21938, 21966, 21994, 22022, 22050, 22078, 22106, 22134, 22162, 22190, 22218, 22246, 22274, 22302, 22330, 22358, 22386, 22414, 22442, 22470, 22498, 22528, 22558, 22588, 22618, 22648, 22678, 22708, 22738, 22768, 22798, 22828, 22858, 22888, 22918, 22948, 22978, 23008, 23038, 23068, 23098, 23128, 23158, 23188, 23218, 23248, 23278, 23308, 23338, 23368, 23398, 23428, 23458, 23488, 23518, 23548, 23578, 23608, 23638, 23668, 23698, 23728, 23758, 23788, 23818, 23848, 23878, 23908, 23938, 23968, 23998, 24028, 24058, 24088, 24118, 24148, 24178, 24208, 24238, 24268, 24298, 24328, 24358, 24388, 24418, 24448, 24480, 24512, 24544, 24576, 24608, 24640, 24672, 24704, 24736, 24768, 24800, 24832, 24864, 24896, 24928, 24960, 24992, 25024, 25056, 25088, 25120, 25152, 25184, 25216, 25248, 25280, 25312, 25344, 25376, 25408, 25440, 25472, 25504, 25536, 25568, 25600, 25632, 25664, 25696, 25728, 25760, 25794, 25828, 25862, 25896, 25930, 25964, 25998, 26032, 26066, 26100, 26134, 26168, 26202, 26236, 26270, 26304, 26338, 26372, 26406, 26440, 26474, 26510, 26546, 26582, 26618, 26654, 26690, 26726, 26762, 26798, 26834, 26872, 26910, 26948, 26986, 27024, 27064, 27104, 27146}; -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_CONSTRUCTORS_ATLAS_EDGES_H */ diff --git a/src/vendor/cigraph/src/constructors/basic_constructors.c b/src/vendor/cigraph/src/constructors/basic_constructors.c index 12f0e16893f..b626884cdf8 100644 --- a/src/vendor/cigraph/src/constructors/basic_constructors.c +++ b/src/vendor/cigraph/src/constructors/basic_constructors.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -51,10 +50,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 +66,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/constructors/de_bruijn.c b/src/vendor/cigraph/src/constructors/de_bruijn.c index e7a55d2b7e4..58df531f502 100644 --- a/src/vendor/cigraph/src/constructors/de_bruijn.c +++ b/src/vendor/cigraph/src/constructors/de_bruijn.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team diff --git a/src/vendor/cigraph/src/constructors/famous.c b/src/vendor/cigraph/src/constructors/famous.c index 7c26d901232..98ea77062eb 100644 --- a/src/vendor/cigraph/src/constructors/famous.c +++ b/src/vendor/cigraph/src/constructors/famous.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -20,8 +19,6 @@ */ -#include - #include "igraph_constructors.h" #include "internal/hacks.h" /* strcasecmp */ diff --git a/src/vendor/cigraph/src/constructors/full.c b/src/vendor/cigraph/src/constructors/full.c index c5774950d1b..16ac90cd275 100644 --- a/src/vendor/cigraph/src/constructors/full.c +++ b/src/vendor/cigraph/src/constructors/full.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team diff --git a/src/vendor/cigraph/src/constructors/kautz.c b/src/vendor/cigraph/src/constructors/kautz.c index 7684847b341..7976f116203 100644 --- a/src/vendor/cigraph/src/constructors/kautz.c +++ b/src/vendor/cigraph/src/constructors/kautz.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team diff --git a/src/vendor/cigraph/src/constructors/lattices.c b/src/vendor/cigraph/src/constructors/lattices.c index 7ea8e23c5ec..323b9308cf6 100644 --- a/src/vendor/cigraph/src/constructors/lattices.c +++ b/src/vendor/cigraph/src/constructors/lattices.c @@ -249,8 +249,6 @@ static igraph_error_t triangular_lattice_hex_shape( * \function igraph_triangular_lattice * \brief A triangular lattice with the given shape. * - * \experimental - * * Creates a triangular lattice whose vertices have the form (i, j) for non-negative * integers i and j and (i, j) is generally connected with (i + 1, j), (i, j + 1), * and (i - 1, j + 1). The function constructs a planar dual of the graph @@ -534,8 +532,6 @@ static igraph_error_t hexagonal_lattice_hex_shape( * \function igraph_hexagonal_lattice * \brief A hexagonal lattice with the given shape. * - * \experimental - * * Creates a hexagonal lattice whose vertices have the form (i, j) for non-negative * integers i and j and (i, j) is generally connected with (i + 1, j), and if i is * odd also with (i - 1, j + 1). The function constructs a planar dual of the graph diff --git a/src/vendor/cigraph/src/constructors/lcf.c b/src/vendor/cigraph/src/constructors/lcf.c index 44eb78640a8..0409db4ad70 100644 --- a/src/vendor/cigraph/src/constructors/lcf.c +++ b/src/vendor/cigraph/src/constructors/lcf.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -27,33 +26,38 @@ #include "math/safe_intop.h" /** - * \function igraph_lcf_vector + * \function igraph_lcf * \brief Creates a graph from LCF notation. * - * This function is essentially the same as \ref igraph_lcf(), only - * the way for giving the arguments is different. See \ref - * igraph_lcf() for details. + * LCF notation (named after Lederberg, Coxeter and Frucht) is a concise notation + * for 3-regular Hamiltonian graphs. It consists of three parameters: the + * number of vertices in the graph, a list of shifts giving additional + * edges to a cycle backbone, and another integer giving how many times + * the shifts should be performed. See + * https://mathworld.wolfram.com/LCFNotation.html for details. + * * \param graph Pointer to an uninitialized graph object. - * \param n Integer constant giving the number of vertices. - * \param shifts A vector giving the shifts. - * \param repeats An integer constant giving the number of repeats - * for the shifts. + * \param n Integer constant giving the number of vertices. This + * is normally set to the number of shifts multiplied by the + * number of repeats. + * \param shifts An integer vector giving the shifts. + * \param repeats The number of repeats for the shifts. * \return Error code. * - * \sa \ref igraph_lcf(), \ref igraph_extended_chordal_ring() + * \sa \ref igraph_lcf_small(), \ref igraph_extended_chordal_ring() * * Time complexity: O(|V|+|E|), linear in the number of vertices plus * the number of edges. */ -igraph_error_t igraph_lcf_vector(igraph_t *graph, igraph_integer_t n, - const igraph_vector_int_t *shifts, - igraph_integer_t repeats) { +igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, + const igraph_vector_int_t *shifts, + igraph_integer_t repeats) { igraph_vector_int_t edges; igraph_integer_t no_of_shifts = igraph_vector_int_size(shifts); - igraph_integer_t ptr = 0, i, sptr = 0; + igraph_integer_t ptr = 0, sptr = 0; igraph_integer_t no_of_nodes = n; - igraph_integer_t no_of_edges = n + no_of_shifts * repeats; + igraph_integer_t no_of_edges; igraph_integer_t no_of_edges2; if (repeats < 0) { @@ -69,7 +73,7 @@ igraph_error_t igraph_lcf_vector(igraph_t *graph, igraph_integer_t n, if (no_of_nodes > 0) { /* Create a ring first */ - for (i = 0; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { VECTOR(edges)[ptr++] = i; VECTOR(edges)[ptr++] = i + 1; } @@ -95,16 +99,12 @@ igraph_error_t igraph_lcf_vector(igraph_t *graph, igraph_integer_t n, } /** - * \function igraph_lcf - * \brief Creates a graph from LCF notation. + * \function igraph_lcf_small + * \brief Shorthand to create a graph from LCF notation, giving shifts as the arguments. * - * - * LCF is short for Lederberg-Coxeter-Frucht, it is a concise notation for - * 3-regular Hamiltonian graphs. It consists of three parameters: the - * number of vertices in the graph, a list of shifts giving additional - * edges to a cycle backbone, and another integer giving how many times - * the shifts should be performed. See - * https://mathworld.wolfram.com/LCFNotation.html for details. + * This function provides a shorthand to give the shifts of the LCF notation + * directly as function arguments. See \ref igraph_lcf() for an explanation + * of LCF notation. * * \param graph Pointer to an uninitialized graph object. * \param n Integer, the number of vertices in the graph. @@ -112,7 +112,7 @@ igraph_error_t igraph_lcf_vector(igraph_t *graph, igraph_integer_t n, * plus an additional 0 to mark the end of the arguments. * \return Error code. * - * \sa See \ref igraph_lcf_vector() for a similar function using an + * \sa See \ref igraph_lcf() for a similar function using an * \ref igraph_vector_t instead of the variable length argument list; * \ref igraph_circulant() to create circulant graphs. * @@ -121,7 +121,7 @@ igraph_error_t igraph_lcf_vector(igraph_t *graph, igraph_integer_t n, * * \example examples/simple/igraph_lcf.c */ -igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, ...) { +igraph_error_t igraph_lcf_small(igraph_t *graph, igraph_integer_t n, ...) { igraph_vector_int_t shifts; igraph_integer_t repeats; va_list ap; @@ -129,7 +129,7 @@ igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, ...) { IGRAPH_VECTOR_INT_INIT_FINALLY(&shifts, 0); va_start(ap, n); - while (1) { + while (true) { igraph_error_t err; int num = va_arg(ap, int); if (num == 0) { @@ -148,7 +148,7 @@ igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, ...) { repeats = igraph_vector_int_pop_back(&shifts); } - IGRAPH_CHECK(igraph_lcf_vector(graph, n, &shifts, repeats)); + IGRAPH_CHECK(igraph_lcf(graph, n, &shifts, repeats)); igraph_vector_int_destroy(&shifts); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/constructors/linegraph.c b/src/vendor/cigraph/src/constructors/linegraph.c index cad6070f0aa..1c7ab491b94 100644 --- a/src/vendor/cigraph/src/constructors/linegraph.c +++ b/src/vendor/cigraph/src/constructors/linegraph.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -47,7 +46,7 @@ static igraph_error_t igraph_i_linegraph_undirected(const igraph_t *graph, igrap IGRAPH_ALLOW_INTERRUPTION(); if (from != prev) { - IGRAPH_CHECK(igraph_incident(graph, &adjedges, from, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &adjedges, from, IGRAPH_ALL, IGRAPH_LOOPS)); } n = igraph_vector_int_size(&adjedges); for (igraph_integer_t i = 0; i < n; i++) { @@ -58,7 +57,7 @@ static igraph_error_t igraph_i_linegraph_undirected(const igraph_t *graph, igrap } } - IGRAPH_CHECK(igraph_incident(graph, &adjedges2, to, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &adjedges2, to, IGRAPH_ALL, IGRAPH_LOOPS)); n = igraph_vector_int_size(&adjedges2); for (igraph_integer_t i = 0; i < n; i++) { igraph_integer_t e2 = VECTOR(adjedges2)[i]; @@ -105,7 +104,7 @@ static igraph_error_t igraph_i_linegraph_directed(const igraph_t *graph, igraph_ IGRAPH_ALLOW_INTERRUPTION(); if (from != prev) { - IGRAPH_CHECK(igraph_incident(graph, &adjedges, from, IGRAPH_IN)); + IGRAPH_CHECK(igraph_incident(graph, &adjedges, from, IGRAPH_IN, IGRAPH_LOOPS)); } n = igraph_vector_int_size(&adjedges); for (j = 0; j < n; j++) { diff --git a/src/vendor/cigraph/src/constructors/mycielskian.c b/src/vendor/cigraph/src/constructors/mycielskian.c index e52f774b44e..2dd0cea7864 100644 --- a/src/vendor/cigraph/src/constructors/mycielskian.c +++ b/src/vendor/cigraph/src/constructors/mycielskian.c @@ -43,7 +43,7 @@ * \ili A vertex \c u_i corresponding to each vertex \c v_i of \c G. * \ili An extra vertex \c w. * \endilist - * + * * * The edges are added as follows: * @@ -52,7 +52,7 @@ * \ili For each edge (v_i, v_j) in \c G, two new edges are added: * (u_i, v_j) and (v_i, u_j). * \endilist - * + * * Thus, if \c G has \c n vertices and \c m edges, the Mycielskian M(G) * has 2n + 1 vertices, and 3m + n edges. * @@ -80,7 +80,7 @@ * m_k = ((2m + 2n + 1) * 3^k - n_{k+1}) / 2 * edges, where \c n and \c m are the vertex and edge count of the original * graph, respectively. - * + * * \param graph Pointer to the input graph. * \param res Pointer to an uninitialized graph object where the Mycielskian * of the input graph will be stored. @@ -188,7 +188,7 @@ igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_i * The Mycielski graph of order \p k, denoted \c M_k, is a triangle-free graph on * \p k vertices with chromatic number \p k. It is defined through the Mycielski * construction described in the documentation of \ref igraph_mycielskian(). - * + * * * Some authors define Mycielski graphs only for k > 1. * igraph extends this to all k >= 0. @@ -206,7 +206,7 @@ igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_i * The edge count is * m_k = (7 * 3^(k-2) + 1) / 2 - 3 * 2^(k - 2) for k > 1 * and 0 otherwise. - * + * * \param graph Pointer to an uninitialized graph object. The generated * Mycielski graph will be stored here. * \param k Integer, the order of the Mycielski graph (must be non-negative). diff --git a/src/vendor/cigraph/src/constructors/prufer.c b/src/vendor/cigraph/src/constructors/prufer.c index d2de9052d97..85df30d7e5a 100644 --- a/src/vendor/cigraph/src/constructors/prufer.c +++ b/src/vendor/cigraph/src/constructors/prufer.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team diff --git a/src/vendor/cigraph/src/constructors/regular.c b/src/vendor/cigraph/src/constructors/regular.c index ea0be7ebd6b..d3780785fcb 100644 --- a/src/vendor/cigraph/src/constructors/regular.c +++ b/src/vendor/cigraph/src/constructors/regular.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -285,29 +284,6 @@ igraph_error_t igraph_wheel(igraph_t *graph, igraph_integer_t n, igraph_wheel_mo return IGRAPH_SUCCESS; } -/** - * \ingroup generators - * \function igraph_lattice - * \brief Arbitrary dimensional square lattices (deprecated). - * - * \deprecated-by igraph_square_lattice 0.10.0 - */ -igraph_error_t igraph_lattice(igraph_t *graph, const igraph_vector_int_t *dimvector, - igraph_integer_t nei, igraph_bool_t directed, igraph_bool_t mutual, - igraph_bool_t circular) { - igraph_vector_bool_t periodic; - - IGRAPH_VECTOR_BOOL_INIT_FINALLY(&periodic, igraph_vector_int_size(dimvector)); - igraph_vector_bool_fill(&periodic, circular); - - IGRAPH_CHECK(igraph_square_lattice(graph, dimvector, nei, directed, mutual, &periodic)); - - igraph_vector_bool_destroy(&periodic); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - /** * \ingroup generators * \function igraph_square_lattice @@ -727,18 +703,6 @@ igraph_error_t igraph_kary_tree(igraph_t *graph, igraph_integer_t n, igraph_inte return IGRAPH_SUCCESS; } -/** - * \ingroup generators - * \function igraph_tree - * \brief Creates a k-ary tree in which almost all vertices have k children (deprecated alias). - * - * \deprecated-by igraph_kary_tree 0.10.0 - */ -igraph_error_t igraph_tree(igraph_t *graph, igraph_integer_t n, igraph_integer_t children, - igraph_tree_mode_t type) { - return igraph_kary_tree(graph, n, children, type); -} - /** * \ingroup generators * \function igraph_symmetric_tree @@ -932,8 +896,7 @@ igraph_error_t igraph_regular_tree(igraph_t *graph, igraph_integer_t h, igraph_i * \param directed Whether the graph should be directed. * \return Error code. * - * \sa \ref igraph_ring(), \ref igraph_lcf(), \ref igraph_lcf_vector(), - * \ref igraph_circulant() + * \sa \ref igraph_ring(), \ref igraph_lcf(), \ref igraph_circulant() * * Time complexity: O(|V|+|E|), the number of vertices plus the number * of edges. @@ -1001,8 +964,6 @@ igraph_error_t igraph_extended_chordal_ring( * \function igraph_hypercube * \brief The n-dimensional hypercube graph. * - * \experimental - * * The hypercube graph \c Q_n has 2^n vertices and * 2^(n-1) n edges. Two vertices are connected when the binary * representations of their zero-based vertex IDs differs in precisely one bit. diff --git a/src/vendor/cigraph/src/constructors/trees.c b/src/vendor/cigraph/src/constructors/trees.c index 16b625ccef5..e68b3478aeb 100644 --- a/src/vendor/cigraph/src/constructors/trees.c +++ b/src/vendor/cigraph/src/constructors/trees.c @@ -26,8 +26,6 @@ * \function igraph_tree_from_parent_vector * \brief Constructs a tree or forest from a vector encoding the parent of each vertex. * - * \experimental - * * Rooted trees and forests are conveniently represented using a \p parents * vector where the ID of the parent of vertex \c v is stored in parents[v]. * This function serves to construct an igraph graph from a parent vector representation. diff --git a/src/vendor/cigraph/src/core/array.c b/src/vendor/cigraph/src/core/array.c deleted file mode 100644 index 07bc67fad5d..00000000000 --- a/src/vendor/cigraph/src/core/array.c +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- mode: C -*- */ -/* - IGraph library. - Copyright (C) 2006-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#include "igraph_types.h" -#include "igraph_vector.h" -#include "igraph_array.h" - -#define BASE_IGRAPH_REAL -#include "igraph_pmt.h" -#include "array.pmt" -#include "igraph_pmt_off.h" -#undef BASE_IGRAPH_REAL - -#define BASE_INT -#include "igraph_pmt.h" -#include "array.pmt" -#include "igraph_pmt_off.h" -#undef BASE_INT - -#define BASE_CHAR -#include "igraph_pmt.h" -#include "array.pmt" -#include "igraph_pmt_off.h" -#undef BASE_CHAR - -#define BASE_BOOL -#include "igraph_pmt.h" -#include "array.pmt" -#include "igraph_pmt_off.h" -#undef BASE_BOOL diff --git a/src/vendor/cigraph/src/core/array.pmt b/src/vendor/cigraph/src/core/array.pmt deleted file mode 100644 index 227061f57ab..00000000000 --- a/src/vendor/cigraph/src/core/array.pmt +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- mode: C -*- */ -/* - IGraph library. - Copyright (C) 2006-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#include "igraph_types.h" - -#include "math/safe_intop.h" - -igraph_error_t FUNCTION(igraph_array3, init)(TYPE(igraph_array3) *a, - igraph_integer_t n1, igraph_integer_t n2, igraph_integer_t n3) { - - igraph_integer_t size, n1n2; - - IGRAPH_ASSERT(n1 >= 0 && n2 >= 0 && n3 >= 0); - - IGRAPH_SAFE_MULT(n1, n2, &n1n2); - IGRAPH_SAFE_MULT(n1n2, n3, &size); - - IGRAPH_CHECK(FUNCTION(igraph_vector, init)(&a->data, size)); - - a->n1 = n1; - a->n2 = n2; - a->n3 = n3; - a->n1n2 = n1n2; - - return IGRAPH_SUCCESS; -} - -void FUNCTION(igraph_array3, destroy)(TYPE(igraph_array3) *a) { - FUNCTION(igraph_vector, destroy)(&a->data); -} - -igraph_integer_t FUNCTION(igraph_array3, size)(const TYPE(igraph_array3) *a) { - return (a->n1n2) * (a->n3); -} - -igraph_integer_t FUNCTION(igraph_array3, n)(const TYPE(igraph_array3) *a, igraph_integer_t idx) { - switch (idx) { - case 1: return a->n1; - break; - case 2: return a->n2; - break; - case 3: return a->n3; - break; - } - return 0; -} - -igraph_error_t FUNCTION(igraph_array3, resize)( - TYPE(igraph_array3) *a, igraph_integer_t n1, igraph_integer_t n2, - igraph_integer_t n3) { - - igraph_integer_t size, n1n2; - - IGRAPH_ASSERT(n1 >= 0 && n2 >= 0 && n3 >= 0); - - IGRAPH_SAFE_MULT(n1, n2, &n1n2); - IGRAPH_SAFE_MULT(n1n2, n3, &size); - - IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&a->data, size)); - - a->n1 = n1; - a->n2 = n2; - a->n3 = n3; - a->n1n2 = n1n2; - - return IGRAPH_SUCCESS; -} - -void FUNCTION(igraph_array3, null)(TYPE(igraph_array3) *a) { - FUNCTION(igraph_vector, null)(&a->data); -} - -BASE FUNCTION(igraph_array3, sum)(const TYPE(igraph_array3) *a) { - return FUNCTION(igraph_vector, sum)(&a->data); -} - -void FUNCTION(igraph_array3, scale)(TYPE(igraph_array3) *a, BASE by) { - FUNCTION(igraph_vector, scale)(&a->data, by); -} - -void FUNCTION(igraph_array3, fill)(TYPE(igraph_array3) *a, BASE e) { - FUNCTION(igraph_vector, fill)(&a->data, e); -} - -igraph_error_t FUNCTION(igraph_array3, update)(TYPE(igraph_array3) *to, - const TYPE(igraph_array3) *from) { - IGRAPH_CHECK(FUNCTION(igraph_array3, resize)(to, from->n1, from->n2, from->n3)); - FUNCTION(igraph_vector, update)(&to->data, &from->data); - return IGRAPH_SUCCESS; -} diff --git a/src/vendor/cigraph/src/core/buckets.c b/src/vendor/cigraph/src/core/buckets.c index d2204cd99e3..7aa08b4b39b 100644 --- a/src/vendor/cigraph/src/core/buckets.c +++ b/src/vendor/cigraph/src/core/buckets.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/buckets.h b/src/vendor/cigraph/src/core/buckets.h index 176eddf5468..e88c4c923d2 100644 --- a/src/vendor/cigraph/src/core/buckets.h +++ b/src/vendor/cigraph/src/core/buckets.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2020 The igraph development team @@ -27,7 +26,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* Buckets, needed for the maximum flow algorithm */ @@ -67,6 +66,6 @@ void igraph_dbuckets_add(igraph_dbuckets_t *b, igraph_integer_t bucket, void igraph_dbuckets_delete(igraph_dbuckets_t *b, igraph_integer_t bucket, igraph_integer_t elem); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/cutheap.c b/src/vendor/cigraph/src/core/cutheap.c index 96dd1be7367..2d1abc9fff2 100644 --- a/src/vendor/cigraph/src/core/cutheap.c +++ b/src/vendor/cigraph/src/core/cutheap.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team diff --git a/src/vendor/cigraph/src/core/cutheap.h b/src/vendor/cigraph/src/core/cutheap.h index fcbb4cdcc39..078813dea21 100644 --- a/src/vendor/cigraph/src/core/cutheap.h +++ b/src/vendor/cigraph/src/core/cutheap.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2020 The igraph development team @@ -27,7 +26,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* Special maximum heap, needed for the minimum cut algorithm */ @@ -48,6 +47,6 @@ IGRAPH_PRIVATE_EXPORT igraph_integer_t igraph_i_cutheap_popmax(igraph_i_cutheap_ IGRAPH_PRIVATE_EXPORT void igraph_i_cutheap_update(igraph_i_cutheap_t *ch, igraph_integer_t index, igraph_real_t add); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_cutheap_reset_undefine(igraph_i_cutheap_t *ch, igraph_integer_t vertex); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/dqueue.c b/src/vendor/cigraph/src/core/dqueue.c index 20e8d953f8e..f226ed09cdf 100644 --- a/src/vendor/cigraph/src/core/dqueue.c +++ b/src/vendor/cigraph/src/core/dqueue.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/dqueue.pmt b/src/vendor/cigraph/src/core/dqueue.pmt index eb0f4c47caa..d9bc11698d5 100644 --- a/src/vendor/cigraph/src/core/dqueue.pmt +++ b/src/vendor/cigraph/src/core/dqueue.pmt @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -429,15 +428,3 @@ BASE FUNCTION(igraph_dqueue, get)(const TYPE(igraph_dqueue) *q, igraph_integer_t IGRAPH_FATAL("Out of bounds access in dqueue."); } } - -/** - * \ingroup dqueue - * \function igraph_dqueue_e - * \brief Access an element in a queue (deprecated alias). - * - * \deprecated-by igraph_dqueue_get 0.10.2 - */ - -BASE FUNCTION(igraph_dqueue, e)(const TYPE(igraph_dqueue) *q, igraph_integer_t idx) { - return FUNCTION(igraph_dqueue, get)(q, idx); -} diff --git a/src/vendor/cigraph/src/core/error.c b/src/vendor/cigraph/src/core/error.c index 6450659907d..e0202cd92f9 100644 --- a/src/vendor/cigraph/src/core/error.c +++ b/src/vendor/cigraph/src/core/error.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -92,63 +91,70 @@ static const char *igraph_i_error_strings[] = { /* 3 */ "Parse error", /* 4 */ "Invalid value", /* 5 */ "Already exists", - /* 6 */ "Invalid edge vector", + /* 6 */ NULL, // "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", /* 12 */ "Unimplemented function call", /* 13 */ "Interrupted", /* 14 */ "Numeric procedure did not converge", - /* 15 */ "Matrix-vector product failed", - /* 16 */ "N must be positive", - /* 17 */ "NEV must be positive", - /* 18 */ "NCV must be greater than NEV and less than or equal to N " - "(and for the non-symmetric solver NCV-NEV >=2 must also hold)", - /* 19 */ "Maximum number of iterations should be positive", - /* 20 */ "Invalid WHICH parameter", - /* 21 */ "Invalid BMAT parameter", - /* 22 */ "WORKL is too small", - /* 23 */ "LAPACK error in tridiagonal eigenvalue calculation", - /* 24 */ "Starting vector is zero", - /* 25 */ "MODE is invalid", - /* 26 */ "MODE and BMAT are not compatible", - /* 27 */ "ISHIFT must be 0 or 1", - /* 28 */ "NEV and WHICH='BE' are incompatible", - /* 29 */ "Could not build an Arnoldi factorization", - /* 30 */ "No eigenvalues to sufficient accuracy", - /* 31 */ "HOWMNY is invalid", - /* 32 */ "HOWMNY='S' is not implemented", - /* 33 */ "Different number of converged Ritz values", - /* 34 */ "Error from calculation of a real Schur form", - /* 35 */ "LAPACK (dtrevc) error for calculating eigenvectors", - /* 36 */ "Unknown ARPACK error", + + /* ARPACK error codes moved to igraph_arpack_error_t in arpack.c from version 1.0 */ + /* 15 */ "ARPACK error", // used to be "Matrix-vector product failed", + /* 16 */ NULL, // "N must be positive", + /* 17 */ NULL, // "NEV must be positive", + /* 18 */ NULL, // "NCV must be greater than NEV and less than or equal to N " + // "(and for the non-symmetric solver NCV-NEV >=2 must also hold)", + /* 19 */ NULL, // "Maximum number of iterations should be positive", + /* 20 */ NULL, // "Invalid WHICH parameter", + /* 21 */ NULL, // "Invalid BMAT parameter", + /* 22 */ NULL, // "WORKL is too small", + /* 23 */ NULL, // "LAPACK error in tridiagonal eigenvalue calculation", + /* 24 */ NULL, // "Starting vector is zero", + /* 25 */ NULL, // "MODE is invalid", + /* 26 */ NULL, // "MODE and BMAT are not compatible", + /* 27 */ NULL, // "ISHIFT must be 0 or 1", + /* 28 */ NULL, // "NEV and WHICH='BE' are incompatible", + /* 29 */ NULL, // "Could not build an Arnoldi factorization", + /* 30 */ NULL, // "No eigenvalues to sufficient accuracy", + /* 31 */ NULL, // "HOWMNY is invalid", + /* 32 */ NULL, // "HOWMNY='S' is not implemented", + /* 33 */ NULL, // "Different number of converged Ritz values", + /* 34 */ NULL, // "Error from calculation of a real Schur form", + /* 35 */ NULL, // "LAPACK (dtrevc) error for calculating eigenvectors", + /* 36 */ NULL, // "Unknown ARPACK error", + /* ARPACK error codes end here */ + /* 37 */ "Negative loop detected while calculating shortest paths", /* 38 */ "Internal error, likely a bug in igraph", - /* 39 */ "Maximum number of iterations reached", - /* 40 */ "No shifts could be applied during a cycle of the " - "Implicitly restarted Arnoldi iteration. One possibility " - "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", - /* 43 */ "GLPK Error, GLP_EBOUND", - /* 44 */ "GLPK Error, GLP_EROOT", - /* 45 */ "GLPK Error, GLP_ENOPFS", - /* 46 */ "GLPK Error, GLP_ENODFS", - /* 47 */ "GLPK Error, GLP_EFAIL", - /* 48 */ "GLPK Error, GLP_EMIPGAP", - /* 49 */ "GLPK Error, GLP_ETMLIM", - /* 50 */ "GLPK Error, GLP_STOP", - /* 51 */ "Internal attribute handler error", + + /* More ARPACK error codes moved to igraph_arpack_error_t in arpack.c from version 1.0 */ + /* 39 */ NULL, // "Maximum number of iterations reached", + /* 40 */ NULL, // "No shifts could be applied during a cycle of the " + // "Implicitly restarted Arnoldi iteration. One possibility " + // "is to increase the size of NCV relative to NEV", + /* 41 */ NULL, // "The Schur form computed by LAPACK routine dlahqr " + // "could not be reordered by LAPACK routine dtrsen.", + /* ARPACK error codes end here */ + + /* 42 */ NULL, // "Big integer division by zero", /* removed in 1.0 */ + /* 43 */ NULL, // "GLPK Error, GLP_EBOUND", /* removed in 1.0 */ + /* 44 */ NULL, // "GLPK Error, GLP_EROOT", /* removed in 1.0 */ + /* 45 */ NULL, // "GLPK Error, GLP_ENOPFS", /* removed in 1.0 */ + /* 46 */ NULL, // "GLPK Error, GLP_ENODFS", /* removed in 1.0 */ + /* 47 */ NULL, // "GLPK Error, GLP_EFAIL", /* removed in 1.0 */ + /* 48 */ NULL, // "GLPK Error, GLP_EMIPGAP", /* removed in 1.0 */ + /* 49 */ NULL, // "GLPK Error, GLP_ETMLIM", /* removed in 1.0 */ + /* 50 */ NULL, // "GLPK Error, GLP_STOP", /* removed in 1.0 */ + /* 51 */ NULL, // "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.", + /* 53 */ NULL, // "LAPACK call resulted in an error", /* removed in 1.0 */ + /* 54 */ NULL, // "Internal DrL error", /* removed in 1.0 */ /* 55 */ "Integer or double overflow", - /* 56 */ "Internal GPLK error", - /* 57 */ "CPU time exceeded", + /* 56 */ NULL, // "Internal GPLK error", /* removed in 1.0 */ + /* 57 */ NULL, // "CPU time exceeded", /* removed in 1.0 */ /* 58 */ "Integer or double underflow", /* 59 */ "Random walk got stuck", /* 60 */ "Search stopped; this error should never be visible to the user, " @@ -174,7 +180,10 @@ const char *igraph_strerror(const igraph_error_t igraph_errno) { (int) igraph_errno >= sizeof(igraph_i_error_strings) / sizeof(igraph_i_error_strings[0])) { IGRAPH_FATALF("Invalid error code %d; no error string available.", (int) igraph_errno); } - return igraph_i_error_strings[igraph_errno]; + const char *msg = igraph_i_error_strings[igraph_errno]; + /* Messages removed in 1.0 were replaced by NULL and should not be used. */ + IGRAPH_ASSERT(msg != NULL); + return msg; } diff --git a/src/vendor/cigraph/src/core/estack.c b/src/vendor/cigraph/src/core/estack.c index 7c45a2a82ba..7be14c90113 100644 --- a/src/vendor/cigraph/src/core/estack.c +++ b/src/vendor/cigraph/src/core/estack.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/estack.h b/src/vendor/cigraph/src/core/estack.h index 9a738a69733..6dbe7282d13 100644 --- a/src/vendor/cigraph/src/core/estack.h +++ b/src/vendor/cigraph/src/core/estack.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -28,7 +27,7 @@ #include "igraph_bitset.h" #include "igraph_stack.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef struct igraph_estack_t { igraph_stack_int_t stack; @@ -47,6 +46,6 @@ IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_estack_size(c IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_estack_print(const igraph_estack_t *s); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/fixed_vectorlist.c b/src/vendor/cigraph/src/core/fixed_vectorlist.c index 8b247f75599..89b239d8016 100644 --- a/src/vendor/cigraph/src/core/fixed_vectorlist.c +++ b/src/vendor/cigraph/src/core/fixed_vectorlist.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/fixed_vectorlist.h b/src/vendor/cigraph/src/core/fixed_vectorlist.h index 34e2437873a..9e393e36765 100644 --- a/src/vendor/cigraph/src/core/fixed_vectorlist.h +++ b/src/vendor/cigraph/src/core/fixed_vectorlist.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2012 Gabor Csardi @@ -29,7 +28,7 @@ #include "igraph_vector.h" #include "igraph_vector_list.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Vectorlist, fixed length */ @@ -45,6 +44,6 @@ igraph_error_t igraph_fixed_vectorlist_convert(igraph_fixed_vectorlist_t *l, const igraph_vector_int_t *from, igraph_integer_t size); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/grid.h b/src/vendor/cigraph/src/core/grid.h index 3043359752e..0446940a4be 100644 --- a/src/vendor/cigraph/src/core/grid.h +++ b/src/vendor/cigraph/src/core/grid.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2020 The igraph development team @@ -28,7 +27,7 @@ #include "igraph_matrix.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * 2d grid containing points @@ -73,6 +72,6 @@ igraph_integer_t igraph_2dgrid_next(igraph_2dgrid_t *grid, igraph_integer_t igraph_2dgrid_next_nei(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/heap.c b/src/vendor/cigraph/src/core/heap.c index a202ea64a60..641e0aee8a3 100644 --- a/src/vendor/cigraph/src/core/heap.c +++ b/src/vendor/cigraph/src/core/heap.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/heap.pmt b/src/vendor/cigraph/src/core/heap.pmt index 0aa14c97030..7883a9f261d 100644 --- a/src/vendor/cigraph/src/core/heap.pmt +++ b/src/vendor/cigraph/src/core/heap.pmt @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -62,7 +61,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 +86,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 +105,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..49de46a7a6c 100644 --- a/src/vendor/cigraph/src/core/indheap.c +++ b/src/vendor/cigraph/src/core/indheap.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -69,7 +68,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 +104,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++) { @@ -124,17 +121,13 @@ 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; - } - } + IGRAPH_ASSERT(h != NULL); + if (h->stor_begin != NULL) { + IGRAPH_FREE(h->stor_begin); + } + if (h->index_begin != NULL) { + IGRAPH_FREE(h->index_begin); + } } /** @@ -143,8 +136,8 @@ void igraph_indheap_destroy(igraph_indheap_t* h) { */ igraph_bool_t igraph_indheap_empty(const igraph_indheap_t *h) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); return h->stor_begin == h->end; } @@ -154,8 +147,8 @@ igraph_bool_t igraph_indheap_empty(const igraph_indheap_t *h) { */ igraph_error_t igraph_indheap_push(igraph_indheap_t* h, igraph_real_t elem) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); /* full, allocate more storage */ if (h->stor_end == h->end) { @@ -186,8 +179,8 @@ igraph_error_t igraph_indheap_push(igraph_indheap_t* h, igraph_real_t elem) { */ igraph_error_t igraph_indheap_push_with_index(igraph_indheap_t* h, igraph_integer_t idx, igraph_real_t elem) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); /* full, allocate more storage */ if (h->stor_end == h->end) { @@ -220,8 +213,8 @@ igraph_error_t igraph_indheap_push_with_index(igraph_indheap_t* h, igraph_intege void igraph_indheap_modify(igraph_indheap_t* h, igraph_integer_t idx, igraph_real_t elem) { igraph_integer_t i, n; - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); n = igraph_indheap_size(h); for (i = 0; i < n; i++) @@ -276,8 +269,8 @@ igraph_real_t igraph_indheap_delete_max(igraph_indheap_t* h) { */ igraph_integer_t igraph_indheap_size(const igraph_indheap_t* h) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); return h->end - h->stor_begin; } @@ -293,8 +286,8 @@ igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_integer_t size igraph_integer_t actual_size = igraph_indheap_size(h); igraph_real_t *tmp1; igraph_integer_t *tmp2; - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); if (size <= actual_size) { return IGRAPH_SUCCESS; @@ -330,8 +323,8 @@ igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_integer_t size */ igraph_integer_t igraph_indheap_max_index(const igraph_indheap_t *h) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); return h->index_begin[0]; } @@ -444,27 +437,26 @@ igraph_error_t igraph_d_indheap_init(igraph_d_indheap_t* h, igraph_integer_t all alloc_size = 1; } h->stor_begin = IGRAPH_CALLOC(alloc_size, igraph_real_t); - if (h->stor_begin == 0) { - h->index_begin = 0; - h->index2_begin = 0; + if (h->stor_begin == NULL) { + h->index_begin = NULL; + h->index2_begin = NULL; IGRAPH_ERROR("d_indheap init failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } 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) { + if (h->index_begin == NULL) { IGRAPH_FREE(h->stor_begin); - h->stor_begin = 0; - h->index2_begin = 0; + h->stor_begin = NULL; + h->index2_begin = NULL; IGRAPH_ERROR("d_indheap init failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } h->index2_begin = IGRAPH_CALLOC(alloc_size, igraph_integer_t); - if (h->index2_begin == 0) { + if (h->index2_begin == NULL) { IGRAPH_FREE(h->stor_begin); IGRAPH_FREE(h->index_begin); - h->stor_begin = 0; - h->index_begin = 0; + h->stor_begin = NULL; + h->index_begin = NULL; IGRAPH_ERROR("d_indheap init failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -477,20 +469,15 @@ 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; - } + IGRAPH_ASSERT(h != NULL); + if (h->stor_begin != NULL) { + IGRAPH_FREE(h->stor_begin); + } + if (h->index_begin != NULL) { + IGRAPH_FREE(h->index_begin); + } + if (h->index2_begin != NULL) { + IGRAPH_FREE(h->index2_begin); } } @@ -500,8 +487,8 @@ void igraph_d_indheap_destroy(igraph_d_indheap_t* h) { */ igraph_bool_t igraph_d_indheap_empty(const igraph_d_indheap_t *h) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); return h->stor_begin == h->end; } @@ -512,8 +499,8 @@ igraph_bool_t igraph_d_indheap_empty(const igraph_d_indheap_t *h) { igraph_error_t igraph_d_indheap_push(igraph_d_indheap_t* h, igraph_real_t elem, igraph_integer_t idx, igraph_integer_t idx2) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); /* full, allocate more storage */ if (h->stor_end == h->end) { @@ -577,8 +564,8 @@ igraph_real_t igraph_d_indheap_delete_max(igraph_d_indheap_t* h) { */ igraph_integer_t igraph_d_indheap_size(const igraph_d_indheap_t* h) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); return h->end - h->stor_begin; } @@ -594,8 +581,8 @@ igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t* h, igraph_integer_t igraph_integer_t actual_size = igraph_d_indheap_size(h); igraph_real_t *tmp1; igraph_integer_t *tmp2, *tmp3; - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); if (size <= actual_size) { return IGRAPH_SUCCESS; @@ -640,8 +627,8 @@ igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t* h, igraph_integer_t */ void igraph_d_indheap_max_index(igraph_d_indheap_t *h, igraph_integer_t *idx, igraph_integer_t *idx2) { - IGRAPH_ASSERT(h != 0); - IGRAPH_ASSERT(h->stor_begin != 0); + IGRAPH_ASSERT(h != NULL); + IGRAPH_ASSERT(h->stor_begin != NULL); (*idx) = h->index_begin[0]; (*idx2) = h->index2_begin[0]; } @@ -910,7 +897,7 @@ igraph_integer_t igraph_2wheap_max_index(const igraph_2wheap_t *h) { * it was deactivated earlier. */ igraph_bool_t igraph_2wheap_has_elem(const igraph_2wheap_t *h, igraph_integer_t idx) { - return VECTOR(h->index2)[idx] != 0; + return (VECTOR(h->index2)[idx] != 0); } /** diff --git a/src/vendor/cigraph/src/core/indheap.h b/src/vendor/cigraph/src/core/indheap.h index 93194cbf7c7..840d51ae413 100644 --- a/src/vendor/cigraph/src/core/indheap.h +++ b/src/vendor/cigraph/src/core/indheap.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2020 The igraph development team @@ -27,7 +26,7 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Indexed heap */ @@ -42,11 +41,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 +79,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); @@ -152,6 +149,6 @@ IGRAPH_PRIVATE_EXPORT igraph_real_t igraph_2wheap_delete_max_index(igraph_2wheap IGRAPH_PRIVATE_EXPORT void igraph_2wheap_modify(igraph_2wheap_t *h, igraph_integer_t idx, igraph_real_t elem); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_2wheap_check(const igraph_2wheap_t *h); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/interruption.c b/src/vendor/cigraph/src/core/interruption.c index 08aebf77d88..13cd2a65a88 100644 --- a/src/vendor/cigraph/src/core/interruption.c +++ b/src/vendor/cigraph/src/core/interruption.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -25,13 +24,13 @@ #include "config.h" /* IGRAPH_THREAD_LOCAL */ -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 a7866226d83..089e0742583 100644 --- a/src/vendor/cigraph/src/core/interruption.h +++ b/src/vendor/cigraph/src/core/interruption.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -29,7 +28,7 @@ #include "config.h" /* IGRAPH_THREAD_LOCAL */ -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS extern IGRAPH_THREAD_LOCAL igraph_interruption_handler_t *igraph_i_interruption_handler; @@ -38,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; \ } \ } \ @@ -77,6 +75,6 @@ extern IGRAPH_THREAD_LOCAL igraph_interruption_handler_t *igraph_i_interruption_ } \ } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/marked_queue.c b/src/vendor/cigraph/src/core/marked_queue.c index 29fe4116cba..3d4fa87f688 100644 --- a/src/vendor/cigraph/src/core/marked_queue.c +++ b/src/vendor/cigraph/src/core/marked_queue.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/marked_queue.h b/src/vendor/cigraph/src/core/marked_queue.h index 70a2fdce5ed..f0f8dac5553 100644 --- a/src/vendor/cigraph/src/core/marked_queue.h +++ b/src/vendor/cigraph/src/core/marked_queue.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -30,7 +29,7 @@ #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* This is essentially a double ended queue, with some extra features: (1) The is-element? operation is fast, O(1). This requires that we @@ -70,6 +69,6 @@ IGRAPH_PRIVATE_EXPORT void igraph_marked_queue_int_pop_back_batch(igraph_marked_ IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_marked_queue_int_as_vector(const igraph_marked_queue_int_t *q, igraph_vector_int_t *vec); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/matrix.c b/src/vendor/cigraph/src/core/matrix.c index 62a1c3c2fde..79b0db9c521 100644 --- a/src/vendor/cigraph/src/core/matrix.c +++ b/src/vendor/cigraph/src/core/matrix.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -221,19 +220,6 @@ igraph_bool_t igraph_matrix_complex_all_almost_e(igraph_matrix_complex_t *lhs, igraph_vector_complex_all_almost_e(&lhs->data, &rhs->data, eps); } -/** - * Deprecated in favour of \ref igraph_matrix_all_almost_e() which uses - * relative tolerances. Will be removed in 0.11. - * - * Checks if two matrices are equal within an absolute tolerance. - */ -igraph_bool_t igraph_matrix_all_e_tol(const igraph_matrix_t *lhs, - const igraph_matrix_t *rhs, - igraph_real_t tol) { - return lhs->ncol == rhs->ncol && lhs->nrow == rhs->nrow && - igraph_vector_e_tol(&lhs->data, &rhs->data, tol); -} - /** * \function igraph_matrix_all_almost_e diff --git a/src/vendor/cigraph/src/core/matrix.pmt b/src/vendor/cigraph/src/core/matrix.pmt index 6c1d00e165c..84dac7de7c3 100644 --- a/src/vendor/cigraph/src/core/matrix.pmt +++ b/src/vendor/cigraph/src/core/matrix.pmt @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -547,18 +546,6 @@ igraph_error_t FUNCTION(igraph_matrix, init_copy)(TYPE(igraph_matrix) *to, const return IGRAPH_SUCCESS; } -/** - * \ingroup matrix - * \function igraph_matrix_copy - * \brief Copies a matrix (deprecated alias). - * - * \deprecated-by igraph_matrix_init_copy 0.10 - */ - -igraph_error_t FUNCTION(igraph_matrix, copy)(TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from) { - return FUNCTION(igraph_matrix, init_copy)(to, from); -} - #ifndef NOTORDERED /** @@ -949,30 +936,6 @@ BASE* FUNCTION(igraph_matrix, get_ptr)(const TYPE(igraph_matrix) *m, return &MATRIX(*m, row, col); } -/** - * \function igraph_matrix_e - * Extract an element from a matrix (deprecated alias). - * - * \deprecated-by igraph_matrix_get 0.10.0 - */ - -BASE FUNCTION(igraph_matrix, e)(const TYPE(igraph_matrix) *m, - igraph_integer_t row, igraph_integer_t col) { - return FUNCTION(igraph_matrix, get)(m, row, col); -} - -/** - * \function igraph_matrix_e_ptr - * Pointer to an element of a matrix. - * - * \deprecated-by igraph_matrix_get_ptr 0.10.0 - */ - -BASE* FUNCTION(igraph_matrix, e_ptr)(const TYPE(igraph_matrix) *m, - igraph_integer_t row, igraph_integer_t col) { - return FUNCTION(igraph_matrix, get_ptr)(m, row, col); -} - /** * \function igraph_matrix_set * Set an element. @@ -1115,12 +1078,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; @@ -1131,9 +1093,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/matrix_list.c b/src/vendor/cigraph/src/core/matrix_list.c index f00e5d7d1c5..0dd8d4cda3f 100644 --- a/src/vendor/cigraph/src/core/matrix_list.c +++ b/src/vendor/cigraph/src/core/matrix_list.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2022 The igraph development team diff --git a/src/vendor/cigraph/src/core/printing.c b/src/vendor/cigraph/src/core/printing.c index 85635f581b8..181039d453d 100644 --- a/src/vendor/cigraph/src/core/printing.c +++ b/src/vendor/cigraph/src/core/printing.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/progress.c b/src/vendor/cigraph/src/core/progress.c index b5021e05f75..4a547d21072 100644 --- a/src/vendor/cigraph/src/core/progress.c +++ b/src/vendor/cigraph/src/core/progress.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -30,7 +29,7 @@ static IGRAPH_THREAD_LOCAL char igraph_i_progressmsg_buffer[1000]; /** * \function igraph_progress - * Report progress + * \brief Report the progress of a calculation from an igraph function. * * Note that the usual way to report progress is the \ref IGRAPH_PROGRESS * macro, as that takes care of the return value of the progress @@ -45,25 +44,22 @@ static IGRAPH_THREAD_LOCAL char igraph_i_progressmsg_buffer[1000]; * report progress pass a null pointer here. Users can * write their own progress handlers and functions with progress * reporting, and then pass some meaningfull context here. - * \return If there is a progress handler installed and - * it does not return \c IGRAPH_SUCCESS, then \c IGRAPH_INTERRUPTED - * is returned. + * \return Error code from the progress handler function, or \c IGRAPH_SUCCESS + * if no progress handler function was registered. * * Time complexity: O(1). */ igraph_error_t igraph_progress(const char *message, igraph_real_t percent, void *data) { if (igraph_i_progress_handler) { - if (igraph_i_progress_handler(message, percent, data) != IGRAPH_SUCCESS) { - return IGRAPH_INTERRUPTED; - } + return igraph_i_progress_handler(message, percent, data); } return IGRAPH_SUCCESS; } /** * \function igraph_progressf - * Report progress, printf-like version + * \brief Report the progress of a calculation from an igraph function, printf-like. * * This is a more flexible version of \ref igraph_progress(), with * a printf-like template string. First the template string @@ -84,9 +80,8 @@ igraph_error_t igraph_progress(const char *message, igraph_real_t percent, void * reporting, and then pass some meaningfull context here. * \param ... Additional argument that were specified in the * \p message argument. - * \return If there is a progress handler installed and - * it does not return \c IGRAPH_SUCCESS, then \c IGRAPH_INTERRUPTED - * is returned. + * \return Error code from the progress handler function, or \c IGRAPH_SUCCESS + * if no progress handler function was registered. * \return */ diff --git a/src/vendor/cigraph/src/core/psumtree.c b/src/vendor/cigraph/src/core/psumtree.c index f0bfc73720e..96c74c353d6 100644 --- a/src/vendor/cigraph/src/core/psumtree.c +++ b/src/vendor/cigraph/src/core/psumtree.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/set.h b/src/vendor/cigraph/src/core/set.h index cd6c8540d1c..63d4f16dab3 100644 --- a/src/vendor/cigraph/src/core/set.h +++ b/src/vendor/cigraph/src/core/set.h @@ -23,7 +23,7 @@ #include "igraph_error.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ /* Flexible set */ @@ -58,6 +58,6 @@ IGRAPH_PRIVATE_EXPORT igraph_bool_t igraph_set_iterate(const igraph_set_t *set, igraph_integer_t *state, igraph_integer_t *element); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/setup.c b/src/vendor/cigraph/src/core/setup.c new file mode 100644 index 00000000000..729f36704cc --- /dev/null +++ b/src/vendor/cigraph/src/core/setup.c @@ -0,0 +1,68 @@ +/* + IGraph library. + Copyright (C) 2025 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 . +*/ + +#include "igraph_setup.h" +#include "igraph_random.h" + +#include "random/random_internal.h" + +/** + * \ingroup setup + * \function setup_rng + * \brief Initializes the random number generator. + * + * This function initializes the igraph library by setting up a random seed + * for its internal random number generator. It should be called before + * using any igraph functions that may use random numbers. + * + * \return Error code; currently always \c IGRAPH_SUCCESS. + */ +static igraph_error_t setup_rng(void) { + igraph_rng_t *rng = igraph_rng_default(); + + if (!rng->is_seeded) { + igraph_rng_seed(rng, igraph_i_get_random_seed()); + rng->is_seeded = true; + }; + + return IGRAPH_SUCCESS; +} + +/** + * \ingroup setup + * \function igraph_setup + * \brief Initializes the igraph library. + * + * This function is a convenience function to call all setup functions that are + * provided by the igraph library. + * + * + * Most of the library functions will work even if this function is not called, + * but it is recommended to call it before using any igraph functions that may + * use random numbers, such as graph generators or random sampling functions. + * This function initializes the random number generator with a seed based on + * the current time, ensuring that the random numbers generated by igraph are + * different each time the program is run. + * + * \return Error code; currently always \c IGRAPH_SUCCESS. + */ +igraph_error_t igraph_setup(void) { + IGRAPH_CHECK(setup_rng()); + return IGRAPH_SUCCESS; +} + diff --git a/src/vendor/cigraph/src/core/sparsemat.c b/src/vendor/cigraph/src/core/sparsemat.c index c5803146785..fdd8accdc18 100644 --- a/src/vendor/cigraph/src/core/sparsemat.c +++ b/src/vendor/cigraph/src/core/sparsemat.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2012 Gabor Csardi @@ -28,7 +27,6 @@ #include "igraph_interface.h" #include "igraph_memory.h" #include "igraph_types.h" -#include "igraph_vector_ptr.h" #include "internal/hacks.h" /* IGRAPH_STATIC_ASSERT */ @@ -172,19 +170,6 @@ igraph_error_t igraph_sparsemat_init_copy( return IGRAPH_SUCCESS; } -/** - * \function igraph_sparsemat_copy - * \brief Copies a sparse matrix (deprecated alias). - * - * \deprecated-by igraph_sparsemat_init_copy 0.10 - */ - -igraph_error_t igraph_sparsemat_copy( - igraph_sparsemat_t *to, const igraph_sparsemat_t *from -) { - return igraph_sparsemat_init_copy(to, from); -} - /** * \function igraph_sparsemat_destroy * \brief Deallocates memory used by a sparse matrix. @@ -1010,7 +995,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 +1003,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 +1029,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 +1040,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 +1065,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 +1076,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 +1102,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 +1113,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 +1143,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 +1154,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 +1187,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,215 +1195,9 @@ 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); - } - - return IGRAPH_SUCCESS; -} - -static igraph_error_t igraph_i_sparsemat_cc(igraph_t *graph, const igraph_sparsemat_t *A, - igraph_bool_t directed) { - - igraph_vector_int_t edges; - CS_INT no_of_nodes = A->cs->m; - CS_INT no_of_edges = A->cs->p[A->cs->n]; - CS_INT *p = A->cs->p; - CS_INT *i = A->cs->i; - igraph_integer_t from = 0; - igraph_integer_t to = 0; - igraph_integer_t e = 0; - - if (no_of_nodes != A->cs->n) { - IGRAPH_ERROR("Cannot create graph object", IGRAPH_NONSQUARE); - } - - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); - - while (*p < no_of_edges) { - while (to < * (p + 1)) { - if (directed || from >= *i) { - VECTOR(edges)[e++] = from; - VECTOR(edges)[e++] = (*i); - } - to++; - i++; - } - from++; - p++; - } - igraph_vector_int_resize(&edges, e); - - IGRAPH_CHECK(igraph_create(graph, &edges, no_of_nodes, directed)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - -static igraph_error_t igraph_i_sparsemat_triplet(igraph_t *graph, const igraph_sparsemat_t *A, - igraph_bool_t directed) { - - igraph_vector_int_t edges; - CS_INT no_of_nodes = A->cs->m; - CS_INT no_of_edges = A->cs->nz; - CS_INT *i = A->cs->p; - CS_INT *j = A->cs->i; - igraph_integer_t e; - - if (no_of_nodes != A->cs->n) { - IGRAPH_ERROR("Cannot create graph object", IGRAPH_NONSQUARE); - } - - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); - - for (e = 0; e < 2 * no_of_edges; i++, j++) { - if (directed || *i >= *j) { - VECTOR(edges)[e++] = (*i); - VECTOR(edges)[e++] = (*j); - } - } - igraph_vector_int_resize(&edges, e); - - IGRAPH_CHECK(igraph_create(graph, &edges, no_of_nodes, directed)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - -/** - * \function igraph_sparsemat - * \brief Creates an igraph graph from a sparse matrix. - * - * One edge is created for each non-zero entry in the matrix. If you - * have a symmetric matrix, and want to create an undirected graph, - * then delete the entries in the upper diagonal first, or call \ref - * igraph_simplify() on the result graph to eliminate the multiple - * edges. - * - * \param graph Pointer to an uninitialized igraph_t object, the - * graphs is stored here. - * \param A The input matrix, in triplet or column-compressed format. - * \param directed Whether to create a directed graph. - * \return Error code. - * - * Time complexity: TODO. - */ - -igraph_error_t igraph_sparsemat(igraph_t *graph, const igraph_sparsemat_t *A, - igraph_bool_t directed) { - - if (igraph_sparsemat_is_cc(A)) { - return (igraph_i_sparsemat_cc(graph, A, directed)); - } else { - return (igraph_i_sparsemat_triplet(graph, A, directed)); - } -} - -static igraph_error_t igraph_i_weighted_sparsemat_cc(const igraph_sparsemat_t *A, - igraph_bool_t directed, const char *attr, - igraph_bool_t loops, - igraph_vector_int_t *edges, - igraph_vector_t *weights) { - - CS_INT no_of_edges = A->cs->p[A->cs->n]; - CS_INT *p = A->cs->p; - CS_INT *i = A->cs->i; - CS_ENTRY *x = A->cs->x; - igraph_integer_t from = 0; - igraph_integer_t to = 0; - igraph_integer_t e = 0, w = 0; - - IGRAPH_UNUSED(attr); - - IGRAPH_CHECK(igraph_vector_int_resize(edges, no_of_edges * 2)); - IGRAPH_CHECK(igraph_vector_resize(weights, no_of_edges)); - - while (*p < no_of_edges) { - while (to < * (p + 1)) { - if ( (loops || from != *i) && (directed || from >= *i) && *x != 0) { - VECTOR(*edges)[e++] = (*i); - VECTOR(*edges)[e++] = from; - VECTOR(*weights)[w++] = (*x); - } - to++; - i++; - x++; - } - from++; - p++; - } - - igraph_vector_int_resize(edges, e); /* shrinks */ - igraph_vector_resize(weights, w); /* shrinks */ - - return IGRAPH_SUCCESS; -} - -static igraph_error_t igraph_i_weighted_sparsemat_triplet(const igraph_sparsemat_t *A, - igraph_bool_t directed, - const char *attr, - igraph_bool_t loops, - igraph_vector_int_t *edges, - igraph_vector_t *weights) { - - IGRAPH_UNUSED(A); IGRAPH_UNUSED(directed); IGRAPH_UNUSED(attr); - IGRAPH_UNUSED(loops); IGRAPH_UNUSED(edges); IGRAPH_UNUSED(weights); - - /* TODO */ - IGRAPH_ERROR("Triplet matrices are not implemented", - IGRAPH_UNIMPLEMENTED); -} - -igraph_error_t igraph_weighted_sparsemat(igraph_t *graph, const igraph_sparsemat_t *A, - igraph_bool_t directed, const char *attr, - 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_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_VECTOR_INT_INIT_FINALLY(&edges, pot_edges * 2); - IGRAPH_VECTOR_INIT_FINALLY(&weights, pot_edges); - IGRAPH_VECTOR_PTR_INIT_FINALLY(&attr_vec, 1); - - if (igraph_sparsemat_is_cc(A)) { - IGRAPH_CHECK(igraph_i_weighted_sparsemat_cc(A, directed, attr, loops, - &edges, &weights)); - } else { - IGRAPH_CHECK(igraph_i_weighted_sparsemat_triplet(A, directed, attr, - loops, &edges, - &weights)); + IGRAPH_ERROR("Cannot perform LU solve.", IGRAPH_FAILURE); } - /* 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; - - /* 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_FINALLY_CLEAN(1); - - /* Cleanup */ - igraph_vector_int_destroy(&edges); - igraph_vector_destroy(&weights); - igraph_vector_ptr_destroy(&attr_vec); - IGRAPH_FINALLY_CLEAN(3); - return IGRAPH_SUCCESS; } @@ -1524,20 +1311,6 @@ igraph_error_t igraph_sparsemat_init_eye( } } -/** - * \function igraph_sparsemat_eye - * \brief Creates a sparse identity matrix (deprecated alias). - * - * \deprecated-by igraph_sparsemat_init_eye 0.10 - */ - -igraph_error_t igraph_sparsemat_eye( - igraph_sparsemat_t *A, igraph_integer_t n, igraph_integer_t nzmax, - igraph_real_t value, igraph_bool_t compress -) { - return igraph_sparsemat_init_eye(A, n, nzmax, value, compress); -} - static igraph_error_t igraph_i_sparsemat_init_diag_triplet( igraph_sparsemat_t *A, igraph_integer_t nzmax, const igraph_vector_t *values ) { @@ -1604,20 +1377,6 @@ igraph_error_t igraph_sparsemat_init_diag( } } -/** - * \function igraph_sparsemat_diag - * \brief Creates a sparse diagonal matrix (deprecated alias). - * - * \deprecated-by igraph_sparsemat_init_diag 0.10 - */ - -igraph_error_t igraph_sparsemat_diag( - igraph_sparsemat_t *A, igraph_integer_t nzmax, const igraph_vector_t *values, - igraph_bool_t compress -) { - return igraph_sparsemat_init_diag(A, nzmax, values, compress); -} - static igraph_error_t igraph_i_sparsemat_arpack_multiply(igraph_real_t *to, const igraph_real_t *from, int n, @@ -1702,11 +1461,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) { @@ -1806,11 +1565,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/stack.c b/src/vendor/cigraph/src/core/stack.c index 69b3b3efef9..483aa40bfeb 100644 --- a/src/vendor/cigraph/src/core/stack.c +++ b/src/vendor/cigraph/src/core/stack.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/stack.pmt b/src/vendor/cigraph/src/core/stack.pmt index 4be8cff534d..7f081117941 100644 --- a/src/vendor/cigraph/src/core/stack.pmt +++ b/src/vendor/cigraph/src/core/stack.pmt @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/statusbar.c b/src/vendor/cigraph/src/core/statusbar.c index 503bb34e44e..d8b947ff2a8 100644 --- a/src/vendor/cigraph/src/core/statusbar.c +++ b/src/vendor/cigraph/src/core/statusbar.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -39,26 +38,24 @@ static IGRAPH_THREAD_LOCAL igraph_status_handler_t *igraph_i_status_handler = 0; * one. Otherwise it does nothing. Note that the standard way to * report the status from an igraph function is the * \ref IGRAPH_STATUS or \ref IGRAPH_STATUSF macro, as these - * take care of the termination of the calling function if the - * status handler returns with \c IGRAPH_INTERRUPTED. + * take care of cleaning up allocated memory from the calling + * function if the status handler returns with an error code. * * \param message The status message. * \param data Additional context, with user-defined semantics. * Existing igraph functions pass a null pointer here. - * \return Error code. If a status handler function was called - * and it did not return with \c IGRAPH_SUCCESS, then - * \c IGRAPH_INTERRUPTED is returned by \c igraph_status(). + * \return Error code from the status handler function, or \c IGRAPH_SUCCESS + * if no status handler function was registered. * * Time complexity: O(1). */ igraph_error_t igraph_status(const char *message, void *data) { if (igraph_i_status_handler) { - if (igraph_i_status_handler(message, data) != IGRAPH_SUCCESS) { - return IGRAPH_INTERRUPTED; - } + return igraph_i_status_handler(message, data); + } else { + return IGRAPH_SUCCESS; } - return IGRAPH_SUCCESS; } /** @@ -69,15 +66,15 @@ igraph_error_t igraph_status(const char *message, void *data) { * that has a syntax similar to the \c printf standard C library function. * It substitutes the values of the additional arguments into the * \p message template string and calls \ref igraph_status(). + * * \param message Status message template string, the syntax is the same * as for the \c printf function. * \param data Additional context, with user-defined semantics. * Existing igraph functions pass a null pointer here. * \param ... The additional arguments to fill the template given in the * \p message argument. - * \return Error code. If a status handler function was called - * and it did not return with \c IGRAPH_SUCCESS, then - * \c IGRAPH_INTERRUPTED is returned by \ref igraph_status(). + * \return Error code from the status handler function, or \c IGRAPH_SUCCESS + * if no status handler function was registered. */ igraph_error_t igraph_statusf(const char *message, void *data, ...) { diff --git a/src/vendor/cigraph/src/core/strvector.c b/src/vendor/cigraph/src/core/strvector.c index 94293ee7632..51714ed5bdf 100644 --- a/src/vendor/cigraph/src/core/strvector.c +++ b/src/vendor/cigraph/src/core/strvector.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -21,8 +20,9 @@ */ -#include "igraph_types.h" #include "igraph_strvector.h" + +#include "igraph_types.h" #include "igraph_memory.h" #include "igraph_error.h" @@ -70,7 +70,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 +93,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 +171,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 +249,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++) { @@ -277,18 +276,6 @@ igraph_error_t igraph_strvector_init_copy(igraph_strvector_t *to, return IGRAPH_SUCCESS; } -/** - * \ingroup strvector - * \function igraph_strvector_copy - * \brief Initialization by copying (deprecated alias). - * - * \deprecated-by igraph_strvector_init_copy 0.10.0 - */ - -igraph_error_t igraph_strvector_copy(igraph_strvector_t *to, - const igraph_strvector_t *from) { - return igraph_strvector_init_copy(to, from); -} /** * \function igraph_strvector_append @@ -310,16 +297,25 @@ 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); - igraph_integer_t newlen; + const igraph_strvector_t *from) { + const igraph_integer_t to_size = igraph_strvector_size(to); + const igraph_integer_t from_size = igraph_strvector_size(from); + const igraph_integer_t to_capacity = igraph_strvector_capacity(to); + igraph_integer_t new_to_size; igraph_bool_t error = false; - char *tmp; + const char *tmp; - IGRAPH_SAFE_ADD(len1, len2, &newlen); - IGRAPH_CHECK(igraph_strvector_reserve(to, newlen)); + IGRAPH_SAFE_ADD(to_size, from_size, &new_to_size); + + if (to_capacity < new_to_size) { + igraph_integer_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; + if (new_to_capacity < new_to_size) { + new_to_capacity = new_to_size; + } + IGRAPH_CHECK(igraph_strvector_reserve(to, new_to_capacity)); + } - for (igraph_integer_t i = 0; i < len2; i++) { + for (igraph_integer_t i = 0; i < from_size; i++) { if (from->stor_begin[i] == NULL || from->stor_begin[i][0] == '\0') { /* Represent empty strings as NULL. */ tmp = NULL; @@ -335,7 +331,7 @@ igraph_error_t igraph_strvector_append(igraph_strvector_t *to, } if (error) { - igraph_strvector_resize(to, len1); /* always shrinks */ + igraph_strvector_resize(to, to_size); /* always shrinks */ IGRAPH_ERROR("Cannot append string vector.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -362,7 +358,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 +427,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 +480,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 +511,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; @@ -552,7 +545,7 @@ igraph_integer_t igraph_strvector_size(const igraph_strvector_t *sv) { * Ensures that the vector has at least one extra slot at the end of its * allocated storage area. */ -static igraph_error_t igraph_i_strvector_expand_if_full(igraph_strvector_t *sv) { +static igraph_error_t strvector_expand_if_full(igraph_strvector_t *sv) { IGRAPH_ASSERT(sv != NULL); IGRAPH_ASSERT(sv->stor_begin != NULL); @@ -585,8 +578,8 @@ 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); + IGRAPH_CHECK(strvector_expand_if_full(sv)); + const char *tmp = strdup(value); IGRAPH_CHECK_OOM(tmp, "Cannot push new string to string vector."); *sv->end = tmp; sv->end++; @@ -610,59 +603,32 @@ igraph_error_t igraph_strvector_push_back(igraph_strvector_t *sv, const char *va igraph_error_t igraph_strvector_push_back_len( igraph_strvector_t *sv, - const char *value, igraph_integer_t len) { + const char *value, size_t len) { - IGRAPH_CHECK(igraph_i_strvector_expand_if_full(sv)); - char *tmp = strndup(value, len); - if (! tmp) { - IGRAPH_ERROR("Cannot add string to string vector.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } + IGRAPH_CHECK(strvector_expand_if_full(sv)); + const char *tmp = strndup(value, len); + IGRAPH_CHECK_OOM(tmp, "Insufficient memory to push to string vector."); *sv->end = tmp; sv->end++; return IGRAPH_SUCCESS; } -/** - * \ingroup strvector - * \function igraph_strvector_add - * \brief Adds an element to the back of a string vector (deprecated alias). - * - * \deprecated-by igraph_strvector_push_back 0.10.0 - */ - -igraph_error_t igraph_strvector_add(igraph_strvector_t *sv, const char *value) { - return igraph_strvector_push_back(sv, value); -} - -/** - * \ingroup strvector - * \function igraph_strvector_set2 - * \brief Sets an element of the string vector given a buffer and its size (deprecated alias). - * - * \deprecated-by igraph_strvector_set_len 0.10.0 - */ - -igraph_error_t igraph_strvector_set2( - igraph_strvector_t *sv, igraph_integer_t idx, const char *value, size_t len -) { - return igraph_strvector_set_len(sv, idx, value, len); -} /** * \ingroup strvector * \function igraph_strvector_print - * \brief Prints a string vector. + * \brief Prints a string vector to a file. * * \param sv The string vector. * \param file The file to write to. * \param sep The separator to print between strings. * \return Error code. */ -igraph_error_t igraph_strvector_print(const igraph_strvector_t *sv, FILE *file, - const char *sep) { +igraph_error_t igraph_strvector_fprint(const igraph_strvector_t *sv, FILE *file, + const char *sep) { - igraph_integer_t n = igraph_strvector_size(sv); + const igraph_integer_t n = igraph_strvector_size(sv); if (n != 0) { fprintf(file, "%s", igraph_strvector_get(sv, 0)); } @@ -672,6 +638,22 @@ igraph_error_t igraph_strvector_print(const igraph_strvector_t *sv, FILE *file, return IGRAPH_SUCCESS; } +/** + * \ingroup strvector + * \function igraph_strvector_print + * \brief Prints a string vector. + * + * \param sv The string vector. + * \param sep The separator to print between strings. + * \return Error code. + */ +#ifndef USING_R +igraph_error_t igraph_strvector_print(const igraph_strvector_t *sv, + const char *sep) { + return igraph_strvector_fprint(sv, stdout, sep); +} +#endif + /** * \ingroup strvector * \function igraph_strvector_index @@ -698,6 +680,45 @@ 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; +} + /** * \function igraph_strvector_swap_elements * \brief Swap two elements in a string vector. @@ -711,7 +732,7 @@ igraph_error_t igraph_strvector_index(const igraph_strvector_t *sv, * Time complexity: O(1). */ void igraph_strvector_swap_elements(igraph_strvector_t *sv, igraph_integer_t i, igraph_integer_t j) { - char *tmp = sv->stor_begin[i]; + const char *tmp = sv->stor_begin[i]; sv->stor_begin[i] = sv->stor_begin[j]; sv->stor_begin[j] = tmp; } diff --git a/src/vendor/cigraph/src/core/trie.c b/src/vendor/cigraph/src/core/trie.c index 2c129bba3f8..751f55e9e82 100644 --- a/src/vendor/cigraph/src/core/trie.c +++ b/src/vendor/cigraph/src/core/trie.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/core/trie.h b/src/vendor/cigraph/src/core/trie.h index 3bfcb47ba85..58d75b4f017 100644 --- a/src/vendor/cigraph/src/core/trie.h +++ b/src/vendor/cigraph/src/core/trie.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2020 The igraph development team @@ -29,7 +28,7 @@ #include "igraph_vector.h" #include "igraph_vector_ptr.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * Trie data type @@ -67,6 +66,6 @@ IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_trie_size(igr const igraph_strvector_t* igraph_i_trie_borrow_keys(igraph_trie_t *t); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/core/typed_list.pmt b/src/vendor/cigraph/src/core/typed_list.pmt index 979af44deb9..7c30fdad6a3 100644 --- a/src/vendor/cigraph/src/core/typed_list.pmt +++ b/src/vendor/cigraph/src/core/typed_list.pmt @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2022 The igraph development team @@ -65,6 +64,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 #if defined(BASE_BITSET) #define ITEM_FUNCTION(f) CONCAT2x(igraph_bitset,f) @@ -120,6 +121,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 @@ -408,14 +441,12 @@ void FUNCTION(replace)(TYPE *v, igraph_integer_t pos, ITEM_TYPE *e) { * Time complexity: O(1). */ -igraph_error_t FUNCTION(swap)(TYPE *v1, TYPE *v2) { +void FUNCTION(swap)(TYPE *v1, TYPE *v2) { TYPE tmp; tmp = *v1; *v1 = *v2; *v2 = tmp; - - return IGRAPH_SUCCESS; } /** @@ -433,11 +464,10 @@ igraph_error_t FUNCTION(swap)(TYPE *v1, TYPE *v2) { * Time complexity: O(1). */ -igraph_error_t FUNCTION(swap_elements)(TYPE *v1, igraph_integer_t i, igraph_integer_t j) { +void FUNCTION(swap_elements)(TYPE *v1, igraph_integer_t i, igraph_integer_t j) { ITEM_TYPE tmp = v1->stor_begin[i]; v1->stor_begin[i] = v1->stor_begin[j]; v1->stor_begin[j] = tmp; - return IGRAPH_SUCCESS; } /** diff --git a/src/vendor/cigraph/src/core/vector.c b/src/vendor/cigraph/src/core/vector.c index dcc4a077d1f..e5da75c1b56 100644 --- a/src/vendor/cigraph/src/core/vector.c +++ b/src/vendor/cigraph/src/core/vector.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -59,8 +58,6 @@ #include "igraph_pmt_off.h" #undef BASE_COMPLEX -#include "core/indheap.h" - /** * \ingroup vector * \function igraph_vector_floor @@ -97,23 +94,6 @@ igraph_error_t igraph_vector_round(const igraph_vector_t *from, igraph_vector_in return IGRAPH_SUCCESS; } -igraph_error_t igraph_vector_order2(igraph_vector_t *v) { - igraph_indheap_t heap; - - IGRAPH_CHECK(igraph_indheap_init_array(&heap, VECTOR(*v), igraph_vector_size(v))); - IGRAPH_FINALLY(igraph_indheap_destroy, &heap); - - igraph_vector_clear(v); - while (!igraph_indheap_empty(&heap)) { - IGRAPH_CHECK(igraph_vector_push_back(v, igraph_indheap_max_index(&heap) - 1)); - igraph_indheap_delete_max(&heap); - } - - igraph_indheap_destroy(&heap); - IGRAPH_FINALLY_CLEAN(1); - return IGRAPH_SUCCESS; -} - /** * \ingroup vector * \function igraph_vector_int_pair_order @@ -200,23 +180,36 @@ igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, return IGRAPH_SUCCESS; } -igraph_error_t igraph_vector_int_order1(const igraph_vector_int_t* v, - igraph_vector_int_t* res, - igraph_integer_t nodes) { - igraph_integer_t edges = igraph_vector_int_size(v); +/** + * \function igraph_i_vector_int_order + * + * \param v Integer vector with non-negative entries. + * \param res The indices of the elements of \p v will be written here + * in sorted order. + * \param maxval The largest value in \p v must be provided here. + * \return Error code. + * + * Time complexity: O(maxval). + */ +igraph_error_t igraph_i_vector_int_order( + const igraph_vector_int_t *v, + igraph_vector_int_t *res, + igraph_integer_t maxval) { + + const igraph_integer_t size = igraph_vector_int_size(v); igraph_vector_int_t ptr; igraph_vector_int_t rad; - igraph_integer_t i, j; + igraph_integer_t j; IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); - IGRAPH_VECTOR_INT_INIT_FINALLY(&ptr, nodes + 1); - IGRAPH_VECTOR_INT_INIT_FINALLY(&rad, edges); - IGRAPH_CHECK(igraph_vector_int_resize(res, edges)); + IGRAPH_VECTOR_INT_INIT_FINALLY(&ptr, maxval + 1); + IGRAPH_VECTOR_INT_INIT_FINALLY(&rad, size); + IGRAPH_CHECK(igraph_vector_int_resize(res, size)); - for (i = 0; i < edges; i++) { - igraph_integer_t radix = v->stor_begin[i]; + for (igraph_integer_t i = 0; i < size; i++) { + igraph_integer_t radix = VECTOR(*v)[i]; if (VECTOR(ptr)[radix] != 0) { VECTOR(rad)[i] = VECTOR(ptr)[radix]; } @@ -224,13 +217,13 @@ igraph_error_t igraph_vector_int_order1(const igraph_vector_int_t* v, } j = 0; - for (i = 0; i < nodes + 1; i++) { + for (igraph_integer_t i = 0; i < maxval + 1; i++) { if (VECTOR(ptr)[i] != 0) { igraph_integer_t next = VECTOR(ptr)[i] - 1; - res->stor_begin[j++] = next; + VECTOR(*res)[j++] = next; while (VECTOR(rad)[next] != 0) { next = VECTOR(rad)[next] - 1; - res->stor_begin[j++] = next; + VECTOR(*res)[j++] = next; } } } @@ -242,25 +235,38 @@ igraph_error_t igraph_vector_int_order1(const igraph_vector_int_t* v, return IGRAPH_SUCCESS; } -igraph_error_t igraph_vector_rank( - const igraph_vector_t *v, igraph_vector_int_t *res, igraph_integer_t nodes) { +/** + * \function igraph_i_vector_int_rank + * + * \param v Integer vector with non-negative entries. + * \param res The zero-based rank of the elements of \p v will be written here + * from smallest to largest. + * \param maxval The largest value in \p v must be provided here. + * \return Error code. + * + * Time complexity: O(maxval). + */ +igraph_error_t igraph_i_vector_int_rank( + const igraph_vector_int_t *v, + igraph_vector_int_t *res, + igraph_integer_t maxval) { + const igraph_integer_t size = igraph_vector_int_size(v); igraph_vector_int_t rad; igraph_vector_int_t ptr; - igraph_integer_t edges = igraph_vector_size(v); - igraph_integer_t i, c = 0; + igraph_integer_t c = 0; - IGRAPH_VECTOR_INT_INIT_FINALLY(&rad, nodes); - IGRAPH_VECTOR_INT_INIT_FINALLY(&ptr, edges); - IGRAPH_CHECK(igraph_vector_int_resize(res, edges)); + IGRAPH_VECTOR_INT_INIT_FINALLY(&rad, maxval); + IGRAPH_VECTOR_INT_INIT_FINALLY(&ptr, size); + IGRAPH_CHECK(igraph_vector_int_resize(res, size)); - for (i = 0; i < edges; i++) { + for (igraph_integer_t i = 0; i < size; i++) { igraph_integer_t elem = VECTOR(*v)[i]; VECTOR(ptr)[i] = VECTOR(rad)[elem]; VECTOR(rad)[elem] = i + 1; } - for (i = 0; i < nodes; i++) { + for (igraph_integer_t i = 0; i < maxval; i++) { igraph_integer_t p = VECTOR(rad)[i]; while (p != 0) { VECTOR(*res)[p - 1] = c++; @@ -271,38 +277,7 @@ igraph_error_t igraph_vector_rank( igraph_vector_int_destroy(&ptr); igraph_vector_int_destroy(&rad); IGRAPH_FINALLY_CLEAN(2); - return IGRAPH_SUCCESS; -} - -igraph_error_t igraph_vector_int_rank( - const igraph_vector_int_t *v, igraph_vector_int_t *res, igraph_integer_t nodes) { - igraph_vector_int_t rad; - igraph_vector_int_t ptr; - igraph_integer_t edges = igraph_vector_int_size(v); - igraph_integer_t i, c = 0; - - IGRAPH_VECTOR_INT_INIT_FINALLY(&rad, nodes); - IGRAPH_VECTOR_INT_INIT_FINALLY(&ptr, edges); - IGRAPH_CHECK(igraph_vector_int_resize(res, edges)); - - for (i = 0; i < edges; i++) { - igraph_integer_t elem = VECTOR(*v)[i]; - VECTOR(ptr)[i] = VECTOR(rad)[elem]; - VECTOR(rad)[elem] = i + 1; - } - - for (i = 0; i < nodes; i++) { - igraph_integer_t p = VECTOR(rad)[i]; - while (p != 0) { - VECTOR(*res)[p - 1] = c++; - p = VECTOR(ptr)[p - 1]; - } - } - - igraph_vector_int_destroy(&ptr); - igraph_vector_int_destroy(&rad); - IGRAPH_FINALLY_CLEAN(2); return IGRAPH_SUCCESS; } @@ -476,38 +451,6 @@ igraph_bool_t igraph_vector_complex_all_almost_e(const igraph_vector_complex_t * return true; } -/** - * Deprecated in favour of \ref igraph_vector_all_almost_e() which uses - * relative tolerances. Will be removed in 0.11. - * - * Checks if two vectors are equal within an absolute tolerance. - */ -igraph_bool_t igraph_vector_e_tol(const igraph_vector_t *lhs, - const igraph_vector_t *rhs, - igraph_real_t tol) { - igraph_integer_t i, s; - IGRAPH_ASSERT(lhs != 0); - IGRAPH_ASSERT(rhs != 0); - IGRAPH_ASSERT(lhs->stor_begin != 0); - IGRAPH_ASSERT(rhs->stor_begin != 0); - - s = igraph_vector_size(lhs); - if (s != igraph_vector_size(rhs)) { - return false; - } else { - if (tol == 0) { - tol = DBL_EPSILON; - } - for (i = 0; i < s; i++) { - igraph_real_t l = VECTOR(*lhs)[i]; - igraph_real_t r = VECTOR(*rhs)[i]; - if (l < r - tol || l > r + tol) { - return false; - } - } - return true; - } -} /** * \function igraph_vector_all_almost_e diff --git a/src/vendor/cigraph/src/core/vector.pmt b/src/vendor/cigraph/src/core/vector.pmt index 53c057049f0..40a691f0bcb 100644 --- a/src/vendor/cigraph/src/core/vector.pmt +++ b/src/vendor/cigraph/src/core/vector.pmt @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -677,36 +676,6 @@ BASE* FUNCTION(igraph_vector, get_ptr)(const TYPE(igraph_vector) *v, igraph_inte return v->stor_begin + pos; } -/** - * \ingroup vector - * \function igraph_vector_e - * \brief Access an element of a vector (deprecated alias). - * - * \deprecated-by igraph_vector_get 0.10.0 - */ - -BASE FUNCTION(igraph_vector, e)(const TYPE(igraph_vector) *v, igraph_integer_t pos) { - return FUNCTION(igraph_vector, get)(v, pos); -} - -/** - * \ingroup vector - * \function igraph_vector_e_ptr - * \brief Get the address of an element of a vector. - * - * \param v The \type igraph_vector_t object. - * \param pos The position of the element, the position of the first - * element is zero. - * \return Pointer to the desired element. - * \sa \ref igraph_vector_get() and the \ref VECTOR macro. - * - * Time complexity: O(1). - */ - -BASE* FUNCTION(igraph_vector, e_ptr)(const TYPE(igraph_vector) *v, igraph_integer_t pos) { - return FUNCTION(igraph_vector, get_ptr)(v, pos); -} - /** * \ingroup vector * \function igraph_vector_set @@ -1092,17 +1061,6 @@ igraph_error_t FUNCTION(igraph_vector, sort_ind)( return IGRAPH_SUCCESS; } -/** - * \function igraph_vector_qsort_ind - * \brief Returns a permutation of indices that sorts a vector (deprecated alias). - * - * \deprecated-by igraph_vector_sort_ind 0.10.14 - */ -igraph_error_t FUNCTION(igraph_vector, qsort_ind)(const TYPE(igraph_vector) *v, - igraph_vector_int_t *inds, igraph_order_t order) { - return FUNCTION(igraph_vector, sort_ind)(v, inds, order); -} - /** * \function igraph_vector_lex_cmp * \brief Lexicographical comparison of two vectors (type-safe variant). @@ -1584,19 +1542,6 @@ igraph_error_t FUNCTION(igraph_vector, init_copy)( return IGRAPH_SUCCESS; } -/** - * \ingroup vector - * \function igraph_vector_copy - * \brief Initializes a vector from another vector object (deprecated alias). - * - * \deprecated-by igraph_vector_init_copy 0.10 - */ - -igraph_error_t FUNCTION(igraph_vector, copy)(TYPE(igraph_vector) *to, - const TYPE(igraph_vector) *from) { - return FUNCTION(igraph_vector, init_copy)(to, from); -} - /** * \ingroup vector * \function igraph_vector_sum @@ -1712,38 +1657,6 @@ igraph_error_t FUNCTION(igraph_vector, cumsum)(TYPE(igraph_vector) *to, #ifndef NOTORDERED -/** - * \ingroup vector - * \function igraph_vector_init_seq - * \brief Initializes a vector with a sequence, inclusive endpoints (deprecated). - * - * - * The vector will contain the numbers \p from, \p from+1, ..., \p to. Note that - * both endpoints are \em inclusive, contrary to typical usage of ranges in C. - * - * \deprecated-by igraph_vector_init_range 0.10.0 - * - * \param v Pointer to an uninitialized vector object. - * \param from The lower limit in the sequence (inclusive). - * \param to The upper limit in the sequence (inclusive). - * \return Error code: - * \c IGRAPH_ENOMEM: out of memory. - * - * Time complexity: O(n), the number - * of elements in the vector. - */ - -igraph_error_t FUNCTION(igraph_vector, init_seq)(TYPE(igraph_vector) *v, BASE from, BASE to) { - BASE *p; - IGRAPH_CHECK(FUNCTION(igraph_vector, init)(v, (to - from + 1))); - - for (p = v->stor_begin; p < v->end; p++) { - *p = from++; - } - - return IGRAPH_SUCCESS; -} - /** * \ingroup vector * \function igraph_vector_init_range @@ -1890,14 +1803,6 @@ igraph_error_t FUNCTION(igraph_vector, move_interval)(TYPE(igraph_vector) *v, return IGRAPH_SUCCESS; } -/** - * \deprecated-by igraph_vector_move_interval 0.10.0 - */ -igraph_error_t FUNCTION(igraph_vector, move_interval2)(TYPE(igraph_vector) *v, - igraph_integer_t begin, igraph_integer_t end, igraph_integer_t to) { - return FUNCTION(igraph_vector, move_interval)(v, begin, end, to); -} - #ifndef NOTORDERED /** @@ -2206,7 +2111,7 @@ static igraph_bool_t FUNCTION(igraph_i_vector, binsearch_slice)(const TYPE(igrap * vector if it is present. If \p v does not * contain \p what then * \p pos is set to the position to which it - * should be inserted (to keep the the vector sorted of course). + * should be inserted (to keep the vector sorted of course). * \return True if \p what is found in the vector, false otherwise. * * Time complexity: O(log(n)), @@ -2240,7 +2145,7 @@ igraph_bool_t FUNCTION(igraph_vector, binsearch)(const TYPE(igraph_vector) *v, * \param pos Pointer to an \type igraph_integer_t. This is set to the position of an * instance of \p what in the slice of the vector if it is present. If \p * v does not contain \p what then \p pos is set to the position to which - * it should be inserted (to keep the the vector sorted). + * it should be inserted (to keep the vector sorted). * \param start The start position of the slice to search (inclusive). * \param end The end position of the slice to search (exclusive). * \return True if \p what is found in the vector, false otherwise. @@ -2328,18 +2233,6 @@ igraph_bool_t FUNCTION(igraph_vector, contains_sorted)(const TYPE(igraph_vector) return false; } -/** - * \ingroup vector - * \function igraph_vector_binsearch2 - * \brief Binary search, without returning the index. - * - * \deprecated-by igraph_vector_contains_sorted 0.10.14 - */ -igraph_bool_t FUNCTION(igraph_vector, binsearch2)(const TYPE(igraph_vector) *v, - BASE what) { - return FUNCTION(igraph_vector, contains_sorted)(v, what); -} - #endif /** @@ -2504,17 +2397,28 @@ igraph_error_t FUNCTION(igraph_vector, filter_smaller)(TYPE(igraph_vector) *v, */ igraph_error_t FUNCTION(igraph_vector, append)(TYPE(igraph_vector) *to, - const TYPE(igraph_vector) *from) { - igraph_integer_t tosize, fromsize; - igraph_integer_t newsize; + const TYPE(igraph_vector) *from) { + IGRAPH_ASSERT(to != NULL); + IGRAPH_ASSERT(to->stor_begin != NULL); + + const igraph_integer_t to_size = FUNCTION(igraph_vector, size)(to); + const igraph_integer_t from_size = FUNCTION(igraph_vector, size)(from); + const igraph_integer_t to_capacity = FUNCTION(igraph_vector, capacity)(to); + igraph_integer_t new_to_size; - tosize = FUNCTION(igraph_vector, size)(to); - fromsize = FUNCTION(igraph_vector, size)(from); - IGRAPH_SAFE_ADD(tosize, fromsize, &newsize); - IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(to, newsize)); - memcpy(to->stor_begin + tosize, from->stor_begin, - sizeof(BASE) * fromsize); - to->end = to->stor_begin + tosize + fromsize; + IGRAPH_SAFE_ADD(to_size, from_size, &new_to_size); + + if (to_capacity < new_to_size) { + igraph_integer_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; + if (new_to_capacity < new_to_size) { + new_to_capacity = new_to_size; + } + IGRAPH_CHECK(FUNCTION(igraph_vector, reserve)(to, new_to_capacity)); + } + + memcpy(to->stor_begin + to_size, from->stor_begin, + sizeof(BASE) * from_size); + to->end = to->stor_begin + new_to_size; return IGRAPH_SUCCESS; } @@ -2603,20 +2507,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; } /** @@ -2624,22 +2525,19 @@ igraph_error_t FUNCTION(igraph_vector, swap)(TYPE(igraph_vector) *v1, TYPE(igrap * \brief Swap two elements in a vector. * * Note that currently no range checking is performed. + * * \param v The input vector. * \param i Index of the first element. - * \param j Index of the second element (may be the same as the - * first one). - * \return Error code, currently always \c IGRAPH_SUCCESS. + * \param j Index of the second element (may be the same as the first one). * * Time complexity: O(1). */ -igraph_error_t FUNCTION(igraph_vector, swap_elements)(TYPE(igraph_vector) *v, - igraph_integer_t i, igraph_integer_t j) { +void FUNCTION(igraph_vector, swap_elements)(TYPE(igraph_vector) *v, + igraph_integer_t i, igraph_integer_t j) { BASE tmp = VECTOR(*v)[i]; VECTOR(*v)[i] = VECTOR(*v)[j]; VECTOR(*v)[j] = tmp; - - return IGRAPH_SUCCESS; } /** @@ -2672,16 +2570,14 @@ void FUNCTION(igraph_vector, reverse_section)(TYPE(igraph_vector) *v, igraph_int * first, etc. * * \param v The input vector. - * \return Error code, currently always \c IGRAPH_SUCCESS. * * \sa igraph_vector_reverse_section() to reverse only a section of a vector. * * Time complexity: O(n), the number of elements. */ -igraph_error_t FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v) { +void FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v) { FUNCTION(igraph_vector, reverse_section)(v, 0, FUNCTION(igraph_vector, size)(v)); - return IGRAPH_SUCCESS; } /** @@ -2722,7 +2618,6 @@ void FUNCTION(igraph_vector, rotate_left)(TYPE(igraph_vector) *v, igraph_integer * 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 @@ -2743,12 +2638,11 @@ void FUNCTION(igraph_vector, rotate_left)(TYPE(igraph_vector) *v, igraph_integer * \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; - RNG_BEGIN(); while (n > 1) { k = RNG_INTEGER(0, n - 1); n--; @@ -2756,9 +2650,6 @@ igraph_error_t FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v) { VECTOR(*v)[n] = VECTOR(*v)[k]; VECTOR(*v)[k] = dummy; } - RNG_END(); - - return IGRAPH_SUCCESS; } /** @@ -3409,6 +3300,17 @@ igraph_error_t FUNCTION(igraph_vector, fprint)(const TYPE(igraph_vector) *v, FIL #endif /* defined(OUT_FORMAT) || defined(FPRINTFUNC) */ +/** + * \function igraph_vector_index + * \brief Extract elements from a vector at specific indices. + * + * \param v the vector to extract elements from + * \param newv the result vector + * \param idx vector containing the indices of the elements to extract + * + * \sa \ref igraph_vector_index_in_place for the in-place variant + */ + igraph_error_t FUNCTION(igraph_vector, index)(const TYPE(igraph_vector) *v, TYPE(igraph_vector) *newv, const igraph_vector_int_t *idx) { @@ -3424,7 +3326,18 @@ igraph_error_t FUNCTION(igraph_vector, index)(const TYPE(igraph_vector) *v, return IGRAPH_SUCCESS; } -igraph_error_t FUNCTION(igraph_vector, index_int)(TYPE(igraph_vector) *v, +/** + * \function igraph_vector_index_in_place + * \brief Extract elements from a vector at specific indices in-place. + * + * \param v the vector to extract elements from. This will be modified in-place. + * \param idx vector containing the indices of the elements to extract + * + * \sa \ref igraph_vector_index for a function that does not modify the original + * vector + */ + +igraph_error_t FUNCTION(igraph_vector, index_in_place)(TYPE(igraph_vector) *v, const igraph_vector_int_t *idx) { BASE *tmp; igraph_integer_t i, n = igraph_vector_int_size(idx); diff --git a/src/vendor/cigraph/src/core/vector_list.c b/src/vendor/cigraph/src/core/vector_list.c index 5f761b11530..bd51b4ccc28 100644 --- a/src/vendor/cigraph/src/core/vector_list.c +++ b/src/vendor/cigraph/src/core/vector_list.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2022 The igraph development team diff --git a/src/vendor/cigraph/src/core/vector_ptr.c b/src/vendor/cigraph/src/core/vector_ptr.c index ce063fd69da..182afb82465 100644 --- a/src/vendor/cigraph/src/core/vector_ptr.c +++ b/src/vendor/cigraph/src/core/vector_ptr.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -27,6 +26,8 @@ #include "igraph_memory.h" #include "igraph_qsort.h" +#include "math/safe_intop.h" + #include /* memcpy & co. */ #include /* uintptr_t */ #include @@ -205,10 +206,10 @@ void igraph_vector_ptr_destroy_all(igraph_vector_ptr_t* v) { /** * \ingroup vectorptr + * \function igraph_vector_ptr_reserve * \brief Reserves memory for a pointer vector for later use. * - * @return Error code: - * - IGRAPH_ENOMEM: out of memory + * \return Error code. */ igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_integer_t capacity) { @@ -232,6 +233,39 @@ igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_integer_ return IGRAPH_SUCCESS; } +/** + * \ingroup vectorptr + * \function igraph_vector_ptr_resize_min + * \brief Deallocate the unused memory of a pointer vector. + * + * This function attempts to deallocate the unused reserved storage + * of a pointer vector. If it succeeds, \ref igraph_vector_ptr_size() and + * \ref igraph_vector_ptr_capacity() will be the same. The data in the + * pointer vector is always preserved, even if deallocation is not successful. + * + * \param v Pointer to an initialized pointer vector. + * + * \sa \ref igraph_vector_ptr_resize(), \ref igraph_vector_ptr_reserve(). + * + * Time complexity: operating system dependent, O(n) at worst. + */ + +void igraph_vector_ptr_resize_min(igraph_vector_ptr_t* v) { + igraph_integer_t size; + void **tmp; + if (v->stor_end == v->end) { + return; + } + + size = (v->end - v->stor_begin); + tmp = IGRAPH_REALLOC(v->stor_begin, size, void *); + + if (tmp != NULL) { + v->stor_begin = tmp; + v->stor_end = v->end = v->stor_begin + size; + } +} + /** * \ingroup vectorptr * \brief Decides whether the pointer vector is empty. @@ -256,10 +290,27 @@ igraph_bool_t igraph_vector_ptr_empty(const igraph_vector_ptr_t* v) { igraph_integer_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v) { IGRAPH_ASSERT(v != NULL); - /* IGRAPH_ASSERT(v->stor_begin != NULL); */ /* TODO */ + IGRAPH_ASSERT(v->stor_begin != NULL); return v->end - v->stor_begin; } +/** + * \ingroup vectorptr + * \function igraph_vector_ptr_capacity + * \brief Returns the allocated capacity of the pointer vector. + * + * \param v The pointer vector object. + * \return The allocated capacity. + * + * Time complexity: O(1). + */ + +igraph_integer_t igraph_vector_ptr_capacity(const igraph_vector_ptr_t* v) { + IGRAPH_ASSERT(v != NULL); + IGRAPH_ASSERT(v->stor_begin != NULL); + return v->stor_end - v->stor_begin; +} + /** * \ingroup vectorptr * \function igraph_vector_ptr_clear @@ -391,18 +442,6 @@ void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_integer_t pos) return *(v->stor_begin + pos); } -/** - * \ingroup vectorptr - * \function igraph_vector_ptr_e - * \brief Access an element of a pointer vector (deprecated alias). - * - * \deprecated-by igraph_vector_ptr_get 0.10.0 - */ - -void *igraph_vector_ptr_e(const igraph_vector_ptr_t* v, igraph_integer_t pos) { - return igraph_vector_ptr_get(v, pos); -} - /** * \ingroup vectorptr * \function igraph_vector_ptr_set @@ -547,18 +586,6 @@ igraph_error_t igraph_vector_ptr_init_copy(igraph_vector_ptr_t *to, const igraph return IGRAPH_SUCCESS; } -/** - * \ingroup vectorptr - * \function igraph_vector_ptr_copy - * \brief Initializes a pointer vector from another one (deprecated alias). - * - * \deprecated-by igraph_vector_ptr_init_copy 0.10 - */ - -igraph_error_t igraph_vector_ptr_copy(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from) { - return igraph_vector_ptr_init_copy(to, from); -} - /** * \ingroup vectorptr * \brief Remove an element from a pointer vector. @@ -601,15 +628,25 @@ void igraph_vector_ptr_sort(igraph_vector_ptr_t *v, int (*compar)(const void*, c } igraph_error_t igraph_vector_ptr_append(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from) { - igraph_integer_t origsize = igraph_vector_ptr_size(to); - igraph_integer_t othersize = igraph_vector_ptr_size(from); - igraph_integer_t i; + const igraph_integer_t to_size = igraph_vector_ptr_size(to); + const igraph_integer_t from_size = igraph_vector_ptr_size(from); + const igraph_integer_t to_capacity = igraph_vector_ptr_capacity(to); + igraph_integer_t new_to_size; - IGRAPH_CHECK(igraph_vector_ptr_resize(to, origsize + othersize)); - for (i = 0; i < othersize; i++, origsize++) { - to->stor_begin[origsize] = from->stor_begin[i]; + IGRAPH_SAFE_ADD(to_size, from_size, &new_to_size); + + if (to_capacity < new_to_size) { + igraph_integer_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; + if (new_to_capacity < new_to_size) { + new_to_capacity = new_to_size; + } + IGRAPH_CHECK(igraph_vector_ptr_reserve(to, new_to_capacity)); } + memcpy(to->stor_begin + to_size, from->stor_begin, + sizeof(void *) * from_size); + to->end = to->stor_begin + new_to_size; + return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/flow/flow.c b/src/vendor/cigraph/src/flow/flow.c index 6a5cfd0f86d..d638a044724 100644 --- a/src/vendor/cigraph/src/flow/flow.c +++ b/src/vendor/cigraph/src/flow/flow.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -28,14 +27,13 @@ #include "igraph_conversion.h" #include "igraph_constants.h" #include "igraph_constructors.h" +#include "igraph_cycles.h" #include "igraph_dqueue.h" #include "igraph_error.h" #include "igraph_interface.h" -#include "igraph_memory.h" #include "igraph_progress.h" #include "igraph_operators.h" #include "igraph_structural.h" -#include "igraph_topology.h" #include "core/buckets.h" #include "core/cutheap.h" @@ -168,8 +166,8 @@ static igraph_error_t igraph_i_maxflow_undirected( const igraph_vector_t *capacity, igraph_maxflow_stats_t *stats) { - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t edges; igraph_vector_t newcapacity; igraph_t newgraph; @@ -493,9 +491,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, const igraph_vector_t *capacity, igraph_maxflow_stats_t *stats) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_orig_edges = igraph_ecount(graph); - igraph_integer_t no_of_edges = 2 * no_of_orig_edges; + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_integer_t no_of_orig_edges = igraph_ecount(graph); + const igraph_integer_t no_of_edges = 2 * no_of_orig_edges; igraph_vector_t rescap, excess; igraph_vector_int_t from, to, rev, distance; @@ -506,12 +504,12 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, igraph_dqueue_int_t bfsq; - igraph_integer_t i, j, idx; + igraph_integer_t idx; igraph_integer_t npushsince = 0, nrelabelsince = 0; igraph_maxflow_stats_t local_stats; /* used if the user passed a null pointer for stats */ - if (stats == 0) { + if (stats == NULL) { stats = &local_stats; } @@ -595,11 +593,11 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* Create the basic data structure */ IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0)); - IGRAPH_CHECK(igraph_vector_int_rank(&edges, &rank, no_of_nodes)); + IGRAPH_CHECK(igraph_i_vector_int_rank(&edges, &rank, no_of_nodes)); - for (i = 0; i < no_of_edges; i += 2) { - igraph_integer_t pos = VECTOR(rank)[i]; - igraph_integer_t pos2 = VECTOR(rank)[i + 1]; + for (igraph_integer_t i = 0; i < no_of_edges; i += 2) { + const igraph_integer_t pos = VECTOR(rank)[i]; + const igraph_integer_t pos2 = VECTOR(rank)[i + 1]; VECTOR(from)[pos] = VECTOR(edges)[i]; VECTOR(to)[pos] = VECTOR(edges)[i + 1]; VECTOR(from)[pos2] = VECTOR(edges)[i + 1]; @@ -614,13 +612,13 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, think, because of the possible isolate vertices. */ idx = -1; - for (i = 0; i <= VECTOR(from)[0]; i++) { + for (igraph_integer_t i = 0; i <= VECTOR(from)[0]; i++) { idx++; VECTOR(first)[idx] = 0; } - for (i = 1; i < no_of_edges; i++) { - igraph_integer_t n = (VECTOR(from)[i] - - VECTOR(from)[ VECTOR(first)[idx] ]); - for (j = 0; j < n; j++) { + for (igraph_integer_t i = 1; i < no_of_edges; i++) { + const igraph_integer_t n = (VECTOR(from)[i] - + VECTOR(from)[ VECTOR(first)[idx] ]); + for (igraph_integer_t j = 0; j < n; j++) { idx++; VECTOR(first)[idx] = i; } } @@ -640,7 +638,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* And the current pointers, initially the same as the first */ IGRAPH_VECTOR_INT_INIT_FINALLY(¤t, no_of_nodes); - for (i = 0; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { VECTOR(current)[i] = VECTOR(first)[i]; } @@ -652,9 +650,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, IGRAPH_FINALLY(igraph_dbuckets_destroy, &ibuckets); /* Send as much flow as possible from the source to its neighbors */ - for (i = FIRST(source), j = LAST(source); i < j; i++) { + for (igraph_integer_t i = FIRST(source), j = LAST(source); i < j; i++) { if (HEAD(i) != source) { - igraph_real_t delta = RESCAP(i); + const igraph_real_t delta = RESCAP(i); RESCAP(i) = 0; RESCAP(REV(i)) += delta; EXCESS(HEAD(i)) += delta; @@ -665,7 +663,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, (stats->nobfs)++; while (!igraph_buckets_empty(&buckets)) { - igraph_integer_t vertex = igraph_buckets_popmax(&buckets); + const igraph_integer_t vertex = igraph_buckets_popmax(&buckets); DISCHARGE(vertex); if (npushsince > no_of_nodes / 2 && nrelabelsince > no_of_nodes) { (stats->nobfs)++; @@ -698,8 +696,8 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, VECTOR(added)[target] = true; marked++; while (!igraph_dqueue_int_empty(&Q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); - for (i = FIRST(actnode), j = LAST(actnode); i < j; i++) { + const igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); + for (igraph_integer_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) { igraph_integer_t nei = HEAD(i); if (!VECTOR(added)[nei] && RESCAP(REV(i)) > 0.0) { VECTOR(added)[nei] = true; @@ -716,7 +714,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, if (cut) { igraph_vector_int_clear(cut); - for (i = 0; i < no_of_orig_edges; i++) { + for (igraph_integer_t i = 0; i < no_of_orig_edges; i++) { igraph_integer_t f = IGRAPH_FROM(graph, i); igraph_integer_t t = IGRAPH_TO(graph, i); if (!VECTOR(added)[f] && VECTOR(added)[t]) { @@ -728,7 +726,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, if (partition2) { igraph_integer_t x = 0; IGRAPH_CHECK(igraph_vector_int_resize(partition2, marked)); - for (i = 0; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { if (VECTOR(added)[i]) { VECTOR(*partition2)[x++] = i; } @@ -739,7 +737,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, igraph_integer_t x = 0; IGRAPH_CHECK(igraph_vector_int_resize(partition, no_of_nodes - marked)); - for (i = 0; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { if (!VECTOR(added)[i]) { VECTOR(*partition)[x++] = i; } @@ -755,7 +753,6 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, from the source */ igraph_dqueue_int_t Q; igraph_vector_int_t added; /* uses more than two values, cannot be bool */ - igraph_integer_t j, k, l; igraph_t flow_graph; igraph_vector_int_t flow_edges; igraph_bool_t dag; @@ -769,12 +766,12 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, IGRAPH_CHECK(igraph_dqueue_int_push(&Q, 0)); VECTOR(added)[source] = 1; while (!igraph_dqueue_int_empty(&Q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&Q); + const igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); + const igraph_integer_t actdist = igraph_dqueue_int_pop(&Q); DIST(actnode) = actdist; - for (i = FIRST(actnode), j = LAST(actnode); i < j; i++) { - igraph_integer_t nei = HEAD(i); + for (igraph_integer_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) { + const igraph_integer_t nei = HEAD(i); if (!VECTOR(added)[nei] && RESCAP(REV(i)) > 0.0) { VECTOR(added)[nei] = 1; IGRAPH_CHECK(igraph_dqueue_int_push(&Q, nei)); @@ -789,7 +786,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* Reinitialize the buckets */ igraph_buckets_clear(&buckets); - for (i = 0; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { if (EXCESS(i) > 0.0 && i != source && i != target) { igraph_buckets_add(&buckets, DIST(i), i); } @@ -797,10 +794,11 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* Now we return the flow to the source */ while (!igraph_buckets_empty(&buckets)) { - igraph_integer_t vertex = igraph_buckets_popmax(&buckets); + const igraph_integer_t vertex = igraph_buckets_popmax(&buckets); /* DISCHARGE(vertex) comes here */ do { + igraph_integer_t i, j; for (i = CURRENT(vertex), j = LAST(vertex); i < j; i++) { if (RESCAP(i) > 0) { igraph_integer_t nei = HEAD(i); @@ -833,7 +831,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, igraph_integer_t min; igraph_integer_t min_edge = 0; DIST(vertex) = min = no_of_nodes; - for (k = FIRST(vertex), l = LAST(vertex); k < l; k++) { + for (igraph_integer_t k = FIRST(vertex), l = LAST(vertex); k < l; k++) { if (RESCAP(k) > 0) { if (DIST(HEAD(k)) < min) { min = DIST(HEAD(k)); @@ -881,8 +879,8 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, 'stack', but it was visited before. */ IGRAPH_VECTOR_INT_INIT_FINALLY(&flow_edges, 0); - for (i = 0, j = 0; i < no_of_edges; i += 2, j++) { - igraph_integer_t pos = VECTOR(rank)[i]; + for (igraph_integer_t i = 0, j = 0; i < no_of_edges; i += 2, j++) { + const igraph_integer_t pos = VECTOR(rank)[i]; if ((capacity ? VECTOR(*capacity)[j] : 1.0) > RESCAP(pos)) { IGRAPH_CHECK(igraph_vector_int_push_back(&flow_edges, IGRAPH_FROM(graph, j))); @@ -911,9 +909,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, #define MYCAP(i) (VECTOR(mycap)[(i)]) - for (i = 0; i < no_of_edges; i += 2) { - igraph_integer_t pos = VECTOR(rank)[i]; - igraph_integer_t pos2 = VECTOR(rank)[i + 1]; + for (igraph_integer_t i = 0; i < no_of_edges; i += 2) { + const igraph_integer_t pos = VECTOR(rank)[i]; + const igraph_integer_t pos2 = VECTOR(rank)[i + 1]; MYCAP(pos) = (capacity ? VECTOR(*capacity)[i / 2] : 1.0) - RESCAP(pos); MYCAP(pos2) = 0.0; } @@ -928,7 +926,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, VECTOR(added)[source] = 1; while (!igraph_vector_int_empty(&stack) && igraph_vector_int_tail(&stack) != target) { - igraph_integer_t actnode = igraph_vector_int_tail(&stack); + const igraph_integer_t actnode = igraph_vector_int_tail(&stack); igraph_integer_t edge = FIRST(actnode) + CURRENT(actnode); igraph_integer_t nei; while (edge < LAST(actnode) && MYCAP(edge) == 0.0) { @@ -948,19 +946,18 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, until we find 'nei' again, determine the flow along the cycle. */ igraph_real_t thisflow = MYCAP(edge); - igraph_integer_t idx; - for (idx = igraph_vector_int_size(&stack) - 2; + for (igraph_integer_t idx = igraph_vector_int_size(&stack) - 2; idx >= 0 && VECTOR(stack)[idx + 1] != nei; idx -= 2) { - igraph_integer_t e = VECTOR(stack)[idx]; - igraph_real_t rcap = e >= 0 ? MYCAP(e) : MYCAP(edge); + const igraph_integer_t e = VECTOR(stack)[idx]; + const igraph_real_t rcap = e >= 0 ? MYCAP(e) : MYCAP(edge); if (rcap < thisflow) { thisflow = rcap; } } MYCAP(edge) -= thisflow; RESCAP(edge) += thisflow; - for (idx = igraph_vector_int_size(&stack) - 2; + for (igraph_integer_t idx = igraph_vector_int_size(&stack) - 2; idx >= 0 && VECTOR(stack)[idx + 1] != nei; idx -= 2) { - igraph_integer_t e = VECTOR(stack)[idx]; + const igraph_integer_t e = VECTOR(stack)[idx]; if (e >= 0) { MYCAP(e) -= thisflow; RESCAP(e) += thisflow; @@ -982,17 +979,17 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* If non-empty, then it contains a path from source to target in the residual graph. We factor out this path from the flow. */ if (!igraph_vector_int_empty(&stack)) { - igraph_integer_t pl = igraph_vector_int_size(&stack); + const igraph_integer_t pl = igraph_vector_int_size(&stack); igraph_real_t thisflow = EXCESS(target); - for (i = 2; i < pl; i += 2) { - igraph_integer_t edge = VECTOR(stack)[i]; - igraph_real_t rcap = MYCAP(edge); + for (igraph_integer_t i = 2; i < pl; i += 2) { + const igraph_integer_t edge = VECTOR(stack)[i]; + const igraph_real_t rcap = MYCAP(edge); if (rcap < thisflow) { thisflow = rcap; } } - for (i = 2; i < pl; i += 2) { - igraph_integer_t edge = VECTOR(stack)[i]; + for (igraph_integer_t i = 2; i < pl; i += 2) { + const igraph_integer_t edge = VECTOR(stack)[i]; MYCAP(edge) -= thisflow; } } @@ -1008,8 +1005,8 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* ----------------------------------------------------------- */ IGRAPH_CHECK(igraph_vector_resize(flow, no_of_orig_edges)); - for (i = 0, j = 0; i < no_of_edges; i += 2, j++) { - igraph_integer_t pos = VECTOR(rank)[i]; + for (igraph_integer_t i = 0, j = 0; i < no_of_edges; i += 2, j++) { + const igraph_integer_t pos = VECTOR(rank)[i]; VECTOR(*flow)[j] = (capacity ? VECTOR(*capacity)[j] : 1.0) - RESCAP(pos); } @@ -1135,7 +1132,7 @@ igraph_error_t igraph_st_mincut_value(const igraph_t *graph, igraph_real_t *valu IGRAPH_ERROR("source and target vertices are the same", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_maxflow_value(graph, value, source, target, capacity, 0)); + IGRAPH_CHECK(igraph_maxflow_value(graph, value, source, target, capacity, NULL)); return IGRAPH_SUCCESS; } @@ -1397,18 +1394,16 @@ static igraph_error_t igraph_i_mincut_undirected( igraph_integer_t bignode = VECTOR(mergehist)[2 * mincut_step + 1]; igraph_integer_t i, idx; igraph_integer_t size = 1; - bool *mark; + igraph_bitset_t mark; - mark = IGRAPH_CALLOC(no_of_nodes, bool); - IGRAPH_CHECK_OOM(mark, "Not enough memory for minimum cut."); - IGRAPH_FINALLY(igraph_free, mark); + IGRAPH_BITSET_INIT_FINALLY(&mark, no_of_nodes); /* first count the vertices in the partition */ - mark[bignode] = true; + IGRAPH_BIT_SET(mark, bignode); for (i = mincut_step - 1; i >= 0; i--) { - if ( mark[ VECTOR(mergehist)[2 * i] ] ) { + if ( IGRAPH_BIT_TEST(mark, VECTOR(mergehist)[2 * i]) ) { size++; - mark [ VECTOR(mergehist)[2 * i + 1] ] = true; + IGRAPH_BIT_SET(mark, VECTOR(mergehist)[2 * i + 1]); } } @@ -1418,7 +1413,7 @@ static igraph_error_t igraph_i_mincut_undirected( idx = 0; VECTOR(*partition)[idx++] = bignode; for (i = mincut_step - 1; i >= 0; i--) { - if (mark[ VECTOR(mergehist)[2 * i] ]) { + if (IGRAPH_BIT_TEST(mark, VECTOR(mergehist)[2 * i])) { VECTOR(*partition)[idx++] = VECTOR(mergehist)[2 * i + 1]; } } @@ -1429,7 +1424,7 @@ static igraph_error_t igraph_i_mincut_undirected( IGRAPH_CHECK(igraph_vector_int_resize(partition2, no_of_nodes - size)); idx = 0; for (i = 0; i < no_of_nodes; i++) { - if (!mark[i]) { + if (!IGRAPH_BIT_TEST(mark, i)) { VECTOR(*partition2)[idx++] = i; } } @@ -1444,8 +1439,8 @@ static igraph_error_t igraph_i_mincut_undirected( igraph_vector_int_clear(&mergehist); for (i = 0; i < no_of_edges; i++) { igraph_edge(graph, i, &from, &to); - if ((mark[from] && !mark[to]) || - (mark[to] && !mark[from])) { + if ((IGRAPH_BIT_TEST(mark, from) && !IGRAPH_BIT_TEST(mark, to)) || + (IGRAPH_BIT_TEST(mark, to) && !IGRAPH_BIT_TEST(mark, from))) { IGRAPH_CHECK(igraph_vector_int_push_back(&mergehist, i)); } } @@ -1453,7 +1448,7 @@ static igraph_error_t igraph_i_mincut_undirected( IGRAPH_CHECK(igraph_vector_int_append(cut, &mergehist)); } - IGRAPH_FREE(mark); + igraph_bitset_destroy(&mark); igraph_vector_int_destroy(&mergehist); IGRAPH_FINALLY_CLEAN(2); } @@ -1474,7 +1469,7 @@ static igraph_error_t igraph_i_mincut_directed( igraph_real_t flow; igraph_real_t minmaxflow = IGRAPH_INFINITY; igraph_vector_int_t mypartition, mypartition2, mycut; - igraph_vector_int_t *ppartition = 0, *ppartition2 = 0, *pcut = 0; + igraph_vector_int_t *ppartition = NULL, *ppartition2 = NULL, *pcut = NULL; igraph_vector_int_t bestpartition, bestpartition2, bestcut; if (partition) { @@ -1709,7 +1704,7 @@ igraph_error_t igraph_mincut_value(const igraph_t *graph, igraph_real_t *res, for (i = 1; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, 0, i, - capacity, 0)); + capacity, NULL)); if (flow < minmaxflow) { minmaxflow = flow; if (flow == 0) { @@ -1717,7 +1712,7 @@ igraph_error_t igraph_mincut_value(const igraph_t *graph, igraph_real_t *res, } } IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, i, 0, - capacity, 0)); + capacity, NULL)); if (flow < minmaxflow) { minmaxflow = flow; if (flow == 0) { @@ -1825,12 +1820,12 @@ static igraph_error_t igraph_i_st_vertex_connectivity_directed( /* "Disable" the edges incident on the input half of the source vertex * and the output half of the target vertex */ IGRAPH_VECTOR_INT_INIT_FINALLY(&incs, 0); - IGRAPH_CHECK(igraph_incident(&newgraph, &incs, source + no_of_nodes, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(&newgraph, &incs, source + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS)); len = igraph_vector_int_size(&incs); for (i = 0; i < len; i++) { VECTOR(capacity)[VECTOR(incs)[i]] = 0; } - IGRAPH_CHECK(igraph_incident(&newgraph, &incs, target, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(&newgraph, &incs, target, IGRAPH_ALL, IGRAPH_LOOPS)); len = igraph_vector_int_size(&incs); for (i = 0; i < len; i++) { VECTOR(capacity)[VECTOR(incs)[i]] = 0; @@ -1840,7 +1835,7 @@ static igraph_error_t igraph_i_st_vertex_connectivity_directed( /* Do the maximum flow */ IGRAPH_CHECK(igraph_maxflow_value(&newgraph, &real_res, - source, target + no_of_nodes, &capacity, 0)); + source, target + no_of_nodes, &capacity, NULL)); *res = (igraph_integer_t) real_res; *res -= no_conn; @@ -1996,12 +1991,12 @@ static igraph_error_t igraph_i_vertex_connectivity_directed( if (!done) { /* "Disable" the edges incident on the input half of the source vertex * and the output half of the target vertex */ - IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS)); len = igraph_vector_int_size(&incs); for (k = 0; k < len; k++) { VECTOR(capacity)[VECTOR(incs)[k]] = 0; } - IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL, IGRAPH_LOOPS)); len = igraph_vector_int_size(&incs); for (k = 0; k < len; k++) { VECTOR(capacity)[VECTOR(incs)[k]] = 0; @@ -2009,16 +2004,16 @@ static igraph_error_t igraph_i_vertex_connectivity_directed( /* Do the maximum flow */ IGRAPH_CHECK(igraph_maxflow_value( - &split_graph, &real_res, i, j + no_of_nodes, &capacity, 0 + &split_graph, &real_res, i, j + no_of_nodes, &capacity, NULL )); /* Restore the capacities */ - IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS)); len = igraph_vector_int_size(&incs); for (k = 0; k < len; k++) { VECTOR(capacity)[VECTOR(incs)[k]] = 1; } - IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL, IGRAPH_LOOPS)); len = igraph_vector_int_size(&incs); for (k = 0; k < len; k++) { VECTOR(capacity)[VECTOR(incs)[k]] = 1; @@ -2231,7 +2226,7 @@ igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph, IGRAPH_ERROR("The source and target vertices must be different.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, 0, 0)); + IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL)); *res = (igraph_integer_t) flow; return IGRAPH_SUCCESS; @@ -2339,7 +2334,7 @@ igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph, IGRAPH_UNIMPLEMENTED); } - IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, 0, 0)); + IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL)); *res = (igraph_integer_t) flow; diff --git a/src/vendor/cigraph/src/flow/flow_conversion.c b/src/vendor/cigraph/src/flow/flow_conversion.c index 01b20a5dddd..22814f54f3f 100644 --- a/src/vendor/cigraph/src/flow/flow_conversion.c +++ b/src/vendor/cigraph/src/flow/flow_conversion.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2023 The igraph development team diff --git a/src/vendor/cigraph/src/flow/flow_internal.h b/src/vendor/cigraph/src/flow/flow_internal.h index a269d0090dd..d95a7c165e9 100644 --- a/src/vendor/cigraph/src/flow/flow_internal.h +++ b/src/vendor/cigraph/src/flow/flow_internal.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2021 The igraph development team @@ -30,7 +29,7 @@ #include "core/estack.h" #include "core/marked_queue.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_all_st_cuts_pivot( const igraph_t *graph, const igraph_marked_queue_int_t *S, @@ -39,6 +38,6 @@ IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_all_st_cuts_pivot( igraph_error_t igraph_i_split_vertices(const igraph_t* graph, igraph_t* result); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/flow/st-cuts.c b/src/vendor/cigraph/src/flow/st-cuts.c index 6823b0d88e8..891c419ec68 100644 --- a/src/vendor/cigraph/src/flow/st-cuts.c +++ b/src/vendor/cigraph/src/flow/st-cuts.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2021 The igraph development team @@ -27,12 +26,12 @@ #include "igraph_constants.h" #include "igraph_constructors.h" #include "igraph_components.h" +#include "igraph_cycles.h" #include "igraph_error.h" #include "igraph_interface.h" #include "igraph_operators.h" #include "igraph_stack.h" #include "igraph_visitor.h" -#include "igraph_topology.h" #include "core/estack.h" #include "core/marked_queue.h" @@ -598,9 +597,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 +763,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 */ @@ -785,15 +782,16 @@ igraph_error_t igraph_i_all_st_cuts_pivot( /* TODO: use the adjacency list, instead of neighbors() */ IGRAPH_BITSET_INIT_FINALLY(&GammaS, no_of_nodes); if (igraph_marked_queue_int_size(S) == 0) { - IGRAPH_BIT_SET(GammaS, VECTOR(Sbar_map)[source] - 1); + IGRAPH_BIT_SET(GammaS, VECTOR(Sbar_map)[source]); } else { for (i = 0; i < no_of_nodes; i++) { if (igraph_marked_queue_int_iselement(S, i)) { igraph_vector_int_t neis; igraph_integer_t j; IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, - IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, i, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); for (j = 0; j < n; j++) { igraph_integer_t nei = VECTOR(neis)[j]; @@ -840,7 +838,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, @@ -1171,7 +1169,9 @@ static igraph_error_t igraph_i_all_st_mincuts_minimal(const igraph_t *residual, */ for (i = 0; i < no_of_nodes; i++) { igraph_integer_t j, n; - IGRAPH_CHECK(igraph_neighbors(residual, &neis, i, IGRAPH_IN)); + IGRAPH_CHECK(igraph_neighbors( + residual, &neis, i, IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); // Only consider nodes that are not in S. @@ -1429,7 +1429,7 @@ igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value /* Permute vertices and replace residual with tmpgraph that is topologically * sorted. */ - IGRAPH_CHECK(igraph_permute_vertices(&residual, &tmpgraph, &inv_order)); + IGRAPH_CHECK(igraph_permute_vertices(&residual, &tmpgraph, &order)); igraph_destroy(&residual); // We first free memory from original residual graph residual = tmpgraph; // Then we replace it by allocated memory from tmpgraph diff --git a/src/vendor/cigraph/src/games/barabasi.c b/src/vendor/cigraph/src/games/barabasi.c index 9ef883b2320..45b7144ede1 100644 --- a/src/vendor/cigraph/src/games/barabasi.c +++ b/src/vendor/cigraph/src/games/barabasi.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -146,8 +144,6 @@ static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer IGRAPH_CHECK(igraph_vector_int_resize(&edges, no_of_edges * 2)); } - RNG_BEGIN(); - /* and the others */ for (i = (start_from ? start_nodes : 1), k = (start_from ? 0 : 1); @@ -174,8 +170,6 @@ static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer } } - RNG_END(); - IGRAPH_FREE(bag); IGRAPH_CHECK(igraph_create(graph, &edges, no_of_nodes, directed)); igraph_vector_int_destroy(&edges); @@ -253,8 +247,6 @@ static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(&edges, no_of_edges * 2)); } - RNG_BEGIN(); - /* And the rest: */ for (i = (start_from ? start_nodes : 1), k = (start_from ? 0 : 1); i < no_of_nodes; i++, k++) { @@ -291,8 +283,6 @@ static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, } } - RNG_END(); - igraph_psumtree_destroy(&sumtree); igraph_vector_int_destroy(°ree); IGRAPH_FINALLY_CLEAN(2); @@ -352,8 +342,6 @@ static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, IGRAPH_FINALLY(igraph_psumtree_destroy, &sumtree); IGRAPH_VECTOR_INT_INIT_FINALLY(°ree, no_of_nodes); - RNG_BEGIN(); - /* First node(s): */ if (start_from) { igraph_integer_t ii, sn = igraph_vcount(start_from); @@ -425,8 +413,6 @@ static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, } } - RNG_END(); - igraph_psumtree_destroy(&sumtree); igraph_vector_int_destroy(°ree); IGRAPH_FINALLY_CLEAN(2); @@ -482,7 +468,7 @@ static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, * \param m The number of outgoing edges generated for each * vertex. Only used when \p outseq is \c NULL. * \param outseq Gives the (out-)degrees of the vertices. If this is - * constant, this can be a \c NULL pointer or an empty vector. + * constant, this can be a \c NULL pointer. * In this case \p m contains the constant out-degree. * The very first vertex has by definition no outgoing edges, * so the first number in this vector is ignored. @@ -547,10 +533,7 @@ igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_integer_t n, igraph_integer_t start_nodes = start_from ? igraph_vcount(start_from) : 0; igraph_integer_t newn = start_from ? n - start_nodes : n; - /* Fix obscure parameterizations */ - if (outseq && igraph_vector_int_empty(outseq)) { - outseq = NULL; - } + /* In undirected graphs, always consider the total degree. */ if (!directed) { outpref = true; } @@ -570,7 +553,7 @@ igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_integer_t n, if (!outseq && m < 0) { IGRAPH_ERROR("Number of edges added per step must not be negative.", IGRAPH_EINVAL); } - if (outseq && igraph_vector_int_min(outseq) < 0) { + if (outseq && newn > 0 && igraph_vector_int_min(outseq) < 0) { IGRAPH_ERROR("Negative out-degree in sequence.", IGRAPH_EINVAL); } if (!outpref && A <= 0) { @@ -708,12 +691,12 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, if (no_of_nodes < 0) { IGRAPH_ERRORF("Number of nodes must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, no_of_nodes); } - if (outseq != 0 && igraph_vector_int_size(outseq) != 0 && igraph_vector_int_size(outseq) != no_of_nodes) { + if (outseq && igraph_vector_int_size(outseq) != no_of_nodes) { IGRAPH_ERRORF("The length of the out-degree sequence (%" IGRAPH_PRId ") does not agree with the number of nodes (%" IGRAPH_PRId ").", IGRAPH_EINVAL, igraph_vector_int_size(outseq), no_of_nodes); } - if ( (outseq == 0 || igraph_vector_int_size(outseq) == 0) && m < 0) { + if (!outseq && m < 0) { IGRAPH_ERRORF("The number of edges per time step must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, m); @@ -745,13 +728,16 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, zero_age_appeal); } + /* This effectively also hanbdles an outseq size of 0. + * From here on we assume that outseq has a size of at least 1. */ if (no_of_nodes == 0) { - return igraph_empty(graph, 0, directed); + IGRAPH_CHECK(igraph_empty(graph, 0, directed)); + return IGRAPH_SUCCESS; } binwidth = no_of_nodes / aging_bins + 1; - if (outseq == 0 || igraph_vector_int_size(outseq) == 0) { + if (!outseq) { no_of_neighbors = m; IGRAPH_SAFE_MULT(no_of_nodes - 1, no_of_neighbors, &no_of_edges); } else { @@ -768,8 +754,6 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, IGRAPH_FINALLY(igraph_psumtree_destroy, &sumtree); IGRAPH_VECTOR_INT_INIT_FINALLY(°ree, no_of_nodes); - RNG_BEGIN(); - /* First node: */ /* Any weight may be used for the first node. In the first step, it will be connected to * with certainty, after which its weight will be set appropriately. */ @@ -782,7 +766,7 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, IGRAPH_ALLOW_INTERRUPTION(); - if (outseq != 0 && igraph_vector_int_size(outseq) != 0) { + if (outseq) { no_of_neighbors = VECTOR(*outseq)[i]; } sum = igraph_psumtree_sum(&sumtree); @@ -845,8 +829,6 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, } } - RNG_END(); - igraph_vector_int_destroy(°ree); igraph_psumtree_destroy(&sumtree); IGRAPH_FINALLY_CLEAN(2); diff --git a/src/vendor/cigraph/src/games/callaway_traits.c b/src/vendor/cigraph/src/games/callaway_traits.c index 8381e4e5544..0e019ee0279 100644 --- a/src/vendor/cigraph/src/games/callaway_traits.c +++ b/src/vendor/cigraph/src/games/callaway_traits.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -163,8 +161,6 @@ igraph_error_t igraph_callaway_traits_game(igraph_t *graph, igraph_integer_t nod IGRAPH_VECTOR_INT_INIT_FINALLY(nodetypes, nodes); } - RNG_BEGIN(); - for (i = 0; i < nodes; i++) { igraph_real_t uni = RNG_UNIF(0, maxcum); igraph_integer_t type; @@ -186,8 +182,6 @@ igraph_error_t igraph_callaway_traits_game(igraph_t *graph, igraph_integer_t nod } } - RNG_END(); - if (! node_type_vec) { igraph_vector_int_destroy(nodetypes); IGRAPH_FREE(nodetypes); diff --git a/src/vendor/cigraph/src/games/chung_lu.c b/src/vendor/cigraph/src/games/chung_lu.c index b0430774d08..6aa5a4c2698 100644 --- a/src/vendor/cigraph/src/games/chung_lu.c +++ b/src/vendor/cigraph/src/games/chung_lu.c @@ -234,7 +234,6 @@ igraph_error_t igraph_chung_lu_game(igraph_t *graph, IGRAPH_CHECK(igraph_vector_sort_ind(in_weights, &idx, IGRAPH_DESCENDING)); - RNG_BEGIN(); for (igraph_integer_t i=0; i < no_of_nodes; i++) { igraph_integer_t vi, vj; igraph_real_t wi, wj; @@ -309,7 +308,6 @@ igraph_error_t igraph_chung_lu_game(igraph_t *graph, IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 16); } } - RNG_END(); igraph_vector_int_destroy(&idx); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/games/citations.c b/src/vendor/cigraph/src/games/citations.c index 729778152f6..e193f16e957 100644 --- a/src/vendor/cigraph/src/games/citations.c +++ b/src/vendor/cigraph/src/games/citations.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -160,8 +158,6 @@ igraph_error_t igraph_lastcit_game(igraph_t *graph, index[0] = 0; index[1] = 0; - RNG_BEGIN(); - for (igraph_integer_t i = 1; i < no_of_nodes; i++) { /* Add new edges */ @@ -200,8 +196,6 @@ igraph_error_t igraph_lastcit_game(igraph_t *graph, } - RNG_END(); - igraph_psumtree_destroy(&sumtree); IGRAPH_FREE(index); IGRAPH_FREE(lastcit); @@ -300,8 +294,6 @@ igraph_error_t igraph_cited_type_game(igraph_t *graph, igraph_integer_t nodes, } sum = VECTOR(cumsum)[1] = nnval; - RNG_BEGIN(); - for (i = 1; i < nodes; i++) { for (j = 0; j < edges_per_step; j++) { igraph_integer_t to; @@ -325,8 +317,6 @@ igraph_error_t igraph_cited_type_game(igraph_t *graph, igraph_integer_t nodes, igraph_vector_push_back(&cumsum, sum); /* reserved */ } - RNG_END(); - igraph_vector_destroy(&cumsum); IGRAPH_FINALLY_CLEAN(1); IGRAPH_CHECK(igraph_create(graph, &edges, nodes, directed)); @@ -469,8 +459,6 @@ igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_integer_t n VECTOR(sums)[i] = MATRIX(*pref, i, type); } - RNG_BEGIN(); - for (i = 1; i < nodes; i++) { igraph_integer_t type = VECTOR(*types)[i]; igraph_real_t sum = VECTOR(sums)[type]; @@ -497,8 +485,6 @@ igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_integer_t n } } - RNG_END(); - igraph_i_citing_cited_type_game_free(&str); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/games/correlated.c b/src/vendor/cigraph/src/games/correlated.c index 576cffb7c96..b66b4c28901 100644 --- a/src/vendor/cigraph/src/games/correlated.c +++ b/src/vendor/cigraph/src/games/correlated.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -122,7 +120,7 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g IGRAPH_EINVAL); } } - IGRAPH_CHECK(igraph_is_simple(old_graph, &simple)); + IGRAPH_CHECK(igraph_is_simple(old_graph, &simple, IGRAPH_DIRECTED)); if (! simple) { IGRAPH_ERROR("The original graph must be simple for correlated Erdos-Renyi game.", IGRAPH_EINVAL); @@ -162,8 +160,6 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g */ sort_edges(&edges, old_graph); - RNG_BEGIN(); - if (p_del > 0) { last = RNG_GEOM(p_del); while (last < no_of_edges) { @@ -184,8 +180,6 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g } no_add = igraph_vector_size(&add); - RNG_END(); - /* Now we are merging the original edges, the edges that are removed, and the new edges. We have the following pointers: - p_a: the next edge to add diff --git a/src/vendor/cigraph/src/games/degree_sequence.c b/src/vendor/cigraph/src/games/degree_sequence.c index 37679de4964..b5646bd429c 100644 --- a/src/vendor/cigraph/src/games/degree_sequence.c +++ b/src/vendor/cigraph/src/games/degree_sequence.c @@ -39,7 +39,7 @@ static igraph_error_t configuration( const igraph_vector_int_t *out_seq, const igraph_vector_int_t *in_seq) { - const igraph_bool_t directed = (in_seq != NULL && igraph_vector_int_size(in_seq) != 0); + const igraph_bool_t directed = (in_seq != NULL); igraph_integer_t outsum = 0, insum = 0; igraph_bool_t graphical; igraph_integer_t no_of_nodes, no_of_edges; @@ -84,8 +84,6 @@ static igraph_error_t configuration( IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges * 2)); - RNG_BEGIN(); - if (directed) { for (igraph_integer_t i = 0; i < no_of_edges; i++) { igraph_integer_t from = RNG_INTEGER(0, bagp1 - 1); @@ -110,8 +108,6 @@ static igraph_error_t configuration( } } - RNG_END(); - IGRAPH_FREE(bag1); IGRAPH_FINALLY_CLEAN(1); if (directed) { @@ -160,9 +156,6 @@ static igraph_error_t fast_heur_undirected( IGRAPH_CHECK(igraph_set_init(&incomplete_vertices, 0)); IGRAPH_FINALLY(igraph_set_destroy, &incomplete_vertices); - /* Start the RNG */ - RNG_BEGIN(); - /* Outer loop; this will try to construct a graph several times from scratch * until it finally succeeds. */ finished = false; @@ -248,9 +241,6 @@ static igraph_error_t fast_heur_undirected( } } - /* Finish the RNG */ - RNG_END(); - /* Clean up */ igraph_set_destroy(&incomplete_vertices); igraph_vector_int_destroy(&residual_degrees); @@ -310,9 +300,6 @@ static igraph_error_t fast_heur_directed( IGRAPH_CHECK(igraph_set_init(&incomplete_in_vertices, 0)); IGRAPH_FINALLY(igraph_set_destroy, &incomplete_in_vertices); - /* Start the RNG */ - RNG_BEGIN(); - /* Outer loop; this will try to construct a graph several times from scratch * until it finally succeeds. */ finished = false; @@ -395,9 +382,6 @@ static igraph_error_t fast_heur_directed( } } - /* Finish the RNG */ - RNG_END(); - /* Clean up */ igraph_set_destroy(&incomplete_in_vertices); igraph_set_destroy(&incomplete_out_vertices); @@ -448,8 +432,6 @@ static igraph_error_t configuration_simple_undirected_set( IGRAPH_CHECK(igraph_set_reserve(set, VECTOR(*degseq)[i])); } - RNG_BEGIN(); - for (;;) { igraph_bool_t success = true; @@ -495,8 +477,6 @@ static igraph_error_t configuration_simple_undirected_set( IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); } - RNG_END(); - igraph_vector_ptr_destroy_all(&adjlist); IGRAPH_FINALLY_CLEAN(1); @@ -518,8 +498,6 @@ static igraph_error_t configuration_simple_undirected_bitset( IGRAPH_CHECK(igraph_bitset_resize(igraph_bitset_list_get_ptr(&adjlist, i), vcount)); } - RNG_BEGIN(); - for (;;) { igraph_bool_t success = true; @@ -565,8 +543,6 @@ static igraph_error_t configuration_simple_undirected_bitset( IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); } - RNG_END(); - igraph_bitset_list_destroy(&adjlist); IGRAPH_FINALLY_CLEAN(1); @@ -671,8 +647,6 @@ static igraph_error_t configuration_simple_directed( igraph_integer_t vertex_done_mark = 1; - RNG_BEGIN(); - for (;;) { igraph_bool_t success = true; igraph_integer_t previous_to = -1; @@ -715,8 +689,6 @@ static igraph_error_t configuration_simple_directed( IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); } - RNG_END(); - for (igraph_integer_t i=0; i < ecount; i++) { VECTOR(edges)[2*i] = VECTOR(out_stubs)[i]; VECTOR(edges)[2*i+1] = VECTOR(in_stubs)[i]; @@ -744,7 +716,7 @@ igraph_error_t edge_switching( IGRAPH_CHECK(igraph_realize_degree_sequence(graph, out_seq, in_seq, IGRAPH_SIMPLE_SW, IGRAPH_REALIZE_DEGSEQ_INDEX)); IGRAPH_FINALLY(igraph_destroy, graph); - IGRAPH_CHECK(igraph_rewire(graph, 10 * igraph_ecount(graph), IGRAPH_REWIRING_SIMPLE)); + IGRAPH_CHECK(igraph_rewire(graph, 10 * igraph_ecount(graph), IGRAPH_SIMPLE_SW)); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; } @@ -778,13 +750,10 @@ igraph_error_t edge_switching( * https://doi.org/10.1088/2632-072x/abced5. * * \param graph Pointer to an uninitialized graph object. - * \param out_deg The degree sequence for an undirected graph (if - * \p in_seq is \c NULL or of length zero), or the out-degree - * sequence of a directed graph (if \p in_deq is not - * of length zero). - * \param in_deg It is either a zero-length vector or - * \c NULL (if an undirected - * graph is generated), or the in-degree sequence. + * \param out_degrees A vector of integers specifying the degree sequence for + * undirected graphs or the out-degree sequence for directed graphs. + * \param in_degrees A vector of integers specifying the in-degree sequence for + * directed graphs. For undirected graphs, it must be \c NULL. * \param method The method to generate the graph. Possible values: * \clist * \cli IGRAPH_DEGSEQ_CONFIGURATION @@ -861,37 +830,33 @@ igraph_error_t edge_switching( igraph_error_t igraph_degree_sequence_game( igraph_t *graph, - const igraph_vector_int_t *out_deg, - const igraph_vector_int_t *in_deg, + const igraph_vector_int_t *out_degrees, + const igraph_vector_int_t *in_degrees, igraph_degseq_t method) { - if (in_deg && igraph_vector_int_empty(in_deg) && !igraph_vector_int_empty(out_deg)) { - in_deg = NULL; - } - switch (method) { case IGRAPH_DEGSEQ_CONFIGURATION: - return configuration(graph, out_deg, in_deg); + return configuration(graph, out_degrees, in_degrees); case IGRAPH_DEGSEQ_VL: - return igraph_i_degree_sequence_game_vl(graph, out_deg, in_deg); + return igraph_i_degree_sequence_game_vl(graph, out_degrees, in_degrees); case IGRAPH_DEGSEQ_FAST_HEUR_SIMPLE: - if (! in_deg) { - return fast_heur_undirected(graph, out_deg); + if (! in_degrees) { + return fast_heur_undirected(graph, out_degrees); } else { - return fast_heur_directed(graph, out_deg, in_deg); + return fast_heur_directed(graph, out_degrees, in_degrees); } case IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE: - if (! in_deg) { - return configuration_simple_undirected(graph, out_deg); + if (! in_degrees) { + return configuration_simple_undirected(graph, out_degrees); } else { - return configuration_simple_directed(graph, out_deg, in_deg); + return configuration_simple_directed(graph, out_degrees, in_degrees); } case IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE: - return edge_switching(graph, out_deg, in_deg); + return edge_switching(graph, out_degrees, in_degrees); default: IGRAPH_ERROR("Invalid degree sequence game method.", IGRAPH_EINVAL); diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h b/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h index be905308b3e..4c6ee6dae78 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h @@ -23,12 +23,12 @@ #include "igraph_datatype.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_degree_sequence_game_vl(igraph_t *graph, const igraph_vector_int_t *out_seq, const igraph_vector_int_t *in_seq); -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_GAMES_DEGREE_SEQUENCE_VL_H */ diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp index 0e512751c26..857cf5c5aa9 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp @@ -151,8 +151,6 @@ igraph_error_t igraph_i_degree_sequence_game_vl(igraph_t *graph, IGRAPH_EINVAL); } - RNG_BEGIN(); - degree_sequence *dd = new degree_sequence(out_seq); graph_molloy_opt *g = new graph_molloy_opt(*dd); @@ -160,13 +158,11 @@ igraph_error_t igraph_i_degree_sequence_game_vl(igraph_t *graph, if (!g->havelhakimi()) { delete g; - RNG_END(); IGRAPH_FATAL("g->havelhakimi() failed; please report as a bug."); } if (!g->make_connected()) { delete g; - RNG_END(); IGRAPH_ERROR("Cannot make a connected graph from the given degree sequence.", IGRAPH_EINVAL); } @@ -180,8 +176,6 @@ igraph_error_t igraph_i_degree_sequence_game_vl(igraph_t *graph, IGRAPH_CHECK(gh->print(graph)); delete gh; - - RNG_END(); ); return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/games/dotproduct.c b/src/vendor/cigraph/src/games/dotproduct.c index e372af0e5b7..d0456f2a538 100644 --- a/src/vendor/cigraph/src/games/dotproduct.c +++ b/src/vendor/cigraph/src/games/dotproduct.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2014 Gabor Csardi @@ -52,8 +51,8 @@ * Time complexity: O(n*n*m), where n is the number of vertices, * and m is the length of the latent vectors. * - * \sa \ref igraph_sample_dirichlet(), \ref - * igraph_sample_sphere_volume(), \ref igraph_sample_sphere_surface() + * \sa \ref igraph_rng_sample_dirichlet(), \ref + * igraph_rng_sample_sphere_volume(), \ref igraph_rng_sample_sphere_surface() * for functions to generate the latent vectors. */ @@ -68,8 +67,6 @@ igraph_error_t igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *v IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - RNG_BEGIN(); - for (i = 0; i < ncol; i++) { igraph_integer_t from = directed ? 0 : i + 1; igraph_vector_t v1; @@ -97,8 +94,6 @@ igraph_error_t igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *v } } - RNG_END(); - IGRAPH_CHECK(igraph_create(graph, &edges, ncol, directed)); igraph_vector_int_destroy(&edges); @@ -106,185 +101,3 @@ igraph_error_t igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *v return IGRAPH_SUCCESS; } - -/** - * \function igraph_sample_sphere_surface - * \brief Sample points uniformly from the surface of a sphere. - * - * The center of the sphere is at the origin. - * - * \param dim The dimension of the random vectors. - * \param n The number of vectors to sample. - * \param radius Radius of the sphere, it must be positive. - * \param positive Whether to restrict sampling to the positive - * orthant. - * \param res Pointer to an initialized matrix, the result is - * stored here, each column will be a sampled vector. The matrix is - * resized, as needed. - * \return Error code. - * - * Time complexity: O(n*dim*g), where g is the time complexity of - * generating a standard normal random number. - * - * \sa \ref igraph_sample_sphere_volume(), \ref - * igraph_sample_dirichlet() for other similar samplers. - */ - -igraph_error_t igraph_sample_sphere_surface(igraph_integer_t dim, igraph_integer_t n, - igraph_real_t radius, - igraph_bool_t positive, - igraph_matrix_t *res) { - igraph_integer_t i, j; - - if (dim < 2) { - IGRAPH_ERROR("Sphere must be at least two dimensional to sample from " - "surface.", IGRAPH_EINVAL); - } - if (n < 0) { - IGRAPH_ERROR("Number of samples must be non-negative.", IGRAPH_EINVAL); - } - if (radius <= 0) { - IGRAPH_ERROR("Sphere radius must be positive.", IGRAPH_EINVAL); - } - - IGRAPH_CHECK(igraph_matrix_resize(res, dim, n)); - - RNG_BEGIN(); - - for (i = 0; i < n; i++) { - igraph_real_t *col = &MATRIX(*res, 0, i); - igraph_real_t sum = 0.0; - for (j = 0; j < dim; j++) { - col[j] = RNG_NORMAL(0, 1); - sum += col[j] * col[j]; - } - sum = sqrt(sum); - for (j = 0; j < dim; j++) { - col[j] = radius * col[j] / sum; - } - if (positive) { - for (j = 0; j < dim; j++) { - col[j] = fabs(col[j]); - } - } - } - - RNG_END(); - - return IGRAPH_SUCCESS; -} - -/** - * \function igraph_sample_sphere_volume - * \brief Sample points uniformly from the volume of a sphere. - * - * The center of the sphere is at the origin. - * - * \param dim The dimension of the random vectors. - * \param n The number of vectors to sample. - * \param radius Radius of the sphere, it must be positive. - * \param positive Whether to restrict sampling to the positive - * orthant. - * \param res Pointer to an initialized matrix, the result is - * stored here, each column will be a sampled vector. The matrix is - * resized, as needed. - * \return Error code. - * - * Time complexity: O(n*dim*g), where g is the time complexity of - * generating a standard normal random number. - * - * \sa \ref igraph_sample_sphere_surface(), \ref - * igraph_sample_dirichlet() for other similar samplers. - */ - - -igraph_error_t igraph_sample_sphere_volume(igraph_integer_t dim, igraph_integer_t n, - igraph_real_t radius, - igraph_bool_t positive, - igraph_matrix_t *res) { - - igraph_integer_t i, j; - - /* Arguments are checked by the following call */ - - IGRAPH_CHECK(igraph_sample_sphere_surface(dim, n, radius, positive, res)); - - RNG_BEGIN(); - - for (i = 0; i < n; i++) { - igraph_real_t *col = &MATRIX(*res, 0, i); - igraph_real_t U = pow(RNG_UNIF01(), 1.0 / dim); - for (j = 0; j < dim; j++) { - col[j] *= U; - } - } - - RNG_END(); - - return IGRAPH_SUCCESS; -} - -/** - * \function igraph_sample_dirichlet - * \brief Sample points from a Dirichlet distribution. - * - * \param n The number of vectors to sample. - * \param alpha The parameters of the Dirichlet distribution. They - * must be positive. The length of this vector gives the dimension - * of the generated samples. - * \param res Pointer to an initialized matrix, the result is stored - * here, one sample in each column. It will be resized, as needed. - * \return Error code. - * - * Time complexity: O(n * dim * g), where dim is the dimension of the - * sample vectors, set by the length of alpha, and g is the time - * complexity of sampling from a Gamma distribution. - * - * \sa \ref igraph_sample_sphere_surface() and - * \ref igraph_sample_sphere_volume() for other methods to sample - * latent vectors. - */ - -igraph_error_t igraph_sample_dirichlet(igraph_integer_t n, const igraph_vector_t *alpha, - igraph_matrix_t *res) { - - igraph_integer_t len = igraph_vector_size(alpha); - igraph_integer_t i, j; - igraph_real_t sum, num; - igraph_rng_t* rng = igraph_rng_default(); - - if (n < 0) { - IGRAPH_ERRORF("Number of samples should be non-negative, got %" IGRAPH_PRId ".", - IGRAPH_EINVAL, n); - } - - if (len < 2) { - IGRAPH_ERRORF("Dirichlet parameter vector too short, must " - "have at least two entries, got %" IGRAPH_PRId - ".", IGRAPH_EINVAL, len); - } - - if (igraph_vector_min(alpha) <= 0) { - IGRAPH_ERRORF("Dirichlet concentration parameters must be positive, got %g.", - IGRAPH_EINVAL, igraph_vector_min(alpha)); - } - - IGRAPH_CHECK(igraph_matrix_resize(res, len, n)); - - RNG_BEGIN(); - - for (i = 0; i < n; i++) { - for (j = 0, sum = 0.0; j < len; j++) { - num = igraph_rng_get_gamma(rng, VECTOR(*alpha)[j], 1.0); - sum += num; - MATRIX(*res, j, i) = num; - } - for (j = 0; j < len; j++) { - MATRIX(*res, j, i) /= sum; - } - } - - RNG_END(); - - return IGRAPH_SUCCESS; -} diff --git a/src/vendor/cigraph/src/games/erdos_renyi.c b/src/vendor/cigraph/src/games/erdos_renyi.c index 8ee699b40c0..a52f19f648b 100644 --- a/src/vendor/cigraph/src/games/erdos_renyi.c +++ b/src/vendor/cigraph/src/games/erdos_renyi.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -66,7 +64,6 @@ static igraph_error_t gnp_large( IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount_estimate)); - RNG_BEGIN(); for (igraph_integer_t i=0; i < n; i++) { igraph_integer_t j = directed ? 0 : i; @@ -93,7 +90,6 @@ static igraph_error_t gnp_large( IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } } - RNG_END(); IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); igraph_vector_int_destroy(&edges); @@ -159,10 +155,10 @@ igraph_error_t igraph_erdos_renyi_game_gnp( int iter = 0; if (n < 0) { - IGRAPH_ERROR("Invalid number of vertices.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of vertices for G(n,p) model.", IGRAPH_EINVAL); } if (p < 0.0 || p > 1.0) { - IGRAPH_ERROR("Invalid probability given.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid probability given for G(n,p) model.", IGRAPH_EINVAL); } if (p == 0.0 || no_of_nodes == 0) { @@ -193,8 +189,6 @@ igraph_error_t igraph_erdos_renyi_game_gnp( IGRAPH_VECTOR_INIT_FINALLY(&s, 0); IGRAPH_CHECK(igraph_vector_reserve(&s, ecount_estimate)); - RNG_BEGIN(); - last = RNG_GEOM(p); while (last < maxedges) { IGRAPH_CHECK(igraph_vector_push_back(&s, last)); @@ -203,8 +197,6 @@ igraph_error_t igraph_erdos_renyi_game_gnp( IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } - RNG_END(); - ecount = igraph_vector_size(&s); if (ecount > IGRAPH_ECOUNT_MAX) { IGRAPH_ERROR("Overflow in number of edges.", IGRAPH_EOVERFLOW); @@ -263,11 +255,41 @@ igraph_error_t igraph_erdos_renyi_game_gnp( /** * \ingroup generators - * \function igraph_erdos_renyi_game_gnm - * \brief Generates a random (Erdős-Rényi) graph with a fixed number of edges. + * \function igraph_iea_game + * \brief Generates a random multigraph through independent edge assignment. * - * In the G(n, m) Erdős-Rényi model, a graph with \p n vertices - * and \p m edges is generated uniformly at random. + * \experimental + * + * This model generates random multigraphs on \p n vertices with \p m edges + * through independent edge assignment (IEA). Each of the \p m edges is assigned + * uniformly at random to an \em ordered vertex pair, independently of each + * other. + * + * + * This model does not sample multigraphs uniformly. Undirected graphs are + * generated with probability proportional to + * + * + * (prod_(i<j) A_ij ! prod_i A_ii !!)^(-1), + * + * + * where \c A denotes the adjacency matrix and !! denotes + * the double factorial. Here \c A is assumed to have twice the number of + * self-loops on its diagonal. The corresponding expression for directed + * graphs is + * + * + * (prod_(i,j) A_ij !)^(-1). + * + * + * Thus the probability of all simple graphs (which only have 0s and 1s in + * the adjacency matrix) is the same, while that of non-simple ones depends + * on their edge and self-loop multiplicities. + * + * + * An alternative way to think of this model is that it performs uniform + * sampling of \em edge-labeled graphs, i.e. graphs in which not only vertices, + * but also edges carry unique identities and are distinguishable. * * \param graph Pointer to an uninitialized graph object. * \param n The number of vertices in the graph. @@ -276,176 +298,405 @@ igraph_error_t igraph_erdos_renyi_game_gnp( * \param loops Whether to generate self-loops. * \return Error code: * \c IGRAPH_EINVAL: invalid \p n or \p m parameter. - * \c IGRAPH_ENOMEM: there is not enough memory for the operation. + * \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. * - * \sa \ref igraph_erdos_renyi_game_gnp() to sample from the related - * G(n, p) model, which constrains the \em expected edge count; - * \ref igraph_degree_sequence_game() to constrain the degree sequence; - * \ref igraph_bipartite_game_gnm() for the bipartite version of this model; - * \ref igraph_barabasi_game() and \ref igraph_growing_random_game() for other - * commonly used random graph models. - * - * \example examples/simple/igraph_erdos_renyi_game_gnm.c + * \sa \ref igraph_erdos_renyi_game_gnm() to uniformly sample graphs with + * a given number of vertices and edges. */ -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_error_t igraph_iea_game( + igraph_t *graph, + igraph_integer_t n, igraph_integer_t m, + igraph_bool_t directed, igraph_bool_t loops) { - /* This function uses doubles in its `s` vector, and for `maxedges` and `last`. - * This is because on a system with 32-bit ints, maxedges will be larger than - * IGRAPH_INTEGER_MAX and this will cause overflows when calculating `from` and `to` - * for tests on large graphs. This is also why we need a 'real' version of random_sample. - */ - igraph_integer_t no_of_nodes = n; - igraph_integer_t no_of_edges = m; - igraph_real_t no_of_nodes_real = (igraph_real_t) no_of_nodes; /* for divisions below */ - igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_vector_t s = IGRAPH_VECTOR_NULL; + igraph_vector_int_t edges; int iter = 0; if (n < 0) { - IGRAPH_ERROR("Invalid number of vertices.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of vertices for IEA model.", IGRAPH_EINVAL); } if (m < 0 || m > IGRAPH_ECOUNT_MAX) { - IGRAPH_ERROR("Invalid number of edges.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of edges for IEA model.", IGRAPH_EINVAL); } - if (m == 0.0 || no_of_nodes == 0) { - IGRAPH_CHECK(igraph_empty(graph, n, directed)); - } else { + /* Special cases of "too many edges" that also apply to multigraphs: + * - The null graph cannot have edges. + * - The singleton graph canot have edges unless loops are allowed. + */ + if (m > 0 && ((n == 0) || (!loops && n == 1))) { + IGRAPH_ERROR( + "Too many edges requested compared to the number of vertices for IEA model.", + IGRAPH_EINVAL); + } - igraph_integer_t i; - igraph_real_t maxedges = n; - if (directed && loops) { - maxedges *= n; - } else if (directed && !loops) { - maxedges *= (n - 1); - } else if (!directed && loops) { - maxedges *= (n + 1) / 2.0; + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); + + 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 { - maxedges *= (n - 1) / 2.0; + 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); + } - if (no_of_edges > maxedges) { - IGRAPH_ERROR("Too many edges requested compared to the number of vertices.", IGRAPH_EINVAL); - } + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} - if (maxedges == no_of_edges) { - IGRAPH_CHECK(igraph_full(graph, n, directed, loops)); - } else { - igraph_integer_t slen; +/* Uniform sampling of multigraphs from G(n,m) */ +static igraph_error_t gnm_multi( + igraph_t *graph, + igraph_integer_t n, igraph_integer_t m, + igraph_bool_t directed, igraph_bool_t loops) { + + /* Conceptually, uniform multigraph sampling works as follows: + * + * - Consider a list containing all vertex pairs. Use unordered pairs for + * undirected graphs, ordered pairs for directed ones, and include + * self-pairs if desired. + * - Pick a list element uniformly at random with replacement and append + * it to the list. Add the corresponding edge to the graph. + * - Continue picking elements form the list uniformly at random and + * appending the pick to the list until we have sampled the desired + * number of edges. + * + * Let's illustrate how this is implemented on the directed case with loops + * allowed. Each element of the n*n adjacency matrix corresponds to an + * ordered vertex pair. Uniformly sampling a matrix element is possible + * by generating two random matrix indices. As an analog of appending to the + * list of pairs, we extend the matrix with additional rows. The last row + * will generally be incomplete, so we use rejection sampling to avoid + * exceeding its length. + * + * In the undirected case, we still sample _ordered_ vertex pairs for + * simplicity. To account for the resulting duplication, we append the + * sampled pair _twice_. In the undirected case with loops, we must also + * duplicate the matrix diagonal. + */ - IGRAPH_VECTOR_INIT_FINALLY(&s, 0); - IGRAPH_CHECK(igraph_random_sample_real(&s, 0, maxedges - 1, no_of_edges)); + igraph_vector_int_t edges; + igraph_integer_t nrow, ncol; + igraph_integer_t last; /* column index of last element in last row */ + int iter = 0; + + /* Constraining n and m by IGRAPH_VCOUNT_MAX and IGRAPH_ECOUNT_MAX, + * as done in the caller, is sufficient to prevent overflow, + * except for the one special case below: + */ - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, igraph_vector_size(&s) * 2)); + if (!directed && !loops && + n == IGRAPH_VCOUNT_MAX && m == IGRAPH_ECOUNT_MAX) { + IGRAPH_ERROR("Too many edges or vertices for G(n,m) multigraph.", IGRAPH_EINVAL); + } + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2*m); + + if (directed && loops) { + nrow = ncol = n; + last = ncol-1; + for (igraph_integer_t i=0; i < m; i++) { + while (true) { + igraph_integer_t r = RNG_INTEGER(0, nrow-1); + igraph_integer_t c = RNG_INTEGER(0, ncol-1); + + if (r >= n) { + igraph_integer_t j = (r - n) * ncol + c; + if (IGRAPH_UNLIKELY(j >= i)) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; + } else { + VECTOR(edges)[2*i] = r; + VECTOR(edges)[2*i+1] = c; + } - slen = igraph_vector_size(&s); - if (directed && loops) { - for (i = 0; i < slen; i++) { - igraph_integer_t to = floor(VECTOR(s)[i] / no_of_nodes_real); - igraph_integer_t from = VECTOR(s)[i] - to * no_of_nodes_real; - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + last += 1; + if (last >= ncol) { + last -= ncol; + nrow++; } - } else if (directed && !loops) { - for (i = 0; i < slen; i++) { - igraph_integer_t from = floor(VECTOR(s)[i] / (no_of_nodes_real - 1)); - igraph_integer_t to = VECTOR(s)[i] - from * (no_of_nodes_real - 1); - if (from == to) { - to = no_of_nodes - 1; + + break; + } + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else if (directed && !loops) { + nrow = n; + ncol = n-1; + last = ncol-1; + for (igraph_integer_t i=0; i < m; i++) { + while (true) { + igraph_integer_t r = RNG_INTEGER(0, nrow-1); + igraph_integer_t c = RNG_INTEGER(0, ncol-1); + + if (r >= n) { + igraph_integer_t j = (r - n) * ncol + c; + if (IGRAPH_UNLIKELY(j >= i)) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; + } else { + + /* Eliminate self-loops. */ + if (c == r) { + c = n-1; } - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + + VECTOR(edges)[2*i] = r; + VECTOR(edges)[2*i+1] = c; } - } else if (!directed && loops) { - for (i = 0; i < slen; i++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) - 1) / 2); - igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to + 1)) / 2; - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + + last += 1; + if (last >= ncol) { + last -= ncol; + nrow++; + } + + break; + } + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else if (!directed && loops) { + nrow = n; + ncol = n+1; + last = ncol-1; + for (igraph_integer_t i=0; i < m; i++) { + while (true) { + igraph_integer_t r = RNG_INTEGER(0, nrow-1); + igraph_integer_t c = RNG_INTEGER(0, ncol-1); + + if (r >= n) { + igraph_integer_t j = (r - n) * ncol + c; + if (IGRAPH_UNLIKELY(j >= 2*i)) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*(j/2)]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*(j/2)+1]; + } else { + + /* Two chances to sample from matrix diagonal, + * when c == r and when c == n. */ + if (c == n) { + c = r; + } + + VECTOR(edges)[2*i] = r; + VECTOR(edges)[2*i+1] = c; } - } else { /* !directed && !loops */ - for (i = 0; i < slen; i++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) + 1) / 2); - igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to - 1)) / 2; - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + + last += 2; + while (last >= ncol) { + last -= ncol; + nrow++; } + + break; } + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else /* !directed && !loops */ { + nrow = n; + ncol = n-1; + last = ncol-1; + for (igraph_integer_t i=0; i < m; i++) { + while (true) { + igraph_integer_t r = RNG_INTEGER(0, nrow-1); + igraph_integer_t c = RNG_INTEGER(0, ncol-1); + + if (r >= n) { + igraph_integer_t j = (r - n) * ncol + c; + if (IGRAPH_UNLIKELY(j >= 2*i)) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*(j/2)]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*(j/2)+1]; + } else { + + /* Eliminate self-loops. */ + if (c == r) { + c = n-1; + } + + VECTOR(edges)[2*i] = r; + VECTOR(edges)[2*i+1] = c; + } + + last += 2; + while (last >= ncol) { + last -= ncol; + nrow++; + } - igraph_vector_destroy(&s); - IGRAPH_FINALLY_CLEAN(1); - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); + break; + } + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } } + 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 - * \brief Generates a random (Erdős-Rényi) graph. + * \function igraph_erdos_renyi_game_gnm + * \brief Generates a random (Erdős-Rényi) graph with a fixed number of edges. * - * This function is deprecated; use \ref igraph_erdos_renyi_game_gnm() or - * \ref igraph_erdos_renyi_game_gnp() instead. + * In the G(n, m) Erdős-Rényi model, a graph with \p n vertices + * and \p m edges is generated uniformly at random. * * \param graph Pointer to an uninitialized graph object. - * \param type The type of the random graph, possible values: - * \clist - * \cli IGRAPH_ERDOS_RENYI_GNM - * G(n,m) graph, - * m edges are - * selected uniformly randomly in a graph with - * n vertices. - * \cli IGRAPH_ERDOS_RENYI_GNP - * G(n,p) graph, - * every possible edge is included in the graph with - * probability p. - * \endclist * \param n The number of vertices in the graph. - * \param p_or_m This is the p parameter for - * G(n,p) graphs and the - * m - * parameter for G(n,m) graphs. + * \param m The number of edges in the graph. * \param directed Whether to generate a directed graph. - * \param loops Whether to generate loops (self) edges. + * \param loops Whether to generate self-loops. + * \param multiple Whether it is allowed to generate more than one edge between + * the same pair of vertices. * \return Error code: - * \c IGRAPH_EINVAL: invalid - * \p type, \p n, - * \p p or \p m - * parameter. - * \c IGRAPH_ENOMEM: there is not enough - * memory for the operation. + * \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. * - * \sa \ref igraph_barabasi_game(), \ref igraph_growing_random_game(), - * \ref igraph_erdos_renyi_game_gnm(), \ref igraph_erdos_renyi_game_gnp() + * \sa \ref igraph_erdos_renyi_game_gnp() to sample from the related + * G(n, p) model, which constrains the \em expected edge count; + * \ref igraph_iea_game() to generate multigraph by assigning edges to vertex + * pairs uniformly and independently; + * \ref igraph_degree_sequence_game() to constrain the degree sequence; + * \ref igraph_bipartite_game_gnm() for the bipartite version of this model; + * \ref igraph_barabasi_game() and \ref igraph_growing_random_game() for other + * commonly used random graph models. + * + * \example examples/simple/igraph_erdos_renyi_game_gnm.c */ -igraph_error_t igraph_erdos_renyi_game(igraph_t *graph, igraph_erdos_renyi_t type, - igraph_integer_t n, igraph_real_t p_or_m, - igraph_bool_t directed, igraph_bool_t loops) { - - 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); +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 multiple +) { + + /* This function uses doubles in its `s` vector, and for `maxedges` and `last`. + * This is because on a system with 32-bit ints, maxedges will be larger than + * IGRAPH_INTEGER_MAX and this will cause overflows when calculating `from` and `to` + * for tests on large graphs. This is also why we need a 'real' version of random_sample. + */ + igraph_real_t n_real = (igraph_real_t) n; /* for divisions below */ + igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; + igraph_vector_t s = IGRAPH_VECTOR_NULL; + int iter = 0; + + /* The multigraph implementation relies on the below checks to avoid overflow. */ + if (n < 0 || n > IGRAPH_VCOUNT_MAX) { + IGRAPH_ERROR("Invalid number of vertices for G(n,m) model.", IGRAPH_EINVAL); + } + if (m < 0 || m > IGRAPH_ECOUNT_MAX) { + IGRAPH_ERROR("Invalid number of edges for G(n,m) model.", IGRAPH_EINVAL); + } + + /* Special cases of "too many edges" that also apply to multigraphs: + * - The null graph cannot have edges. + * - The singleton graph canot have edges unless loops are allowed. + */ + if (m > 0 && ((n == 0) || (!loops && n == 1))) { + IGRAPH_ERROR( + "Too many edges requested compared to the number of vertices for G(n,m) model.", + IGRAPH_EINVAL); + } + + if (m == 0) { + return igraph_empty(graph, n, directed); + } + + if (multiple) { + return gnm_multi(graph, n, m, directed, loops); + } + + igraph_real_t maxedges = n; + if (directed && loops) { + maxedges *= n; + } else if (directed && !loops) { + maxedges *= (n - 1); + } else if (!directed && loops) { + maxedges *= (n + 1) / 2.0; + } else { + maxedges *= (n - 1) / 2.0; + } + + if (m > maxedges) { + IGRAPH_ERROR( + "Too many edges requested compared to the number of vertices for G(n,m) model.", + IGRAPH_EINVAL); + } + + if (maxedges == m) { + IGRAPH_CHECK(igraph_full(graph, n, directed, loops)); } else { - IGRAPH_ERROR("Invalid type", IGRAPH_EINVAL); + igraph_integer_t slen; + + IGRAPH_VECTOR_INIT_FINALLY(&s, 0); + IGRAPH_CHECK(igraph_i_random_sample_real(&s, 0, maxedges - 1, m)); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, igraph_vector_size(&s) * 2)); + + slen = igraph_vector_size(&s); + if (directed && loops) { + for (igraph_integer_t i = 0; i < slen; i++) { + igraph_integer_t to = floor(VECTOR(s)[i] / n_real); + igraph_integer_t from = VECTOR(s)[i] - to * n_real; + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else if (directed && !loops) { + for (igraph_integer_t i = 0; i < slen; i++) { + igraph_integer_t from = floor(VECTOR(s)[i] / (n_real - 1)); + igraph_integer_t to = VECTOR(s)[i] - from * (n_real - 1); + if (from == to) { + to = n - 1; + } + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else if (!directed && loops) { + for (igraph_integer_t i = 0; i < slen; i++) { + igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) - 1) / 2); + igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to + 1)) / 2; + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else { /* !directed && !loops */ + for (igraph_integer_t i = 0; i < slen; i++) { + igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) + 1) / 2); + igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to - 1)) / 2; + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } + + igraph_vector_destroy(&s); + IGRAPH_FINALLY_CLEAN(1); + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); } + + return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/games/establishment.c b/src/vendor/cigraph/src/games/establishment.c index 9df705606c9..9ed1daabfda 100644 --- a/src/vendor/cigraph/src/games/establishment.c +++ b/src/vendor/cigraph/src/games/establishment.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -147,8 +145,6 @@ igraph_error_t igraph_establishment_game(igraph_t *graph, igraph_integer_t nodes IGRAPH_VECTOR_INT_INIT_FINALLY(nodetypes, nodes); } - RNG_BEGIN(); - for (i = 0; i < nodes; i++) { igraph_real_t uni = RNG_UNIF(0, maxcum); igraph_integer_t type; @@ -168,8 +164,6 @@ igraph_error_t igraph_establishment_game(igraph_t *graph, igraph_integer_t nodes } } - RNG_END(); - if (! node_type_vec) { igraph_vector_int_destroy(nodetypes); IGRAPH_FREE(nodetypes); diff --git a/src/vendor/cigraph/src/games/forestfire.c b/src/vendor/cigraph/src/games/forestfire.c index 417320c0a66..11baf7a9218 100644 --- a/src/vendor/cigraph/src/games/forestfire.c +++ b/src/vendor/cigraph/src/games/forestfire.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -159,8 +158,6 @@ igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes, IGRAPH_FINALLY(igraph_vector_int_destroy, &visited); IGRAPH_DQUEUE_INT_INIT_FINALLY(&neiq, 10); - RNG_BEGIN(); - #define ADD_EDGE_TO(nei) \ if (VECTOR(visited)[(nei)] != actnode+1) { \ VECTOR(visited)[(nei)] = actnode+1; \ @@ -243,8 +240,6 @@ igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes, #undef ADD_EDGE_TO - RNG_END(); - IGRAPH_PROGRESS("Forest fire: ", 100.0, NULL); igraph_dqueue_int_destroy(&neiq); diff --git a/src/vendor/cigraph/src/games/grg.c b/src/vendor/cigraph/src/games/grg.c index 008bf247134..a8804e2251c 100644 --- a/src/vendor/cigraph/src/games/grg.c +++ b/src/vendor/cigraph/src/games/grg.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -91,15 +89,11 @@ igraph_error_t igraph_grg_game(igraph_t *graph, igraph_integer_t nodes, IGRAPH_VECTOR_INIT_FINALLY(yy, nodes); } - RNG_BEGIN(); - for (i = 0; i < nodes; i++) { VECTOR(*xx)[i] = RNG_UNIF01(); VECTOR(*yy)[i] = RNG_UNIF01(); } - RNG_END(); - igraph_vector_sort(xx); if (!torus) { diff --git a/src/vendor/cigraph/src/games/growing_random.c b/src/vendor/cigraph/src/games/growing_random.c index 79e5231f3f1..9d343070b49 100644 --- a/src/vendor/cigraph/src/games/growing_random.c +++ b/src/vendor/cigraph/src/games/growing_random.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -84,8 +82,6 @@ igraph_error_t igraph_growing_random_game(igraph_t *graph, igraph_integer_t n, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); - RNG_BEGIN(); - for (igraph_integer_t i = 1; i < no_of_nodes; i++) { for (igraph_integer_t j = 0; j < no_of_neighbors; j++) { if (citation) { @@ -101,8 +97,6 @@ igraph_error_t igraph_growing_random_game(igraph_t *graph, igraph_integer_t n, } } - RNG_END(); - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); igraph_vector_int_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/games/islands.c b/src/vendor/cigraph/src/games/islands.c index edececa2be1..2143b8816c1 100644 --- a/src/vendor/cigraph/src/games/islands.c +++ b/src/vendor/cigraph/src/games/islands.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -114,8 +112,6 @@ igraph_error_t igraph_simple_interconnected_islands_game( IGRAPH_VECTOR_INIT_FINALLY(&s, 0); IGRAPH_CHECK(igraph_vector_reserve(&s, 1.1 * avg_edges_per_island)); - RNG_BEGIN(); - /* first create all the islands */ for (is = 0; is < islands_n; is++) { /* for each island */ /* index for start and end of nodes in this island, both inclusive */ @@ -145,7 +141,7 @@ igraph_error_t igraph_simple_interconnected_islands_game( island_ecount = islands_size * islands_size; number_of_inter_island_edges = n_inter; for (i = is + 1; i < islands_n; i++) { /* for each other island (not the previous ones) */ - IGRAPH_CHECK(igraph_random_sample_real(&s, 0, island_ecount - 1, n_inter)); + IGRAPH_CHECK(igraph_i_random_sample_real(&s, 0, island_ecount - 1, n_inter)); start_index_of_other_island = i * islands_size; for (j = 0; j < n_inter; j++) { /* for each link between islands */ @@ -163,8 +159,6 @@ igraph_error_t igraph_simple_interconnected_islands_game( igraph_vector_destroy(&s); IGRAPH_FINALLY_CLEAN(1); - RNG_END(); - /* actually fill the graph object */ IGRAPH_CHECK(igraph_create(graph, &edges, number_of_nodes, 0)); diff --git a/src/vendor/cigraph/src/games/k_regular.c b/src/vendor/cigraph/src/games/k_regular.c index 0cebc213ad2..6f7536e50f7 100644 --- a/src/vendor/cigraph/src/games/k_regular.c +++ b/src/vendor/cigraph/src/games/k_regular.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team diff --git a/src/vendor/cigraph/src/games/preference.c b/src/vendor/cigraph/src/games/preference.c index 4ef26d6ac85..b2e78842ed4 100644 --- a/src/vendor/cigraph/src/games/preference.c +++ b/src/vendor/cigraph/src/games/preference.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -161,8 +159,6 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(&vids_by_type, types); - RNG_BEGIN(); - if (!fixed_sizes) { igraph_vector_t cumdist; @@ -327,8 +323,6 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, } } - RNG_END(); - igraph_vector_destroy(&s); igraph_vector_int_list_destroy(&vids_by_type); IGRAPH_FINALLY_CLEAN(2); @@ -490,8 +484,6 @@ igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer } maxcum = igraph_vector_tail(&cumdist); - RNG_BEGIN(); - for (i = 0; i < nodes; i++) { igraph_integer_t in_type, out_type; igraph_real_t uni1 = RNG_UNIF(0, maxcum); @@ -593,8 +585,6 @@ igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer } } - RNG_END(); - igraph_vector_destroy(&s); igraph_vector_int_destroy(&intersect); igraph_vector_int_list_destroy(&vids_by_intype); diff --git a/src/vendor/cigraph/src/games/recent_degree.c b/src/vendor/cigraph/src/games/recent_degree.c index 63d9fbb93ad..2edb02cccba 100644 --- a/src/vendor/cigraph/src/games/recent_degree.c +++ b/src/vendor/cigraph/src/games/recent_degree.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -81,16 +79,15 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes igraph_integer_t edgeptr = 0; igraph_vector_t degree; igraph_dqueue_int_t history; - igraph_bool_t have_outseq = outseq && igraph_vector_int_size(outseq) > 0; if (no_of_nodes < 0) { IGRAPH_ERRORF("Number of vertices cannot be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, no_of_nodes); } - if (have_outseq && igraph_vector_int_size(outseq) != no_of_nodes) { + if (outseq && igraph_vector_int_size(outseq) != no_of_nodes) { IGRAPH_ERRORF("Out-degree sequence is specified, but its length (%" IGRAPH_PRId ") does not equal the number of nodes (%" IGRAPH_PRId ").", IGRAPH_EINVAL, igraph_vector_int_size(outseq), no_of_nodes); } - if (!have_outseq && m < 0) { + if (!outseq && m < 0) { IGRAPH_ERRORF("Number of edges per step cannot be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, m); } @@ -101,12 +98,14 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes IGRAPH_ERRORF("The zero appeal cannot be negative, got %g.", IGRAPH_EINVAL, zero_appeal); } + /* This effectively also hanbdles an outseq size of 0. + * From here on we assume that outseq has a size of at least 1. */ if (no_of_nodes == 0) { IGRAPH_CHECK(igraph_empty(graph, 0, directed)); return IGRAPH_SUCCESS; } - if (!have_outseq) { + if (!outseq) { no_of_neighbors = m; IGRAPH_SAFE_MULT(no_of_nodes - 1, no_of_neighbors, &no_of_edges); } else { @@ -126,8 +125,6 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes 1.5 * time_window * no_of_edges / no_of_nodes + 10)); IGRAPH_FINALLY(igraph_dqueue_int_destroy, &history); - RNG_BEGIN(); - /* first node */ IGRAPH_CHECK(igraph_psumtree_update(&sumtree, 0, zero_appeal)); IGRAPH_CHECK(igraph_dqueue_int_push(&history, -1)); @@ -136,7 +133,7 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes for (i = 1; i < no_of_nodes; i++) { igraph_real_t sum; igraph_integer_t to; - if (have_outseq) { + if (outseq) { no_of_neighbors = VECTOR(*outseq)[i]; } @@ -176,8 +173,6 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes } } - RNG_END(); - igraph_dqueue_int_destroy(&history); igraph_psumtree_destroy(&sumtree); igraph_vector_destroy(°ree); @@ -252,16 +247,15 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, igraph_integer_t edgeptr = 0; igraph_vector_t degree; igraph_dqueue_int_t history; - igraph_bool_t have_outseq = outseq && igraph_vector_int_size(outseq) > 0; if (no_of_nodes < 0) { IGRAPH_ERRORF("Number of nodes should not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, no_of_nodes); } - if (have_outseq && igraph_vector_int_size(outseq) != no_of_nodes) { + if (outseq && igraph_vector_int_size(outseq) != no_of_nodes) { IGRAPH_ERRORF("Out-degree sequence is specified, but its length (%" IGRAPH_PRId ") does not equal the number of nodes (%" IGRAPH_PRId ").", IGRAPH_EINVAL, igraph_vector_int_size(outseq), no_of_nodes); } - if (!have_outseq && m < 0) { + if (!outseq && m < 0) { IGRAPH_ERRORF("Numer of edges per step cannot be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, m); } if (aging_bins <= 0) { @@ -274,12 +268,14 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, IGRAPH_ERRORF("The zero appeal cannot be negative, got %g.", IGRAPH_EINVAL, zero_appeal); } + /* This effectively also hanbdles an outseq size of 0. + * From here on we assume that outseq has a size of at least 1. */ if (no_of_nodes == 0) { IGRAPH_CHECK(igraph_empty(graph, 0, directed)); return IGRAPH_SUCCESS; } - if (!have_outseq) { + if (!outseq) { no_of_neighbors = m; IGRAPH_SAFE_MULT(no_of_nodes - 1, no_of_neighbors, &no_of_edges); } else { @@ -301,8 +297,6 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, 1.5 * time_window * no_of_edges / no_of_nodes + 10)); IGRAPH_FINALLY(igraph_dqueue_int_destroy, &history); - RNG_BEGIN(); - /* first node */ IGRAPH_CHECK(igraph_psumtree_update(&sumtree, 0, zero_appeal)); IGRAPH_CHECK(igraph_dqueue_int_push(&history, -1)); @@ -312,7 +306,7 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, igraph_real_t sum; igraph_integer_t to; - if (have_outseq) { + if (outseq) { no_of_neighbors = VECTOR(*outseq)[i]; } @@ -374,8 +368,6 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, } } - RNG_END(); - igraph_dqueue_int_destroy(&history); igraph_vector_destroy(°ree); igraph_psumtree_destroy(&sumtree); diff --git a/src/vendor/cigraph/src/games/sbm.c b/src/vendor/cigraph/src/games/sbm.c index 12cf6639536..cf3932e0a52 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) { @@ -127,8 +126,6 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - RNG_BEGIN(); - for (from = 0; from < no_blocks; from++) { igraph_integer_t fromsize = VECTOR(*block_sizes)[from]; igraph_integer_t start = directed ? 0 : from; @@ -233,8 +230,6 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, fromoff += fromsize; } - RNG_END(); - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); igraph_vector_int_destroy(&edges); @@ -326,8 +321,6 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - RNG_BEGIN(); - /* Block models first */ for (b = 0; b < no_blocks; b++) { @@ -415,8 +408,6 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, } } - RNG_END(); - IGRAPH_CHECK(igraph_create(graph, &edges, n, /*directed=*/ 0)); igraph_vector_int_destroy(&edges); @@ -532,8 +523,6 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, IGRAPH_VECTOR_INIT_FINALLY(&csizes, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - RNG_BEGIN(); - /* Block models first */ for (b = 0; b < no_blocks; b++) { @@ -631,8 +620,6 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, } } - RNG_END(); - IGRAPH_CHECK(igraph_create(graph, &edges, n, /*directed=*/ 0)); igraph_vector_int_destroy(&edges); diff --git a/src/vendor/cigraph/src/games/static_fitness.c b/src/vendor/cigraph/src/games/static_fitness.c index bc03c38a9b2..a87ece9dfab 100644 --- a/src/vendor/cigraph/src/games/static_fitness.c +++ b/src/vendor/cigraph/src/games/static_fitness.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -202,7 +200,6 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o p_cum_fitness_in = &cum_fitness_out; } - RNG_BEGIN(); num_steps = no_of_edges; if (multiple) { /* Generating when multiple edges are allowed */ @@ -292,7 +289,6 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o igraph_adjlist_destroy(&al); IGRAPH_FINALLY_CLEAN(1); } - RNG_END(); IGRAPH_PROGRESS("Static fitness game", 100.0, NULL); @@ -445,7 +441,7 @@ igraph_error_t igraph_static_power_law_game(igraph_t *graph, for (igraph_integer_t 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/games/tree.c b/src/vendor/cigraph/src/games/tree.c index 52b1b94144d..6eedd1f792c 100644 --- a/src/vendor/cigraph/src/games/tree.c +++ b/src/vendor/cigraph/src/games/tree.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -45,11 +43,9 @@ static igraph_error_t igraph_i_tree_game_prufer(igraph_t *graph, igraph_integer_ IGRAPH_VECTOR_INT_INIT_FINALLY(&prufer, n - 2); - RNG_BEGIN(); for (igraph_integer_t i = 0; i < n - 2; ++i) { VECTOR(prufer)[i] = RNG_INTEGER(0, n - 1); } - RNG_END(); IGRAPH_CHECK(igraph_from_prufer(graph, &prufer)); @@ -91,8 +87,6 @@ static igraph_error_t igraph_i_tree_game_loop_erased_random_walk(igraph_t *graph IGRAPH_CHECK(igraph_vector_int_init_range(&vertices, 0, n)); IGRAPH_FINALLY(igraph_vector_int_destroy, &vertices); - RNG_BEGIN(); - /* A simple implementation could be as below. This is for illustration only. * The actually implemented algorithm avoids unnecessary walking on the already visited * portion of the vertex set. @@ -134,8 +128,6 @@ static igraph_error_t igraph_i_tree_game_loop_erased_random_walk(igraph_t *graph VECTOR(edges)[2 * k - 1] = i; } - RNG_END(); - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); igraph_vector_int_destroy(&vertices); diff --git a/src/vendor/cigraph/src/games/watts_strogatz.c b/src/vendor/cigraph/src/games/watts_strogatz.c index d7aa1c5aeff..ad3d64909cd 100644 --- a/src/vendor/cigraph/src/games/watts_strogatz.c +++ b/src/vendor/cigraph/src/games/watts_strogatz.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team diff --git a/src/vendor/cigraph/src/graph/adjlist.c b/src/vendor/cigraph/src/graph/adjlist.c index 15706dcc991..3a792f6b83a 100644 --- a/src/vendor/cigraph/src/graph/adjlist.c +++ b/src/vendor/cigraph/src/graph/adjlist.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -52,18 +51,10 @@ */ static igraph_error_t igraph_i_simplify_sorted_int_adjacency_vector_in_place( igraph_vector_int_t *v, igraph_integer_t index, igraph_neimode_t mode, - igraph_loops_t loops, igraph_multiple_t multiple, igraph_bool_t *has_loops, + igraph_loops_t loops, igraph_bool_t multiple, igraph_bool_t *has_loops, igraph_bool_t *has_multiple ); -/** - * Helper function that removes loops from an incidence vector (either both - * occurrences or only one of them). - */ -static igraph_error_t igraph_i_remove_loops_from_incidence_vector_in_place( - igraph_vector_int_t *v, const igraph_t *graph, igraph_loops_t loops -); - /** * \section about_adjlists * @@ -118,7 +109,13 @@ static igraph_error_t igraph_i_remove_loops_from_incidence_vector_in_place( * * * This function returns each neighbor list in sorted order, just - * like \ref igraph_neighbors(). + * like \ref igraph_neighbors(). However, adjacency lists \em "in general" + * are not guaranteed to be sorted, and we reserve the right to change the + * ordering of vertices in the result in the future without considering this + * a breaking change. If you need to ensure that the adjacency lists are + * sorted, you can use \ref igraph_adjlist_sort() to sort all the adjacency + * lists, or call \ref igraph_vector_int_sort() on the individual adjacency + * vectors after the initialization. * * * As of igraph 0.10, there is a small performance cost to setting \p loops @@ -155,9 +152,10 @@ static igraph_error_t igraph_i_remove_loops_from_incidence_vector_in_place( igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, - igraph_multiple_t multiple) { + igraph_bool_t multiple) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degrees; + int iter = 0; if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) { IGRAPH_ERROR("Cannot create adjacency list view.", IGRAPH_EINVMODE); @@ -169,7 +167,7 @@ igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); /* igraph_degree() is fast when loops=true */ - IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), mode, /* loops= */ true)); + IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), mode, IGRAPH_LOOPS)); al->length = no_of_nodes; al->adjs = IGRAPH_CALLOC(al->length, igraph_vector_int_t); @@ -194,11 +192,18 @@ igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, igraph_bool_t has_loops = false; igraph_bool_t has_multiple = false; + + /* In theory, we could just run igraph_neighbors() in a loop with 'loops' + * and 'multiple' set exactly how the caller wants it. However, we take the + * opportunity to also _cache_ whether the graph has multiple or loop edges + * if we are looping over all vertices anyway, and that requires us to query + * the neighbors in full */ + for (igraph_integer_t i = 0; i < al->length; i++) { - IGRAPH_ALLOW_INTERRUPTION(); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1000); IGRAPH_CHECK(igraph_vector_int_init(&al->adjs[i], VECTOR(degrees)[i])); - IGRAPH_CHECK(igraph_neighbors(graph, &al->adjs[i], i, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &al->adjs[i], i, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); /* Attention: This function will only set values for has_loops and has_multiple * if it finds loops/multi-edges. Otherwise they are left at their original value. */ @@ -245,7 +250,7 @@ igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, * \param no_of_nodes The number of vertices * \return Error code. * - * Time complexity: O(|V|), linear in the number of vertices. + * Time complexity: O(n), linear in the number of vertices. */ igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_integer_t no_of_nodes) { @@ -282,7 +287,13 @@ igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_integer_t * or both (\c IGRAPH_ALL) types of neighbors (in the * complementer graph) to include in the adjacency list. It is * ignored for undirected networks. - * \param loops Whether to consider loop edges. + * \param loops Specifies how to treat loop edges. \c IGRAPH_NO_LOOPS will not + * include loops edges in the returned adjacency list. \c IGRAPH_LOOPS_ONCE + * will include vertex \p i in the adjacency list of vetex \p i \em once if + * the original graph did not have a loop edge incident on vertex \p i, + * while \c IGRAPH_LOOPS_TWICE will include vertex \p i \em twice \em if + * \p mode is set to \c IGRAPH_ALL (otherwise it is treated the same way as + * \c IGRAPH_LOOPS_ONCE ). * \return Error code. * * \sa \ref igraph_adjlist_init(), \ref igraph_complementer() @@ -292,10 +303,11 @@ igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_integer_t igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, - igraph_bool_t loops) { + igraph_loops_t loops) { igraph_bitset_t seen; igraph_vector_int_t neis; + int iter = 0; if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) { IGRAPH_ERROR("Invalid neighbor mode specified for complementer adjlist view.", IGRAPH_EINVMODE); @@ -305,6 +317,10 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, mode = IGRAPH_ALL; } + if (loops == IGRAPH_LOOPS_TWICE && mode != IGRAPH_ALL) { + loops = IGRAPH_LOOPS_ONCE; + } + al->length = igraph_vcount(graph); al->adjs = IGRAPH_CALLOC(al->length, igraph_vector_int_t); IGRAPH_CHECK_OOM(al->adjs, "Insufficient memory for creating complementer adjlist view."); @@ -318,15 +334,16 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, * Then we iterate over 'seen' and record non-marked vertices in * the adjacency list. */ - IGRAPH_ALLOW_INTERRUPTION(); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1000); /* Reset neighbor counter and 'seen' vector. */ igraph_bitset_null(&seen); igraph_integer_t n = al->length; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, mode, loops, IGRAPH_NO_MULTIPLE)); - if (!loops) { + if (loops == IGRAPH_NO_LOOPS) { + /* If we want no loops, we pretend that we have always seen one */ IGRAPH_BIT_SET(seen, i); n--; } @@ -339,11 +356,23 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, } } + if (loops == IGRAPH_LOOPS_TWICE) { + /* If we want loops twice and the bit corresponding to the loop + * edge is _not_ set, we need one extra slot in the allocated + * vector */ + if (!IGRAPH_BIT_TEST(seen, i)) { + n++; + } + } + /* Produce "non-neighbor" list in sorted order. */ IGRAPH_CHECK(igraph_vector_int_init(&al->adjs[i], n)); for (igraph_integer_t j = 0, k = 0; k < n; j++) { if (!IGRAPH_BIT_TEST(seen, j)) { VECTOR(al->adjs[i])[k++] = j; + if (loops == IGRAPH_LOOPS_TWICE && i == j) { + VECTOR(al->adjs[i])[k++] = j; + } } } } @@ -424,11 +453,10 @@ igraph_error_t igraph_adjlist_init_from_inclist( * Free all memory allocated for an adjacency list. * \param al The adjacency list to destroy. * - * Time complexity: depends on memory management. + * Time complexity: O(n), where n is the size of the adjacency list. */ void igraph_adjlist_destroy(igraph_adjlist_t *al) { - igraph_integer_t i; - for (i = 0; i < al->length; i++) { + for (igraph_integer_t i = 0; i < al->length; i++) { /* This works if some igraph_vector_int_t's contain NULL, because igraph_vector_int_destroy can handle this. */ igraph_vector_int_destroy(&al->adjs[i]); @@ -438,15 +466,17 @@ void igraph_adjlist_destroy(igraph_adjlist_t *al) { /** * \function igraph_adjlist_clear - * Removes all edges from an adjacency list. + * \brief Removes all edges from an adjacency list. + * + * The size of the adjacency list stays unchanged, but all adjacent + * vertices will be removed. * * \param al The adjacency list. - * Time complexity: depends on memory management, typically O(n), where n is - * the total number of elements in the adjacency list. + * + * Time complexity: O(n), where n is the size of the adjacency list. */ void igraph_adjlist_clear(igraph_adjlist_t *al) { - igraph_integer_t i; - for (i = 0; i < al->length; i++) { + for (igraph_integer_t i = 0; i < al->length; i++) { igraph_vector_int_clear(&al->adjs[i]); } } @@ -476,8 +506,8 @@ igraph_integer_t igraph_adjlist_size(const igraph_adjlist_t *al) { * * \param al The adjacency list. * - * Time complexity: O(n log n), n is the total number of elements in - * the adjacency list. + * Time complexity: O(m log m), m is the total number of neighbors stored + * in the adjacency list. */ void igraph_adjlist_sort(igraph_adjlist_t *al) { igraph_integer_t i; @@ -630,76 +660,6 @@ igraph_error_t igraph_adjlist_replace_edge( } -static igraph_error_t igraph_i_remove_loops_from_incidence_vector_in_place( - igraph_vector_int_t *v, const igraph_t *graph, igraph_loops_t loops -) { - igraph_integer_t i, length, eid, write_ptr; - igraph_vector_int_t *seen_loops = 0; - - /* In this function we make use of the fact that we are dealing with - * _incidence_ lists, and the only way for an edge ID to appear twice - * within an incidence list is if the edge is a loop edge; otherwise each - * element will be unique. - * - * Note that incidence vectors are not sorted by edge ID, so we need to - * look up the edges in the graph to decide whether they are loops or not. - * - * Also, it may be tempting to introduce a boolean in case of IGRAPH_LOOPS_ONCE, - * and flip it every time we see a loop to get rid of half of the occurrences, - * but the problem is that even if the same loop edge ID appears twice in - * the input list, they are not guaranteed to be next to each other; it - * may be the case that there are multiple loop edges, each edge appears - * twice, and we want to keep exactly one of them for each ID. That's why - * we have a "seen_loops" vector. - */ - - if (loops == IGRAPH_LOOPS_TWICE) { - /* Loop edges appear twice by default, nothing to do. */ - return IGRAPH_SUCCESS; - } - - length = igraph_vector_int_size(v); - if (length == 0) { - return IGRAPH_SUCCESS; - } - - if (loops == IGRAPH_LOOPS_ONCE) { - /* We need a helper vector */ - seen_loops = IGRAPH_CALLOC(1, igraph_vector_int_t); - IGRAPH_FINALLY(igraph_free, seen_loops); - IGRAPH_CHECK(igraph_vector_int_init(seen_loops, 0)); - IGRAPH_FINALLY(igraph_vector_int_destroy, seen_loops); - } else if (loops != IGRAPH_NO_LOOPS) { - IGRAPH_ERROR("Invalid value for 'loops' argument", IGRAPH_EINVAL); - } - - for (i = 0, write_ptr = 0; i < length; i++) { - eid = VECTOR(*v)[i]; - if (IGRAPH_FROM(graph, eid) == IGRAPH_TO(graph, eid)) { - /* Loop edge */ - if (seen_loops && !igraph_vector_int_contains(seen_loops, eid)) { - VECTOR(*v)[write_ptr++] = eid; - IGRAPH_CHECK(igraph_vector_int_push_back(seen_loops, eid)); - } - } else { - /* Not a loop edge */ - VECTOR(*v)[write_ptr++] = eid; - } - } - - /* Always succeeds since we never grow the vector */ - igraph_vector_int_resize(v, write_ptr); - - /* Destroy the helper vector */ - if (seen_loops) { - igraph_vector_int_destroy(seen_loops); - IGRAPH_FREE(seen_loops); - IGRAPH_FINALLY_CLEAN(2); - } - - return IGRAPH_SUCCESS; -} - #ifndef USING_R igraph_error_t igraph_inclist_print(const igraph_inclist_t *al) { igraph_integer_t i; @@ -769,6 +729,7 @@ igraph_error_t igraph_inclist_init(const igraph_t *graph, igraph_loops_t loops) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degrees; + int iter = 0; if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) { IGRAPH_ERROR("Cannot create incidence list view.", IGRAPH_EINVMODE); @@ -780,7 +741,7 @@ igraph_error_t igraph_inclist_init(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); /* igraph_degrees() is fast when loops=true */ - IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), mode, /* loops= */ 1)); + IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), mode, IGRAPH_LOOPS)); il->length = no_of_nodes; il->incs = IGRAPH_CALLOC(il->length, igraph_vector_int_t); @@ -790,16 +751,10 @@ igraph_error_t igraph_inclist_init(const igraph_t *graph, IGRAPH_FINALLY(igraph_inclist_destroy, il); for (igraph_integer_t i = 0; i < il->length; i++) { - IGRAPH_ALLOW_INTERRUPTION(); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1000); IGRAPH_CHECK(igraph_vector_int_init(&il->incs[i], VECTOR(degrees)[i])); - IGRAPH_CHECK(igraph_incident(graph, &il->incs[i], i, mode)); - - if (loops != IGRAPH_LOOPS_TWICE) { - IGRAPH_CHECK( - igraph_i_remove_loops_from_incidence_vector_in_place(&il->incs[i], graph, loops) - ); - } + IGRAPH_CHECK(igraph_incident(graph, &il->incs[i], i, mode, loops)); } igraph_vector_int_destroy(°rees); @@ -820,7 +775,7 @@ igraph_error_t igraph_inclist_init(const igraph_t *graph, * \param n The number of vertices in the incidence list. * \return Error code. * - * Time complexity: O(|V|), linear in the number of vertices. + * Time complexity: O(n), linear in the number of vertices. */ igraph_error_t igraph_inclist_init_empty(igraph_inclist_t *il, igraph_integer_t n) { @@ -847,12 +802,11 @@ igraph_error_t igraph_inclist_init_empty(igraph_inclist_t *il, igraph_integer_t * * \param il The incidence list to destroy. * - * Time complexity: depends on memory management. + * Time complexity: O(n), where n is the size of the incidence list. */ void igraph_inclist_destroy(igraph_inclist_t *il) { - igraph_integer_t i; - for (i = 0; i < il->length; i++) { + for (igraph_integer_t i = 0; i < il->length; i++) { /* This works if some igraph_vector_int_t's contain NULL, because igraph_vector_int_destroy can handle this. */ igraph_vector_int_destroy(&il->incs[i]); @@ -864,10 +818,12 @@ void igraph_inclist_destroy(igraph_inclist_t *il) { * \function igraph_inclist_clear * \brief Removes all edges from an incidence list. * + * The size of the incidence list stays unchanged, but all incident edges + * will be removed. + * * \param il The incidence list. * - * Time complexity: depends on memory management, typically O(n), where n is - * the total number of elements in the incidence list. + * Time complexity: O(n), where n is the size of the incidence list. */ void igraph_inclist_clear(igraph_inclist_t *il) { igraph_integer_t i; @@ -892,7 +848,7 @@ igraph_integer_t igraph_inclist_size(const igraph_inclist_t *il) { /* See the prototype above for a description of this function. */ static igraph_error_t igraph_i_simplify_sorted_int_adjacency_vector_in_place( igraph_vector_int_t *v, igraph_integer_t index, igraph_neimode_t mode, - igraph_loops_t loops, igraph_multiple_t multiple, igraph_bool_t *has_loops, + igraph_loops_t loops, igraph_bool_t multiple, igraph_bool_t *has_loops, igraph_bool_t *has_multiple ) { @@ -1091,7 +1047,7 @@ igraph_error_t igraph_lazy_adjlist_init(const igraph_t *graph, igraph_lazy_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, - igraph_multiple_t multiple) { + igraph_bool_t multiple) { if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) { IGRAPH_ERROR("Cannot create lazy adjacency list view.", IGRAPH_EINVMODE); } @@ -1189,17 +1145,7 @@ igraph_vector_int_t *igraph_i_lazy_adjlist_get_real(igraph_lazy_adjlist_t *al, i return NULL; } - ret = igraph_neighbors(al->graph, al->adjs[no], no, al->mode); - if (ret != IGRAPH_SUCCESS) { - igraph_vector_int_destroy(al->adjs[no]); - IGRAPH_FREE(al->adjs[no]); - return NULL; - } - - ret = igraph_i_simplify_sorted_int_adjacency_vector_in_place( - al->adjs[no], no, al->mode, al->loops, al->multiple, NULL, - NULL - ); + ret = igraph_neighbors(al->graph, al->adjs[no], no, al->mode, al->loops, al->multiple); if (ret != IGRAPH_SUCCESS) { igraph_vector_int_destroy(al->adjs[no]); IGRAPH_FREE(al->adjs[no]); @@ -1340,21 +1286,12 @@ igraph_vector_int_t *igraph_i_lazy_inclist_get_real(igraph_lazy_inclist_t *il, i return NULL; } - ret = igraph_incident(il->graph, il->incs[no], no, il->mode); + ret = igraph_incident(il->graph, il->incs[no], no, il->mode, il->loops); if (ret != IGRAPH_SUCCESS) { igraph_vector_int_destroy(il->incs[no]); IGRAPH_FREE(il->incs[no]); return NULL; } - - if (il->loops != IGRAPH_LOOPS_TWICE) { - ret = igraph_i_remove_loops_from_incidence_vector_in_place(il->incs[no], il->graph, il->loops); - if (ret != IGRAPH_SUCCESS) { - igraph_vector_int_destroy(il->incs[no]); - IGRAPH_FREE(il->incs[no]); - return NULL; - } - } } return il->incs[no]; diff --git a/src/vendor/cigraph/src/graph/attributes.c b/src/vendor/cigraph/src/graph/attributes.c index 731d628d9d3..03679a7f832 100644 --- a/src/vendor/cigraph/src/graph/attributes.c +++ b/src/vendor/cigraph/src/graph/attributes.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -30,21 +29,603 @@ #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 +) { + IGRAPH_UNUSED(list); + 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,12 +750,12 @@ 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) { if (igraph_i_attribute_table) { - return igraph_i_attribute_table->gettype(graph, type, elemtype, name); + return igraph_i_attribute_table->get_type(graph, type, elemtype, name); } else { return IGRAPH_SUCCESS; } @@ -178,6 +765,7 @@ igraph_error_t igraph_i_attribute_gettype(const igraph_t *graph, igraph_error_t igraph_i_attribute_get_numeric_graph_attr(const igraph_t *graph, const char *name, igraph_vector_t *value) { + igraph_vector_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_numeric_graph_attr(graph, name, value); } else { @@ -189,6 +777,7 @@ igraph_error_t igraph_i_attribute_get_numeric_vertex_attr(const igraph_t *graph, const char *name, igraph_vs_t vs, igraph_vector_t *value) { + igraph_vector_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_numeric_vertex_attr(graph, name, vs, value); } else { @@ -200,6 +789,7 @@ igraph_error_t igraph_i_attribute_get_numeric_edge_attr(const igraph_t *graph, const char *name, igraph_es_t es, igraph_vector_t *value) { + igraph_vector_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_numeric_edge_attr(graph, name, es, value); } else { @@ -210,6 +800,7 @@ igraph_error_t igraph_i_attribute_get_numeric_edge_attr(const igraph_t *graph, igraph_error_t igraph_i_attribute_get_string_graph_attr(const igraph_t *graph, const char *name, igraph_strvector_t *value) { + igraph_strvector_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_string_graph_attr(graph, name, value); } else { @@ -221,6 +812,7 @@ igraph_error_t igraph_i_attribute_get_string_vertex_attr(const igraph_t *graph, const char *name, igraph_vs_t vs, igraph_strvector_t *value) { + igraph_strvector_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_string_vertex_attr(graph, name, vs, value); } else { @@ -232,6 +824,7 @@ igraph_error_t igraph_i_attribute_get_string_edge_attr(const igraph_t *graph, const char *name, igraph_es_t es, igraph_strvector_t *value) { + igraph_strvector_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_string_edge_attr(graph, name, es, value); } else { @@ -242,6 +835,7 @@ igraph_error_t igraph_i_attribute_get_string_edge_attr(const igraph_t *graph, igraph_error_t igraph_i_attribute_get_bool_graph_attr(const igraph_t *graph, const char *name, igraph_vector_bool_t *value) { + igraph_vector_bool_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_bool_graph_attr(graph, name, value); } else { @@ -253,6 +847,7 @@ igraph_error_t igraph_i_attribute_get_bool_vertex_attr(const igraph_t *graph, const char *name, igraph_vs_t vs, igraph_vector_bool_t *value) { + igraph_vector_bool_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_bool_vertex_attr(graph, name, vs, value); } else { @@ -264,6 +859,7 @@ igraph_error_t igraph_i_attribute_get_bool_edge_attr(const igraph_t *graph, const char *name, igraph_es_t es, igraph_vector_bool_t *value) { + igraph_vector_bool_clear(value); if (igraph_i_attribute_table) { return igraph_i_attribute_table->get_bool_edge_attr(graph, name, es, value); } else { @@ -301,12 +897,6 @@ igraph_set_attribute_table(const igraph_attribute_table_t * table) { return old; } -igraph_attribute_table_t * -igraph_i_set_attribute_table(const igraph_attribute_table_t * table) { - IGRAPH_WARNING("igraph_i_set_attribute_table is deprecated, use igraph_set_attribute_table."); - return igraph_set_attribute_table(table); -} - igraph_bool_t igraph_has_attribute_table(void) { return igraph_i_attribute_table != NULL; } diff --git a/src/vendor/cigraph/src/graph/attributes.h b/src/vendor/cigraph/src/graph/attributes.h index c1ceb3e7a0f..257a83d50da 100644 --- a/src/vendor/cigraph/src/graph/attributes.h +++ b/src/vendor/cigraph/src/graph/attributes.h @@ -24,26 +24,20 @@ #include "igraph_strvector.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_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); @@ -110,6 +106,6 @@ igraph_error_t igraph_i_attribute_get_bool_edge_attr(const igraph_t *graph, igraph_es_t es, igraph_vector_bool_t *value); -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_GRAPH_ATTRIBUTES_H */ diff --git a/src/vendor/cigraph/src/graph/basic_query.c b/src/vendor/cigraph/src/graph/basic_query.c index 10dc66cdb4a..780fddf9e63 100644 --- a/src/vendor/cigraph/src/graph/basic_query.c +++ b/src/vendor/cigraph/src/graph/basic_query.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -62,32 +61,3 @@ igraph_error_t igraph_are_adjacent(const igraph_t *graph, return IGRAPH_SUCCESS; } - - -/** - * \ingroup structural - * \function igraph_are_connected - * \brief Decides whether two vertices are adjacent (deprecated alias). - * - * \deprecated-by igraph_are_adjacent 0.10.10 - * - * Decides whether there are any edges that have \p v1 and \p v2 - * as endpoints. This function is of course symmetric for undirected - * graphs. - * - * \param graph The graph object. - * \param v1 The first vertex. - * \param v2 The second vertex. - * \param res Boolean, \c true if there is an edge from - * \p v1 to \p v2, \c false otherwise. - * \return The error code \c IGRAPH_EINVVID is returned if an invalid - * vertex ID is given. - * - * Time complexity: O( min(log(d1), log(d2)) ), - * d1 is the (out-)degree of \p v1 and d2 is the (in-)degree of \p v2. - */ -igraph_error_t igraph_are_connected(const igraph_t *graph, - igraph_integer_t v1, igraph_integer_t v2, - igraph_bool_t *res) { - return igraph_are_adjacent(graph, v1, v2, res); -} diff --git a/src/vendor/cigraph/src/graph/caching.h b/src/vendor/cigraph/src/graph/caching.h index 3a3e1491ffa..52459b8a8b5 100644 --- a/src/vendor/cigraph/src/graph/caching.h +++ b/src/vendor/cigraph/src/graph/caching.h @@ -28,7 +28,7 @@ #include /* memset */ -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS struct igraph_i_property_cache_t { igraph_bool_t value[IGRAPH_PROP_I_SIZE]; @@ -47,6 +47,6 @@ void igraph_i_property_cache_invalidate_conditionally( const igraph_t *graph, uint32_t keep_always, uint32_t keep_when_false, uint32_t keep_when_true ); -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_CACHING_H */ diff --git a/src/vendor/cigraph/src/graph/cattributes.c b/src/vendor/cigraph/src/graph/cattributes.c index f4242af7f70..7ff60db13ff 100644 --- a/src/vendor/cigraph/src/graph/cattributes.c +++ b/src/vendor/cigraph/src/graph/cattributes.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -9,7 +8,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. @@ -26,191 +24,193 @@ #include "igraph_interface.h" #include "igraph_random.h" -#include "internal/hacks.h" /* strdup */ - #include /* 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 n = igraph_attribute_record_list_size(attrs); + for (igraph_integer_t i = 0; i < n; i++) { + const 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); + const 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 +220,133 @@ 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_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 (igraph_integer_t 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_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); - 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(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); - } - } - } + IGRAPH_ASSERT(origlen >= 0); - /* 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); + /* Find all the attributes that are newly added, and create new value vectors + * for them in the original graph */ + for (igraph_integer_t i = 0; i < nattrno; i++) { + const igraph_attribute_record_t *nattr_entry = igraph_attribute_record_list_get_ptr(nattr, i); + const char *nname = nattr_entry->name; + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(val, nname, nattr_entry->type, origlen, NULL)); } /* Now append the new values */ - 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) { + length = igraph_attribute_record_list_size(val); + for (igraph_integer_t i = 0; i < length; i++) { + 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 +363,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 { @@ -566,7 +425,7 @@ static igraph_error_t igraph_i_attribute_permutation_work_area_alloc_for_numeric if (vec == NULL) { vec = IGRAPH_CALLOC(1, igraph_vector_t); - IGRAPH_CHECK_OOM(vec, "Cannot permute attributes"); + IGRAPH_CHECK_OOM(vec, "Cannot permute attributes."); IGRAPH_FINALLY(igraph_free, vec); IGRAPH_CHECK(igraph_vector_init(vec, work_area->length)); work_area->numeric = vec; @@ -583,7 +442,7 @@ static igraph_error_t igraph_i_attribute_permutation_work_area_alloc_for_boolean if (vec == NULL) { vec = IGRAPH_CALLOC(1, igraph_vector_bool_t); - IGRAPH_CHECK_OOM(vec, "Cannot permute attributes"); + IGRAPH_CHECK_OOM(vec, "Cannot permute attributes."); IGRAPH_FINALLY(igraph_free, vec); IGRAPH_CHECK(igraph_vector_bool_init(vec, work_area->length)); work_area->boolean = vec; @@ -600,7 +459,7 @@ static igraph_error_t igraph_i_attribute_permutation_work_area_alloc_for_strings if (vec == NULL) { vec = IGRAPH_CALLOC(1, igraph_vector_ptr_t); - IGRAPH_CHECK_OOM(vec, "Cannot permute attributes"); + IGRAPH_CHECK_OOM(vec, "Cannot permute attributes."); IGRAPH_FINALLY(igraph_free, vec); IGRAPH_CHECK(igraph_vector_ptr_init(vec, 0)); IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(vec, igraph_strvector_destroy); @@ -619,7 +478,7 @@ static igraph_error_t igraph_i_attribute_permutation_work_area_permute_and_store igraph_strvector_t *new_vec; new_vec = IGRAPH_CALLOC(1, igraph_strvector_t); - IGRAPH_CHECK_OOM(new_vec, "Cannot permute attributes"); + IGRAPH_CHECK_OOM(new_vec, "Cannot permute attributes."); IGRAPH_FINALLY(igraph_free, new_vec); IGRAPH_CHECK(igraph_strvector_init(new_vec, 0)); IGRAPH_FINALLY(igraph_strvector_destroy, new_vec); @@ -631,13 +490,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, j; + igraph_integer_t 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 (igraph_integer_t 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_attribute_record_t *oldrec; igraph_vector_t *num, *num_work; igraph_strvector_t *str, str_work; @@ -646,7 +557,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 +566,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 (igraph_integer_t 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 +600,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 (igraph_integer_t 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 +617,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 (igraph_integer_t 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 +631,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 (igraph_integer_t 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 +667,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,84 +687,57 @@ 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++) { + for (igraph_integer_t i = 0; i < newlen; i++) { igraph_real_t s = 0.0; - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; - igraph_integer_t j, n = igraph_vector_int_size(idx); - for (j = 0; j < n; j++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); + for (igraph_integer_t j = 0; j < n; j++) { igraph_integer_t x = VECTOR(*idx)[j]; s += VECTOR(*oldv)[x]; } 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++) { + for (igraph_integer_t i = 0; i < newlen; i++) { igraph_real_t s = 1.0; - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; - igraph_integer_t j, n = igraph_vector_int_size(idx); - for (j = 0; j < n; j++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); + for (igraph_integer_t j = 0; j < n; j++) { igraph_integer_t x = VECTOR(*idx)[j]; s *= VECTOR(*oldv)[x]; } 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); + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); igraph_real_t m = n > 0 ? VECTOR(*oldv)[ VECTOR(*idx)[0] ] : IGRAPH_NAN; - for (j = 1; j < n; j++) { + for (igraph_integer_t j = 1; j < n; j++) { igraph_integer_t x = VECTOR(*idx)[j]; igraph_real_t val = VECTOR(*oldv)[x]; if (val < m) { @@ -940,31 +747,21 @@ 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); + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); igraph_real_t m = n > 0 ? VECTOR(*oldv)[ VECTOR(*idx)[0] ] : IGRAPH_NAN; - for (j = 1; j < n; j++) { + for (igraph_integer_t j = 1; j < n; j++) { igraph_integer_t x = VECTOR(*idx)[j]; igraph_real_t val = VECTOR(*oldv)[x]; if (val > m) { @@ -974,9 +771,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,21 +778,12 @@ 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++) { - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = IGRAPH_NAN; @@ -1010,11 +795,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,19 +802,12 @@ 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);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = IGRAPH_NAN; @@ -1043,9 +816,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,19 +823,12 @@ 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);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = IGRAPH_NAN; @@ -1074,31 +837,21 @@ 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); + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); igraph_real_t s = n > 0 ? 0.0 : IGRAPH_NAN; - for (j = 0; j < n; j++) { + for (igraph_integer_t j = 0; j < n; j++) { igraph_integer_t x = VECTOR(*idx)[j]; s += VECTOR(*oldv)[x]; } @@ -1108,9 +861,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,19 +869,15 @@ 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); for (igraph_integer_t i = 0; i < newlen; i++) { - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); IGRAPH_CHECK(igraph_vector_resize(&values, n)); @@ -1146,8 +892,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,21 +901,12 @@ 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++) { - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = 0; @@ -1182,11 +918,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,19 +925,12 @@ 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);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = 0; @@ -1215,9 +939,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,19 +946,12 @@ 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);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = 0; @@ -1246,9 +960,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,23 +967,16 @@ 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); + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); VECTOR(*newv)[i] = 1; - for (j = 0; j < n; j++) { - x = VECTOR(*idx)[j]; + for (igraph_integer_t j = 0; j < n; j++) { + igraph_integer_t x = VECTOR(*idx)[j]; if (!VECTOR(*oldv)[x]) { VECTOR(*newv)[i] = 0; break; @@ -1280,9 +984,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,23 +991,16 @@ 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); + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); VECTOR(*newv)[i] = 0; - for (j = 0; j < n; j++) { - x = VECTOR(*idx)[j]; + for (igraph_integer_t j = 0; j < n; j++) { + igraph_integer_t x = VECTOR(*idx)[j]; if (VECTOR(*oldv)[x]) { VECTOR(*newv)[i] = 1; break; @@ -1314,9 +1008,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,27 +1015,17 @@ 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++) { - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; - - n = igraph_vector_int_size(idx); + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); - num_trues = 0; - for (j = 0; j < n; j++) { - x = VECTOR(*idx)[j]; + igraph_integer_t num_trues = 0; + for (igraph_integer_t j = 0; j < n; j++) { + igraph_integer_t x = VECTOR(*idx)[j]; if (VECTOR(*oldv)[x]) { num_trues++; } @@ -1361,11 +1042,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,19 +1050,15 @@ 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); for (igraph_integer_t i = 0; i < newlen; i++) { - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); IGRAPH_CHECK(igraph_vector_bool_resize(&values, n)); @@ -1401,8 +1073,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,21 +1082,12 @@ 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(); - - for (i = 0; i < newlen; i++) { - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); const char *tmp; if (n == 0) { @@ -1440,30 +1102,19 @@ 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; - 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); + const igraph_strvector_t *oldv = oldrec->value.as_strvector; + igraph_integer_t newlen = igraph_vector_int_list_size(merges); + 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);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { IGRAPH_CHECK(igraph_strvector_set(newv, i, "")); @@ -1473,28 +1124,19 @@ 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; - 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); + const igraph_strvector_t *oldv = oldrec->value.as_strvector; + igraph_integer_t newlen = igraph_vector_int_list_size(merges); + 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);; + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); if (n == 0) { IGRAPH_CHECK(igraph_strvector_set(newv, i, "")); @@ -1504,43 +1146,32 @@ 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; - 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); + const igraph_strvector_t *oldv = oldrec->value.as_strvector; + igraph_integer_t newlen = igraph_vector_int_list_size(merges); + 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);; - igraph_integer_t j, n = igraph_vector_int_size(idx); + for (igraph_integer_t i = 0; i < newlen; i++) { + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); + igraph_integer_t n = igraph_vector_int_size(idx); size_t len = 0; const char *tmp; char *tmp2; - for (j = 0; j < n; j++) { + for (igraph_integer_t j = 0; j < n; j++) { tmp = igraph_strvector_get(oldv, j); 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++) { + for (igraph_integer_t j = 0; j < n; j++) { tmp = igraph_strvector_get(oldv, j); strcpy(tmp2 + len, tmp); len += strlen(tmp); @@ -1551,30 +1182,23 @@ 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); for (igraph_integer_t i = 0; i < newlen; i++) { - igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; + const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); igraph_integer_t n = igraph_vector_int_size(idx); IGRAPH_CHECK(igraph_strvector_resize(&values, n)); @@ -1595,8 +1219,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; } @@ -1641,650 +1264,35 @@ typedef struct { } 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; +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_attribute_combination_todo_item_t *todo_items; - IGRAPH_ASSERT(graph != newgraph); - IGRAPH_ASSERT(igraph_vector_ptr_empty(new_val)); + IGRAPH_ASSERT(attrs != new_attrs); + IGRAPH_ASSERT(igraph_attribute_record_list_empty(new_attrs)); - 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 */ - } + 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 < valno; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*val)[i]; + for (igraph_integer_t i = 0; i < no_attrs; i++) { + const igraph_attribute_record_t *oldrec = igraph_attribute_record_list_get_ptr(attrs, 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; -} - -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; - 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; - igraph_attribute_combination_todo_item_t *todo_items; - - IGRAPH_ASSERT(graph != newgraph); - IGRAPH_ASSERT(igraph_vector_ptr_empty(new_eal)); - - 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 */ - } - IGRAPH_FINALLY(igraph_free, todo_items); - - for (i = 0; i < ealno; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*eal)[i]; - const char *name = oldrec->name; - igraph_attribute_combination_type_t todo; - igraph_function_pointer_t voidfunc; - IGRAPH_CHECK(igraph_attribute_combination_query(comb, name, &todo, &voidfunc)); - todo_items[i].type = todo; + todo_items[i].type = type; todo_items[i].func.as_void = voidfunc; - if (todo != IGRAPH_ATTRIBUTE_COMBINE_IGNORE) { - keepno++; - } } - 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 (igraph_integer_t i = 0; i < no_attrs; i++) { + const 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,151 +1302,142 @@ 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", + IGRAPH_ERROR("Median calculation not implemented.", IGRAPH_UNIMPLEMENTED); break; case IGRAPH_ATTRIBUTE_COMBINE_CONCAT: - IGRAPH_ERROR("Cannot concatenate numeric attributes", + IGRAPH_ERROR("Cannot concatenate numeric attributes.", 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_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: - IGRAPH_ERROR("Cannot sum strings", IGRAPH_EATTRCOMBINE); + IGRAPH_ERROR("Cannot sum strings.", IGRAPH_EATTRCOMBINE); break; case IGRAPH_ATTRIBUTE_COMBINE_PROD: - IGRAPH_ERROR("Cannot multiply strings", IGRAPH_EATTRCOMBINE); + IGRAPH_ERROR("Cannot multiply strings.", IGRAPH_EATTRCOMBINE); break; case IGRAPH_ATTRIBUTE_COMBINE_MIN: - IGRAPH_ERROR("Cannot find minimum of strings", + IGRAPH_ERROR("Cannot find minimum of strings.", IGRAPH_EATTRCOMBINE); break; case IGRAPH_ATTRIBUTE_COMBINE_MAX: - IGRAPH_ERROR("Cannot find maximum of strings", + IGRAPH_ERROR("Cannot find maximum of strings.", IGRAPH_EATTRCOMBINE); break; case IGRAPH_ATTRIBUTE_COMBINE_MEAN: - IGRAPH_ERROR("Cannot calculate mean of strings", + IGRAPH_ERROR("Cannot calculate mean of strings.", IGRAPH_EATTRCOMBINE); break; case IGRAPH_ATTRIBUTE_COMBINE_MEDIAN: - IGRAPH_ERROR("Cannot calculate median of strings", + 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)); + 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; } } else { - IGRAPH_ERROR("Unknown attribute type, this should not happen", + IGRAPH_ERROR("Unknown attribute type, this should not happen.", 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 +1446,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 +1500,13 @@ 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_integer_t i, j; + igraph_attribute_record_list_t *attr[3] = { &at->gal, &at->val, &at->eal }; - for (i = 0; i < 3; i++) { + for (igraph_integer_t 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); + const 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)); @@ -2474,8 +1515,8 @@ static igraph_error_t igraph_i_cattribute_get_info(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(t, len)); } - for (j = 0; j < len; j++) { - igraph_attribute_record_t *rec = VECTOR(*al)[j]; + for (igraph_integer_t j = 0; j < len; j++) { + const 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) { @@ -2493,137 +1534,86 @@ static igraph_error_t igraph_i_cattribute_get_info(const igraph_t *graph, 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; - + const igraph_i_cattributes_t *at = graph->attr; 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); + IGRAPH_ERROR("Unknown attribute element type.", IGRAPH_EINVAL); break; } - return igraph_i_cattribute_find(attr[attrnum], name, 0); + return false; } -static igraph_error_t igraph_i_cattribute_gettype(const igraph_t *graph, +static igraph_error_t igraph_i_cattribute_get_type(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); + 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); - } - - 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; - IGRAPH_CHECK(igraph_vector_resize(value, 1)); - VECTOR(*value)[0] = VECTOR(*num)[0]; + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(gal, name, IGRAPH_ATTRIBUTE_NUMERIC, &rec)); + IGRAPH_CHECK(igraph_vector_push_back(value, VECTOR(*rec->value.as_vector)[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); - } - 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; - IGRAPH_CHECK(igraph_vector_bool_resize(value, 1)); - VECTOR(*value)[0] = VECTOR(*log)[0]; + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(gal, name, IGRAPH_ATTRIBUTE_BOOLEAN, &rec)); + IGRAPH_CHECK(igraph_vector_bool_push_back(value, VECTOR(*rec->value.as_vector_bool)[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); - } - 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; - IGRAPH_CHECK(igraph_strvector_resize(value, 1)); - IGRAPH_CHECK(igraph_strvector_set(value, 0, igraph_strvector_get(str, 0))); + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(gal, name, IGRAPH_ATTRIBUTE_STRING, &rec)); + IGRAPH_CHECK(igraph_strvector_push_back(value, igraph_strvector_get(rec->value.as_strvector, 0))); return IGRAPH_SUCCESS; } @@ -2633,30 +1623,21 @@ 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); + const igraph_vector_t *num; - 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)); } else { igraph_vit_t it; - igraph_integer_t i = 0; + igraph_integer_t i = igraph_vector_size(value); IGRAPH_CHECK(igraph_vit_create(graph, vs, &it)); IGRAPH_FINALLY(igraph_vit_destroy, &it); - IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_VIT_SIZE(it))); + IGRAPH_CHECK(igraph_vector_resize(value, i + IGRAPH_VIT_SIZE(it))); for (; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) { igraph_integer_t v = IGRAPH_VIT_GET(it); VECTOR(*value)[i] = VECTOR(*num)[v]; @@ -2673,31 +1654,23 @@ 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_vit_t it; - igraph_integer_t i, j, v; + igraph_attribute_record_list_t *val = &attr->val; igraph_attribute_record_t *rec; - igraph_vector_bool_t *log; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); + const igraph_vector_bool_t *log; - 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)); } else { + igraph_vit_t it; + igraph_integer_t i = igraph_vector_bool_size(value); IGRAPH_CHECK(igraph_vit_create(graph, vs, &it)); IGRAPH_FINALLY(igraph_vit_destroy, &it); - IGRAPH_CHECK(igraph_vector_bool_resize(value, IGRAPH_VIT_SIZE(it))); - for (i = 0; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) { - v = IGRAPH_VIT_GET(it); + IGRAPH_CHECK(igraph_vector_bool_resize(value, i + IGRAPH_VIT_SIZE(it))); + for (; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) { + igraph_integer_t v = IGRAPH_VIT_GET(it); VECTOR(*value)[i] = VECTOR(*log)[v]; } igraph_vit_destroy(&it); @@ -2712,34 +1685,25 @@ 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); + const igraph_strvector_t *str; - 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)); } else { igraph_vit_t it; - igraph_integer_t i = 0; + igraph_integer_t i = igraph_strvector_size(value); IGRAPH_CHECK(igraph_vit_create(graph, vs, &it)); IGRAPH_FINALLY(igraph_vit_destroy, &it); - IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_VIT_SIZE(it))); + IGRAPH_CHECK(igraph_strvector_resize(value, i + IGRAPH_VIT_SIZE(it))); for (; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) { igraph_integer_t v = IGRAPH_VIT_GET(it); - const char *s = igraph_strvector_get(str, v); - IGRAPH_CHECK(igraph_strvector_set(value, i, s)); + IGRAPH_CHECK(igraph_strvector_set(value, i, igraph_strvector_get(str, v))); } igraph_vit_destroy(&it); IGRAPH_FINALLY_CLEAN(1); @@ -2748,35 +1712,25 @@ 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); + const igraph_vector_t *num; - 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)); } else { igraph_eit_t it; - igraph_integer_t i = 0; + igraph_integer_t i = igraph_vector_size(value); IGRAPH_CHECK(igraph_eit_create(graph, es, &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); - IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_EIT_SIZE(it))); + IGRAPH_CHECK(igraph_vector_resize(value, i + IGRAPH_EIT_SIZE(it))); for (; !IGRAPH_EIT_END(it); IGRAPH_EIT_NEXT(it), i++) { igraph_integer_t e = IGRAPH_EIT_GET(it); VECTOR(*value)[i] = VECTOR(*num)[e]; @@ -2788,39 +1742,29 @@ 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); + const igraph_strvector_t *str; - 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)); } else { igraph_eit_t it; - igraph_integer_t i = 0; + igraph_integer_t i = igraph_strvector_size(value); IGRAPH_CHECK(igraph_eit_create(graph, es, &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); - IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_EIT_SIZE(it))); + IGRAPH_CHECK(igraph_strvector_resize(value, i + IGRAPH_EIT_SIZE(it))); for (; !IGRAPH_EIT_END(it); IGRAPH_EIT_NEXT(it), i++) { igraph_integer_t e = IGRAPH_EIT_GET(it); - const char *s = igraph_strvector_get(str, e); - IGRAPH_CHECK(igraph_strvector_set(value, i, s)); + IGRAPH_CHECK(igraph_strvector_set(value, i, igraph_strvector_get(str, e))); } igraph_eit_destroy(&it); IGRAPH_FINALLY_CLEAN(1); @@ -2829,35 +1773,26 @@ 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); + const igraph_vector_bool_t *log; - 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)); } else { igraph_eit_t it; - igraph_integer_t i = 0; + igraph_integer_t i = igraph_vector_bool_size(value); IGRAPH_CHECK(igraph_eit_create(graph, es, &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); - IGRAPH_CHECK(igraph_vector_bool_resize(value, IGRAPH_EIT_SIZE(it))); + IGRAPH_CHECK(igraph_vector_bool_resize(value, i + IGRAPH_EIT_SIZE(it))); for (; !IGRAPH_EIT_END(it); IGRAPH_EIT_NEXT(it), i++) { igraph_integer_t e = IGRAPH_EIT_GET(it); VECTOR(*value)[i] = VECTOR(*log)[e]; @@ -2883,7 +1818,7 @@ const igraph_attribute_table_t igraph_cattribute_table = { &igraph_i_cattribute_combine_edges, &igraph_i_cattribute_get_info, &igraph_i_cattribute_has_attr, - &igraph_i_cattribute_gettype, + &igraph_i_cattribute_get_type, &igraph_i_cattribute_get_numeric_graph_attr, &igraph_i_cattribute_get_string_graph_attr, &igraph_i_cattribute_get_bool_graph_attr, @@ -2954,21 +1889,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); + const igraph_attribute_record_t *rec; + const igraph_vector_t *num; - 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 +1920,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); + const igraph_attribute_record_t *rec; + const igraph_vector_bool_t *log; - 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 +1952,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); + const igraph_attribute_record_t *rec; + const igraph_strvector_t *str; - 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 +1986,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); + const igraph_attribute_record_t *rec; + const igraph_vector_t *num; - 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 +2019,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); + const igraph_attribute_record_t *rec; + const igraph_vector_bool_t *log; - 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 +2054,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); + const igraph_attribute_record_t *rec; + const igraph_strvector_t *str; - 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 +2087,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); + const igraph_attribute_record_t *rec; + const igraph_vector_t *num; - 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 +2120,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); + const igraph_attribute_record_t *rec; + const igraph_vector_bool_t *log; - 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 +2155,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); + const igraph_attribute_record_t *rec; + const igraph_strvector_t *str; - 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 +2184,8 @@ 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); + igraph_vector_clear(result); + return igraph_i_cattribute_get_numeric_vertex_attr(graph, name, vids, result); } /** @@ -3300,9 +2204,8 @@ 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); + igraph_vector_bool_clear(result); + return igraph_i_cattribute_get_bool_vertex_attr(graph, name, vids, result); } /** @@ -3321,9 +2224,8 @@ 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); + igraph_vector_clear(result); + return igraph_i_cattribute_get_numeric_edge_attr(graph, name, eids, result); } /** @@ -3342,9 +2244,8 @@ 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); + igraph_vector_bool_clear(result); + return igraph_i_cattribute_get_bool_edge_attr(graph, name, eids, result); } /** @@ -3364,9 +2265,8 @@ 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); + igraph_strvector_clear(result); + return igraph_i_cattribute_get_string_vertex_attr(graph, name, vids, result); } /** @@ -3386,9 +2286,8 @@ 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); + igraph_strvector_clear(result); + return igraph_i_cattribute_get_string_edge_attr(graph, name, eids, result); } /** @@ -3454,44 +2353,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 +2383,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 +2414,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 +2448,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 +2479,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 +2511,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 +2542,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 +2573,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 +2605,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 +2635,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)) { - IGRAPH_ERROR("Invalid vertex attribute vector length", IGRAPH_EINVAL); + 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 +2668,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)) { - IGRAPH_ERROR("Invalid vertex attribute vector length", IGRAPH_EINVAL); + 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 +2700,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)) { - IGRAPH_ERROR("Invalid vertex attribute vector length", IGRAPH_EINVAL); + 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 +2732,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)) { - IGRAPH_ERROR("Invalid edge attribute vector length", IGRAPH_EINVAL); + 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 +2764,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)) { - IGRAPH_ERROR("Invalid edge attribute vector length", IGRAPH_EINVAL); + 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 +2797,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)) { - IGRAPH_ERROR("Invalid edge attribute vector length", IGRAPH_EINVAL); + 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 +2825,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 +2848,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 +2866,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 +2898,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/graph_list.c b/src/vendor/cigraph/src/graph/graph_list.c index 9d82ec2901a..39ecc926526 100644 --- a/src/vendor/cigraph/src/graph/graph_list.c +++ b/src/vendor/cigraph/src/graph/graph_list.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2022 The igraph development team diff --git a/src/vendor/cigraph/src/graph/internal.h b/src/vendor/cigraph/src/graph/internal.h index 1e5d2620c1b..0ab34f5ffc4 100644 --- a/src/vendor/cigraph/src/graph/internal.h +++ b/src/vendor/cigraph/src/graph/internal.h @@ -21,22 +21,12 @@ #include "igraph_datatype.h" #include "igraph_decls.h" -#include "igraph_constants.h" #include "igraph_error.h" -#include "igraph_vector.h" -__BEGIN_DECLS - -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_neighbors( - const igraph_t *graph, igraph_vector_int_t *neis, igraph_integer_t pnode, - igraph_neimode_t mode, igraph_loops_t loops, igraph_multiple_t multiple); - -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_incident( - const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t pnode, - igraph_neimode_t mode, igraph_loops_t loops); +IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_reverse(igraph_t *graph); -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_GRAPH_INTERNAL_H */ diff --git a/src/vendor/cigraph/src/graph/iterators.c b/src/vendor/cigraph/src/graph/iterators.c index 79a2abbdb0f..f9aa111912b 100644 --- a/src/vendor/cigraph/src/graph/iterators.c +++ b/src/vendor/cigraph/src/graph/iterators.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -145,17 +144,32 @@ igraph_vs_t igraph_vss_all(void) { * from/to \c vid. That is, all the neighbors of \c vid considered * as if the graph is undirected. * \endclist + * \param loops Whether to include the vertex itself in the neighborhood if the + * vertex has a loop edge. If \c IGRAPH_NO_LOOPS, loop edges are + * excluded. If \c IGRAPH_LOOPS_ONCE, the vertex is included in its own + * neighborhood once for every loop edge that it has. If + * \c IGRAPH_LOOPS_TWICE, the vertex is included twice in its own + * neighborhood for every loop edge that it has, but only if the graph is + * undirected or \p mode is set to \c IGRAPH_ALL. + * \param multiple Whether to include multiple edges. If \c IGRAPH_NO_MULTIPLE, + * multiple edges are not included in the neighborhood. If + * \c IGRAPH_MULTIPLE, multiple edges are included in the neighborhood. + * * \return Error code. * \sa \ref igraph_vs_destroy() * * Time complexity: O(1). */ -igraph_error_t igraph_vs_adj(igraph_vs_t *vs, - igraph_integer_t vid, igraph_neimode_t mode) { +igraph_error_t igraph_vs_adj( + igraph_vs_t *vs, igraph_integer_t vid, igraph_neimode_t mode, + igraph_loops_t loops, igraph_bool_t multiple +) { vs->type = IGRAPH_VS_ADJ; vs->data.adj.vid = vid; vs->data.adj.mode = mode; + vs->data.adj.loops = loops; + vs->data.adj.multiple = multiple; return IGRAPH_SUCCESS; } @@ -201,6 +215,8 @@ igraph_error_t igraph_vs_nonadj(igraph_vs_t *vs, igraph_integer_t vid, vs->type = IGRAPH_VS_NONADJ; vs->data.adj.vid = vid; vs->data.adj.mode = mode; + vs->data.adj.loops = IGRAPH_LOOPS; + vs->data.adj.multiple = IGRAPH_MULTIPLE; return IGRAPH_SUCCESS; } @@ -474,52 +490,6 @@ igraph_vs_t igraph_vss_range(igraph_integer_t start, igraph_integer_t end) { return vs; } -/** - * \function igraph_vs_seq - * \brief Vertex set, an interval of vertices with inclusive endpoints (deprecated). - * - * Creates a vertex selector containing all vertices with vertex ID - * equal to or bigger than \p from and equal to or smaller than \p to. - * Note that both endpoints are inclusive, contrary to C conventions. - * - * \deprecated-by igraph_vs_range 0.10.0 - * - * \param vs Pointer to an uninitialized vertex selector object. - * \param from The first vertex ID to be included in the vertex selector. - * \param to The last vertex ID to be included in the vertex selector. - * \return Error code. - * \sa \ref igraph_vs_range(), \ref igraph_vss_seq(), \ref igraph_vs_destroy() - * - * Time complexity: O(1). - * - * \example examples/simple/igraph_vs_range.c - */ - -igraph_error_t igraph_vs_seq(igraph_vs_t *vs, igraph_integer_t from, igraph_integer_t to) { - *vs = igraph_vss_range(from, to + 1); - return IGRAPH_SUCCESS; -} - -/** - * \function igraph_vss_seq - * \brief An interval of vertices with inclusive endpoints (immediate version, deprecated). - * - * The immediate version of \ref igraph_vs_seq(). - * - * \deprecated-by igraph_vss_range 0.10.0 - * - * \param from The first vertex ID to be included in the vertex selector. - * \param to The last vertex ID to be included in the vertex selector. - * \return Error code. - * \sa \ref igraph_vss_range(), \ref igraph_vs_seq() - * - * Time complexity: O(1). - */ - -igraph_vs_t igraph_vss_seq(igraph_integer_t from, igraph_integer_t to) { - return igraph_vss_range(from, to + 1); -} - /** * \function igraph_vs_destroy * \brief Destroy a vertex set. @@ -664,7 +634,10 @@ igraph_error_t igraph_vs_size(const igraph_t *graph, const igraph_vs_t *vs, case IGRAPH_VS_ADJ: IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &vec, vs->data.adj.vid, vs->data.adj.mode)); + IGRAPH_CHECK(igraph_neighbors( + graph, &vec, vs->data.adj.vid, vs->data.adj.mode, + vs->data.adj.loops, vs->data.adj.multiple + )); *result = igraph_vector_int_size(&vec); igraph_vector_int_destroy(&vec); IGRAPH_FINALLY_CLEAN(1); @@ -672,7 +645,10 @@ igraph_error_t igraph_vs_size(const igraph_t *graph, const igraph_vs_t *vs, case IGRAPH_VS_NONADJ: IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &vec, vs->data.adj.vid, vs->data.adj.mode)); + IGRAPH_CHECK(igraph_neighbors( + graph, &vec, vs->data.adj.vid, vs->data.adj.mode, + vs->data.adj.loops, vs->data.adj.multiple + )); vec_len = igraph_vector_int_size(&vec); *result = igraph_vcount(graph); seen = IGRAPH_CALLOC(*result, igraph_bool_t); @@ -753,7 +729,10 @@ igraph_error_t igraph_vit_create(const igraph_t *graph, igraph_vs_t vs, igraph_v IGRAPH_FINALLY(igraph_free, vec_int); IGRAPH_VECTOR_INT_INIT_FINALLY(vec_int, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &vec, vs.data.adj.vid, vs.data.adj.mode)); + IGRAPH_CHECK(igraph_neighbors( + graph, &vec, vs.data.adj.vid, vs.data.adj.mode, + vs.data.adj.loops, vs.data.adj.multiple + )); n = igraph_vector_int_size(&vec); IGRAPH_CHECK(igraph_vector_int_resize(vec_int, n)); for (i = 0; i < n; i++) { @@ -776,7 +755,10 @@ igraph_error_t igraph_vit_create(const igraph_t *graph, igraph_vs_t vs, igraph_v IGRAPH_FINALLY(igraph_free, vec_int); IGRAPH_VECTOR_INT_INIT_FINALLY(vec_int, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &vec, vs.data.adj.vid, vs.data.adj.mode)); + IGRAPH_CHECK(igraph_neighbors( + graph, &vec, vs.data.adj.vid, vs.data.adj.mode, + vs.data.adj.loops, vs.data.adj.multiple + )); vec_len = igraph_vector_int_size(&vec); n = igraph_vcount(graph); seen = IGRAPH_CALLOC(n, igraph_bool_t); @@ -986,17 +968,25 @@ igraph_es_t igraph_ess_all(igraph_edgeorder_type_t order) { * \c IGRAPH_OUT, outgoing edges; * \c IGRAPH_IN, incoming edges; * \c IGRAPH_ALL, all edges. + * \param loops Whether to include loop edges in the result. If + * \c IGRAPH_NO_LOOPS, loop edges are excluded. If \c IGRAPH_LOOPS_ONCE, + * loop edges are included once. If \c IGRAPH_LOOPS_TWICE, loop edges + * are included twice, but only if the graph is undirected or \p mode is + * set to \c IGRAPH_ALL. * \return Error code. * \sa \ref igraph_es_destroy() * * Time complexity: O(1). */ -igraph_error_t igraph_es_incident(igraph_es_t *es, - igraph_integer_t vid, igraph_neimode_t mode) { +igraph_error_t igraph_es_incident( + igraph_es_t *es, igraph_integer_t vid, igraph_neimode_t mode, + igraph_loops_t loops +) { es->type = IGRAPH_ES_INCIDENT; es->data.incident.vid = vid; es->data.incident.mode = mode; + es->data.incident.loops = loops; return IGRAPH_SUCCESS; } @@ -1196,47 +1186,6 @@ igraph_es_t igraph_ess_range(igraph_integer_t start, igraph_integer_t end) { return es; } -/** - * \function igraph_es_seq - * \brief Edge selector, a sequence of edge IDs, with inclusive endpoints (deprecated). - * - * All edge IDs between \p from and \p to (inclusive) will be - * included in the edge selection. - * - * \deprecated-by igraph_es_range 0.10.0 - * - * \param es Pointer to an uninitialized edge selector object. - * \param from The first edge ID to be included. - * \param to The last edge ID to be included. - * \return Error code. - * \sa \ref igraph_ess_seq(), \ref igraph_es_destroy() - * - * Time complexity: O(1). - */ - -igraph_error_t igraph_es_seq(igraph_es_t *es, igraph_integer_t from, igraph_integer_t to) { - *es = igraph_ess_range(from, to + 1); - return IGRAPH_SUCCESS; -} - -/** - * \function igraph_ess_seq - * \brief Immediate version of the sequence edge selector, with inclusive endpoints. - * - * \deprecated-by igraph_ess_range 0.10.0 - * - * \param from The first edge ID to include. - * \param to The last edge ID to include. - * \return The initialized edge selector. - * \sa \ref igraph_es_seq() - * - * Time complexity: O(1). - */ - -igraph_es_t igraph_ess_seq(igraph_integer_t from, igraph_integer_t to) { - return igraph_ess_range(from, to + 1); -} - /** * \function igraph_es_pairs * \brief Edge selector, multiple edges defined by their endpoints in a vector. @@ -1610,8 +1559,10 @@ igraph_error_t igraph_es_size(const igraph_t *graph, const igraph_es_t *es, case IGRAPH_ES_INCIDENT: IGRAPH_VECTOR_INT_INIT_FINALLY(&v, 0); - IGRAPH_CHECK(igraph_incident(graph, &v, - es->data.incident.vid, es->data.incident.mode)); + IGRAPH_CHECK(igraph_incident( + graph, &v, es->data.incident.vid, es->data.incident.mode, + es->data.incident.loops + )); *result = igraph_vector_int_size(&v); igraph_vector_int_destroy(&v); IGRAPH_FINALLY_CLEAN(1); @@ -1758,7 +1709,7 @@ static igraph_error_t igraph_i_eit_create_allfromto(const igraph_t *graph, igraph_vector_int_t adj; IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0); for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - IGRAPH_CHECK(igraph_incident(graph, &adj, i, mode)); + IGRAPH_CHECK(igraph_incident(graph, &adj, i, mode, IGRAPH_LOOPS)); igraph_vector_int_append(vec, &adj); /* reserved */ } igraph_vector_int_destroy(&adj); @@ -1771,7 +1722,7 @@ static igraph_error_t igraph_i_eit_create_allfromto(const igraph_t *graph, IGRAPH_CHECK_OOM(added, "Cannot create edge iterator."); IGRAPH_FINALLY(igraph_free, added); for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - IGRAPH_CHECK(igraph_incident(graph, &adj, i, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &adj, i, IGRAPH_ALL, IGRAPH_LOOPS)); const igraph_integer_t length = igraph_vector_int_size(&adj); for (igraph_integer_t j = 0; j < length; j++) { if (!added[ VECTOR(adj)[j] ]) { @@ -1802,7 +1753,10 @@ static igraph_error_t igraph_i_eit_create_incident(const igraph_t* graph, igraph_integer_t i, n; IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0); - IGRAPH_CHECK(igraph_incident(graph, &vec, es.data.incident.vid, es.data.incident.mode)); + IGRAPH_CHECK(igraph_incident( + graph, &vec, es.data.incident.vid, es.data.incident.mode, + es.data.incident.loops + )); vec_int = IGRAPH_CALLOC(1, igraph_vector_int_t); IGRAPH_CHECK_OOM(vec_int, "Cannot create edge iterator."); @@ -1994,7 +1948,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: @@ -2005,7 +1959,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: @@ -2014,10 +1968,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 a2d5f47b7d7..dfe921ad2a8 100644 --- a/src/vendor/cigraph/src/graph/type_common.c +++ b/src/vendor/cigraph/src/graph/type_common.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -90,7 +89,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 +132,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)) { @@ -142,35 +154,59 @@ igraph_error_t igraph_edge( * \param eids Edge selector, the series of edges. * \param edges Pointer to an initialized vector. The start and endpoints of * each edge will be placed here. + * \param bycol Boolean constant. If true, the edges will be returned + * columnwise, e.g. the first edge is + * res[0]->res[|E|], the second is + * res[1]->res[|E|+1], etc. Supply false to get + * the edge list in a format compatible with \ref igraph_add_edges(). * \return Error code. - * \sa \ref igraph_get_edgelist() to get the endpoints of all edges; - * \ref igraph_get_eids() for the opposite operation; + * \sa \ref igraph_get_eids() for the opposite operation; * \ref igraph_edge() for getting the endpoints of a single edge; * \ref IGRAPH_TO(), \ref IGRAPH_FROM() and \ref IGRAPH_OTHER() for * a faster but non-error-checked method. * * Time complexity: O(k) where k is the number of edges in the selector. */ -igraph_error_t igraph_edges(const igraph_t *graph, igraph_es_t eids, igraph_vector_int_t *edges) { +igraph_error_t igraph_edges( + const igraph_t *graph, igraph_es_t eids, igraph_vector_int_t *edges, + igraph_bool_t bycol +) { igraph_eit_t eit; - igraph_integer_t n, ptr = 0; + igraph_integer_t n, ptr = 0, ptr2; IGRAPH_CHECK(igraph_eit_create(graph, eids, &eit)); IGRAPH_FINALLY(igraph_eit_destroy, &eit); n = IGRAPH_EIT_SIZE(eit); IGRAPH_CHECK(igraph_vector_int_resize(edges, n * 2)); - if (igraph_is_directed(graph)) { - for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); - VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); - VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); + if (bycol) { + ptr2 = n; + if (igraph_is_directed(graph)) { + for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { + igraph_integer_t e = IGRAPH_EIT_GET(eit); + VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); + VECTOR(*edges)[ptr2++] = IGRAPH_TO(graph, e); + } + } else { + for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { + igraph_integer_t e = IGRAPH_EIT_GET(eit); + VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); + VECTOR(*edges)[ptr2++] = IGRAPH_FROM(graph, e); + } } } else { - for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); - VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); - VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); + if (igraph_is_directed(graph)) { + for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { + igraph_integer_t e = IGRAPH_EIT_GET(eit); + VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); + VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); + } + } else { + for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { + igraph_integer_t e = IGRAPH_EIT_GET(eit); + VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); + VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); + } } } diff --git a/src/vendor/cigraph/src/graph/type_indexededgelist.c b/src/vendor/cigraph/src/graph/type_indexededgelist.c index 5421e9c69f3..c66088a6ceb 100644 --- a/src/vendor/cigraph/src/graph/type_indexededgelist.c +++ b/src/vendor/cigraph/src/graph/type_indexededgelist.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -95,12 +94,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 +125,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 +151,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 +191,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 +214,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 +238,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 +249,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 +261,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 +384,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; @@ -407,7 +415,7 @@ igraph_error_t igraph_add_vertices(igraph_t *graph, igraph_integer_t nv, void *a /* Add attributes if necessary. This section is protected with * FINALLY_ENTER/EXIT so that the graph would not be accidentally - * free upon error until it could be restored to a consistant state. */ + * free upon error until it could be restored to a consistent state. */ if (graph->attr) { igraph_error_t err; @@ -605,14 +613,14 @@ 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. * * * This function changes the IDs of the vertices (except in some very * special cases, but these should not be relied on anyway). You can use the - * \c idx argument to obtain the mapping from old vertex IDs to the new ones, - * and the \c newidx argument to obtain the reverse mapping. + * \p map argument to obtain the mapping from old vertex IDs to the new ones, + * and the \p newmap argument to obtain the reverse mapping. * * * This function invalidates all iterators. @@ -620,12 +628,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 +639,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 +653,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); } @@ -666,31 +670,32 @@ igraph_error_t igraph_delete_vertices_idx( for (; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit) ) { igraph_integer_t vertex = IGRAPH_VIT_GET(vit); if (vertex < 0 || vertex >= no_of_nodes) { - IGRAPH_ERROR("Cannot delete vertices", IGRAPH_EINVVID); + IGRAPH_ERROR("Cannot delete vertices.", IGRAPH_EINVVID); } VECTOR(*my_vertex_recoding)[vertex] = 1; } /* 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 +712,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 +736,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 +750,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 +774,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); } @@ -861,28 +864,32 @@ igraph_integer_t igraph_ecount(const igraph_t *graph) { * \c IGRAPH_ALL, both kinds of vertices are * searched. * This parameter is ignored for undirected graphs. + * \param loops Specifies how to treat loop edges. \c IGRAPH_NO_LOOPS + * removes loop edges from the result. \c IGRAPH_LOOPS_ONCE + * makes each loop edge appear only once in the result. + * \c IGRAPH_LOOPS_TWICE makes loop edges appear \em twice in the + * result if the graph is undirected or \p mode is set to \c IGRAPH_ALL + * (and once otherwise as returning them twice does not make sense for + * directed graphs). + * \param multiple Specifies how to treat multiple (parallel) edges. + * \c IGRAPH_NO_MULTIPLE collapses parallel edges into a single one; + * \c IGRAPH_MULTIPLE keeps the multiplicities of parallel edges + * so the same neighbor will appear as many times in the result as the + * number of parallel edges going between the two vertices. * \return Error code: * \c IGRAPH_EINVVID: invalid vertex ID. * \c IGRAPH_EINVMODE: invalid mode argument. * \c IGRAPH_ENOMEM: not enough memory. * - * Time complexity: O(d), - * d is the number - * of adjacent vertices to the queried vertex. + * Time complexity: O(d), d is the number of adjacent vertices to the queried + * vertex. * * \example examples/simple/igraph_neighbors.c */ -igraph_error_t igraph_neighbors(const igraph_t *graph, igraph_vector_int_t *neis, igraph_integer_t pnode, - igraph_neimode_t mode) { - if (!igraph_is_directed(graph) || mode == IGRAPH_ALL) { - return igraph_i_neighbors(graph, neis, pnode, mode, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE); - } else { - return igraph_i_neighbors(graph, neis, pnode, mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE); - } -} - -igraph_error_t igraph_i_neighbors(const igraph_t *graph, igraph_vector_int_t *neis, igraph_integer_t pnode, - igraph_neimode_t mode, igraph_loops_t loops, igraph_multiple_t multiple) { +igraph_error_t igraph_neighbors( + const igraph_t *graph, igraph_vector_int_t *neis, igraph_integer_t pnode, + igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple +) { #define DEDUPLICATE_IF_NEEDED(vertex, n) \ if (should_filter_duplicates) { \ if (vertex == pnode) { \ @@ -944,8 +951,11 @@ igraph_error_t igraph_i_neighbors(const igraph_t *graph, igraph_vector_int_t *ne } if (mode != IGRAPH_ALL && loops == IGRAPH_LOOPS_TWICE) { + /* IGRAPH_ERROR("For a directed graph (with directions not ignored), " "IGRAPH_LOOPS_TWICE does not make sense.", IGRAPH_EINVAL); + */ + loops = IGRAPH_LOOPS_ONCE; } /* Calculate needed space first & allocate it */ @@ -1144,13 +1154,25 @@ igraph_bool_t igraph_is_directed(const igraph_t *graph) { * Time complexity: O(1) if \p loops is \c true, and * O(d) otherwise, where d is the degree. */ -igraph_error_t igraph_degree_1(const igraph_t *graph, igraph_integer_t *deg, - igraph_integer_t vid, igraph_neimode_t mode, igraph_bool_t loops) { +igraph_error_t igraph_degree_1( + const igraph_t *graph, igraph_integer_t *deg, igraph_integer_t vid, + igraph_neimode_t mode, igraph_loops_t loops +) { + igraph_integer_t loop_counter; if (!igraph_is_directed(graph)) { mode = IGRAPH_ALL; } + if (loops != IGRAPH_NO_LOOPS && loops != IGRAPH_LOOPS_ONCE && + loops != IGRAPH_LOOPS_TWICE) { + IGRAPH_ERROR("Invalid loops argument.", IGRAPH_EINVAL); + } + + if (loops == IGRAPH_LOOPS_ONCE && (mode & IGRAPH_ALL) != IGRAPH_ALL) { + loops = IGRAPH_LOOPS_TWICE; + } + *deg = 0; if (mode & IGRAPH_OUT) { *deg += (VECTOR(graph->os)[vid + 1] - VECTOR(graph->os)[vid]); @@ -1158,23 +1180,32 @@ igraph_error_t igraph_degree_1(const igraph_t *graph, igraph_integer_t *deg, if (mode & IGRAPH_IN) { *deg += (VECTOR(graph->is)[vid + 1] - VECTOR(graph->is)[vid]); } - if (! loops) { + + if (loops != IGRAPH_LOOPS_TWICE) { /* When loops should not be counted, we remove their contribution from the * previously computed degree. */ + loop_counter = 0; if (mode & IGRAPH_OUT) { for (igraph_integer_t i = VECTOR(graph->os)[vid]; i < VECTOR(graph->os)[vid + 1]; i++) { if (VECTOR(graph->to)[ VECTOR(graph->oi)[i] ] == vid) { - *deg -= 1; + loop_counter++; } } } if (mode & IGRAPH_IN) { for (igraph_integer_t i = VECTOR(graph->is)[vid]; i < VECTOR(graph->is)[vid + 1]; i++) { if (VECTOR(graph->from)[ VECTOR(graph->ii)[i] ] == vid) { - *deg -= 1; + loop_counter++; } } } + + if (loops == IGRAPH_NO_LOOPS || mode != IGRAPH_ALL) { + *deg -= loop_counter; + } else { + /* loops == IGRAPH_LOOPS_ONCE && mode == IGRAPH_ALL */ + *deg -= loop_counter / 2; + } } return IGRAPH_SUCCESS; @@ -1205,8 +1236,10 @@ igraph_error_t igraph_degree_1(const igraph_t *graph, igraph_integer_t *deg, * \c IGRAPH_ALL, total degree (sum of the * in- and out-degree). * This parameter is ignored for undirected graphs. - * \param loops Boolean, gives whether the self-loops should be - * counted. + * \param loops Specifies how to treat loop edges when calculating the + * degree. \c IGRAPH_NO_LOOPS ignores loop edges; \c IGRAPH_LOOPS_ONCE + * counts each loop edge only once; \c IGRAPH_LOOPS_TWICE counts each + * loop edge twice in undirected graphs and once in directed graphs. * \return Error code: * \c IGRAPH_EINVVID: invalid vertex ID. * \c IGRAPH_EINVMODE: invalid mode argument. @@ -1223,9 +1256,10 @@ igraph_error_t igraph_degree_1(const igraph_t *graph, igraph_integer_t *deg, * * \example examples/simple/igraph_degree.c */ -igraph_error_t igraph_degree(const igraph_t *graph, igraph_vector_int_t *res, - const igraph_vs_t vids, - igraph_neimode_t mode, igraph_bool_t loops) { +igraph_error_t igraph_degree( + const igraph_t *graph, igraph_vector_int_t *res, const igraph_vs_t vids, + igraph_neimode_t mode, igraph_loops_t loops +) { igraph_integer_t nodes_to_calc; igraph_integer_t i, j; @@ -1238,15 +1272,21 @@ igraph_error_t igraph_degree(const igraph_t *graph, igraph_vector_int_t *res, IGRAPH_ERROR("Invalid mode for degree calculation.", IGRAPH_EINVMODE); } - if (! loops) { + if (loops == IGRAPH_NO_LOOPS || loops == IGRAPH_LOOPS_ONCE) { /* If the graph is known not to have loops, we can use the faster - * loops == true code path, which has O(1) complexity instead of of O(d). */ + * loops == IGRAPH_LOOPS_TWICE code path, which has O(1) complexity + * instead of of O(d). */ if (igraph_i_property_cache_has(graph, IGRAPH_PROP_HAS_LOOP) && !igraph_i_property_cache_get_bool(graph, IGRAPH_PROP_HAS_LOOP)) { - loops = true; + loops = IGRAPH_LOOPS_TWICE; } } + if (loops == IGRAPH_LOOPS_ONCE && mode != IGRAPH_ALL) { + /* We can use the faster loops == IGRAPH_LOOPS_TWICE path again */ + loops = IGRAPH_LOOPS_TWICE; + } + nodes_to_calc = IGRAPH_VIT_SIZE(vit); if (!igraph_is_directed(graph)) { mode = IGRAPH_ALL; @@ -1255,7 +1295,7 @@ igraph_error_t igraph_degree(const igraph_t *graph, igraph_vector_int_t *res, IGRAPH_CHECK(igraph_vector_int_resize(res, nodes_to_calc)); igraph_vector_int_null(res); - if (loops) { + if (loops == IGRAPH_LOOPS_TWICE) { if (mode & IGRAPH_OUT) { for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); @@ -1272,56 +1312,105 @@ igraph_error_t igraph_degree(const igraph_t *graph, igraph_vector_int_t *res, VECTOR(*res)[i] += (VECTOR(graph->is)[vid + 1] - VECTOR(graph->is)[vid]); } } - } else if (igraph_vs_is_all(&vids)) { /* no loops, calculating degree for all vertices */ - // When calculating degree for all vertices, iterating over edges is faster - igraph_integer_t no_of_edges = igraph_ecount(graph); + } else if (loops == IGRAPH_LOOPS_ONCE) { + IGRAPH_ASSERT((mode & IGRAPH_ALL) == IGRAPH_ALL); - if (mode & IGRAPH_OUT) { + /* We arbitrarily count loop edges in the (mode & IGRAPH_OUT) branch but + * not in the (mode & IGRAPH_IN) branch */ + + if (igraph_vs_is_all(&vids)) { + // When calculating degree for all vertices, iterating over edges is faster + igraph_integer_t no_of_edges = igraph_ecount(graph); + + /* mode & IGRAPH_OUT branch */ for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { igraph_integer_t from = IGRAPH_FROM(graph, edge); - if (from != IGRAPH_TO(graph, edge)) { - VECTOR(*res)[from]++; - } + VECTOR(*res)[from]++; } - } - if (mode & IGRAPH_IN) { + + /* mode & IGRAPH_IN branch */ for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { igraph_integer_t to = IGRAPH_TO(graph, edge); if (IGRAPH_FROM(graph, edge) != to) { VECTOR(*res)[to]++; } } - } - } else { /* no loops */ - if (mode & IGRAPH_OUT) { + } else { + /* mode & IGRAPH_OUT branch */ for (IGRAPH_VIT_RESET(vit), i = 0; - !IGRAPH_VIT_END(vit); - IGRAPH_VIT_NEXT(vit), i++) { + !IGRAPH_VIT_END(vit); + IGRAPH_VIT_NEXT(vit), i++) { igraph_integer_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->os)[vid + 1] - VECTOR(graph->os)[vid]); - for (j = VECTOR(graph->os)[vid]; - j < VECTOR(graph->os)[vid + 1]; j++) { - if (VECTOR(graph->to)[ VECTOR(graph->oi)[j] ] == vid) { - VECTOR(*res)[i] -= 1; - } - } } - } - if (mode & IGRAPH_IN) { + + /* mode & IGRAPH_IN branch */ for (IGRAPH_VIT_RESET(vit), i = 0; - !IGRAPH_VIT_END(vit); - IGRAPH_VIT_NEXT(vit), i++) { + !IGRAPH_VIT_END(vit); + IGRAPH_VIT_NEXT(vit), i++) { igraph_integer_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->is)[vid + 1] - VECTOR(graph->is)[vid]); for (j = VECTOR(graph->is)[vid]; - j < VECTOR(graph->is)[vid + 1]; j++) { + j < VECTOR(graph->is)[vid + 1]; j++) { if (VECTOR(graph->from)[ VECTOR(graph->ii)[j] ] == vid) { VECTOR(*res)[i] -= 1; } } } } - } /* loops */ + } else { + /* no loops should be counted */ + if (igraph_vs_is_all(&vids)) { + // When calculating degree for all vertices, iterating over edges is faster + igraph_integer_t no_of_edges = igraph_ecount(graph); + + if (mode & IGRAPH_OUT) { + for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { + igraph_integer_t from = IGRAPH_FROM(graph, edge); + if (from != IGRAPH_TO(graph, edge)) { + VECTOR(*res)[from]++; + } + } + } + if (mode & IGRAPH_IN) { + for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { + igraph_integer_t to = IGRAPH_TO(graph, edge); + if (IGRAPH_FROM(graph, edge) != to) { + VECTOR(*res)[to]++; + } + } + } + } else { + if (mode & IGRAPH_OUT) { + for (IGRAPH_VIT_RESET(vit), i = 0; + !IGRAPH_VIT_END(vit); + IGRAPH_VIT_NEXT(vit), i++) { + igraph_integer_t vid = IGRAPH_VIT_GET(vit); + VECTOR(*res)[i] += (VECTOR(graph->os)[vid + 1] - VECTOR(graph->os)[vid]); + for (j = VECTOR(graph->os)[vid]; + j < VECTOR(graph->os)[vid + 1]; j++) { + if (VECTOR(graph->to)[ VECTOR(graph->oi)[j] ] == vid) { + VECTOR(*res)[i] -= 1; + } + } + } + } + if (mode & IGRAPH_IN) { + for (IGRAPH_VIT_RESET(vit), i = 0; + !IGRAPH_VIT_END(vit); + IGRAPH_VIT_NEXT(vit), i++) { + igraph_integer_t vid = IGRAPH_VIT_GET(vit); + VECTOR(*res)[i] += (VECTOR(graph->is)[vid + 1] - VECTOR(graph->is)[vid]); + for (j = VECTOR(graph->is)[vid]; + j < VECTOR(graph->is)[vid + 1]; j++) { + if (VECTOR(graph->from)[ VECTOR(graph->ii)[j] ] == vid) { + VECTOR(*res)[i] -= 1; + } + } + } + } + } + } igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(1); @@ -1422,8 +1511,6 @@ igraph_error_t igraph_degree(const igraph_t *graph, igraph_vector_int_t *res, * d2 is the minimum of the out-degree of \c to and the in-degree of \c from. * * \example examples/simple/igraph_get_eid.c - * - * Added in version 0.2. */ igraph_error_t igraph_get_eid(const igraph_t *graph, igraph_integer_t *eid, @@ -1454,7 +1541,7 @@ igraph_error_t igraph_get_eid(const igraph_t *graph, igraph_integer_t *eid, if (*eid < 0) { if (error) { - IGRAPH_ERROR("Cannot get edge ID, no such edge", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot get edge ID, no such edge.", IGRAPH_EINVAL); } } @@ -1519,12 +1606,12 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, } if (n % 2 != 0) { - IGRAPH_ERROR("Cannot get edge IDs, invalid length of edge IDs", + IGRAPH_ERROR("Cannot get edge IDs, invalid length of vertex pair vector.", IGRAPH_EINVAL); } if (!igraph_vector_int_isininterval(pairs, 0, no_of_nodes - 1)) { - IGRAPH_ERROR("Cannot get edge IDs, invalid vertex ID", IGRAPH_EINVVID); + IGRAPH_ERROR("Cannot get edge IDs, invalid vertex ID.", IGRAPH_EINVVID); } IGRAPH_CHECK(igraph_vector_int_resize(eids, n / 2)); @@ -1542,7 +1629,7 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, VECTOR(*eids)[i] = eid; if (eid < 0 && error) { - IGRAPH_ERROR("Cannot get edge ID, no such edge", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot get edge ID, no such edge.", IGRAPH_EINVAL); } } } else { @@ -1554,7 +1641,7 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, FIND_UNDIRECTED_EDGE(graph, from, to, &eid); VECTOR(*eids)[i] = eid; if (eid < 0 && error) { - IGRAPH_ERROR("Cannot get edge ID, no such edge", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot get edge ID, no such edge.", IGRAPH_EINVAL); } } } @@ -1626,11 +1713,11 @@ igraph_error_t igraph_get_all_eids_between( igraph_integer_t no_of_nodes = igraph_vcount(graph); if (source < 0 || source >= no_of_nodes) { - IGRAPH_ERROR("Cannot get edge IDs, invalid source vertex ID", IGRAPH_EINVVID); + IGRAPH_ERROR("Cannot get edge IDs, invalid source vertex ID.", IGRAPH_EINVVID); } if (target < 0 || target >= no_of_nodes) { - IGRAPH_ERROR("Cannot get edge IDs, invalid target vertex ID", IGRAPH_EINVVID); + IGRAPH_ERROR("Cannot get edge IDs, invalid target vertex ID.", IGRAPH_EINVVID); } igraph_vector_int_clear(eids); @@ -1658,39 +1745,38 @@ igraph_error_t igraph_get_all_eids_between( * \brief Gives the incident edges of a vertex. * * \param graph The graph object. - * \param eids An initialized vector. It will be resized - * to hold the result. + * \param eids An initialized vector. It will be resized to hold the result. * \param pnode A vertex ID. * \param mode Specifies what kind of edges to include for directed - * graphs. \c IGRAPH_OUT means only outgoing edges, \c IGRAPH_IN only - * incoming edges, \c IGRAPH_ALL both. This parameter is ignored for - * undirected graphs. - * \return Error code. \c IGRAPH_EINVVID: invalid \p pnode argument, - * \c IGRAPH_EINVMODE: invalid \p mode argument. - * - * Added in version 0.2. + * graphs. \c IGRAPH_OUT means only outgoing edges, \c IGRAPH_IN means + * only incoming edges, \c IGRAPH_ALL means both. This parameter is + * ignored for undirected graphs. + * \param loops Specifies how to treat loop edges. \c IGRAPH_NO_LOOPS + * removes loop edges from the result. \c IGRAPH_LOOPS_ONCE + * makes each loop edge appear only once in the result. + * \c IGRAPH_LOOPS_TWICE makes loop edges appear \em twice in the + * result if the graph is undirected or \p mode is set to \c IGRAPH_ALL + * (and once otherwise as returning them twice does not make sense for + * directed graphs). + * \return Error code: + * \c IGRAPH_EINVVID: invalid vertex ID. + * \c IGRAPH_EINVMODE: invalid mode argument. + * \c IGRAPH_ENOMEM: not enough memory. * * Time complexity: O(d), the number of incident edges to \p pnode. */ -igraph_error_t igraph_incident(const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t pnode, - igraph_neimode_t mode) { - if (!igraph_is_directed(graph) || mode == IGRAPH_ALL) { - return igraph_i_incident(graph, eids, pnode, mode, IGRAPH_LOOPS_TWICE); - } else { - return igraph_i_incident(graph, eids, pnode, mode, IGRAPH_LOOPS_ONCE); - } -} - -igraph_error_t igraph_i_incident(const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t pnode, - igraph_neimode_t mode, igraph_loops_t loops) { +igraph_error_t igraph_incident( + const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t pnode, + igraph_neimode_t mode, igraph_loops_t loops +) { igraph_integer_t length = 0, idx = 0; igraph_integer_t i, j; igraph_integer_t node = pnode; igraph_bool_t directed = igraph_is_directed(graph); if (node < 0 || node > igraph_vcount(graph) - 1) { - IGRAPH_ERROR("Given vertex is not in the graph.", IGRAPH_EINVVID); + IGRAPH_ERRORF("Vertex %" IGRAPH_PRId " is not in the graph.", IGRAPH_EINVVID, node); } if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { @@ -1702,8 +1788,11 @@ igraph_error_t igraph_i_incident(const igraph_t *graph, igraph_vector_int_t *eid } if (mode != IGRAPH_ALL && loops == IGRAPH_LOOPS_TWICE) { + /* IGRAPH_ERROR("For a directed graph (with directions not ignored), " - "IGRAPH_LOOPS_TWICE does not make sense.\n", IGRAPH_EINVAL); + "IGRAPH_LOOPS_TWICE does not make sense.", IGRAPH_EINVAL); + */ + loops = IGRAPH_LOOPS_ONCE; } /* Calculate needed space first & allocate it */ @@ -1814,7 +1903,6 @@ igraph_error_t igraph_i_incident(const igraph_t *graph, igraph_vector_int_t *eid } IGRAPH_CHECK(igraph_vector_int_resize(eids, length)); return IGRAPH_SUCCESS; -#undef DEDUPLICATE_IF_NEEDED } diff --git a/src/vendor/cigraph/src/graph/visitors.c b/src/vendor/cigraph/src/graph/visitors.c index f373c09932b..93d45403db1 100644 --- a/src/vendor/cigraph/src/graph/visitors.c +++ b/src/vendor/cigraph/src/graph/visitors.c @@ -384,8 +384,9 @@ igraph_error_t igraph_bfs_simple( while (!igraph_dqueue_int_empty(&q)) { igraph_integer_t actvect = igraph_dqueue_int_pop(&q); igraph_integer_t actdist = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actvect, - mode)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, actvect, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); igraph_integer_t nei_count = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < nei_count; i++) { const igraph_integer_t neighbor = VECTOR(neis)[i]; diff --git a/src/vendor/cigraph/src/hrg/hrg.cc b/src/vendor/cigraph/src/hrg/hrg.cc index 374bde6977c..b4d57936d15 100644 --- a/src/vendor/cigraph/src/hrg/hrg.cc +++ b/src/vendor/cigraph/src/hrg/hrg.cc @@ -413,8 +413,6 @@ igraph_error_t igraph_hrg_fit(const igraph_t *graph, const igraph_integer_t no_of_nodes = igraph_vcount(graph); - RNG_BEGIN(); - dendro d; // If we want to start from HRG @@ -439,8 +437,6 @@ igraph_error_t igraph_hrg_fit(const igraph_t *graph, MCMCEquilibrium_Find(d, hrg); } - RNG_END(); - return IGRAPH_SUCCESS; IGRAPH_HANDLE_EXCEPTIONS_END @@ -465,15 +461,11 @@ igraph_error_t igraph_hrg_sample(const igraph_hrg_t *hrg, igraph_t *sample) { // TODO: error handling - RNG_BEGIN(); - d.clearDendrograph(); d.importDendrogramStructure(hrg); d.makeRandomGraph(); IGRAPH_CHECK(d.recordGraphStructure(sample)); - RNG_END(); - return IGRAPH_SUCCESS; IGRAPH_HANDLE_EXCEPTIONS_END } @@ -512,8 +504,6 @@ igraph_error_t igraph_hrg_sample_many( return IGRAPH_SUCCESS; } - RNG_BEGIN(); - d.clearDendrograph(); d.importDendrogramStructure(hrg); while (num_samples-- > 0) { @@ -524,8 +514,6 @@ igraph_error_t igraph_hrg_sample_many( IGRAPH_FINALLY_CLEAN(1); } - RNG_END(); - return IGRAPH_SUCCESS; IGRAPH_HANDLE_EXCEPTIONS_END } @@ -636,12 +624,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 +638,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 +661,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 @@ -720,8 +709,6 @@ igraph_error_t igraph_hrg_consensus(const igraph_t *graph, IGRAPH_ERROR("`hrg' must be given if `start' is true.", IGRAPH_EINVAL); } - RNG_BEGIN(); - dendro d; if (start) { @@ -740,8 +727,6 @@ igraph_error_t igraph_hrg_consensus(const igraph_t *graph, d.recordConsensusTree(parents, weights); - RNG_END(); - return IGRAPH_SUCCESS; IGRAPH_HANDLE_EXCEPTIONS_END @@ -875,8 +860,6 @@ igraph_error_t igraph_hrg_predict(const igraph_t *graph, IGRAPH_ERROR("`hrg' must be given when `start' is true", IGRAPH_EINVAL); } - RNG_BEGIN(); - dendro d; std::unique_ptr sg = igraph_i_hrg_getsimplegraph(graph, d, num_bins); @@ -903,8 +886,6 @@ igraph_error_t igraph_hrg_predict(const igraph_t *graph, rankCandidatesByProbability(*sg, d, br_list.get(), mk); IGRAPH_CHECK(recordPredictions(br_list.get(), edges, prob, mk)); - RNG_END(); - return IGRAPH_SUCCESS; IGRAPH_HANDLE_EXCEPTIONS_END @@ -974,7 +955,7 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_is_simple(graph, &simple)); + IGRAPH_CHECK(igraph_is_simple(graph, &simple, IGRAPH_DIRECTED)); if (!simple) { IGRAPH_ERROR("HRG graph must be a simple graph.", IGRAPH_EINVAL); } @@ -1050,7 +1031,7 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, if (ri >= 0) { continue; } - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); VECTOR(hrg->left )[-ri - 1] = VECTOR(idx)[ VECTOR(neis)[0] ]; VECTOR(hrg->right)[-ri - 1] = VECTOR(idx)[ VECTOR(neis)[1] ]; VECTOR(hrg->prob )[-ri - 1] = VECTOR(*prob)[i]; diff --git a/src/vendor/cigraph/src/internal/glpk_support.c b/src/vendor/cigraph/src/internal/glpk_support.c index 384390e737d..10d98eb321c 100644 --- a/src/vendor/cigraph/src/internal/glpk_support.c +++ b/src/vendor/cigraph/src/internal/glpk_support.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2011-2012 Gabor Csardi @@ -49,7 +47,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 +88,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); } } @@ -128,9 +126,8 @@ igraph_error_t igraph_i_glpk_check(int retval, const char* message) { } /* handle errors */ -#define HANDLE_CODE(c) case c: code = #c; ret = IGRAPH_##c; break; -#define HANDLE_CODE2(c) case c: code = #c; ret = IGRAPH_FAILURE; break; -#define HANDLE_CODE3(c) case c: code = #c; ret = IGRAPH_INTERRUPTED; break; +#define HANDLE_CODE(c) case c: code = #c; ret = IGRAPH_FAILURE; break; +#define HANDLE_CODE2(c) case c: code = #c; ret = IGRAPH_INTERRUPTED; break; switch (retval) { HANDLE_CODE(GLP_EBOUND); HANDLE_CODE(GLP_EROOT); @@ -140,14 +137,14 @@ igraph_error_t igraph_i_glpk_check(int retval, const char* message) { HANDLE_CODE(GLP_EMIPGAP); HANDLE_CODE(GLP_ETMLIM); - HANDLE_CODE3(GLP_ESTOP); + HANDLE_CODE2(GLP_ESTOP); - HANDLE_CODE2(GLP_EBADB); - HANDLE_CODE2(GLP_ESING); - HANDLE_CODE2(GLP_ECOND); - HANDLE_CODE2(GLP_EOBJLL); - HANDLE_CODE2(GLP_EOBJUL); - HANDLE_CODE2(GLP_EITLIM); + HANDLE_CODE(GLP_EBADB); + HANDLE_CODE(GLP_ESING); + HANDLE_CODE(GLP_ECOND); + HANDLE_CODE(GLP_EOBJLL); + HANDLE_CODE(GLP_EOBJUL); + HANDLE_CODE(GLP_EITLIM); default: IGRAPH_ERROR("Unknown GLPK error.", IGRAPH_FAILURE); diff --git a/src/vendor/cigraph/src/internal/glpk_support.h b/src/vendor/cigraph/src/internal/glpk_support.h index 973b6dad61e..701bf737f5e 100644 --- a/src/vendor/cigraph/src/internal/glpk_support.h +++ b/src/vendor/cigraph/src/internal/glpk_support.h @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -40,9 +38,9 @@ #include #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS -typedef struct igraph_i_glpk_error_info_s { +typedef struct { jmp_buf jmp; /* used for bailing when there is a GLPK error */ bool is_interrupted; /* Boolean; true if there was an interruption */ bool is_error; /* Boolean; true if the error hook was called */ @@ -131,18 +129,18 @@ void igraph_i_glp_delete_prob(glp_prob *p); igraph_i_glpk_error_info.msg_ptr--; \ } \ *igraph_i_glpk_error_info.msg_ptr = '\0'; \ - igraph_error(igraph_i_glpk_error_info.msg, IGRAPH_FILE_BASENAME, __LINE__, IGRAPH_EGLP); \ + igraph_error(igraph_i_glpk_error_info.msg, IGRAPH_FILE_BASENAME, __LINE__, IGRAPH_FAILURE); \ } else if (igraph_i_glpk_error_info.is_error) { \ /* This branch can never be reached unless compiled with USING_R and using */ \ /* the hack to support pre-4.57 GLPK versions. See comments in glpk_support.c. */ \ - igraph_error("Error while running GLPK solver.", IGRAPH_FILE_BASENAME, __LINE__, IGRAPH_EGLP); \ + igraph_error("Error while running GLPK solver.", IGRAPH_FILE_BASENAME, __LINE__, IGRAPH_FAILURE); \ } \ - return IGRAPH_EGLP; \ + return IGRAPH_FAILURE; \ } \ } \ } while (0) -__END_DECLS +IGRAPH_END_C_DECLS #endif /* HAVE_GLPK */ diff --git a/src/vendor/cigraph/src/internal/gmp_internal.h b/src/vendor/cigraph/src/internal/gmp_internal.h index 5cc0b9910ad..25f77139d70 100644 --- a/src/vendor/cigraph/src/internal/gmp_internal.h +++ b/src/vendor/cigraph/src/internal/gmp_internal.h @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2020 The igraph development team diff --git a/src/vendor/cigraph/src/internal/hacks.c b/src/vendor/cigraph/src/internal/hacks.c index 09f42206b62..2b21b370919 100644 --- a/src/vendor/cigraph/src/internal/hacks.c +++ b/src/vendor/cigraph/src/internal/hacks.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/internal/hacks.h b/src/vendor/cigraph/src/internal/hacks.h index b38bfce873c..04e57c1402b 100644 --- a/src/vendor/cigraph/src/internal/hacks.h +++ b/src/vendor/cigraph/src/internal/hacks.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2003-2012 Gabor Csardi @@ -35,7 +34,7 @@ #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS #ifndef HAVE_STRDUP #define strdup igraph_i_strdup @@ -68,6 +67,6 @@ __BEGIN_DECLS */ #define IGRAPH_STATIC_ASSERT(condition) ((void)sizeof(char[1 - 2*!(condition)])) -__END_DECLS +IGRAPH_END_C_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/internal/zeroin.c b/src/vendor/cigraph/src/internal/zeroin.c deleted file mode 100644 index 89ade546255..00000000000 --- a/src/vendor/cigraph/src/internal/zeroin.c +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- mode: C -*- */ -/* - IGraph library. - Copyright (C) 2007-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -/* from GNU R's zeroin.c, minor modifications by Gabor Csardi */ - -/* from NETLIB c/brent.shar with max.iter, add'l info and convergence - details hacked in by Peter Dalgaard */ - -/************************************************************************* - * C math library - * function ZEROIN - obtain a function zero within the given range - * - * Input - * double zeroin(ax,bx,f,info,Tol,Maxit) - * double ax; Root will be seeked for within - * double bx; a range [ax,bx] - * double (*f)(double x, void *info); Name of the function whose zero - * will be seeked for - * void *info; Add'l info passed to f - * double *Tol; Acceptable tolerance for the root - * value. - * May be specified as 0.0 to cause - * the program to find the root as - * accurate as possible - * - * int *Maxit; Max. iterations - * - * - * Output - * Zeroin returns an estimate for the root with accuracy - * 4*EPSILON*abs(x) + tol - * *Tol returns estimated precision - * *Maxit returns actual # of iterations, or -1 if maxit was - * reached without convergence. - * - * Algorithm - * G.Forsythe, M.Malcolm, C.Moler, Computer methods for mathematical - * computations. M., Mir, 1980, p.180 of the Russian edition - * - * The function makes use of the bisection procedure combined with - * the linear or quadric inverse interpolation. - * At every step program operates on three abscissae - a, b, and c. - * b - the last and the best approximation to the root - * a - the last but one approximation - * c - the last but one or even earlier approximation than a that - * 1) |f(b)| <= |f(c)| - * 2) f(b) and f(c) have opposite signs, i.e. b and c confine - * the root - * At every step Zeroin selects one of the two new approximations, the - * former being obtained by the bisection procedure and the latter - * resulting in the interpolation (if a,b, and c are all different - * the quadric interpolation is utilized, otherwise the linear one). - * If the latter (i.e. obtained by the interpolation) point is - * reasonable (i.e. lies within the current interval [b,c] not being - * too close to the boundaries) it is accepted. The bisection result - * is used in the other case. Therefore, the range of uncertainty is - * ensured to be reduced at least by the factor 1.6 - * - ************************************************************************ - */ - -#include "igraph_nongraph.h" -#include "igraph_types.h" - -#include "core/interruption.h" - -#include -#include - -#define EPSILON DBL_EPSILON - -igraph_error_t igraph_zeroin( /* An estimate of the root */ - igraph_real_t *ax, /* Left border | of the range */ - igraph_real_t *bx, /* Right border| the root is seeked*/ - igraph_real_t (*f)(igraph_real_t x, void *info), /* Function under investigation */ - void *info, /* Add'l info passed on to f */ - igraph_real_t *Tol, /* Acceptable tolerance */ - int *Maxit, /* Max # of iterations */ - igraph_real_t *res) { /* Result is stored here */ - igraph_real_t a, b, c, /* Abscissae, descr. see above */ - fa, fb, fc; /* f(a), f(b), f(c) */ - igraph_real_t tol; - int maxit; - - a = *ax; b = *bx; fa = (*f)(a, info); fb = (*f)(b, info); - c = a; fc = fa; - maxit = *Maxit + 1; tol = * Tol; - - /* First test if we have found a root at an endpoint */ - if (fa == 0.0) { - *Tol = 0.0; - *Maxit = 0; - *res = a; - return IGRAPH_SUCCESS; - } - if (fb == 0.0) { - *Tol = 0.0; - *Maxit = 0; - *res = b; - return IGRAPH_SUCCESS; - } - - while (maxit--) { /* Main iteration loop */ - igraph_real_t prev_step = b - a; /* Distance from the last but one to the last approximation */ - igraph_real_t tol_act; /* Actual tolerance */ - igraph_real_t p; /* Interpolation step is calculated in the form p/q; */ - igraph_real_t q; /* division operations are delayed until the last moment */ - igraph_real_t new_step; /* Step at this iteration */ - - IGRAPH_ALLOW_INTERRUPTION(); - - if ( fabs(fc) < fabs(fb) ) { - /* Swap data for b to be the best approximation */ - a = b; b = c; c = a; - fa = fb; fb = fc; fc = fa; - } - tol_act = 2 * EPSILON * fabs(b) + tol / 2; - new_step = (c - b) / 2; - - if ( fabs(new_step) <= tol_act || fb == (igraph_real_t)0 ) { - *Maxit -= maxit; - *Tol = fabs(c - b); - *res = b; - return IGRAPH_SUCCESS; /* Acceptable approx. is found */ - } - - /* Decide if the interpolation can be tried */ - if ( fabs(prev_step) >= tol_act /* If prev_step was large enough*/ - && fabs(fa) > fabs(fb) ) { - /* and was in true direction, - * Interpolation may be tried */ - register igraph_real_t t1, cb, t2; - cb = c - b; - if ( a == c ) { /* If we have only two distinct */ - /* points linear interpolation */ - t1 = fb / fa; /* can only be applied */ - p = cb * t1; - q = 1.0 - t1; - } else { /* Quadric inverse interpolation*/ - - q = fa / fc; t1 = fb / fc; t2 = fb / fa; - p = t2 * ( cb * q * (q - t1) - (b - a) * (t1 - 1.0) ); - q = (q - 1.0) * (t1 - 1.0) * (t2 - 1.0); - } - if ( p > (igraph_real_t)0 ) { /* p was calculated with the */ - q = -q; /* opposite sign; make p positive */ - } else { /* and assign possible minus to */ - p = -p; /* q */ - } - - if ( p < (0.75 * cb * q - fabs(tol_act * q) / 2) /* If b+p/q falls in [b,c]*/ - && p < fabs(prev_step * q / 2) ) { /* and isn't too large */ - new_step = p / q; - } /* it is accepted - * If p/q is too large then the - * bisection procedure can - * reduce [b,c] range to more - * extent */ - } - - if ( fabs(new_step) < tol_act) { /* Adjust the step to be not less*/ - if ( new_step > (igraph_real_t)0 ) { /* than tolerance */ - new_step = tol_act; - } else { - new_step = -tol_act; - } - } - a = b; fa = fb; /* Save the previous approx. */ - b += new_step; fb = (*f)(b, info); /* Do step to a new approxim. */ - if ( (fb > 0 && fc > 0) || (fb < 0 && fc < 0) ) { - /* Adjust c for it to have a sign opposite to that of b */ - c = a; fc = fa; - } - - } - /* failed! */ - *Tol = fabs(c - b); - *Maxit = -1; - *res = b; - return IGRAPH_DIVERGED; -} diff --git a/src/vendor/cigraph/src/io/dimacs.c b/src/vendor/cigraph/src/io/dimacs.c index 4de4f40ff21..5b4527da3f5 100644 --- a/src/vendor/cigraph/src/io/dimacs.c +++ b/src/vendor/cigraph/src/io/dimacs.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team @@ -39,24 +38,6 @@ #define IGRAPH_DIMACS_MAX_EDGE_COUNT INT32_MAX #endif -/** - * \function igraph_read_graph_dimacs - * \brief Read a graph in DIMACS format (deprecated alias). - * - * \deprecated-by igraph_read_graph_dimacs_flow 0.10.0 - */ -igraph_error_t igraph_read_graph_dimacs(igraph_t *graph, FILE *instream, - igraph_strvector_t *problem, - igraph_vector_int_t *label, - igraph_integer_t *source, - igraph_integer_t *target, - igraph_vector_t *capacity, - igraph_bool_t directed) { - return igraph_read_graph_dimacs_flow( - graph, instream, problem, label, source, target, capacity, directed - ); -} - #define EXPECT(actual, expected) \ do { \ if ((actual) != (expected)) { \ @@ -305,18 +286,6 @@ igraph_error_t igraph_read_graph_dimacs_flow( return IGRAPH_SUCCESS; } -/** - * \function igraph_write_graph_dimacs - * \brief Write a graph in DIMACS format (deprecated alias). - * - * \deprecated-by igraph_write_graph_dimacs_flow 0.10.0 - */ -igraph_error_t igraph_write_graph_dimacs(const igraph_t *graph, FILE *outstream, - igraph_integer_t source, igraph_integer_t target, - const igraph_vector_t *capacity) { - return igraph_write_graph_dimacs_flow(graph, outstream, source, target, capacity); -} - /** * \function igraph_write_graph_dimacs_flow * \brief Write a graph in DIMACS format. diff --git a/src/vendor/cigraph/src/io/dl-lexer.l b/src/vendor/cigraph/src/io/dl-lexer.l index e4a96c4b993..e34d8e29db5 100644 --- a/src/vendor/cigraph/src/io/dl-lexer.l +++ b/src/vendor/cigraph/src/io/dl-lexer.l @@ -44,12 +44,11 @@ */ -#include -#include - #include "io/dl-header.h" #include "io/parsers/dl-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_dl_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in DL parser: " # msg) diff --git a/src/vendor/cigraph/src/io/dl.c b/src/vendor/cigraph/src/io/dl.c index 6b8435c8a0c..c7b08aab4f0 100644 --- a/src/vendor/cigraph/src/io/dl.c +++ b/src/vendor/cigraph/src/io/dl.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team @@ -70,9 +69,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 +153,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 +184,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/dot.c b/src/vendor/cigraph/src/io/dot.c index 88b8c5f732b..c6b56a2b396 100644 --- a/src/vendor/cigraph/src/io/dot.c +++ b/src/vendor/cigraph/src/io/dot.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team diff --git a/src/vendor/cigraph/src/io/edgelist.c b/src/vendor/cigraph/src/io/edgelist.c index ccd3b09a7b2..f763ff53691 100644 --- a/src/vendor/cigraph/src/io/edgelist.c +++ b/src/vendor/cigraph/src/io/edgelist.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team diff --git a/src/vendor/cigraph/src/io/gml-lexer.l b/src/vendor/cigraph/src/io/gml-lexer.l index 31f5d58a0ad..375dc6fbca0 100644 --- a/src/vendor/cigraph/src/io/gml-lexer.l +++ b/src/vendor/cigraph/src/io/gml-lexer.l @@ -42,11 +42,11 @@ */ -#include - #include "io/gml-header.h" #include "io/parsers/gml-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_gml_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in GML parser: " # msg) diff --git a/src/vendor/cigraph/src/io/gml-tree.h b/src/vendor/cigraph/src/io/gml-tree.h index 26e9308f1ff..93731308f90 100644 --- a/src/vendor/cigraph/src/io/gml-tree.h +++ b/src/vendor/cigraph/src/io/gml-tree.h @@ -26,7 +26,7 @@ #include "igraph_vector.h" #include "igraph_vector_ptr.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef enum { IGRAPH_I_GML_TREE_TREE = 0, IGRAPH_I_GML_TREE_INTEGER, @@ -82,6 +82,6 @@ IGRAPH_FUNCATTR_PURE const char *igraph_gml_tree_get_string(const igraph_gml_tre IGRAPH_FUNCATTR_PURE igraph_gml_tree_t *igraph_gml_tree_get_tree(const igraph_gml_tree_t *t, igraph_integer_t pos); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/io/gml.c b/src/vendor/cigraph/src/io/gml.c index f5ddc1c1027..bad40a80208 100644 --- a/src/vendor/cigraph/src/io/gml.c +++ b/src/vendor/cigraph/src/io/gml.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2022 The igraph development team @@ -162,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); @@ -263,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. */ @@ -290,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)); } } } @@ -334,34 +316,23 @@ 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); + igraph_attribute_record_t *atrec = igraph_attribute_record_list_get_ptr(attrs, i); + + /* We 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 resize 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)); } else { - /* Must never reach here. */ - IGRAPH_FATAL("Unexpected attribute type."); + IGRAPH_WARNINGF("Composite %s attribute '%s' ignored in GML file.", kind, atrec->name); } } return IGRAPH_SUCCESS; @@ -426,10 +397,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 */ @@ -493,10 +462,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); @@ -687,13 +658,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; @@ -725,13 +695,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; @@ -770,13 +739,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; @@ -794,10 +762,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); @@ -812,9 +780,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/graphdb.c b/src/vendor/cigraph/src/io/graphdb.c index b5dc0b262e0..5c67af7de0e 100644 --- a/src/vendor/cigraph/src/io/graphdb.c +++ b/src/vendor/cigraph/src/io/graphdb.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team diff --git a/src/vendor/cigraph/src/io/graphml.c b/src/vendor/cigraph/src/io/graphml.c index 28b3c435252..1b42b626637 100644 --- a/src/vendor/cigraph/src/io/graphml.c +++ b/src/vendor/cigraph/src/io/graphml.c @@ -88,17 +88,13 @@ static xmlEntity blankEntity = { } 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 { @@ -210,34 +206,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) { @@ -409,34 +387,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]; @@ -444,131 +413,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)); @@ -577,9 +483,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]) /* for use in strnxxx()-style functions that take a char * and a length */ #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,52 +591,30 @@ 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."); - if (rec->id) { - /* may happen if the 'id' attribute is provided multiple times */ - xmlFree((void *) rec->id); - rec->id = NULL; - } - rec->id = fromXmlChar(xmlStr); - xmlStr = NULL; + safely_free_optional_string(&rec->id); + 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."); - if (rec->record.name) { - /* may happen if the 'attr.name' attribute is provided multiple times */ - xmlFree((void *) rec->record.name); - rec->record.name = NULL; - } - 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)); @@ -749,9 +664,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 */ @@ -760,9 +677,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. */ @@ -780,7 +698,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; } } @@ -794,12 +712,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 ); } } @@ -813,42 +731,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; } @@ -876,9 +764,7 @@ static igraph_error_t igraph_i_graphml_attribute_data_setup( state->data_key = NULL; } state->data_key = xmlStrndup(XML_ATTR_VALUE(it)); - if (state->data_key == 0) { - return IGRAPH_ENOMEM; /* LCOV_EXCL_LINE */ - } + IGRAPH_CHECK_OOM(state->data_key, "Insufficient memory to read GraphML file."); igraph_vector_char_clear(&state->data_char); state->data_type = type; } else { @@ -892,16 +778,17 @@ static igraph_error_t igraph_i_graphml_attribute_data_setup( static igraph_error_t igraph_i_graphml_append_to_data_char( struct igraph_i_graphml_parser_state *state, const xmlChar *data, int len ) { + igraph_vector_char_t data_vec; + if (!state->successful) { return IGRAPH_SUCCESS; } - /* vector_push_back() minimizes reallocations by doubling the size of the buffer, - * while vector_append() would only allocate as much additional memory as needed. */ IGRAPH_STATIC_ASSERT(sizeof(char) == sizeof(xmlChar)); - for (int i=0; i < len; i++) { - IGRAPH_CHECK(igraph_vector_char_push_back(&state->data_char, data[i])); - } + IGRAPH_CHECK(igraph_vector_char_append( + &state->data_char, + igraph_vector_char_view(&data_vec, (char *) data, len) + )); return IGRAPH_SUCCESS; } @@ -955,66 +842,44 @@ 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; - } - } - /* Add null terminator */ IGRAPH_CHECK(igraph_vector_char_push_back(&state->data_char, '\x00')); + boolvec = rec->value.as_vector_bool; IGRAPH_CHECK(igraph_i_graphml_parse_boolean( - VECTOR(state->data_char), VECTOR(*boolvec) + id, graphmlrec->default_value.as_boolean + VECTOR(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; - } - } - /* Add null terminator */ IGRAPH_CHECK(igraph_vector_char_push_back(&state->data_char, '\x00')); + vec = rec->value.as_vector; IGRAPH_CHECK(igraph_i_graphml_parse_numeric( - VECTOR(state->data_char), VECTOR(*vec) + id, - graphmlrec->default_value.as_numeric + VECTOR(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)); - } - } + /* Ensure that the vector ends with a null terminator */ + strvec = rec->value.as_strvector; if (igraph_vector_char_size(&state->data_char) > 0) { - /* Ensure that the vector ends with a null terminator */ IGRAPH_CHECK(igraph_vector_char_push_back(&state->data_char, '\x00')); strvalue = VECTOR(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: @@ -1032,8 +897,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); @@ -1041,32 +908,25 @@ 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: /* Add null terminator */ IGRAPH_CHECK(igraph_vector_char_push_back(&state->data_char, '\x00')); - IGRAPH_CHECK(igraph_i_graphml_parse_boolean( - VECTOR(state->data_char), &graphmlrec->default_value.as_boolean, 0 - )); + IGRAPH_CHECK(igraph_i_graphml_parse_boolean(VECTOR(state->data_char), &default_bool, false)); + IGRAPH_CHECK(igraph_attribute_record_set_default_boolean(rec, default_bool)); break; case IGRAPH_ATTRIBUTE_NUMERIC: /* Add null terminator */ IGRAPH_CHECK(igraph_vector_char_push_back(&state->data_char, '\x00')); - IGRAPH_CHECK(igraph_i_graphml_parse_numeric( - VECTOR(state->data_char), &graphmlrec->default_value.as_numeric, IGRAPH_NAN - )); + IGRAPH_CHECK(igraph_i_graphml_parse_numeric(VECTOR(state->data_char), &default_num, IGRAPH_NAN)); + IGRAPH_CHECK(igraph_attribute_record_set_default_numeric(rec, default_num)); break; case IGRAPH_ATTRIBUTE_STRING: /* Add null terminator */ IGRAPH_CHECK(igraph_vector_char_push_back(&state->data_char, '\x00')); - str = strdup(VECTOR(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, VECTOR(state->data_char))); break; case IGRAPH_ATTRIBUTE_UNSPECIFIED: break; diff --git a/src/vendor/cigraph/src/io/leda.c b/src/vendor/cigraph/src/io/leda.c index cf742cdde62..48a2f6c5535 100644 --- a/src/vendor/cigraph/src/io/leda.c +++ b/src/vendor/cigraph/src/io/leda.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team @@ -84,7 +83,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 +103,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-lexer.l b/src/vendor/cigraph/src/io/lgl-lexer.l index 0c9036010e8..64802df0e93 100644 --- a/src/vendor/cigraph/src/io/lgl-lexer.l +++ b/src/vendor/cigraph/src/io/lgl-lexer.l @@ -44,11 +44,11 @@ */ -#include - #include "io/lgl-header.h" #include "io/parsers/lgl-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_lgl_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in LGL parser: " # msg) 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 3cba8c034bd..1c1a00d07db 100644 --- a/src/vendor/cigraph/src/io/lgl.c +++ b/src/vendor/cigraph/src/io/lgl.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team @@ -77,10 +76,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 +109,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 +159,32 @@ 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); + 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 = &ws; - VECTOR(weight)[0] = &weightrec; } /* Create graph */ @@ -189,11 +194,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 +285,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 +299,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-lexer.l b/src/vendor/cigraph/src/io/ncol-lexer.l index 1e554ff54f4..b668b48cc60 100644 --- a/src/vendor/cigraph/src/io/ncol-lexer.l +++ b/src/vendor/cigraph/src/io/ncol-lexer.l @@ -44,11 +44,11 @@ */ -#include - #include "io/ncol-header.h" #include "io/parsers/ncol-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_ncol_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in NCOL parser: " # msg) 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 d5f739a77dc..be600851c57 100644 --- a/src/vendor/cigraph/src/io/ncol.c +++ b/src/vendor/cigraph/src/io/ncol.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team @@ -81,10 +80,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 +114,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 +185,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 +226,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 +313,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 +328,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 63308777adf..0dc37976d6e 100644 --- a/src/vendor/cigraph/src/io/pajek-header.h +++ b/src/vendor/cigraph/src/io/pajek-header.h @@ -20,10 +20,10 @@ */ +#include "igraph_attributes.h" #include "igraph_bitset.h" #include "igraph_error.h" #include "igraph_vector.h" -#include "igraph_vector_ptr.h" #include "core/trie.h" @@ -55,9 +55,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-lexer.l b/src/vendor/cigraph/src/io/pajek-lexer.l index 3743d08c7dc..fdb4ac82a2a 100644 --- a/src/vendor/cigraph/src/io/pajek-lexer.l +++ b/src/vendor/cigraph/src/io/pajek-lexer.l @@ -44,11 +44,11 @@ */ -#include - #include "io/pajek-header.h" #include "io/parsers/pajek-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_pajek_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in Pajek parser: " # msg) diff --git a/src/vendor/cigraph/src/io/pajek-parser.y b/src/vendor/cigraph/src/io/pajek-parser.y index da13026d141..4933acd1f56 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 @@ -265,7 +271,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)); }; @@ -565,49 +570,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)); } @@ -692,7 +675,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); } @@ -704,7 +689,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); } @@ -715,7 +702,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); } @@ -726,7 +715,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); } @@ -734,10 +725,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) { @@ -752,29 +743,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; } @@ -814,7 +789,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; } @@ -856,3 +831,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 d229a370020..be554f95337 100644 --- a/src/vendor/cigraph/src/io/pajek.c +++ b/src/vendor/cigraph/src/io/pajek.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team @@ -48,32 +47,6 @@ void igraph_pajek_yylex_destroy_wrapper (void *scanner ) { (void) igraph_pajek_yylex_destroy(scanner); } -static void 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 @@ static void 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,22 +144,22 @@ 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_bitset_t seen; /* used to mark already seen vertex IDs */ IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_TRIE_INIT_FINALLY(&vattrnames, 1); - IGRAPH_CHECK(igraph_vector_ptr_init(&vattrs, 0)); - IGRAPH_FINALLY(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(pajek_destroy_attr_vector, &eattrs); + IGRAPH_CHECK(igraph_attribute_record_list_init(&eattrs, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &eattrs); IGRAPH_BITSET_INIT_FINALLY(&seen, 0); @@ -243,33 +215,10 @@ igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream) { IGRAPH_FINALLY_CLEAN(2); /* 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 */ @@ -279,9 +228,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); - pajek_destroy_attr_vector(&eattrs); + igraph_attribute_record_list_destroy(&eattrs); igraph_trie_destroy(&eattrnames); - pajek_destroy_attr_vector(&vattrs); + igraph_attribute_record_list_destroy(&vattrs); igraph_trie_destroy(&vattrnames); IGRAPH_FINALLY_CLEAN(6); /* +1 for 'graph' */ @@ -452,7 +401,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", @@ -534,7 +483,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, @@ -585,7 +534,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 { @@ -595,7 +544,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)); @@ -605,7 +554,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)); @@ -707,7 +656,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; @@ -716,7 +665,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)); @@ -726,7 +675,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/io/parse_utils.c b/src/vendor/cigraph/src/io/parse_utils.c index 2b0e0d73da6..9bd24c0a79a 100644 --- a/src/vendor/cigraph/src/io/parse_utils.c +++ b/src/vendor/cigraph/src/io/parse_utils.c @@ -296,8 +296,6 @@ struct igraph_safelocale_s { * \function igraph_enter_safelocale * \brief Temporarily set the C locale. * - * \experimental - * * igraph's foreign format readers and writers require a locale that uses a * decimal point instead of a decimal comma. This is a convenience function * that temporarily sets the C locale so that readers and writers would work @@ -354,8 +352,6 @@ igraph_error_t igraph_enter_safelocale(igraph_safelocale_t *loc) { * \function igraph_exit_safelocale * \brief Temporarily set the C locale. * - * \experimental - * * Restores a locale saved by \ref igraph_enter_safelocale() and deallocates * all associated data. This function \em must be paired with a call to * \ref igraph_enter_safelocale(). diff --git a/src/vendor/cigraph/src/isomorphism/bliss.cc b/src/vendor/cigraph/src/isomorphism/bliss.cc index fedc3c3c421..541a5b17947 100644 --- a/src/vendor/cigraph/src/isomorphism/bliss.cc +++ b/src/vendor/cigraph/src/isomorphism/bliss.cc @@ -19,7 +19,7 @@ #include "bliss/graph.hh" -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "igraph_conversion.h" #include "igraph_interface.h" #include "igraph_interrupt.h" @@ -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,49 @@ 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 igraph_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 + ); +} + +static igraph_error_t igraph_i_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 +); + +/** + * \function igraph_canonical_permutation_bliss * \brief Canonical permutation using Bliss. * * This function computes the vertex permutation which transforms @@ -258,8 +302,27 @@ 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_vector_int_t inv_permutation; + + IGRAPH_VECTOR_INT_INIT_FINALLY(&inv_permutation, igraph_vcount(graph)); + IGRAPH_CHECK(igraph_i_canonical_permutation_bliss(graph, colors, &inv_permutation, sh, info)); + IGRAPH_CHECK(igraph_invert_permutation(&inv_permutation, labeling)); + igraph_vector_int_destroy(&inv_permutation); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + +static igraph_error_t igraph_i_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 +353,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. * - * \deprecated-by igraph_count_automorphisms 0.10.5 + * 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 . + * + * 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 +420,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 +449,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 +504,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 +566,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 +654,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_i_canonical_permutation_bliss(graph1, colors1, &perm1, sh, info1)); + IGRAPH_CHECK(igraph_i_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/isoclasses.c b/src/vendor/cigraph/src/isomorphism/isoclasses.c index a15db7b20c3..e75a418f2f9 100644 --- a/src/vendor/cigraph/src/isomorphism/isoclasses.c +++ b/src/vendor/cigraph/src/isomorphism/isoclasses.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2021 The igraph development team @@ -19,7 +18,7 @@ 02110-1301 USA */ -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "igraph_constructors.h" #include "igraph_interface.h" @@ -2696,7 +2695,9 @@ igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, const igraph_vect for (i = 0; i < subgraph_size; i++) { igraph_integer_t from = VECTOR(*vids)[i]; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, from, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, from, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (j = 0; j < s; j++) { igraph_integer_t nei = VECTOR(neis)[j], to; diff --git a/src/vendor/cigraph/src/isomorphism/isoclasses.h b/src/vendor/cigraph/src/isomorphism/isoclasses.h index 67fa9a2b06c..40c38d3b0a8 100644 --- a/src/vendor/cigraph/src/isomorphism/isoclasses.h +++ b/src/vendor/cigraph/src/isomorphism/isoclasses.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2008-2020 The igraph development team @@ -26,7 +25,7 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS extern const unsigned int igraph_i_isoclass2_3[]; extern const unsigned int igraph_i_isoclass2_4[]; @@ -41,6 +40,6 @@ extern const unsigned int igraph_i_isoclass_4u_idx[]; extern const unsigned int igraph_i_isoclass_5u_idx[]; extern const unsigned int igraph_i_isoclass_6u_idx[]; -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c b/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c index 2b8ff8e693c..c0e5e3007c9 100644 --- a/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c +++ b/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -21,7 +20,7 @@ */ -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "igraph_constructors.h" #include "igraph_interface.h" diff --git a/src/vendor/cigraph/src/isomorphism/lad.c b/src/vendor/cigraph/src/isomorphism/lad.c index 689c3260c9f..2ab5c09cce0 100644 --- a/src/vendor/cigraph/src/isomorphism/lad.c +++ b/src/vendor/cigraph/src/isomorphism/lad.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2012 Gabor Csardi @@ -46,7 +45,7 @@ -- Tamas Nepusz, 11 July 2013 */ -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "igraph_adjlist.h" #include "igraph_bitset.h" @@ -1332,7 +1331,7 @@ static igraph_error_t igraph_i_lad_filter(bool induced, Tdomain* D, Tgraph* Gp, -static igraph_error_t igraph_i_lad_solve(igraph_integer_t timeLimit, bool firstSol, bool induced, +static igraph_error_t igraph_i_lad_solve(bool firstSol, bool induced, Tdomain* D, Tgraph* Gp, Tgraph* Gt, igraph_bool_t *invalid, igraph_bool_t *iso, igraph_vector_int_t *vec, igraph_vector_int_t *map, igraph_vector_int_list_t *maps, @@ -1347,17 +1346,11 @@ static igraph_error_t igraph_i_lad_solve(igraph_integer_t timeLimit, bool firstS igraph_integer_t u, v, minDom, i; igraph_integer_t* nbVal; igraph_integer_t* globalMatching; - clock_t end = clock(); igraph_integer_t* val; bool result; (*nbNodes)++; - if ( (double)(end - *begin) / CLOCKS_PER_SEC >= timeLimit) { - /* CPU time limit exceeded */ - IGRAPH_ERROR("LAD CPU time exceeded", IGRAPH_CPUTIME); - } - /* Allocate memory */ ALLOC_ARRAY_IN_HISTORY(nbVal, Gp->nbVertices, igraph_integer_t, alloc_history); ALLOC_ARRAY_IN_HISTORY(globalMatching, Gp->nbVertices, igraph_integer_t, alloc_history); @@ -1423,7 +1416,7 @@ static igraph_error_t igraph_i_lad_solve(igraph_integer_t timeLimit, bool firstS (*nbNodes)++; igraph_i_lad_resetToFilter(D); } else { - IGRAPH_CHECK(igraph_i_lad_solve(timeLimit, firstSol, induced, + IGRAPH_CHECK(igraph_i_lad_solve(firstSol, induced, D, Gp, Gt, invalid, iso, vec, map, maps, nbNodes, nbFail, nbSol, begin, alloc_history)); @@ -1522,7 +1515,7 @@ igraph_error_t igraph_subisomorphic_lad(const igraph_t *pattern, const igraph_t const igraph_vector_int_list_t *domains, igraph_bool_t *iso, igraph_vector_int_t *map, igraph_vector_int_list_t *maps, - igraph_bool_t induced, igraph_integer_t time_limit) { + igraph_bool_t induced) { bool firstSol = maps == NULL; bool initialDomains = domains != NULL; @@ -1553,9 +1546,6 @@ igraph_error_t igraph_subisomorphic_lad(const igraph_t *pattern, const igraph_t IGRAPH_ERROR("Cannot search for a directed pattern in an undirected target " "or vice versa", IGRAPH_EINVAL); } - if (time_limit <= 0) { - time_limit = IGRAPH_INTEGER_MAX; - } if (iso) { *iso = (igraph_vcount(pattern) == 0); @@ -1631,7 +1621,7 @@ igraph_error_t igraph_subisomorphic_lad(const igraph_t *pattern, const igraph_t IGRAPH_CHECK(igraph_vector_ptr_init(&alloc_history, 0)); IGRAPH_FINALLY(igraph_vector_ptr_destroy_all, &alloc_history); - IGRAPH_CHECK(igraph_i_lad_solve(time_limit, firstSol, (bool) induced, &D, + IGRAPH_CHECK(igraph_i_lad_solve(firstSol, (bool) induced, &D, &Gp, &Gt, &invalidDomain, iso, &vec, map, maps, &nbNodes, &nbFail, &nbSol, &begin, &alloc_history)); diff --git a/src/vendor/cigraph/src/isomorphism/queries.c b/src/vendor/cigraph/src/isomorphism/queries.c index 5768bc57022..d693bcb3978 100644 --- a/src/vendor/cigraph/src/isomorphism/queries.c +++ b/src/vendor/cigraph/src/isomorphism/queries.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team @@ -20,7 +19,7 @@ */ -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "igraph_interface.h" #include "igraph_structural.h" @@ -161,33 +160,6 @@ igraph_error_t igraph_isomorphic(const igraph_t *graph1, const igraph_t *graph2, return IGRAPH_SUCCESS; } -/** - * \function igraph_isomorphic_34 - * \brief Graph isomorphism for 3-4 vertices (deprecated). - * - * \deprecated-by igraph_isomorphic 0.10.0 - * - * If you really care about performance and you \em know for sure that your - * input graphs are simple and have either 3 or 4 vertices for directed graphs, - * or 3-6 vertices for undirected graphs, you can compare their isomorphism - * classes obtained from \ref igraph_isoclass() directly instead of calling - * \ref igraph_isomorphic(); this saves the cost of checking whether the graphs - * do not contain multiple edges or self-loops. - * - * \param graph1 The first input graph. - * \param graph2 The second input graph. Must have the same - * directedness as \p graph1. - * \param iso Pointer to a boolean, the result is stored here. - * \return Error code. - * - * Time complexity: O(1). - */ -igraph_error_t igraph_isomorphic_34( - const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *iso -) { - return igraph_i_isomorphic_small(graph1, graph2, iso); -} - /** * \function igraph_i_isomorphic_small * \brief Graph isomorphism for small graphs. diff --git a/src/vendor/cigraph/src/isomorphism/vf2.c b/src/vendor/cigraph/src/isomorphism/vf2.c index 646a49bb228..85a4e3811bc 100644 --- a/src/vendor/cigraph/src/isomorphism/vf2.c +++ b/src/vendor/cigraph/src/isomorphism/vf2.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -21,7 +20,7 @@ */ -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "igraph_adjlist.h" #include "igraph_interface.h" @@ -697,26 +696,6 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( return IGRAPH_SUCCESS; } -/** - * \function igraph_isomorphic_function_vf2 - * \brief The generic VF2 interface (deprecated alias). - * - * \deprecated-by igraph_get_isomorphisms_vf2_callback 0.10.0 - */ -igraph_error_t igraph_isomorphic_function_vf2( - const igraph_t *graph1, const igraph_t *graph2, - const igraph_vector_int_t *vertex_color1, const igraph_vector_int_t *vertex_color2, - const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_vector_int_t *map12, igraph_vector_int_t *map21, - igraph_isohandler_t *isohandler_fn, igraph_isocompat_t *node_compat_fn, - igraph_isocompat_t *edge_compat_fn, void *arg -) { - return igraph_get_isomorphisms_vf2_callback( - graph1, graph2, vertex_color1, vertex_color2, edge_color1, edge_color2, - map12, map21, isohandler_fn, node_compat_fn, edge_compat_fn, arg - ); -} - typedef struct { igraph_isocompat_t *node_compat_fn, *edge_compat_fn; void *arg, *carg; @@ -885,7 +864,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. */ @@ -1545,26 +1524,6 @@ static igraph_error_t igraph_i_subisomorphic_vf2_cb( return IGRAPH_STOP; } -/** - * \function igraph_subisomorphic_function_vf2 - * \brief Generic VF2 function for subgraph isomorphism problems (deprecated alias). - * - * \deprecated-by igraph_get_subisomorphisms_vf2_callback 0.10.0 - */ -igraph_error_t igraph_subisomorphic_function_vf2( - const igraph_t *graph1, const igraph_t *graph2, - const igraph_vector_int_t *vertex_color1, const igraph_vector_int_t *vertex_color2, - const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_vector_int_t *map12, igraph_vector_int_t *map21, - igraph_isohandler_t *isohandler_fn, igraph_isocompat_t *node_compat_fn, - igraph_isocompat_t *edge_compat_fn, void *arg -) { - return igraph_get_subisomorphisms_vf2_callback( - graph1, graph2, vertex_color1, vertex_color2, edge_color1, edge_color2, - map12, map21, isohandler_fn, node_compat_fn, edge_compat_fn, arg - ); -} - /** * \function igraph_subisomorphic_vf2 * Decide subgraph isomorphism using VF2 diff --git a/src/vendor/cigraph/src/layout/circular.c b/src/vendor/cigraph/src/layout/circular.c index ed1bad318ca..029ced2eaac 100644 --- a/src/vendor/cigraph/src/layout/circular.c +++ b/src/vendor/cigraph/src/layout/circular.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team diff --git a/src/vendor/cigraph/src/layout/davidson_harel.c b/src/vendor/cigraph/src/layout/davidson_harel.c index 551d29202df..7e54763bc43 100644 --- a/src/vendor/cigraph/src/layout/davidson_harel.c +++ b/src/vendor/cigraph/src/layout/davidson_harel.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -27,7 +25,7 @@ #include "igraph_random.h" #include "core/interruption.h" -#include "core/math.h" +#include "core/math.h" /* M_PI */ #include "layout/layout_internal.h" #include @@ -197,8 +195,6 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix IGRAPH_FINALLY(igraph_vector_int_destroy, &try_idx); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 100); - RNG_BEGIN(); - if (!use_seed) { for (igraph_integer_t i = 0; i < no_nodes; i++) { igraph_real_t x, y; @@ -329,7 +325,9 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix } if (w_edge_lengths != 0) { - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); igraph_integer_t len = igraph_vector_int_size(&neis); for (igraph_integer_t j = 0; j < len; j++) { igraph_integer_t u = VECTOR(neis)[j]; @@ -346,7 +344,9 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix if (w_edge_crossings != 0) { igraph_integer_t no = 0; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); igraph_integer_t len = igraph_vector_int_size(&neis); for (igraph_integer_t j = 0; j < len; j++) { igraph_integer_t u = VECTOR(neis)[j]; @@ -395,7 +395,7 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix } /* All other nodes from all of v's incident edges */ - IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_ALL, IGRAPH_NO_LOOPS)); igraph_integer_t no = igraph_vector_int_size(&neis); for (igraph_integer_t e = 0; e < no; e++) { igraph_integer_t mye = VECTOR(neis)[e]; @@ -443,8 +443,6 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix } /* round < maxiter */ - RNG_END(); - igraph_vector_int_destroy(&neis); igraph_vector_int_destroy(&try_idx); igraph_vector_destroy(&try_x); diff --git a/src/vendor/cigraph/src/layout/drl/drl_layout.cpp b/src/vendor/cigraph/src/layout/drl/drl_layout.cpp index 9e15e9d72bd..79c09474750 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_layout.cpp +++ b/src/vendor/cigraph/src/layout/drl/drl_layout.cpp @@ -468,8 +468,6 @@ igraph_error_t igraph_layout_drl(const igraph_t *graph, igraph_matrix_t *res, } IGRAPH_HANDLE_EXCEPTIONS( - RNG_BEGIN(); - drl::graph neighbors(graph, options, weights); neighbors.init_parms(options); if (use_seed) { @@ -477,8 +475,6 @@ igraph_error_t igraph_layout_drl(const igraph_t *graph, igraph_matrix_t *res, neighbors.read_real(res); } IGRAPH_CHECK(neighbors.draw_graph(res)); - - RNG_END(); ); return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp b/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp index de2b809845e..9400659e2b5 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp +++ b/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp @@ -119,8 +119,6 @@ igraph_error_t igraph_layout_drl_3d(const igraph_t *graph, igraph_matrix_t *res, } IGRAPH_HANDLE_EXCEPTIONS( - RNG_BEGIN(); - drl3d::graph neighbors(graph, options, weights); neighbors.init_parms(options); if (use_seed) { @@ -128,8 +126,6 @@ igraph_error_t igraph_layout_drl_3d(const igraph_t *graph, igraph_matrix_t *res, neighbors.read_real(res); } IGRAPH_CHECK(neighbors.draw_graph(res)); - - RNG_END(); ); return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/layout/fruchterman_reingold.c b/src/vendor/cigraph/src/layout/fruchterman_reingold.c index 60b38c1b7ce..f4fb9637408 100644 --- a/src/vendor/cigraph/src/layout/fruchterman_reingold.c +++ b/src/vendor/cigraph/src/layout/fruchterman_reingold.c @@ -57,7 +57,6 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&dispx, vcount); IGRAPH_VECTOR_INIT_FINALLY(&dispy, vcount); - RNG_BEGIN(); for (igraph_integer_t i = 0; i < niter; i++) { IGRAPH_ALLOW_INTERRUPTION(); @@ -155,7 +154,6 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, temp -= difftemp; } - RNG_END(); igraph_vector_destroy(&dispx); igraph_vector_destroy(&dispy); @@ -199,7 +197,6 @@ static igraph_error_t igraph_layout_i_grid_fr( IGRAPH_VECTOR_INIT_FINALLY(&dispx, vcount); IGRAPH_VECTOR_INIT_FINALLY(&dispy, vcount); - RNG_BEGIN(); for (igraph_integer_t i = 0; i < niter; i++) { igraph_integer_t v, u; @@ -274,7 +271,6 @@ static igraph_error_t igraph_layout_i_grid_fr( temp -= difftemp; } - RNG_END(); igraph_vector_destroy(&dispx); igraph_vector_destroy(&dispy); @@ -552,7 +548,6 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&dispy, vcount); IGRAPH_VECTOR_INIT_FINALLY(&dispz, vcount); - RNG_BEGIN(); for (igraph_integer_t i = 0; i < niter; i++) { IGRAPH_ALLOW_INTERRUPTION(); @@ -671,7 +666,6 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, temp -= difftemp; } - RNG_END(); igraph_vector_destroy(&dispx); igraph_vector_destroy(&dispy); diff --git a/src/vendor/cigraph/src/layout/gem.c b/src/vendor/cigraph/src/layout/gem.c index 4526b7ebcb3..a2345d62d2b 100644 --- a/src/vendor/cigraph/src/layout/gem.c +++ b/src/vendor/cigraph/src/layout/gem.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -28,7 +26,7 @@ #include "igraph_structural.h" #include "core/interruption.h" -#include "core/math.h" +#include "core/math.h" /* M_PI */ /** * \ingroup layout @@ -131,8 +129,6 @@ igraph_error_t igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, IGRAPH_VECTOR_INIT_FINALLY(&phi, no_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 10); - RNG_BEGIN(); - /* Initialization */ IGRAPH_CHECK(igraph_strength(graph, &phi, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, /* weights = */ 0)); @@ -189,7 +185,9 @@ igraph_error_t igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, } } - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); nlen = igraph_vector_int_size(&neis); for (j = 0; j < nlen; j++) { igraph_integer_t u = VECTOR(neis)[j]; @@ -238,9 +236,6 @@ igraph_error_t igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, } /* while temp && iter */ - - RNG_END(); - igraph_vector_int_destroy(&neis); igraph_vector_destroy(&phi); igraph_vector_int_destroy(&perm); diff --git a/src/vendor/cigraph/src/layout/graphopt.c b/src/vendor/cigraph/src/layout/graphopt.c index c985122de55..b0b74b5a9f4 100644 --- a/src/vendor/cigraph/src/layout/graphopt.c +++ b/src/vendor/cigraph/src/layout/graphopt.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team diff --git a/src/vendor/cigraph/src/layout/large_graph.c b/src/vendor/cigraph/src/layout/large_graph.c index 96df10947aa..756186f4c92 100644 --- a/src/vendor/cigraph/src/layout/large_graph.c +++ b/src/vendor/cigraph/src/layout/large_graph.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -30,7 +28,7 @@ #include "core/grid.h" #include "core/interruption.h" -#include "core/math.h" +#include "core/math.h" /* M_PI */ static void igraph_i_norm2d(igraph_real_t *x, igraph_real_t *y) { igraph_real_t len = sqrt(*x * *x + *y * *y); @@ -155,8 +153,6 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, * TODO: If this function is updated to handle weights, it should * construct the MST and traverse that instead. */ - RNG_BEGIN(); - /* Determine the root vertex, random pick right now */ if (proot < 0) { root = RNG_INTEGER(0, no_of_nodes - 1); @@ -278,7 +274,7 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, igraph_integer_t vid = VECTOR(vids)[j]; igraph_integer_t k; IGRAPH_ALLOW_INTERRUPTION(); - IGRAPH_CHECK(igraph_incident(graph, &eids, vid, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &eids, vid, IGRAPH_ALL, IGRAPH_LOOPS)); for (k = 0; k < igraph_vector_int_size(&eids); k++) { igraph_integer_t eid = VECTOR(eids)[k]; igraph_integer_t from = IGRAPH_FROM(graph, eid), to = IGRAPH_TO(graph, eid); @@ -378,8 +374,6 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, } } - RNG_END(); - IGRAPH_PROGRESS("Large graph layout", 100.0, 0); igraph_vector_int_destroy(&vids); igraph_vector_int_destroy(&layers); diff --git a/src/vendor/cigraph/src/layout/layout_bipartite.c b/src/vendor/cigraph/src/layout/layout_bipartite.c index 92d018b4cda..59de88917f3 100644 --- a/src/vendor/cigraph/src/layout/layout_bipartite.c +++ b/src/vendor/cigraph/src/layout/layout_bipartite.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team diff --git a/src/vendor/cigraph/src/layout/layout_grid.c b/src/vendor/cigraph/src/layout/layout_grid.c index 16ec85b88fe..d8edad23dea 100644 --- a/src/vendor/cigraph/src/layout/layout_grid.c +++ b/src/vendor/cigraph/src/layout/layout_grid.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team diff --git a/src/vendor/cigraph/src/layout/layout_internal.h b/src/vendor/cigraph/src/layout/layout_internal.h index a9b193a16ac..d68c97e6e80 100644 --- a/src/vendor/cigraph/src/layout/layout_internal.h +++ b/src/vendor/cigraph/src/layout/layout_internal.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2021 The igraph development team @@ -31,7 +30,7 @@ #include "layout/merge_grid.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_layout_merge_dla(igraph_i_layout_mergegrid_t *grid, igraph_integer_t actg, igraph_real_t *x, igraph_real_t *y, igraph_real_t r, @@ -71,6 +70,6 @@ igraph_error_t igraph_i_layout_random_bounded_3d( const igraph_vector_t *miny, const igraph_vector_t *maxy, const igraph_vector_t *minz, const igraph_vector_t *maxz); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/layout/layout_random.c b/src/vendor/cigraph/src/layout/layout_random.c index dd51fa94d31..45fd0e1f7d4 100644 --- a/src/vendor/cigraph/src/layout/layout_random.c +++ b/src/vendor/cigraph/src/layout/layout_random.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -49,15 +47,11 @@ igraph_error_t igraph_layout_random(const igraph_t *graph, igraph_matrix_t *res) IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2)); - RNG_BEGIN(); - for (i = 0; i < no_of_nodes; i++) { MATRIX(*res, i, 0) = RNG_UNIF(-1, 1); MATRIX(*res, i, 1) = RNG_UNIF(-1, 1); } - RNG_END(); - return IGRAPH_SUCCESS; } @@ -86,16 +80,12 @@ igraph_error_t igraph_layout_random_3d(const igraph_t *graph, igraph_matrix_t *r IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3)); - RNG_BEGIN(); - for (i = 0; i < no_of_nodes; i++) { MATRIX(*res, i, 0) = RNG_UNIF(-1, 1); MATRIX(*res, i, 1) = RNG_UNIF(-1, 1); MATRIX(*res, i, 2) = RNG_UNIF(-1, 1); } - RNG_END(); - return IGRAPH_SUCCESS; } @@ -154,7 +144,6 @@ igraph_error_t igraph_i_layout_random_bounded( } } - RNG_BEGIN(); IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2)); for (igraph_integer_t i = 0; i < no_nodes; i++) { igraph_real_t x1 = minx ? VECTOR(*minx)[i] : dminx; @@ -176,7 +165,6 @@ igraph_error_t igraph_i_layout_random_bounded( MATRIX(*res, i, 0) = RNG_UNIF(x1, x2); MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); } - RNG_END(); return IGRAPH_SUCCESS; } @@ -251,7 +239,6 @@ igraph_error_t igraph_i_layout_random_bounded_3d( } } - RNG_BEGIN(); IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 3)); for (igraph_integer_t i = 0; i < no_nodes; i++) { igraph_real_t x1 = minx ? VECTOR(*minx)[i] : dminx; @@ -282,7 +269,6 @@ igraph_error_t igraph_i_layout_random_bounded_3d( MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); MATRIX(*res, i, 2) = RNG_UNIF(z1, z2); } - RNG_END(); return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/layout/mds.c b/src/vendor/cigraph/src/layout/mds.c index 6a34b6f9f26..d26eef3d22e 100644 --- a/src/vendor/cigraph/src/layout/mds.c +++ b/src/vendor/cigraph/src/layout/mds.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -28,7 +26,6 @@ #include "igraph_components.h" #include "igraph_eigen.h" #include "igraph_interface.h" -#include "igraph_memory.h" #include "igraph_operators.h" #include "igraph_paths.h" #include "igraph_random.h" @@ -195,8 +192,6 @@ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, igraph_matrix_t m; igraph_bool_t conn; - RNG_BEGIN(); - /* Check the distance matrix */ if (dist && (igraph_matrix_nrow(dist) != no_of_nodes || igraph_matrix_ncol(dist) != no_of_nodes)) { @@ -215,7 +210,7 @@ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, /* Copy or obtain the distance matrix */ if (dist == 0) { IGRAPH_MATRIX_INIT_FINALLY(&m, no_of_nodes, no_of_nodes); - IGRAPH_CHECK(igraph_distances(graph, &m, igraph_vss_all(), igraph_vss_all(), IGRAPH_ALL)); + IGRAPH_CHECK(igraph_distances(graph, NULL, &m, igraph_vss_all(), igraph_vss_all(), IGRAPH_ALL)); } else { IGRAPH_CHECK(igraph_matrix_init_copy(&m, dist)); IGRAPH_FINALLY(igraph_matrix_destroy, &m); @@ -293,8 +288,6 @@ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, IGRAPH_FINALLY_CLEAN(6); } - RNG_END(); - igraph_matrix_destroy(&m); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/layout/merge_dla.c b/src/vendor/cigraph/src/layout/merge_dla.c index 7082540aacf..cedf495fce6 100644 --- a/src/vendor/cigraph/src/layout/merge_dla.c +++ b/src/vendor/cigraph/src/layout/merge_dla.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -27,16 +25,31 @@ #include "igraph_random.h" #include "core/interruption.h" -#include "core/math.h" +#include "core/math.h" /* M_PI */ #include "layout/merge_grid.h" #include "layout/layout_internal.h" +static igraph_error_t vector_order(igraph_vector_t *v) { + const igraph_integer_t n = igraph_vector_size(v); + igraph_vector_int_t ind; + + IGRAPH_VECTOR_INT_INIT_FINALLY(&ind, n); + IGRAPH_CHECK(igraph_vector_sort_ind(v, &ind, IGRAPH_DESCENDING)); + + for (igraph_integer_t i=0; i < n; i++) { + VECTOR(*v)[i] = VECTOR(ind)[i]; + } + + igraph_vector_int_destroy(&ind); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + /** * \function igraph_layout_merge_dla * \brief Merges multiple layouts by using a DLA algorithm. * - * \experimental - * * First each layout is covered by a circle. Then the layout of the * largest graph is placed at the origin. Then the other layouts are * placed by the DLA algorithm, larger ones first and smaller ones @@ -84,8 +97,6 @@ igraph_error_t igraph_layout_merge_dla( IGRAPH_VECTOR_INIT_FINALLY(&ny, coords_len); IGRAPH_VECTOR_INIT_FINALLY(&nr, coords_len); - RNG_BEGIN(); - for (i = 0; i < coords_len; i++) { igraph_matrix_t *mat = igraph_matrix_list_get_ptr(coords, i); igraph_integer_t size = igraph_matrix_nrow(mat); @@ -109,7 +120,7 @@ igraph_error_t igraph_layout_merge_dla( igraph_vector_get_ptr(&ny, i), igraph_vector_get_ptr(&nr, i)); } - igraph_vector_order2(&sizes); /* largest first */ + vector_order(&sizes); /* largest first */ /* 0. create grid */ minx = miny = -sqrt(5 * area); @@ -166,8 +177,6 @@ igraph_error_t igraph_layout_merge_dla( } } - RNG_END(); - igraph_i_layout_mergegrid_destroy(&grid); igraph_vector_destroy(&sizes); igraph_vector_destroy(&x); diff --git a/src/vendor/cigraph/src/layout/merge_grid.h b/src/vendor/cigraph/src/layout/merge_grid.h index c4dd0f2c76d..48d08e9041d 100644 --- a/src/vendor/cigraph/src/layout/merge_grid.h +++ b/src/vendor/cigraph/src/layout/merge_grid.h @@ -23,7 +23,7 @@ #include "igraph_error.h" #include "igraph_types.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* A type of grid used for merging layouts; each cell is owned by exactly one graph */ @@ -50,6 +50,6 @@ igraph_integer_t igraph_i_layout_mergegrid_get(igraph_i_layout_mergegrid_t *grid igraph_integer_t igraph_i_layout_mergegrid_get_sphere(igraph_i_layout_mergegrid_t *g, igraph_real_t x, igraph_real_t y, igraph_real_t r); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/layout/reingold_tilford.c b/src/vendor/cigraph/src/layout/reingold_tilford.c index d16949866c6..fc1e98f3aea 100644 --- a/src/vendor/cigraph/src/layout/reingold_tilford.c +++ b/src/vendor/cigraph/src/layout/reingold_tilford.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2020 The igraph development team @@ -32,7 +30,7 @@ #include "igraph_progress.h" #include "igraph_structural.h" -#include "core/math.h" +#include "core/math.h" /* M_PI */ static igraph_error_t layout_reingold_tilford_unreachable( const igraph_t *graph, @@ -572,7 +570,7 @@ igraph_error_t igraph_roots_for_tree_layout( igraph_vector_t ecc; IGRAPH_VECTOR_INIT_FINALLY(&ecc, no_of_nodes); - IGRAPH_CHECK(igraph_eccentricity(graph, &ecc, igraph_vss_all(), mode)); + IGRAPH_CHECK(igraph_eccentricity(graph, NULL, &ecc, igraph_vss_all(), mode)); IGRAPH_CHECK(igraph_vector_sort_ind(&ecc, &order, IGRAPH_ASCENDING)); igraph_vector_destroy(&ecc); diff --git a/src/vendor/cigraph/src/layout/sugiyama.c b/src/vendor/cigraph/src/layout/sugiyama.c index 097a96ce097..dc59ffd1df5 100644 --- a/src/vendor/cigraph/src/layout/sugiyama.c +++ b/src/vendor/cigraph/src/layout/sugiyama.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -41,24 +39,12 @@ /* #define SUGIYAMA_DEBUG */ -#ifdef _MSC_VER -/* MSVC does not support variadic macros */ -#include -static void debug(const char* fmt, ...) { - va_list args; - va_start(args, fmt); -#ifdef SUGIYAMA_DEBUG - vfprintf(stderr, fmt, args); -#endif - va_end(args); -} -#else + #ifdef SUGIYAMA_DEBUG #define debug(...) fprintf(stderr, __VA_ARGS__) #else #define debug(...) #endif -#endif /* MSVC uses __forceinline instead of inline */ #ifdef _MSC_VER @@ -402,7 +388,7 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re /* Okay, this vertex is in the component we are considering. * Add the neighbors of this vertex, excluding loops */ - IGRAPH_CHECK(igraph_incident(graph, &neis, i, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &neis, i, IGRAPH_OUT, IGRAPH_LOOPS)); j = igraph_vector_int_size(&neis); for (k = 0; k < j; k++) { igraph_integer_t eid = VECTOR(neis)[k]; @@ -611,9 +597,9 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_vertically(const igra /* Calculate in- and out-strengths for the remaining edges */ IGRAPH_CHECK(igraph_strength(graph, &indegs, igraph_vss_all(), - IGRAPH_IN, 1, weights)); + IGRAPH_IN, IGRAPH_LOOPS, weights)); IGRAPH_CHECK(igraph_strength(graph, &outdegs, igraph_vss_all(), - IGRAPH_IN, 1, weights)); + IGRAPH_IN, IGRAPH_LOOPS, weights)); j = igraph_vector_int_size(&feedback_edges); for (i = 0; i < j; i++) { igraph_integer_t eid = VECTOR(feedback_edges)[i]; @@ -713,7 +699,10 @@ static igraph_error_t igraph_i_layout_sugiyama_calculate_barycenters(const igrap igraph_vector_null(barycenters); for (i = 0; i < n; i++) { - IGRAPH_CHECK(igraph_neighbors(graph, &neis, VECTOR(*layer_members)[i], direction)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, VECTOR(*layer_members)[i], direction, + IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); m = igraph_vector_int_size(&neis); if (m == 0) { /* No neighbors in this direction. Just use the current X coordinate */ @@ -923,7 +912,10 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_horizontally(const ig /* Find all the edges from this layer to the next */ igraph_vector_int_clear(&neis1); for (j = 0; j < n; j++) { - IGRAPH_CHECK(igraph_neighbors(graph, &neis2, VECTOR(*vertices)[j], IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis2, VECTOR(*vertices)[j], IGRAPH_OUT, + IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); IGRAPH_CHECK(igraph_vector_int_append(&neis1, &neis2)); } @@ -1119,7 +1111,9 @@ static igraph_error_t igraph_i_layout_sugiyama_vertical_alignment(const igraph_t } /* Find the neighbors of vertex j in layer i */ - IGRAPH_CHECK(igraph_neighbors(graph, &neis, vertex, neimode)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, vertex, neimode, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); if (n == 0) diff --git a/src/vendor/cigraph/src/layout/umap.c b/src/vendor/cigraph/src/layout/umap.c index e3bd10ec60d..247518e9d71 100644 --- a/src/vendor/cigraph/src/layout/umap.c +++ b/src/vendor/cigraph/src/layout/umap.c @@ -255,7 +255,7 @@ igraph_error_t igraph_layout_umap_compute_weights( /* Iterate over vertices x, like in the paper */ for (igraph_integer_t i = 0; i < no_of_vertices; i++) { /* Edges out of this vertex, e.g. to its k-nearest neighbors */ - IGRAPH_CHECK(igraph_incident(graph, &eids, i, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &eids, i, IGRAPH_OUT, IGRAPH_LOOPS)); no_of_neis = igraph_vector_int_size(&eids); /* Vertex has no neighbors */ @@ -854,7 +854,7 @@ static igraph_error_t igraph_i_umap_apply_forces( /* NOTE: the efficiency of this step could be improved but it * should be only used for small graphs anyway, so it's fine */ igraph_bool_t skip = false; - IGRAPH_CHECK(igraph_incident(graph, &neis, from, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &neis, from, IGRAPH_ALL, IGRAPH_LOOPS)); const igraph_integer_t nneis = igraph_vector_int_size(&neis); for (igraph_integer_t k = 0; k < nneis; k++) { igraph_integer_t eid2 = VECTOR(neis)[k]; @@ -1138,8 +1138,6 @@ static igraph_error_t igraph_i_layout_umap( } } - RNG_BEGIN(); - /* Fit a and b parameter to find smooth approximation to * probability distribution in embedding space */ IGRAPH_CHECK(igraph_i_umap_fit_ab(min_dist, &a, &b)); @@ -1154,8 +1152,6 @@ static igraph_error_t igraph_i_layout_umap( epochs, negative_sampling_rate)); - RNG_END(); - if (!distances_are_weights) { igraph_vector_destroy(&weights); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/linalg/arpack.c b/src/vendor/cigraph/src/linalg/arpack.c index 1908ecb4b5c..f3157a9e311 100644 --- a/src/vendor/cigraph/src/linalg/arpack.c +++ b/src/vendor/cigraph/src/linalg/arpack.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* vim:set ts=4 sw=4 sts=4 noet: */ /* IGraph library. @@ -37,90 +36,16 @@ /* The ARPACK example file dssimp.f is used as a template */ -static igraph_error_t igraph_i_arpack_err_dsaupd(int error) { - switch (error) { - case 1: return IGRAPH_ARPACK_MAXIT; - case 3: return IGRAPH_ARPACK_NOSHIFT; - case -1: return IGRAPH_ARPACK_NPOS; - case -2: return IGRAPH_ARPACK_NEVNPOS; - case -3: return IGRAPH_ARPACK_NCVSMALL; - case -4: return IGRAPH_ARPACK_NONPOSI; - case -5: return IGRAPH_ARPACK_WHICHINV; - case -6: return IGRAPH_ARPACK_BMATINV; - case -7: return IGRAPH_ARPACK_WORKLSMALL; - case -8: return IGRAPH_ARPACK_TRIDERR; - case -9: return IGRAPH_ARPACK_ZEROSTART; - case -10: return IGRAPH_ARPACK_MODEINV; - case -11: return IGRAPH_ARPACK_MODEBMAT; - case -12: return IGRAPH_ARPACK_ISHIFT; - case -13: return IGRAPH_ARPACK_NEVBE; - case -9999: return IGRAPH_ARPACK_NOFACT; - default: return IGRAPH_ARPACK_UNKNOWN; - } -} +static igraph_arpack_error_t igraph_i_arpack_err_dsaupd(int error); +static igraph_arpack_error_t igraph_i_arpack_err_dseupd(int error); +static igraph_arpack_error_t igraph_i_arpack_err_dnaupd(int error); +static igraph_arpack_error_t igraph_i_arpack_err_dneupd(int error); -static igraph_error_t igraph_i_arpack_err_dseupd(int error) { - switch (error) { - case -1: return IGRAPH_ARPACK_NPOS; - case -2: return IGRAPH_ARPACK_NEVNPOS; - case -3: return IGRAPH_ARPACK_NCVSMALL; - case -5: return IGRAPH_ARPACK_WHICHINV; - case -6: return IGRAPH_ARPACK_BMATINV; - case -7: return IGRAPH_ARPACK_WORKLSMALL; - case -8: return IGRAPH_ARPACK_TRIDERR; - case -9: return IGRAPH_ARPACK_ZEROSTART; - case -10: return IGRAPH_ARPACK_MODEINV; - case -11: return IGRAPH_ARPACK_MODEBMAT; - case -12: return IGRAPH_ARPACK_NEVBE; - case -14: return IGRAPH_ARPACK_FAILED; - case -15: return IGRAPH_ARPACK_HOWMNY; - case -16: return IGRAPH_ARPACK_HOWMNYS; - case -17: return IGRAPH_ARPACK_EVDIFF; - default: return IGRAPH_ARPACK_UNKNOWN; - } +static igraph_arpack_error_t last_arpack_error = IGRAPH_ARPACK_NO_ERROR; -} - -static igraph_error_t igraph_i_arpack_err_dnaupd(int error) { - switch (error) { - case 1: return IGRAPH_ARPACK_MAXIT; - case 3: return IGRAPH_ARPACK_NOSHIFT; - case -1: return IGRAPH_ARPACK_NPOS; - case -2: return IGRAPH_ARPACK_NEVNPOS; - case -3: return IGRAPH_ARPACK_NCVSMALL; - case -4: return IGRAPH_ARPACK_NONPOSI; - case -5: return IGRAPH_ARPACK_WHICHINV; - case -6: return IGRAPH_ARPACK_BMATINV; - case -7: return IGRAPH_ARPACK_WORKLSMALL; - case -8: return IGRAPH_ARPACK_TRIDERR; - case -9: return IGRAPH_ARPACK_ZEROSTART; - case -10: return IGRAPH_ARPACK_MODEINV; - case -11: return IGRAPH_ARPACK_MODEBMAT; - case -12: return IGRAPH_ARPACK_ISHIFT; - case -9999: return IGRAPH_ARPACK_NOFACT; - default: return IGRAPH_ARPACK_UNKNOWN; - } -} - -static igraph_error_t igraph_i_arpack_err_dneupd(int error) { - switch (error) { - case 1: return IGRAPH_ARPACK_REORDER; - case -1: return IGRAPH_ARPACK_NPOS; - case -2: return IGRAPH_ARPACK_NEVNPOS; - case -3: return IGRAPH_ARPACK_NCVSMALL; - case -5: return IGRAPH_ARPACK_WHICHINV; - case -6: return IGRAPH_ARPACK_BMATINV; - case -7: return IGRAPH_ARPACK_WORKLSMALL; - case -8: return IGRAPH_ARPACK_SHUR; - case -9: return IGRAPH_ARPACK_LAPACK; - case -10: return IGRAPH_ARPACK_MODEINV; - case -11: return IGRAPH_ARPACK_MODEBMAT; - case -12: return IGRAPH_ARPACK_HOWMNYS; - case -13: return IGRAPH_ARPACK_HOWMNY; - case -14: return IGRAPH_ARPACK_FAILED; - case -15: return IGRAPH_ARPACK_EVDIFF; - default: return IGRAPH_ARPACK_UNKNOWN; - } +#define IGRAPH_ARPACK_ERROR(code) { \ + last_arpack_error = code; \ + IGRAPH_ERROR(igraph_arpack_error_to_string(code), IGRAPH_EARPACK); \ } /* Pristine ARPACK options object that is not exposed to the user; this is used @@ -346,7 +271,7 @@ static igraph_error_t igraph_i_arpack_rssolve_1x1(igraph_arpack_function_t *fun, int nev = options->nev; if (nev <= 0) { - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_NEVNPOS); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_NEVNPOS); } /* Probe the value in the matrix */ @@ -379,7 +304,7 @@ static igraph_error_t igraph_i_arpack_rnsolve_1x1(igraph_arpack_function_t *fun, int nev = options->nev; if (nev <= 0) { - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_NEVNPOS); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_NEVNPOS); } /* Probe the value in the matrix */ @@ -418,7 +343,7 @@ static igraph_error_t igraph_i_arpack_rnsolve_2x2(igraph_arpack_function_t *fun, int nev = options->nev; if (nev <= 0) { - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_NEVNPOS); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_NEVNPOS); } if (nev > 2) { nev = 2; @@ -478,7 +403,7 @@ static igraph_error_t igraph_i_arpack_rnsolve_2x2(igraph_arpack_function_t *fun, /* eval1 must be the one with the smallest imaginary part */ swap_evals = (IGRAPH_IMAG(eval1) > IGRAPH_IMAG(eval2)); } else { - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_WHICHINV); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_WHICHINV); } } else if (options->which[0] == 'L') { if (options->which[1] == 'M') { @@ -491,13 +416,13 @@ static igraph_error_t igraph_i_arpack_rnsolve_2x2(igraph_arpack_function_t *fun, /* eval1 must be the one with the largest imaginary part */ swap_evals = (IGRAPH_IMAG(eval1) < IGRAPH_IMAG(eval2)); } else { - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_WHICHINV); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_WHICHINV); } } else if (options->which[0] == 'X' && options->which[1] == 'X') { /* No preference on the ordering of eigenvectors */ } else { /* fprintf(stderr, "%c%c\n", options->which[0], options->which[1]); */ - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_WHICHINV); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_WHICHINV); } options->nconv = nev; @@ -563,7 +488,7 @@ static igraph_error_t igraph_i_arpack_rssolve_2x2(igraph_arpack_function_t *fun, int nev = options->nev; if (nev <= 0) { - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_NEVNPOS); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_NEVNPOS); } if (nev > 2) { nev = 2; @@ -612,7 +537,7 @@ static igraph_error_t igraph_i_arpack_rssolve_2x2(igraph_arpack_function_t *fun, } else if (options->which[0] == 'X' && options->which[1] == 'X') { /* No preference on the ordering of eigenvectors */ } else { - IGRAPH_ERROR("ARPACK error", IGRAPH_ARPACK_WHICHINV); + IGRAPH_ARPACK_ERROR(IGRAPH_ARPACK_WHICHINV); } options->nconv = nev; @@ -1049,11 +974,9 @@ igraph_error_t igraph_arpack_rssolve(igraph_arpack_function_t *fun, void *extra, } else { // we need to generate a random vector on our own; let's not rely on // ARPACK to do so because we want to use our own RNG - RNG_BEGIN(); for (i = 0; i < options->n; i++) { resid[i] = RNG_UNIF(-1, 1); } - RNG_END(); } /* Ok, we have everything */ @@ -1099,7 +1022,7 @@ igraph_error_t igraph_arpack_rssolve(igraph_arpack_function_t *fun, void *extra, igraph_i_arpack_report_no_convergence(options); } if (options->info != 0) { - IGRAPH_ERROR("ARPACK error", igraph_i_arpack_err_dsaupd(options->info)); + IGRAPH_ARPACK_ERROR(igraph_i_arpack_err_dsaupd(options->info)); } options->ierr = 0; @@ -1121,7 +1044,7 @@ igraph_error_t igraph_arpack_rssolve(igraph_arpack_function_t *fun, void *extra, #endif if (options->ierr != 0) { - IGRAPH_ERROR("ARPACK error", igraph_i_arpack_err_dseupd(options->ierr)); + IGRAPH_ARPACK_ERROR(igraph_i_arpack_err_dseupd(options->ierr)); } /* Save the result */ @@ -1329,11 +1252,9 @@ igraph_error_t igraph_arpack_rnsolve(igraph_arpack_function_t *fun, void *extra, } else { // we need to generate a random vector on our own; let's not rely on // ARPACK to do so because we want to use our own RNG - RNG_BEGIN(); for (i = 0; i < options->n; i++) { resid[i] = RNG_UNIF(-1, 1); } - RNG_END(); } /* Ok, we have everything */ @@ -1384,7 +1305,7 @@ igraph_error_t igraph_arpack_rnsolve(igraph_arpack_function_t *fun, void *extra, igraph_i_arpack_report_no_convergence(options); } if (options->info != 0 && options->info != -9999) { - IGRAPH_ERROR("ARPACK error", igraph_i_arpack_err_dnaupd(options->info)); + IGRAPH_ARPACK_ERROR(igraph_i_arpack_err_dnaupd(options->info)); } options->ierr = 0; @@ -1406,7 +1327,7 @@ igraph_error_t igraph_arpack_rnsolve(igraph_arpack_function_t *fun, void *extra, #endif if (options->ierr != 0) { - IGRAPH_ERROR("ARPACK error", igraph_i_arpack_err_dneupd(options->ierr)); + IGRAPH_ARPACK_ERROR(igraph_i_arpack_err_dneupd(options->ierr)); } /* Save the result */ @@ -1554,3 +1475,160 @@ igraph_error_t igraph_arpack_unpack_complex(igraph_matrix_t *vectors, igraph_mat return IGRAPH_SUCCESS; } + +/* ************************************************************************* */ + +/* Helper functions to map ARPACK error codes to \c igraph_arpack_error_t */ + +static igraph_arpack_error_t igraph_i_arpack_err_dsaupd(int error) { + switch (error) { + case 0: return IGRAPH_ARPACK_NO_ERROR; + case 1: return IGRAPH_ARPACK_MAXIT; + case 3: return IGRAPH_ARPACK_NOSHIFT; + case -1: return IGRAPH_ARPACK_NPOS; + case -2: return IGRAPH_ARPACK_NEVNPOS; + case -3: return IGRAPH_ARPACK_NCVSMALL; + case -4: return IGRAPH_ARPACK_NONPOSI; + case -5: return IGRAPH_ARPACK_WHICHINV; + case -6: return IGRAPH_ARPACK_BMATINV; + case -7: return IGRAPH_ARPACK_WORKLSMALL; + case -8: return IGRAPH_ARPACK_TRIDERR; + case -9: return IGRAPH_ARPACK_ZEROSTART; + case -10: return IGRAPH_ARPACK_MODEINV; + case -11: return IGRAPH_ARPACK_MODEBMAT; + case -12: return IGRAPH_ARPACK_ISHIFT; + case -13: return IGRAPH_ARPACK_NEVBE; + case -9999: return IGRAPH_ARPACK_NOFACT; + default: return IGRAPH_ARPACK_UNKNOWN; + } +} + +static igraph_arpack_error_t igraph_i_arpack_err_dseupd(int error) { + switch (error) { + case 0: return IGRAPH_ARPACK_NO_ERROR; + case -1: return IGRAPH_ARPACK_NPOS; + case -2: return IGRAPH_ARPACK_NEVNPOS; + case -3: return IGRAPH_ARPACK_NCVSMALL; + case -5: return IGRAPH_ARPACK_WHICHINV; + case -6: return IGRAPH_ARPACK_BMATINV; + case -7: return IGRAPH_ARPACK_WORKLSMALL; + case -8: return IGRAPH_ARPACK_TRIDERR; + case -9: return IGRAPH_ARPACK_ZEROSTART; + case -10: return IGRAPH_ARPACK_MODEINV; + case -11: return IGRAPH_ARPACK_MODEBMAT; + case -12: return IGRAPH_ARPACK_NEVBE; + case -14: return IGRAPH_ARPACK_FAILED; + case -15: return IGRAPH_ARPACK_HOWMNY; + case -16: return IGRAPH_ARPACK_HOWMNYS; + case -17: return IGRAPH_ARPACK_EVDIFF; + default: return IGRAPH_ARPACK_UNKNOWN; + } + +} + +static igraph_arpack_error_t igraph_i_arpack_err_dnaupd(int error) { + switch (error) { + case 0: return IGRAPH_ARPACK_NO_ERROR; + case 1: return IGRAPH_ARPACK_MAXIT; + case 3: return IGRAPH_ARPACK_NOSHIFT; + case -1: return IGRAPH_ARPACK_NPOS; + case -2: return IGRAPH_ARPACK_NEVNPOS; + case -3: return IGRAPH_ARPACK_NCVSMALL; + case -4: return IGRAPH_ARPACK_NONPOSI; + case -5: return IGRAPH_ARPACK_WHICHINV; + case -6: return IGRAPH_ARPACK_BMATINV; + case -7: return IGRAPH_ARPACK_WORKLSMALL; + case -8: return IGRAPH_ARPACK_TRIDERR; + case -9: return IGRAPH_ARPACK_ZEROSTART; + case -10: return IGRAPH_ARPACK_MODEINV; + case -11: return IGRAPH_ARPACK_MODEBMAT; + case -12: return IGRAPH_ARPACK_ISHIFT; + case -9999: return IGRAPH_ARPACK_NOFACT; + default: return IGRAPH_ARPACK_UNKNOWN; + } +} + +static igraph_arpack_error_t igraph_i_arpack_err_dneupd(int error) { + switch (error) { + case 0: return IGRAPH_ARPACK_NO_ERROR; + case 1: return IGRAPH_ARPACK_REORDER; + case -1: return IGRAPH_ARPACK_NPOS; + case -2: return IGRAPH_ARPACK_NEVNPOS; + case -3: return IGRAPH_ARPACK_NCVSMALL; + case -5: return IGRAPH_ARPACK_WHICHINV; + case -6: return IGRAPH_ARPACK_BMATINV; + case -7: return IGRAPH_ARPACK_WORKLSMALL; + case -8: return IGRAPH_ARPACK_SHUR; + case -9: return IGRAPH_ARPACK_LAPACK; + case -10: return IGRAPH_ARPACK_MODEINV; + case -11: return IGRAPH_ARPACK_MODEBMAT; + case -12: return IGRAPH_ARPACK_HOWMNYS; + case -13: return IGRAPH_ARPACK_HOWMNY; + case -14: return IGRAPH_ARPACK_FAILED; + case -15: return IGRAPH_ARPACK_EVDIFF; + default: return IGRAPH_ARPACK_UNKNOWN; + } +} + +static const char* igraph_i_arpack_error_strings[] = { + /* 15 */ "Matrix-vector product failed", + /* 16 */ "N must be positive", + /* 17 */ "NEV must be positive", + /* 18 */ "NCV must be greater than NEV and less than or equal to N " + "(and for the non-symmetric solver NCV-NEV >=2 must also hold)", + /* 19 */ "Maximum number of iterations should be positive", + /* 20 */ "Invalid WHICH parameter", + /* 21 */ "Invalid BMAT parameter", + /* 22 */ "WORKL is too small", + /* 23 */ "LAPACK error in tridiagonal eigenvalue calculation", + /* 24 */ "Starting vector is zero", + /* 25 */ "MODE is invalid", + /* 26 */ "MODE and BMAT are not compatible", + /* 27 */ "ISHIFT must be 0 or 1", + /* 28 */ "NEV and WHICH='BE' are incompatible", + /* 29 */ "Could not build an Arnoldi factorization", + /* 30 */ "No eigenvalues to sufficient accuracy", + /* 31 */ "HOWMNY is invalid", + /* 32 */ "HOWMNY='S' is not implemented", + /* 33 */ "Different number of converged Ritz values", + /* 34 */ "Error from calculation of a real Schur form", + /* 35 */ "LAPACK (dtrevc) error for calculating eigenvectors", + /* 36 */ "Unknown ARPACK error", + /* 37 */ 0, + /* 38 */ 0, + /* 39 */ "Maximum number of iterations reached", + /* 40 */ "No shifts could be applied during a cycle of the " + "Implicitly restarted Arnoldi iteration. One possibility " + "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." +}; + +/** + * \function igraph_arpack_error_to_string + * \brief Convert an ARPACK error code to a human-readable representation. + */ +const char* igraph_arpack_error_to_string(igraph_arpack_error_t error) { + if (error == IGRAPH_ARPACK_NO_ERROR) { + return "No error"; + } + + int index = (error >= IGRAPH_ARPACK_PROD) + ? error - IGRAPH_ARPACK_PROD + : -1; + const char* message = 0; + + if (index >= 0 && index < sizeof(igraph_i_arpack_error_strings) / sizeof(igraph_i_arpack_error_strings[0])) { + message = igraph_i_arpack_error_strings[index]; + } + + return message ? message : "Unknown ARPACK error"; +} + +/** + * \function igraph_arpack_get_last_error + * \brief Returns the last error code returned from an ARPACK function. + */ +igraph_arpack_error_t igraph_arpack_get_last_error(void) { + return last_arpack_error; +} diff --git a/src/vendor/cigraph/src/linalg/arpack_internal.h b/src/vendor/cigraph/src/linalg/arpack_internal.h index 0392624d179..1d90481b1b4 100644 --- a/src/vendor/cigraph/src/linalg/arpack_internal.h +++ b/src/vendor/cigraph/src/linalg/arpack_internal.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -31,7 +30,7 @@ #include "igraph_decls.h" #include "config.h" /* INTERNAL_ARPACK */ -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS #ifndef INTERNAL_ARPACK #define igraphdsaupd_ dsaupd_ @@ -228,6 +227,6 @@ int igraphdsortc_(char *which, int *apply, int* n, double *xreal, #endif -__END_DECLS +IGRAPH_END_C_DECLS #endif /* ARPACK_INTERNAL_H */ diff --git a/src/vendor/cigraph/src/linalg/blas.c b/src/vendor/cigraph/src/linalg/blas.c index 19fe8ad3ba5..0eb0c8bcc96 100644 --- a/src/vendor/cigraph/src/linalg/blas.c +++ b/src/vendor/cigraph/src/linalg/blas.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/linalg/blas_internal.h b/src/vendor/cigraph/src/linalg/blas_internal.h index ab1bd693c27..df1d4fdf49a 100644 --- a/src/vendor/cigraph/src/linalg/blas_internal.h +++ b/src/vendor/cigraph/src/linalg/blas_internal.h @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -32,7 +30,7 @@ #include "igraph_decls.h" #include "config.h" /* INTERNAL_BLAS */ -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS #ifndef INTERNAL_BLAS #define igraphdaxpy_ daxpy_ @@ -89,6 +87,6 @@ double igraphdnrm2_(int *n, double *x, int *incx); double igraphddot_(int *n, double *dx, int *incx, double *dy, int *incy); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/linalg/eigen.c b/src/vendor/cigraph/src/linalg/eigen.c index 337e1294d21..af70fafcbda 100644 --- a/src/vendor/cigraph/src/linalg/eigen.c +++ b/src/vendor/cigraph/src/linalg/eigen.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -1143,11 +1142,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 ed5d64cc1df..80de98a76f2 100644 --- a/src/vendor/cigraph/src/linalg/lapack.c +++ b/src/vendor/cigraph/src/linalg/lapack.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -128,25 +127,25 @@ igraph_error_t igraph_lapack_dgetrf(igraph_matrix_t *a, igraph_vector_int_t *ipi } else if (*info < 0) { switch (*info) { case -1: - IGRAPH_ERROR("Invalid number of rows.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid number of rows.", IGRAPH_FAILURE); break; case -2: - IGRAPH_ERROR("Invalid number of columns.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid number of columns.", IGRAPH_FAILURE); break; case -3: - IGRAPH_ERROR("Invalid input matrix.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid input matrix.", IGRAPH_FAILURE); break; case -4: - IGRAPH_ERROR("Invalid LDA parameter.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid LDA parameter.", IGRAPH_FAILURE); break; case -5: - IGRAPH_ERROR("Invalid pivot vector.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid pivot vector.", IGRAPH_FAILURE); break; case -6: - IGRAPH_ERROR("Invalid info argument.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid info argument.", IGRAPH_FAILURE); break; default: - IGRAPH_ERROR("Unknown LAPACK error.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Unknown LAPACK error.", IGRAPH_FAILURE); break; } } @@ -208,7 +207,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); @@ -233,34 +232,34 @@ igraph_error_t igraph_lapack_dgetrs(igraph_bool_t transpose, const igraph_matrix if (info < 0) { switch (info) { case -1: - IGRAPH_ERROR("Invalid transpose argument.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid transpose argument.", IGRAPH_FAILURE); break; case -2: - IGRAPH_ERROR("Invalid number of rows/columns.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid number of rows/columns.", IGRAPH_FAILURE); break; case -3: - IGRAPH_ERROR("Invalid number of RHS vectors.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid number of RHS vectors.", IGRAPH_FAILURE); break; case -4: - IGRAPH_ERROR("Invalid LU matrix.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid LU matrix.", IGRAPH_FAILURE); break; case -5: - IGRAPH_ERROR("Invalid LDA parameter.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid LDA parameter.", IGRAPH_FAILURE); break; case -6: - IGRAPH_ERROR("Invalid pivot vector.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid pivot vector.", IGRAPH_FAILURE); break; case -7: - IGRAPH_ERROR("Invalid RHS matrix.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid RHS matrix.", IGRAPH_FAILURE); break; case -8: - IGRAPH_ERROR("Invalid LDB parameter.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid LDB parameter.", IGRAPH_FAILURE); break; case -9: - IGRAPH_ERROR("Invalid info argument.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid info argument.", IGRAPH_FAILURE); break; default: - IGRAPH_ERROR("Unknown LAPACK error.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Unknown LAPACK error.", IGRAPH_FAILURE); break; } } @@ -320,7 +319,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); @@ -337,31 +336,31 @@ igraph_error_t igraph_lapack_dgesv(igraph_matrix_t *a, igraph_vector_int_t *ipiv } else if (*info < 0) { switch (*info) { case -1: - IGRAPH_ERROR("Invalid number of rows/column.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid number of rows/column.", IGRAPH_FAILURE); break; case -2: - IGRAPH_ERROR("Invalid number of RHS vectors.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid number of RHS vectors.", IGRAPH_FAILURE); break; case -3: - IGRAPH_ERROR("Invalid input matrix.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid input matrix.", IGRAPH_FAILURE); break; case -4: - IGRAPH_ERROR("Invalid LDA parameter.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid LDA parameter.", IGRAPH_FAILURE); break; case -5: - IGRAPH_ERROR("Invalid pivot vector.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid pivot vector.", IGRAPH_FAILURE); break; case -6: - IGRAPH_ERROR("Invalid RHS matrix.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid RHS matrix.", IGRAPH_FAILURE); break; case -7: - IGRAPH_ERROR("Invalid LDB parameter.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid LDB parameter.", IGRAPH_FAILURE); break; case -8: - IGRAPH_ERROR("Invalid info argument.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Invalid info argument.", IGRAPH_FAILURE); break; default: - IGRAPH_ERROR("Unknown LAPACK error.", IGRAPH_ELAPACK); + IGRAPH_ERROR("Unknown LAPACK error.", IGRAPH_FAILURE); break; } } @@ -459,7 +458,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 +640,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)); @@ -684,10 +683,10 @@ igraph_error_t igraph_lapack_dgeev(const igraph_matrix_t *A, VECTOR(work), &lwork, info); if (*info < 0) { - IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_ELAPACK); + IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_FAILURE); } else if (*info > 0) { if (error) { - IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_ELAPACK); + IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_FAILURE); } else { IGRAPH_WARNING("Cannot calculate eigenvalues (dgeev)."); } @@ -868,7 +867,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) { @@ -953,10 +952,10 @@ igraph_error_t igraph_lapack_dgeevx(igraph_lapack_dgeevx_balance_t balance, VECTOR(work), &lwork, VECTOR(iwork), info); if (*info < 0) { - IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_ELAPACK); + IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_FAILURE); } else if (*info > 0) { if (error) { - IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_ELAPACK); + IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_FAILURE); } else { IGRAPH_WARNING("Cannot calculate eigenvalues (dgeev)."); } @@ -1003,7 +1002,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/linalg/lapack_internal.h b/src/vendor/cigraph/src/linalg/lapack_internal.h index b95885d1b8a..a6dd3feeabe 100644 --- a/src/vendor/cigraph/src/linalg/lapack_internal.h +++ b/src/vendor/cigraph/src/linalg/lapack_internal.h @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -32,7 +30,7 @@ #include "igraph_decls.h" #include "config.h" /* INTERNAL_LAPACK */ -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS #ifndef INTERNAL_LAPACK #define igraphdgeevx_ dgeevx_ @@ -181,6 +179,6 @@ int igraphdgehrd_(int *n, int *ilo, int *ihi, double *A, int *lda, double igraphddot_(int *n, double *dx, int *incx, double *dy, int *incy); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/math/complex.c b/src/vendor/cigraph/src/math/complex.c index 10ee36f61a1..ef3efaffc2f 100644 --- a/src/vendor/cigraph/src/math/complex.c +++ b/src/vendor/cigraph/src/math/complex.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2010-2012 Gabor Csardi @@ -43,20 +42,6 @@ igraph_complex_t igraph_complex_polar(igraph_real_t r, igraph_real_t theta) { return res; } -/** - * Deprecated in favour of igraph_complex_almost_equals(), which uses relative - * tolerances. Will be removed in 0.11. - */ -igraph_bool_t igraph_complex_eq_tol(igraph_complex_t z1, - igraph_complex_t z2, - igraph_real_t tol) { - if (fabs(IGRAPH_REAL(z1) - IGRAPH_REAL(z2)) > tol || - fabs(IGRAPH_IMAG(z1) - IGRAPH_IMAG(z2)) > tol) { - return false; - } - return true; -} - igraph_real_t igraph_complex_arg(igraph_complex_t z) { igraph_real_t x = IGRAPH_REAL(z); igraph_real_t y = IGRAPH_IMAG(z); diff --git a/src/vendor/cigraph/src/math/safe_intop.h b/src/vendor/cigraph/src/math/safe_intop.h index 79db3ddd9c3..e8b3605f697 100644 --- a/src/vendor/cigraph/src/math/safe_intop.h +++ b/src/vendor/cigraph/src/math/safe_intop.h @@ -29,7 +29,7 @@ #include -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /* Largest positive value for igraph_real_t that can safely represent integers. */ #define IGRAPH_MAX_EXACT_REAL ((double)(1LL << DBL_MANT_DIG)) @@ -134,6 +134,6 @@ IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_safe_mult(igraph_integer_t a, igra igraph_error_t igraph_i_safe_vector_int_sum(const igraph_vector_int_t *vec, igraph_integer_t *res); igraph_error_t igraph_i_safe_vector_int_prod(const igraph_vector_int_t *vec, igraph_integer_t *res); -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_MATH_SAFE_INTOP_H */ diff --git a/src/vendor/cigraph/src/math/utils.c b/src/vendor/cigraph/src/math/utils.c index 7c0be5baf4f..9b64c184f73 100644 --- a/src/vendor/cigraph/src/math/utils.c +++ b/src/vendor/cigraph/src/math/utils.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2007-2012 Gabor Csardi @@ -28,26 +27,6 @@ #include #include -int igraph_finite(double x) { - return isfinite(x); -} - -int igraph_is_nan(double x) { - return isnan(x); -} - -int igraph_is_inf(double x) { - return isinf(x) != 0; -} - -int igraph_is_posinf(double x) { - return isinf(x) && x > 0; -} - -int igraph_is_neginf(double x) { - return isinf(x) && x < 0; -} - /** * \function igraph_almost_equals * \brief Compare two double-precision floats with a tolerance. diff --git a/src/vendor/cigraph/src/misc/bipartite.c b/src/vendor/cigraph/src/misc/bipartite.c index 1f324b87476..95ea1111791 100644 --- a/src/vendor/cigraph/src/misc/bipartite.c +++ b/src/vendor/cigraph/src/misc/bipartite.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2008-2012 Gabor Csardi @@ -284,8 +283,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)); @@ -562,7 +560,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; @@ -589,21 +587,6 @@ igraph_error_t igraph_create_bipartite(igraph_t *graph, const igraph_vector_bool return IGRAPH_SUCCESS; } -/** - * \function igraph_incidence - * \brief Creates a bipartite graph from a bipartite adjacency matrix (deprecated alias). - * - * \deprecated-by igraph_biadjacency 0.10.5 - */ - -igraph_error_t igraph_incidence( - igraph_t *graph, igraph_vector_bool_t *types, - const igraph_matrix_t *incidence, igraph_bool_t directed, - igraph_neimode_t mode, igraph_bool_t multiple -) { - return igraph_biadjacency(graph, types, incidence, directed, mode, multiple); -} - /** * \function igraph_biadjacency * \brief Creates a bipartite graph from a bipartite adjacency matrix. @@ -615,63 +598,62 @@ igraph_error_t igraph_incidence( * edges between the two corresponding vertices. * * - * Note that this function can operate in two modes, depending on the + * This function can operate in two modes, depending on the * \p multiple argument. If it is \c false, then a single edge is - * created for every non-zero element in the bipartite adjacency matrix. If \p - * multiple is \c true, then the matrix elements are rounded up - * to the closest non-negative integer to get the number of edges to - * create between a pair of vertices. - * - * - * This function does not create multiple edges if \p multiple is - * \c false, but might create some if it is \c true. + * created for every non-zero element in the bipartite adjacency matrix. If + * \p multiple is \c true, then as many edges are created between two + * vertices as the corresponding matrix element. When \p multiple + * is set to \c true, matrix elements should be whole numbers. + * Otherwise their fractional part will be discarded. * * \param graph Pointer to an uninitialized graph object. * \param types Pointer to an initialized boolean vector, or a null * pointer. If not a null pointer, then the vertex types are stored * here. It is resized as needed. - * \param input The bipartite adjacency matrix that serves as an input + * \param biadjmatrix The bipartite adjacency matrix that serves as an input * to this function. * \param directed Specifies whether to create an undirected or a directed * graph. * \param mode Specifies the direction of the edges in a directed * graph. If \c IGRAPH_OUT, then edges point from vertices * of the first kind (corresponding to rows) to vertices of the - * second kind (corresponding to columns); if \c - * IGRAPH_IN, then the opposite direction is realized; if \c - * IGRAPH_ALL, then mutual edges will be created. - * \param multiple How to interpret the matrix elements. See details above. + * second kind (corresponding to columns); if \c IGRAPH_IN, + * then the opposite direction is realized; if \c IGRAPH_ALL, + * then mutual edges will be created. + * \param multiple Whether to interpret matrix entries as edge multiplicities, + * see details above. * \return Error code. * * Time complexity: O(n*m), the size of the bipartite adjacency matrix. */ igraph_error_t igraph_biadjacency( - igraph_t *graph, igraph_vector_bool_t *types, - const igraph_matrix_t *input, igraph_bool_t directed, - igraph_neimode_t mode, igraph_bool_t multiple -) { - - igraph_integer_t n1 = igraph_matrix_nrow(input); - igraph_integer_t n2 = igraph_matrix_ncol(input); - igraph_integer_t no_of_nodes = n1 + n2; + igraph_t *graph, + igraph_vector_bool_t *types, + const igraph_matrix_t *biadjmatrix, + igraph_bool_t directed, + igraph_neimode_t mode, + igraph_bool_t multiple) { + + const igraph_integer_t n1 = igraph_matrix_nrow(biadjmatrix); + const igraph_integer_t n2 = igraph_matrix_ncol(biadjmatrix); + const igraph_integer_t no_of_nodes = n1 + n2; igraph_vector_int_t edges; - igraph_integer_t i, j, k; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - if (n1 > 0 && n2 > 0 && igraph_matrix_min(input) < 0) { - IGRAPH_ERRORF( - "Bipartite adjacencey matrix elements should be non-negative, found %g.", - IGRAPH_EINVAL, igraph_matrix_min(input) - ); - } - if (multiple) { - for (i = 0; i < n1; i++) { - for (j = 0; j < n2; j++) { - igraph_integer_t elem = ceil(MATRIX(*input, i, j)); + if (n1 > 0 && n2 > 0 && igraph_matrix_min(biadjmatrix) < 0) { + IGRAPH_ERRORF( + "Bipartite adjacency matrix elements should be non-negative, found %g.", + IGRAPH_EINVAL, igraph_matrix_min(biadjmatrix) + ); + } + + for (igraph_integer_t j = 0; j < n2; j++) { + for (igraph_integer_t i = 0; i < n1; i++) { + igraph_integer_t elem = MATRIX(*biadjmatrix, i, j); igraph_integer_t from, to; if (elem == 0) { @@ -687,12 +669,12 @@ igraph_error_t igraph_biadjacency( } if (mode != IGRAPH_ALL || !directed) { - for (k = 0; k < elem; k++) { + for (igraph_integer_t k = 0; k < elem; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); } } else { - for (k = 0; k < elem; k++) { + for (igraph_integer_t k = 0; k < elem; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); @@ -704,11 +686,11 @@ igraph_error_t igraph_biadjacency( } else { - for (i = 0; i < n1; i++) { - for (j = 0; j < n2; j++) { + for (igraph_integer_t j = 0; j < n2; j++) { + for (igraph_integer_t i = 0; i < n1; i++) { igraph_integer_t from, to; - if (MATRIX(*input, i, j) != 0) { + if (MATRIX(*biadjmatrix, i, j) != 0) { if (mode == IGRAPH_IN) { from = n1 + j; to = i; @@ -734,33 +716,116 @@ igraph_error_t igraph_biadjacency( IGRAPH_CHECK(igraph_create(graph, &edges, no_of_nodes, directed)); igraph_vector_int_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); + IGRAPH_FINALLY(igraph_destroy, graph); if (types) { IGRAPH_CHECK(igraph_vector_bool_resize(types, no_of_nodes)); igraph_vector_bool_null(types); - for (i = n1; i < no_of_nodes; i++) { - VECTOR(*types)[i] = 1; + for (igraph_integer_t i = n1; i < no_of_nodes; i++) { + VECTOR(*types)[i] = true; } } IGRAPH_FINALLY_CLEAN(1); + return IGRAPH_SUCCESS; } + /** - * \function igraph_get_incidence - * \brief Convert a bipartite graph into a bipartite adjacency matrix (deprecated alias). + * \function igraph_weighted_biadjacency + * \brief Creates a bipartite graph from a weighted bipartite adjacency matrix. + * + * A bipartite (or two-mode) graph contains two types of vertices and + * edges always connect vertices of different types. A bipartite adjacency + * matrix is an \em n x \em m matrix, \em n and \em m are the number of vertices + * of the two types, respectively. Nonzero elements in the matrix denote + * edges between the two corresponding vertices. + * + * \param graph Pointer to an uninitialized graph object. + * \param types Pointer to an initialized boolean vector, or a null + * pointer. If not a null pointer, then the vertex types are stored + * here. It is resized as needed. + * \param weights Pointer to an initialized vector, the weights will be stored here. + * \param biadjmatrix The bipartite adjacency matrix that serves as an input + * to this function. + * \param directed Specifies whether to create an undirected or a directed + * graph. + * \param mode Specifies the direction of the edges in a directed + * graph. If \c IGRAPH_OUT, then edges point from vertices + * of the first kind (corresponding to rows) to vertices of the + * second kind (corresponding to columns); if \c IGRAPH_IN, + * then the opposite direction is realized; if \c IGRAPH_ALL, + * then mutual edges will be created. + * \return Error code. * - * \deprecated-by igraph_get_biadjacency 0.10.5 + * Time complexity: O(n*m), the size of the bipartite adjacency matrix. */ -igraph_error_t igraph_get_incidence(const igraph_t *graph, - const igraph_vector_bool_t *types, - igraph_matrix_t *res, - igraph_vector_int_t *row_ids, - igraph_vector_int_t *col_ids) { - return igraph_get_biadjacency(graph, types, res, row_ids, col_ids); +igraph_error_t igraph_weighted_biadjacency( + igraph_t *graph, + igraph_vector_bool_t *types, + igraph_vector_t *weights, + const igraph_matrix_t *biadjmatrix, + igraph_bool_t directed, + igraph_neimode_t mode) { + + const igraph_integer_t n1 = igraph_matrix_nrow(biadjmatrix); + const igraph_integer_t n2 = igraph_matrix_ncol(biadjmatrix); + const igraph_integer_t no_of_nodes = n1 + n2; + igraph_vector_int_t edges; + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + igraph_vector_clear(weights); + + for (igraph_integer_t j = 0; j < n2; j++) { + for (igraph_integer_t i = 0; i < n1; i++) { + igraph_real_t weight = MATRIX(*biadjmatrix, i, j); + igraph_integer_t from, to; + + if (weight != 0) { + if (mode == IGRAPH_IN) { + from = n1 + j; + to = i; + } else { + from = i; + to = n1 + j; + } + if (mode != IGRAPH_ALL || !directed) { + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, from)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); + IGRAPH_CHECK(igraph_vector_push_back(weights, weight)); + } else { + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, from)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); + IGRAPH_CHECK(igraph_vector_push_back(weights, weight)); + + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, from)); + IGRAPH_CHECK(igraph_vector_push_back(weights, weight)); + } + } + } + } + + IGRAPH_CHECK(igraph_create(graph, &edges, no_of_nodes, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + IGRAPH_FINALLY(igraph_destroy, graph); + + if (types) { + IGRAPH_CHECK(igraph_vector_bool_resize(types, no_of_nodes)); + igraph_vector_bool_null(types); + for (igraph_integer_t i = n1; i < no_of_nodes; i++) { + VECTOR(*types)[i] = true; + } + } + + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; } /** @@ -779,11 +844,14 @@ igraph_error_t igraph_get_incidence(const igraph_t *graph, * \param types Boolean vector containing the vertex types. Vertices belonging * to the first partition have type \c false, the one in the second * partition type \c true. + * \param weights A vector specifying a weight for each edge or \c NULL. + * If \c NULL, all edges are assumed to have weight 1. * \param res Pointer to an initialized matrix, the result is stored * here. An element of the matrix gives the number of edges - * (irrespectively of their direction) between the two corresponding - * vertices. The rows will correspond to vertices with type \c false, - * the columns correspond to vertices with type \c true. + * (irrespectively of their direction), or sum of edge weights, + * between the two corresponding vertices. The rows will correspond + * to vertices with type \c false, the columns correspond to vertices + * with type \c true. * \param row_ids Pointer to an initialized vector or \c NULL. * If not a null pointer, then the IDs of vertices with type \c false * are stored here, with the same ordering as the rows of the @@ -801,36 +869,43 @@ igraph_error_t igraph_get_incidence(const igraph_t *graph, igraph_error_t igraph_get_biadjacency( const igraph_t *graph, const igraph_vector_bool_t *types, + const igraph_vector_t *weights, igraph_matrix_t *res, igraph_vector_int_t *row_ids, igraph_vector_int_t *col_ids ) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t n1 = 0, n2 = 0, i; - igraph_vector_int_t perm; - igraph_integer_t p1, p2; + igraph_integer_t n1 = 0, n2 = 0; igraph_integer_t ignored_edges = 0; + igraph_vector_int_t perm; if (igraph_vector_bool_size(types) != no_of_nodes) { IGRAPH_ERRORF("Vertex type vector size (%" IGRAPH_PRId ") not equal to number of vertices (%" IGRAPH_PRId ").", IGRAPH_EINVAL, igraph_vector_bool_size(types), no_of_nodes); } - for (i = 0; i < no_of_nodes; i++) { + if (weights) { + if (igraph_vector_size(weights) != no_of_edges) { + IGRAPH_ERRORF("Edge weight vector size (%" IGRAPH_PRId ") not equal to number of edges (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, igraph_vector_size(weights), no_of_edges); + } + } + + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { n1 += VECTOR(*types)[i] == false ? 1 : 0; } n2 = no_of_nodes - n1; IGRAPH_VECTOR_INT_INIT_FINALLY(&perm, no_of_nodes); - for (i = 0, p1 = 0, p2 = n1; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0, p1 = 0, p2 = n1; i < no_of_nodes; i++) { VECTOR(perm)[i] = VECTOR(*types)[i] ? p2++ : p1++; } IGRAPH_CHECK(igraph_matrix_resize(res, n1, n2)); igraph_matrix_null(res); - for (i = 0; i < no_of_edges; i++) { + for (igraph_integer_t i = 0; i < no_of_edges; i++) { igraph_integer_t from = IGRAPH_FROM(graph, i); igraph_integer_t to = IGRAPH_TO(graph, i); igraph_integer_t from2 = VECTOR(perm)[from]; @@ -838,12 +913,13 @@ igraph_error_t igraph_get_biadjacency( if (VECTOR(*types)[from] == VECTOR(*types)[to]) { ignored_edges++; } else if (! VECTOR(*types)[from]) { - MATRIX(*res, from2, to2 - n1) += 1; + MATRIX(*res, from2, to2 - n1) += weights ? VECTOR(*weights)[i] : 1; } else { - MATRIX(*res, to2, from2 - n1) += 1; + MATRIX(*res, to2, from2 - n1) += weights ? VECTOR(*weights)[i] : 1; } } - if (ignored_edges) { + + if (ignored_edges > 0) { IGRAPH_WARNINGF("%" IGRAPH_PRId " edges running within partitions were ignored.", ignored_edges); } @@ -854,7 +930,7 @@ igraph_error_t igraph_get_biadjacency( IGRAPH_CHECK(igraph_vector_int_resize(col_ids, n2)); } if (row_ids || col_ids) { - for (i = 0; i < no_of_nodes; i++) { + for (igraph_integer_t i = 0; i < no_of_nodes; i++) { if (! VECTOR(*types)[i]) { if (row_ids) { igraph_integer_t i2 = VECTOR(perm)[i]; @@ -903,6 +979,9 @@ igraph_error_t igraph_get_biadjacency( * * Time complexity: O(|V|+|E|), linear in the number of vertices and * edges. + * + * \sa igraph_is_bipartite_coloring() do determine if all edges connect + * vertices of different types, given a specific type vector. */ igraph_error_t igraph_is_bipartite(const igraph_t *graph, @@ -961,7 +1040,9 @@ igraph_error_t igraph_is_bipartite(const igraph_t *graph, igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); char acttype = VECTOR(seen)[actnode]; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, actnode, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); for (j = 0; j < n; j++) { igraph_integer_t nei = VECTOR(neis)[j]; @@ -1032,7 +1113,6 @@ static igraph_error_t gnp_bipartite_large( IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount_estimate)); - RNG_BEGIN(); for (igraph_integer_t i = 0; i < n1; i++) { igraph_integer_t j = 0; @@ -1070,7 +1150,6 @@ static igraph_error_t gnp_bipartite_large( IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } } - RNG_END(); /* n1 + n2 has already been checked for overflow in the caller function. */ IGRAPH_CHECK(igraph_create(graph, &edges, n1 + n2, directed)); @@ -1129,11 +1208,15 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * int iter = 0; if (n1 < 0 || n2 < 0) { - IGRAPH_ERROR("Invalid number of vertices for bipartite graph.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of vertices for bipartite G(n,p) model.", IGRAPH_EINVAL); } if (p < 0.0 || p > 1.0) { - IGRAPH_ERROR("Invalid connection probability.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid connection probability for bipartite G(n,p) model.", IGRAPH_EINVAL); + } + + if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { + IGRAPH_ERROR("Invalid mode for bipartite G(n,p) model.", IGRAPH_EINVAL); } IGRAPH_SAFE_ADD(n1, n2, &n); @@ -1173,8 +1256,6 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * IGRAPH_VECTOR_INIT_FINALLY(&s, 0); IGRAPH_CHECK(igraph_vector_reserve(&s, ecount_estimate)); - RNG_BEGIN(); - last = RNG_GEOM(p); while (last < maxedges) { IGRAPH_CHECK(igraph_vector_push_back(&s, last)); @@ -1183,8 +1264,6 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } - RNG_END(); - slen = igraph_vector_size(&s); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, slen * 2)); @@ -1228,6 +1307,236 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * return IGRAPH_SUCCESS; } +/** + * \function igraph_bipartite_iea_game + * \brief Generates a random bipartite multigraph through independent edge assignment. + * + * \experimental + * + * This model generates random multigraphs with \p n1 bottom vertices, + * \p n2 top vertices and \p m edges through independent edge assignment (IEA). + * Each of the \p m edges is assigned uniformly at random to a vertex pair, + * independently of each other. + * + * + * This model does not sample multigraphs uniformly. Undirected graphs are + * generated with probability proportional to + * + * + * (prod_(i<j) A_ij !)^(-1), + * + * + * where \c A denotes the adjacency matrix. The corresponding expression for + * directed graphs is + * + * + * (prod_(i,j) A_ij !)^(-1). + * + * + * Thus the probability of all simple graphs (which only have 0s and 1s in the + * adjacency matrix) is the same, while that of non-simple ones depends on + * their edge and self-loop multiplicities. + * + * \param graph Pointer to an uninitialized igraph graph, the result + * is stored here. + * \param types Pointer to an initialized boolean vector, or a \c NULL + * pointer. If not \c NULL, then the vertex types are stored + * here. Bottom vertices come first, \p n1 of them, then \p 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 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_iea_game() for the unipartite version; + * \ref igraph_bipartite_game_gnm() to uniformly sample bipartite graphs + * with a given number of vertices and edges. + * + * Time complexity: O(|V|+|E|), linear in the number of vertices and + * edges. + */ + +igraph_error_t igraph_bipartite_iea_game( + 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; + + if (n1 < 0 || n2 < 0) { + IGRAPH_ERROR("Invalid number of vertices for bipartite IEA model.", IGRAPH_EINVAL); + } + if (m < 0 || m > IGRAPH_ECOUNT_MAX) { + IGRAPH_ERROR("Invalid number of edges for bipartite IEA model.", IGRAPH_EINVAL); + } + if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { + IGRAPH_ERROR("Invalid mode for bipartite IEA model.", IGRAPH_EINVAL); + } + + IGRAPH_SAFE_ADD(n1, n2, &n); + + if (types) { + igraph_integer_t i; + IGRAPH_CHECK(igraph_vector_bool_resize(types, n)); + igraph_vector_bool_null(types); + for (i = n1; i < n; i++) { + VECTOR(*types)[i] = true; + } + } + + if (m == 0 || n1 == 0 || n2 == 0) { + if (m > 0) { + IGRAPH_ERROR("Too many edges requested compared to the number of vertices.", IGRAPH_EINVAL); + } + IGRAPH_CHECK(igraph_empty(graph, n, directed)); + return IGRAPH_SUCCESS; + } + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); + + 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_BOOL())) { + 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); + } + + } + + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + +static igraph_error_t bipartite_gnm_multi( + igraph_t *graph, + igraph_integer_t n1, igraph_integer_t n2, igraph_integer_t m, + igraph_bool_t directed, igraph_neimode_t mode) { + + /* See igraph_erdos_renyi_game_gnm() for how the sampling works. */ + + igraph_vector_int_t edges; + igraph_integer_t n; + igraph_integer_t nrow, ncol; + igraph_integer_t last; + igraph_integer_t offset1 = 0, offset2 = n1; + + IGRAPH_SAFE_ADD(n1, n2, &n); + + /* The larger partition is associated with collumns, the smaller + * with rows. This setup helps avoid integer overflow. We swap + * n1 and n2 so that n1 is smaller. */ + if (n1 > n2) { + igraph_integer_t tmp = n1; + n1 = n2; + n2 = tmp; + + offset1 = n2; offset2 = 0; + + mode = IGRAPH_REVERSE_MODE(mode); + } + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2*m); + + if (!directed || mode != IGRAPH_ALL) { + nrow = n1; + ncol = n2; + last = ncol-1; + for (igraph_integer_t i=0; i < m; i++) { + while (true) { + igraph_integer_t r = RNG_INTEGER(0, nrow-1); + igraph_integer_t c = RNG_INTEGER(0, ncol-1); + + if (r >= n1) { + igraph_integer_t j = (r - n1) * ncol + c; + if (j >= i) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; + } else { + if (directed && mode == IGRAPH_IN) { + VECTOR(edges)[2*i] = c + offset2; + VECTOR(edges)[2*i+1] = r + offset1; + } else { + VECTOR(edges)[2*i] = r + offset1; + VECTOR(edges)[2*i+1] = c + offset2; + } + } + + last += 1; + if (last >= ncol) { + last -= ncol; + nrow++; + } + + break; + } + } + } else /* directed, mutual allowed */ { + nrow = 2*n1; + ncol = n2; + last = ncol-1; + for (igraph_integer_t i=0; i < m; i++) { + while (true) { + igraph_integer_t r = RNG_INTEGER(0, nrow-1); + igraph_integer_t c = RNG_INTEGER(0, ncol-1); + + if (r >= 2*n1) { + igraph_integer_t j = (r - 2*n1) * ncol + c; + if (j >= i) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; + } else { + if (r < n1) { + VECTOR(edges)[2*i] = r + offset1; + VECTOR(edges)[2*i+1] = c + offset2; + } else { + VECTOR(edges)[2*i] = c + offset2; + VECTOR(edges)[2*i+1] = r - n1 + offset1; + } + } + + last += 1; + if (last >= ncol) { + last -= ncol; + nrow++; + } + + break; + } + } + } + + 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. @@ -1254,6 +1563,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, @@ -1267,7 +1578,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; @@ -1275,10 +1586,13 @@ igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t * int iter = 0; if (n1 < 0 || n2 < 0) { - IGRAPH_ERROR("Invalid number of vertices for bipartite graph.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of vertices for bipartite G(n,m) model.", IGRAPH_EINVAL); } if (m < 0 || m > IGRAPH_ECOUNT_MAX) { - IGRAPH_ERROR("Invalid number of edges.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of edges for bipartite G(n,m) model.", IGRAPH_EINVAL); + } + if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { + IGRAPH_ERROR("Invalid mode for bipartite G(n,m) model.", IGRAPH_EINVAL); } IGRAPH_SAFE_ADD(n1, n2, &n); @@ -1297,7 +1611,10 @@ igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t * IGRAPH_ERROR("Too many edges requested compared to the number of vertices.", IGRAPH_EINVAL); } IGRAPH_CHECK(igraph_empty(graph, n, directed)); + } else if (multiple) { + IGRAPH_CHECK(bipartite_gnm_multi(graph, n1, n2, m, directed, mode)); } else { + igraph_integer_t i; igraph_real_t maxedges; @@ -1319,7 +1636,7 @@ igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t * IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_VECTOR_INIT_FINALLY(&s, 0); - IGRAPH_CHECK(igraph_random_sample_real(&s, 0, maxedges - 1, m)); + IGRAPH_CHECK(igraph_i_random_sample_real(&s, 0, maxedges - 1, m)); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); for (i = 0; i < m; i++) { @@ -1361,67 +1678,3 @@ igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t * return IGRAPH_SUCCESS; } - -/** - * \function igraph_bipartite_game - * \brief Generate a bipartite random graph (similar to Erdős-Rényi). - * - * This function is deprecated; use \ref igraph_bipartite_game_gnm() or - * \ref igraph_bipartite_game_gnp() instead. - * - * \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 type The type of the random graph, possible values: - * \clist - * \cli IGRAPH_ERDOS_RENYI_GNM - * G(n,m) graph, - * m edges are - * selected uniformly randomly in a graph with - * n vertices. - * \cli IGRAPH_ERDOS_RENYI_GNP - * G(n,p) graph, - * every possible edge is included in the graph with - * probability p. - * \endclist - * \param n1 The number of bottom vertices. - * \param n2 The number of top vertices. - * \param p The connection probability for G(n,p) graphs. It is - * ignored for G(n,m) graphs. - * \param m The number of edges for G(n,m) graphs. It is ignored for - * G(n,p) graphs. - * \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_bipartite_game_gnm(), \ref igraph_bipartite_game_gnp(). - * - * Time complexity: O(|V|+|E|), linear in the number of vertices and - * edges. - */ - -igraph_error_t igraph_bipartite_game(igraph_t *graph, igraph_vector_bool_t *types, - igraph_erdos_renyi_t type, - igraph_integer_t n1, igraph_integer_t n2, - igraph_real_t p, igraph_integer_t m, - igraph_bool_t directed, igraph_neimode_t mode) { - - 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); - } else { - IGRAPH_ERROR("Invalid bipartite game type.", IGRAPH_EINVAL); - } -} diff --git a/src/vendor/cigraph/src/misc/chordality.c b/src/vendor/cigraph/src/misc/chordality.c index 85056b7566a..1dcfbad9161 100644 --- a/src/vendor/cigraph/src/misc/chordality.c +++ b/src/vendor/cigraph/src/misc/chordality.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2008-2021 The igraph development team diff --git a/src/vendor/cigraph/src/misc/cocitation.c b/src/vendor/cigraph/src/misc/cocitation.c index 9657162ec58..5545f3737b3 100644 --- a/src/vendor/cigraph/src/misc/cocitation.c +++ b/src/vendor/cigraph/src/misc/cocitation.c @@ -178,7 +178,7 @@ igraph_error_t igraph_similarity_inverse_log_weighted(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&weights, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), mode0, true)); + IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), mode0, IGRAPH_LOOPS)); for (igraph_integer_t i = 0; i < no_of_nodes; i++) { VECTOR(weights)[i] = VECTOR(degrees)[i]; if (VECTOR(weights)[i] > 1) { @@ -234,7 +234,7 @@ static igraph_error_t igraph_i_cocitation_real(const igraph_t *graph, igraph_mat const igraph_real_t weight = weights ? VECTOR(*weights)[from] : 1; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, from, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, from, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); const igraph_integer_t nei_count = igraph_vector_int_size(&neis); for (i = 0; i < nei_count - 1; i++) { @@ -287,9 +287,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 from The vertex IDs of the first set of vertices of the + * pairs for which the calculation will be done. + * \param 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 @@ -323,27 +325,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)) { @@ -352,18 +354,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)); @@ -377,8 +379,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; @@ -563,7 +565,7 @@ igraph_error_t igraph_similarity_jaccard_es(const igraph_t *graph, igraph_vector igraph_vector_int_t pairs; IGRAPH_VECTOR_INT_INIT_FINALLY(&pairs, 0); - IGRAPH_CHECK(igraph_edges(graph, es, &pairs)); + IGRAPH_CHECK(igraph_edges(graph, es, &pairs, 0)); IGRAPH_CHECK(igraph_similarity_jaccard_pairs(graph, res, &pairs, mode, loops)); igraph_vector_int_destroy(&pairs); IGRAPH_FINALLY_CLEAN(1); @@ -583,9 +585,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 @@ -619,10 +623,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/coloring.c b/src/vendor/cigraph/src/misc/coloring.c index b88da7e31b2..e62c467c18d 100644 --- a/src/vendor/cigraph/src/misc/coloring.c +++ b/src/vendor/cigraph/src/misc/coloring.c @@ -51,7 +51,7 @@ static igraph_error_t igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, igraph_vector_int_t degree; IGRAPH_VECTOR_INT_INIT_FINALLY(°ree, 0); - IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_ALL, false)); + IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_ALL, IGRAPH_NO_LOOPS)); vertex = igraph_vector_int_which_max(°ree); maxdeg = VECTOR(degree)[vertex]; @@ -79,7 +79,7 @@ static igraph_error_t igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, * At the beginning, all vertices are set as "uncolored", see the vector_int_fill() call above. * Colors will be decremented to start at 0 later. */ while (true) { - IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, vertex, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, vertex, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); igraph_integer_t nei_count = igraph_vector_int_size(&neighbors); /* Colour current vertex by finding the smallest available non-0 color. @@ -294,7 +294,10 @@ static igraph_error_t igraph_i_vertex_coloring_dsatur( * * \return Error code. * - * \example examples/simple/igraph_coloring.c + * \sa igraph_is_vertex_coloring() to check if a coloring is valid, i.e. if all + * edges connect vertices of different colors. + * + * \example examples/simple/coloring.c */ igraph_error_t igraph_vertex_coloring_greedy(const igraph_t *graph, igraph_vector_int_t *colors, igraph_coloring_greedy_t heuristic) { switch (heuristic) { @@ -306,3 +309,215 @@ igraph_error_t igraph_vertex_coloring_greedy(const igraph_t *graph, igraph_vecto IGRAPH_ERROR("Invalid heuristic for greedy vertex coloring.", IGRAPH_EINVAL); } } + +/** + * \function igraph_is_vertex_coloring + * \brief Checks whether a vertex coloring is valid. + * + * \experimental + * + * This function checks whether the given vertex type/color assignment is a valid + * vertex coloring, i.e., no two adjacent vertices have the same color. + * Self-loops are ignored. + * + * \param graph The input graph. + * \param types The vertex types/colors as an integer vector. + * \param res Pointer to a boolean, the result is stored here. + * \return Error code. + * + * Time complexity: O(|E|), linear in the number of edges. + */ +igraph_error_t igraph_is_vertex_coloring( + const igraph_t *graph, + const igraph_vector_int_t *types, + igraph_bool_t *res) { + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_integer_t ecount = igraph_ecount(graph); + int iter = 0; + + if (igraph_vector_int_size(types) != vcount) { + IGRAPH_ERROR("Invalid vertex type vector length.", IGRAPH_EINVAL); + } + + *res = true; + + for (igraph_integer_t e = 0; e < ecount; e++) { + igraph_integer_t from = IGRAPH_FROM(graph, e); + igraph_integer_t to = IGRAPH_TO(graph, e); + + /* Skip self-loops */ + if (from == to) { + continue; + } + + if (VECTOR(*types)[from] == VECTOR(*types)[to]) { + *res = false; + break; + } + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 10); + } + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_is_bipartite_coloring + * \brief Checks whether a bipartite vertex coloring is valid. + * + * \experimental + * + * This function checks whether the given vertex type assignment is a valid + * bipartite coloring, i.e., no two adjacent vertices have the same type. + * Additionally, for directed graphs, it determines the mode of edge directions. + * Self-loops are ignored. + * + * \param graph The input graph. + * \param types The vertex types as a boolean vector. + * \param res Pointer to a boolean, the result is stored here. + * \param mode Pointer to store the edge direction mode. Can be \c NULL if not needed. + * If all edges go from false to true vertices, \c IGRAPH_OUT is returned. + * If all edges go from true to false vertices, \c IGRAPH_IN is returned. + * If edges go in both directions or graph is undirected, \c IGRAPH_ALL is returned. + * \return Error code. + * + * Time complexity: O(|E|), linear in the number of edges. + * + * \sa igraph_is_bipartite() to determine whether a graph is bipartite, + * i.e. 2-colorable, and find such a coloring. + */ +igraph_error_t igraph_is_bipartite_coloring( + const igraph_t *graph, + const igraph_vector_bool_t *types, + igraph_bool_t *res, + igraph_neimode_t *mode) { + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_integer_t ecount = igraph_ecount(graph); + int iter = 0; + + if (igraph_vector_bool_size(types) != vcount) { + IGRAPH_ERROR("Invalid vertex type vector length.", IGRAPH_EINVAL); + } + + *res = true; + if (mode) { + *mode = IGRAPH_ALL; + } + + igraph_bool_t directed = igraph_is_directed(graph); + igraph_bool_t has_false_to_true = false; + igraph_bool_t has_true_to_false = false; + + for (igraph_integer_t e = 0; e < ecount; e++) { + igraph_integer_t from = IGRAPH_FROM(graph, e); + igraph_integer_t to = IGRAPH_TO(graph, e); + + /* Skip self-loops */ + if (from == to) { + continue; + } + + igraph_bool_t from_type = VECTOR(*types)[from]; + igraph_bool_t to_type = VECTOR(*types)[to]; + + /* Check if adjacent vertices have the same type */ + if (from_type == to_type) { + *res = false; + break; + } + + /* Track edge directions for directed graphs */ + if (directed && mode) { + if (!from_type && to_type) { + has_false_to_true = true; + } else if (from_type && !to_type) { + has_true_to_false = true; + } + } + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 10); + } + + /* Determine the mode for directed graphs */ + if (*res && directed && mode) { + if (has_false_to_true && !has_true_to_false) { + *mode = IGRAPH_OUT; + } else if (!has_false_to_true && has_true_to_false) { + *mode = IGRAPH_IN; + } else { + *mode = IGRAPH_ALL; + } + } + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_is_edge_coloring + * \brief Checks whether an edge coloring is valid. + * + * \experimental + * + * This function checks whether the given edge color assignment is a valid + * edge coloring, i.e., no two adjacent edges have the same color. + * + * Note that this function does not consider self-edges (loops) as being + * adjacent to themselves, so graphs with self-loops may still be considered + * to have a valid edge coloring. + * + * \param graph The input graph. + * \param types The edge colors as an integer vector. + * \param res Pointer to a boolean, the result is stored here. + * \return Error code. + * + * Time complexity: O(|V|*d*log(d)), where d is the maximum degree. + */ +igraph_error_t igraph_is_edge_coloring( + const igraph_t *graph, + const igraph_vector_int_t *types, + igraph_bool_t *res) { + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_integer_t ecount = igraph_ecount(graph); + igraph_vector_int_t edges, edge_colors; + int iter = 0; + + if (igraph_vector_int_size(types) != ecount) { + IGRAPH_ERROR("Invalid edge type vector length.", IGRAPH_EINVAL); + } + + /* Be optimistic */ + *res = true; + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_VECTOR_INT_INIT_FINALLY(&edge_colors, 0); + + /* For each vertex, check that all incident edges have different colors */ + for (igraph_integer_t v = 0; v < vcount; v++) { + IGRAPH_CHECK(igraph_incident(graph, &edges, v, IGRAPH_ALL, IGRAPH_LOOPS_ONCE)); + + /* Get sorted edge color list */ + IGRAPH_CHECK(igraph_vector_int_index(types, &edge_colors, &edges)); + igraph_vector_int_sort(&edge_colors); + + /* Look for consecutive duplicates in edge color list */ + igraph_integer_t edge_color_count = igraph_vector_int_size(&edge_colors); + for (igraph_integer_t i = 0; i < edge_color_count - 1; i++) { + if (VECTOR(edge_colors)[i] == VECTOR(edge_colors)[i + 1]) { + *res = false; + goto done; + } + } + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 7); + } + +done: + igraph_vector_int_destroy(&edge_colors); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(2); + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/misc/conversion.c b/src/vendor/cigraph/src/misc/conversion.c index 74ec04d2b84..e277652f07d 100644 --- a/src/vendor/cigraph/src/misc/conversion.c +++ b/src/vendor/cigraph/src/misc/conversion.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -302,33 +301,6 @@ igraph_error_t igraph_get_adjacency_sparse( #undef WEIGHT_OF -/** - * \function igraph_get_sparsemat - * \brief Converts an igraph graph to a sparse matrix (deprecated). - * - * If the graph is undirected, then a symmetric matrix is created. - * - * - * This function is deprecated in favour of \ref igraph_get_adjacency_sparse(), - * but does not work in an identical way. This function takes an \em uninitialized - * \c igraph_sparsemat_t while \ref igraph_get_adjacency_sparse() takes - * an already initialized one. - * - * \param graph The input graph. - * \param res Pointer to an \em uninitialized sparse matrix. The result - * will be stored here. - * \return Error code. - * - * \deprecated-by igraph_get_adjacency_sparse 0.10.0 - */ - -igraph_error_t igraph_get_sparsemat(const igraph_t *graph, igraph_sparsemat_t *res) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t nzmax = igraph_is_directed(graph) ? no_of_edges : 2*no_of_edges; - IGRAPH_CHECK(igraph_sparsemat_init(res, no_of_nodes, no_of_nodes, nzmax)); - return igraph_get_adjacency_sparse(graph, res, IGRAPH_GET_ADJACENCY_BOTH, NULL, IGRAPH_LOOPS_ONCE); -} /** * \ingroup conversion @@ -353,37 +325,7 @@ igraph_error_t igraph_get_sparsemat(const igraph_t *graph, igraph_sparsemat_t *r */ igraph_error_t igraph_get_edgelist(const igraph_t *graph, igraph_vector_int_t *res, igraph_bool_t bycol) { - - igraph_eit_t edgeit; - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t vptr = 0; - igraph_integer_t from, to; - - IGRAPH_CHECK(igraph_vector_int_resize(res, no_of_edges * 2)); - IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), - &edgeit)); - IGRAPH_FINALLY(igraph_eit_destroy, &edgeit); - - if (bycol) { - while (!IGRAPH_EIT_END(edgeit)) { - igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &from, &to); - VECTOR(*res)[vptr] = from; - VECTOR(*res)[vptr + no_of_edges] = to; - vptr++; - IGRAPH_EIT_NEXT(edgeit); - } - } else { - while (!IGRAPH_EIT_END(edgeit)) { - igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &from, &to); - VECTOR(*res)[vptr++] = from; - VECTOR(*res)[vptr++] = to; - IGRAPH_EIT_NEXT(edgeit); - } - } - - igraph_eit_destroy(&edgeit); - IGRAPH_FINALLY_CLEAN(1); - return IGRAPH_SUCCESS; + return igraph_edges(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), res, bycol); } /** @@ -439,8 +381,6 @@ igraph_error_t igraph_to_directed(igraph_t *graph, IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0)); if (mode == IGRAPH_TO_DIRECTED_RANDOM) { - RNG_BEGIN(); - for (igraph_integer_t i=0; i < no_of_edges; ++i) { if (RNG_INTEGER(0,1)) { igraph_integer_t temp = VECTOR(edges)[2*i]; @@ -448,8 +388,6 @@ igraph_error_t igraph_to_directed(igraph_t *graph, VECTOR(edges)[2*i+1] = temp; } } - - RNG_END(); } else if (mode == IGRAPH_TO_DIRECTED_ACYCLIC) { /* Currently, the endpoints of undirected edges are ordered in the internal graph datastructure, i.e. it is always true that from < to. @@ -471,8 +409,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); @@ -504,8 +441,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); @@ -605,8 +541,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; @@ -628,8 +563,8 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, igraph_integer_t n_out, n_in; igraph_integer_t p1 = -1, p2 = -1; igraph_integer_t e1 = 0, e2 = 0, n1 = 0, n2 = 0, last; - IGRAPH_CHECK(igraph_incident(graph, &outadj, i, IGRAPH_OUT)); - IGRAPH_CHECK(igraph_incident(graph, &inadj, i, IGRAPH_IN)); + IGRAPH_CHECK(igraph_incident(graph, &outadj, i, IGRAPH_OUT, IGRAPH_LOOPS)); + IGRAPH_CHECK(igraph_incident(graph, &inadj, i, IGRAPH_IN, IGRAPH_LOOPS)); n_out = igraph_vector_int_size(&outadj); n_in = igraph_vector_int_size(&inadj); @@ -703,8 +638,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; @@ -743,10 +677,8 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, igraph_integer_t n_out, n_in; igraph_integer_t p1 = -1, p2 = -1; igraph_integer_t e1 = 0, e2 = 0, n1 = 0, n2 = 0; - IGRAPH_CHECK(igraph_incident(graph, &outadj, i, - IGRAPH_OUT)); - IGRAPH_CHECK(igraph_incident(graph, &inadj, i, - IGRAPH_IN)); + IGRAPH_CHECK(igraph_incident(graph, &outadj, i, IGRAPH_OUT, IGRAPH_LOOPS)); + IGRAPH_CHECK(igraph_incident(graph, &inadj, i, IGRAPH_IN, IGRAPH_LOOPS)); n_out = igraph_vector_int_size(&outadj); n_in = igraph_vector_int_size(&inadj); @@ -793,8 +725,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; @@ -827,19 +758,29 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, * \brief Stochastic adjacency matrix of a graph. * * Stochastic matrix of a graph. The stochastic matrix of a graph is - * its adjacency matrix, normalized row-wise or column-wise, such that - * the sum of each row (or column) is one. + * its adjacency matrix, normalized row-wise (or column-wise), such that + * the sum of each row (or column) is one. The row-wise normalized matrix + * is also called a \em right-stochastic and contains the transition + * probabilities of a random walk that follows edge directions in a directed + * graph. The column-wise normalized matrix is called \em left-stochastic and + * is related to random walks moving against edge directions. + * + * + * When the out-degree (or in-degree) of a vertex is zero, the corresponding + * row (or column) of the row-wise (or column-wise) normalized stochastic + * matrix will be zero. * * \param graph The input graph. * \param res Pointer to an initialized matrix, the result is stored here. * It will be resized as needed. - * \param column_wise Whether to normalize column-wise. + * \param column_wise If \c false, row-wise normalization is used. + * If \c true, column-wise normalization is used. * \param weights An optional vector containing the weight of each edge * in the graph. Supply a null pointer here to make all edges have * the same weight of 1. * \return Error code. * - * Time complexity: O(|V||V|), |V| is the number of vertices in the graph. + * Time complexity: O(|V|^2), |V| is the number of vertices in the graph. * * \sa \ref igraph_get_stochastic_sparse(), the sparse version of this * function. @@ -852,7 +793,7 @@ igraph_error_t igraph_get_stochastic( igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); - igraph_integer_t i, from, to; + igraph_integer_t from, to; igraph_vector_t sums; igraph_real_t sum; @@ -862,25 +803,29 @@ igraph_error_t igraph_get_stochastic( IGRAPH_VECTOR_INIT_FINALLY(&sums, no_of_nodes); if (directed) { + /* Directed */ + IGRAPH_CHECK(igraph_strength( graph, &sums, igraph_vss_all(), column_wise ? IGRAPH_IN : IGRAPH_OUT, - /* loops = */ true, weights + IGRAPH_LOOPS, weights )); - for (i = 0; i < no_of_edges; i++) { + for (igraph_integer_t i = 0; i < no_of_edges; i++) { from = IGRAPH_FROM(graph, i); to = IGRAPH_TO(graph, i); sum = VECTOR(sums)[column_wise ? to : from]; MATRIX(*res, from, to) += WEIGHT_OF(i) / sum; } } else { + /* Undirected */ + IGRAPH_CHECK(igraph_strength( graph, &sums, igraph_vss_all(), IGRAPH_ALL, - /* loops = */ true, weights + IGRAPH_LOOPS, weights )); - for (i = 0; i < no_of_edges; i++) { + for (igraph_integer_t i = 0; i < no_of_edges; i++) { from = IGRAPH_FROM(graph, i); to = IGRAPH_TO(graph, i); MATRIX(*res, from, to) += WEIGHT_OF(i) / VECTOR(sums)[column_wise ? to : from]; @@ -900,14 +845,14 @@ igraph_error_t igraph_get_stochastic( * \function igraph_get_stochastic_sparse * \brief The stochastic adjacency matrix of a graph. * - * Stochastic matrix of a graph. The stochastic matrix of a graph is - * its adjacency matrix, normalized row-wise or column-wise, such that - * the sum of each row (or column) is one. + * Stochastic matrix of a graph in sparse format. See \ref igraph_get_stochastic() + * for the information on stochastic matrices. * * \param graph The input graph. * \param res Pointer to an \em initialized sparse matrix, the * result is stored here. The matrix will be resized as needed. - * \param column_wise Whether to normalize column-wise. + * \param column_wise If \c false, row-wise normalization is used. + * If \c true, column-wise normalization is used. * \param weights An optional vector containing the weight of each edge * in the graph. Supply a null pointer here to make all edges have * the same weight of 1. @@ -926,46 +871,15 @@ igraph_error_t igraph_get_stochastic_sparse( IGRAPH_CHECK(igraph_get_adjacency_sparse(graph, res, IGRAPH_GET_ADJACENCY_BOTH, weights, IGRAPH_LOOPS_TWICE)); if (column_wise) { - IGRAPH_CHECK(igraph_sparsemat_normalize_cols(res, /* allow_zeros = */ false)); + IGRAPH_CHECK(igraph_sparsemat_normalize_cols(res, /* allow_zeros = */ true)); } else { - IGRAPH_CHECK(igraph_sparsemat_normalize_rows(res, /* allow_zeros = */ false)); + IGRAPH_CHECK(igraph_sparsemat_normalize_rows(res, /* allow_zeros = */ true)); } return IGRAPH_SUCCESS; } -/** - * \function igraph_get_stochastic_sparsemat - * \brief Stochastic adjacency matrix of a graph (deprecated). - * - * This function is deprecated in favour of \ref igraph_get_stochastic_sparse(), - * but does not work in an identical way. This function takes an \em uninitialized - * \c igraph_sparsemat_t while \ref igraph_get_stochastic_sparse() takes - * an already initialized one. - * - * \param graph The input graph. - * \param res Pointer to an \em uninitialized sparse matrix, the - * result is stored here. The matrix will be resized as needed. - * \param column_wise Whether to normalize column-wise. For undirected - * graphs this argument does not have any effect. - * \return Error code. - * - * \deprecated-by igraph_get_stochastic_sparse 0.10.0 - */ - -igraph_error_t igraph_get_stochastic_sparsemat(const igraph_t *graph, - igraph_sparsemat_t *res, - igraph_bool_t column_wise) { - - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t nzmax = igraph_is_directed(graph) ? no_of_edges : 2*no_of_edges; - IGRAPH_CHECK(igraph_sparsemat_init(res, no_of_nodes, no_of_nodes, nzmax)); - return igraph_get_stochastic_sparse(graph, res, column_wise, NULL); -} - - /** * \ingroup conversion * \function igraph_to_prufer @@ -1031,7 +945,9 @@ igraph_error_t igraph_to_prufer(const igraph_t *graph, igraph_vector_int_t* pruf VECTOR(degrees)[leaf] = 0; /* mark leaf v as deleted */ - IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, leaf, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neighbors, leaf, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); /* Find the unique remaining neighbor of the leaf */ neighbor_count = igraph_vector_int_size(&neighbors); diff --git a/src/vendor/cigraph/src/misc/cycle_bases.c b/src/vendor/cigraph/src/misc/cycle_bases.c index 01732a8163e..6ba87fd04a2 100644 --- a/src/vendor/cigraph/src/misc/cycle_bases.c +++ b/src/vendor/cigraph/src/misc/cycle_bases.c @@ -348,7 +348,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/degree_sequence.cpp b/src/vendor/cigraph/src/misc/degree_sequence.cpp index a3c27a6dda6..2aa829bb23a 100644 --- a/src/vendor/cigraph/src/misc/degree_sequence.cpp +++ b/src/vendor/cigraph/src/misc/degree_sequence.cpp @@ -21,15 +21,13 @@ #include "core/exceptions.h" #include "math/safe_intop.h" +#include "misc/graphicality.h" #include #include #include #include -#define IGRAPH_I_MULTI_EDGES_SW 0x02 /* 010, more than one edge allowed between distinct vertices */ -#define IGRAPH_I_MULTI_LOOPS_SW 0x04 /* 100, more than one self-loop allowed on the same vertex */ - /******************************/ /***** Helper constructs ******/ /******************************/ diff --git a/src/vendor/cigraph/src/misc/embedding.c b/src/vendor/cigraph/src/misc/embedding.c index 732f67e667d..74a60683fac 100644 --- a/src/vendor/cigraph/src/misc/embedding.c +++ b/src/vendor/cigraph/src/misc/embedding.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2013 Gabor Csardi @@ -29,8 +28,6 @@ #include "igraph_random.h" #include "igraph_structural.h" -#include "core/math.h" - #include typedef struct { @@ -721,11 +718,9 @@ static igraph_error_t igraph_i_spectral_embedding(const igraph_t *graph, /* We provide a random start vector to ARPACK on our own to ensure that * we use igraph's RNG and not the one from ARPACK (which relies on LAPACK) */ - RNG_BEGIN(); for (i = 0; i < vc; i++) { MATRIX(*X, i, 0) = RNG_UNIF(-1, 1); } - RNG_END(); IGRAPH_CHECK(igraph_arpack_rssolve(callback, &data, options, 0, &tmpD, X)); @@ -940,7 +935,7 @@ static igraph_error_t igraph_i_lse_und(const igraph_t *graph, } IGRAPH_VECTOR_INIT_FINALLY(°, 0); - IGRAPH_CHECK(igraph_strength(graph, °, igraph_vss_all(), IGRAPH_ALL, /*loops=*/ 1, weights)); + IGRAPH_CHECK(igraph_strength(graph, °, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, weights)); switch (type) { case IGRAPH_EMBEDDING_D_A: @@ -993,8 +988,8 @@ static igraph_error_t igraph_i_lse_dir(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(°_in, n); IGRAPH_VECTOR_INIT_FINALLY(°_out, n); - IGRAPH_CHECK(igraph_strength(graph, °_in, igraph_vss_all(), IGRAPH_IN, /*loops=*/ 1, weights)); - IGRAPH_CHECK(igraph_strength(graph, °_out, igraph_vss_all(), IGRAPH_OUT, /*loops=*/ 1, weights)); + IGRAPH_CHECK(igraph_strength(graph, °_in, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS, weights)); + IGRAPH_CHECK(igraph_strength(graph, °_out, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, weights)); for (i = 0; i < n; i++) { VECTOR(deg_in)[i] = 1.0 / sqrt(VECTOR(deg_in)[i]); diff --git a/src/vendor/cigraph/src/misc/feedback_arc_set.c b/src/vendor/cigraph/src/misc/feedback_arc_set.c index 2bf8a0c2580..03dd6ee6b1b 100644 --- a/src/vendor/cigraph/src/misc/feedback_arc_set.c +++ b/src/vendor/cigraph/src/misc/feedback_arc_set.c @@ -26,7 +26,6 @@ #include "igraph_interface.h" #include "igraph_memory.h" #include "igraph_stack.h" -#include "igraph_topology.h" #include "igraph_vector.h" #include "igraph_vector_list.h" #include "igraph_visitor.h" @@ -125,7 +124,7 @@ static igraph_error_t igraph_i_find_cycle(const igraph_t *graph, PATH_PUSH(va, ea); IGRAPH_CHECK(igraph_stack_int_push(&stack, -1)); - IGRAPH_CHECK(igraph_incident(graph, &inc, va, mode)); + IGRAPH_CHECK(igraph_incident(graph, &inc, va, mode, IGRAPH_LOOPS)); igraph_integer_t n = igraph_vector_int_size(&inc); for (igraph_integer_t i=0; i < n; i++) { igraph_integer_t eb = VECTOR(inc)[i]; @@ -449,12 +448,12 @@ igraph_error_t igraph_i_feedback_arc_set_undirected(const igraph_t *graph, igrap IGRAPH_CHECK(igraph_vector_init_copy(&vcopy, weights)); IGRAPH_FINALLY(igraph_vector_destroy, &vcopy); igraph_vector_scale(&vcopy, -1); - IGRAPH_CHECK(igraph_minimum_spanning_tree(graph, &edges, &vcopy)); + IGRAPH_CHECK(igraph_minimum_spanning_tree(graph, &edges, &vcopy, IGRAPH_MST_AUTOMATIC)); igraph_vector_destroy(&vcopy); IGRAPH_FINALLY_CLEAN(1); } else { /* Any spanning tree will do */ - IGRAPH_CHECK(igraph_minimum_spanning_tree(graph, &edges, 0)); + IGRAPH_CHECK(igraph_minimum_spanning_tree(graph, &edges, NULL, IGRAPH_MST_AUTOMATIC)); } /* Now we have a bunch of edges that constitute a spanning forest. We have @@ -481,7 +480,7 @@ igraph_error_t igraph_i_feedback_arc_set_undirected(const igraph_t *graph, igrap IGRAPH_VECTOR_INIT_FINALLY(°rees, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&roots, no_of_nodes); IGRAPH_CHECK(igraph_strength(graph, °rees, igraph_vss_all(), - IGRAPH_ALL, /* loops */ false, weights)); + IGRAPH_ALL, IGRAPH_NO_LOOPS, weights)); IGRAPH_CHECK(igraph_vector_sort_ind(°rees, &roots, IGRAPH_DESCENDING)); IGRAPH_CHECK(igraph_bfs(graph, @@ -537,12 +536,12 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec IGRAPH_VECTOR_INIT_FINALLY(&instrengths, no_of_nodes); IGRAPH_VECTOR_INIT_FINALLY(&outstrengths, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, &indegrees, igraph_vss_all(), IGRAPH_IN, false)); - IGRAPH_CHECK(igraph_degree(graph, &outdegrees, igraph_vss_all(), IGRAPH_OUT, false)); + IGRAPH_CHECK(igraph_degree(graph, &indegrees, igraph_vss_all(), IGRAPH_IN, IGRAPH_NO_LOOPS)); + IGRAPH_CHECK(igraph_degree(graph, &outdegrees, igraph_vss_all(), IGRAPH_OUT, IGRAPH_NO_LOOPS)); if (weights) { - IGRAPH_CHECK(igraph_strength(graph, &instrengths, igraph_vss_all(), IGRAPH_IN, false, weights)); - IGRAPH_CHECK(igraph_strength(graph, &outstrengths, igraph_vss_all(), IGRAPH_OUT, false, weights)); + IGRAPH_CHECK(igraph_strength(graph, &instrengths, igraph_vss_all(), IGRAPH_IN, IGRAPH_NO_LOOPS, weights)); + IGRAPH_CHECK(igraph_strength(graph, &outstrengths, igraph_vss_all(), IGRAPH_OUT, IGRAPH_NO_LOOPS, weights)); } else { for (igraph_integer_t u = 0; u < no_of_nodes; u++) { VECTOR(instrengths)[u] = VECTOR(indegrees)[u]; @@ -580,7 +579,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Exclude the node from further searches */ VECTOR(indegrees)[u] = VECTOR(outdegrees)[u] = -1; /* Get the neighbors and decrease their degrees */ - IGRAPH_CHECK(igraph_incident(graph, &neis, u, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &neis, u, IGRAPH_OUT, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < neis_size; i++) { const igraph_integer_t eid = VECTOR(neis)[i]; @@ -611,7 +610,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Exclude the node from further searches */ VECTOR(indegrees)[u] = VECTOR(outdegrees)[u] = -1; /* Get the neighbors and decrease their degrees */ - IGRAPH_CHECK(igraph_incident(graph, &neis, u, IGRAPH_IN)); + IGRAPH_CHECK(igraph_incident(graph, &neis, u, IGRAPH_IN, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < neis_size; i++) { const igraph_integer_t eid = VECTOR(neis)[i]; @@ -647,7 +646,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Remove vertex v */ VECTOR(ordering)[v] = order_next_pos++; /* Remove outgoing edges */ - IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_OUT, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < neis_size; i++) { const igraph_integer_t eid = VECTOR(neis)[i]; @@ -663,7 +662,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec } } /* Remove incoming edges */ - IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_IN)); + IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_IN, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < neis_size; i++) { const igraph_integer_t eid = VECTOR(neis)[i]; @@ -725,7 +724,9 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec for (igraph_integer_t i = 0; i < no_of_nodes; i++) { igraph_integer_t from = VECTOR(ranks)[i]; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, from, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, from, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); neis_size = igraph_vector_int_size(&neis); for (igraph_integer_t j = 0; j < neis_size; j++) { igraph_integer_t to = VECTOR(neis)[j]; @@ -1273,7 +1274,7 @@ igraph_error_t igraph_i_feedback_vertex_set_ip_cg( /* Add as many vertex-disjoint cycles at once as possible. */ while (true) { for (int i=0; i < cycle_size; i++) { - IGRAPH_CHECK(igraph_incident(graph, &incident, VECTOR(cycle)[i], IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &incident, VECTOR(cycle)[i], IGRAPH_ALL, IGRAPH_LOOPS)); const igraph_integer_t incident_size = igraph_vector_int_size(&incident); for (igraph_integer_t j = 0; j < incident_size; j++) { igraph_integer_t eid = VECTOR(incident)[j]; @@ -1303,7 +1304,7 @@ igraph_error_t igraph_i_feedback_vertex_set_ip_cg( igraph_integer_t i = VAR_TO_ID(j); IGRAPH_CHECK(igraph_vector_int_push_back(result, i)); - IGRAPH_CHECK(igraph_incident(graph, &incident, i, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &incident, i, IGRAPH_ALL, IGRAPH_LOOPS)); const igraph_integer_t incident_size = igraph_vector_int_size(&incident); for (igraph_integer_t k = 0; k < incident_size; k++) { diff --git a/src/vendor/cigraph/src/misc/feedback_arc_set.h b/src/vendor/cigraph/src/misc/feedback_arc_set.h index 447405cb81d..e47a03d8113 100644 --- a/src/vendor/cigraph/src/misc/feedback_arc_set.h +++ b/src/vendor/cigraph/src/misc/feedback_arc_set.h @@ -23,7 +23,7 @@ #include "igraph_datatype.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_feedback_arc_set_eades( const igraph_t *graph, igraph_vector_int_t *result, @@ -47,6 +47,6 @@ igraph_error_t igraph_i_feedback_vertex_set_ip_cg( const igraph_t *graph, igraph_vector_int_t *result, const igraph_vector_t *weights); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/misc/graphicality.c b/src/vendor/cigraph/src/misc/graphicality.c index 8cc3f343b9a..7dffa73cd2b 100644 --- a/src/vendor/cigraph/src/misc/graphicality.c +++ b/src/vendor/cigraph/src/misc/graphicality.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2020 The igraph development team @@ -20,8 +18,7 @@ #include "igraph_graphicality.h" -#define IGRAPH_I_MULTI_EDGES_SW 0x02 /* 010, more than one edge allowed between distinct vertices */ -#define IGRAPH_I_MULTI_LOOPS_SW 0x04 /* 100, more than one self-loop allowed on the same vertex */ +#include "misc/graphicality.h" static igraph_error_t igraph_i_is_graphical_undirected_multi_loops(const igraph_vector_int_t *degrees, igraph_bool_t *res); static igraph_error_t igraph_i_is_graphical_undirected_loopless_multi(const igraph_vector_int_t *degrees, igraph_bool_t *res); diff --git a/src/vendor/cigraph/src/misc/graphicality.h b/src/vendor/cigraph/src/misc/graphicality.h new file mode 100644 index 00000000000..c200e32c8a4 --- /dev/null +++ b/src/vendor/cigraph/src/misc/graphicality.h @@ -0,0 +1,27 @@ +/* + IGraph library. + Copyright (C) 2025 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 . +*/ + +#ifndef IGRAPH_MISC_GRAPHICALITY_H +#define IGRAPH_MISC_GRAPHICALITY_H + +#include "igraph_graphicality.h" + +#define IGRAPH_I_MULTI_EDGES_SW 0x02 /* 010, more than one edge allowed between distinct vertices */ +#define IGRAPH_I_MULTI_LOOPS_SW 0x04 /* 100, more than one self-loop allowed on the same vertex */ + +#endif /* IGRAPH_MISC_GRAPHICALITY_H */ diff --git a/src/vendor/cigraph/src/misc/matching.c b/src/vendor/cigraph/src/misc/matching.c index 6f2190943b2..bab4f61f906 100644 --- a/src/vendor/cigraph/src/misc/matching.c +++ b/src/vendor/cigraph/src/misc/matching.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2012 Tamas Nepusz @@ -34,24 +32,11 @@ /* #define MATCHING_DEBUG */ -#ifdef _MSC_VER -/* MSVC does not support variadic macros */ -#include -static void debug(const char* fmt, ...) { - va_list args; - va_start(args, fmt); -#ifdef MATCHING_DEBUG - vfprintf(stderr, fmt, args); -#endif - va_end(args); -} -#else #ifdef MATCHING_DEBUG #define debug(...) fprintf(stderr, __VA_ARGS__) #else #define debug(...) #endif -#endif /** * \function igraph_is_matching @@ -188,8 +173,9 @@ igraph_error_t igraph_is_maximal_matching(const igraph_t *graph, continue; } - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, - IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, i, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); for (j = 0; j < n; j++) { if (VECTOR(*matching)[VECTOR(neis)[j]] == -1) { @@ -369,8 +355,9 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted( if (MATCHED(i)) { continue; } - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, - IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, i, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); for (j = 0; j < n; j++) { k = VECTOR(neis)[j]; @@ -416,8 +403,9 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted( debug("Considering vertex %ld\n", v); /* Line 5: find row u among the neighbors of v s.t. label(u) is minimal */ - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, - IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); for (i = 0; i < n; i++) { if (VECTOR(labels)[VECTOR(neis)[i]] < label_u) { @@ -498,8 +486,9 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted_relabel( igraph_integer_t v = igraph_dqueue_int_pop(&q); igraph_integer_t w; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, - IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, v, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); for (j = 0; j < n; j++) { diff --git a/src/vendor/cigraph/src/misc/microscopic_update.c b/src/vendor/cigraph/src/misc/microscopic_update.c deleted file mode 100644 index 0cced87d827..00000000000 --- a/src/vendor/cigraph/src/misc/microscopic_update.c +++ /dev/null @@ -1,1209 +0,0 @@ -/* -*- mode: C -*- */ -/* - Microscopic update rules for dealing with agent-level strategy revision. - Copyright (C) 2011 Minh Van Nguyen - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#include "igraph_microscopic_update.h" - -#include "igraph_iterators.h" -#include "igraph_interface.h" -#include "igraph_random.h" -#include "igraph_error.h" - -/** - * Internal use only. - * Compute the cumulative proportionate values of a vector. The vector is - * assumed to hold values associated with edges. - * - * \param graph The graph object representing the game network. No error - * checks will be performed on this graph. You are responsible for - * ensuring that this is a valid graph for the particular - * microscopic update rule at hand. - * \param U A vector of edge values for which we want to compute cumulative - * proportionate values. So U[i] is the value of the edge with ID i. - * With a local perspective, we would only compute cumulative - * proportionate values for some combination of U. This vector could - * be, for example, a vector of weights for edges in \p graph. It is - * assumed that each value of U is nonnegative; it is your - * responsibility to ensure this. Furthermore, this vector must have a - * length the same as the number of edges in \p graph; you are - * responsible for ensuring this condition holds. - * \param V Pointer to an initialized vector. The cumulative proportionate - * values will be computed and stored here. No error checks will be - * performed on this parameter. - * \param islocal Boolean; this flag controls which perspective to use. If - * true then we use the local perspective; otherwise we use the global - * perspective. In the context of this function, the local perspective - * for a vertex v consists of all edges incident on v. In contrast, the - * global perspective for v consists of all edges in \p graph. - * \param vid The vertex to use if we are considering a local perspective, - * i.e. if \p islocal is true. This vertex will be ignored if - * \p islocal is false. That is, if \p islocal is false then it is safe - * pass the value -1 here. On the other hand, if \p islocal is true then - * it is assumed that this is indeed a vertex of \p graph. - * \param mode Defines the sort of neighbourhood to consider for \p vid. This - * is only relevant if we are considering the local perspective, i.e. if - * \p islocal is true. If we are considering the global perspective, - * then this parameter would be ignored. In other words, if \p islocal - * is false then it is safe to pass the value \p IGRAPH_ALL here. If - * \p graph is undirected, then we use all the immediate neighbours of - * \p vid. Thus if you know that \p graph is undirected, then it is - * safe to pass the value \p IGRAPH_ALL here. Supported values are: - * \clist - * \cli IGRAPH_OUT - * Use the out-neighbours of \p vid. This option is only relevant - * when \p graph is a digraph and we are considering the local - * perspective. - * \cli IGRAPH_IN - * Use the in-neighbours of \p vid. Again this option is only relevant - * when \p graph is a directed graph and we are considering the local - * perspective. - * \cli IGRAPH_ALL - * Use both the in- and out-neighbours of \p vid. This option is only - * relevant if \p graph is a digraph and we are considering a local - * perspective. Also use this value if \p graph is undirected or we - * are considering the global perspective. - * \endclist - * \return Codes: - * \clist - * \cli IGRAPH_EINVAL - * This error code is returned in the following case: The vector - * \p U, or some combination of its values, sums to zero. - * \cli IGRAPH_SUCCESS - * This signal is returned if the cumulative proportionate values - * were successfully computed. - * \endclist - * - * Time complexity: O(2n) where n is the number of edges in the perspective - * of \p vid. - */ - -static igraph_error_t igraph_i_ecumulative_proportionate_values(const igraph_t *graph, - const igraph_vector_t *U, - igraph_vector_t *V, - igraph_bool_t islocal, - igraph_integer_t vid, - igraph_neimode_t mode) { - igraph_eit_t A; /* all edges in v's perspective */ - igraph_es_t es; - igraph_integer_t e; - igraph_real_t C; /* cumulative probability */ - igraph_real_t P; /* probability */ - igraph_real_t S; /* sum of values */ - igraph_integer_t i; - - /* Set the perspective. Let v be the vertex under consideration. The local */ - /* perspective for v consists of edges incident on it. In contrast, the */ - /* global perspective for v are all edges in the given graph. Hence in the */ - /* global perspective, we will ignore the given vertex and the given */ - /* neighbourhood type, but instead consider all edges in the given graph. */ - if (islocal) { - IGRAPH_CHECK(igraph_es_incident(&es, vid, mode)); - } else { - IGRAPH_CHECK(igraph_es_all(&es, IGRAPH_EDGEORDER_ID)); - } - IGRAPH_FINALLY(igraph_es_destroy, &es); - - /* Sum up all the values of vector U in the perspective for v. This sum */ - /* will be used in normalizing each value. */ - /* NOTE: Here we assume that each value to be summed is nonnegative, */ - /* and at least one of the values is nonzero. The behaviour resulting */ - /* from all values being zero would be division by zero later on when */ - /* we normalize each value. We check to see that the values sum to zero. */ - /* NOTE: In this function, the order in which we iterate through the */ - /* edges of interest should be the same as the order in which we do so */ - /* in the caller function. If the caller function doesn't care about the */ - /* order of values in the resulting vector V, then there's no need to take */ - /* special notice of that order. But in some cases the order of values in */ - /* V is taken into account, for example, in the Moran process. */ - S = 0.0; - IGRAPH_CHECK(igraph_eit_create(graph, es, &A)); - IGRAPH_FINALLY(igraph_eit_destroy, &A); - while (!IGRAPH_EIT_END(A)) { - e = IGRAPH_EIT_GET(A); - S += VECTOR(*U)[e]; - IGRAPH_EIT_NEXT(A); - } - /* avoid division by zero later on */ - if (S == 0.0) { - igraph_eit_destroy(&A); - igraph_es_destroy(&es); - IGRAPH_FINALLY_CLEAN(2); - IGRAPH_ERROR("Vector of values sums to zero", IGRAPH_EINVAL); - } - - /* Get cumulative probability and relative value for each edge in the */ - /* perspective of v. The vector V holds the cumulative proportionate */ - /* values of all edges in v's perspective. The value V[0] is the */ - /* cumulative proportionate value of the first edge in the edge iterator */ - /* A. The value V[1] is the cumulative proportionate value of the second */ - /* edge in the iterator A. And so on. */ - C = 0.0; - i = 0; - IGRAPH_EIT_RESET(A); - IGRAPH_CHECK(igraph_vector_resize(V, IGRAPH_EIT_SIZE(A))); - while (!IGRAPH_EIT_END(A)) { - e = IGRAPH_EIT_GET(A); - /* NOTE: Beware of division by zero here. This can happen if the vector */ - /* of values, or the combination of interest, sums to zero. */ - P = VECTOR(*U)[e] / S; - C += P; - VECTOR(*V)[i] = C; - i++; - IGRAPH_EIT_NEXT(A); - } - - igraph_eit_destroy(&A); - igraph_es_destroy(&es); - - /* Pop A and es from the finally stack -- that's three items */ - IGRAPH_FINALLY_CLEAN(2); - - return IGRAPH_SUCCESS; -} - -/** - * Internal use only. - * Compute the cumulative proportionate values of a vector. The vector is - * assumed to hold values associated with vertices. - * - * \param graph The graph object representing the game network. No error - * checks will be performed on this graph. You are responsible for - * ensuring that this is a valid graph for the particular - * microscopic update rule at hand. - * \param U A vector of vertex values for which we want to compute cumulative - * proportionate values. The vector could be, for example, a vector of - * fitness for vertices of \p graph. It is assumed that each value of U - * is nonnegative; it is your responsibility to ensure this. Also U, or - * a combination of interest, is assumed to sum to a positive value; - * this condition will be checked. - * \param V Pointer to an initialized vector. The cumulative proportionate - * values will be computed and stored here. No error checks will be - * performed on this parameter. - * \param islocal Boolean; this flag controls which perspective to use. If - * true then we use the local perspective; otherwise we use the global - * perspective. The local perspective for a vertex v is the set of all - * immediate neighbours of v. In contrast, the global perspective - * for v is the vertex set of \p graph. - * \param vid The vertex to use if we are considering a local perspective, - * i.e. if \p islocal is true. This vertex will be ignored if - * \p islocal is false. That is, if \p islocal is false then it is safe - * pass the value -1 here. On the other hand, if \p islocal is true then - * it is assumed that this is indeed a vertex of \p graph. - * \param mode Defines the sort of neighbourhood to consider for \p vid. This - * is only relevant if we are considering the local perspective, i.e. if - * \p islocal is true. If we are considering the global perspective, - * then this parameter would be ignored. In other words, if \p islocal - * is false then it is safe to pass the value \p IGRAPH_ALL here. If - * \p graph is undirected, then we use all the immediate neighbours of - * \p vid. Thus if you know that \p graph is undirected, then it is - * safe to pass the value \p IGRAPH_ALL here. Supported values are: - * \clist - * \cli IGRAPH_OUT - * Use the out-neighbours of \p vid. This option is only relevant - * when \p graph is a digraph and we are considering the local - * perspective. - * \cli IGRAPH_IN - * Use the in-neighbours of \p vid. Again this option is only relevant - * when \p graph is a directed graph and we are considering the local - * perspective. - * \cli IGRAPH_ALL - * Use both the in- and out-neighbours of \p vid. This option is only - * relevant if \p graph is a digraph and we are considering a local - * perspective. Also use this value if \p graph is undirected or we - * are considering the global perspective. - * \endclist - * \return Codes: - * \clist - * \cli IGRAPH_EINVAL - * This error code is returned in the following case: The vector - * \p U, or some combination of its values, sums to zero. - * \cli IGRAPH_SUCCESS - * This signal is returned if the cumulative proportionate values - * were successfully computed. - * \endclist - * - * Time complexity: O(2n) where n is the number of vertices in the - * perspective of vid. - */ - -static igraph_error_t igraph_i_vcumulative_proportionate_values(const igraph_t *graph, - const igraph_vector_t *U, - igraph_vector_t *V, - igraph_bool_t islocal, - igraph_integer_t vid, - igraph_neimode_t mode) { - igraph_integer_t v; - igraph_real_t C; /* cumulative probability */ - igraph_real_t P; /* probability */ - igraph_real_t S; /* sum of values */ - igraph_vit_t A; /* all vertices in v's perspective */ - igraph_vs_t vs; - igraph_integer_t i; - - /* Set the perspective. Let v be the vertex under consideration; it might */ - /* be that we want to update v's strategy. The local perspective for v */ - /* consists of its immediate neighbours. In contrast, the global */ - /* perspective for v are all the vertices in the given graph. Hence in the */ - /* global perspective, we will ignore the given vertex and the given */ - /* neighbourhood type, but instead consider all vertices in the given */ - /* graph. */ - if (islocal) { - IGRAPH_CHECK(igraph_vs_adj(&vs, vid, mode)); - } else { - IGRAPH_CHECK(igraph_vs_all(&vs)); - } - IGRAPH_FINALLY(igraph_vs_destroy, &vs); - - /* Sum up all the values of vector U in the perspective for v. This */ - /* sum will be used in normalizing each value. If we are using a local */ - /* perspective, then we also need to consider the quantity of v in */ - /* computing the sum. */ - /* NOTE: Here we assume that each value to be summed is nonnegative, */ - /* and at least one of the values is nonzero. The behaviour resulting */ - /* from all values being zero would be division by zero later on when */ - /* we normalize each value. We check to see that the values sum to zero. */ - /* NOTE: In this function, the order in which we iterate through the */ - /* vertices of interest should be the same as the order in which we do so */ - /* in the caller function. If the caller function doesn't care about the */ - /* order of values in the resulting vector V, then there's no need to take */ - /* special notice of that order. But in some cases the order of values in */ - /* V is taken into account, for example, in roulette wheel selection. */ - S = 0.0; - IGRAPH_CHECK(igraph_vit_create(graph, vs, &A)); - IGRAPH_FINALLY(igraph_vit_destroy, &A); - while (!IGRAPH_VIT_END(A)) { - v = IGRAPH_VIT_GET(A); - S += VECTOR(*U)[v]; - IGRAPH_VIT_NEXT(A); - } - if (islocal) { - S += VECTOR(*U)[vid]; - } - /* avoid division by zero later on */ - if (S == 0.0) { - igraph_vit_destroy(&A); - igraph_vs_destroy(&vs); - IGRAPH_FINALLY_CLEAN(2); - IGRAPH_ERROR("Vector of values sums to zero", IGRAPH_EINVAL); - } - - /* Get cumulative probability and relative value for each vertex in the */ - /* perspective of v. The vector V holds the cumulative proportionate */ - /* values of all vertices in v's perspective. The value V[0] is the */ - /* cumulative proportionate value of the first vertex in the vertex */ - /* iterator A. The value V[1] is the cumulative proportionate value of */ - /* the second vertex in the iterator A. And so on. If we are using the */ - /* local perspective, then we also need to consider the cumulative */ - /* proportionate value of v. In the case of the local perspective, we */ - /* don't need to compute and store v's cumulative proportionate value, */ - /* but we pretend that such value is appended to the vector V. */ - C = 0.0; - i = 0; - IGRAPH_VIT_RESET(A); - IGRAPH_CHECK(igraph_vector_resize(V, IGRAPH_VIT_SIZE(A))); - while (!IGRAPH_VIT_END(A)) { - v = IGRAPH_VIT_GET(A); - /* NOTE: Beware of division by zero here. This can happen if the vector */ - /* of values, or a combination of interest, sums to zero. */ - P = VECTOR(*U)[v] / S; - C += P; - VECTOR(*V)[i] = C; - i++; - IGRAPH_VIT_NEXT(A); - } - - igraph_vit_destroy(&A); - igraph_vs_destroy(&vs); - - /* Pop A and vs from the finally stack -- that's two items */ - IGRAPH_FINALLY_CLEAN(2); - - return IGRAPH_SUCCESS; -} - -/** - * Internal use only. - * A set of standard tests to be performed prior to strategy updates. The - * tests contained in this function are common to many strategy revision - * functions in this file. This function is meant to be invoked from within - * a specific strategy update function in order to perform certain common - * tests, including sanity checks and conditions under which no strategy - * updates are necessary. - * - * \param graph The graph object representing the game network. This cannot - * be the empty or trivial graph, but must have at least two vertices - * and one edge. If \p graph has one vertex, then no strategy update - * would take place. Furthermore, if \p graph has at least two vertices - * but zero edges, then strategy update would also not take place. - * \param vid The vertex whose strategy is to be updated. It is assumed that - * \p vid represents a vertex in \p graph. No checking is performed and - * it is your responsibility to ensure that \p vid is indeed a vertex - * of \p graph. If an isolated vertex is provided, i.e. the input - * vertex has degree 0, then no strategy update would take place and - * \p vid would retain its current strategy. Strategy update would also - * not take place if the local neighbourhood of \p vid are its - * in-neighbours (respectively out-neighbours), but \p vid has zero - * in-neighbours (respectively out-neighbours). Loops are ignored in - * computing the degree (in, out, all) of \p vid. - * \param quantities A vector of quantities providing the quantity of each - * vertex in \p graph. Think of each entry of the vector as being - * generated by a function such as the fitness function for the game. - * So if the vector represents fitness quantities, then each vector - * entry is the fitness of some vertex. The length of this vector must - * be the same as the number of vertices in the vertex set of \p graph. - * \param strategies A vector of the current strategies for the vertex - * population. Each strategy is identified with a nonnegative integer, - * whose interpretation depends on the payoff matrix of the game. - * Generally we use the strategy ID as a row or column index of the - * payoff matrix. The length of this vector must be the same as the - * number of vertices in the vertex set of \p graph. - * \param mode Defines the sort of neighbourhood to consider for \p vid. If - * \p graph is undirected, then we use all the immediate neighbours of - * \p vid. Thus if you know that \p graph is undirected, then it is safe - * to pass the value \p IGRAPH_ALL here. Supported values are: - * \clist - * \cli IGRAPH_OUT - * Use the out-neighbours of \p vid. This option is only relevant - * when \p graph is a directed graph. - * \cli IGRAPH_IN - * Use the in-neighbours of \p vid. Again this option is only relevant - * when \p graph is a directed graph. - * \cli IGRAPH_ALL - * Use both the in- and out-neighbours of \p vid. This option is only - * relevant if \p graph is a digraph. Also use this value if - * \p graph is undirected. - * \endclist - * \param updates Boolean; at the end of this test suite, this flag - * indicates whether to proceed with strategy revision. If true then - * strategy revision should proceed; otherwise there is no need to - * continue with revising a vertex's strategy. A caller function that - * invokes this function would use the value of \p updates to - * determine whether to proceed with strategy revision. - * \param islocal Boolean; this flag controls which perspective to use. If - * true then we use the local perspective; otherwise we use the global - * perspective. The local perspective for \p vid is the set of all - * immediate neighbours of \p vid. In contrast, the global perspective - * for \p vid is the vertex set of \p graph. - * \return Codes: - * \clist - * \cli IGRAPH_EINVAL - * This error code is returned in each of the following cases: - * (1) Any of the parameters \p graph, \p quantities, or - * \p strategies is a null pointer. (2) The vector \p quantities - * or \p strategies has a length different from the number of - * vertices in \p graph. (3) The parameter \p graph is the empty - * or null graph, i.e. the graph with zero vertices and edges. - * \cli IGRAPH_SUCCESS - * This signal is returned if no errors were raised. You should use - * the value of the boolean \p updates to decide whether to go - * ahead with updating a vertex's strategy. - * \endclist - */ - -static igraph_error_t igraph_i_microscopic_standard_tests(const igraph_t *graph, - igraph_integer_t vid, - const igraph_vector_t *quantities, - const igraph_vector_int_t *strategies, - igraph_neimode_t mode, - igraph_bool_t *updates, - igraph_bool_t islocal) { - - igraph_integer_t nvert; - igraph_vector_int_t degv; - *updates = true; - - /* sanity checks */ - if (graph == NULL) { - IGRAPH_ERROR("Graph is a null pointer", IGRAPH_EINVAL); - } - if (quantities == NULL) { - IGRAPH_ERROR("Quantities vector is a null pointer", IGRAPH_EINVAL); - } - if (strategies == NULL) { - IGRAPH_ERROR("Strategies vector is a null pointer", IGRAPH_EINVAL); - } - - /* the empty graph */ - nvert = igraph_vcount(graph); - if (nvert < 1) { - IGRAPH_ERROR("Graph cannot be the empty graph", IGRAPH_EINVAL); - } - /* invalid vector length */ - if (nvert != igraph_vector_size(quantities)) { - IGRAPH_ERROR("Size of quantities vector different from number of vertices", - IGRAPH_EINVAL); - } - if (nvert != igraph_vector_int_size(strategies)) { - IGRAPH_ERROR("Size of strategies vector different from number of vertices", - IGRAPH_EINVAL); - } - - /* Various conditions under which no strategy updates will take place. That - * is, the vertex retains its current strategy. - */ - /* given graph has < 2 vertices */ - if (nvert < 2) { - *updates = false; - } - /* graph has >= 2 vertices, but no edges */ - if (igraph_ecount(graph) < 1) { - *updates = false; - } - - /* Test for vertex isolation, depending on the perspective given. For - * undirected graphs, a given vertex v is isolated if its degree is zero. - * If we are considering in-neighbours (respectively out-neighbours), then - * we say that v is isolated if its in-degree (respectively out-degree) is - * zero. In general, this vertex isolation test is only relevant if we are - * using a local perspective, i.e. if we only consider the immediate - * neighbours (local perspective) of v as opposed to all vertices in the - * vertex set of the graph (global perspective). - */ - if (islocal) { - /* Moving on ahead with vertex isolation test, since local perspective */ - /* is requested. */ - IGRAPH_VECTOR_INT_INIT_FINALLY(°v, 1); - IGRAPH_CHECK(igraph_degree(graph, °v, igraph_vss_1(vid), - mode, IGRAPH_NO_LOOPS)); - if (VECTOR(degv)[0] < 1) { - *updates = false; - } - igraph_vector_int_destroy(°v); - IGRAPH_FINALLY_CLEAN(1); - } - - return IGRAPH_SUCCESS; -} - -/** - * \ingroup spatialgames - * \function igraph_deterministic_optimal_imitation - * \brief Adopt a strategy via deterministic optimal imitation. - * - * A simple deterministic imitation strategy where a vertex revises its - * strategy to that which yields a local optimum. Here "local" is with - * respect to the immediate neighbours of the vertex. The vertex retains its - * current strategy where this strategy yields a locally optimal quantity. - * The quantity in this case could be a measure such as fitness. - * - * \param graph The graph object representing the game network. This cannot - * be the empty or trivial graph, but must have at least two vertices - * and one edge. If \p graph has one vertex, then no strategy update - * would take place. Furthermore, if \p graph has at least two vertices - * but zero edges, then strategy update would also not take place. - * \param vid The vertex whose strategy is to be updated. It is assumed that - * \p vid represents a vertex in \p graph. No checking is performed and - * it is your responsibility to ensure that \p vid is indeed a vertex - * of \p graph. If an isolated vertex is provided, i.e. the input - * vertex has degree 0, then no strategy update would take place and - * \p vid would retain its current strategy. Strategy update would also - * not take place if the local neighbourhood of \p vid are its - * in-neighbours (respectively out-neighbours), but \p vid has zero - * in-neighbours (respectively out-neighbours). Loops are ignored in - * computing the degree (in, out, all) of \p vid. - * \param optimality Boolean; controls the type of optimality to be used. - * Supported values are: - * \clist - * \cli IGRAPH_MAXIMUM - * Use maximum deterministic imitation, where the strategy of the - * vertex with maximum quantity (e.g. fitness) would be adopted. We - * update the strategy of \p vid to that which yields a local - * maximum. - * \cli IGRAPH_MINIMUM - * Use minimum deterministic imitation. That is, the strategy of the - * vertex with minimum quantity would be imitated. In other words, - * update to the strategy that yields a local minimum. - * \endclist - * \param quantities A vector of quantities providing the quantity of each - * vertex in \p graph. Think of each entry of the vector as being - * generated by a function such as the fitness function for the game. - * So if the vector represents fitness quantities, then each vector - * entry is the fitness of some vertex. The length of this vector must - * be the same as the number of vertices in the vertex set of \p graph. - * \param strategies A vector of the current strategies for the vertex - * population. The updated strategy for \p vid would be stored here. - * Each strategy is identified with a nonnegative integer, whose - * interpretation depends on the payoff matrix of the game. Generally - * we use the strategy ID as a row or column index of the payoff - * matrix. The length of this vector must be the same as the number of - * vertices in the vertex set of \p graph. - * \param mode Defines the sort of neighbourhood to consider for \p vid. If - * \p graph is undirected, then we use all the immediate neighbours of - * \p vid. Thus if you know that \p graph is undirected, then it is safe - * to pass the value \p IGRAPH_ALL here. Supported values are: - * \clist - * \cli IGRAPH_OUT - * Use the out-neighbours of \p vid. This option is only relevant - * when \p graph is a directed graph. - * \cli IGRAPH_IN - * Use the in-neighbours of \p vid. Again this option is only relevant - * when \p graph is a directed graph. - * \cli IGRAPH_ALL - * Use both the in- and out-neighbours of \p vid. This option is only - * relevant if \p graph is a digraph. Also use this value if - * \p graph is undirected. - * \endclist - * \return The error code \p IGRAPH_EINVAL is returned in each of the - * following cases: (1) Any of the parameters \p graph, \p quantities, - * or \p strategies is a null pointer. (2) The vector \p quantities - * or \p strategies has a length different from the number of vertices - * in \p graph. (3) The parameter \p graph is the empty or null graph, - * i.e. the graph with zero vertices and edges. - * - * Time complexity: O(2d), where d is the degree of the vertex \p vid. - * - * \example examples/simple/igraph_deterministic_optimal_imitation.c - */ - -igraph_error_t igraph_deterministic_optimal_imitation(const igraph_t *graph, - igraph_integer_t vid, - igraph_optimal_t optimality, - const igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode) { - igraph_integer_t i, k, v; - igraph_real_t q; - igraph_vector_int_t adj; - igraph_bool_t updates; - - IGRAPH_CHECK(igraph_i_microscopic_standard_tests(graph, vid, quantities, - strategies, mode, &updates, - /*is local?*/ true)); - if (!updates) { - return IGRAPH_SUCCESS; /* Nothing to do */ - } - - /* Choose a locally optimal strategy to imitate. This can be either maximum - * or minimum deterministic imitation. By now we know that the given vertex v - * has degree >= 1 and at least 1 edge. Then within its immediate - * neighbourhood adj(v) and including v itself, there exists a vertex whose - * strategy yields a local optimal quantity. - */ - /* Random permutation of adj(v). This ensures that if there are multiple */ - /* candidates with an optimal strategy, then we choose one such candidate */ - /* at random. */ - IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &adj, vid, mode)); - IGRAPH_CHECK(igraph_vector_int_shuffle(&adj)); - /* maximum deterministic imitation */ - i = vid; - q = VECTOR(*quantities)[vid]; - if (optimality == IGRAPH_MAXIMUM) { - for (k = 0; k < igraph_vector_int_size(&adj); k++) { - v = VECTOR(adj)[k]; - if (VECTOR(*quantities)[v] > q) { - i = v; - q = VECTOR(*quantities)[v]; - } - } - } else { /* minimum deterministic imitation */ - for (k = 0; k < igraph_vector_int_size(&adj); k++) { - v = VECTOR(adj)[k]; - if (VECTOR(*quantities)[v] < q) { - i = v; - q = VECTOR(*quantities)[v]; - } - } - } - /* Now i is a vertex with a locally optimal quantity, the value of which */ - /* is q. Update the strategy of vid to that of i. */ - VECTOR(*strategies)[vid] = VECTOR(*strategies)[i]; - igraph_vector_int_destroy(&adj); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - -/** - * \ingroup spatialgames - * \function igraph_moran_process - * \brief The Moran process in a network setting. - * - * This is an extension of the classic Moran process to a network setting. - * The Moran process is a model of haploid (asexual) reproduction within a - * population having a fixed size. In the network setting, the Moran process - * operates on a weighted graph. At each time step a vertex a is chosen for - * reproduction and another vertex b is chosen for death. Vertex a gives birth - * to an identical clone c, which replaces b. Vertex c is a clone of a in that - * c inherits both the current quantity (e.g. fitness) and current strategy - * of a. - * - * - * The graph G representing the game network is assumed to be simple, - * i.e. free of loops and without multiple edges. If, on the other hand, G has - * a loop incident on some vertex v, then it is possible that when v is chosen - * for reproduction it would forgo this opportunity. In particular, when v is - * chosen for reproduction and v is also chosen for death, the clone of v - * would be v itself with its current vertex ID. In effect v forgoes its - * chance for reproduction. - * - * \param graph The graph object representing the game network. This cannot - * be the empty or trivial graph, but must have at least two vertices - * and one edge. The Moran process will not take place in each of the - * following cases: (1) If \p graph has one vertex. (2) If \p graph has - * at least two vertices but zero edges. - * \param weights A vector of all edge weights for \p graph. Thus weights[i] - * means the weight of the edge with edge ID i. For the purpose of the - * Moran process, each weight is assumed to be positive; it is your - * responsibility to ensure this condition holds. The length of this - * vector must be the same as the number of edges in \p graph. - * \param quantities A vector of quantities providing the quantity of each - * vertex in \p graph. The quantity of the new clone will be stored - * here. Think of each entry of the vector as being generated by a - * function such as the fitness function for the game. So if the vector - * represents fitness quantities, then each vector entry is the fitness - * of some vertex. The length of this vector must be the same as the - * number of vertices in the vertex set of \p graph. For the purpose of - * the Moran process, each vector entry is assumed to be nonnegative; - * no checks will be performed for this. It is your responsibility to - * ensure that at least one entry is positive. Furthermore, this vector - * cannot be a vector of zeros; this condition will be checked. - * \param strategies A vector of the current strategies for the vertex - * population. The strategy of the new clone will be stored here. Each - * strategy is identified with a nonnegative integer, whose - * interpretation depends on the payoff matrix of the game. Generally - * we use the strategy ID as a row or column index of the payoff - * matrix. The length of this vector must be the same as the number of - * vertices in the vertex set of \p graph. - * \param mode Defines the sort of neighbourhood to consider for the vertex a - * chosen for reproduction. This is only relevant if \p graph is - * directed. If \p graph is undirected, then it is safe to pass the - * value \p IGRAPH_ALL here. Supported values are: - * \clist - * \cli IGRAPH_OUT - * Use the out-neighbours of a. This option is only relevant when - * \p graph is directed. - * \cli IGRAPH_IN - * Use the in-neighbours of a. Again this option is only relevant - * when \p graph is directed. - * \cli IGRAPH_ALL - * Use both the in- and out-neighbours of a. This option is only - * relevant if \p graph is directed. Also use this value if - * \p graph is undirected. - * \endclist - * \return The error code \p IGRAPH_EINVAL is returned in each of the following - * cases: (1) Any of the parameters \p graph, \p weights, - * \p quantities or \p strategies is a null pointer. (2) The vector - * \p quantities or \p strategies has a length different from the - * number of vertices in \p graph. (3) The vector \p weights has a - * length different from the number of edges in \p graph. (4) The - * parameter \p graph is the empty or null graph, i.e. the graph with - * zero vertices and edges. (5) The vector \p weights, or the - * combination of interest, sums to zero. (6) The vector \p quantities, - * or the combination of interest, sums to zero. - * - * Time complexity: depends on the random number generator, but is usually - * O(n) where n is the number of vertices in \p graph. - * - * - * References: - * \clist - * \cli (Lieberman et al. 2005) - * E. Lieberman, C. Hauert, and M. A. Nowak. Evolutionary dynamics on - * graphs. \emb Nature, \eme 433(7023):312--316, 2005. - * \cli (Moran 1958) - * P. A. P. Moran. Random processes in genetics. \emb Mathematical - * Proceedings of the Cambridge Philosophical Society, \eme 54(1):60--71, - * 1958. - * \endclist - */ - -igraph_error_t igraph_moran_process(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode) { - igraph_bool_t updates; - igraph_integer_t a = -1; /* vertex chosen for reproduction */ - igraph_integer_t b = -1; /* vertex chosen for death */ - igraph_integer_t e, nedge, u, v; - igraph_real_t r; /* random number */ - igraph_vector_int_t deg; - igraph_vector_t V; /* vector of cumulative proportionate values */ - igraph_vit_t vA; /* vertex list */ - igraph_eit_t eA; /* edge list */ - igraph_vs_t vs; - igraph_es_t es; - igraph_integer_t i; - - /* don't test for vertex isolation, hence vid = -1 and islocal = 0 */ - IGRAPH_CHECK(igraph_i_microscopic_standard_tests(graph, /*vid*/ -1, - quantities, strategies, mode, - &updates, /*is local?*/ false)); - if (!updates) { - return IGRAPH_SUCCESS; /* nothing more to do */ - } - if (weights == NULL) { - IGRAPH_ERROR("Weights vector is a null pointer", IGRAPH_EINVAL); - } - nedge = igraph_ecount(graph); - if (nedge != igraph_vector_size(weights)) { - IGRAPH_ERROR("Size of weights vector different from number of edges", - IGRAPH_EINVAL); - } - - IGRAPH_VECTOR_INIT_FINALLY(&V, 0); - - /* Cumulative proportionate quantities. We are using the global */ - /* perspective, hence islocal = 0, vid = -1 and mode = IGRAPH_ALL. */ - IGRAPH_CHECK(igraph_i_vcumulative_proportionate_values(graph, quantities, &V, - /*is local?*/ false, - /*vid*/ -1, - /*mode*/ IGRAPH_ALL)); - - /* Choose a vertex for reproduction from among all vertices in the graph. */ - /* The vertex is chosen proportionate to its quantity and such that its */ - /* degree is >= 1. In case we are considering in-neighbours (respectively */ - /* out-neighbours), the chosen vertex must have in-degree (respectively */ - /* out-degree) >= 1. All loops will be ignored. At this point, we know */ - /* that the graph has at least one edge, which may be directed or not. */ - /* Furthermore the quantities of all vertices sum to a positive value. */ - /* Hence at least one vertex will be chosen for reproduction. */ - IGRAPH_CHECK(igraph_vs_all(&vs)); - IGRAPH_FINALLY(igraph_vs_destroy, &vs); - IGRAPH_CHECK(igraph_vit_create(graph, vs, &vA)); - IGRAPH_FINALLY(igraph_vit_destroy, &vA); - RNG_BEGIN(); - r = RNG_UNIF01(); - RNG_END(); - i = 0; - IGRAPH_VECTOR_INT_INIT_FINALLY(°, 1); - while (!IGRAPH_VIT_END(vA)) { - u = IGRAPH_VIT_GET(vA); - IGRAPH_CHECK(igraph_degree(graph, °, igraph_vss_1(u), mode, - IGRAPH_NO_LOOPS)); - if (VECTOR(deg)[0] < 1) { - i++; - IGRAPH_VIT_NEXT(vA); - continue; - } - if (r <= VECTOR(V)[i]) { - /* we have found our candidate vertex for reproduction */ - a = u; - break; - } - i++; - IGRAPH_VIT_NEXT(vA); - } - /* By now we should have chosen a vertex for reproduction. Check this. */ - IGRAPH_ASSERT(a >= 0); - - /* Cumulative proportionate weights. We are using the local perspective */ - /* with respect to vertex a, which has been chosen for reproduction. */ - /* The degree of a is deg(a) >= 1 with respect to the mode "mode", which */ - /* can flag either the in-degree, out-degree or all degree of a. But it */ - /* still might happen that the edge weights of interest would sum to zero. */ - /* An error would be raised in that case. */ - IGRAPH_CHECK(igraph_i_ecumulative_proportionate_values(graph, weights, &V, - /*is local?*/ true, - /*vertex*/ a, mode)); - - /* Choose a vertex for death from among all vertices in a's perspective. */ - /* Let E be all the edges in the perspective of a. If (u,v) \in E is any */ - /* such edge, then we have a = u or a = v. That is, any edge in E has a */ - /* for one of its endpoints. As G is assumed to be a simple graph, then */ - /* exactly one of u or v is the vertex a. Without loss of generality, we */ - /* assume that each edge in E has the form (a, v_i). Then the vertex v_j */ - /* chosen for death is chosen proportionate to the weight of the edge */ - /* (a, v_j). */ - IGRAPH_CHECK(igraph_es_incident(&es, a, mode)); - IGRAPH_FINALLY(igraph_es_destroy, &es); - IGRAPH_CHECK(igraph_eit_create(graph, es, &eA)); - IGRAPH_FINALLY(igraph_eit_destroy, &eA); - RNG_BEGIN(); - r = RNG_UNIF01(); - RNG_END(); - i = 0; - while (!IGRAPH_EIT_END(eA)) { - e = IGRAPH_EIT_GET(eA); - if (r <= VECTOR(V)[i]) { - /* We have found our candidate vertex for death; call this vertex b. */ - /* As G is simple, then a =/= b. Check the latter condition. */ - IGRAPH_CHECK(igraph_edge(graph, /*edge ID*/ e, - /*tail vertex*/ &u, /*head vertex*/ &v)); - if (a == u) { - b = v; - } else { - b = u; - } - IGRAPH_ASSERT(a != b); /* always true if G is simple */ - break; - } - i++; - IGRAPH_EIT_NEXT(eA); - } - - /* By now a vertex a is chosen for reproduction and a vertex b is chosen */ - /* for death. Check that b has indeed been chosen. Clone vertex a and kill */ - /* vertex b. Let the clone c have the vertex ID of b, and the strategy and */ - /* quantity of a. */ - IGRAPH_ASSERT(b >= 0); - VECTOR(*quantities)[b] = VECTOR(*quantities)[a]; - VECTOR(*strategies)[b] = VECTOR(*strategies)[a]; - - igraph_eit_destroy(&eA); - igraph_es_destroy(&es); - igraph_vector_int_destroy(°); - igraph_vit_destroy(&vA); - igraph_vs_destroy(&vs); - igraph_vector_destroy(&V); - IGRAPH_FINALLY_CLEAN(6); - - return IGRAPH_SUCCESS; -} - -/** - * \ingroup spatialgames - * \function igraph_roulette_wheel_imitation - * \brief Adopt a strategy via roulette wheel selection. - * - * A simple stochastic imitation strategy where a vertex revises its - * strategy to that of a vertex u chosen proportionate to u's quantity - * (e.g. fitness). This is a special case of stochastic imitation, where a - * candidate is not chosen uniformly at random but proportionate to its - * quantity. - * - * \param graph The graph object representing the game network. This cannot - * be the empty or trivial graph, but must have at least two vertices - * and one edge. If \p graph has one vertex, then no strategy update - * would take place. Furthermore, if \p graph has at least two vertices - * but zero edges, then strategy update would also not take place. - * \param vid The vertex whose strategy is to be updated. It is assumed that - * \p vid represents a vertex in \p graph. No checking is performed and - * it is your responsibility to ensure that \p vid is indeed a vertex - * of \p graph. If an isolated vertex is provided, i.e. the input - * vertex has degree 0, then no strategy update would take place and - * \p vid would retain its current strategy. Strategy update would also - * not take place if the local neighbourhood of \p vid are its - * in-neighbours (respectively out-neighbours), but \p vid has zero - * in-neighbours (respectively out-neighbours). Loops are ignored in - * computing the degree (in, out, all) of \p vid. - * \param islocal Boolean; this flag controls which perspective to use in - * computing the relative quantity. If true then we use the local - * perspective; otherwise we use the global perspective. The local - * perspective for \p vid is the set of all immediate neighbours of - * \p vid. In contrast, the global perspective for \p vid is the - * vertex set of \p graph. - * \param quantities A vector of quantities providing the quantity of each - * vertex in \p graph. Think of each entry of the vector as being - * generated by a function such as the fitness function for the game. - * So if the vector represents fitness quantities, then each vector - * entry is the fitness of some vertex. The length of this vector must - * be the same as the number of vertices in the vertex set of \p graph. - * For the purpose of roulette wheel selection, each vector entry is - * assumed to be nonnegative; no checks will be performed for this. It - * is your responsibility to ensure that at least one entry is nonzero. - * Furthermore, this vector cannot be a vector of zeros; this condition - * will be checked. - * \param strategies A vector of the current strategies for the vertex - * population. The updated strategy for \p vid would be stored here. - * Each strategy is identified with a nonnegative integer, whose - * interpretation depends on the payoff matrix of the game. Generally - * we use the strategy ID as a row or column index of the payoff - * matrix. The length of this vector must be the same as the number of - * vertices in the vertex set of \p graph. - * \param mode Defines the sort of neighbourhood to consider for \p vid. This - * is only relevant if we are considering the local perspective, i.e. if - * \p islocal is true. If we are considering the global perspective, - * then it is safe to pass the value \p IGRAPH_ALL here. If \p graph is - * undirected, then we use all the immediate neighbours of \p vid. Thus - * if you know that \p graph is undirected, then it is safe to pass the - * value \p IGRAPH_ALL here. Supported values are: - * \clist - * \cli IGRAPH_OUT - * Use the out-neighbours of \p vid. This option is only relevant - * when \p graph is a digraph and we are considering the local - * perspective. - * \cli IGRAPH_IN - * Use the in-neighbours of \p vid. Again this option is only relevant - * when \p graph is a directed graph and we are considering the local - * perspective. - * \cli IGRAPH_ALL - * Use both the in- and out-neighbours of \p vid. This option is only - * relevant if \p graph is a digraph. Also use this value if - * \p graph is undirected or we are considering the global - * perspective. - * \endclist - * \return The error code \p IGRAPH_EINVAL is returned in each of the following - * cases: (1) Any of the parameters \p graph, \p quantities, or - * \p strategies is a null pointer. (2) The vector \p quantities or - * \p strategies has a length different from the number of vertices - * in \p graph. (3) The parameter \p graph is the empty or null graph, - * i.e. the graph with zero vertices and edges. (4) The vector - * \p quantities sums to zero. - * - * Time complexity: O(n) where n is the number of vertices in the perspective - * to consider. If we consider the global perspective, then n is the number - * of vertices in the vertex set of \p graph. On the other hand, for the local - * perspective n is the degree of \p vid, excluding loops. - * - * - * Reference: - * \clist - * \cli (Yu & Gen 2010) - * X. Yu and M. Gen. \emb Introduction to Evolutionary Algorithms. \eme - * Springer, 2010, pages 18--20. - * \endclist - * - * \example examples/simple/igraph_roulette_wheel_imitation.c - */ - -igraph_error_t igraph_roulette_wheel_imitation(const igraph_t *graph, - igraph_integer_t vid, - igraph_bool_t islocal, - const igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode) { - igraph_bool_t updates; - igraph_integer_t u; - igraph_real_t r; /* random number */ - igraph_vector_t V; /* vector of cumulative proportionate quantities */ - igraph_vit_t A; /* all vertices in v's perspective */ - igraph_vs_t vs; - igraph_integer_t i; - - IGRAPH_CHECK(igraph_i_microscopic_standard_tests(graph, vid, quantities, - strategies, mode, &updates, - islocal)); - if (!updates) { - return IGRAPH_SUCCESS; /* nothing further to do */ - } - - /* set the perspective */ - if (islocal) { - IGRAPH_CHECK(igraph_vs_adj(&vs, vid, mode)); - } else { - IGRAPH_CHECK(igraph_vs_all(&vs)); - } - IGRAPH_FINALLY(igraph_vs_destroy, &vs); - IGRAPH_CHECK(igraph_vit_create(graph, vs, &A)); - IGRAPH_FINALLY(igraph_vit_destroy, &A); - - IGRAPH_VECTOR_INIT_FINALLY(&V, 0); - - IGRAPH_CHECK(igraph_i_vcumulative_proportionate_values(graph, quantities, &V, - islocal, vid, mode)); - - /* Finally, choose a vertex u to imitate. The vertex u is chosen */ - /* proportionate to its quantity. In the case of a local perspective, we */ - /* pretend that v's cumulative proportionate quantity has been appended to */ - /* the vector V. Let V be of length n so that V[n-1] is the last element */ - /* of V, and let r be a real number chosen uniformly at random from the */ - /* unit interval [0,1]. If r > V[i] for all i < n, then v defaults to */ - /* retaining its current strategy. Similarly in the case of the global */ - /* perspective, if r > V[i] for all i < n - 1 then v would adopt the */ - /* strategy of the vertex whose cumulative proportionate quantity is */ - /* V[n-1]. */ - /* NOTE: Here we assume that the order in which we iterate through the */ - /* vertices in A is the same as the order in which we do so in the */ - /* invoked function igraph_vcumulative_proportionate_values(). */ - /* Otherwise we would incorrectly associate each V[i] with a vertex in A. */ - RNG_BEGIN(); - r = RNG_UNIF01(); - RNG_END(); - i = 0; - while (!IGRAPH_VIT_END(A)) { - if (r <= VECTOR(V)[i]) { - /* We have found our candidate vertex for imitation. Update strategy */ - /* of v to that of u, and exit the selection loop. */ - u = IGRAPH_VIT_GET(A); - VECTOR(*strategies)[vid] = VECTOR(*strategies)[u]; - break; - } - i++; - IGRAPH_VIT_NEXT(A); - } - - /* By now, vertex v should either retain its current strategy or it has */ - /* adopted the strategy of a vertex in its perspective. Nothing else to */ - /* do, but clean up. */ - igraph_vector_destroy(&V); - igraph_vit_destroy(&A); - igraph_vs_destroy(&vs); - IGRAPH_FINALLY_CLEAN(3); - - return IGRAPH_SUCCESS; -} - -/** - * \ingroup spatialgames - * \function igraph_stochastic_imitation - * \brief Adopt a strategy via stochastic imitation with uniform selection. - * - * A simple stochastic imitation strategy where a vertex revises its - * strategy to that of a vertex chosen uniformly at random from its local - * neighbourhood. This is called stochastic imitation via uniform selection, - * where the strategy to imitate is chosen via some random process. For the - * purposes of this function, we use uniform selection from a pool of - * candidates. - * - * \param graph The graph object representing the game network. This cannot - * be the empty or trivial graph, but must have at least two vertices - * and one edge. If \p graph has one vertex, then no strategy update - * would take place. Furthermore, if \p graph has at least two vertices - * but zero edges, then strategy update would also not take place. - * \param vid The vertex whose strategy is to be updated. It is assumed that - * \p vid represents a vertex in \p graph. No checking is performed and - * it is your responsibility to ensure that \p vid is indeed a vertex - * of \p graph. If an isolated vertex is provided, i.e. the input - * vertex has degree 0, then no strategy update would take place and - * \p vid would retain its current strategy. Strategy update would also - * not take place if the local neighbourhood of \p vid are its - * in-neighbours (respectively out-neighbours), but \p vid has zero - * in-neighbours (respectively out-neighbours). Loops are ignored in - * computing the degree (in, out, all) of \p vid. - * \param algo This flag controls which algorithm to use in stochastic - * imitation. Supported values are: - * \clist - * \cli IGRAPH_IMITATE_AUGMENTED - * Augmented imitation. Vertex \p vid imitates the strategy of the - * chosen vertex u provided that doing so would increase the - * quantity (e.g. fitness) of \p vid. Augmented imitation can be - * thought of as "imitate if better". - * \cli IGRAPH_IMITATE_BLIND - * Blind imitation. Vertex \p vid blindly imitates the strategy of - * the chosen vertex u, regardless of whether doing so would - * increase or decrease the quantity of \p vid. - * \cli IGRAPH_IMITATE_CONTRACTED - * Contracted imitation. Here vertex \p vid imitates the strategy of - * the chosen vertex u if doing so would decrease the quantity of - * \p vid. Think of contracted imitation as "imitate if worse". - * \endclist - * \param quantities A vector of quantities providing the quantity of each - * vertex in \p graph. Think of each entry of the vector as being - * generated by a function such as the fitness function for the game. - * So if the vector represents fitness quantities, then each vector - * entry is the fitness of some vertex. The length of this vector must - * be the same as the number of vertices in the vertex set of \p graph. - * \param strategies A vector of the current strategies for the vertex - * population. The updated strategy for \p vid would be stored here. - * Each strategy is identified with a nonnegative integer, whose - * interpretation depends on the payoff matrix of the game. Generally - * we use the strategy ID as a row or column index of the payoff - * matrix. The length of this vector must be the same as the number of - * vertices in the vertex set of \p graph. - * \param mode Defines the sort of neighbourhood to consider for \p vid. If - * \p graph is undirected, then we use all the immediate neighbours of - * \p vid. Thus if you know that \p graph is undirected, then it is safe - * to pass the value \p IGRAPH_ALL here. Supported values are: - * \clist - * \cli IGRAPH_OUT - * Use the out-neighbours of \p vid. This option is only relevant - * when \p graph is a directed graph. - * \cli IGRAPH_IN - * Use the in-neighbours of \p vid. Again this option is only relevant - * when \p graph is a directed graph. - * \cli IGRAPH_ALL - * Use both the in- and out-neighbours of \p vid. This option is only - * relevant if \p graph is a digraph. Also use this value if - * \p graph is undirected. - * \endclist - * \return The error code \p IGRAPH_EINVAL is returned in each of the following - * cases: (1) Any of the parameters \p graph, \p quantities, or - * \p strategies is a null pointer. (2) The vector \p quantities or - * \p strategies has a length different from the number of vertices - * in \p graph. (3) The parameter \p graph is the empty or null graph, - * i.e. the graph with zero vertices and edges. (4) The parameter - * \p algo refers to an unsupported stochastic imitation algorithm. - * - * Time complexity: depends on the uniform random number generator, but should - * usually be O(1). - * - * \example examples/simple/igraph_stochastic_imitation.c - */ - -igraph_error_t igraph_stochastic_imitation(const igraph_t *graph, - igraph_integer_t vid, - igraph_imitate_algorithm_t algo, - const igraph_vector_t *quantities, - igraph_vector_int_t *strategies, - igraph_neimode_t mode) { - igraph_bool_t updates; - igraph_integer_t u; - igraph_vector_int_t adj; - igraph_integer_t i; - - /* sanity checks */ - if (algo != IGRAPH_IMITATE_AUGMENTED && - algo != IGRAPH_IMITATE_BLIND && - algo != IGRAPH_IMITATE_CONTRACTED) { - IGRAPH_ERROR("Unsupported stochastic imitation algorithm", - IGRAPH_EINVAL); - } - IGRAPH_CHECK(igraph_i_microscopic_standard_tests(graph, vid, quantities, - strategies, mode, &updates, - /*is local?*/ true)); - if (!updates) { - return IGRAPH_SUCCESS; /* nothing more to do */ - } - - /* immediate neighbours of v */ - IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &adj, vid, mode)); - - /* Blind imitation. Let v be the vertex whose strategy we want to revise. */ - /* Choose a vertex u uniformly at random from the immediate neighbours of */ - /* v, including v itself. Then blindly update the strategy of v to that of */ - /* u, irrespective of whether doing so would increase or decrease the */ - /* quantity (e.g. fitness) of v. Here v retains its current strategy if */ - /* the chosen vertex u is indeed v itself. */ - if (algo == IGRAPH_IMITATE_BLIND) { - IGRAPH_CHECK(igraph_vector_int_push_back(&adj, vid)); - RNG_BEGIN(); - i = RNG_INTEGER(0, igraph_vector_int_size(&adj) - 1); - RNG_END(); - u = VECTOR(adj)[i]; - VECTOR(*strategies)[vid] = VECTOR(*strategies)[u]; - } - /* Augmented imitation. Let v be the vertex whose strategy we want to */ - /* revise. Let f be the quantity function for the game. Choose a vertex u */ - /* uniformly at random from the immediate neighbours of v; do not include */ - /* v. Then v imitates the strategy of u if f(u) > f(v). Otherwise v */ - /* retains its current strategy. */ - else if (algo == IGRAPH_IMITATE_AUGMENTED) { - RNG_BEGIN(); - i = RNG_INTEGER(0, igraph_vector_int_size(&adj) - 1); - RNG_END(); - u = VECTOR(adj)[i]; - if (VECTOR(*quantities)[u] > VECTOR(*quantities)[vid]) { - VECTOR(*strategies)[vid] = VECTOR(*strategies)[u]; - } - } - /* Contracted imitation. Let v be the vertex whose strategy we want to */ - /* update and let f be the quantity function for the game. Choose a vertex */ - /* u uniformly at random from the immediate neighbours of v, excluding v */ - /* itself. Then v imitates the strategy of u provided that f(u) < f(v). */ - /* Otherwise v retains its current strategy. */ - else if (algo == IGRAPH_IMITATE_CONTRACTED) { - RNG_BEGIN(); - i = RNG_INTEGER(0, igraph_vector_int_size(&adj) - 1); - RNG_END(); - u = VECTOR(adj)[i]; - if (VECTOR(*quantities)[u] < VECTOR(*quantities)[vid]) { - VECTOR(*strategies)[vid] = VECTOR(*strategies)[u]; - } - } - - /* clean up */ - igraph_vector_int_destroy(&adj); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} diff --git a/src/vendor/cigraph/src/misc/mixing.c b/src/vendor/cigraph/src/misc/mixing.c index d3b77b84aa8..445e3fe2097 100644 --- a/src/vendor/cigraph/src/misc/mixing.c +++ b/src/vendor/cigraph/src/misc/mixing.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2009-2023 The igraph development team @@ -419,8 +418,6 @@ igraph_error_t igraph_assortativity_degree(const igraph_t *graph, * \function igraph_joint_degree_matrix * \brief The joint degree matrix of a graph. * - * \experimental - * * In graph theory, the joint degree matrix \c J_ij of a graph gives the number * of edges, or sum of edge weights, between vertices of degree \c i and degree * \c j. This function stores \c J_ij into jdm[i-1, j-1]. @@ -498,8 +495,8 @@ igraph_error_t igraph_joint_degree_matrix( // Compute max degrees IGRAPH_VECTOR_INT_INIT_FINALLY(&out_degrees, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&in_degrees, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, &out_degrees, igraph_vss_all(), IGRAPH_OUT, true)); - IGRAPH_CHECK(igraph_degree(graph, &in_degrees, igraph_vss_all(), IGRAPH_IN, true)); + IGRAPH_CHECK(igraph_degree(graph, &out_degrees, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS)); + IGRAPH_CHECK(igraph_degree(graph, &in_degrees, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS)); if (max_out_degree < 0) { max_out_degree = no_of_nodes > 0 ? igraph_vector_int_max(&out_degrees) : 0; @@ -535,7 +532,7 @@ igraph_error_t igraph_joint_degree_matrix( igraph_integer_t maxdeg; IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_ALL, true)); + IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); // Compute max degree of the graph only if needed if (max_out_degree < 0 || max_in_degree < 0) { @@ -709,8 +706,6 @@ static igraph_error_t mixing_matrix( * \function igraph_joint_degree_distribution * \brief The joint degree distribution of a graph. * - * \experimental - * * Computes the joint degree distribution \c P_ij of a graph, used in the * study of degree correlations. \c P_ij is the probability that a randomly * chosen ordered pair of \em connected vertices have degrees \c i and \c j. @@ -820,17 +815,17 @@ igraph_error_t igraph_joint_degree_distribution( if (have_out) { IGRAPH_VECTOR_INT_INIT_FINALLY(°_out, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, °_out, igraph_vss_all(), IGRAPH_OUT, /* loops */ true)); + IGRAPH_CHECK(igraph_degree(graph, °_out, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS)); } if (have_in) { IGRAPH_VECTOR_INT_INIT_FINALLY(°_in, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, °_in, igraph_vss_all(), IGRAPH_IN, /* loops */ true)); + IGRAPH_CHECK(igraph_degree(graph, °_in, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS)); } if (have_all) { IGRAPH_VECTOR_INT_INIT_FINALLY(°_all, no_of_nodes); - IGRAPH_CHECK(igraph_degree(graph, °_all, igraph_vss_all(), IGRAPH_ALL, /* loops */ true)); + IGRAPH_CHECK(igraph_degree(graph, °_all, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); } switch (from_mode) { @@ -879,8 +874,6 @@ igraph_error_t igraph_joint_degree_distribution( * \function igraph_joint_type_distribution * \brief Mixing matrix for vertex categories. * - * \experimental - * * Computes the mixing matrix M_ij, i.e. the joint distribution of vertex types * at the endpoints directed of edges. Categories are represented by non-negative integer * indices, passed in \p from_types and \p to_types. The row and column counts of \p m diff --git a/src/vendor/cigraph/src/misc/motifs.c b/src/vendor/cigraph/src/misc/motifs.c index 3a018d5d170..fb174c8e62b 100644 --- a/src/vendor/cigraph/src/misc/motifs.c +++ b/src/vendor/cigraph/src/misc/motifs.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -328,8 +327,6 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte IGRAPH_CHECK(igraph_stack_int_init(&stack, 0)); IGRAPH_FINALLY(igraph_stack_int_destroy, &stack); - RNG_BEGIN(); - for (father = 0; father < no_of_nodes; father++) { igraph_integer_t level; @@ -486,8 +483,6 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte } /* for father */ - RNG_END(); - IGRAPH_FREE(added); IGRAPH_FREE(subg); igraph_vector_int_destroy(&vids); @@ -522,7 +517,10 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte * the search tree. * * \param graph The graph object to study. - * \param est Pointer to an integer, the result will be stored here. + * \param est Pointer to an \c igraph_real_t, the result will be stored here. + * Note that even though the result is an integer, we need to use + * \c igraph_real_t to avoid overflow when igraph is compiled with + * 32-bit integers. * \param size The size of the subgraphs to look for. * \param cut_prob Vector of probabilities for cutting the search tree * at a given level. The first element is the first level, etc. @@ -544,7 +542,7 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte * Time complexity: TODO. */ -igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_integer_t *est, +igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real_t *est, igraph_integer_t size, const igraph_vector_t *cut_prob, igraph_integer_t sample_size, const igraph_vector_int_t *parsample) { @@ -608,8 +606,6 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte *est = 0; - RNG_BEGIN(); - for (sam = 0; sam < sample_size; sam++) { igraph_integer_t father = VECTOR(*sample)[sam]; igraph_integer_t level, s; @@ -629,7 +625,9 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte /* init V_E */ igraph_vector_int_clear(&adjverts); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, father, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { igraph_integer_t nei = VECTOR(neis)[i]; @@ -671,7 +669,9 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte IGRAPH_CHECK(igraph_stack_int_push(&stack, nei)); IGRAPH_CHECK(igraph_stack_int_push(&stack, level)); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, nei, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, nei, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { igraph_integer_t nei2 = VECTOR(neis)[i]; @@ -696,7 +696,9 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte nei = igraph_vector_int_pop_back(&vids); added[nei] -= 1; level -= 1; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, nei, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, nei, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { added[ VECTOR(neis)[i] ] -= 1; @@ -712,7 +714,9 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte /* clear the added vector */ added[father] -= 1; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, father, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { added[ VECTOR(neis)[i] ] -= 1; @@ -720,8 +724,6 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte } /* for father */ - RNG_END(); - (*est) *= ((igraph_real_t) no_of_nodes / sample_size); if (parsample == 0) { @@ -748,8 +750,10 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte * classes to them. Arbitrarily large motif sizes are supported. * * \param graph The graph object to study. - * \param no Pointer to an integer type, the result will be stored - * here. + * \param no Pointer to an \c igraph_real_t, the result will be stored here. + * Note that even though the result is an integer, we need to use + * \c igraph_real_t to avoid overflow when igraph is compiled with + * 32-bit integers. * \param size The size of the motifs to count. * \param cut_prob Vector of probabilities for cutting the search tree * at a given level. The first element is the first level, etc. @@ -763,8 +767,10 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte * Time complexity: TODO. */ -igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t *no, - igraph_integer_t size, const igraph_vector_t *cut_prob) { +igraph_error_t igraph_motifs_randesu_no( + const igraph_t *graph, igraph_real_t *no, igraph_integer_t size, + const igraph_vector_t *cut_prob +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t neis; @@ -796,8 +802,6 @@ igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t *no = 0; - RNG_BEGIN(); - for (father = 0; father < no_of_nodes; father++) { igraph_integer_t level, s; @@ -816,7 +820,9 @@ igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t /* init V_E */ igraph_vector_int_clear(&adjverts); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, father, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { igraph_integer_t nei = VECTOR(neis)[i]; @@ -858,7 +864,9 @@ igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t IGRAPH_CHECK(igraph_stack_int_push(&stack, nei)); IGRAPH_CHECK(igraph_stack_int_push(&stack, level)); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, nei, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, nei, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { igraph_integer_t nei2 = VECTOR(neis)[i]; @@ -883,7 +891,9 @@ igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t nei = igraph_vector_int_pop_back(&vids); added[nei] -= 1; level -= 1; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, nei, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, nei, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { added[ VECTOR(neis)[i] ] -= 1; @@ -899,7 +909,9 @@ igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t /* clear the added vector */ added[father] -= 1; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, father, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { added[ VECTOR(neis)[i] ] -= 1; @@ -907,8 +919,6 @@ igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t } /* for father */ - RNG_END(); - IGRAPH_FREE(added); igraph_vector_int_destroy(&vids); igraph_vector_int_destroy(&adjverts); @@ -967,8 +977,8 @@ igraph_error_t igraph_dyad_census(const igraph_t *graph, igraph_real_t *mut, igraph_integer_t ideg, odeg; igraph_integer_t ip, op; - IGRAPH_CHECK(igraph_i_neighbors(graph, &inneis, i, IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); - IGRAPH_CHECK(igraph_i_neighbors(graph, &outneis, i, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); + IGRAPH_CHECK(igraph_neighbors(graph, &inneis, i, IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); + IGRAPH_CHECK(igraph_neighbors(graph, &outneis, i, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); ideg = igraph_vector_int_size(&inneis); odeg = igraph_vector_int_size(&outneis); diff --git a/src/vendor/cigraph/src/misc/order_cycle.h b/src/vendor/cigraph/src/misc/order_cycle.h index 2ed87f54ee2..32dd34f67f1 100644 --- a/src/vendor/cigraph/src/misc/order_cycle.h +++ b/src/vendor/cigraph/src/misc/order_cycle.h @@ -23,13 +23,13 @@ #include "igraph_datatype.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_order_cycle( const igraph_t *graph, const igraph_vector_int_t *cycle, igraph_vector_int_t *res); -__END_DECLS +IGRAPH_END_C_DECLS #endif /* IGRAPH_ORDER_CYCLE_H */ diff --git a/src/vendor/cigraph/src/misc/other.c b/src/vendor/cigraph/src/misc/other.c index ed7363ad3b9..7b0d35025e2 100644 --- a/src/vendor/cigraph/src/misc/other.c +++ b/src/vendor/cigraph/src/misc/other.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/misc/power_law_fit.c b/src/vendor/cigraph/src/misc/power_law_fit.c index ae71225a8c3..8aebfcf4b42 100644 --- a/src/vendor/cigraph/src/misc/power_law_fit.c +++ b/src/vendor/cigraph/src/misc/power_law_fit.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -198,8 +197,6 @@ igraph_error_t igraph_power_law_fit( } } - RNG_BEGIN(); - plfit_stored_error_handler = plfit_set_error_handler(igraph_i_plfit_error_handler_store); if (discrete) { igraph_i_plfit_prepare_discrete_options(&disc_options, finite_size_correction); @@ -220,8 +217,6 @@ igraph_error_t igraph_power_law_fit( } plfit_set_error_handler(plfit_stored_error_handler); - RNG_END(); - IGRAPH_CHECK(igraph_i_handle_plfit_error(retval)); if (result) { @@ -294,8 +289,6 @@ igraph_error_t igraph_plfit_result_calculate_p_value( finite_size_correction = igraph_i_plfit_should_use_finite_size_correction(model->data); - RNG_BEGIN(); - plfit_stored_error_handler = plfit_set_error_handler(igraph_i_plfit_error_handler_store); if (model->continuous) { igraph_i_plfit_prepare_continuous_options(&cont_options, finite_size_correction); @@ -316,8 +309,6 @@ igraph_error_t igraph_plfit_result_calculate_p_value( } plfit_set_error_handler(plfit_stored_error_handler); - RNG_END(); - IGRAPH_CHECK(igraph_i_handle_plfit_error(retval)); if (result) { diff --git a/src/vendor/cigraph/src/misc/scan.c b/src/vendor/cigraph/src/misc/scan.c index 689ceb33d86..f054b2fe4e8 100644 --- a/src/vendor/cigraph/src/misc/scan.c +++ b/src/vendor/cigraph/src/misc/scan.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2013 Gabor Csardi @@ -26,7 +25,6 @@ #include "igraph_adjlist.h" #include "igraph_dqueue.h" #include "igraph_interface.h" -#include "igraph_memory.h" #include "igraph_operators.h" #include "igraph_stack.h" #include "igraph_structural.h" @@ -65,46 +63,7 @@ igraph_error_t igraph_local_scan_0(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_t *weights, igraph_neimode_t mode) { - return igraph_strength(graph, res, igraph_vss_all(), mode, /*loops=*/ 1, - weights); -} - -/* This removes loop, multiple edges and edges that point - "backwards" according to the rank vector. It works on - edge lists */ - -static igraph_error_t igraph_i_trans4_il_simplify(const igraph_t *graph, igraph_inclist_t *il, - const igraph_vector_int_t *rank) { - - igraph_integer_t i; - igraph_integer_t n = il->length; - igraph_vector_int_t mark; - - IGRAPH_VECTOR_INT_INIT_FINALLY(&mark, n); - - for (i = 0; i < n; i++) { - igraph_vector_int_t *v = &il->incs[i]; - igraph_integer_t j, l = igraph_vector_int_size(v); - igraph_integer_t irank = VECTOR(*rank)[i]; - VECTOR(mark)[i] = i + 1; - for (j = 0; j < l; /* nothing */) { - igraph_integer_t edge = VECTOR(*v)[j]; - igraph_integer_t e = IGRAPH_OTHER(graph, edge, i); - if (VECTOR(*rank)[e] > irank && VECTOR(mark)[e] != i + 1) { - VECTOR(mark)[e] = i + 1; - j++; - } else { - VECTOR(*v)[j] = igraph_vector_int_tail(v); - igraph_vector_int_pop_back(v); - l--; - } - } - } - - igraph_vector_int_destroy(&mark); - IGRAPH_FINALLY_CLEAN(1); - return IGRAPH_SUCCESS; - + return igraph_strength(graph, res, igraph_vss_all(), mode, IGRAPH_LOOPS, weights); } /* This one handles both weighted and unweighted cases */ diff --git a/src/vendor/cigraph/src/misc/sir.c b/src/vendor/cigraph/src/misc/sir.c index fb2a64f7515..d635f67aa30 100644 --- a/src/vendor/cigraph/src/misc/sir.c +++ b/src/vendor/cigraph/src/misc/sir.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2014 Gabor Csardi @@ -138,19 +137,13 @@ igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, IGRAPH_ERROR("Number of SIR simulations must be positive.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_is_simple(graph, &simple)); - if (!simple) { - IGRAPH_ERROR("SIR model only works with simple graphs.", IGRAPH_EINVAL); - } if (igraph_is_directed(graph)) { - igraph_bool_t has_mutual; IGRAPH_WARNING("Edge directions are ignored in SIR model."); - /* When the graph is directed, mutual edges are effectively multi-edges as we - * are ignoring edge directions. */ - IGRAPH_CHECK(igraph_has_mutual(graph, &has_mutual, false)); - if (has_mutual) { - IGRAPH_ERROR("SIR model only works with simple graphs.", IGRAPH_EINVAL); - } + } + + IGRAPH_CHECK(igraph_is_simple(graph, &simple, IGRAPH_UNDIRECTED)); + if (!simple) { + IGRAPH_ERROR("SIR model only works with simple graphs.", IGRAPH_EINVAL); } IGRAPH_CHECK(igraph_vector_int_init(&status, no_of_nodes)); @@ -172,8 +165,6 @@ igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, VECTOR(*result)[i] = sir; } - RNG_BEGIN(); - for (j = 0; j < no_sim; j++) { igraph_sir_t *sir = VECTOR(*result)[j]; @@ -265,8 +256,6 @@ igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, } /* j < no_sim */ - RNG_END(); - igraph_psumtree_destroy(&tree); igraph_adjlist_destroy(&adjlist); igraph_vector_int_destroy(&status); diff --git a/src/vendor/cigraph/src/misc/spanning_trees.c b/src/vendor/cigraph/src/misc/spanning_trees.c index 77413945a1b..06089d65cb0 100644 --- a/src/vendor/cigraph/src/misc/spanning_trees.c +++ b/src/vendor/cigraph/src/misc/spanning_trees.c @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2011-2023 The igraph development team + Copyright (C) 2011-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 @@ -21,202 +21,71 @@ #include "igraph_components.h" #include "igraph_dqueue.h" #include "igraph_interface.h" -#include "igraph_operators.h" #include "igraph_random.h" #include "igraph_structural.h" #include "core/indheap.h" #include "core/interruption.h" -static igraph_error_t igraph_i_minimum_spanning_tree_unweighted( - const igraph_t *graph, igraph_vector_int_t *result); -static igraph_error_t igraph_i_minimum_spanning_tree_prim( - const igraph_t *graph, igraph_vector_int_t *result, const igraph_vector_t *weights); +static igraph_integer_t max_tree_edges(igraph_integer_t no_of_nodes, igraph_integer_t no_of_edges) { + if (no_of_nodes == 0) return 0; + if (no_of_edges < no_of_nodes) return no_of_edges; + return no_of_nodes - 1; +} + + +/* Unweighted case -- just a simple BFS */ /** * \ingroup structural - * \function igraph_minimum_spanning_tree - * \brief Calculates one minimum spanning tree of a graph. + * \function igraph_i_minimum_spanning_tree_unweighted + * \brief A spanning tree of an unweighted graph. * - * Finds a spanning tree of the graph. If the graph is not connected - * then its minimum spanning forest is returned. This is the set of the - * minimum spanning trees of each component. + * Produces an arbitrary spanning tree of the graph. * * - * Directed graphs are considered as undirected for this computation. + * Directed graphs are treated as undirected for this computation. * * - * This function is deterministic, i.e. it always returns the same - * spanning tree. See \ref igraph_random_spanning_tree() for the uniform - * random sampling of spanning trees of a graph. + * If the graph is not connected then a spanning forest is returned. + * This is a set of spanning trees of each component. * - * \param graph The graph object. + * \param graph The graph object. Edge directions will be ignored. * \param res An initialized vector, the IDs of the edges that constitute * a spanning tree will be returned here. Use * \ref igraph_subgraph_from_edges() to extract the spanning tree as * a separate graph object. - * \param weights A vector containing the weights of the edges - * in the same order as the simple edge iterator visits them - * (i.e. in increasing order of edge IDs). - * \return Error code: - * \c IGRAPH_ENOMEM, not enough memory for - * temporary data. - * - * Time complexity: O(|V|+|E|) for the unweighted case, O(|E| log |V|) - * for the weighted case. |V| is the number of vertices, |E| the - * number of edges in the graph. - * - * \sa \ref igraph_minimum_spanning_tree_unweighted() and - * \ref igraph_minimum_spanning_tree_prim() if you only need the - * tree as a separate graph object. - * - * \example examples/simple/igraph_minimum_spanning_tree.c - */ -igraph_error_t igraph_minimum_spanning_tree( - const igraph_t *graph, igraph_vector_int_t *res, const igraph_vector_t *weights -) { - if (weights == NULL) { - IGRAPH_CHECK(igraph_i_minimum_spanning_tree_unweighted(graph, res)); - } else { - IGRAPH_CHECK(igraph_i_minimum_spanning_tree_prim(graph, res, weights)); - } - return IGRAPH_SUCCESS; -} - -/** - * \ingroup structural - * \function igraph_minimum_spanning_tree_unweighted - * \brief Calculates one minimum spanning tree of an unweighted graph. - * - * \deprecated-by igraph_minimum_spanning_tree 0.10.14 - * - * If the graph has more minimum spanning trees (this is always the - * case, except if it is a forest) this implementation returns only - * the same one. - * - * - * Directed graphs are considered as undirected for this computation. - * - * - * If the graph is not connected then its minimum spanning forest is - * returned. This is the set of the minimum spanning trees of each - * component. - * - * \param graph The graph object. Edge directions will be ignored. - * \param mst The minimum spanning tree, another graph object. Do - * \em not initialize this object before passing it to - * this function, but be sure to call \ref igraph_destroy() on it if - * you don't need it any more. * \return Error code: - * \c IGRAPH_ENOMEM, not enough memory for - * temporary data. + * \c IGRAPH_ENOMEM, not enough memory for temporary data. * * Time complexity: O(|V|+|E|), * |V| is the * number of vertices, |E| the number * of edges in the graph. * - * \sa \ref igraph_minimum_spanning_tree_prim() for weighted graphs, - * \ref igraph_minimum_spanning_tree() if you need the IDs of the - * edges that constitute the spanning tree. + * \sa \ref igraph_minimum_spanning_tree() for a common interface to all + * minimum spanning tree algorithms. */ -igraph_error_t igraph_minimum_spanning_tree_unweighted(const igraph_t *graph, - igraph_t *mst) { - igraph_vector_int_t edges; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_nodes > 0 ? no_of_nodes - 1 : 0); - IGRAPH_CHECK(igraph_i_minimum_spanning_tree_unweighted(graph, &edges)); - IGRAPH_CHECK(igraph_subgraph_from_edges( - graph, mst, igraph_ess_vector(&edges), /* delete_vertices = */ false)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - -/** - * \ingroup structural - * \function igraph_minimum_spanning_tree_prim - * \brief Calculates one minimum spanning tree of a weighted graph. - * - * \deprecated-by igraph_minimum_spanning_tree 0.10.14 - * - * Finds a spanning tree or spanning forest for which the sum of edge - * weights is the smallest. This function uses Prim's method for carrying - * out the computation. - * - * - * Directed graphs are considered as undirected for this computation. - * - * - * Reference: - * - * - * Prim, R.C.: Shortest connection networks and some - * generalizations, Bell System Technical - * Journal, Vol. 36, - * 1957, 1389--1401. - * https://doi.org/10.1002/j.1538-7305.1957.tb01515.x - * - * \param graph The graph object. Edge directions will be ignored. - * \param mst The result of the computation, a graph object containing - * the minimum spanning tree of the graph. - * Do \em not initialize this object before passing it to - * this function, but be sure to call \ref igraph_destroy() on it if - * you don't need it any more. - * \param weights A vector containing the weights of the edges - * in the same order as the simple edge iterator visits them - * (i.e. in increasing order of edge IDs). - * \return Error code: - * \c IGRAPH_ENOMEM, not enough memory. - * \c IGRAPH_EINVAL, length of weight vector does not - * match number of edges. - * - * Time complexity: O(|E| log |V|), - * |V| is the number of vertices, - * |E| the number of edges in the - * graph. - * - * \sa \ref igraph_minimum_spanning_tree_unweighted() for unweighted graphs, - * \ref igraph_minimum_spanning_tree() if you need the IDs of the - * edges that constitute the spanning tree. - * - * \example examples/simple/igraph_minimum_spanning_tree.c - */ - -igraph_error_t igraph_minimum_spanning_tree_prim(const igraph_t *graph, igraph_t *mst, - const igraph_vector_t *weights) { - igraph_vector_int_t edges; - - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, igraph_vcount(graph) - 1); - IGRAPH_CHECK(igraph_i_minimum_spanning_tree_prim(graph, &edges, weights)); - IGRAPH_CHECK(igraph_subgraph_from_edges( - graph, mst, igraph_ess_vector(&edges), /* delete_vertices = */ false)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - - -static igraph_error_t igraph_i_minimum_spanning_tree_unweighted(const igraph_t* graph, igraph_vector_int_t* res) { +static igraph_error_t igraph_i_minimum_spanning_tree_unweighted( + const igraph_t* graph, + igraph_vector_int_t* res) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_bitset_t already_added, added_edges; igraph_dqueue_int_t q; igraph_vector_int_t eids; - igraph_vector_int_clear(res); - IGRAPH_BITSET_INIT_FINALLY(&added_edges, no_of_edges); IGRAPH_BITSET_INIT_FINALLY(&already_added, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&eids, 0); IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100); + igraph_vector_int_clear(res); + IGRAPH_CHECK(igraph_vector_int_reserve(res, max_tree_edges(no_of_nodes, no_of_edges))); + /* Perform a BFS */ for (igraph_integer_t i = 0; i < no_of_nodes; i++) { if (IGRAPH_BIT_TEST(already_added, i)) { @@ -230,8 +99,7 @@ static igraph_error_t igraph_i_minimum_spanning_tree_unweighted(const igraph_t* while (! igraph_dqueue_int_empty(&q)) { igraph_integer_t eids_size; igraph_integer_t act_node = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_incident(graph, &eids, act_node, - IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &eids, act_node, IGRAPH_ALL, IGRAPH_LOOPS)); eids_size = igraph_vector_int_size(&eids); for (igraph_integer_t j = 0; j < eids_size; j++) { igraph_integer_t edge = VECTOR(eids)[j]; @@ -240,7 +108,7 @@ static igraph_error_t igraph_i_minimum_spanning_tree_unweighted(const igraph_t* if (! IGRAPH_BIT_TEST(already_added, to)) { IGRAPH_BIT_SET(already_added, to); IGRAPH_BIT_SET(added_edges, edge); - IGRAPH_CHECK(igraph_vector_int_push_back(res, edge)); + igraph_vector_int_push_back(res, edge); /* reserved */ IGRAPH_CHECK(igraph_dqueue_int_push(&q, to)); } } @@ -257,20 +125,66 @@ static igraph_error_t igraph_i_minimum_spanning_tree_unweighted(const igraph_t* return IGRAPH_SUCCESS; } + +/* Prims' algorithm */ + +/** + * \ingroup structural + * \function igraph_i_minimum_spanning_tree_prim + * \brief A minimum spanning tree of a weighted graph using Prim's method. + * + * Finds a spanning tree or spanning forest for which the sum of edge + * weights is the smallest. This function uses Prim's method for carrying + * out the computation. + * + * + * Directed graphs are treated as undirected for this computation. + * + * + * Reference: + * + * + * Prim, R.C.: Shortest connection networks and some + * generalizations, Bell System Technical + * Journal, Vol. 36, + * 1957, 1389--1401. + * https://doi.org/10.1002/j.1538-7305.1957.tb01515.x + * + * \param graph The graph object. Edge directions will be ignored. + * \param res An initialized vector, the IDs of the edges that constitute + * a spanning tree will be returned here. Use + * \ref igraph_subgraph_from_edges() to extract the spanning tree as + * a separate graph object. + * \param weights A vector containing the weights of the edges in the order + * of edge IDs. Weights must not be NaN. + * \return Error code: + * \c IGRAPH_ENOMEM, not enough memory. + * \c IGRAPH_EINVAL, length of weight vector does not + * match number of edges, or NaN in weights. + * + * Time complexity: O(|E| log |V|), + * |V| is the number of vertices, + * |E| the number of edges in the + * graph. + * + * \sa \ref igraph_minimum_spanning_tree() for a common interface to all + * minimum spanning tree algorithms. + * + * \example examples/simple/igraph_minimum_spanning_tree.c + */ + static igraph_error_t igraph_i_minimum_spanning_tree_prim( - const igraph_t* graph, igraph_vector_int_t* res, const igraph_vector_t *weights) { + const igraph_t* graph, + igraph_vector_int_t* res, + const igraph_vector_t *weights) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_bitset_t already_added, added_edges; igraph_d_indheap_t heap; - const igraph_neimode_t mode = IGRAPH_ALL; - igraph_vector_int_t adj; - igraph_vector_int_clear(res); - if (weights == NULL) { return igraph_i_minimum_spanning_tree_unweighted(graph, res); } @@ -280,9 +194,12 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( } if (igraph_vector_is_any_nan(weights)) { - IGRAPH_ERROR("Weigths must not contain NaN values.", IGRAPH_EINVAL); + IGRAPH_ERROR("Weights must not contain NaN values.", IGRAPH_EINVAL); } + igraph_vector_int_clear(res); + IGRAPH_CHECK(igraph_vector_int_reserve(res, max_tree_edges(no_of_nodes, no_of_edges))); + IGRAPH_BITSET_INIT_FINALLY(&added_edges, no_of_edges); IGRAPH_BITSET_INIT_FINALLY(&already_added, no_of_nodes); @@ -300,7 +217,7 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( IGRAPH_BIT_SET(already_added, i); /* add all edges of the first vertex */ - IGRAPH_CHECK(igraph_incident(graph, &adj, i, mode)); + IGRAPH_CHECK(igraph_incident(graph, &adj, i, IGRAPH_ALL, IGRAPH_LOOPS)); adj_size = igraph_vector_int_size(&adj); for (igraph_integer_t j = 0; j < adj_size; j++) { igraph_integer_t edgeno = VECTOR(adj)[j]; @@ -320,19 +237,19 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( /* Is this edge already included? */ if (! IGRAPH_BIT_TEST(added_edges, edge)) { - igraph_integer_t to = IGRAPH_OTHER(graph, edge, from); + const igraph_integer_t to = IGRAPH_OTHER(graph, edge, from); /* Does it point to a visited node? */ if (! IGRAPH_BIT_TEST(already_added, to)) { IGRAPH_BIT_SET(already_added, to); IGRAPH_BIT_SET(added_edges, edge); - IGRAPH_CHECK(igraph_vector_int_push_back(res, edge)); + igraph_vector_int_push_back(res, edge); /* reserved */ /* add all outgoing edges */ - IGRAPH_CHECK(igraph_incident(graph, &adj, to, mode)); + IGRAPH_CHECK(igraph_incident(graph, &adj, to, IGRAPH_ALL, IGRAPH_LOOPS)); adj_size = igraph_vector_int_size(&adj); for (igraph_integer_t j = 0; j < adj_size; j++) { - igraph_integer_t edgeno = VECTOR(adj)[j]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, edgeno, to); + const igraph_integer_t edgeno = VECTOR(adj)[j]; + const igraph_integer_t neighbor = IGRAPH_OTHER(graph, edgeno, to); if (! IGRAPH_BIT_TEST(already_added, neighbor)) { IGRAPH_CHECK(igraph_d_indheap_push(&heap, -VECTOR(*weights)[edgeno], to, edgeno)); } @@ -352,6 +269,221 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( } +/* Kruskal's algorithm */ + +static igraph_integer_t get_comp(igraph_vector_int_t *comp, igraph_integer_t i) { + igraph_integer_t k = i; + for (;;) { + igraph_integer_t next = VECTOR(*comp)[k]; + if (next == k) { + VECTOR(*comp)[i] = k; + return k; + } else { + k = next; + } + } +} + +static void merge_comp(igraph_vector_int_t *comp, igraph_integer_t i, igraph_integer_t j) { + igraph_integer_t ci = get_comp(comp, i); + igraph_integer_t cj = get_comp(comp, j); + VECTOR(*comp)[ci] = cj; +} + +/** + * \ingroup structural + * \function igraph_i_minimum_spanning_tree_kruskal + * \brief A minimum spanning tree of a weighted graph using Kruskal's method. + * + * Finds a spanning tree or spanning forest for which the sum of edge + * weights is the smallest. This function uses Kruskal's method for carrying + * out the computation. + * + * + * Directed graphs are treated as undirected for this computation. + * + * + * Reference: + * + * + * Kruskal, J. B.: + * On the shortest spanning subtree of a graph and the traveling salesman problem, + * Proc. Amer. Math. Soc. 7 (1956), 48-50 + * https://doi.org/10.1090%2FS0002-9939-1956-0078686-7 + * + * \param graph The graph object. Edge directions will be ignored. + * \param res An initialized vector, the IDs of the edges that constitute + * a spanning tree will be returned here. Use + * \ref igraph_subgraph_from_edges() to extract the spanning tree as + * a separate graph object. + * \param weights A vector containing the weights of the edges in the order + * of edge IDs. Weights must not be NaN. + * \return Error code: + * \c IGRAPH_ENOMEM, not enough memory. + * \c IGRAPH_EINVAL, length of weight vector does not + * match number of edges, or NaN in weights. + * + * Time complexity: O(|E| log |E|), + * |V| is the number of vertices, + * |E| the number of edges in the + * graph. + * + * \sa \ref igraph_minimum_spanning_tree() for a common interface to all + * minimum spanning tree algorithms. + * + * \example examples/simple/igraph_minimum_spanning_tree.c + */ + +static igraph_error_t igraph_i_minimum_spanning_tree_kruskal( + const igraph_t *graph, + igraph_vector_int_t *res, + const igraph_vector_t *weights) { + + const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_vector_int_t idx, comp; + igraph_integer_t tree_edge_count; + int iter = 0; + + if (weights == NULL) { + return igraph_i_minimum_spanning_tree_unweighted(graph, res); + } + + if (igraph_vector_size(weights) != igraph_ecount(graph)) { + IGRAPH_ERROR("Weight vector length does not match number of edges.", IGRAPH_EINVAL); + } + + if (igraph_vector_is_any_nan(weights)) { + IGRAPH_ERROR("Weights must not contain NaN values.", IGRAPH_EINVAL); + } + + IGRAPH_VECTOR_INT_INIT_FINALLY(&idx, no_of_edges); + IGRAPH_CHECK(igraph_vector_sort_ind(weights, &idx, IGRAPH_ASCENDING)); + + IGRAPH_CHECK(igraph_vector_int_init_range(&comp, 0, no_of_nodes)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &comp); + + igraph_vector_int_clear(res); + IGRAPH_CHECK(igraph_vector_int_reserve(res, max_tree_edges(no_of_nodes, no_of_edges))); + + tree_edge_count = 0; + for (igraph_integer_t i=0; i < no_of_edges; i++) { + igraph_integer_t edge = VECTOR(idx)[i]; + igraph_integer_t u = IGRAPH_FROM(graph, edge); + igraph_integer_t v = IGRAPH_TO(graph, edge); + + igraph_integer_t cu = get_comp(&comp, u); + igraph_integer_t cv = get_comp(&comp, v); + + if (cu != cv) { + merge_comp(&comp, u, v); + igraph_vector_int_push_back(res, edge); /* reserved */ + tree_edge_count++; + } + + if (tree_edge_count == no_of_nodes - 1) { + /* We have enough edges for a tree. */ + break; + } + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 16); + } + + igraph_vector_int_destroy(&idx); + igraph_vector_int_destroy(&comp); + IGRAPH_FINALLY_CLEAN(2); + + return IGRAPH_SUCCESS; +} + + +/** + * \ingroup structural + * \function igraph_minimum_spanning_tree + * \brief Calculates a minimum spanning tree of a graph. + * + * Finds a minimum weight spanning tree of the graph. If the graph is not + * connected then its minimum spanning forest is returned, i.e. the set + * of the minimum spanning trees of each component. + * + * + * Directed graphs are treated as undirected for this computation. + * + * + * This function is deterministic, i.e. it always returns the same + * spanning tree. See \ref igraph_random_spanning_tree() for the uniform + * random sampling of spanning trees of a graph. + * + * + * References: + * + * + * Prim, R.C.: Shortest connection networks and some + * generalizations, Bell System Technical + * Journal, Vol. 36, + * 1957, 1389--1401. + * https://doi.org/10.1002/j.1538-7305.1957.tb01515.x + * + * + * Kruskal, J. B.: + * On the shortest spanning subtree of a graph and the traveling salesman problem, + * Proc. Amer. Math. Soc. 7 (1956), 48-50 + * https://doi.org/10.1090%2FS0002-9939-1956-0078686-7 + * + * \param graph The graph object. Edge directions will be ignored. + * \param res An initialized vector, the IDs of the edges that constitute + * a spanning tree will be returned here. Use + * \ref igraph_subgraph_from_edges() to extract the spanning tree as + * a separate graph object. + * \param weights A vector containing the weights of the edges in the order + * of edge IDs. Weights must not be NaN. Supply \c NULL to treat all + * edges as having the same weight. + * \param method The type of the algorithm used. + * \clist + * \cli IGRAPH_MST_AUTOMATIC + * tries to select the best performing algorithm for the current graph. + * \cli IGRAPH_MST_UNWEIGHTED + * ignores edge weights and produces an arbitrary spanning tree. + * \cli IGRAPH_MST_PRIM + * uses Prim's algorithm. + * \cli IGRAPH_MST_KRUSKAL + * uses Kruskal's algorithm. + * \endclist + * \return Error code. + * + * Time complexity: See the functions implementing the specific algorithms. + * + * \sa \ref igraph_random_spanning_tree() to compute a random spanning tree + * instead of a minimum one. + * + * \example examples/simple/igraph_minimum_spanning_tree.c + */ +igraph_error_t igraph_minimum_spanning_tree( + const igraph_t *graph, igraph_vector_int_t *res, + const igraph_vector_t *weights, igraph_mst_algorithm_t method) +{ + if (method == IGRAPH_MST_AUTOMATIC) { + /* For now we use igraph_minimum_spanning_tree_kruskal() unconditionally + * for the weighted case; see benchmarks. */ + if (weights == NULL) { + method = IGRAPH_MST_UNWEIGHTED; + } else { + method = IGRAPH_MST_KRUSKAL; + } + } + switch (method) { + case IGRAPH_MST_UNWEIGHTED: + return igraph_i_minimum_spanning_tree_unweighted(graph, res); + case IGRAPH_MST_PRIM: + return igraph_i_minimum_spanning_tree_prim(graph, res, weights); + case IGRAPH_MST_KRUSKAL: + return igraph_i_minimum_spanning_tree_kruskal(graph, res, weights); + default: + IGRAPH_ERROR("Invalid method for minimum spanning tree.", IGRAPH_EINVAL); + } +} + + /* igraph_random_spanning_tree */ /* Loop-erased random walk (LERW) implementation. @@ -370,8 +502,6 @@ static igraph_error_t igraph_i_lerw(const igraph_t *graph, igraph_vector_int_t * VECTOR(*visited)[start] = true; visited_count = 1; - RNG_BEGIN(); - while (visited_count < comp_size) { igraph_integer_t degree, edge; igraph_vector_int_t *edges; @@ -395,8 +525,6 @@ static igraph_error_t igraph_i_lerw(const igraph_t *graph, igraph_vector_int_t * IGRAPH_ALLOW_INTERRUPTION(); } - RNG_END(); - return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/operators/add_edge.c b/src/vendor/cigraph/src/operators/add_edge.c index 57924919c2f..b0f179fe97b 100644 --- a/src/vendor/cigraph/src/operators/add_edge.c +++ b/src/vendor/cigraph/src/operators/add_edge.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team diff --git a/src/vendor/cigraph/src/operators/complementer.c b/src/vendor/cigraph/src/operators/complementer.c index f6a41c6327a..3324d881368 100644 --- a/src/vendor/cigraph/src/operators/complementer.c +++ b/src/vendor/cigraph/src/operators/complementer.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team @@ -68,7 +67,7 @@ igraph_error_t igraph_complementer(igraph_t *res, const igraph_t *graph, for (i = 0; i < no_of_nodes; i++) { IGRAPH_ALLOW_INTERRUPTION(); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); if (loops) { for (j = no_of_nodes - 1; j >= *limit; j--) { if (igraph_vector_int_empty(&neis) || j > igraph_vector_int_tail(&neis)) { @@ -95,8 +94,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/compose.c b/src/vendor/cigraph/src/operators/compose.c index 6c3373c3b3f..ab5681f413f 100644 --- a/src/vendor/cigraph/src/operators/compose.c +++ b/src/vendor/cigraph/src/operators/compose.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team @@ -96,12 +95,12 @@ igraph_error_t igraph_compose(igraph_t *res, for (igraph_integer_t i = 0; i < no_of_nodes_left; i++) { IGRAPH_ALLOW_INTERRUPTION(); - IGRAPH_CHECK(igraph_incident(g1, &neis1, i, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(g1, &neis1, i, IGRAPH_OUT, IGRAPH_LOOPS)); while (!igraph_vector_int_empty(&neis1)) { const igraph_integer_t con = igraph_vector_int_pop_back(&neis1); const igraph_integer_t v1 = IGRAPH_OTHER(g1, con, i); if (v1 < no_of_nodes_right) { - IGRAPH_CHECK(igraph_incident(g2, &neis2, v1, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(g2, &neis2, v1, IGRAPH_OUT, IGRAPH_LOOPS)); } else { continue; } diff --git a/src/vendor/cigraph/src/operators/connect_neighborhood.c b/src/vendor/cigraph/src/operators/connect_neighborhood.c index a0ada48a3e5..d9172968d1f 100644 --- a/src/vendor/cigraph/src/operators/connect_neighborhood.c +++ b/src/vendor/cigraph/src/operators/connect_neighborhood.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -99,7 +98,7 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord for (i = 0; i < no_of_nodes; i++) { added[i] = i + 1; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); in = igraph_vector_int_size(&neis); if (order > 1) { for (j = 0; j < in; j++) { @@ -114,7 +113,7 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord igraph_integer_t actnode = igraph_dqueue_int_pop(&q); igraph_integer_t actdist = igraph_dqueue_int_pop(&q); igraph_integer_t n; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); n = igraph_vector_int_size(&neis); if (actdist < order - 1) { @@ -171,11 +170,9 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord /** * \function igraph_graph_power - * \brief The kth power of a graph. + * \brief The k-th power of a graph. * - * \experimental - * - * The kth power of a graph G is a simple graph where vertex \c u is connected to + * The k-th power of a graph G is a simple graph where vertex \c u is connected to * \c v by a single edge if \c v is reachable from \c u in G within at most k steps. * By convention, the zeroth power of a graph has no edges. The first power is * identical to the original graph, except that multiple edges and self-loops @@ -218,8 +215,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 bb965d52a43..3d285e6bc71 100644 --- a/src/vendor/cigraph/src/operators/contract.c +++ b/src/vendor/cigraph/src/operators/contract.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2021 The igraph development team @@ -116,8 +115,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..adadd3bcf64 100644 --- a/src/vendor/cigraph/src/operators/difference.c +++ b/src/vendor/cigraph/src/operators/difference.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team @@ -171,8 +170,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/disjoint_union.c b/src/vendor/cigraph/src/operators/disjoint_union.c index f6e31ab4cfe..6c012638bbc 100644 --- a/src/vendor/cigraph/src/operators/disjoint_union.c +++ b/src/vendor/cigraph/src/operators/disjoint_union.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team diff --git a/src/vendor/cigraph/src/operators/intersection.c b/src/vendor/cigraph/src/operators/intersection.c index 006e390d73e..2cade98cfd9 100644 --- a/src/vendor/cigraph/src/operators/intersection.c +++ b/src/vendor/cigraph/src/operators/intersection.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team diff --git a/src/vendor/cigraph/src/operators/join.c b/src/vendor/cigraph/src/operators/join.c index 57bb2d99803..cbedae4e25d 100644 --- a/src/vendor/cigraph/src/operators/join.c +++ b/src/vendor/cigraph/src/operators/join.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2024 The igraph development team @@ -26,8 +25,6 @@ * \function igraph_join * \brief Creates the join of two disjoint graphs. * - * \experimental - * * First the vertices of the second graph will be relabeled with new * vertex IDs to have two disjoint sets of vertex IDs, then the union * of the two graphs will be formed. Finally, the vertces from the diff --git a/src/vendor/cigraph/src/operators/misc_internal.c b/src/vendor/cigraph/src/operators/misc_internal.c index f57d88d35d0..9ff882bd704 100644 --- a/src/vendor/cigraph/src/operators/misc_internal.c +++ b/src/vendor/cigraph/src/operators/misc_internal.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team diff --git a/src/vendor/cigraph/src/operators/misc_internal.h b/src/vendor/cigraph/src/operators/misc_internal.h index 2dc7cc7b5ad..878a41b5379 100644 --- a/src/vendor/cigraph/src/operators/misc_internal.h +++ b/src/vendor/cigraph/src/operators/misc_internal.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2020 The igraph development team @@ -30,7 +29,7 @@ #include "igraph_vector.h" #include "igraph_vector_ptr.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS typedef enum { IGRAPH_MERGE_MODE_UNION = 1, @@ -42,6 +41,6 @@ igraph_error_t igraph_i_merge(igraph_t *res, igraph_i_merge_mode_t mode, const igraph_t *left, const igraph_t *right, igraph_vector_int_t *edge_map1, igraph_vector_int_t *edge_map2); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/operators/permute.c b/src/vendor/cigraph/src/operators/permute.c index f84ba6bc663..cb72aea1751 100644 --- a/src/vendor/cigraph/src/operators/permute.c +++ b/src/vendor/cigraph/src/operators/permute.c @@ -1,7 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2020 The igraph development team + Copyright (C) 2006-2025 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 @@ -14,17 +13,14 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #include "igraph_operators.h" +#include "igraph_isomorphism.h" #include "igraph_constructors.h" #include "igraph_interface.h" -#include "igraph_topology.h" #include "graph/attributes.h" @@ -46,7 +42,7 @@ igraph_error_t igraph_invert_permutation(const igraph_vector_int_t *permutation, IGRAPH_CHECK(igraph_vector_int_resize(inverse, n)); igraph_vector_int_fill(inverse, -1); - for (igraph_integer_t i=0; i < n; i++) { + for (igraph_integer_t i = 0; i < n; i++) { igraph_integer_t j = VECTOR(*permutation)[i]; if (j < 0 || j >= n) { IGRAPH_ERROR("Invalid index in permutation vector.", IGRAPH_EINVAL); @@ -73,8 +69,9 @@ igraph_error_t igraph_invert_permutation(const igraph_vector_int_t *permutation, * \param graph The input graph. * \param res Pointer to an uninitialized graph object. The new graph * is created here. - * \param permutation The permutation to apply. Vertex 0 is mapped to - * the first element of the vector, vertex 1 to the second, etc. + * \param permutation The permutation to apply. The i-th element of the + * vector specifies the index of the vertex in the original graph that + * will become vertex i in the new graph. * \return Error code. * * Time complexity: O(|V|+|E|), linear in terms of the number of @@ -102,8 +99,8 @@ igraph_error_t igraph_permute_vertices(const igraph_t *graph, igraph_t *res, p = 0; for (igraph_integer_t i = 0; i < no_of_edges; i++) { - VECTOR(edges)[p++] = VECTOR(*permutation)[ IGRAPH_FROM(graph, i) ]; - VECTOR(edges)[p++] = VECTOR(*permutation)[ IGRAPH_TO(graph, i) ]; + VECTOR(edges)[p++] = VECTOR(index)[ IGRAPH_FROM(graph, i) ]; + VECTOR(edges)[p++] = VECTOR(index)[ IGRAPH_TO(graph, i) ]; } IGRAPH_CHECK(igraph_create(res, &edges, no_of_nodes, igraph_is_directed(graph))); @@ -112,12 +109,11 @@ 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) { - IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, res, &index)); + IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, res, permutation)); } igraph_vector_int_destroy(&vtypes); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/operators/products.c b/src/vendor/cigraph/src/operators/products.c index da2021270dd..ac84006ed77 100644 --- a/src/vendor/cigraph/src/operators/products.c +++ b/src/vendor/cigraph/src/operators/products.c @@ -20,6 +20,7 @@ #include "igraph_constructors.h" #include "igraph_interface.h" +#include "igraph_structural.h" #include "math/safe_intop.h" @@ -332,6 +333,58 @@ static igraph_error_t tensor_product(igraph_t *res, return IGRAPH_SUCCESS; } +static igraph_error_t modular_product(igraph_t *res, + const igraph_t *g1, + const igraph_t *g2) { + + const igraph_bool_t directed = igraph_is_directed(g1); + + if (igraph_is_directed(g2) != directed) { + IGRAPH_ERROR("Modular product between a directed and an undirected graph is invalid.", + IGRAPH_EINVAL); + } + + igraph_bool_t is_simple1, is_simple2; + IGRAPH_CHECK(igraph_is_simple(g1, &is_simple1, IGRAPH_DIRECTED)); + IGRAPH_CHECK(igraph_is_simple(g2, &is_simple2, IGRAPH_DIRECTED)); + + if (!is_simple1 || !is_simple2) { + IGRAPH_ERROR("Modular product requires simple graphs as input.", IGRAPH_EINVAL); + } + + // See: https://en.wikipedia.org/wiki/Graph_product#Overview_table + + igraph_t g1_compl, g2_compl; + IGRAPH_CHECK(igraph_complementer(&g1_compl, g1, /*loops*/ false)); + IGRAPH_FINALLY(igraph_destroy, &g1_compl); + + IGRAPH_CHECK(igraph_complementer(&g2_compl, g2, /*loops*/ false)); + IGRAPH_FINALLY(igraph_destroy, &g2_compl); + + // Condition 2 of adjacency is same as tensor product of complements, without loop + igraph_t tensor_compl; + IGRAPH_CHECK(tensor_product(&tensor_compl, &g1_compl, &g2_compl)); + + igraph_destroy(&g2_compl); + igraph_destroy(&g1_compl); + IGRAPH_FINALLY_CLEAN(2); + + IGRAPH_FINALLY(igraph_destroy, &tensor_compl); + + // Condition 1 of adjacency is same as tensor product + igraph_t tensor; + IGRAPH_CHECK(tensor_product(&tensor, g1, g2)); + IGRAPH_FINALLY(igraph_destroy, &tensor); + + IGRAPH_CHECK(igraph_union(res, &tensor, &tensor_compl, /*edge_map1*/ NULL, /*edge_map2*/ NULL)); + + igraph_destroy(&tensor); + igraph_destroy(&tensor_compl); + IGRAPH_FINALLY_CLEAN(2); + + return IGRAPH_SUCCESS; +} + /** * \function igraph_product * \brief The graph product of two graphs, according to the chosen product type. @@ -419,16 +472,33 @@ static igraph_error_t tensor_product(igraph_t *res, * 2 |E1| |E2| in the undirected case. * * - * Time Complexity: O(|V1| |V2| + |E1| |E2|) + * Time complexity: O(|V1| |V2| + |E1| |E2|) * where |V1| and |V2| are the number of vertices, and * |E1| and |E2| are the number of edges of the operands. + * + * \cli IGRAPH_PRODUCT_MODULAR + * Computes the modular product of two graphs. In the product graph, + * there is a connection from (u1, v1) to (u2, v2) + * if and only if + * u1 ~ u2 and v1 ~ v2 or + * NOT (u1 ~ u2) and NOT (v1 ~ v2). + * The modular product requires both graphs to be simple. + * Thus, the number of edges in the product is + * |E1| |E2| + |E1'| |E2'| in the directed case and + * 2 |E1| |E2| + 2 |E1'| |E2'| in the undirected case. + * + * + * Time complexity: O(|V1| |V2| + |E1| |E2| + |E1'| |E2'|) + * where |V1| and |V2| are the number of vertices, + * |E1| and |E2| are the number of edges of the operands, and + * |E1'| and |E2'| are the number of edges of their complement. * \endclist * * * Reference: * - * - * Richar Hammack, Wilfried Imrich, and Sandi Klavžar (2011). + * + * Richard Hammack, Wilfried Imrich, and Sandi Klavžar (2011). * Handbook of Product Graphs (2nd ed.). CRC Press. * https://doi.org/10.1201/b10959 * @@ -441,6 +511,8 @@ static igraph_error_t tensor_product(igraph_t *res, * \return Error code: * \c IGRAPH_EINVAL if the specified \p type is unsupported or the input * graphs \p g1 and \p g2 are incompatible for the requested product. + * + * \sa \ref igraph_rooted_product() for the rooted product. */ igraph_error_t igraph_product(igraph_t *res, @@ -460,7 +532,121 @@ igraph_error_t igraph_product(igraph_t *res, case IGRAPH_PRODUCT_TENSOR: return tensor_product(res, g1, g2); + case IGRAPH_PRODUCT_MODULAR: + return modular_product(res, g1, g2); + default: IGRAPH_ERROR("Unknown graph product type.", IGRAPH_EINVAL); } } + +/** + * \function igraph_rooted_product + * \brief The rooted graph product of two graphs. + * + * \experimental + * + * This function computes the rooted product of two graphs. The two graphs + * must be of the same type, either directed or undirected. If a product of + * an undirected and a directed graph is required, convert one of them to the + * appropriate type using \ref igraph_to_directed() or \ref igraph_to_undirected(). + * + * + * The vertex IDs in the product graph related to the IDs in the operands in + * the same convention as in \ref igraph_product(). + * + * + * In the rooted product graph of G and H, with root vertex ID \p root in H, + * there is a connection from (u1, v1) to (u2, v2) + * if and only if + * u1 = u2 and v1 ~ v2 or + * u1 ~ u2 and v1 = v2 = root. + * Thus, the number of edges in the product graph is + * |V1| |E2| + |E1|. + * + * \param res Pointer to an uninitialized graph object. The product graph will + * be stored here. + * \param g1 The first operand graph. + * \param g2 The second operand graph. It must have the same directedness as \p g1. + * \param root The root vertex id of the second graph. + * + * \return Error code: + * \c IGRAPH_EINVAL if the specified \p type is unsupported or the input + * graphs \p g1 and \p g2 are incompatible for the requested product. + * \c IGRAPH_EINVVID if invalid vertex ID passed as \p root. + * + * \sa \ref igraph_product() for other types of graph products. + * + * Time complexity: O(|V1| |V2| + |V1| |E2| + |E1|) + * where |V1| and |V2| are the number of vertices, and + * |E1| and |E2| are the number of edges of the operands. + */ + +igraph_error_t igraph_rooted_product(igraph_t *res, + const igraph_t *g1, + const igraph_t *g2, + const igraph_integer_t root) { + + const igraph_bool_t directed = igraph_is_directed(g1); + + if (igraph_is_directed(g2) != directed) { + IGRAPH_ERROR("Rooted product between a directed and an undirected graph is invalid.", + IGRAPH_EINVAL); + } + + const igraph_integer_t vcount1 = igraph_vcount(g1); + const igraph_integer_t vcount2 = igraph_vcount(g2); + + if (root < 0 || root >= vcount2) { // root must be in range [0, vcount2-1] + IGRAPH_ERROR("The given root vertex is not present in the second graph.", IGRAPH_EINVVID); + } + + const igraph_integer_t ecount1 = igraph_ecount(g1); + const igraph_integer_t ecount2 = igraph_ecount(g2); + igraph_integer_t vcount; + igraph_integer_t ecount, ecount_double; + igraph_vector_int_t edges; + + // New vertex count = vcount1 * vcount2 + IGRAPH_SAFE_MULT(vcount1, vcount2, &vcount); + + // New edge count = vcount1 * ecount2 + ecount1 + IGRAPH_SAFE_MULT(vcount1, ecount2, &ecount); + IGRAPH_SAFE_ADD(ecount, ecount1, &ecount); + + IGRAPH_SAFE_MULT(ecount, 2, &ecount_double); + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, ecount_double); + + // Vertex ((i, j)) with i from g1, and j from g2 + // will have new vertex id: i * vcount2 + j + + igraph_integer_t edge_index = 0; + + // Edges of form ((u, root)) - ((v, root)) + for (igraph_integer_t i = 0; i < ecount1; ++i) { + igraph_integer_t from = IGRAPH_FROM(g1, i); + igraph_integer_t to = IGRAPH_TO(g1, i); + + VECTOR(edges)[edge_index++] = from * vcount2 + root; // ((from, root)) + VECTOR(edges)[edge_index++] = to * vcount2 + root; // ((to, root)) + } + + // For all edges (from, to) in g2, add edge from ((j, from)) to ((j, to)) + // for all vertex j in g1 + for (igraph_integer_t i = 0; i < ecount2; ++i) { + igraph_integer_t from = IGRAPH_FROM(g2, i); + igraph_integer_t to = IGRAPH_TO(g2, i); + + for (igraph_integer_t j = 0; j < vcount1; ++j) { + VECTOR(edges)[edge_index++] = j * vcount2 + from; // ((j, from)) + VECTOR(edges)[edge_index++] = j * vcount2 + to; // ((j, to)) + } + } + + IGRAPH_CHECK(igraph_create(res, &edges, vcount, directed)); + + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/operators/reverse.c b/src/vendor/cigraph/src/operators/reverse.c index da99dfadeae..943b03619bf 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, true, true, true); /* 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.c b/src/vendor/cigraph/src/operators/rewire.c index 851da5cc7ac..2ce5c874d6a 100644 --- a/src/vendor/cigraph/src/operators/rewire.c +++ b/src/vendor/cigraph/src/operators/rewire.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -32,6 +30,7 @@ #include "igraph_structural.h" #include "core/interruption.h" +#include "misc/graphicality.h" #include "operators/rewire_internal.h" /* Threshold that defines when to switch over to using adjacency lists during @@ -39,14 +38,13 @@ #define REWIRE_ADJLIST_THRESHOLD 10 /* Not declared static so that the testsuite can use it, but not part of the public API. */ -igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewiring_t mode, igraph_bool_t use_adjlist) { +igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_bool_t loops, igraph_bool_t use_adjlist) { const igraph_integer_t no_of_edges = igraph_ecount(graph); char message[256]; igraph_integer_t a, b, c, d, dummy, num_swaps, num_successful_swaps; igraph_vector_int_t eids; igraph_vector_int_t edgevec, alledges; const igraph_bool_t directed = igraph_is_directed(graph); - const igraph_bool_t loops = (mode & IGRAPH_REWIRING_SIMPLE_LOOPS); igraph_bool_t ok; igraph_es_t es; igraph_adjlist_t al; @@ -56,8 +54,6 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewir return IGRAPH_SUCCESS; } - RNG_BEGIN(); - IGRAPH_VECTOR_INT_INIT_FINALLY(&eids, 2); if (use_adjlist) { @@ -80,6 +76,7 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewir while (num_swaps < n) { IGRAPH_ALLOW_INTERRUPTION(); + if (num_swaps % 1000 == 0) { snprintf(message, sizeof(message), "Random rewiring (%.2f%% of the trials were successful)", @@ -87,110 +84,103 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewir IGRAPH_PROGRESS(message, (100.0 * num_swaps) / n, 0); } - switch (mode) { - case IGRAPH_REWIRING_SIMPLE: - case IGRAPH_REWIRING_SIMPLE_LOOPS: - ok = true; + ok = true; - /* Choose two edges randomly */ - VECTOR(eids)[0] = RNG_INTEGER(0, no_of_edges - 1); - do { - VECTOR(eids)[1] = RNG_INTEGER(0, no_of_edges - 1); - } while (VECTOR(eids)[0] == VECTOR(eids)[1]); + /* Choose two edges randomly */ + VECTOR(eids)[0] = RNG_INTEGER(0, no_of_edges - 1); + do { + VECTOR(eids)[1] = RNG_INTEGER(0, no_of_edges - 1); + } while (VECTOR(eids)[0] == VECTOR(eids)[1]); - /* Get the endpoints */ - if (use_adjlist) { - a = VECTOR(alledges)[VECTOR(eids)[0] * 2]; - b = VECTOR(alledges)[VECTOR(eids)[0] * 2 + 1]; - c = VECTOR(alledges)[VECTOR(eids)[1] * 2]; - d = VECTOR(alledges)[VECTOR(eids)[1] * 2 + 1]; - } else { - IGRAPH_CHECK(igraph_edge(graph, VECTOR(eids)[0], &a, &b)); - IGRAPH_CHECK(igraph_edge(graph, VECTOR(eids)[1], &c, &d)); - } + /* Get the endpoints */ + if (use_adjlist) { + a = VECTOR(alledges)[VECTOR(eids)[0] * 2]; + b = VECTOR(alledges)[VECTOR(eids)[0] * 2 + 1]; + c = VECTOR(alledges)[VECTOR(eids)[1] * 2]; + d = VECTOR(alledges)[VECTOR(eids)[1] * 2 + 1]; + } else { + IGRAPH_CHECK(igraph_edge(graph, VECTOR(eids)[0], &a, &b)); + IGRAPH_CHECK(igraph_edge(graph, VECTOR(eids)[1], &c, &d)); + } - /* For an undirected graph, we have two "variants" of each edge, i.e. - * a -- b and b -- a. Since some rewirings can be performed only when we - * "swap" the endpoints, we do it now with probability 0.5 */ - if (!directed && RNG_BOOL()) { - dummy = c; c = d; d = dummy; - if (use_adjlist) { - /* Flip the edge in the unordered edge-list, so the update later on - * hits the correct end. */ - VECTOR(alledges)[VECTOR(eids)[1] * 2] = c; - VECTOR(alledges)[VECTOR(eids)[1] * 2 + 1] = d; - } + /* For an undirected graph, we have two "variants" of each edge, i.e. + * a -- b and b -- a. Since some rewirings can be performed only when we + * "swap" the endpoints, we do it now with probability 0.5 */ + if (!directed && RNG_BOOL()) { + dummy = c; c = d; d = dummy; + if (use_adjlist) { + /* Flip the edge in the unordered edge-list, so the update later on + * hits the correct end. */ + VECTOR(alledges)[VECTOR(eids)[1] * 2] = c; + VECTOR(alledges)[VECTOR(eids)[1] * 2 + 1] = d; } + } - /* If we do not touch loops, check whether a == b or c == d and disallow - * the swap if needed */ - if (!loops && (a == b || c == d)) { + /* If we do not touch loops, check whether a == b or c == d and disallow + * the swap if needed */ + if (!loops && (a == b || c == d)) { + ok = false; + } else { + /* Check whether they are suitable for rewiring */ + if (a == c || b == d) { + /* Swapping would have no effect */ ok = false; } else { - /* Check whether they are suitable for rewiring */ - if (a == c || b == d) { - /* Swapping would have no effect */ - ok = false; - } else { - /* a != c && b != d */ - /* If a == d or b == c, the swap would generate at least one loop, so - * we disallow them unless we want to have loops */ - ok = loops || (a != d && b != c); - /* Also, if a == b and c == d and we allow loops, doing the swap - * would result in a multiple edge if the graph is undirected */ - ok = ok && (directed || a != b || c != d); - } + /* a != c && b != d */ + /* If a == d or b == c, the swap would generate at least one loop, so + * we disallow them unless we want to have loops */ + ok = loops || (a != d && b != c); + /* Also, if a == b and c == d and we allow loops, doing the swap + * would result in a multiple edge if the graph is undirected */ + ok = ok && (directed || a != b || c != d); } + } - /* All good so far. Now check for the existence of a --> d and c --> b to - * disallow the creation of multiple edges */ - if (ok) { - if (use_adjlist) { - if (igraph_adjlist_has_edge(&al, a, d, directed)) { - ok = false; - } - } else { - IGRAPH_CHECK(igraph_are_adjacent(graph, a, d, &ok)); - ok = !ok; + /* All good so far. Now check for the existence of a --> d and c --> b to + * disallow the creation of multiple edges */ + if (ok) { + if (use_adjlist) { + if (igraph_adjlist_has_edge(&al, a, d, directed)) { + ok = false; } + } else { + IGRAPH_CHECK(igraph_are_adjacent(graph, a, d, &ok)); + ok = !ok; } - if (ok) { - if (use_adjlist) { - if (igraph_adjlist_has_edge(&al, c, b, directed)) { - ok = false; - } - } else { - IGRAPH_CHECK(igraph_are_adjacent(graph, c, b, &ok)); - ok = !ok; + } + if (ok) { + if (use_adjlist) { + if (igraph_adjlist_has_edge(&al, c, b, directed)) { + ok = false; } + } else { + IGRAPH_CHECK(igraph_are_adjacent(graph, c, b, &ok)); + ok = !ok; } + } - /* If we are still okay, we can perform the rewiring */ - if (ok) { - /* printf("Deleting: %" IGRAPH_PRId " -> %" IGRAPH_PRId ", %" IGRAPH_PRId " -> %" IGRAPH_PRId "\n", - a, b, c, d); */ - if (use_adjlist) { - /* Replace entry in sorted adjlist: */ - IGRAPH_CHECK(igraph_adjlist_replace_edge(&al, a, b, d, directed)); - IGRAPH_CHECK(igraph_adjlist_replace_edge(&al, c, d, b, directed)); - /* Also replace in unsorted edgelist: */ - VECTOR(alledges)[VECTOR(eids)[0] * 2 + 1] = d; - VECTOR(alledges)[VECTOR(eids)[1] * 2 + 1] = b; - } else { - IGRAPH_CHECK(igraph_delete_edges(graph, es)); - VECTOR(edgevec)[0] = a; VECTOR(edgevec)[1] = d; - VECTOR(edgevec)[2] = c; VECTOR(edgevec)[3] = b; - /* printf("Adding: %" IGRAPH_PRId " -> %" IGRAPH_PRId ", %" IGRAPH_PRId " -> %" IGRAPH_PRId "\n", - a, d, c, b); */ - IGRAPH_CHECK(igraph_add_edges(graph, &edgevec, 0)); - } - num_successful_swaps++; + /* If we are still okay, we can perform the rewiring */ + if (ok) { + /* printf("Deleting: %" IGRAPH_PRId " -> %" IGRAPH_PRId ", %" IGRAPH_PRId " -> %" IGRAPH_PRId "\n", + a, b, c, d); */ + if (use_adjlist) { + /* Replace entry in sorted adjlist: */ + IGRAPH_CHECK(igraph_adjlist_replace_edge(&al, a, b, d, directed)); + IGRAPH_CHECK(igraph_adjlist_replace_edge(&al, c, d, b, directed)); + /* Also replace in unsorted edgelist: */ + VECTOR(alledges)[VECTOR(eids)[0] * 2 + 1] = d; + VECTOR(alledges)[VECTOR(eids)[1] * 2 + 1] = b; + } else { + IGRAPH_CHECK(igraph_delete_edges(graph, es)); + VECTOR(edgevec)[0] = a; VECTOR(edgevec)[1] = d; + VECTOR(edgevec)[2] = c; VECTOR(edgevec)[3] = b; + /* printf("Adding: %" IGRAPH_PRId " -> %" IGRAPH_PRId ", %" IGRAPH_PRId " -> %" IGRAPH_PRId "\n", + a, d, c, b); */ + IGRAPH_CHECK(igraph_add_edges(graph, &edgevec, 0)); } - break; - default: - RNG_END(); - IGRAPH_ERROR("Invalid rewiring mode.", IGRAPH_EINVAL); + num_successful_swaps++; } + num_swaps++; } @@ -212,8 +202,6 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewir igraph_vector_int_destroy(&eids); IGRAPH_FINALLY_CLEAN(use_adjlist ? 3 : 2); - RNG_END(); - return IGRAPH_SUCCESS; } @@ -237,16 +225,15 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewir * * \param graph The graph object to be rewired. * \param n Number of rewiring trials to perform. - * \param mode The rewiring algorithm to be used. It can be one of the following flags: - * \clist - * \cli IGRAPH_REWIRING_SIMPLE - * This method does not create or destroy self-loops, and does - * not create multi-edges. - * \cli IGRAPH_REWIRING_SIMPLE_LOOPS - * This method allows the creation or destruction of self-loops. - * Self-loops are created by switching edges that have a single - * common endpoint. - * \endclist + * \param allowed_edge_types The types of edges that rewiring may create in the graph. + * Currently, the following are implemented: + * \clist + * \cli IGRAPH_SIMPLE_SW + * simple graphs (i.e. no self-loops or multi-edges allowed). + * \cli IGRAPH_LOOPS_SW + * single self-loops are allowed, but not multi-edges. + * \endclist + * Multigraphs are not yet supported. * * \return Error code: * \clist @@ -258,7 +245,13 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewir * * Time complexity: TODO. */ -igraph_error_t igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewiring_t mode) { +igraph_error_t igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_edge_type_sw_t allowed_edge_types) { igraph_bool_t use_adjlist = n >= REWIRE_ADJLIST_THRESHOLD; - return igraph_i_rewire(graph, n, mode, use_adjlist); + + if ((allowed_edge_types & IGRAPH_I_MULTI_EDGES_SW) || + (allowed_edge_types & IGRAPH_I_MULTI_LOOPS_SW)) { + IGRAPH_ERROR("Rewiring multigraphs is not yet implemented.", IGRAPH_UNIMPLEMENTED); + } + + return igraph_i_rewire(graph, n, allowed_edge_types & IGRAPH_LOOPS_SW, use_adjlist); } diff --git a/src/vendor/cigraph/src/operators/rewire_edges.c b/src/vendor/cigraph/src/operators/rewire_edges.c index 6c5b856bfe2..10999288f48 100644 --- a/src/vendor/cigraph/src/operators/rewire_edges.c +++ b/src/vendor/cigraph/src/operators/rewire_edges.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -88,7 +86,7 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ ADD_STUB(from, idx1); ADD_STUB(to, idx2); } - IGRAPH_CHECK(igraph_vector_int_order1(&tmp, &eorder, no_verts)); + IGRAPH_CHECK(igraph_i_vector_int_order(&tmp, &eorder, no_verts)); igraph_vector_int_destroy(&tmp); IGRAPH_FINALLY_CLEAN(1); @@ -135,7 +133,7 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ for (i = 0; i < no_edges; i++) { VECTOR(tmp)[i] = VECTOR(*edges)[2 * i + 1]; } - IGRAPH_CHECK(igraph_vector_int_order1(&tmp, &eorder, no_verts)); + IGRAPH_CHECK(igraph_i_vector_int_order(&tmp, &eorder, no_verts)); igraph_vector_int_destroy(&tmp); IGRAPH_FINALLY_CLEAN(1); @@ -238,8 +236,6 @@ igraph_error_t igraph_rewire_edges(igraph_t *graph, igraph_real_t prob, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, endpoints); - RNG_BEGIN(); - if (prob != 0 && no_of_edges > 0) { if (multiple) { /* If multiple edges are allowed, then there is an easy and fast @@ -266,16 +262,13 @@ igraph_error_t igraph_rewire_edges(igraph_t *graph, igraph_real_t prob, } } - RNG_END(); - IGRAPH_CHECK(igraph_create(&newgraph, &edges, no_of_nodes, igraph_is_directed(graph))); igraph_vector_int_destroy(&edges); 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; @@ -359,8 +352,6 @@ igraph_error_t igraph_rewire_directed_edges(igraph_t *graph, igraph_real_t prob, IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0)); - RNG_BEGIN(); - to_rewire = RNG_GEOM(prob); while (to_rewire < no_of_edges) { if (loops) { @@ -373,16 +364,13 @@ igraph_error_t igraph_rewire_directed_edges(igraph_t *graph, igraph_real_t prob, to_rewire += RNG_GEOM(prob) + 1; } - RNG_END(); - IGRAPH_CHECK(igraph_create(&newgraph, &edges, no_of_nodes, igraph_is_directed(graph))); igraph_vector_int_destroy(&edges); 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/rewire_internal.h b/src/vendor/cigraph/src/operators/rewire_internal.h index b82b10eec95..5308b121daf 100644 --- a/src/vendor/cigraph/src/operators/rewire_internal.h +++ b/src/vendor/cigraph/src/operators/rewire_internal.h @@ -2,14 +2,16 @@ #define IGRAPH_OPERATORS_REWIRE_INTERNAL_H #include "igraph_decls.h" -#include "igraph_interface.h" +#include "igraph_constants.h" +#include "igraph_datatype.h" +#include "igraph_error.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_rewire( - igraph_t *graph, igraph_integer_t n, igraph_rewiring_t mode, + igraph_t *graph, igraph_integer_t n, igraph_bool_t loops, igraph_bool_t use_adjlist); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/operators/simplify.c b/src/vendor/cigraph/src/operators/simplify.c index ba6c98f9859..1851a11b4dd 100644 --- a/src/vendor/cigraph/src/operators/simplify.c +++ b/src/vendor/cigraph/src/operators/simplify.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team @@ -172,8 +171,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 aede768480b..8f6a4450c37 100644 --- a/src/vendor/cigraph/src/operators/subgraph.c +++ b/src/vendor/cigraph/src/operators/subgraph.c @@ -25,7 +25,6 @@ #include "core/interruption.h" #include "core/set.h" #include "graph/attributes.h" -#include "graph/internal.h" #include "operators/subgraph.h" /** @@ -74,7 +73,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); @@ -129,10 +128,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); @@ -158,10 +158,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); @@ -173,7 +173,7 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( igraph_integer_t new_vid = i; igraph_bool_t skip_loop_edge; - IGRAPH_CHECK(igraph_incident(graph, &nei_edges, old_vid, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &nei_edges, old_vid, IGRAPH_OUT, IGRAPH_LOOPS)); n = igraph_vector_int_size(&nei_edges); if (directed) { @@ -182,19 +182,19 @@ 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 { /* undirected graph. We need to be careful with loop edges as each * loop edge will appear twice. We use a boolean flag to skip every * second loop edge */ - skip_loop_edge = 0; + skip_loop_edge = false; for (igraph_integer_t j = 0; j < n; j++) { eid = VECTOR(nei_edges)[j]; @@ -204,10 +204,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 */ @@ -234,7 +233,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); @@ -245,8 +243,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 = */ true, /* va = */ false, /* ea = */ false)); + 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)); @@ -405,12 +402,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 @@ -438,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. @@ -480,7 +477,7 @@ igraph_error_t igraph_induced_subgraph_edges(const igraph_t *graph, igraph_vs_t for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { igraph_integer_t v = IGRAPH_VIT_GET(vit); - IGRAPH_CHECK(igraph_i_incident(graph, &incedges, v, IGRAPH_ALL, IGRAPH_LOOPS_ONCE)); + IGRAPH_CHECK(igraph_incident(graph, &incedges, v, IGRAPH_ALL, IGRAPH_LOOPS_ONCE)); igraph_integer_t d = igraph_vector_int_size(&incedges); for (igraph_integer_t i=0; i < d; i++) { @@ -488,7 +485,7 @@ igraph_error_t igraph_induced_subgraph_edges(const igraph_t *graph, igraph_vs_t igraph_integer_t u = IGRAPH_OTHER(graph, e, v); /* The v <= u check avoids adding non-loop edges twice. * Loop edges only appear once due to the use of - * IGRAPH_LOOPS_ONCE in igraph_i_incident() */ + * IGRAPH_LOOPS_ONCE in igraph_incident() */ if (v <= u && igraph_set_contains(&vids_set, u)) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, e)); } @@ -503,25 +500,12 @@ igraph_error_t igraph_induced_subgraph_edges(const igraph_t *graph, igraph_vs_t return IGRAPH_SUCCESS; } -/** - * \ingroup structural - * \function igraph_subgraph_edges - * \brief Creates a subgraph with the specified edges and their endpoints (deprecated alias). - * - * \deprecated-by igraph_subgraph_from_edges 0.10.3 - */ -igraph_error_t igraph_subgraph_edges( - const igraph_t *graph, igraph_t *res, const igraph_es_t eids, - igraph_bool_t delete_vertices -) { - return igraph_subgraph_from_edges(graph, res, eids, delete_vertices); -} - /** * \ingroup structural * \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 are always contiguous integers starting at * zero, the edge IDs in the extracted subgraph will be different from those diff --git a/src/vendor/cigraph/src/operators/subgraph.h b/src/vendor/cigraph/src/operators/subgraph.h index d293f7b2f9f..ec954d0a671 100644 --- a/src/vendor/cigraph/src/operators/subgraph.h +++ b/src/vendor/cigraph/src/operators/subgraph.h @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2003-2021 The igraph development team @@ -29,7 +27,7 @@ #include "igraph_error.h" #include "igraph_iterators.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_induced_subgraph_map( const igraph_t *graph, igraph_t *res, const igraph_vs_t vids, @@ -37,6 +35,6 @@ IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_induced_subgraph_map( igraph_vector_int_t *invmap, igraph_bool_t map_is_prepared ); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/operators/union.c b/src/vendor/cigraph/src/operators/union.c index 71876bdacc3..d106200f036 100644 --- a/src/vendor/cigraph/src/operators/union.c +++ b/src/vendor/cigraph/src/operators/union.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006-2020 The igraph development team @@ -20,8 +19,6 @@ */ -#include - #include "igraph_operators.h" #include "igraph_constructors.h" diff --git a/src/vendor/cigraph/src/paths/all_shortest_paths.c b/src/vendor/cigraph/src/paths/all_shortest_paths.c index 4cfa2196f10..ee0df71bf7f 100644 --- a/src/vendor/cigraph/src/paths/all_shortest_paths.c +++ b/src/vendor/cigraph/src/paths/all_shortest_paths.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -31,6 +29,12 @@ #include /* memset */ +static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( + const igraph_t *graph, igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, igraph_vector_int_t *nrgeo, + igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode +); + /** * \function igraph_get_all_shortest_paths * \brief All shortest paths (geodesics) from a vertex. @@ -95,13 +99,30 @@ * case. */ -igraph_error_t igraph_get_all_shortest_paths(const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, - igraph_vector_int_t *nrgeo, - igraph_integer_t from, const igraph_vs_t to, - igraph_neimode_t mode) { +igraph_error_t igraph_get_all_shortest_paths( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, + igraph_vector_int_t *nrgeo, + igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode +) { + if (weights == NULL) { + /* Unweighted version */ + return igraph_i_get_all_shortest_paths_unweighted( + graph, vertices, edges, nrgeo, from, to, mode + ); + } else { + /* Weighted version */ + return igraph_get_all_shortest_paths_dijkstra( + graph, vertices, edges, nrgeo, from, to, weights, mode + ); + } +} +static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( + const igraph_t *graph, igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, igraph_vector_int_t *nrgeo, + igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t *geodist; igraph_vector_int_list_t paths; @@ -213,9 +234,9 @@ igraph_error_t igraph_get_all_shortest_paths(const igraph_t *graph, * using igraph_neighbors() due to branch mispredictions in IGRAPH_OTHER(), so we * use igraph_incident() only if the user needs the edge-paths */ if (edges) { - IGRAPH_CHECK(igraph_incident(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_incident(graph, &neis, actnode, mode, IGRAPH_LOOPS)); } else { - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); } n = igraph_vector_int_size(&neis); diff --git a/src/vendor/cigraph/src/paths/astar.c b/src/vendor/cigraph/src/paths/astar.c index c3d5f55c822..4fcdfb0acf6 100644 --- a/src/vendor/cigraph/src/paths/astar.c +++ b/src/vendor/cigraph/src/paths/astar.c @@ -44,8 +44,6 @@ static igraph_error_t null_heuristic( * \function igraph_get_shortest_path_astar * \brief A* gives the shortest path from one vertex to another, with heuristic. * - * \experimental - * * Calculates a shortest path from a single source vertex to a single * target, using the A* algorithm. A* tries to find a shortest path by * starting at \p from and moving to vertices that lie on a path with diff --git a/src/vendor/cigraph/src/paths/bellman_ford.c b/src/vendor/cigraph/src/paths/bellman_ford.c index 692aeb97df4..b0ff4a7d905 100644 --- a/src/vendor/cigraph/src/paths/bellman_ford.c +++ b/src/vendor/cigraph/src/paths/bellman_ford.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -95,7 +93,7 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, n times. */ if (!weights) { - return igraph_distances(graph, res, from, to, mode); + return igraph_distances(graph, NULL, res, from, to, mode); } if (igraph_vector_size(weights) != no_of_edges) { @@ -219,20 +217,6 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, return IGRAPH_SUCCESS; } -/** - * \function igraph_shortest_paths_bellman_ford - * \brief Weighted shortest path lengths between vertices, allowing negative weights (deprecated). - * - * \deprecated-by igraph_distances_bellman_ford 0.10.0 - */ -igraph_error_t igraph_shortest_paths_bellman_ford(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode) { - return igraph_distances_bellman_ford(graph, res, from, to, weights, mode); -} /** * \ingroup structural @@ -329,7 +313,7 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, int counter = 0; if (!weights) { - return igraph_get_shortest_paths(graph, vertices, edges, from, to, mode, + return igraph_get_shortest_paths(graph, NULL, vertices, edges, from, to, mode, parents, inbound_edges); } @@ -586,12 +570,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 784fe33b4ca..c3f56de66f9 100644 --- a/src/vendor/cigraph/src/paths/dijkstra.c +++ b/src/vendor/cigraph/src/paths/dijkstra.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -39,8 +37,6 @@ * \function igraph_distances_dijkstra_cutoff * \brief Weighted shortest path lengths between vertices, with cutoff. * - * \experimental - * * This function is similar to \ref igraph_distances_dijkstra(), but * paths longer than \p cutoff will not be considered. * @@ -111,7 +107,7 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, igraph_vector_int_t indexv; if (!weights) { - return igraph_distances_cutoff(graph, res, from, to, mode, cutoff); + return igraph_distances_cutoff(graph, NULL, res, from, to, mode, cutoff); } if (igraph_vector_size(weights) != no_of_edges) { @@ -300,20 +296,6 @@ igraph_error_t igraph_distances_dijkstra(const igraph_t *graph, return igraph_distances_dijkstra_cutoff(graph, res, from, to, weights, mode, -1); } -/** - * \function igraph_shortest_paths_dijkstra - * \brief Weighted shortest path lengths between vertices (deprecated). - * - * \deprecated-by igraph_distances_dijkstra 0.10.0 - */ -igraph_error_t igraph_shortest_paths_dijkstra(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode) { - return igraph_distances_dijkstra(graph, res, from, to, weights, mode); -} /** * \ingroup structural @@ -434,7 +416,7 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, igraph_integer_t i, to_reach; if (!weights) { - return igraph_get_shortest_paths(graph, vertices, edges, from, to, mode, + return igraph_get_shortest_paths(graph, NULL, vertices, edges, from, to, mode, parents, inbound_edges); } @@ -696,12 +678,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); } @@ -801,7 +783,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, const double eps = IGRAPH_SHORTEST_PATH_EPSILON; if (!weights) { - return igraph_get_all_shortest_paths(graph, vertices, edges, nrgeo, from, to, mode); + return igraph_get_all_shortest_paths(graph, NULL, vertices, edges, nrgeo, from, to, mode); } if (from < 0 || from >= no_of_nodes) { diff --git a/src/vendor/cigraph/src/paths/distances.c b/src/vendor/cigraph/src/paths/distances.c index 3b86fe87eac..b6fd98b7f5a 100644 --- a/src/vendor/cigraph/src/paths/distances.c +++ b/src/vendor/cigraph/src/paths/distances.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2021 The igraph development team @@ -36,12 +34,11 @@ * vid_ecc will then return the id of the vertex farthest from the one in * vids. If unconn == false and not all other vertices were reachable from * the single given vertex, -1 is returned in vid_ecc. */ -static igraph_error_t igraph_i_eccentricity(const igraph_t *graph, - igraph_vector_t *res, - igraph_vs_t vids, - igraph_lazy_adjlist_t *adjlist, - igraph_integer_t *vid_ecc, - igraph_bool_t unconn) { +static igraph_error_t igraph_i_eccentricity_unweighted( + const igraph_t *graph, igraph_vector_t *res, igraph_vs_t vids, + igraph_lazy_adjlist_t *adjlist, igraph_integer_t *vid_ecc, + igraph_bool_t unconn +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; @@ -122,7 +119,7 @@ static igraph_error_t igraph_i_eccentricity(const igraph_t *graph, /** * This function finds the weighted eccentricity and returns it via \p ecc. - * It's used for igraph_pseudo_diameter_dijkstra() and igraph_eccentricity_dijkstra(). + * It's used for igraph_pseudo_diameter() and igraph_eccentricity(). * \p vid_ecc returns the vertex id of the ecc with the greatest * distance from \p vid_start. If two vertices have the same greatest distance, * the one with the lowest degree is chosen. @@ -130,13 +127,10 @@ static igraph_error_t igraph_i_eccentricity(const igraph_t *graph, * wil be set to infinity, and \p vid_ecc to -1; */ static igraph_error_t igraph_i_eccentricity_dijkstra( - const igraph_t *graph, - const igraph_vector_t *weights, - igraph_real_t *ecc, - igraph_integer_t vid_start, - igraph_integer_t *vid_ecc, - igraph_bool_t unconn, - igraph_lazy_inclist_t *inclist) { + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *ecc, + igraph_integer_t vid_start, igraph_integer_t *vid_ecc, igraph_bool_t unconn, + igraph_lazy_inclist_t *inclist +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_2wheap_t Q; @@ -239,61 +233,11 @@ static igraph_error_t igraph_i_eccentricity_dijkstra( * components. Isolated vertices have eccentricity zero. * * \param graph The input graph, it can be directed or undirected. - * \param res Pointer to an initialized vector, the result is stored - * here. - * \param vids The vertices for which the eccentricity is calculated. - * \param mode What kind of paths to consider for the calculation: - * \c IGRAPH_OUT, paths that follow edge directions; - * \c IGRAPH_IN, paths that follow the opposite directions; and - * \c IGRAPH_ALL, paths that ignore edge directions. This argument - * is ignored for undirected graphs. - * \return Error code. - * - * Time complexity: O(|S| (|V|+|E|)), where |V| is the number of - * vertices, |E| is the number of edges and |S| is the number of - * vertices for which eccentricity is calculated. - * - * \sa \ref igraph_radius(). - * - * \example examples/simple/igraph_eccentricity.c - */ - -igraph_error_t igraph_eccentricity(const igraph_t *graph, - igraph_vector_t *res, - igraph_vs_t vids, - igraph_neimode_t mode) { - igraph_lazy_adjlist_t adjlist; - - IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, mode, - IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); - IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); - - IGRAPH_CHECK(igraph_i_eccentricity(graph, res, vids, &adjlist, - /*vid_ecc*/ NULL, /*unconn*/ true)); - igraph_lazy_adjlist_destroy(&adjlist); - IGRAPH_FINALLY_CLEAN(1); - return IGRAPH_SUCCESS; -} - -/** - * \function igraph_eccentricity_dijkstra - * \brief Eccentricity of some vertices, using weighted edges. - * - * The eccentricity of a vertex is calculated by measuring the shortest - * distance from (or to) the vertex, to (or from) all vertices in the - * graph, and taking the maximum. - * - * - * This implementation ignores vertex pairs that are in different - * components. Isolated vertices have eccentricity zero. - * - * \param graph The input graph, it can be directed or undirected. * \param weights The edge weights. All edge weights must be * non-negative for Dijkstra's algorithm to work. Additionally, no * edge weight may be NaN. If either case does not hold, an error - * is returned. If this is a null pointer, then the unweighted - * version, \ref igraph_eccentricity() is called. Edges with positive - * infinite weights are ignored. + * is returned. Use a null pointer to calculate the unweighted + * eccentricities. Edges with positive infinite weights are ignored. * \param res Pointer to an initialized vector, the result is stored * here. * \param vids The vertices for which the eccentricity is calculated. @@ -307,13 +251,13 @@ igraph_error_t igraph_eccentricity(const igraph_t *graph, * Time complexity: O(|V| |E| log|V| + |V|), where |V| is the number of * vertices, |E| the number of edges. * + * \example examples/simple/igraph_eccentricity.c */ -igraph_error_t igraph_eccentricity_dijkstra(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_vector_t *res, - igraph_vs_t vids, - igraph_neimode_t mode) { +igraph_error_t igraph_eccentricity( + const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, + igraph_vs_t vids, igraph_neimode_t mode +) { igraph_lazy_inclist_t inclist; igraph_vit_t vit; igraph_integer_t dump; @@ -321,7 +265,17 @@ igraph_error_t igraph_eccentricity_dijkstra(const igraph_t *graph, igraph_integer_t no_of_edges = igraph_ecount(graph); if (weights == NULL) { - return igraph_eccentricity(graph, res, vids, mode); + igraph_lazy_adjlist_t adjlist; + + IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, mode, + IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); + IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); + + IGRAPH_CHECK(igraph_i_eccentricity_unweighted(graph, res, vids, &adjlist, + /*vid_ecc*/ NULL, /*unconn*/ true)); + igraph_lazy_adjlist_destroy(&adjlist); + IGRAPH_FINALLY_CLEAN(1); + return IGRAPH_SUCCESS; } if (igraph_vector_size(weights) != no_of_edges) { @@ -346,10 +300,11 @@ igraph_error_t igraph_eccentricity_dijkstra(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_resize(res, 0)); IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); - for (IGRAPH_VIT_RESET(vit); - !IGRAPH_VIT_END(vit); - IGRAPH_VIT_NEXT(vit)) { - IGRAPH_CHECK(igraph_i_eccentricity_dijkstra(graph, weights, &ecc, IGRAPH_VIT_GET(vit), /*vid_ecc*/ &dump, /*unconn*/ true, &inclist)); + for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { + IGRAPH_CHECK(igraph_i_eccentricity_dijkstra( + graph, weights, &ecc, IGRAPH_VIT_GET(vit), + /*vid_ecc*/ &dump, /*unconn*/ true, &inclist + )); IGRAPH_CHECK(igraph_vector_push_back(res, ecc)); } igraph_lazy_inclist_destroy(&inclist); @@ -359,53 +314,6 @@ igraph_error_t igraph_eccentricity_dijkstra(const igraph_t *graph, /** * \function igraph_radius - * \brief Radius of a graph. - * - * The radius of a graph is the defined as the minimum eccentricity of - * its vertices, see \ref igraph_eccentricity(). - * - * \param graph The input graph, it can be directed or undirected. - * \param radius Pointer to a real variable, the result is stored - * here. - * \param mode What kind of paths to consider for the calculation: - * \c IGRAPH_OUT, paths that follow edge directions; - * \c IGRAPH_IN, paths that follow the opposite directions; and - * \c IGRAPH_ALL, paths that ignore edge directions. This argument - * is ignored for undirected graphs. - * \return Error code. - * - * Time complexity: O(|V|(|V|+|E|)), where |V| is the number of - * vertices and |E| is the number of edges. - * - * \sa \ref igraph_radius_dijkstra() for the weighted version, - * \ref igraph_diameter() for the maximum eccentricity, - * \ref igraph_eccentricity() for the eccentricities of all vertices. - * - * \example examples/simple/igraph_radius.c - */ - -igraph_error_t igraph_radius(const igraph_t *graph, igraph_real_t *radius, - igraph_neimode_t mode) { - - igraph_integer_t no_of_nodes = igraph_vcount(graph); - - if (no_of_nodes == 0) { - *radius = IGRAPH_NAN; - } else { - igraph_vector_t ecc; - IGRAPH_VECTOR_INIT_FINALLY(&ecc, igraph_vcount(graph)); - IGRAPH_CHECK(igraph_eccentricity(graph, &ecc, igraph_vss_all(), - mode)); - *radius = igraph_vector_min(&ecc); - igraph_vector_destroy(&ecc); - IGRAPH_FINALLY_CLEAN(1); - } - - return IGRAPH_SUCCESS; -} - -/** - * \function igraph_radius_dijkstra * \brief Radius of a graph, using weighted edges. * * \experimental @@ -432,27 +340,22 @@ igraph_error_t igraph_radius(const igraph_t *graph, igraph_real_t *radius, * Time complexity: O(|V| |E| log|V| + |V|), where |V| is the number of * vertices, |E| the number of edges. * - * \sa \ref igraph_radius() for the unweighted version, - * \ref igraph_diameter_dijkstra() for the maximum weighted eccentricity, - * \ref igraph_eccentricity_dijkstra() for weighted eccentricities of - * all vertices. + * \sa \ref igraph_diameter() for the maximum eccentricity, + * \ref igraph_eccentricity() for eccentricities of all vertices. */ -igraph_error_t igraph_radius_dijkstra(const igraph_t *graph, const igraph_vector_t *weights, - igraph_real_t *radius, igraph_neimode_t mode) { - +igraph_error_t igraph_radius( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_real_t *radius, igraph_neimode_t mode +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); - if (weights == NULL) { - return igraph_radius(graph, radius, mode); - } - if (no_of_nodes == 0) { *radius = IGRAPH_NAN; } else { igraph_vector_t ecc; IGRAPH_VECTOR_INIT_FINALLY(&ecc, igraph_vcount(graph)); - IGRAPH_CHECK(igraph_eccentricity_dijkstra(graph, weights, &ecc, igraph_vss_all(), mode)); + IGRAPH_CHECK(igraph_eccentricity(graph, weights, &ecc, igraph_vss_all(), mode)); *radius = igraph_vector_min(&ecc); igraph_vector_destroy(&ecc); IGRAPH_FINALLY_CLEAN(1); @@ -461,54 +364,11 @@ igraph_error_t igraph_radius_dijkstra(const igraph_t *graph, const igraph_vector return IGRAPH_SUCCESS; } -/** - * \function igraph_pseudo_diameter - * \brief Approximation and lower bound of diameter. - * - * This algorithm finds a pseudo-peripheral vertex and returns its - * eccentricity. This value can be used as an approximation - * and lower bound of the diameter of a graph. - * - * - * A pseudo-peripheral vertex is a vertex v, such that for every - * vertex u which is as far away from v as possible, v is also as - * far away from u as possible. The process of finding one depends - * on where the search starts, and for a disconnected graph the - * maximum diameter found will be that of the component \p vid_start - * is in. - * - * \param graph The input graph, if it is directed, its edge directions - * are ignored. - * \param diameter Pointer to a real variable, the result is stored - * here. - * \param vid_start Id of the starting vertex. If this is negative, a - * random starting vertex is chosen. - * \param from Pointer to an integer, if not \c NULL it will be set to the - * source vertex of the diameter path. If \p unconn is \c false, and - * a disconnected graph is detected, this is set to -1. - * \param to Pointer to an integer, if not \c NULL it will be set to the - * target vertex of the diameter path. If \p unconn is \c false, and - * a disconnected graph is detected, this is set to -1. - * \param directed Boolean, whether to consider directed - * paths. Ignored for undirected graphs. - * \param unconn What to do if the graph is not connected. If - * \c true the longest geodesic within a component - * will be returned, otherwise \c IGRAPH_INFINITY is returned. - * \return Error code. - * - * Time complexity: O(|V| |E|)), where |V| is the number of - * vertices and |E| is the number of edges. - * - * \sa \ref igraph_eccentricity(), \ref igraph_diameter(). - * - */ -igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, - igraph_real_t *diameter, - igraph_integer_t vid_start, - igraph_integer_t *from, - igraph_integer_t *to, - igraph_bool_t directed, - igraph_bool_t unconn) { +static igraph_error_t igraph_i_pseudo_diameter_unweighted( + const igraph_t *graph, igraph_real_t *diameter, igraph_integer_t vid_start, + igraph_integer_t *from, igraph_integer_t *to, + igraph_bool_t directed, igraph_bool_t unconn +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_real_t ecc_v; @@ -536,9 +396,7 @@ igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, } if (vid_start < 0) { - RNG_BEGIN(); vid_start = RNG_INTEGER(0, no_of_nodes - 1); - RNG_END(); } if (!igraph_is_directed(graph) || !directed) { @@ -551,8 +409,9 @@ igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, ifrom = vid_start; IGRAPH_VECTOR_INIT_FINALLY(&ecc_vec, no_of_nodes); - IGRAPH_CHECK(igraph_i_eccentricity(graph, &ecc_vec, igraph_vss_1(vid_start), - &adjlist, &vid_ecc, unconn)); + IGRAPH_CHECK(igraph_i_eccentricity_unweighted( + graph, &ecc_vec, igraph_vss_1(vid_start), &adjlist, &vid_ecc, unconn + )); ecc_u = VECTOR(ecc_vec)[0]; if (!unconn && vid_ecc == -1) { @@ -563,8 +422,9 @@ igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, ito = vid_ecc; - IGRAPH_CHECK(igraph_i_eccentricity(graph, &ecc_vec, igraph_vss_1(vid_ecc), - &adjlist, &vid_ecc, true)); + IGRAPH_CHECK(igraph_i_eccentricity_unweighted( + graph, &ecc_vec, igraph_vss_1(vid_ecc), &adjlist, &vid_ecc, true + )); ecc_v = VECTOR(ecc_vec)[0]; @@ -599,10 +459,14 @@ igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&ecc_in, igraph_vcount(graph)); IGRAPH_VECTOR_INIT_FINALLY(&ecc_out, igraph_vcount(graph)); - IGRAPH_CHECK(igraph_i_eccentricity(graph, &ecc_out, igraph_vss_1(vid_start), - &adjlist_out, &vid_ecc_out, unconn)); - IGRAPH_CHECK(igraph_i_eccentricity(graph, &ecc_in, igraph_vss_1(vid_start), - &adjlist_in, &vid_ecc_in, unconn)); + IGRAPH_CHECK(igraph_i_eccentricity_unweighted( + graph, &ecc_out, igraph_vss_1(vid_start), &adjlist_out, + &vid_ecc_out, unconn + )); + IGRAPH_CHECK(igraph_i_eccentricity_unweighted( + graph, &ecc_in, igraph_vss_1(vid_start), &adjlist_in, + &vid_ecc_in, unconn + )); /* A directed graph is strongly connected iff all vertices are reachable * from vid_start both when moving along or moving opposite the edge directions. */ @@ -625,10 +489,14 @@ igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, /* TODO: In the undirected case, we break ties between vertices at the * same distance based on their degree. In te directed case, should we * use in-, out- or total degree? */ - IGRAPH_CHECK(igraph_i_eccentricity(graph, &ecc_out, igraph_vss_1(vid_ecc), - &adjlist_out, &vid_ecc_out, true)); - IGRAPH_CHECK(igraph_i_eccentricity(graph, &ecc_in, igraph_vss_1(vid_ecc), - &adjlist_in, &vid_ecc_in, true)); + IGRAPH_CHECK(igraph_i_eccentricity_unweighted( + graph, &ecc_out, igraph_vss_1(vid_ecc), &adjlist_out, + &vid_ecc_out, true + )); + IGRAPH_CHECK(igraph_i_eccentricity_unweighted( + graph, &ecc_in, igraph_vss_1(vid_ecc), &adjlist_in, + &vid_ecc_in, true + )); if (VECTOR(ecc_out)[0] > VECTOR(ecc_in)[0]) { vid_ecc = vid_ecc_out; @@ -690,60 +558,12 @@ igraph_error_t igraph_pseudo_diameter(const igraph_t *graph, } -/** - * \function igraph_pseudo_diameter_dijkstra - * \brief Approximation and lower bound of the diameter of a weighted graph. - * - * This algorithm finds a pseudo-peripheral vertex and returns its - * weighted eccentricity. This value can be used as an approximation - * and lower bound of the diameter of a graph. - * - * - * A pseudo-peripheral vertex is a vertex v, such that for every - * vertex u which is as far away from v as possible, v is also as - * far away from u as possible. The process of finding one depends - * on where the search starts, and for a disconnected graph the - * maximum diameter found will be that of the component \p vid_start - * is in. - * - * - * If the graph has no vertices, \c IGRAPH_NAN is returned. - * - * \param graph The input graph, can be directed or undirected. - * \param weights The edge weights of the graph. Can be \c NULL for an - * unweighted graph. All weights should be non-negative. Edges with - * positive infinite weights are ignored. - * \param diameter This will contain the weighted pseudo-diameter. - * \param vid_start Id of the starting vertex. If this is negative, a - * random starting vertex is chosen. - * \param from If not \c NULL this will be set to the - * source vertex of the diameter path. If the graph has no diameter path, - * it will be set to -1. - * \param to If not \c NULL this will be set to the - * target vertex of the diameter path. If the graph has no diameter path, - * it will be set to -1. - * \param directed Boolean, whether to consider directed - * paths. Ignored for undirected graphs. - * \param unconn What to do if the graph is not connected. If - * \c true the longest geodesic within a component - * will be returned, otherwise \c IGRAPH_INFINITY is - * returned. - * \return Error code. - * - * Time complexity: O(|V| |E| log|E|), |V| is the number of vertices, - * |E| is the number of edges. - * - * \sa \ref igraph_diameter_dijkstra() - */ -igraph_error_t igraph_pseudo_diameter_dijkstra(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_real_t *diameter, - igraph_integer_t vid_start, - igraph_integer_t *from, - igraph_integer_t *to, - igraph_bool_t directed, - igraph_bool_t unconn) { - +static igraph_error_t igraph_i_pseudo_diameter_dijkstra( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_real_t *diameter, igraph_integer_t vid_start, + igraph_integer_t *from, igraph_integer_t *to, + igraph_bool_t directed, igraph_bool_t unconn +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t no_of_edges = igraph_ecount(graph); @@ -757,9 +577,7 @@ igraph_error_t igraph_pseudo_diameter_dijkstra(const igraph_t *graph, IGRAPH_ERROR("Starting vertex ID for pseudo-diameter out of range.", IGRAPH_EINVAL); } - if (!weights) { - return igraph_pseudo_diameter(graph, diameter, vid_start, from, to, directed, unconn); - } + IGRAPH_ASSERT(weights != 0); if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", @@ -791,9 +609,7 @@ igraph_error_t igraph_pseudo_diameter_dijkstra(const igraph_t *graph, } if (vid_start < 0) { - RNG_BEGIN(); vid_start = RNG_INTEGER(0, no_of_nodes - 1); - RNG_END(); } if (!igraph_is_directed(graph) || !directed) { @@ -924,81 +740,84 @@ igraph_error_t igraph_pseudo_diameter_dijkstra(const igraph_t *graph, } /** - * \function igraph_graph_center - * \brief Central vertices of a graph. + * \function igraph_pseudo_diameter + * \brief Approximation and lower bound of the diameter of a graph. * - * The central vertices of a graph are calculated by finding the vertices - * with the minimum eccentricity. This concept is typically applied to - * (strongly) connected graphs. In disconnected graphs, the smallest - * eccentricity is taken across all components. + * This algorithm finds a pseudo-peripheral vertex and returns its + * eccentricity. This value can be used as an approximation + * and lower bound of the diameter of a graph. * - * \param graph The input graph, it can be directed or undirected. - * \param res Pointer to an initialized vector, the result is stored - * here. - * \param mode What kind of paths to consider for the calculation: - * \c IGRAPH_OUT, paths that follow edge directions; - * \c IGRAPH_IN, paths that follow the opposite directions; and - * \c IGRAPH_ALL, paths that ignore edge directions. This argument - * is ignored for undirected graphs. - * \return Error code. + * + * A pseudo-peripheral vertex is a vertex v, such that for every + * vertex u which is as far away from v as possible, v is also as + * far away from u as possible. The process of finding one depends + * on where the search starts, and for a disconnected graph the + * maximum diameter found will be that of the component \p vid_start + * is in. + * + * + * If the graph has no vertices, \c IGRAPH_NAN is returned. * - * Time complexity: O(|V| (|V|+|E|)), where |V| is the number of - * vertices and |E| is the number of edges. + * \param graph The input graph, can be directed or undirected. + * \param weights The edge weights of the graph. Can be \c NULL for an + * unweighted graph. All weights should be non-negative. Edges with + * positive infinite weights are ignored. + * \param diameter This will contain the pseudo-diameter. + * \param vid_start Id of the starting vertex. If this is negative, a + * random starting vertex is chosen. + * \param from If not \c NULL this will be set to the + * source vertex of the diameter path. If the graph has no diameter path, + * it will be set to -1. + * \param to If not \c NULL this will be set to the + * target vertex of the diameter path. If the graph has no diameter path, + * it will be set to -1. + * \param directed Boolean, whether to consider directed + * paths. Ignored for undirected graphs. + * \param unconn What to do if the graph is not connected. If + * \c true the longest geodesic within a component + * will be returned, otherwise \c IGRAPH_INFINITY is + * returned. + * \return Error code. * - * \sa \ref igraph_graph_center_dijkstra(), - * \ref igraph_eccentricity(), \ref igraph_radius() + * Time complexity: O(|V| |E| log|E|), |V| is the number of vertices, + * |E| is the number of edges. * + * \sa \ref igraph_diameter() */ -igraph_error_t igraph_graph_center( - const igraph_t *graph, igraph_vector_int_t *res, igraph_neimode_t mode +igraph_error_t igraph_pseudo_diameter( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_real_t *diameter, igraph_integer_t vid_start, + igraph_integer_t *from, igraph_integer_t *to, + igraph_bool_t directed, igraph_bool_t unconn ) { - - igraph_vector_t ecc; - - igraph_vector_int_clear(res); - if (igraph_vcount(graph) == 0) { - return IGRAPH_SUCCESS; - } - - IGRAPH_VECTOR_INIT_FINALLY(&ecc, 0); - IGRAPH_CHECK(igraph_eccentricity(graph, &ecc, igraph_vss_all(), mode)); - - /* igraph_eccentricity() does not return infinity or NaN, and the null graph - * case was handled above, therefore calling vector_min() is safe. */ - igraph_real_t min_eccentricity = igraph_vector_min(&ecc); - igraph_integer_t n = igraph_vector_size(&ecc); - for (igraph_integer_t i = 0; i < n; i++) { - if (VECTOR(ecc)[i] == min_eccentricity) { - IGRAPH_CHECK(igraph_vector_int_push_back(res, i)); - } + if (weights) { + return igraph_i_pseudo_diameter_dijkstra( + graph, weights, diameter, vid_start, from, to, directed, unconn + ); + } else { + return igraph_i_pseudo_diameter_unweighted( + graph, diameter, vid_start, from, to, directed, unconn + ); } - - igraph_vector_destroy(&ecc); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; } /** - * \function igraph_graph_center_dijkstra - * \brief Central vertices of a graph, using weighted edges. + * \function igraph_graph_center + * \brief Central vertices of a graph. * * \experimental * * The central vertices of a graph are calculated by finding the vertices - * with the minimum eccentricity. This function takes edge weights into - * account and uses Dijkstra's algorithm for the shortest path calculation. - * The concept of the graph center is typically applied to - * (strongly) connected graphs. In disconnected graphs, the smallest + * with the minimum eccentricity. The concept of the graph center is typically + * applied to (strongly) connected graphs. In disconnected graphs, the smallest * eccentricity is taken across all components. * * \param graph The input graph, it can be directed or undirected. * \param weights The edge weights. All edge weights must be * non-negative for Dijkstra's algorithm to work. Additionally, no * edge weight may be NaN. If either case does not hold, an error - * is returned. If this is a null pointer, then the unweighted - * version, \ref igraph_graph_center() is called. Edges with positive - * infinite weights are ignored. + * is returned. Pass a null pointer here if all edges have equal weight. + * Edges with positive infinite weights are ignored. * \param res Pointer to an initialized vector, the result is stored * here. * \param mode What kind of paths to consider for the calculation: @@ -1011,30 +830,26 @@ igraph_error_t igraph_graph_center( * Time complexity: O(|V| |E| log|V| + |V|), where |V| is the number of * vertices, |E| the number of edges. * - * \sa \ref igraph_graph_center(), - * \ref igraph_eccentricity_dijkstra(), \ref igraph_radius_dijkstra() + * \sa \ref igraph_graph_center(), \ref igraph_eccentricity(), \ref igraph_radius() * */ -igraph_error_t igraph_graph_center_dijkstra( - const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_t *res, igraph_neimode_t mode +igraph_error_t igraph_graph_center( + const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_t *res, + igraph_neimode_t mode ) { igraph_vector_t ecc; const igraph_real_t eps = IGRAPH_SHORTEST_PATH_EPSILON; - if (weights == NULL) { - return igraph_graph_center(graph, res, mode); - } - igraph_vector_int_clear(res); if (igraph_vcount(graph) == 0) { return IGRAPH_SUCCESS; } IGRAPH_VECTOR_INIT_FINALLY(&ecc, 0); - IGRAPH_CHECK(igraph_eccentricity_dijkstra(graph, weights, &ecc, igraph_vss_all(), mode)); + IGRAPH_CHECK(igraph_eccentricity(graph, weights, &ecc, igraph_vss_all(), mode)); - /* igraph_eccentricity_dijkstra() does not return infinity or NaN, and the null graph + /* igraph_eccentricity() does not return infinity or NaN, and the null graph * case was handled above, therefore calling vector_min() is safe. */ igraph_real_t min_eccentricity = igraph_vector_min(&ecc); igraph_integer_t n = igraph_vector_size(&ecc); diff --git a/src/vendor/cigraph/src/paths/eulerian.c b/src/vendor/cigraph/src/paths/eulerian.c index 11cf63fd762..982c839a57f 100644 --- a/src/vendor/cigraph/src/paths/eulerian.c +++ b/src/vendor/cigraph/src/paths/eulerian.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team diff --git a/src/vendor/cigraph/src/paths/floyd_warshall.c b/src/vendor/cigraph/src/paths/floyd_warshall.c index 18502e43080..0ab833869c8 100644 --- a/src/vendor/cigraph/src/paths/floyd_warshall.c +++ b/src/vendor/cigraph/src/paths/floyd_warshall.c @@ -199,8 +199,6 @@ static igraph_error_t distances_floyd_warshall_tree(igraph_matrix_t *res) { * \function igraph_distances_floyd_warshall * \brief Weighted all-pairs shortest path lengths with the Floyd-Warshall algorithm. * - * \experimental - * * The Floyd-Warshall algorithm computes weighted shortest path lengths between * all pairs of vertices at the same time. It is useful with very dense weighted graphs, * as its running time is primarily determined by the vertex count, and is not sensitive diff --git a/src/vendor/cigraph/src/paths/johnson.c b/src/vendor/cigraph/src/paths/johnson.c index fdd09ffc8a0..5d8a92cfab9 100644 --- a/src/vendor/cigraph/src/paths/johnson.c +++ b/src/vendor/cigraph/src/paths/johnson.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -66,7 +64,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 +84,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 +100,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, NULL, res, from, to, mode); } if (igraph_vector_size(weights) != no_of_edges) { @@ -107,7 +111,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, NULL, res, from, to, mode); } /* If no negative weights, then we can run Dijkstra's algorithm */ @@ -117,13 +121,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 +146,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 +173,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 +186,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 +200,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 +217,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 +232,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); @@ -226,17 +253,3 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, return IGRAPH_SUCCESS; } - -/** - * \function igraph_shortest_paths_johnson - * \brief Weighted shortest path lengths between vertices, using Johnson's algorithm (deprecated). - * - * \deprecated-by igraph_distances_johnson 0.10.0 - */ -igraph_error_t igraph_shortest_paths_johnson(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights) { - return igraph_distances_johnson(graph, res, from, to, weights); -} diff --git a/src/vendor/cigraph/src/paths/random_walk.c b/src/vendor/cigraph/src/paths/random_walk.c index 40d9938a1f8..ebdd615ca00 100644 --- a/src/vendor/cigraph/src/paths/random_walk.c +++ b/src/vendor/cigraph/src/paths/random_walk.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2014 Gabor Csardi @@ -59,8 +58,6 @@ static igraph_error_t igraph_i_random_walk_adjlist(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(vertices, steps + 1)); - RNG_BEGIN(); - VECTOR(*vertices)[0] = start; for (i = 1; i <= steps; i++) { igraph_vector_int_t *neis; @@ -83,8 +80,6 @@ static igraph_error_t igraph_i_random_walk_adjlist(const igraph_t *graph, IGRAPH_ALLOW_INTERRUPTION(); } - RNG_END(); - igraph_lazy_adjlist_destroy(&adj); IGRAPH_FINALLY_CLEAN(1); @@ -155,8 +150,6 @@ static igraph_error_t igraph_i_random_walk_inclist( VECTOR(cdfs)[i] = NULL; } - RNG_BEGIN(); - if (vertices) { VECTOR(*vertices)[0] = start; } @@ -237,8 +230,6 @@ static igraph_error_t igraph_i_random_walk_inclist( IGRAPH_ALLOW_INTERRUPTION(); } - RNG_END(); - igraph_vector_ptr_destroy_all(&cdfs); igraph_vector_destroy(&weight_temp); igraph_lazy_inclist_destroy(&il); @@ -347,50 +338,3 @@ igraph_error_t igraph_random_walk(const igraph_t *graph, start, mode, steps, stuck); } } - - -/** - * \function igraph_random_edge_walk - * \brief Performs a random walk on a graph and returns the traversed edges. - * - * Performs a random walk with a given length on a graph, from the given - * start vertex. Edge directions are (potentially) considered, depending on - * the \p mode argument. - * - * \param graph The input graph, it can be directed or undirected. - * Multiple edges are respected, so are loop edges. - * \param weights A vector of non-negative edge weights. It is assumed - * that at least one strictly positive weight is found among the - * outgoing edges of each vertex. Additionally, no edge weight may - * be NaN. If either case does not hold, an error is returned. If it - * is a NULL pointer, all edges are considered to have equal weight. - * \param edgewalk An initialized vector; the indices of traversed - * edges are stored here. It will be resized as needed. - * \param start The start vertex for the walk. - * \param steps The number of steps to take. If the random walk gets - * stuck, then the \p stuck argument specifies what happens. - * \param mode How to walk along the edges in directed graphs. - * \c IGRAPH_OUT means following edge directions, \c IGRAPH_IN means - * going opposite the edge directions, \c IGRAPH_ALL means ignoring - * edge directions. This argument is ignored for undirected graphs. - * \param stuck What to do if the random walk gets stuck. - * \c IGRAPH_RANDOM_WALK_STUCK_RETURN means that the function returns - * with a shorter walk; \c IGRAPH_RANDOM_WALK_STUCK_ERROR means - * that an \c IGRAPH_ERWSTUCK error is reported. In both cases, - * \p edgewalk is truncated to contain the actual interrupted walk. - * - * \return Error code. - * - * \deprecated-by igraph_random_walk 0.10.0 - */ -igraph_error_t igraph_random_edge_walk( - const igraph_t *graph, - const igraph_vector_t *weights, - igraph_vector_int_t *edgewalk, - igraph_integer_t start, igraph_neimode_t mode, - igraph_integer_t steps, - igraph_random_walk_stuck_t stuck) { - - return igraph_random_walk(graph, weights, NULL, edgewalk, - start, mode, steps, stuck); -} diff --git a/src/vendor/cigraph/src/paths/shortest_paths.c b/src/vendor/cigraph/src/paths/shortest_paths.c index 315236d8dd9..64dea6c8d82 100644 --- a/src/vendor/cigraph/src/paths/shortest_paths.c +++ b/src/vendor/cigraph/src/paths/shortest_paths.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2020 The igraph development team @@ -142,15 +140,15 @@ static igraph_error_t igraph_i_average_path_length_unweighted( } -/* Computes the average of pairwise distances (used for igraph_average_path_length_dijkstra), - * or of inverse pairwise distances (used for igraph_global_efficiency), in an unweighted graph. +/* Computes the average of pairwise distances (used for igraph_average_path_length), + * or of inverse pairwise distances (used for igraph_global_efficiency), in a weighted graph. * Uses Dijkstra's algorithm, therefore all weights must be non-negative. */ static igraph_error_t igraph_i_average_path_length_dijkstra( const igraph_t *graph, + const igraph_vector_t *weights, igraph_real_t *res, igraph_real_t *unconnected_pairs, - const igraph_vector_t *weights, const igraph_bool_t directed, const igraph_bool_t invert, /* average inverse distances instead of distances */ const igraph_bool_t unconn /* average over connected pairs instead of all pairs */) @@ -178,9 +176,7 @@ static igraph_error_t igraph_i_average_path_length_dijkstra( igraph_real_t no_of_pairs; igraph_real_t no_of_conn_pairs = 0.0; /* no. of ordered pairs between which there is a path */ - if (!weights) { - return igraph_i_average_path_length_unweighted(graph, res, unconnected_pairs, directed, invert, unconn); - } + IGRAPH_ASSERT(weights != 0); if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match the number of edges (%" IGRAPH_PRId ").", @@ -292,45 +288,7 @@ static igraph_error_t igraph_i_average_path_length_dijkstra( /** * \ingroup structural * \function igraph_average_path_length - * \brief The average unweighted shortest path length between all vertex pairs. - * - * If no vertex pairs can be included in the calculation, for example because - * the graph has fewer than two vertices, or if the graph has no edges and - * \p unconn is set to \c true, NaN is returned. - * - * \param graph The graph object. - * \param res Pointer to a real number, this will contain the result. - * \param unconn_pairs Pointer to a real number. If not a null pointer, the - * number of ordered vertex pairs where the second vertex is unreachable - * from the first one will be stored here. - * \param directed Boolean, whether to consider directed - * paths. Ignored for undirected graphs. - * \param unconn What to do if the graph is not connected. If - * \c true, only those vertex pairs will be included in the calculation - * between which there is a path. If \c false, \c IGRAPH_INFINITY is returned - * for disconnected graphs. - * \return Error code: - * \c IGRAPH_ENOMEM, not enough memory for data structures - * - * Time complexity: O(|V| |E|), the number of vertices times the number of edges. - * - * \sa \ref igraph_average_path_length_dijkstra() for the weighted version. - * - * \example examples/simple/igraph_average_path_length.c - */ - -igraph_error_t igraph_average_path_length(const igraph_t *graph, - igraph_real_t *res, igraph_real_t *unconn_pairs, - igraph_bool_t directed, igraph_bool_t unconn) -{ - return igraph_i_average_path_length_unweighted(graph, res, unconn_pairs, directed, /* invert= */ 0, unconn); -} - - -/** - * \ingroup structural - * \function igraph_average_path_length_dijkstra - * \brief The average weighted shortest path length between all vertex pairs. + * \brief The average shortest path length between all vertex pairs. * * If no vertex pairs can be included in the calculation, for example because the graph * has fewer than two vertices, or if the graph has no edges and \c unconn is set to \c true, @@ -340,16 +298,15 @@ igraph_error_t igraph_average_path_length(const igraph_t *graph, * All distinct ordered vertex pairs are taken into account. * * \param graph The graph object. + * \param weights The edge weights. All edge weights must be + * non-negative for Dijkstra's algorithm to work. Additionally, no + * edge weight may be NaN. If either case does not hold, an error + * is returned. Passa a null pointer here if the graph is unweighted. + * Edges with positive infinite weight are ignored. * \param res Pointer to a real number, this will contain the result. * \param unconn_pairs Pointer to a real number. If not a null pointer, the number of * ordered vertex pairs where the second vertex is unreachable from the first one * will be stored here. - * \param weights The edge weights. All edge weights must be - * non-negative for Dijkstra's algorithm to work. Additionally, no - * edge weight may be NaN. If either case does not hold, an error - * is returned. If this is a null pointer, then the unweighted - * version, \ref igraph_average_path_length() is called. Edges with positive - * infinite weight are ignored. * \param directed Boolean, whether to consider directed paths. * Ignored for undirected graphs. * \param unconn If \c true, only those pairs are considered for the calculation @@ -366,17 +323,22 @@ igraph_error_t igraph_average_path_length(const igraph_t *graph, * Time complexity: O(|V| |E| log|E| + |V|), where |V| is the number of * vertices and |E| is the number of edges. * - * \sa \ref igraph_average_path_length() for a slightly faster unweighted version. - * * \example examples/simple/igraph_grg_game.c */ -igraph_error_t igraph_average_path_length_dijkstra(const igraph_t *graph, - igraph_real_t *res, igraph_real_t *unconn_pairs, - const igraph_vector_t *weights, - igraph_bool_t directed, igraph_bool_t unconn) -{ - return igraph_i_average_path_length_dijkstra(graph, res, unconn_pairs, weights, directed, /* invert= */ false, unconn); +igraph_error_t igraph_average_path_length( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_real_t *unconn_pairs, igraph_bool_t directed, igraph_bool_t unconn +) { + if (weights) { + return igraph_i_average_path_length_dijkstra( + graph, weights, res, unconn_pairs, directed, /* invert= */ false, unconn + ); + } else { + return igraph_i_average_path_length_unweighted( + graph, res, unconn_pairs, directed, /* invert = */ false, unconn + ); + } } @@ -402,7 +364,6 @@ igraph_error_t igraph_average_path_length_dijkstra(const igraph_t *graph, * https://dx.doi.org/10.1103/PhysRevLett.87.198701 * * \param graph The graph object. - * \param res Pointer to a real number, this will contain the result. * \param weights The edge weights. All edge weights must be * non-negative for Dijkstra's algorithm to work. Additionally, no * edge weight may be NaN. If either case does not hold, an error @@ -410,6 +371,7 @@ igraph_error_t igraph_average_path_length_dijkstra(const igraph_t *graph, * version, \ref igraph_average_path_length() is used in calculating * the global efficiency. Edges with positive infinite weights are * ignored. + * \param res Pointer to a real number, this will contain the result. * \param directed Boolean, whether to consider directed paths. * Ignored for undirected graphs. * \return Error code: @@ -427,11 +389,19 @@ igraph_error_t igraph_average_path_length_dijkstra(const igraph_t *graph, * \sa \ref igraph_local_efficiency(), \ref igraph_average_local_efficiency() */ -igraph_error_t igraph_global_efficiency(const igraph_t *graph, igraph_real_t *res, - const igraph_vector_t *weights, - igraph_bool_t directed) -{ - return igraph_i_average_path_length_dijkstra(graph, res, NULL, weights, directed, /* invert= */ true, /* unconn= */ false); +igraph_error_t igraph_global_efficiency( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_real_t *res, igraph_bool_t directed +) { + if (weights) { + return igraph_i_average_path_length_dijkstra( + graph, weights, res, NULL, directed, /* invert= */ true, /* unconn= */ false + ); + } else { + return igraph_i_average_path_length_unweighted( + graph, res, NULL, directed, /* invert= */ true, /* unconn= */ false + ); + } } @@ -462,7 +432,7 @@ static igraph_error_t igraph_i_local_efficiency_unweighted( * from, plus 1 */ memset(already_counted, 0, no_of_nodes * sizeof(already_counted[0])); - IGRAPH_CHECK(igraph_neighbors(graph, vertex_neis, vertex, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, vertex_neis, vertex, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); vertex_neis_size = igraph_vector_int_size(vertex_neis); igraph_vector_char_null(nei_mask); @@ -565,7 +535,7 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( igraph_integer_t vertex_neis_size; igraph_integer_t neighbor_count; /* unlike 'inc_edges_size', 'neighbor_count' does not count self-loops or multi-edges */ - IGRAPH_CHECK(igraph_neighbors(graph, vertex_neis, vertex, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, vertex_neis, vertex, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); vertex_neis_size = igraph_vector_int_size(vertex_neis); igraph_vector_char_null(nei_mask); @@ -679,14 +649,14 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( * http://dx.doi.org/10.1103/PhysRevE.71.036122 * * \param graph The graph object. - * \param res Pointer to an initialized vector, this will contain the result. - * \param vids The vertices around which the local efficiency will be calculated. * \param weights The edge weights. All edge weights must be * non-negative. Additionally, no edge weight may be NaN. If either * case does not hold, an error is returned. If this is a null * pointer, then the unweighted version, * \ref igraph_average_path_length() is called. Edges with positive * infinite weights are ignored. + * \param res Pointer to an initialized vector, this will contain the result. + * \param vids The vertices around which the local efficiency will be calculated. * \param directed Boolean, whether to consider directed paths. * Ignored for undirected graphs. * \param mode How to determine the local neighborhood of each vertex @@ -715,11 +685,10 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( * */ -igraph_error_t igraph_local_efficiency(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, - const igraph_vector_t *weights, - igraph_bool_t directed, igraph_neimode_t mode) -{ +igraph_error_t igraph_local_efficiency( + const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, + const igraph_vs_t vids, igraph_bool_t directed, igraph_neimode_t mode +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_integer_t nodes_to_calc; /* no. of vertices includes in computation */ @@ -838,10 +807,10 @@ igraph_error_t igraph_local_efficiency(const igraph_t *graph, igraph_vector_t *r * For the null graph, zero is returned by convention. * * \param graph The graph object. - * \param res Pointer to a real number, this will contain the result. * \param weights The edge weights. They must be all non-negative. * If a null pointer is given, all weights are assumed to be 1. Edges * with positive infinite weight are ignored. + * \param res Pointer to a real number, this will contain the result. * \param directed Boolean, whether to consider directed paths. * Ignored for undirected graphs. * \param mode How to determine the local neighborhood of each vertex @@ -870,10 +839,10 @@ igraph_error_t igraph_local_efficiency(const igraph_t *graph, igraph_vector_t *r * */ -igraph_error_t igraph_average_local_efficiency(const igraph_t *graph, igraph_real_t *res, - const igraph_vector_t *weights, - igraph_bool_t directed, igraph_neimode_t mode) -{ +igraph_error_t igraph_average_local_efficiency( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_bool_t directed, igraph_neimode_t mode +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_vector_t local_eff; @@ -886,7 +855,7 @@ igraph_error_t igraph_average_local_efficiency(const igraph_t *graph, igraph_rea IGRAPH_VECTOR_INIT_FINALLY(&local_eff, no_of_nodes); - IGRAPH_CHECK(igraph_local_efficiency(graph, &local_eff, igraph_vss_all(), weights, directed, mode)); + IGRAPH_CHECK(igraph_local_efficiency(graph, weights, &local_eff, igraph_vss_all(),directed, mode)); *res = igraph_vector_sum(&local_eff); *res /= no_of_nodes; @@ -941,16 +910,16 @@ igraph_error_t igraph_average_local_efficiency(const igraph_t *graph, igraph_rea * Time complexity: O(|V||E|), the * number of vertices times the number of edges. * - * \sa \ref igraph_diameter_dijkstra() for the weighted version, - * \ref igraph_radius() for the minimum eccentricity. + * \sa \ref igraph_radius() for the minimum eccentricity. * * \example examples/simple/igraph_diameter.c */ -igraph_error_t igraph_diameter(const igraph_t *graph, igraph_real_t *res, - igraph_integer_t *from, igraph_integer_t *to, - igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path, - igraph_bool_t directed, igraph_bool_t unconn) { +static igraph_error_t igraph_i_diameter_unweighted( + const igraph_t *graph, igraph_real_t *res, igraph_integer_t *from, + igraph_integer_t *to, igraph_vector_int_t *vertex_path, + igraph_vector_int_t *edge_path, igraph_bool_t directed, igraph_bool_t unconn +) { const igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t n; @@ -1064,7 +1033,7 @@ igraph_error_t igraph_diameter(const igraph_t *graph, igraph_real_t *res, igraph_vector_int_clear(edge_path); } } else { - IGRAPH_CHECK(igraph_get_shortest_path(graph, vertex_path, edge_path, + IGRAPH_CHECK(igraph_get_shortest_path(graph, NULL, vertex_path, edge_path, ifrom, ito, dirmode)); } } @@ -1078,61 +1047,11 @@ igraph_error_t igraph_diameter(const igraph_t *graph, igraph_real_t *res, return IGRAPH_SUCCESS; } -/** - * \function igraph_diameter_dijkstra - * \brief Calculates the weighted diameter of a graph using Dijkstra's algorithm. - * - * This function computes the weighted diameter of a graph, defined as the longest - * weighted shortest path, or the maximum weighted eccentricity of the graph's - * vertices. A corresponding shortest path, as well as its endpoints, - * can also be optionally computed. - * - * - * If the graph has no vertices, \c IGRAPH_NAN is returned. - * - * \param graph The input graph, can be directed or undirected. - * \param weights The edge weights of the graph. Can be \c NULL for an - * unweighted graph. Edges with positive infinite weight are ignored. - * \param res Pointer to a real number, if not \c NULL then it will contain - * the diameter (the actual distance). - * \param from Pointer to an integer, if not \c NULL it will be set to the - * source vertex of the diameter path. If the graph has no diameter path, - * it will be set to -1. - * \param to Pointer to an integer, if not \c NULL it will be set to the - * target vertex of the diameter path. If the graph has no diameter path, - * it will be set to -1. - * \param vertex_path Pointer to an initialized vector. If not \c NULL the actual - * longest geodesic path in terms of vertices will be stored here. The vector will be - * resized as needed. - * \param edge_path Pointer to an initialized vector. If not \c NULL the actual - * longest geodesic path in terms of edges will be stored here. The vector will be - * resized as needed. - * \param directed Boolean, whether to consider directed - * paths. Ignored for undirected graphs. - * \param unconn What to do if the graph is not connected. If - * \c true the longest geodesic within a component - * will be returned, otherwise \c IGRAPH_INFINITY is - * returned. - * \return Error code. - * - * Time complexity: O(|V||E|*log|E|), |V| is the number of vertices, - * |E| is the number of edges. - * - * \sa \ref igraph_diameter() for the unweighted version, - * \ref igraph_radius_dijkstra() for the minimum weighted eccentricity. - */ - - -igraph_error_t igraph_diameter_dijkstra(const igraph_t *graph, - const igraph_vector_t *weights, - igraph_real_t *res, - igraph_integer_t *from, - igraph_integer_t *to, - igraph_vector_int_t *vertex_path, - igraph_vector_int_t *edge_path, - igraph_bool_t directed, - igraph_bool_t unconn) { - +static igraph_error_t igraph_i_diameter_dijkstra( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_integer_t *from, igraph_integer_t *to, igraph_vector_int_t *vertex_path, + igraph_vector_int_t *edge_path, igraph_bool_t directed, igraph_bool_t unconn +) { /* Implementation details. This is the basic Dijkstra algorithm, with a binary heap. The heap is indexed, i.e. it stores not only the distances, but also which vertex they belong to. @@ -1182,16 +1101,9 @@ igraph_error_t igraph_diameter_dijkstra(const igraph_t *graph, return IGRAPH_SUCCESS; } - if (!weights) { - igraph_real_t diameter; - IGRAPH_CHECK(igraph_diameter(graph, &diameter, from, to, vertex_path, edge_path, directed, unconn)); - if (res) { - *res = diameter; - } - return IGRAPH_SUCCESS; - } + IGRAPH_ASSERT(weights != 0); - if (weights && igraph_vector_size(weights) != no_of_edges) { + if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") not equal to number of edges (%" IGRAPH_PRId ").", IGRAPH_EINVAL, igraph_vector_size(weights), no_of_edges); } @@ -1296,9 +1208,72 @@ igraph_error_t igraph_diameter_dijkstra(const igraph_t *graph, weights, dirmode)); } } + return IGRAPH_SUCCESS; } +/** + * \function igraph_diameter + * \brief Calculates the weighted diameter of a graph using Dijkstra's algorithm. + * + * This function computes the weighted diameter of a graph, defined as the longest + * weighted shortest path, or the maximum weighted eccentricity of the graph's + * vertices. A corresponding shortest path, as well as its endpoints, + * can also be optionally computed. + * + * + * If the graph has no vertices, \c IGRAPH_NAN is returned. + * + * \param graph The input graph, can be directed or undirected. + * \param weights The edge weights of the graph. Can be \c NULL for an + * unweighted graph. Edges with positive infinite weight are ignored. + * \param res Pointer to a real number, if not \c NULL then it will contain + * the diameter (the actual distance). + * \param from Pointer to an integer, if not \c NULL it will be set to the + * source vertex of the diameter path. If the graph has no diameter path, + * it will be set to -1. + * \param to Pointer to an integer, if not \c NULL it will be set to the + * target vertex of the diameter path. If the graph has no diameter path, + * it will be set to -1. + * \param vertex_path Pointer to an initialized vector. If not \c NULL the actual + * longest geodesic path in terms of vertices will be stored here. The vector will be + * resized as needed. + * \param edge_path Pointer to an initialized vector. If not \c NULL the actual + * longest geodesic path in terms of edges will be stored here. The vector will be + * resized as needed. + * \param directed Boolean, whether to consider directed + * paths. Ignored for undirected graphs. + * \param unconn What to do if the graph is not connected. If + * \c true the longest geodesic within a component + * will be returned, otherwise \c IGRAPH_INFINITY is + * returned. + * \return Error code. + * + * Time complexity: O(|V||E|*log|E|), |V| is the number of vertices, + * |E| is the number of edges. + * + * \sa \ref igraph_radius() for the minimum eccentricity. + * + * \example examples/simple/igraph_diameter.c + */ +igraph_error_t igraph_diameter( + const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, + igraph_integer_t *from, igraph_integer_t *to, igraph_vector_int_t *vertex_path, + igraph_vector_int_t *edge_path, igraph_bool_t directed, igraph_bool_t unconn +) { + if (weights) { + return igraph_i_diameter_dijkstra( + graph, weights, res, from, to, vertex_path, edge_path, + directed, unconn + ); + } else { + return igraph_i_diameter_unweighted( + graph, res, from, to, vertex_path, edge_path, + directed, unconn + ); + } +} + /** * Temporarily removes all edges incident on the vertex with the given ID from * the graph by setting the weights of these edges to infinity. @@ -1316,7 +1291,7 @@ static igraph_error_t igraph_i_semidelete_vertex( igraph_integer_t vid, igraph_vector_int_t *edges_removed, igraph_vector_int_t *eids ) { - IGRAPH_CHECK(igraph_incident(graph, eids, vid, IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, eids, vid, IGRAPH_ALL, IGRAPH_LOOPS)); const igraph_integer_t n = igraph_vector_int_size(eids); for (igraph_integer_t j = 0; j < n; j++) { diff --git a/src/vendor/cigraph/src/paths/simple_paths.c b/src/vendor/cigraph/src/paths/simple_paths.c index 13837750a2a..8c56fd2414d 100644 --- a/src/vendor/cigraph/src/paths/simple_paths.c +++ b/src/vendor/cigraph/src/paths/simple_paths.c @@ -1,6 +1,6 @@ /* IGraph library. - Copyright (C) 2014-2022 The igraph development team + Copyright (C) 2014-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 @@ -19,9 +19,11 @@ #include "igraph_paths.h" +#include "igraph_adjlist.h" +#include "igraph_bitset.h" #include "igraph_interface.h" #include "igraph_iterators.h" -#include "igraph_adjlist.h" +#include "igraph_vector_list.h" #include "core/interruption.h" @@ -29,27 +31,37 @@ * \function igraph_get_all_simple_paths * \brief List all simple paths from one source. * - * A path is simple if its vertices are unique, i.e. no vertex - * is visited more than once. + * A path is simple if its vertices are unique, i.e. no vertex is visited more + * than once. This function returns paths in terms of their vertices and + * ignores multi-edges. * * - * Note that potentially there are exponentially many - * paths between two vertices of a graph, and you may - * run out of memory when using this function when the - * graph has many cycles. Consider using the \p cutoff - * parameter when you do not need long paths. + * Note that potentially there are exponentially many paths between two + * vertices of a graph, and you may run out of memory when using this function + * when the graph has many cycles. Consider using the \p minlen and \p maxlen + * parameters to restrict the paths that are returned. * * \param graph The input graph. - * \param res Initialized integer vector. The paths are - * returned here in terms of their vertices, separated - * by -1 markers. The paths are included in arbitrary - * order, as they are found. + * \param res Initialized integer vector list. The paths are returned here in + * terms of their vertices. The paths are included in arbitrary order, as + * they are found. * \param from The start vertex. * \param to The target vertices. - * \param cutoff Maximum length of path that is considered. If - * negative, paths of all lengths are considered. - * \param mode The type of the paths to consider, it is ignored - * for undirected graphs. + * \param minlen Minimum length of paths that is considered. If negative, + * no lower bound is used on the path lengths. + * \param maxlen Maximum length of paths that is considered. If negative, + * no upper bound is used on the path lengths. + * \param mode The type of paths to be used for the calculation in directed + * graphs. Possible values: + * \clist + * \cli IGRAPH_OUT + * outgoing paths are calculated. + * \cli IGRAPH_IN + * incoming paths are calculated. + * \cli IGRAPH_ALL + * the directed graph is considered as an undirected one for + * the computation. + * \endclist * \return Error code. * * \sa \ref igraph_get_k_shortest_paths() @@ -58,75 +70,76 @@ * vertices. */ -igraph_error_t igraph_get_all_simple_paths(const igraph_t *graph, - igraph_vector_int_t *res, - igraph_integer_t from, - const igraph_vs_t to, - igraph_integer_t cutoff, - igraph_neimode_t mode) { - - igraph_integer_t no_nodes = igraph_vcount(graph); +igraph_error_t igraph_get_all_simple_paths( + const igraph_t *graph, + igraph_vector_int_list_t *res, + igraph_integer_t from, + const igraph_vs_t to, + igraph_integer_t minlen, + igraph_integer_t maxlen, + igraph_neimode_t mode) { + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_bool_t toall = igraph_vs_is_all(&to); igraph_vit_t vit; - igraph_bool_t toall = igraph_vs_is_all(&to); igraph_lazy_adjlist_t adjlist; igraph_vector_int_t stack, dist; /* used as a stack, but represented as a vector, - in order to be appendable to other vectors */ - igraph_vector_bool_t markto, added; + in order to be appendable the result vector list */ + igraph_bitset_t markto, added; igraph_vector_int_t nptr; int iter = 0; - if (from < 0 || from >= no_nodes) { + if (from < 0 || from >= vcount) { IGRAPH_ERROR("Index of source vertex is out of range.", IGRAPH_EINVVID); } if (!toall) { - IGRAPH_VECTOR_BOOL_INIT_FINALLY(&markto, no_nodes); + IGRAPH_BITSET_INIT_FINALLY(&markto, vcount); IGRAPH_CHECK(igraph_vit_create(graph, to, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); for (; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { - VECTOR(markto)[ IGRAPH_VIT_GET(vit) ] = true; + IGRAPH_BIT_SET(markto, IGRAPH_VIT_GET(vit)); } igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(1); } - IGRAPH_VECTOR_BOOL_INIT_FINALLY(&added, no_nodes); + IGRAPH_BITSET_INIT_FINALLY(&added, vcount); IGRAPH_VECTOR_INT_INIT_FINALLY(&stack, 100); IGRAPH_VECTOR_INT_INIT_FINALLY(&dist, 100); IGRAPH_CHECK(igraph_lazy_adjlist_init( graph, &adjlist, mode, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE )); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); - IGRAPH_VECTOR_INT_INIT_FINALLY(&nptr, no_nodes); + IGRAPH_VECTOR_INT_INIT_FINALLY(&nptr, vcount); - igraph_vector_int_clear(res); + igraph_vector_int_list_clear(res); igraph_vector_int_clear(&stack); igraph_vector_int_clear(&dist); igraph_vector_int_push_back(&stack, from); igraph_vector_int_push_back(&dist, 0); - VECTOR(added)[from] = true; + IGRAPH_BIT_SET(added, from); while (!igraph_vector_int_empty(&stack)) { - igraph_integer_t act = igraph_vector_int_tail(&stack); - igraph_integer_t curdist = igraph_vector_int_tail(&dist); - igraph_vector_int_t *neis = igraph_lazy_adjlist_get(&adjlist, act); - igraph_integer_t n; + const igraph_integer_t act = igraph_vector_int_tail(&stack); + const igraph_integer_t curdist = igraph_vector_int_tail(&dist); + + const igraph_vector_int_t *neis = igraph_lazy_adjlist_get(&adjlist, act); + IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); + + const igraph_integer_t n = igraph_vector_int_size(neis); igraph_integer_t *ptr = igraph_vector_int_get_ptr(&nptr, act); igraph_bool_t any; igraph_bool_t within_dist; igraph_integer_t nei; - IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); - - n = igraph_vector_int_size(neis); - - within_dist = (curdist < cutoff || cutoff < 0); + within_dist = (curdist < maxlen || maxlen < 0); if (within_dist) { /* Search for a neighbor that was not yet visited */ any = false; while (!any && (*ptr) < n) { nei = VECTOR(*neis)[(*ptr)]; - any = !VECTOR(added)[nei]; + any = !IGRAPH_BIT_TEST(added, nei); (*ptr) ++; } } @@ -134,17 +147,18 @@ igraph_error_t igraph_get_all_simple_paths(const igraph_t *graph, /* There is such a neighbor, add it */ IGRAPH_CHECK(igraph_vector_int_push_back(&stack, nei)); IGRAPH_CHECK(igraph_vector_int_push_back(&dist, curdist + 1)); - VECTOR(added)[nei] = true; + IGRAPH_BIT_SET(added, nei); /* Add to results */ - if (toall || VECTOR(markto)[nei]) { - IGRAPH_CHECK(igraph_vector_int_append(res, &stack)); - IGRAPH_CHECK(igraph_vector_int_push_back(res, -1)); + if (toall || IGRAPH_BIT_TEST(markto, nei)) { + if (curdist + 1 >= minlen) { + IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(res, &stack)); + } } } else { /* There is no such neighbor, finished with the subtree */ igraph_integer_t up = igraph_vector_int_pop_back(&stack); igraph_vector_int_pop_back(&dist); - VECTOR(added)[up] = false; + IGRAPH_BIT_CLEAR(added, up); VECTOR(nptr)[up] = 0; } @@ -155,11 +169,11 @@ igraph_error_t igraph_get_all_simple_paths(const igraph_t *graph, igraph_lazy_adjlist_destroy(&adjlist); igraph_vector_int_destroy(&dist); igraph_vector_int_destroy(&stack); - igraph_vector_bool_destroy(&added); + igraph_bitset_destroy(&added); IGRAPH_FINALLY_CLEAN(5); if (!toall) { - igraph_vector_bool_destroy(&markto); + igraph_bitset_destroy(&markto); IGRAPH_FINALLY_CLEAN(1); } diff --git a/src/vendor/cigraph/src/paths/sparsifier.c b/src/vendor/cigraph/src/paths/sparsifier.c index fe0c23cd551..c27e487fe4b 100644 --- a/src/vendor/cigraph/src/paths/sparsifier.c +++ b/src/vendor/cigraph/src/paths/sparsifier.c @@ -260,13 +260,11 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne igraph_bitset_null(&is_cluster_sampled); // Step 1: sample cluster centers - RNG_BEGIN(); for (j = 0; j < no_of_nodes; j++) { if (VECTOR(clustering)[j] == j && RNG_UNIF01() < sample_prob) { IGRAPH_BIT_SET(is_cluster_sampled, j); } } - RNG_END(); // Step 2 and 3 for (v = 0; v < no_of_nodes; v++) { diff --git a/src/vendor/cigraph/src/paths/unweighted.c b/src/vendor/cigraph/src/paths/unweighted.c index 2bf3affafe7..c8a34b5c068 100644 --- a/src/vendor/cigraph/src/paths/unweighted.c +++ b/src/vendor/cigraph/src/paths/unweighted.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -27,17 +25,28 @@ #include "core/interruption.h" +static igraph_error_t igraph_i_distances_cutoff_unweighted( + const igraph_t *graph, igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, + igraph_neimode_t mode, igraph_real_t cutoff +); +static igraph_error_t igraph_i_get_shortest_paths_unweighted( + const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, + igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode, + igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges +); + /** * \ingroup structural * \function igraph_distances_cutoff * \brief Length of the shortest paths between vertices, with cutoff. * - * \experimental - * * This function is similar to \ref igraph_distances(), but * paths longer than \p cutoff will not be considered. * * \param graph The graph object. + * \param weights Optional edge weights. If \c NULL, the graph is considered + * unweighted, i.e. all edge weights are equal to 1. * \param res The result of the calculation, a matrix. A pointer to an * initialized matrix, to be more precise. The matrix will be * resized if needed. It will have the same @@ -83,10 +92,25 @@ * * \example examples/simple/distances.c */ -igraph_error_t igraph_distances_cutoff(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode, igraph_real_t cutoff) { +igraph_error_t igraph_distances_cutoff( + const igraph_t *graph, const igraph_vector_t* weights, igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, + igraph_neimode_t mode, igraph_real_t cutoff +) { + if (weights == NULL) { + /* Unweighted distances */ + return igraph_i_distances_cutoff_unweighted(graph, res, from, to, mode, cutoff); + } else { + /* Dijkstra's algorithm; will return an error if there are negative weights */ + return igraph_distances_dijkstra_cutoff(graph, res, from, to, weights, mode, cutoff); + } +} +static igraph_error_t igraph_i_distances_cutoff_unweighted( + const igraph_t *graph, igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, + igraph_neimode_t mode, igraph_real_t cutoff +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t no_of_from, no_of_to; igraph_integer_t *already_counted; @@ -205,6 +229,8 @@ igraph_error_t igraph_distances_cutoff(const igraph_t *graph, igraph_matrix_t *r * \brief Length of the shortest paths between vertices. * * \param graph The graph object. + * \param weights Optional edge weights. If \c NULL, the graph is considered + * unweighted, i.e. all edge weights are 1. * \param res The result of the calculation, a matrix. A pointer to an * initialized matrix, to be more precise. The matrix will be * resized if needed. It will have the same @@ -249,24 +275,25 @@ igraph_error_t igraph_distances_cutoff(const igraph_t *graph, igraph_matrix_t *r * * \example examples/simple/distances.c */ -igraph_error_t igraph_distances(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode) { - return igraph_distances_cutoff(graph, res, from, to, mode, -1); -} - -/** - * \function igraph_shortest_paths - * \brief Length of the shortest paths between vertices. - * - * \deprecated-by igraph_distances 0.10.0 - */ -igraph_error_t igraph_shortest_paths(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - igraph_neimode_t mode) { - return igraph_distances(graph, res, from, to, mode); +igraph_error_t igraph_distances( + const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, igraph_neimode_t mode +) { + igraph_integer_t from_size; + + if (weights == NULL || igraph_vector_size(weights) == 0 || igraph_vector_min(weights) >= 0) { + /* These are handled by igraph_distances_cutoff() */ + return igraph_distances_cutoff(graph, weights, res, from, to, mode, -1); + } else { + /* Negative weights; will use Bellman-Ford or Johnson algorithm */ + if (mode != IGRAPH_OUT) { + IGRAPH_CHECK(igraph_vs_size(graph, &from, &from_size)); + if (from_size <= 100) { + return igraph_distances_bellman_ford(graph, res, from, to, weights, mode); + } + } + return igraph_distances_johnson(graph, res, from, to, weights, mode); + } } /** @@ -280,6 +307,8 @@ igraph_error_t igraph_shortest_paths(const igraph_t *graph, * to find \em all shortest paths. * * \param graph The graph object. + * \param weights Optional edge weights. If \c NULL, the graph is considered + * unweighted, i.e. all edge weights are equal to 1. * \param vertices The result, the IDs of the vertices along the paths. * This is a list of integer vectors where each element is an * \ref igraph_vector_int_t object. The list will be resized as needed. @@ -344,14 +373,28 @@ igraph_error_t igraph_shortest_paths(const igraph_t *graph, * * \example examples/simple/igraph_get_shortest_paths.c */ -igraph_error_t igraph_get_shortest_paths(const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, - igraph_integer_t from, const igraph_vs_t to, - igraph_neimode_t mode, - igraph_vector_int_t *parents, - igraph_vector_int_t *inbound_edges) { +igraph_error_t igraph_get_shortest_paths( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, + igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode, + igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges +) { + if (weights == NULL) { + return igraph_i_get_shortest_paths_unweighted(graph, vertices, edges, from, to, mode, parents, inbound_edges); + } else if (igraph_vector_size(weights) == 0 || igraph_vector_min(weights) >= 0) { + /* Dijkstra's algorithm */ + return igraph_get_shortest_paths_dijkstra(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); + } else { + /* Negative weights; will use Bellman-Ford algorithm */ + return igraph_get_shortest_paths_bellman_ford(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); + } +} +static igraph_error_t igraph_i_get_shortest_paths_unweighted( + const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, + igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode, + igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges +) { /* TODO: use inclist_t if to is long (longer than 1?) */ igraph_integer_t no_of_nodes = igraph_vcount(graph); @@ -425,7 +468,7 @@ igraph_error_t igraph_get_shortest_paths(const igraph_t *graph, while (!igraph_dqueue_int_empty(&q) && reached < to_reach) { igraph_integer_t act = igraph_dqueue_int_pop(&q) - 1; - IGRAPH_CHECK(igraph_incident(graph, &tmp, act, mode)); + IGRAPH_CHECK(igraph_incident(graph, &tmp, act, mode, IGRAPH_LOOPS)); vsize = igraph_vector_int_size(&tmp); for (j = 0; j < vsize; j++) { igraph_integer_t edge = VECTOR(tmp)[j]; @@ -552,6 +595,8 @@ igraph_error_t igraph_get_shortest_paths(const igraph_t *graph, * \param graph The input graph, it can be directed or * undirected. Directed paths are considered in directed * graphs. + * \param weights Optional edge weights. If \c NULL, the graph is considered + * unweighted, i.e. all edge weights are equal to 1. * \param vertices Pointer to an initialized vector or a null * pointer. If not a null pointer, then the vertex IDs along * the path are stored here, including the source and target @@ -576,12 +621,12 @@ igraph_error_t igraph_get_shortest_paths(const igraph_t *graph, * vertices. */ -igraph_error_t igraph_get_shortest_path(const igraph_t *graph, - igraph_vector_int_t *vertices, - igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, - igraph_neimode_t mode) { +igraph_error_t igraph_get_shortest_path( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_t *vertices, igraph_vector_int_t *edges, + igraph_integer_t from, igraph_integer_t to, + igraph_neimode_t mode +) { igraph_vector_int_list_t vertices2, *vp = &vertices2; igraph_vector_int_list_t edges2, *ep = &edges2; @@ -599,18 +644,18 @@ igraph_error_t igraph_get_shortest_path(const igraph_t *graph, ep = NULL; } - IGRAPH_CHECK(igraph_get_shortest_paths(graph, vp, ep, from, + IGRAPH_CHECK(igraph_get_shortest_paths(graph, weights, vp, ep, from, igraph_vss_1(to), mode, NULL, NULL)); /* 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/voronoi.c b/src/vendor/cigraph/src/paths/voronoi.c index 146a556daad..01eedea1b70 100644 --- a/src/vendor/cigraph/src/paths/voronoi.c +++ b/src/vendor/cigraph/src/paths/voronoi.c @@ -55,7 +55,6 @@ static igraph_error_t igraph_i_voronoi( if (tiebreaker == IGRAPH_VORONOI_RANDOM) { IGRAPH_VECTOR_INT_INIT_FINALLY(&tie_count, no_of_nodes); - RNG_BEGIN(); } IGRAPH_CHECK(igraph_vector_int_resize(membership, no_of_nodes)); @@ -143,7 +142,6 @@ static igraph_error_t igraph_i_voronoi( } if (tiebreaker == IGRAPH_VORONOI_RANDOM) { - RNG_END(); igraph_vector_int_destroy(&tie_count); IGRAPH_FINALLY_CLEAN(1); } @@ -199,7 +197,6 @@ static igraph_error_t igraph_i_voronoi_dijkstra( if (tiebreaker == IGRAPH_VORONOI_RANDOM) { IGRAPH_VECTOR_INT_INIT_FINALLY(&tie_count, no_of_nodes); - RNG_BEGIN(); } IGRAPH_CHECK(igraph_vector_int_resize(membership, no_of_nodes)); @@ -300,7 +297,6 @@ static igraph_error_t igraph_i_voronoi_dijkstra( } if (tiebreaker == IGRAPH_VORONOI_RANDOM) { - RNG_END(); igraph_vector_int_destroy(&tie_count); IGRAPH_FINALLY_CLEAN(1); } diff --git a/src/vendor/cigraph/src/paths/widest_paths.c b/src/vendor/cigraph/src/paths/widest_paths.c index 7598a835763..2691861f218 100644 --- a/src/vendor/cigraph/src/paths/widest_paths.c +++ b/src/vendor/cigraph/src/paths/widest_paths.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team diff --git a/src/vendor/cigraph/src/properties/basic_properties.c b/src/vendor/cigraph/src/properties/basic_properties.c index af296de1456..db6a1d32dd4 100644 --- a/src/vendor/cigraph/src/properties/basic_properties.c +++ b/src/vendor/cigraph/src/properties/basic_properties.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -96,8 +94,6 @@ igraph_error_t igraph_density(const igraph_t *graph, igraph_real_t *res, * \function igraph_mean_degree * \brief The mean degree of a graph. * - * \experimental - * * This is a convenience function that computes the average of all vertex * degrees. In directed graphs, the average of out-degrees and in-degrees is * the same; this is the number that is returned. For the null graph, which @@ -219,7 +215,7 @@ igraph_error_t igraph_diversity(const igraph_t *graph, const igraph_vector_t *we igraph_real_t d; igraph_integer_t v = IGRAPH_VIT_GET(vit); - IGRAPH_CHECK(igraph_incident(graph, &incident, v, /*mode=*/ IGRAPH_ALL)); + IGRAPH_CHECK(igraph_incident(graph, &incident, v, IGRAPH_ALL, IGRAPH_LOOPS)); k = igraph_vector_int_size(&incident); /* degree */ /* @@ -328,8 +324,12 @@ igraph_error_t igraph_reciprocity(const igraph_t *graph, igraph_real_t *res, for (igraph_integer_t i = 0; i < no_of_nodes; i++) { igraph_integer_t ip, op, indeg, outdeg; - IGRAPH_CHECK(igraph_neighbors(graph, &inneis, i, IGRAPH_IN)); - IGRAPH_CHECK(igraph_neighbors(graph, &outneis, i, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &inneis, i, IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE + )); + IGRAPH_CHECK(igraph_neighbors( + graph, &outneis, i, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE + )); indeg = igraph_vector_int_size(&inneis); outdeg = igraph_vector_int_size(&outneis); diff --git a/src/vendor/cigraph/src/properties/complete.c b/src/vendor/cigraph/src/properties/complete.c index 15b9f81177d..4951b86858a 100644 --- a/src/vendor/cigraph/src/properties/complete.c +++ b/src/vendor/cigraph/src/properties/complete.c @@ -20,7 +20,6 @@ #include "igraph_structural.h" #include "core/interruption.h" -#include "graph/internal.h" /** * \ingroup structural @@ -120,7 +119,7 @@ igraph_error_t igraph_is_complete(const igraph_t *graph, igraph_bool_t *res) { } /* If the graph is simple, compare and conclude */ - IGRAPH_CHECK(igraph_is_simple(graph, &simple)); + IGRAPH_CHECK(igraph_is_simple(graph, &simple, IGRAPH_DIRECTED)); if (simple) { *res = (ecount == complete_ecount); @@ -133,8 +132,10 @@ igraph_error_t igraph_is_complete(const igraph_t *graph, igraph_bool_t *res) { for (igraph_integer_t i = 0; i < vcount; ++i) { IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); - IGRAPH_CHECK(igraph_i_neighbors(graph, &neighbours, i, IGRAPH_OUT, - IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neighbours, i, IGRAPH_OUT, IGRAPH_NO_LOOPS, + IGRAPH_NO_MULTIPLE + )); if ((igraph_vector_int_size(&neighbours) < vcount - 1)) { *res = false; @@ -213,8 +214,6 @@ static igraph_error_t is_clique(const igraph_t *graph, igraph_vs_t candidate, * \function igraph_is_clique * \brief Does a set of vertices form a clique? * - * \experimental - * * Tests if all pairs within a set of vertices are adjacent, i.e. whether they * form a clique. An empty set and singleton set are considered to be a clique. * @@ -251,8 +250,6 @@ igraph_error_t igraph_is_clique(const igraph_t *graph, igraph_vs_t candidate, * \function igraph_is_independent_vertex_set * \brief Does a set of vertices form an independent set? * - * \experimental - * * Tests if no pairs within a set of vertices are adjacenct, i.e. whether they * form an independent set. An empty set and singleton set are both considered * to be an independent set. diff --git a/src/vendor/cigraph/src/properties/constraint.c b/src/vendor/cigraph/src/properties/constraint.c index 878eb25c21c..b71573c9a78 100644 --- a/src/vendor/cigraph/src/properties/constraint.c +++ b/src/vendor/cigraph/src/properties/constraint.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -113,10 +111,8 @@ igraph_error_t igraph_constraint(const igraph_t *graph, igraph_vector_t *res, i = IGRAPH_VIT_GET(vit); /* get neighbors of i */ - IGRAPH_CHECK(igraph_incident(graph, &ineis_in, i, - IGRAPH_IN)); - IGRAPH_CHECK(igraph_incident(graph, &ineis_out, i, - IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &ineis_in, i, IGRAPH_IN, IGRAPH_LOOPS)); + IGRAPH_CHECK(igraph_incident(graph, &ineis_out, i, IGRAPH_OUT, IGRAPH_LOOPS)); /* NaN for isolates */ if (igraph_vector_int_size(&ineis_in) == 0 && @@ -176,10 +172,8 @@ igraph_error_t igraph_constraint(const igraph_t *graph, igraph_vector_t *res, if (i == j) { continue; } - IGRAPH_CHECK(igraph_incident(graph, &jneis_in, j, - IGRAPH_IN)); - IGRAPH_CHECK(igraph_incident(graph, &jneis_out, j, - IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &jneis_in, j, IGRAPH_IN, IGRAPH_LOOPS)); + IGRAPH_CHECK(igraph_incident(graph, &jneis_out, j, IGRAPH_OUT, IGRAPH_LOOPS)); vsize2 = igraph_vector_int_size(&jneis_in); for (c = 0; c < vsize2; c++) { edge2 = VECTOR(jneis_in)[c]; @@ -221,10 +215,8 @@ igraph_error_t igraph_constraint(const igraph_t *graph, igraph_vector_t *res, if (i == j) { continue; } - IGRAPH_CHECK(igraph_incident(graph, &jneis_in, j, - IGRAPH_IN)); - IGRAPH_CHECK(igraph_incident(graph, &jneis_out, j, - IGRAPH_OUT)); + IGRAPH_CHECK(igraph_incident(graph, &jneis_in, j, IGRAPH_IN, IGRAPH_LOOPS)); + IGRAPH_CHECK(igraph_incident(graph, &jneis_out, j, IGRAPH_OUT, IGRAPH_LOOPS)); vsize2 = igraph_vector_int_size(&jneis_in); for (c = 0; c < vsize2; c++) { edge2 = VECTOR(jneis_in)[c]; diff --git a/src/vendor/cigraph/src/properties/convergence_degree.c b/src/vendor/cigraph/src/properties/convergence_degree.c index 661818f6aac..0c707fdaf57 100644 --- a/src/vendor/cigraph/src/properties/convergence_degree.c +++ b/src/vendor/cigraph/src/properties/convergence_degree.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team diff --git a/src/vendor/cigraph/src/properties/dag.c b/src/vendor/cigraph/src/properties/dag.c index afad5efbd61..420d7059164 100644 --- a/src/vendor/cigraph/src/properties/dag.c +++ b/src/vendor/cigraph/src/properties/dag.c @@ -1,32 +1,24 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* - IGraph library. - Copyright (C) 2005-2021 The igraph development team + IGraph library. + Copyright (C) 2005-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 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + 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 . */ -#include "igraph_topology.h" +#include "igraph_cycles.h" -#include "igraph_constructors.h" #include "igraph_dqueue.h" #include "igraph_interface.h" -#include "igraph_stack.h" /** * \function igraph_topological_sorting @@ -87,7 +79,7 @@ igraph_error_t igraph_topological_sorting( IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); IGRAPH_CHECK(igraph_dqueue_int_init(&sources, 0)); IGRAPH_FINALLY(igraph_dqueue_int_destroy, &sources); - IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), deg_mode, 0)); + IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), deg_mode, IGRAPH_NO_LOOPS)); igraph_vector_int_clear(res); @@ -106,7 +98,7 @@ igraph_error_t igraph_topological_sorting( /* Exclude the node from further source searches */ VECTOR(degrees)[node] = -1; /* Get the neighbors and decrease their degrees by one */ - IGRAPH_CHECK(igraph_neighbors(graph, &neis, node, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, node, mode, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE)); j = igraph_vector_int_size(&neis); for (i = 0; i < j; i++) { VECTOR(degrees)[ VECTOR(neis)[i] ]--; @@ -173,7 +165,7 @@ igraph_error_t igraph_is_dag(const igraph_t* graph, igraph_bool_t *res) { IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); IGRAPH_DQUEUE_INT_INIT_FINALLY(&sources, 0); - IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_IN, /* loops */ true)); + IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS)); igraph_integer_t vertices_left = no_of_nodes; @@ -191,7 +183,7 @@ igraph_error_t igraph_is_dag(const igraph_t* graph, igraph_bool_t *res) { VECTOR(degrees)[node] = -1; vertices_left--; /* Get the neighbors and decrease their degrees by one */ - IGRAPH_CHECK(igraph_neighbors(graph, &neis, node, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, node, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE)); igraph_integer_t n = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < n; i++) { igraph_integer_t nei = VECTOR(neis)[i]; @@ -220,96 +212,3 @@ igraph_error_t igraph_is_dag(const igraph_t* graph, igraph_bool_t *res) { return IGRAPH_SUCCESS; } - -/* Create the transitive closure of a tree graph. - This is fairly simple, we just collect all ancestors of a vertex - using a depth-first search. - */ -igraph_error_t igraph_transitive_closure_dag(const igraph_t *graph, igraph_t *closure) { - - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_vector_int_t deg; - igraph_vector_int_t new_edges; - igraph_vector_int_t ancestors; - igraph_integer_t root; - igraph_vector_int_t neighbors; - igraph_stack_int_t path; - igraph_vector_bool_t done; - - if (!igraph_is_directed(graph)) { - IGRAPH_ERROR("Tree transitive closure of a directed graph", - IGRAPH_EINVAL); - } - - IGRAPH_VECTOR_INT_INIT_FINALLY(&new_edges, 0); - IGRAPH_VECTOR_INT_INIT_FINALLY(°, no_of_nodes); - IGRAPH_VECTOR_INT_INIT_FINALLY(&ancestors, 0); - IGRAPH_VECTOR_INT_INIT_FINALLY(&neighbors, 0); - IGRAPH_CHECK(igraph_stack_int_init(&path, 0)); - IGRAPH_FINALLY(igraph_stack_int_destroy, &path); - IGRAPH_CHECK(igraph_vector_bool_init(&done, no_of_nodes)); - IGRAPH_FINALLY(igraph_vector_bool_destroy, &done); - - IGRAPH_CHECK(igraph_degree(graph, °, igraph_vss_all(), - IGRAPH_OUT, IGRAPH_LOOPS)); - -#define STAR (-1) - - for (root = 0; root < no_of_nodes; root++) { - if (VECTOR(deg)[root] != 0) { - continue; - } - IGRAPH_CHECK(igraph_stack_int_push(&path, root)); - - while (!igraph_stack_int_empty(&path)) { - igraph_integer_t node = igraph_stack_int_top(&path); - if (node == STAR) { - /* Leaving a node */ - igraph_integer_t j, n; - igraph_stack_int_pop(&path); - node = igraph_stack_int_pop(&path); - if (!VECTOR(done)[node]) { - igraph_vector_int_pop_back(&ancestors); - VECTOR(done)[node] = true; - } - n = igraph_vector_int_size(&ancestors); - for (j = 0; j < n; j++) { - IGRAPH_CHECK(igraph_vector_int_push_back(&new_edges, node)); - IGRAPH_CHECK(igraph_vector_int_push_back(&new_edges, - VECTOR(ancestors)[j])); - } - } else { - /* Getting into a node */ - igraph_integer_t n, j; - if (!VECTOR(done)[node]) { - IGRAPH_CHECK(igraph_vector_int_push_back(&ancestors, node)); - } - IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, - node, IGRAPH_IN)); - n = igraph_vector_int_size(&neighbors); - IGRAPH_CHECK(igraph_stack_int_push(&path, STAR)); - for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(neighbors)[j]; - IGRAPH_CHECK(igraph_stack_int_push(&path, nei)); - } - } - } - } - -#undef STAR - - igraph_vector_bool_destroy(&done); - igraph_stack_int_destroy(&path); - igraph_vector_int_destroy(&neighbors); - igraph_vector_int_destroy(&ancestors); - igraph_vector_int_destroy(°); - IGRAPH_FINALLY_CLEAN(5); - - IGRAPH_CHECK(igraph_create(closure, &new_edges, no_of_nodes, - IGRAPH_DIRECTED)); - - igraph_vector_int_destroy(&new_edges); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} diff --git a/src/vendor/cigraph/src/properties/degrees.c b/src/vendor/cigraph/src/properties/degrees.c index 5096803c1da..79c90c1185c 100644 --- a/src/vendor/cigraph/src/properties/degrees.c +++ b/src/vendor/cigraph/src/properties/degrees.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2023 The igraph development team @@ -41,8 +39,10 @@ * \c IGRAPH_ALL, total degree (sum of the * in- and out-degree). * This parameter is ignored for undirected graphs. - * \param loops Boolean, gives whether the self-loops should be - * counted. + * \param loops Specifies how to treat loop edges when calculating the + * degree. \c IGRAPH_NO_LOOPS ignores loop edges; \c IGRAPH_LOOPS_ONCE + * counts each loop edge only once; \c IGRAPH_LOOPS_TWICE counts each + * loop edge twice in undirected graphs and once in directed graphs. * \return Error code: * \c IGRAPH_EINVVID: invalid vertex ID. * \c IGRAPH_EINVMODE: invalid mode argument. @@ -53,9 +53,10 @@ * * \sa \ref igraph_degree() to retrieve the degrees for several vertices. */ -igraph_error_t igraph_maxdegree(const igraph_t *graph, igraph_integer_t *res, - igraph_vs_t vids, igraph_neimode_t mode, - igraph_bool_t loops) { +igraph_error_t igraph_maxdegree( + const igraph_t *graph, igraph_integer_t *res, igraph_vs_t vids, + igraph_neimode_t mode, igraph_loops_t loops +) { igraph_vector_int_t tmp; @@ -137,8 +138,8 @@ static igraph_error_t avg_nearest_neighbor_degree_weighted(const igraph_t *graph igraph_integer_t nv; igraph_real_t str = VECTOR(strength)[v]; /* Get neighbours and incident edges */ - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, mode)); - IGRAPH_CHECK(igraph_incident(graph, &edge_neis, v, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); + IGRAPH_CHECK(igraph_incident(graph, &edge_neis, v, mode, IGRAPH_LOOPS)); nv = igraph_vector_int_size(&neis); for (igraph_integer_t j = 0; j < nv; j++) { igraph_integer_t nei = VECTOR(neis)[j]; @@ -309,7 +310,7 @@ igraph_error_t igraph_avg_nearest_neighbor_degree(const igraph_t *graph, igraph_real_t sum = 0.0; igraph_integer_t v = IGRAPH_VIT_GET(vit); igraph_integer_t nv; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); nv = igraph_vector_int_size(&neis); for (igraph_integer_t j = 0; j < nv; j++) { igraph_integer_t nei = VECTOR(neis)[j]; @@ -599,7 +600,10 @@ static igraph_error_t strength_all( * \param mode Gives whether to count only outgoing (\c IGRAPH_OUT), * incoming (\c IGRAPH_IN) edges or both (\c IGRAPH_ALL). * This parameter is ignored for undirected graphs. - * \param loops Boolean, whether to count loop edges as well. + * \param loops Specifies how to treat loop edges when calculating the + * strength. \c IGRAPH_NO_LOOPS ignores loop edges; \c IGRAPH_LOOPS_ONCE + * counts each loop edge only once; \c IGRAPH_LOOPS_TWICE counts each + * loop edge twice in undirected graphs and once in directed graphs. * \param weights A vector giving the edge weights. If this is a \c NULL * pointer, then \ref igraph_degree() is called to perform the * calculation. @@ -610,9 +614,10 @@ static igraph_error_t strength_all( * * \sa \ref igraph_degree() for the traditional, non-weighted version. */ -igraph_error_t igraph_strength(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, - igraph_bool_t loops, const igraph_vector_t *weights) { +igraph_error_t igraph_strength( + const igraph_t *graph, igraph_vector_t *res, const igraph_vs_t vids, + igraph_neimode_t mode, igraph_loops_t loops, const igraph_vector_t *weights +) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_vit_t vit; @@ -653,27 +658,12 @@ igraph_error_t igraph_strength(const igraph_t *graph, igraph_vector_t *res, IGRAPH_CHECK(igraph_vector_resize(res, no_vids)); igraph_vector_null(res); - if (loops) { - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - IGRAPH_CHECK(igraph_incident(graph, &neis, IGRAPH_VIT_GET(vit), mode)); - const igraph_integer_t n = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t edge = VECTOR(neis)[j]; - VECTOR(*res)[i] += VECTOR(*weights)[edge]; - } - } - } else { - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - IGRAPH_CHECK(igraph_incident(graph, &neis, IGRAPH_VIT_GET(vit), mode)); - const igraph_integer_t n = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t edge = VECTOR(neis)[j]; - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); - if (from != to) { - VECTOR(*res)[i] += VECTOR(*weights)[edge]; - } - } + for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + IGRAPH_CHECK(igraph_incident(graph, &neis, IGRAPH_VIT_GET(vit), mode, loops)); + const igraph_integer_t n = igraph_vector_int_size(&neis); + for (igraph_integer_t j = 0; j < n; j++) { + igraph_integer_t edge = VECTOR(neis)[j]; + VECTOR(*res)[i] += VECTOR(*weights)[edge]; } } @@ -703,8 +693,10 @@ igraph_error_t igraph_strength(const igraph_t *graph, igraph_vector_t *res, * \c IGRAPH_ALL, total degree (sum of the * in- and out-degree). * This parameter is ignored for undirected graphs. - * \param loops Boolean, gives whether the self-loops should be - * counted. + * \param loops Specifies how to treat loop edges when calculating the + * degrees. \c IGRAPH_NO_LOOPS ignores loop edges; \c IGRAPH_LOOPS_ONCE + * counts each loop edge only once; \c IGRAPH_LOOPS_TWICE counts each + * loop edge twice in undirected graphs and once in directed graphs. * \param order Specifies whether the ordering should be ascending * (\c IGRAPH_ASCENDING) or descending (\c IGRAPH_DESCENDING). * \param only_indices If true, then return a sorted list of indices @@ -718,13 +710,11 @@ igraph_error_t igraph_strength(const igraph_t *graph, igraph_vector_t *res, * \c IGRAPH_EINVMODE: invalid mode argument. * */ -igraph_error_t igraph_sort_vertex_ids_by_degree(const igraph_t *graph, - igraph_vector_int_t *outvids, - igraph_vs_t vids, - igraph_neimode_t mode, - igraph_bool_t loops, - igraph_order_t order, - igraph_bool_t only_indices) { +igraph_error_t igraph_sort_vertex_ids_by_degree( + const igraph_t *graph, igraph_vector_int_t *outvids, + igraph_vs_t vids, igraph_neimode_t mode, igraph_loops_t loops, + igraph_order_t order, igraph_bool_t only_indices +) { igraph_integer_t i, n; igraph_vector_int_t degrees; igraph_vector_int_t vs_vec; diff --git a/src/vendor/cigraph/src/properties/girth.c b/src/vendor/cigraph/src/properties/girth.c index 28ee98be96b..df52e696ec4 100644 --- a/src/vendor/cigraph/src/properties/girth.c +++ b/src/vendor/cigraph/src/properties/girth.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team diff --git a/src/vendor/cigraph/src/properties/loops.c b/src/vendor/cigraph/src/properties/loops.c index 36866a04ac2..ed220512268 100644 --- a/src/vendor/cigraph/src/properties/loops.c +++ b/src/vendor/cigraph/src/properties/loops.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -126,8 +124,6 @@ igraph_error_t igraph_is_loop(const igraph_t *graph, igraph_vector_bool_t *res, * \function igraph_count_loops * \brief Counts the self-loops in the graph. * - * \experimental - * * Counts loop edges, i.e. edges whose two endpoints coincide. * * \param graph The input graph. diff --git a/src/vendor/cigraph/src/properties/multiplicity.c b/src/vendor/cigraph/src/properties/multiplicity.c index d41678597e5..87cbd6ff150 100644 --- a/src/vendor/cigraph/src/properties/multiplicity.c +++ b/src/vendor/cigraph/src/properties/multiplicity.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -37,6 +35,11 @@ * \param graph The input graph. * \param res Pointer to a boolean constant, the result * is stored here. + * \param directed Whether to consider the directions of edges. \c IGRAPH_UNDIRECTED + * means that edge directions will be ignored and a directed graph with at + * least one mutual edge pair will be considered non-simple. \c IGRAPH_DIRECTED + * means that edge directions will be considered. Ignored for + * undirected graphs. * \return Error code. * * \sa \ref igraph_is_loop() and \ref igraph_is_multiple() to @@ -46,7 +49,7 @@ * * Time complexity: O(|V|+|E|). */ -igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res) { +igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res, igraph_bool_t directed) { igraph_integer_t vc = igraph_vcount(graph); igraph_integer_t ec = igraph_ecount(graph); @@ -56,12 +59,15 @@ igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res) { /* If it is known, does the graph have them? */ igraph_bool_t has_loop, has_multi; + /* Will we need to check mutual edges explicitly? */ + igraph_bool_t need_to_check_mutual = directed == IGRAPH_UNDIRECTED && igraph_is_directed(graph); + known_loop = igraph_i_property_cache_has(graph, IGRAPH_PROP_HAS_LOOP); if (known_loop) { has_loop = igraph_i_property_cache_get_bool(graph, IGRAPH_PROP_HAS_LOOP); if (has_loop) { *res = false; - return IGRAPH_SUCCESS; + goto early_exit; } } @@ -70,15 +76,13 @@ igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res) { has_multi = igraph_i_property_cache_get_bool(graph, IGRAPH_PROP_HAS_MULTI); if (has_multi) { *res = false; - return IGRAPH_SUCCESS; + goto early_exit; } } - if (known_loop && known_multi) { - if (!has_loop && !has_multi) { - *res = true; - return IGRAPH_SUCCESS; - } + if (known_loop && known_multi && !has_loop && !has_multi) { + *res = true; + goto early_exit; } /* Up to now, these variables were used to store the cache status. @@ -95,7 +99,9 @@ igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res) { igraph_vector_int_t neis; IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); for (igraph_integer_t i = 0; i < vc; i++) { - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, i, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); const igraph_integer_t n = igraph_vector_int_size(&neis); for (igraph_integer_t j = 0; j < n; j++) { if (VECTOR(neis)[j] == i) { @@ -126,6 +132,19 @@ igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res) { igraph_i_property_cache_set_bool_checked(graph, IGRAPH_PROP_HAS_MULTI, has_multi); } +early_exit: + /* If at this point we have concluded that the graph is simple, _but_ the user + * asked us to ignore edge directions, we need to look for mutual edge pairs + * and return false if we find one. */ + if (*res && need_to_check_mutual) { + /* If the graph is undirected, we also check for mutual edges. */ + igraph_bool_t has_mutual; + IGRAPH_CHECK(igraph_has_mutual(graph, &has_mutual, false)); + if (has_mutual) { + *res = false; + } + } + return IGRAPH_SUCCESS; } @@ -169,8 +188,9 @@ igraph_error_t igraph_has_multiple(const igraph_t *graph, igraph_bool_t *res) { igraph_bool_t found = false; IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); for (i = 0; i < vc && !found; i++) { - IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, - IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &neis, i, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); n = igraph_vector_int_size(&neis); for (j = 1; j < n; j++) { if (VECTOR(neis)[j - 1] == VECTOR(neis)[j]) { @@ -353,7 +373,9 @@ igraph_error_t igraph_count_multiple_1(const igraph_t *graph, igraph_integer_t * igraph_vector_int_t vids; IGRAPH_VECTOR_INT_INIT_FINALLY(&vids, 0); - IGRAPH_CHECK(igraph_neighbors(graph, &vids, from, IGRAPH_OUT)); + IGRAPH_CHECK(igraph_neighbors( + graph, &vids, from, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE + )); count = 0; n = igraph_vector_int_size(&vids); diff --git a/src/vendor/cigraph/src/properties/neighborhood.c b/src/vendor/cigraph/src/properties/neighborhood.c index 2de5680e8f0..2db0b8c7a84 100644 --- a/src/vendor/cigraph/src/properties/neighborhood.c +++ b/src/vendor/cigraph/src/properties/neighborhood.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -122,7 +120,7 @@ igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int const igraph_integer_t actnode = igraph_dqueue_int_pop(&q); const igraph_integer_t actdist = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); const igraph_integer_t n = igraph_vector_int_size(&neis); if (actdist < order - 1) { @@ -260,7 +258,7 @@ igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list const igraph_integer_t actnode = igraph_dqueue_int_pop(&q); const igraph_integer_t actdist = igraph_dqueue_int_pop(&q); - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); const igraph_integer_t n = igraph_vector_int_size(&neis); if (actdist < order - 1) { @@ -405,7 +403,7 @@ igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_li igraph_integer_t actnode = igraph_dqueue_int_pop(&q); igraph_integer_t actdist = igraph_dqueue_int_pop(&q); igraph_integer_t n; - IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); n = igraph_vector_int_size(&neis); if (actdist < order - 1) { diff --git a/src/vendor/cigraph/src/properties/perfect.c b/src/vendor/cigraph/src/properties/perfect.c index de1b42623c8..8f0988bbc38 100644 --- a/src/vendor/cigraph/src/properties/perfect.c +++ b/src/vendor/cigraph/src/properties/perfect.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2021 The igraph development team @@ -23,7 +22,7 @@ #include "igraph_constructors.h" #include "igraph_interface.h" #include "igraph_operators.h" -#include "igraph_topology.h" +#include "igraph_isomorphism.h" #include "core/interruption.h" @@ -69,7 +68,7 @@ igraph_error_t igraph_is_perfect(const igraph_t *graph, igraph_bool_t *perfect) } // If the graph isn't simple then return an error. - IGRAPH_CHECK(igraph_is_simple(graph, &is_simple)); + IGRAPH_CHECK(igraph_is_simple(graph, &is_simple, IGRAPH_DIRECTED)); if (!is_simple) { IGRAPH_ERROR("Perfect graph testing is implemented for simple graphs only. Simplify the graph.", IGRAPH_EINVAL); } @@ -156,7 +155,7 @@ igraph_error_t igraph_is_perfect(const igraph_t *graph, igraph_bool_t *perfect) IGRAPH_FINALLY(igraph_destroy, &cycle); if (cycle_len > girth) { - IGRAPH_CHECK(igraph_subisomorphic_lad(&cycle, graph, NULL, &iso, NULL, NULL, /* induced */ 1, 0)); + IGRAPH_CHECK(igraph_subisomorphic_lad(&cycle, graph, NULL, &iso, NULL, NULL, /* induced */ 1)); if (iso) { *perfect = false; goto clean2; @@ -164,7 +163,7 @@ igraph_error_t igraph_is_perfect(const igraph_t *graph, igraph_bool_t *perfect) } if (cycle_len > comp_girth) { - IGRAPH_CHECK(igraph_subisomorphic_lad(&cycle, &comp_graph, NULL, &iso, NULL, NULL, /* induced */ 1, 0)); + IGRAPH_CHECK(igraph_subisomorphic_lad(&cycle, &comp_graph, NULL, &iso, NULL, NULL, /* induced */ 1)); if (iso) { *perfect = false; goto clean2; diff --git a/src/vendor/cigraph/src/properties/properties_internal.h b/src/vendor/cigraph/src/properties/properties_internal.h index b12b1b43341..70d6a8a3b4e 100644 --- a/src/vendor/cigraph/src/properties/properties_internal.h +++ b/src/vendor/cigraph/src/properties/properties_internal.h @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2011-2021 The igraph development team @@ -24,11 +23,11 @@ #include "igraph_decls.h" #include "igraph_iterators.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_trans4_al_simplify(igraph_adjlist_t *al, const igraph_vector_int_t *rank); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/properties/rich_club.c b/src/vendor/cigraph/src/properties/rich_club.c new file mode 100644 index 00000000000..cf0de3dc18b --- /dev/null +++ b/src/vendor/cigraph/src/properties/rich_club.c @@ -0,0 +1,166 @@ +/* + IGraph library. + Copyright (C) 2025 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 . +*/ + +#include "igraph_structural.h" + +#include "igraph_interface.h" +#include "igraph_isomorphism.h" + +/* Returns the total number of possible edges given the number of vertices in a graph, + * whether it is directed, and whether loops should be assumed possible. + * + * No loops, undirected: n * (n-1) / 2 + * No loops, directed: n * (n-1) + * Loops, undirected: n * (n+1) / 2 + * Loops, directed: n^2 + */ +static igraph_real_t total_possible_edges(igraph_integer_t vcount, + igraph_bool_t directed, + igraph_bool_t loops) { + igraph_real_t nv = (igraph_real_t) vcount; + if (!loops) { + return (directed ? nv * (nv - 1) : nv * (nv - 1) / 2); + } else { + return (directed ? nv * nv : nv * (nv + 1) / 2); + } +} + +/** + * \function igraph_rich_club_sequence + * \brief Density sequence of subgraphs formed by sequential vertex removal. + * + * \experimental + * + * This function takes a graph and a vertex ordering as input, sequentially + * removes the vertices in the given order, and calculates the density of the + * remaining subgraph after each removal. + * + * + * Density is calculated as the ratio of the number of edges (or total edge + * weight, if weighted) to the number of total possible edges in the graph. + * The latter is dependent on whether the graph is directed and whether + * self-loops are assumed to be possible: for undirected graphs without + * self-loops, this total is given by n(n-1)/2, + * and for directed graphs by n(n-1). + * When self-loops are allowed, these are adjusted to n(n+1)/2 + * for undirected and n^2 for directed graphs. + * + * + * Vertex order can be sorted by degree so that the resulting density sequence + * helps reveal how interconnected a graph is across different degree levels, + * or the presence of a "rich-club" effect. + * + * \param graph The graph object to analyze. + * \param weights Vector of edge weights. If \c NULL all weights are + * assumed to be 1. + * \param res Initialized vector, the result will be written here. res[i] + * contain the density of the remaining graph after \c i vertices have been + * removed. If \p normalized is set to \c false, it contains the remaining + * edge count (or remaining total edge weights if weights were given). + * \param vertex_order Vector giving the order in which vertices are removed. + * \param normalized If \c false, return edge counts (or total edge weights). + * If \c true, divide by the largest possible edge count to obtain densities. + * \param loops Whether self-loops are assumed to be possible. Ignored when + * normalized is not requested. + * \param directed If false, directed graphs will be treated as undirected. + * Ignored with undirected graphs. + * + * \return Error code: \c IGRAPH_EINVAL: invalid vertex_order vector and/or weight vector + * lengths + * + * Time complexity: O(|V| + |E|) + * where |V| is the number of vertices and |E| the number of edges in the graph given. + * + * \sa \ref igraph_density(), which uses the same calculation of total possible edges. + */ +igraph_error_t igraph_rich_club_sequence( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + const igraph_vector_int_t *vertex_order, + igraph_bool_t normalized, + igraph_bool_t loops, igraph_bool_t directed) { + + const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_integer_t ecount = igraph_ecount(graph); + igraph_vector_int_t order_of; + + // Error handling: invalid vertex_order and weights sizes + if (igraph_vector_int_size(vertex_order) != vcount) { + IGRAPH_ERRORF("Vertex order vector length (%" IGRAPH_PRId ") does not match " + "number of vertices (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, + igraph_vector_int_size(vertex_order), vcount); + } + if (weights && igraph_vector_size(weights) != ecount) { + IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match " + "number of edges (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, + igraph_vector_size(weights), ecount); + } + + if (! igraph_is_directed(graph)) { + directed = false; + } + + IGRAPH_CHECK(igraph_vector_resize(res, vcount)); + igraph_vector_null(res); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&order_of, vcount); + IGRAPH_CHECK(igraph_invert_permutation(vertex_order, &order_of)); + + igraph_bool_t warning_issued = false; + + // remaining_total_weight vector: number of edges (or total edge weight) removed by index + for (igraph_integer_t eid = 0; eid < ecount; eid++) { + igraph_integer_t v1 = IGRAPH_FROM(graph, eid); + igraph_integer_t v2 = IGRAPH_TO(graph, eid); + if (!loops && normalized && !warning_issued && v1 == v2) { + IGRAPH_WARNING("Self-loops were requested to be assumed absent, " + "but encountered a self-loop. Density calculations will proceed " + "with the assumption of no loops."); + warning_issued = true; + } + igraph_integer_t order_v1 = VECTOR(order_of)[v1]; // order of endpoints + igraph_integer_t order_v2 = VECTOR(order_of)[v2]; + + igraph_integer_t edge_removal_index = (order_v1 < order_v2 ? order_v1 : order_v2); + VECTOR(*res)[edge_removal_index] += (weights ? VECTOR(*weights)[eid] : 1); + } + + // remaining_total_weight vector: edges (or total edge weight) remaining after i removals + igraph_real_t total = 0; + for (igraph_integer_t i = vcount - 1; i >= 0; i--) { + total += VECTOR(*res)[i]; + VECTOR(*res)[i] = total; + } + + // Normalize edge counts to densities + if (normalized) { + for (igraph_integer_t i = 0; i < vcount; i++) { + // (vcount - i) = the number of vertices left in this loop + VECTOR(*res)[i] = + VECTOR(*res)[i] / + total_possible_edges(vcount - i, directed, loops); + } + } + + igraph_vector_int_destroy(&order_of); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/properties/spectral.c b/src/vendor/cigraph/src/properties/spectral.c index e362cef7454..380c46f001d 100644 --- a/src/vendor/cigraph/src/properties/spectral.c +++ b/src/vendor/cigraph/src/properties/spectral.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2006-2012 Gabor Csardi @@ -373,59 +371,3 @@ igraph_error_t igraph_get_laplacian_sparse( return IGRAPH_SUCCESS; } - -/** - * \function igraph_laplacian - * \brief Returns the Laplacian matrix of a graph (deprecated). - * - * This function produces the Laplacian matrix of a graph in either dense or - * sparse format. When \p normalized is set to true, the type of normalization - * used depends on the directnedness of the graph: symmetric normalization - * is used for undirected graphs and left stochastic normalization for - * directed graphs. - * - * \param graph Pointer to the graph to convert. - * \param res Pointer to an initialized matrix object or \c NULL. The dense matrix - * result will be stored here. - * \param sparseres Pointer to an initialized sparse matrix object or \c NULL. - * The sparse matrix result will be stored here. - * \param mode Controls whether to use out- or in-degrees in directed graphs. - * If set to \c IGRAPH_ALL, edge directions will be ignored. - * \param normalized Boolean, whether to normalize the result. - * \param weights An optional vector containing non-negative edge weights, - * to calculate the weighted Laplacian matrix. Set it to a null pointer to - * calculate the unweighted Laplacian. - * \return Error code. - * - * \deprecated-by igraph_get_laplacian 0.10.0 - */ - -igraph_error_t igraph_laplacian( - const igraph_t *graph, igraph_matrix_t *res, igraph_sparsemat_t *sparseres, - igraph_bool_t normalized, const igraph_vector_t *weights -) { - igraph_laplacian_normalization_t norm_method = IGRAPH_LAPLACIAN_UNNORMALIZED; - - if (!res && !sparseres) { - IGRAPH_ERROR("Laplacian: specify at least one of 'res' or 'sparseres'", - IGRAPH_EINVAL); - } - - if (normalized) { - if (igraph_is_directed(graph)) { - norm_method = IGRAPH_LAPLACIAN_LEFT; - } else { - norm_method = IGRAPH_LAPLACIAN_SYMMETRIC; - } - } - - if (res) { - IGRAPH_CHECK(igraph_get_laplacian(graph, res, IGRAPH_OUT, norm_method, weights)); - } - - if (sparseres) { - IGRAPH_CHECK(igraph_get_laplacian_sparse(graph, sparseres, IGRAPH_OUT, norm_method, weights)); - } - - return IGRAPH_SUCCESS; -} diff --git a/src/vendor/cigraph/src/properties/trees.c b/src/vendor/cigraph/src/properties/trees.c index a10ab58643c..d30d35a4c2f 100644 --- a/src/vendor/cigraph/src/properties/trees.c +++ b/src/vendor/cigraph/src/properties/trees.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2021 The igraph development team @@ -22,10 +20,10 @@ */ #include "igraph_structural.h" -#include "igraph_topology.h" #include "igraph_bitset.h" #include "igraph_constructors.h" +#include "igraph_cycles.h" #include "igraph_dqueue.h" #include "igraph_interface.h" #include "igraph_stack.h" @@ -98,7 +96,7 @@ igraph_error_t igraph_unfold_tree(const igraph_t *graph, igraph_t *tree, while (!igraph_dqueue_int_empty(&Q)) { igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); - IGRAPH_CHECK(igraph_incident(graph, &neis, actnode, mode)); + IGRAPH_CHECK(igraph_incident(graph, &neis, actnode, mode, IGRAPH_LOOPS)); igraph_integer_t n = igraph_vector_int_size(&neis); for (igraph_integer_t i = 0; i < n; i++) { @@ -189,7 +187,7 @@ static igraph_error_t igraph_i_is_tree_visitor(const igraph_t *graph, igraph_int } /* register all its yet-unvisited neighbours for future processing */ - IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, u, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, u, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); ncount = igraph_vector_int_size(&neighbors); for (i = 0; i < ncount; ++i) { igraph_integer_t v = VECTOR(neighbors)[i]; @@ -332,7 +330,7 @@ igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_ IGRAPH_CHECK(igraph_vector_int_init(°ree, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, °ree); - IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), mode == IGRAPH_IN ? IGRAPH_OUT : IGRAPH_IN, IGRAPH_LOOPS)); + IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_REVERSE_MODE(mode), IGRAPH_LOOPS)); for (i = 0; i < vcount; ++i) { if (VECTOR(degree)[i] == 0) { @@ -432,7 +430,7 @@ static igraph_error_t igraph_i_is_forest_visitor( } /* Vertex discovery: Register all its neighbours for future processing */ - IGRAPH_CHECK(igraph_neighbors(graph, neis, u, mode)); + IGRAPH_CHECK(igraph_neighbors(graph, neis, u, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); ncount = igraph_vector_int_size(neis); for (i = 0; i < ncount; ++i) { @@ -674,7 +672,7 @@ static igraph_error_t igraph_i_is_forest( IGRAPH_VECTOR_INT_INIT_FINALLY(°ree, 0); IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), - IGRAPH_REVERSE_MODE(mode), /* loops = */ 1)); + IGRAPH_REVERSE_MODE(mode), IGRAPH_LOOPS)); for (v = 0; v < vcount; ++v) { /* In an out-tree, roots have in-degree 0, diff --git a/src/vendor/cigraph/src/properties/triangles.c b/src/vendor/cigraph/src/properties/triangles.c index ea21c355f2f..a37d1ff9ae7 100644 --- a/src/vendor/cigraph/src/properties/triangles.c +++ b/src/vendor/cigraph/src/properties/triangles.c @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -189,7 +187,7 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, maxdegree = deg; } } - IGRAPH_CHECK(igraph_vector_int_order1(°ree, &order, maxdegree + 1)); + IGRAPH_CHECK(igraph_i_vector_int_order(°ree, &order, maxdegree + 1)); igraph_vector_int_destroy(°ree); IGRAPH_FINALLY_CLEAN(1); IGRAPH_VECTOR_INIT_FINALLY(&rank, affected_nodes); @@ -534,28 +532,6 @@ igraph_error_t igraph_count_adjacent_triangles(const igraph_t *graph, } } -/** - * \function igraph_adjacent_triangles - * \brief Count the number of triangles a vertex is part of (deprecated alias). - * - * \deprecated-by igraph_count_adjacent_triangles 0.10.15 - * - * \param graph The input graph. Edge directions and multiplicities are ignored. - * \param res Initiliazed vector, the results are stored here. - * \param vids The vertices to perform the calculation for. - * \return Error mode. - * - * \sa \ref igraph_list_triangles() to list them. - * - * Time complexity: O(d^2 n), d is the average vertex degree of the - * queried vertices, n is their number. - */ - -igraph_error_t igraph_adjacent_triangles(const igraph_t *graph, - igraph_vector_t *res, - const igraph_vs_t vids) { - return igraph_count_adjacent_triangles(graph, res, vids); -} /** * \function igraph_list_triangles @@ -576,7 +552,7 @@ igraph_error_t igraph_adjacent_triangles(const igraph_t *graph, * \return Error code. * * \sa \ref igraph_count_triangles() to count the triangles, - * \ref igraph_adjacent_triangles() to count the triangles a vertex + * \ref igraph_count_adjacent_triangles() to count the triangles a vertex * participates in, \ref igraph_transitivity_undirected() to compute * the global clustering coefficient. * @@ -778,7 +754,7 @@ static igraph_error_t transitivity_barrat4( IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); maxdegree = igraph_vector_int_max(°ree) + 1; - IGRAPH_CHECK(igraph_vector_int_order1(°ree, &order, maxdegree)); + IGRAPH_CHECK(igraph_i_vector_int_order(°ree, &order, maxdegree)); IGRAPH_CHECK(igraph_strength(graph, &strength, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, weights)); diff --git a/src/vendor/cigraph/src/properties/triangles_template.h b/src/vendor/cigraph/src/properties/triangles_template.h index 77dfc6edc38..fbc50e93c8f 100644 --- a/src/vendor/cigraph/src/properties/triangles_template.h +++ b/src/vendor/cigraph/src/properties/triangles_template.h @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -62,7 +60,7 @@ for (i = 0; i < no_of_nodes; i++) { } maxdegree = igraph_vector_int_max(°ree) + 1; -IGRAPH_CHECK(igraph_vector_int_order1(°ree, &order, maxdegree)); +IGRAPH_CHECK(igraph_i_vector_int_order(°ree, &order, maxdegree)); IGRAPH_VECTOR_INT_INIT_FINALLY(&rank, no_of_nodes); for (i = 0; i < no_of_nodes; i++) { VECTOR(rank)[ VECTOR(order)[i] ] = no_of_nodes - i - 1; diff --git a/src/vendor/cigraph/src/properties/triangles_template1.h b/src/vendor/cigraph/src/properties/triangles_template1.h index f495b5ff68a..187f5029334 100644 --- a/src/vendor/cigraph/src/properties/triangles_template1.h +++ b/src/vendor/cigraph/src/properties/triangles_template1.h @@ -1,5 +1,3 @@ -/* -*- mode: C -*- */ -/* vim:set ts=4 sw=4 sts=4 et: */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi diff --git a/src/vendor/cigraph/src/random/random.c b/src/vendor/cigraph/src/random/random.c index df9a2d8f05b..15c98f76f53 100644 --- a/src/vendor/cigraph/src/random/random.c +++ b/src/vendor/cigraph/src/random/random.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005-2012 Gabor Csardi @@ -30,7 +29,6 @@ #include "igraph_vector.h" #include "core/interruption.h" -#include "core/math.h" #include "math/safe_intop.h" #include "random/random_internal.h" @@ -43,6 +41,7 @@ #include #include #include /* DBL_MANT_DIG */ +#include /** * \section about_rngs @@ -146,32 +145,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 +186,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; } /* ------------------------------------ */ @@ -995,8 +994,6 @@ igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_integer_t l igraph_vector_int_clear(res); IGRAPH_CHECK(igraph_vector_int_reserve(res, length)); - RNG_BEGIN(); - Vprime = exp(log(RNG_UNIF01()) * ninv); l = l - 1; @@ -1061,8 +1058,6 @@ igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_integer_t l igraph_vector_int_push_back(res, l); /* allocated */ } - RNG_END(); - return IGRAPH_SUCCESS; } @@ -1101,7 +1096,7 @@ static void igraph_i_random_sample_alga_real(igraph_vector_t *res, /** * \ingroup nongraph - * \function igraph_random_sample_real + * \function igraph_i_random_sample_real * \brief Generates an increasing random sequence of integers (igraph_real_t version). * * This function is the 'real' version of \ref igraph_random_sample(), and was added @@ -1126,7 +1121,7 @@ static void igraph_i_random_sample_alga_real(igraph_vector_t *res, * size of the candidate pool. */ -igraph_error_t igraph_random_sample_real(igraph_vector_t *res, igraph_real_t l, +igraph_error_t igraph_i_random_sample_real(igraph_vector_t *res, igraph_real_t l, igraph_real_t h, igraph_integer_t length) { /* This function is the 'real' version of igraph_random_sample, and was added * so erdos_renyi_game_gnm can use a random sample of doubles instead of integers @@ -1181,8 +1176,6 @@ igraph_error_t igraph_random_sample_real(igraph_vector_t *res, igraph_real_t l, igraph_vector_clear(res); IGRAPH_CHECK(igraph_vector_reserve(res, length)); - RNG_BEGIN(); - Vprime = exp(log(RNG_UNIF01()) * ninv); l = l - 1; @@ -1252,8 +1245,6 @@ igraph_error_t igraph_random_sample_real(igraph_vector_t *res, igraph_real_t l, igraph_vector_push_back(res, l); /* allocated */ } - RNG_END(); - return IGRAPH_SUCCESS; } @@ -1404,7 +1395,7 @@ igraph_error_t igraph_random_sample_real(igraph_vector_t *res, igraph_real_t l, #define R_DT_log(p) (lower_tail? R_D_log(p) : R_D_LExp(p))/* log(p) in qF */ #define R_DT_Clog(p) (lower_tail? R_D_LExp(p): R_D_log(p))/* log(1-p) in qF*/ #define R_DT_Log(p) (lower_tail? (p) : R_Log1_Exp(p)) -/* == R_DT_log when we already "know" log_p == TRUE :*/ +/* == R_DT_log when we already "know" log_p == true :*/ #define R_Q_P01_check(p) \ if ((log_p && p > 0) || \ @@ -1615,8 +1606,6 @@ static double igraph_i_exp_rand(igraph_rng_t *rng) { #define repeat for(;;) -#define FALSE 0 -#define TRUE 1 #define M_1_SQRT_2PI 0.398942280401432677939946059934 /* 1/sqrt(2pi) */ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { @@ -1637,7 +1626,9 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { /* Local Vars [initialize some for -Wall]: */ double del, difmuk = 0., E = 0., fk = 0., fx, fy, g, px, py, t, u = 0., v, x; double pois = -1.; - int k, kflag, big_mu, new_big_mu = FALSE; + int k, big_mu; + bool new_big_mu = false; + bool kflag; if (!isfinite(mu) || mu < 0) { ML_ERR_return_NAN; @@ -1649,13 +1640,13 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { big_mu = mu >= 10.; if (big_mu) { - new_big_mu = FALSE; + new_big_mu = false; } if (!(big_mu && mu == muprev)) {/* maybe compute new persistent par.s */ if (big_mu) { - new_big_mu = TRUE; + new_big_mu = true; /* Case A. (recalculation of s,d,l because mu has changed): * The Poisson probabilities pk exceed the discrete normal * probabilities fk whenever k >= m(mu). @@ -1757,7 +1748,7 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { if (g >= 0.) { /* 'Subroutine' F is called (kflag=0 for correct return) */ - kflag = 0; + kflag = false; goto Step_F; } @@ -1777,7 +1768,7 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { difmuk = mu - fk; /* 'subroutine' F is called (kflag=1 for correct return) */ - kflag = 1; + kflag = true; Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */ @@ -1803,7 +1794,7 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { x *= x;/* x^2 */ fx = -0.5 * x; fy = omega * (((c3 * x + c2) * x + c1) * x + c0); - if (kflag > 0) { + if (kflag) { /* Step H. Hat acceptance (E is repeated on rejection) */ if (c * fabs(u) <= py * exp(px + E) - fy * exp(fx + E)) { break; @@ -2236,32 +2227,3 @@ static double igraph_i_rgamma(igraph_rng_t *rng, double a, double scale) { x = s + 0.5 * t; return scale * x * x; } - -igraph_error_t igraph_rng_get_dirichlet(igraph_rng_t *rng, - const igraph_vector_t *alpha, - igraph_vector_t *result) { - - igraph_integer_t len = igraph_vector_size(alpha); - igraph_real_t sum = 0.0; - - if (len < 2) { - IGRAPH_ERROR("Dirichlet parameter vector too short, must have at least two entries.", - IGRAPH_EINVAL); - } - if (igraph_vector_min(alpha) <= 0) { - IGRAPH_ERROR("Dirichlet concentration parameters must be positive.", - IGRAPH_EINVAL); - } - - IGRAPH_CHECK(igraph_vector_resize(result, len)); - - for (igraph_integer_t i = 0; i < len; i++) { - VECTOR(*result)[i] = igraph_rng_get_gamma(rng, VECTOR(*alpha)[i], 1.0); - sum += VECTOR(*result)[i]; - } - for (igraph_integer_t i = 0; i < len; i++) { - VECTOR(*result)[i] /= sum; - } - - return IGRAPH_SUCCESS; -} diff --git a/src/vendor/cigraph/src/random/random_device.cpp b/src/vendor/cigraph/src/random/random_device.cpp new file mode 100644 index 00000000000..b2a8abab16e --- /dev/null +++ b/src/vendor/cigraph/src/random/random_device.cpp @@ -0,0 +1,43 @@ +/* + IGraph library. + Copyright (C) 2025 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 . +*/ + +#include "random/random_internal.h" + +#include +#include + +/* This function attempts to produce an unpredictable number suitable for + * seeding the RNG upon startup. It makes an effort to avoid producing the + * same number when called within different processes, even if called + * approximately at the same time. However, it cannot guarantee this on + * all systems under all circumstancs. + * + * This function cannot fail. + */ +igraph_uint_t igraph_i_get_random_seed(void) { + try { + // Try to use C++'s std::random_device. This may fail, either because + // the systems's random device ran out of entropy or because the system + // does not offer this functionality. + return std::random_device()(); + } catch (...) { + // If random_device fails, use a time-based seed. A combination of + // time() (calendar time, low resolution) and clock() (processor time + // used, higher resolution) reduces the risk of seed collisions. + return igraph_uint_t(std::clock()) + igraph_uint_t(std::time(NULL)); + } +} diff --git a/src/vendor/cigraph/src/random/random_internal.h b/src/vendor/cigraph/src/random/random_internal.h index 25110da1a34..f935fd7c020 100644 --- a/src/vendor/cigraph/src/random/random_internal.h +++ b/src/vendor/cigraph/src/random/random_internal.h @@ -1,23 +1,18 @@ -/* -*- mode: C -*- */ /* - IGraph library. - Copyright (C) 2021 The igraph development team + IGraph library. + Copyright (C) 2021-2025 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 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA + 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 . */ #ifndef IGRAPH_RANDOM_INTERNAL_H @@ -27,12 +22,14 @@ #include "igraph_types.h" #include "igraph_vector.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS -igraph_error_t igraph_random_sample_real( +igraph_error_t igraph_i_random_sample_real( igraph_vector_t *res, igraph_real_t l, igraph_real_t h, igraph_integer_t length); -__END_DECLS +igraph_uint_t igraph_i_get_random_seed(void); + +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/cigraph/src/random/rng_pcg32.c b/src/vendor/cigraph/src/random/rng_pcg32.c index d821b386d7a..0bc23c78d8d 100644 --- a/src/vendor/cigraph/src/random/rng_pcg32.c +++ b/src/vendor/cigraph/src/random/rng_pcg32.c @@ -23,8 +23,6 @@ #include "pcg/pcg_variants.h" -#include "config.h" /* IGRAPH_THREAD_LOCAL */ - /* The original implementation of the 32-bit PCG random number generator in this * file was obtained from https://github.com/imneme/pcg-c * @@ -115,10 +113,10 @@ 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 + /* is_seeded = */ false }; #undef addr diff --git a/src/vendor/cigraph/src/random/sampling.c b/src/vendor/cigraph/src/random/sampling.c new file mode 100644 index 00000000000..588c74780ab --- /dev/null +++ b/src/vendor/cigraph/src/random/sampling.c @@ -0,0 +1,192 @@ +/* + IGraph library. + Copyright (C) 2025 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#include "igraph_sampling.h" + +/** + * \function igraph_rng_sample_sphere_surface + * \brief Sample points uniformly from the surface of a sphere. + * + * The center of the sphere is at the origin. + * + * \param rng The random number generator to use. + * \param dim The dimension of the random vectors. + * \param n The number of vectors to sample. + * \param radius Radius of the sphere, it must be positive. + * \param positive Whether to restrict sampling to the positive + * orthant. + * \param res Pointer to an initialized matrix, the result is + * stored here, each column will be a sampled vector. The matrix is + * resized, as needed. + * \return Error code. + * + * Time complexity: O(n*dim*g), where g is the time complexity of + * generating a standard normal random number. + * + * \sa \ref igraph_rng_sample_sphere_volume(), \ref + * igraph_rng_sample_dirichlet() for other similar samplers. + */ +igraph_error_t igraph_rng_sample_sphere_surface( + igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_bool_t positive, igraph_matrix_t *res +) { + igraph_integer_t i, j; + + if (dim < 2) { + IGRAPH_ERROR("Sphere must be at least two dimensional to sample from " + "surface.", IGRAPH_EINVAL); + } + if (n < 0) { + IGRAPH_ERROR("Number of samples must be non-negative.", IGRAPH_EINVAL); + } + if (radius <= 0) { + IGRAPH_ERROR("Sphere radius must be positive.", IGRAPH_EINVAL); + } + + IGRAPH_CHECK(igraph_matrix_resize(res, dim, n)); + + for (i = 0; i < n; i++) { + igraph_real_t *col = &MATRIX(*res, 0, i); + igraph_real_t sum = 0.0; + for (j = 0; j < dim; j++) { + col[j] = igraph_rng_get_normal(rng, 0, 1); + sum += col[j] * col[j]; + } + sum = sqrt(sum); + for (j = 0; j < dim; j++) { + col[j] = radius * col[j] / sum; + } + if (positive) { + for (j = 0; j < dim; j++) { + col[j] = fabs(col[j]); + } + } + } + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_rng_sample_sphere_volume + * \brief Sample points uniformly from the volume of a sphere. + * + * The center of the sphere is at the origin. + * + * \param rng The random number generator to use. + * \param dim The dimension of the random vectors. + * \param n The number of vectors to sample. + * \param radius Radius of the sphere, it must be positive. + * \param positive Whether to restrict sampling to the positive + * orthant. + * \param res Pointer to an initialized matrix, the result is + * stored here, each column will be a sampled vector. The matrix is + * resized, as needed. + * \return Error code. + * + * Time complexity: O(n*dim*g), where g is the time complexity of + * generating a standard normal random number. + * + * \sa \ref igraph_rng_sample_sphere_surface(), \ref + * igraph_rng_sample_dirichlet() for other similar samplers. + */ +igraph_error_t igraph_rng_sample_sphere_volume( + igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_bool_t positive, igraph_matrix_t *res +) { + + igraph_integer_t i, j; + + /* Arguments are checked by the following call */ + + IGRAPH_CHECK(igraph_rng_sample_sphere_surface(rng, dim, n, radius, positive, res)); + + for (i = 0; i < n; i++) { + igraph_real_t *col = &MATRIX(*res, 0, i); + igraph_real_t U = pow(igraph_rng_get_unif01(rng), 1.0 / dim); + for (j = 0; j < dim; j++) { + col[j] *= U; + } + } + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_rng_sample_dirichlet + * \brief Sample points from a Dirichlet distribution. + * + * \param rng The random number generator to use. + * \param n The number of vectors to sample. + * \param alpha The parameters of the Dirichlet distribution. They + * must be positive. The length of this vector gives the dimension + * of the generated samples. + * \param res Pointer to an initialized matrix, the result is stored + * here, one sample in each column. It will be resized, as needed. + * \return Error code. + * + * Time complexity: O(n * dim * g), where dim is the dimension of the + * sample vectors, set by the length of alpha, and g is the time + * complexity of sampling from a Gamma distribution. + * + * \sa \ref igraph_rng_sample_sphere_surface() and + * \ref igraph_rng_sample_sphere_volume() for other methods to sample + * latent vectors. + */ +igraph_error_t igraph_rng_sample_dirichlet( + igraph_rng_t* rng, igraph_integer_t n, const igraph_vector_t *alpha, + igraph_matrix_t *res +) { + + igraph_integer_t len = igraph_vector_size(alpha); + igraph_integer_t i, j; + igraph_real_t sum, num; + + if (n < 0) { + IGRAPH_ERRORF("Number of samples should be non-negative, got %" IGRAPH_PRId ".", + IGRAPH_EINVAL, n); + } + + if (len < 2) { + IGRAPH_ERRORF("Dirichlet parameter vector too short, must " + "have at least two entries, got %" IGRAPH_PRId + ".", IGRAPH_EINVAL, len); + } + + if (igraph_vector_min(alpha) <= 0) { + IGRAPH_ERRORF("Dirichlet concentration parameters must be positive, got %g.", + IGRAPH_EINVAL, igraph_vector_min(alpha)); + } + + IGRAPH_CHECK(igraph_matrix_resize(res, len, n)); + + for (i = 0; i < n; i++) { + for (j = 0, sum = 0.0; j < len; j++) { + num = igraph_rng_get_gamma(rng, VECTOR(*alpha)[j], 1.0); + sum += num; + MATRIX(*res, j, i) = num; + } + for (j = 0; j < len; j++) { + MATRIX(*res, j, i) /= sum; + } + } + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/spatial/nearest_neighbor.cpp b/src/vendor/cigraph/src/spatial/nearest_neighbor.cpp new file mode 100644 index 00000000000..6fb5f12fc19 --- /dev/null +++ b/src/vendor/cigraph/src/spatial/nearest_neighbor.cpp @@ -0,0 +1,283 @@ +/* + IGraph library. + Copyright (C) 2025 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 . +*/ + +#include "igraph_spatial.h" + +#include "igraph_constructors.h" +#include "igraph_conversion.h" +#include "igraph_error.h" +#include "igraph_interface.h" +#include "igraph_matrix.h" +#include "igraph_types.h" +#include "igraph_vector.h" + +#include "core/exceptions.h" +#include "core/interruption.h" + +#include "nanoflann/nanoflann.hpp" + +#include + +class ig_point_adaptor { + const igraph_matrix_t *points; + const igraph_integer_t point_count; + +public: + explicit ig_point_adaptor(const igraph_matrix_t *points) : + points(points), point_count(igraph_matrix_nrow(points)) { } + + size_t kdtree_get_point_count() const { + return point_count; + } + + igraph_real_t kdtree_get_pt(const size_t idx, const size_t dim) const { + return MATRIX(*points, idx, dim); + } + + template + bool kdtree_get_bbox(BoundingBox &bb) const { + IGRAPH_UNUSED(bb); + return false; // indicates that it should use default + } +}; + + +class GraphBuildingResultSet { + igraph_integer_t current_vertex = 0; + igraph_integer_t added_count = 0; + const igraph_real_t max_distance; + const igraph_integer_t max_neighbors; + +public: + std::vector neighbors; + std::vector distances; + + using DistanceType = igraph_real_t; + using IndexType = igraph_integer_t; + + GraphBuildingResultSet(const igraph_integer_t max_neighbors, const igraph_real_t max_distance) : + max_distance(max_distance), + max_neighbors(max_neighbors), + neighbors(max_neighbors), + distances(max_neighbors) { } + + bool addPoint(const igraph_real_t distance, const igraph_integer_t index) { + igraph_integer_t i; + + if (index == current_vertex) { + return true; + } + + for (i = added_count; i > 0; i--) { + // TODO: Stabilize result in case of multiple points at exactly the same distance? + // See NANOFLANN_FIRST_MATCH in RKNNResultSet in nanoflann.hpp for reference. + if (distances[i-1] > distance) { + if (i < max_neighbors) { + distances[i] = distances[i-1]; + neighbors[i] = neighbors[i-1]; + } + } else { + break; + } + } + if (i < max_neighbors) { + neighbors[i] = index; + distances[i] = distance; + } + if (added_count != max_neighbors) { + added_count++; + } + return true; + } + + void reset(igraph_integer_t current_vertex_) { + added_count = 0; + current_vertex = current_vertex_; + } + + // Never called. Necessary to conform to the interface. + void sort() { } + + igraph_integer_t size() const { + return added_count; + } + + bool full() const { + return added_count == max_neighbors; + } + + bool empty() const { + return added_count == 0; + } + + igraph_real_t worstDist() const { + if (added_count < max_neighbors || added_count == 0) { + return max_distance; + } + return distances[added_count-1]; + } +}; + +template +static igraph_error_t neighbor_helper( + igraph_t *graph, + const igraph_matrix_t *points, + igraph_integer_t k, + igraph_real_t cutoff, + igraph_integer_t dimension, + igraph_bool_t directed) { + + const igraph_integer_t point_count = igraph_matrix_nrow(points); + ig_point_adaptor adaptor(points); + int iter = 0; + + using kdTree = nanoflann::KDTreeSingleIndexAdaptor; + kdTree tree(dimension, adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10)); + + tree.buildIndex(); + + igraph_vector_t current_point; + IGRAPH_VECTOR_INIT_FINALLY(¤t_point, dimension); + + igraph_integer_t neighbor_count = k >= 0 ? k : point_count; + + GraphBuildingResultSet results(neighbor_count, cutoff); + std::vector edges; + for (igraph_integer_t i = 0; i < point_count; i++) { + results.reset(i); + IGRAPH_CHECK(igraph_matrix_get_row(points, ¤t_point, i)); + + tree.findNeighbors(results, VECTOR(current_point), nanoflann::SearchParameters(0, false)); + for (igraph_integer_t j = 0; j < results.size(); j++) { + edges.push_back(i); + edges.push_back(results.neighbors[j]); + } + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 10); + } + + igraph_vector_destroy(¤t_point); + IGRAPH_FINALLY_CLEAN(1); + + // Overflow check, ensures that edges.size() is not too large for igraph vectors. + if (edges.size() > IGRAPH_INTEGER_MAX) { + IGRAPH_ERROR("Too many edges.", IGRAPH_EOVERFLOW); + } + + igraph_vector_int_t edge_view; + igraph_vector_int_view(&edge_view, edges.data(), edges.size()); + IGRAPH_CHECK(igraph_create(graph, &edge_view, point_count, true)); + + if (! directed) { + IGRAPH_CHECK(igraph_to_undirected(graph, IGRAPH_TO_UNDIRECTED_COLLAPSE, NULL)); + } + + return IGRAPH_SUCCESS; +} + + +template +static igraph_error_t dimension_dispatcher( + igraph_t *graph, + const igraph_matrix_t *points, + igraph_integer_t k, + igraph_real_t cutoff, + igraph_integer_t dimension, + igraph_bool_t directed) { + + switch (dimension) { + case 0: + IGRAPH_ERROR("0-dimensional points are not supported.", IGRAPH_EINVAL); + case 1: + return neighbor_helper(graph, points, k, cutoff, dimension, directed); + case 2: + return neighbor_helper(graph, points, k, cutoff, dimension, directed); + case 3: + return neighbor_helper(graph, points, k, cutoff, dimension, directed); + default: + return neighbor_helper(graph, points, k, cutoff, dimension, directed); + } +} + + +/** + * \function igraph_nearest_neighbor_graph + * \brief Computes the nearest neighbor graph for a spatial point set. + * + * This function constructs the \p k nearest neighbor graph of a given point + * set. Each point is connected to at most \p k spatial neighbors within a + * radius of \p cutoff. + * + * \param graph A pointer to the graph that will be created. + * \param points A matrix containing the points that will be used to create + * the graph. Each row is a point, dimensionality is inferred from the + * column count. + * \param metric The distance metric to use. See \ref igraph_metric_t. + * \param k At most how many neighbors will be added for each vertex, set to + * a negative value to ignore. + * \param cutoff Maximum distance at which connections will be made, set to a + * negative value or \c IGRAPH_INFINITY to ignore. + * \param directed Whether to create a directed graph. + * \return Error code. + * + * Time complexity: O(n log(n)) where n is the number of points. + */ +igraph_error_t igraph_nearest_neighbor_graph(igraph_t *graph, + const igraph_matrix_t *points, + igraph_metric_t metric, + igraph_integer_t k, + igraph_real_t cutoff, + igraph_bool_t directed) { + + const igraph_integer_t dimension = igraph_matrix_ncol(points); + + // Negative cutoff values signify that no cutoff should be used. + cutoff = cutoff >= 0 ? cutoff : IGRAPH_INFINITY; + + // Handle null graph separately. + // The number of matrix columns is not meaningful when there are zero rows. + // This prevents throwing an error when both the column and the row counts are zero. + if (igraph_matrix_nrow(points) == 0) { + return igraph_empty(graph, 0, directed); + } + + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; + + switch (metric) { + case IGRAPH_METRIC_L2: + return dimension_dispatcher >( + graph, + points, + k, + cutoff * cutoff, // L2 uses square distances, so adjust for that here. + dimension, + directed); + case IGRAPH_METRIC_L1: + return dimension_dispatcher >( + graph, + points, + k, + cutoff, + dimension, + directed); + default: + IGRAPH_ERROR("Invalid metric.", IGRAPH_EINVAL); + } + + IGRAPH_HANDLE_EXCEPTIONS_END; +} diff --git a/src/vendor/cigraph/vendor/CMakeLists.txt b/src/vendor/cigraph/vendor/CMakeLists.txt index 9befa6fa1ae..f22769136c1 100644 --- a/src/vendor/cigraph/vendor/CMakeLists.txt +++ b/src/vendor/cigraph/vendor/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(cs) add_subdirectory(f2c) add_subdirectory(glpk) +add_subdirectory(infomap) add_subdirectory(lapack) add_subdirectory(mini-gmp) add_subdirectory(pcg) diff --git a/src/vendor/cigraph/vendor/cs/cs_randperm.c b/src/vendor/cigraph/vendor/cs/cs_randperm.c index 4570da0f854..937187ec742 100644 --- a/src/vendor/cigraph/vendor/cs/cs_randperm.c +++ b/src/vendor/cigraph/vendor/cs/cs_randperm.c @@ -14,7 +14,6 @@ CS_INT *cs_randperm (CS_INT n, CS_INT seed) for (k = 0 ; k < n ; k++) p [k] = n-k-1 ; if (seed == -1) return (p) ; /* return reverse permutation */ /* srand (seed) ; /\* get new random number seed *\/ */ - RNG_BEGIN(); for (k = 0 ; k < n ; k++) { /* j = k + (rand ( ) % (n-k)) ; /\* j = rand CS_INT in range k to n-1 *\/ */ @@ -23,6 +22,5 @@ CS_INT *cs_randperm (CS_INT n, CS_INT seed) p [j] = p [k] ; p [k] = t ; } - RNG_END(); return (p) ; } diff --git a/src/vendor/cigraph/vendor/infomap/CITATION.cff b/src/vendor/cigraph/vendor/infomap/CITATION.cff new file mode 100644 index 00000000000..4acf57c22d6 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/CITATION.cff @@ -0,0 +1,16 @@ +cff-version: 2.8.0 +message: "If you use this software, please cite it as below." +authors: +- family-names: "Edler" + given-names: "Daniel" + orcid: "https://orcid.org/0000-0001-5420-0591" +- family-names: "Holmgren" + given-names: "Anton" + orcid: "https://orcid.org/0000-0001-5859-4073" +- family-names: "Rosvall" + given-names: "Martin" + orcid: "https://orcid.org/0000-0002-7181-9940" +title: "The MapEquation software package" +version: 2.8.0 +date-released: 2024-06-20 +url: "https://mapequation.org/" diff --git a/src/vendor/cigraph/vendor/infomap/CMakeLists.txt b/src/vendor/cigraph/vendor/infomap/CMakeLists.txt new file mode 100644 index 00000000000..111c9e204ec --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/CMakeLists.txt @@ -0,0 +1,48 @@ +# Declare the files needed to compile our vendored Infomap copy +add_library(infomap_vendored + OBJECT + EXCLUDE_FROM_ALL + src/core/MetaMapEquation.cpp + src/core/MemMapEquation.cpp + src/core/InfoEdge.cpp + src/core/BiasedMapEquation.cpp + src/core/StateNetwork.cpp + src/core/iterators/InfomapIterator.cpp + src/core/InfomapBase.cpp + src/core/InfoNode.cpp + src/io/Network.cpp + src/io/ClusterMap.cpp + src/io/ProgramInterface.cpp + src/io/Output.cpp + src/io/Config.cpp + src/utils/Log.cpp + src/utils/FileURI.cpp + src/utils/FlowCalculator.cpp +) + +target_include_directories( + infomap_vendored + + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/ + + PRIVATE + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include + ${PROJECT_BINARY_DIR}/src # config.h +) + +if(BUILD_SHARED_LIBS) + set_property(TARGET infomap_vendored PROPERTY POSITION_INDEPENDENT_CODE ON) +endif() + +# Since these are included as object files, they should call the +# function as is (without visibility specification) +target_compile_definitions(infomap_vendored PRIVATE IGRAPH_STATIC) + +# Infomap uses unsigned indices in OpenMP loops, which requires +# at least OpenMP 3.0. As of 2025, MSVC only supports OpenMP 2.0, +# thus this check is necessary. +if(IGRAPH_OPENMP_SUPPORT AND OpenMP_CXX_VERSION VERSION_GREATER_EQUAL 3) + target_link_libraries(infomap_vendored PRIVATE OpenMP::OpenMP_CXX) +endif() diff --git a/src/vendor/cigraph/vendor/infomap/LICENSE_GPLv3.txt b/src/vendor/cigraph/vendor/infomap/LICENSE_GPLv3.txt new file mode 100644 index 00000000000..e72bfddabc1 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/LICENSE_GPLv3.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/src/vendor/cigraph/vendor/infomap/README.rst b/src/vendor/cigraph/vendor/infomap/README.rst new file mode 100644 index 00000000000..b5819b0eb69 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/README.rst @@ -0,0 +1,162 @@ +.. image:: https://github.com/mapequation/infomap/actions/workflows/build.yml/badge.svg + +Infomap +======= + +Infomap is a network clustering algorithm based on the `Map equation`_. + +For detailed documentation, see `mapequation.org/infomap`_. + +For a list of recent changes, see `CHANGELOG.md`_ in the source directory. + +.. _Map equation: https://www.mapequation.org/publications.html#Rosvall-Axelsson-Bergstrom-2009-Map-equation +.. _`mapequation.org/infomap`: https://www.mapequation.org/infomap +.. _`CHANGELOG.md`: https://github.com/mapequation/infomap/blob/master/CHANGELOG.md + +Getting started +--------------- + +Infomap can be installed either from `PyPI`_ using ``pip`` or by +compiling from source. + +An experimental Javascript version for browsers is available on `NPM`_. + +.. _PyPI: https://pypi.org/project/infomap/ + +Using pip +--------- + +A pre-compiled version is available for macOS users. + +Installing on other operating systems requires a +working ``gcc`` or ``clang`` compiler. + +To install, run:: + + pip install infomap + + +To upgrade, run:: + + pip install --upgrade infomap + + +When the Python package is installed, an executable called +``infomap`` (with lowercase i) is available from any directory. + +To get started, read `Infomap Python API`_. + +.. _`Infomap Python API`: https://mapequation.github.io/infomap/python/ + +Using Docker +------------ + +There are currently two Docker images available on `Docker Hub`_. + +- ``mapequation/infomap`` +- ``mapequation/infomap:notebook`` based on ``jupyter/scipy-notebook`` + +The image ``mapequation/infomap`` can be started with + +.. code-block:: bash + + docker run -it --rm \ + -v `pwd`:/data \ + mapequation/infomap + [infomap arguments] + +You can also use the supplied `docker-compose.yml`_: + +.. code-block:: bash + + docker-compose run --rm infomap + +The image ``mapequation/infomap:notebook`` can be started with + +.. code-block:: bash + + docker run \ + -v `pwd`:/home/jovyan/work \ + -p 8888:8888 \ + mapequation/infomap:notebook \ + start.sh jupyter lab + +Or similarly, using docker-compose: + +.. code-block:: bash + + docker-compose up notebook + +.. _`Docker Hub`: https://hub.docker.com/r/mapequation/infomap +.. _`docker-compose.yml`: https://github.com/mapequation/infomap/blob/master/docker-compose.yml + +Compiling from source +--------------------- + +Installing Infomap from source requires a working ``gcc`` or ``clang`` compiler. + +To download and compile the newest version from `Github`_, clone the repository +by running + +.. code-block:: shell + + git clone git@github.com:mapequation/infomap.git + cd infomap + make + +This creates the binary ``Infomap``, run it using:: + + ./Infomap [options] network_data destination + +For a list of options, run:: + + ./Infomap --help + +Read `the documentation`_ to learn more about the different options. + +.. _Github: https://www.github.com/mapequation/infomap +.. _the documentation: https://www.mapequation.org/infomap + +Npm package +----------- + +An experimental Javascript web worker is available on `NPM`_. + +To install it, run + +.. code-block:: shell + + npm install @mapequation/infomap + +.. _NPM: https://www.npmjs.com/package/@mapequation/infomap + +Feedback +-------- + +If you have any questions, suggestions or issues regarding the software, +please add them to `GitHub issues`_. + +.. _Github issues: http://www.github.com/mapequation/infomap/issues + +Authors +------- + +Daniel Edler, Anton Holmgren, Martin Rosvall + +For contact information, see `mapequation.org/about.html`_. + +.. _`mapequation.org/about.html`: https://www.mapequation.org/about.html + +Terms of use +------------ + +Infomap is released under a dual licence. + +To give everyone maximum freedom to make use of Infomap +and derivative works, we make the code open source under +the GNU General Public License version 3 or any +later version (see `LICENSE_GPLv3.txt`_). + +For a non-copyleft license, please contact us. + +.. _LICENSE_GPLv3.txt: https://github.com/mapequation/infomap/blob/master/LICENSE_GPLv3.txt diff --git a/src/vendor/cigraph/vendor/infomap/src/Infomap.h b/src/vendor/cigraph/vendor/infomap/src/Infomap.h new file mode 100644 index 00000000000..9ebcd6fd0b3 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/Infomap.h @@ -0,0 +1,103 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMAP_H_ +#define INFOMAP_H_ + +#include "core/InfomapBase.h" +#include "io/Config.h" + +#include +#include +#include + +namespace infomap { + +// Wrapper class for the Python API +struct InfomapWrapper : public InfomapBase { +public: + InfomapWrapper() : InfomapBase() { } + InfomapWrapper(const std::string& flags) : InfomapBase(flags) { } + InfomapWrapper(const Config& conf) : InfomapBase(conf) { } + virtual ~InfomapWrapper() = default; + + // =================================================== + // Wrapper methods + // =================================================== + + void readInputData(std::string filename = "", bool accumulate = true) { m_network.readInputData(std::move(filename), accumulate); } + + void addNode(unsigned int id) { m_network.addNode(id); } + void addNode(unsigned int id, std::string name) { m_network.addNode(id, std::move(name)); } + void addNode(unsigned int id, double weight) { m_network.addNode(id, weight); } + void addNode(unsigned int id, std::string name, double weight) { m_network.addNode(id, std::move(name), weight); } + + void addName(unsigned int id, const std::string& name) { m_network.addName(id, name); } + std::string getName(unsigned int id) const + { + auto& names = m_network.names(); + auto it = names.find(id); + return it != names.end() ? it->second : ""; + } + + const std::map& getNames() const { return m_network.names(); } + + void addPhysicalNode(unsigned int id, const std::string& name = "") { m_network.addPhysicalNode(id, name); } + void addStateNode(unsigned int id, unsigned int physId) { m_network.addStateNode(id, physId); } + + void addLink(unsigned int sourceId, unsigned int targetId, double weight = 1.0) { m_network.addLink(sourceId, targetId, weight); } + void addLink(unsigned int sourceId, unsigned int targetId, unsigned long weight) { m_network.addLink(sourceId, targetId, weight); } + void addMultilayerLink(unsigned int layer1, unsigned int n1, unsigned int layer2, unsigned int n2, double weight = 1.0) { m_network.addMultilayerLink(layer1, n1, layer2, n2, weight); } + void addMultilayerIntraLink(unsigned int layer, unsigned int n1, unsigned int n2, double weight) { m_network.addMultilayerIntraLink(layer, n1, n2, weight); } + void addMultilayerInterLink(unsigned int layer1, unsigned int n, unsigned int layer2, double interWeight) { m_network.addMultilayerInterLink(layer1, n, layer2, interWeight); } + + void setBipartiteStartId(unsigned int startId) { m_network.setBipartiteStartId(startId); } + + std::map, double> getLinks(bool flow) const + { + std::map, double> links; + + for (const auto& node : m_network.nodeLinkMap()) { + const auto sourceId = node.first.id; + + for (const auto& link : node.second) { + const auto targetId = link.first.id; + links[{ sourceId, targetId }] = flow ? link.second.flow : link.second.weight; + } + } + + return links; + } + + std::map getModules(int level = 1, bool states = false) + { + if (haveMemory() && !states) { + throw std::runtime_error("Cannot get modules on higher-order network without states."); + } + std::map modules; + for (auto it = iterTree(level); !it.isEnd(); ++it) { + auto& node = *it; + if (node.isLeaf()) { + modules[states ? node.stateId : node.physicalId] = it.moduleId(); + } + } + return modules; + } + + using InfomapBase::codelength; + using InfomapBase::getEntropyRate; + using InfomapBase::getMultilevelModules; + using InfomapBase::iterLeafNodes; + using InfomapBase::iterTree; + using InfomapBase::run; +}; + +} // namespace infomap + +#endif // INFOMAP_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp new file mode 100644 index 00000000000..2ce1f3d102c --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp @@ -0,0 +1,238 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "BiasedMapEquation.h" +#include "FlowData.h" +#include "InfoNode.h" + +#include +#include +#include +#include "StateNetwork.h" + +namespace infomap { + +double BiasedMapEquation::s_totalDegree = 1; +unsigned int BiasedMapEquation::s_numNodes = 0; + +void BiasedMapEquation::setNetworkProperties(const StateNetwork& network) +{ + s_totalDegree = network.sumWeightedDegree(); + // Negative entropy bias is based on discrete counts, if average weight is below 1, use unweighted total degree + if (s_totalDegree < network.sumDegree()) { + s_totalDegree = network.sumDegree(); + } + s_numNodes = network.numNodes(); +} + +double BiasedMapEquation::getIndexCodelength() const +{ + return indexCodelength + indexEntropyBiasCorrection; +} + +double BiasedMapEquation::getModuleCodelength() const +{ + return moduleCodelength + biasedCost + moduleEntropyBiasCorrection; +} + +double BiasedMapEquation::getCodelength() const +{ + return codelength + biasedCost + getEntropyBiasCorrection(); +} + +double BiasedMapEquation::getEntropyBiasCorrection() const +{ + return indexEntropyBiasCorrection + moduleEntropyBiasCorrection; +} + +// =================================================== +// IO +// =================================================== + +std::ostream& BiasedMapEquation::print(std::ostream& out) const +{ + out << indexCodelength << " + " << moduleCodelength; + if (preferredNumModules != 0) { + out << " + " << biasedCost; + } + if (useEntropyBiasCorrection) { + out << " + " << getEntropyBiasCorrection(); + } + out << " = " << io::toPrecision(getCodelength()); + return out; +} + +std::ostream& operator<<(std::ostream& out, const BiasedMapEquation& mapEq) +{ + return mapEq.print(out); +} + +// =================================================== +// Init +// =================================================== + +void BiasedMapEquation::init(const Config& config) +{ + Log(3) << "BiasedMapEquation::init()...\n"; + preferredNumModules = config.preferredNumberOfModules; + useEntropyBiasCorrection = config.entropyBiasCorrection; + entropyBiasCorrectionMultiplier = config.entropyBiasCorrectionMultiplier; +} + +void BiasedMapEquation::initNetwork(InfoNode& root) +{ + Log(3) << "BiasedMapEquation::initNetwork()...\n"; + Base::initNetwork(root); +} + +void BiasedMapEquation::initPartition(std::vector& nodes) +{ + calculateCodelength(nodes); +} + +// =================================================== +// Codelength +// =================================================== + +double BiasedMapEquation::calcNumModuleCost(unsigned int numModules) const +{ + if (preferredNumModules == 0) return 0; + int deltaNumModules = numModules - preferredNumModules; + return 1 * std::abs(deltaNumModules); +} + +double BiasedMapEquation::calcIndexEntropyBiasCorrection(unsigned int numModules) const +{ + return useEntropyBiasCorrection ? entropyBiasCorrectionMultiplier * (numModules - 1) / (2 * s_totalDegree) : 0; +} + +double BiasedMapEquation::calcModuleEntropyBiasCorrection() const +{ + return useEntropyBiasCorrection ? entropyBiasCorrectionMultiplier * s_numNodes / (2 * s_totalDegree) : 0; +} + +double BiasedMapEquation::calcEntropyBiasCorrection(unsigned int numModules) const +{ + return useEntropyBiasCorrection ? entropyBiasCorrectionMultiplier * (numModules - 1 + s_numNodes) / (2 * s_totalDegree) : 0; +} + +void BiasedMapEquation::calculateCodelength(std::vector& nodes) +{ + calculateCodelengthTerms(nodes); + + calculateCodelengthFromCodelengthTerms(); + + currentNumModules = nodes.size(); + + biasedCost = calcNumModuleCost(currentNumModules); + + indexEntropyBiasCorrection = calcIndexEntropyBiasCorrection(currentNumModules); + moduleEntropyBiasCorrection = calcModuleEntropyBiasCorrection(); +} + +double BiasedMapEquation::calcCodelength(const InfoNode& parent) const +{ + return parent.isLeafModule() + ? calcCodelengthOnModuleOfLeafNodes(parent) + : calcCodelengthOnModuleOfModules(parent); +} + +double BiasedMapEquation::calcCodelengthOnModuleOfModules(const InfoNode& parent) const +{ + double L = Base::calcCodelengthOnModuleOfModules(parent); + if (!useEntropyBiasCorrection) + return L; + + return L + entropyBiasCorrectionMultiplier * parent.childDegree() / (2 * s_totalDegree); +} + +double BiasedMapEquation::calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const +{ + double L = Base::calcCodelength(parent); + if (!useEntropyBiasCorrection) + return L; + + return L + entropyBiasCorrectionMultiplier * parent.childDegree() / (2 * s_totalDegree); +} + +int BiasedMapEquation::getDeltaNumModulesIfMoving(unsigned int oldModule, + unsigned int newModule, + std::vector& moduleMembers) +{ + bool removeOld = moduleMembers[oldModule] == 1; + bool createNew = moduleMembers[newModule] == 0; + int deltaNumModules = removeOld && !createNew ? -1 : (!removeOld && createNew ? 1 : 0); + return deltaNumModules; +} + +double BiasedMapEquation::getDeltaCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) +{ + double deltaL = Base::getDeltaCodelengthOnMovingNode(current, oldModuleDelta, newModuleDelta, moduleFlowData, moduleMembers); + + if (preferredNumModules == 0) + return deltaL; + + int deltaNumModules = getDeltaNumModulesIfMoving(oldModuleDelta.module, newModuleDelta.module, moduleMembers); + + double deltaBiasedCost = calcNumModuleCost(currentNumModules + deltaNumModules) - biasedCost; + + double deltaEntropyBiasCorrection = calcEntropyBiasCorrection(currentNumModules + deltaNumModules) - getEntropyBiasCorrection(); + + return deltaL + deltaBiasedCost + deltaEntropyBiasCorrection; +} + +// =================================================== +// Consolidation +// =================================================== + +void BiasedMapEquation::updateCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) +{ + Base::updateCodelengthOnMovingNode(current, oldModuleDelta, newModuleDelta, moduleFlowData, moduleMembers); + + if (preferredNumModules == 0) + return; + + int deltaNumModules = getDeltaNumModulesIfMoving(oldModuleDelta.module, newModuleDelta.module, moduleMembers); + + currentNumModules += deltaNumModules; + biasedCost = calcNumModuleCost(currentNumModules); + indexEntropyBiasCorrection = calcIndexEntropyBiasCorrection(currentNumModules); + moduleEntropyBiasCorrection = calcModuleEntropyBiasCorrection(); +} + +void BiasedMapEquation::consolidateModules(std::vector& modules) +{ + unsigned int numModules = 0; + for (auto& module : modules) { + if (module == nullptr) + continue; + ++numModules; + } + currentNumModules = numModules; +} + +// =================================================== +// Debug +// =================================================== + +void BiasedMapEquation::printDebug() const +{ + std::cout << "BiasedMapEquation\n"; + Base::printDebug(); +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h new file mode 100644 index 00000000000..5663ba53109 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h @@ -0,0 +1,178 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef BIASED_MAPEQUATION_H_ +#define BIASED_MAPEQUATION_H_ + +#include "MapEquation.h" +#include "FlowData.h" +#include "../utils/Log.h" +#include +#include +#include +#include + +namespace infomap { + +class InfoNode; +class StateNetwork; + +class BiasedMapEquation : private MapEquation<> { + using Base = MapEquation<>; + +public: + using FlowDataType = FlowData; + using DeltaFlowDataType = DeltaFlow; + + // =================================================== + // Getters + // =================================================== + + double getIndexCodelength() const override; + + double getModuleCodelength() const override; + + double getCodelength() const override; + + double getEntropyBiasCorrection() const; + + // =================================================== + // IO + // =================================================== + + std::ostream& print(std::ostream& out) const override; + + friend std::ostream& operator<<(std::ostream&, const BiasedMapEquation&); + + // =================================================== + // Init + // =================================================== + + void init(const Config& config) override; + + void initTree(InfoNode& /*root*/) override { } + + void initNetwork(InfoNode& root) override; + + using Base::initSuperNetwork; + + using Base::initSubNetwork; + + void initPartition(std::vector& nodes) override; + + // =================================================== + // Codelength + // =================================================== + + double calcCodelength(const InfoNode& parent) const override; + + using Base::addMemoryContributions; + + double getDeltaCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) override; + + // =================================================== + // Consolidation + // =================================================== + + void updateCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) override; + + void consolidateModules(std::vector& modules) override; + + // =================================================== + // Debug + // =================================================== + + void printDebug() const override; + +private: + // =================================================== + // Private member functions + // =================================================== + double calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const override; + double calcCodelengthOnModuleOfModules(const InfoNode& parent) const override; + + static int getDeltaNumModulesIfMoving(unsigned int oldModule, unsigned int newModule, std::vector& moduleMembers); + + // =================================================== + // Init + // =================================================== + + // =================================================== + // Codelength + // =================================================== + + void calculateCodelength(std::vector& nodes) override; + + using Base::calculateCodelengthTerms; + + using Base::calculateCodelengthFromCodelengthTerms; + + double calcNumModuleCost(unsigned int numModules) const; + + double calcIndexEntropyBiasCorrection(unsigned int numModules) const; + double calcModuleEntropyBiasCorrection() const; + double calcEntropyBiasCorrection(unsigned int numModules) const; + + // =================================================== + // Consolidation + // =================================================== + +public: + // =================================================== + // Public member variables + // =================================================== + + using Base::codelength; + using Base::indexCodelength; + using Base::moduleCodelength; + +private: + // =================================================== + // Private member variables + // =================================================== + + using Base::enter_log_enter; + using Base::enterFlow; + using Base::enterFlow_log_enterFlow; + using Base::exit_log_exit; + using Base::flow_log_flow; // node.(flow + exitFlow) + using Base::nodeFlow_log_nodeFlow; // constant while the leaf network is the same + + // For hierarchical + using Base::exitNetworkFlow; + using Base::exitNetworkFlow_log_exitNetworkFlow; + + // For biased + unsigned int preferredNumModules = 0; + unsigned int currentNumModules = 0; + double biasedCost = 0.0; + + // For entropy bias correction + bool useEntropyBiasCorrection = false; + double entropyBiasCorrectionMultiplier = 1; + double indexEntropyBiasCorrection = 0; + double moduleEntropyBiasCorrection = 0; + static double s_totalDegree; + static unsigned int s_numNodes; + +public: + static void setNetworkProperties(const StateNetwork& network); +}; + +} // namespace infomap + +#endif // BIASED_MAPEQUATION_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/FlowData.h b/src/vendor/cigraph/vendor/infomap/src/core/FlowData.h new file mode 100644 index 00000000000..8b70d9b6121 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/FlowData.h @@ -0,0 +1,165 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef FLOWDATA_H_ +#define FLOWDATA_H_ + +#include +#include + +namespace infomap { + +struct FlowData { + double flow = 0.0; + double enterFlow = 0.0; + double exitFlow = 0.0; + double teleportFlow = 0.0; + double teleportSourceFlow = 0.0; + double teleportWeight = 0.0; + double danglingFlow = 0.0; + + FlowData() = default; + FlowData(double flow) : flow(flow) { } + + FlowData& operator+=(const FlowData& other) + { + flow += other.flow; + enterFlow += other.enterFlow; + exitFlow += other.exitFlow; + teleportFlow += other.teleportFlow; + teleportSourceFlow += other.teleportSourceFlow; + teleportWeight += other.teleportWeight; + danglingFlow += other.danglingFlow; + return *this; + } + + FlowData& operator-=(const FlowData& other) + { + flow -= other.flow; + enterFlow -= other.enterFlow; + exitFlow -= other.exitFlow; + teleportFlow -= other.teleportFlow; + teleportSourceFlow -= other.teleportSourceFlow; + teleportWeight -= other.teleportWeight; + danglingFlow -= other.danglingFlow; + return *this; + } + + friend std::ostream& operator<<(std::ostream& out, const FlowData& data) + { + return out << "flow: " << data.flow << ", enter: " << data.enterFlow << ", exit: " << data.exitFlow + << ", teleWeight: " << data.teleportWeight << ", danglingFlow: " << data.danglingFlow + << ", teleFlow: " << data.teleportFlow; + } +}; + +struct DeltaFlow { + unsigned int module = 0; + double deltaExit = 0.0; + double deltaEnter = 0.0; + unsigned int count = 0; + + explicit DeltaFlow(unsigned int module, double deltaExit, double deltaEnter) + : module(module), + deltaExit(deltaExit), + deltaEnter(deltaEnter) { } + + DeltaFlow() = default; + DeltaFlow(const DeltaFlow&) = default; + DeltaFlow(DeltaFlow&&) = default; + DeltaFlow& operator=(const DeltaFlow&) = default; + DeltaFlow& operator=(DeltaFlow&&) = default; + virtual ~DeltaFlow() = default; + + DeltaFlow& operator+=(const DeltaFlow& other) + { + module = other.module; + deltaExit += other.deltaExit; + deltaEnter += other.deltaEnter; + ++count; + return *this; + } + + virtual void reset() + { + module = 0; + deltaExit = 0.0; + deltaEnter = 0.0; + count = 0; + } + + friend void swap(DeltaFlow& first, DeltaFlow& second) noexcept + { + std::swap(first.module, second.module); + std::swap(first.deltaExit, second.deltaExit); + std::swap(first.deltaEnter, second.deltaEnter); + std::swap(first.count, second.count); + } + + friend std::ostream& operator<<(std::ostream& out, const DeltaFlow& data) + { + return out << "module: " << data.module << ", deltaEnter: " << data.deltaEnter << ", deltaExit: " << data.deltaExit << ", count: " << data.count; + } +}; + +struct MemDeltaFlow : DeltaFlow { + double sumDeltaPlogpPhysFlow = 0.0; + double sumPlogpPhysFlow = 0.0; + + MemDeltaFlow() = default; + + explicit MemDeltaFlow(unsigned int module, double deltaExit, double deltaEnter, double sumDeltaPlogpPhysFlow = 0.0, double sumPlogpPhysFlow = 0.0) + : DeltaFlow(module, deltaExit, deltaEnter), + sumDeltaPlogpPhysFlow(sumDeltaPlogpPhysFlow), + sumPlogpPhysFlow(sumPlogpPhysFlow) { } + + MemDeltaFlow& operator+=(const MemDeltaFlow& other) + { + DeltaFlow::operator+=(other); + sumDeltaPlogpPhysFlow += other.sumDeltaPlogpPhysFlow; + sumPlogpPhysFlow += other.sumPlogpPhysFlow; + return *this; + } + + void reset() override + { + DeltaFlow::reset(); + sumDeltaPlogpPhysFlow = 0.0; + sumPlogpPhysFlow = 0.0; + } + + friend void swap(MemDeltaFlow& first, MemDeltaFlow& second) noexcept + { + swap(static_cast(first), static_cast(second)); + std::swap(first.sumDeltaPlogpPhysFlow, second.sumDeltaPlogpPhysFlow); + std::swap(first.sumPlogpPhysFlow, second.sumPlogpPhysFlow); + } + + friend std::ostream& operator<<(std::ostream& out, const MemDeltaFlow& data) + { + return out << "module: " << data.module << ", deltaEnter: " << data.deltaEnter << ", deltaExit: " << data.deltaExit << ", count: " << data.count << ", sumDeltaPlogpPhysFlow: " << data.sumDeltaPlogpPhysFlow << ", sumPlogpPhysFlow: " << data.sumPlogpPhysFlow; + } +}; + +struct PhysData { + unsigned int physNodeIndex; + double sumFlowFromM2Node; // The amount of flow from the memory node in this physical node + + explicit PhysData(unsigned int physNodeIndex, double sumFlowFromM2Node = 0.0) + : physNodeIndex(physNodeIndex), sumFlowFromM2Node(sumFlowFromM2Node) { } + + friend std::ostream& operator<<(std::ostream& out, const PhysData& data) + { + return out << "physNodeIndex: " << data.physNodeIndex << ", sumFlowFromM2Node: " << data.sumFlowFromM2Node; + } +}; + +} // namespace infomap + +#endif // FLOWDATA_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.cpp b/src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.cpp new file mode 100644 index 00000000000..6bcb7039e69 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.cpp @@ -0,0 +1,26 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "InfoEdge.h" +#include "InfoNode.h" + +namespace infomap { + +InfoNode& infomap::InfoEdge::other(InfoNode& node) const +{ + return (node == *source) ? *target : *source; +} + +std::ostream& operator<<(std::ostream& out, const InfoEdge& edge) +{ + return out << "(" << *edge.source << ") -> (" << *edge.target << "), flow: " + << edge.data.flow; +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.h b/src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.h new file mode 100644 index 00000000000..e2d245fb64d --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfoEdge.h @@ -0,0 +1,47 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOEDGE_H_ +#define INFOEDGE_H_ + +#include + +namespace infomap { + +struct EdgeData { +public: + EdgeData() = default; + + EdgeData(double weight, double flow) : weight(weight), flow(flow) { } + + double weight; + double flow; +}; + +class InfoNode; + +class InfoEdge { +public: + InfoEdge(InfoNode& source, InfoNode& target, double weight, double flow) + : data(weight, flow), + source(&source), + target(&target) { } + + InfoNode& other(InfoNode& node) const; + + friend std::ostream& operator<<(std::ostream& out, const InfoEdge& edge); + + EdgeData data; + InfoNode* source; + InfoNode* target; +}; + +} // namespace infomap + +#endif // INFOEDGE_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfoNode.cpp b/src/vendor/cigraph/vendor/infomap/src/core/InfoNode.cpp new file mode 100644 index 00000000000..b7a7b0aa412 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfoNode.cpp @@ -0,0 +1,405 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "InfoNode.h" +#include "InfomapBase.h" +#include + +namespace infomap { + +InfoNode::~InfoNode() noexcept +{ + if (m_infomap != nullptr) { + delete m_infomap; + } + + deleteChildren(); + + if (next != nullptr) + next->previous = previous; + if (previous != nullptr) + previous->next = next; + if (parent != nullptr) { + if (parent->firstChild == this) + parent->firstChild = next; + if (parent->lastChild == this) + parent->lastChild = previous; + } + + // Delete outgoing edges. + // TODO: Renders ingoing edges invalid. Assume or assert that all nodes on the same level are deleted? + for (edge_iterator outEdgeIt(begin_outEdge()); + outEdgeIt != end_outEdge(); + ++outEdgeIt) { + delete *outEdgeIt; + } +} + +InfomapBase& InfoNode::setInfomap(InfomapBase* infomap) +{ + disposeInfomap(); + m_infomap = infomap; + if (infomap == nullptr) + throw std::logic_error("InfoNode::setInfomap(...) called with null infomap"); + return *m_infomap; +} + +InfomapBase& InfoNode::getInfomap() +{ + if (m_infomap == nullptr) + throw std::logic_error("InfoNode::getInfomap() called but infomap is null"); + return *m_infomap; +} + +const InfomapBase& InfoNode::getInfomap() const +{ + if (m_infomap == nullptr) + throw std::logic_error("InfoNode::getInfomap() called but infomap is null"); + return *m_infomap; +} + +InfoNode* InfoNode::getInfomapRoot() noexcept +{ + return m_infomap != nullptr ? &m_infomap->root() : nullptr; +} + +InfoNode const* InfoNode::getInfomapRoot() const noexcept +{ + return m_infomap != nullptr ? &m_infomap->root() : nullptr; +} + +bool InfoNode::disposeInfomap() noexcept +{ + if (m_infomap != nullptr) { + delete m_infomap; + m_infomap = nullptr; + return true; + } + return false; +} + +unsigned int InfoNode::depth() const noexcept +{ + unsigned int depth = 0; + InfoNode* n = parent; + while (n != nullptr) { + ++depth; + n = n->parent; + } + return depth; +} + +unsigned int InfoNode::firstDepthBelow() const noexcept +{ + unsigned int depthBelow = 0; + InfoNode* child = firstChild; + while (child != nullptr) { + ++depthBelow; + child = child->firstChild; + } + return depthBelow; +} + +unsigned int InfoNode::childIndex() const noexcept +{ + unsigned int childIndex = 0; + const InfoNode* n(this); + while (n->previous) { + n = n->previous; + ++childIndex; + } + return childIndex; +} + +std::vector InfoNode::calculatePath() const noexcept +{ + const InfoNode* current = this; + std::vector path; + while (current->parent != nullptr) { + path.push_back(current->childIndex() + 1); + current = current->parent; + if (current->owner != nullptr) { + current = current->owner; + } + } + std::reverse(path.begin(), path.end()); + return path; +} + +unsigned int InfoNode::infomapChildDegree() const noexcept +{ + return m_infomap == nullptr ? childDegree() : m_infomap->root().childDegree(); +} + +void InfoNode::addChild(InfoNode* child) noexcept +{ + if (firstChild == nullptr) { + child->previous = nullptr; + firstChild = child; + } else { + child->previous = lastChild; + lastChild->next = child; + } + lastChild = child; + child->next = nullptr; + child->parent = this; + ++m_childDegree; +} + +void InfoNode::releaseChildren() noexcept +{ + firstChild = nullptr; + lastChild = nullptr; + m_childDegree = 0; +} + +InfoNode& InfoNode::replaceChildrenWithOneNode() +{ + if (childDegree() == 1) + return *firstChild; + if (firstChild == nullptr) + throw std::logic_error("replaceChildrenWithOneNode called on a node without any children."); + if (firstChild->firstChild == nullptr) + throw std::logic_error("replaceChildrenWithOneNode called on a node without any grandchildren."); + auto* middleNode = new InfoNode(); + InfoNode::child_iterator nodeIt = begin_child(); + unsigned int numOriginalChildrenLeft = m_childDegree; + auto d0 = m_childDegree; + do { + InfoNode* n = nodeIt.current(); + ++nodeIt; + middleNode->addChild(n); + } while (--numOriginalChildrenLeft != 0); + + releaseChildren(); + addChild(middleNode); + auto d1 = middleNode->replaceChildrenWithGrandChildren(); + if (d1 != d0) + throw std::logic_error("replaceChildrenWithOneNode replaced different number of children as having before"); + return *middleNode; +} + +unsigned int InfoNode::replaceChildrenWithGrandChildren() noexcept +{ + if (firstChild == nullptr) + return 0; + InfoNode::child_iterator nodeIt = begin_child(); + unsigned int numOriginalChildrenLeft = m_childDegree; + unsigned int numChildrenReplaced = 0; + do { + InfoNode* n = nodeIt.current(); + ++nodeIt; + numChildrenReplaced += n->replaceWithChildren(); + } while (--numOriginalChildrenLeft != 0); + return numChildrenReplaced; +} + +unsigned int InfoNode::replaceWithChildren() noexcept +{ + if (isLeaf() || isRoot()) + return 0; + + // Re-parent children + unsigned int deltaChildDegree = 0; + InfoNode* child = firstChild; + do { + child->parent = parent; + child = child->next; + ++deltaChildDegree; + } while (child != nullptr); + parent->m_childDegree += deltaChildDegree - 1; // -1 as this node is deleted + + firstChild->previous = previous; + lastChild->next = next; + + if (parent->firstChild == this) { + parent->firstChild = firstChild; + } else { + previous->next = firstChild; + } + + if (parent->lastChild == this) { + parent->lastChild = lastChild; + } else { + next->previous = lastChild; + } + + // Release connected nodes before delete, otherwise children are deleted and neighbours are reconnected. + firstChild = nullptr; + lastChild = nullptr; + next = nullptr; + previous = nullptr; + parent = nullptr; + delete this; + return 1; +} + +void InfoNode::replaceChildrenWithGrandChildrenDebug() noexcept +{ + if (firstChild == nullptr) + return; + InfoNode::child_iterator nodeIt = begin_child(); + unsigned int numOriginalChildrenLeft = m_childDegree; + do { + InfoNode* n = nodeIt.current(); + ++nodeIt; + n->replaceWithChildrenDebug(); + } while (--numOriginalChildrenLeft != 0); +} + +void InfoNode::replaceWithChildrenDebug() noexcept +{ + if (isLeaf() || isRoot()) + return; + + // Re-parent children + unsigned int deltaChildDegree = 0; + InfoNode* child = firstChild; + do { + child->parent = parent; + child = child->next; + ++deltaChildDegree; + } while (child != nullptr); + parent->m_childDegree += deltaChildDegree - 1; // -1 as this node is deleted + + if (parent->firstChild == this) { + parent->firstChild = firstChild; + } else { + previous->next = firstChild; + firstChild->previous = previous; + } + + if (parent->lastChild == this) { + parent->lastChild = lastChild; + } else { + next->previous = lastChild; + lastChild->next = next; + } + + // Release connected nodes before delete, otherwise children are deleted and neighbours are reconnected. + firstChild = nullptr; + lastChild = nullptr; + next = nullptr; + previous = nullptr; + parent = nullptr; + + delete this; +} + +void InfoNode::remove(bool removeChildren) noexcept +{ + firstChild = removeChildren ? nullptr : firstChild; + delete this; +} + +void InfoNode::deleteChildren() noexcept +{ + if (firstChild == nullptr) + return; + + child_iterator nodeIt = begin_child(); + do { + InfoNode* n = nodeIt.current(); + ++nodeIt; + delete n; + } while (nodeIt.current() != nullptr); + + firstChild = nullptr; + lastChild = nullptr; + m_childDegree = 0; +} + +void InfoNode::calcChildDegree() noexcept +{ + m_childrenChanged = false; + if (firstChild == nullptr) + m_childDegree = 0; + else if (firstChild == lastChild) + m_childDegree = 1; + else { + m_childDegree = 0; + for (auto& child : children()) { + (void)child; + ++m_childDegree; + } + } +} + +void InfoNode::setChildDegree(unsigned int value) noexcept +{ + m_childDegree = value; + m_childrenChanged = false; +} + +void InfoNode::initClean() noexcept +{ + releaseChildren(); + previous = next = parent = nullptr; + + physicalNodes.clear(); +} + +void InfoNode::sortChildrenOnFlow(bool recurse) noexcept +{ + if (childDegree() == 0) + return; + std::vector nodes(childDegree()); + double lastFlow = 1.0; + bool isSorted = true; + unsigned int i = 0; + for (InfoNode& child : children()) { + if (child.data.flow > lastFlow) { + isSorted = false; + } + nodes[i] = &child; + lastFlow = child.data.flow; + ++i; + } + if (!isSorted) { + std::sort(nodes.begin(), nodes.end(), [](const InfoNode* a, const InfoNode* b) { + return b->data.flow < a->data.flow; + }); + releaseChildren(); + for (auto node : nodes) { + addChild(node); + } + } + if (recurse) { + for (InfoNode& child : children()) { + auto newRoot = child.getInfomapRoot(); + InfoNode& node = newRoot ? *newRoot : child; + node.sortChildrenOnFlow(recurse); + } + } +} + +unsigned int InfoNode::collapseChildren() noexcept +{ + std::swap(collapsedFirstChild, firstChild); + std::swap(collapsedLastChild, lastChild); + unsigned int numCollapsedChildren = childDegree(); + releaseChildren(); + return numCollapsedChildren; +} + +unsigned int InfoNode::expandChildren() +{ + bool haveCollapsedChildren = collapsedFirstChild != nullptr; + if (haveCollapsedChildren) { + if (firstChild != nullptr || lastChild != nullptr) + throw std::logic_error("Expand collapsed children called on a node that already has children."); + std::swap(collapsedFirstChild, firstChild); + std::swap(collapsedLastChild, lastChild); + calcChildDegree(); + return childDegree(); + } + return 0; +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfoNode.h b/src/vendor/cigraph/vendor/infomap/src/core/InfoNode.h new file mode 100644 index 00000000000..5d2c5e85341 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfoNode.h @@ -0,0 +1,374 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFONODE_H_ +#define INFONODE_H_ + +#include "FlowData.h" +#include "InfoEdge.h" +#include "iterators/infomapIterators.h" +#include "iterators/IterWrapper.h" +#include "../utils/MetaCollection.h" + +#include +#include +#include +#include +#include + +namespace infomap { + +class InfomapBase; + +class InfoNode { +public: + using child_iterator = ChildIterator; + using const_child_iterator = ChildIterator; + using infomap_child_iterator = InfomapChildIterator; + using const_infomap_child_iterator = InfomapChildIterator; + + using tree_iterator = TreeIterator; + using const_tree_iterator = TreeIterator; + + using leaf_node_iterator = LeafNodeIterator; + using const_leaf_node_iterator = LeafNodeIterator; + using leaf_module_iterator = LeafModuleIterator; + using const_leaf_module_iterator = LeafModuleIterator; + + using post_depth_first_iterator = DepthFirstIterator; + using const_post_depth_first_iterator = DepthFirstIterator; + + using edge_iterator = std::vector::iterator; + using const_edge_iterator = std::vector::const_iterator; + + using edge_iterator_wrapper = IterWrapper; + using const_edge_iterator_wrapper = IterWrapper; + + using infomap_iterator_wrapper = IterWrapper; + using const_infomap_iterator_wrapper = IterWrapper; + + using child_iterator_wrapper = IterWrapper; + using const_child_iterator_wrapper = IterWrapper; + + using infomap_child_iterator_wrapper = IterWrapper; + using const_infomap_child_iterator_wrapper = IterWrapper; + +public: + FlowData data; + unsigned int index = 0; // Temporary index used in finding best module + unsigned int stateId = 0; // Unique state node id for the leaf nodes + unsigned int physicalId = 0; // Physical id equals stateId for first order networks, otherwise can be non-unique + unsigned int layerId = 0; // Layer id for multilayer networks + std::vector metaData; // Categorical value for each meta data dimension + + InfoNode* owner = nullptr; // Infomap owner (if this is an Infomap root) + InfoNode* parent = nullptr; + InfoNode* previous = nullptr; // sibling + InfoNode* next = nullptr; // sibling + InfoNode* firstChild = nullptr; + InfoNode* lastChild = nullptr; + InfoNode* collapsedFirstChild = nullptr; + InfoNode* collapsedLastChild = nullptr; + double codelength = 0.0; // TODO: Better design for hierarchical stuff!? + bool dirty = false; + + std::vector physicalNodes; + MetaCollection metaCollection; // For modules + std::vector stateNodes; // For physically aggregated nodes + +private: + unsigned int m_childDegree = 0; + bool m_childrenChanged = false; + unsigned int m_numLeafMembers = 0; + + std::vector m_outEdges; + std::vector m_inEdges; + + InfomapBase* m_infomap = nullptr; + +public: + InfoNode(const FlowData& flowData) + : data(flowData) {}; + + // For first order nodes, physicalId equals stateId + InfoNode(const FlowData& flowData, unsigned int stateId) + : data(flowData), stateId(stateId), physicalId(stateId) {}; + + InfoNode(const FlowData& flowData, unsigned int stateId, unsigned int physicalId) + : data(flowData), stateId(stateId), physicalId(physicalId) {}; + + InfoNode(const FlowData& flowData, unsigned int stateId, unsigned int physicalId, unsigned int layerId) + : data(flowData), stateId(stateId), physicalId(physicalId), layerId(layerId) {}; + + InfoNode() = default; + + InfoNode(const InfoNode& other) + : data(other.data), + index(other.index), + stateId(other.stateId), + physicalId(other.physicalId), + layerId(other.layerId), + metaData(other.metaData), + parent(other.parent), + previous(other.previous), + next(other.next), + firstChild(other.firstChild), + lastChild(other.lastChild), + collapsedFirstChild(other.collapsedFirstChild), + collapsedLastChild(other.collapsedLastChild), + codelength(other.codelength), + dirty(other.dirty), + metaCollection(other.metaCollection), + m_childDegree(other.m_childDegree), + m_childrenChanged(other.m_childrenChanged), + m_numLeafMembers(other.m_numLeafMembers) { } + + ~InfoNode() noexcept; + + InfoNode& operator=(const InfoNode& other) + { + data = other.data; + index = other.index; + stateId = other.stateId; + physicalId = other.physicalId; + layerId = other.layerId; + metaData = other.metaData; + parent = other.parent; + previous = other.previous; + next = other.next; + firstChild = other.firstChild; + lastChild = other.lastChild; + collapsedFirstChild = other.collapsedFirstChild; + collapsedLastChild = other.collapsedLastChild; + codelength = other.codelength; + dirty = other.dirty; + metaCollection = other.metaCollection; + m_childDegree = other.m_childDegree; + m_childrenChanged = other.m_childrenChanged; + m_numLeafMembers = other.m_numLeafMembers; + return *this; + } + + // ---------------------------- Getters ---------------------------- + + unsigned int getMetaData(unsigned int dimension = 0) noexcept + { + if (dimension >= metaData.size()) { + return 0; + } + auto meta = metaData[dimension]; + return meta < 0 ? 0 : static_cast(meta); + } + + // ---------------------------- Infomap ---------------------------- + InfomapBase& getInfomap(); + + const InfomapBase& getInfomap() const; + + InfomapBase& setInfomap(InfomapBase*); + + InfoNode* getInfomapRoot() noexcept; + + InfoNode const* getInfomapRoot() const noexcept; + + /** + * Dispose the Infomap instance if it exists + * @return true if an existing Infomap instance was deleted + */ + bool disposeInfomap() noexcept; + + /** + * Number of physical nodes in memory nodes + */ + unsigned int numPhysicalNodes() const noexcept { return physicalNodes.size(); } + + // ---------------------------- Tree iterators ---------------------------- + + // Default iteration on children + child_iterator begin() noexcept { return { this }; } + + child_iterator end() noexcept { return { nullptr }; } + + const_child_iterator begin() const noexcept { return { this }; } + + const_child_iterator end() const noexcept { return { nullptr }; } + + child_iterator begin_child() noexcept { return { this }; } + + child_iterator end_child() noexcept { return { nullptr }; } + + const_child_iterator begin_child() const noexcept { return { this }; } + + const_child_iterator end_child() const noexcept { return { nullptr }; } + + child_iterator_wrapper children() noexcept { return { { this }, { nullptr } }; } + + const_child_iterator_wrapper children() const noexcept { return { { this }, { nullptr } }; } + + infomap_child_iterator_wrapper infomap_children() noexcept { return { { this }, { nullptr } }; } + + const_infomap_child_iterator_wrapper infomap_children() const noexcept { return { { this }, { nullptr } }; } + + post_depth_first_iterator begin_post_depth_first() noexcept { return { this }; } + + leaf_node_iterator begin_leaf_nodes() noexcept { return { this }; } + + leaf_module_iterator begin_leaf_modules() noexcept { return { this }; } + + tree_iterator begin_tree(unsigned int maxClusterLevel = std::numeric_limits::max()) noexcept { return { this, static_cast(maxClusterLevel) }; } + + tree_iterator end_tree() noexcept { return { nullptr }; } + + const_tree_iterator begin_tree(unsigned int maxClusterLevel = std::numeric_limits::max()) const noexcept { return { this, static_cast(maxClusterLevel) }; } + + const_tree_iterator end_tree() const noexcept { return { nullptr }; } + + infomap_iterator_wrapper infomapTree(unsigned int maxClusterLevel = std::numeric_limits::max()) noexcept { return { { this, static_cast(maxClusterLevel) }, { nullptr } }; } + + const_infomap_iterator_wrapper infomapTree(unsigned int maxClusterLevel = std::numeric_limits::max()) const noexcept { return { { this, static_cast(maxClusterLevel) }, { nullptr } }; } + + // ---------------------------- Graph iterators ---------------------------- + + edge_iterator begin_outEdge() noexcept { return m_outEdges.begin(); } + + edge_iterator end_outEdge() noexcept { return m_outEdges.end(); } + + edge_iterator begin_inEdge() noexcept { return m_inEdges.begin(); } + + edge_iterator end_inEdge() noexcept { return m_inEdges.end(); } + + edge_iterator_wrapper outEdges() noexcept { return { m_outEdges }; } + + edge_iterator_wrapper inEdges() noexcept { return { m_inEdges }; } + + // ---------------------------- Capacity ---------------------------- + + unsigned int childDegree() const noexcept { return m_childDegree; } + + bool isLeaf() const noexcept { return firstChild == nullptr; } + + // TODO: Safe to assume all children are leaves if first child is leaf? + bool isLeafModule() const noexcept { return m_infomap == nullptr && firstChild != nullptr && firstChild->firstChild == nullptr; } + + bool isRoot() const noexcept { return parent == nullptr; } + + unsigned int depth() const noexcept; + + unsigned int firstDepthBelow() const noexcept; + + unsigned int numLeafMembers() const noexcept { return m_numLeafMembers; } + + bool isDangling() const noexcept { return m_outEdges.empty(); } + + unsigned int outDegree() const noexcept { return m_outEdges.size(); } + + unsigned int inDegree() const noexcept { return m_inEdges.size(); } + + unsigned int degree() const noexcept { return outDegree() + inDegree(); } + + // ---------------------------- Order ---------------------------- + bool isFirst() const noexcept { return !parent || parent->firstChild == this; } + + bool isLast() const noexcept { return !parent || parent->lastChild == this; } + + unsigned int childIndex() const noexcept; + + // Generate 1-based tree path + std::vector calculatePath() const noexcept; + + unsigned int infomapChildDegree() const noexcept; + + unsigned int id() const noexcept { return stateId; } + + // ---------------------------- Operators ---------------------------- + + bool operator==(const InfoNode& rhs) const noexcept { return this == &rhs; } + + bool operator!=(const InfoNode& rhs) const noexcept { return this != &rhs; } + + friend std::ostream& operator<<(std::ostream& out, const InfoNode& node) noexcept + { + if (node.isLeaf()) + out << "[" << node.physicalId << "]"; + else + out << "[module]"; + return out; + } + + // ---------------------------- Mutators ---------------------------- + + /** + * Clear a cloned node to initial state + */ + void initClean() noexcept; + + void sortChildrenOnFlow(bool recurse = true) noexcept; + + /** + * Release the children and store the child pointers for later expansion + * @return the number of children collapsed + */ + unsigned int collapseChildren() noexcept; + + /** + * Expand collapsed children + * @return the number of collapsed children expanded + */ + unsigned int expandChildren(); + + // ------ OLD ----- + + // After change, set the child degree if known instead of lazily computing it by traversing the linked list + void setChildDegree(unsigned int value) noexcept; + + void setNumLeafNodes(unsigned int value) noexcept { m_numLeafMembers = value; } + + void addChild(InfoNode* child) noexcept; + + void releaseChildren() noexcept; + + /** + * If not already having a single child, replace children + * with a single new node, assuming grandchildren. + * @return the single child + */ + InfoNode& replaceChildrenWithOneNode(); + + /** + * @return 1 if the node is removed, otherwise 0 + */ + unsigned int replaceWithChildren() noexcept; + + void replaceWithChildrenDebug() noexcept; + + /** + * @return The number of children removed + */ + unsigned int replaceChildrenWithGrandChildren() noexcept; + + void replaceChildrenWithGrandChildrenDebug() noexcept; + + void remove(bool removeChildren) noexcept; + + void deleteChildren() noexcept; + + void addOutEdge(InfoNode& target, double weight, double flow = 0.0) noexcept + { + auto* edge = new InfoEdge(*this, target, weight, flow); + m_outEdges.push_back(edge); + target.m_inEdges.push_back(edge); + } + +private: + void calcChildDegree() noexcept; +}; + +} // namespace infomap + +#endif // INFONODE_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.cpp b/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.cpp new file mode 100644 index 00000000000..1eada521b38 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.cpp @@ -0,0 +1,2182 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "InfomapBase.h" +#include "InfomapConfig.h" +#include "InfoNode.h" +#include "FlowData.h" +#include "BiasedMapEquation.h" +#include "MemMapEquation.h" +#include "MetaMapEquation.h" +#include "InfomapOptimizer.h" +#include "../io/SafeFile.h" +#include "../utils/FileURI.h" +#include "../utils/FlowCalculator.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _OPENMP +#include +#endif + +namespace infomap { + +std::map> InfomapBase::getMultilevelModules(bool states) +{ + if (haveMemory() && !states) { + throw std::runtime_error("Cannot get multilevel modules on higher-order network without states."); + } + unsigned int maxDepth = maxTreeDepth(); + unsigned int numModuleLevels = maxDepth - 1; + std::map> modules; + if (maxDepth < 2) return modules; + for (unsigned int level = 1; level <= numModuleLevels; ++level) { + for (auto it(iterLeafNodes(static_cast(level))); !it.isEnd(); ++it) { + auto& node = *it; + auto nodeId = states ? node.stateId : node.physicalId; + modules[nodeId].push_back(it.moduleId()); + } + } + return modules; +} + +// =================================================== +// IO +// =================================================== + +std::ostream& operator<<(std::ostream& out, const InfomapBase& infomap) +{ + return infomap.toString(out); +} + +// =================================================== +// Getters +// =================================================== + +unsigned int InfomapBase::numLevels() const +{ + // TODO: Make sure this is not called unless tree is guaranteed to have even depth! + unsigned int depth = 0; + InfoNode* n = m_root.firstChild; + while (n != nullptr) { + ++depth; + n = n->firstChild; + } + return depth; +} + +unsigned int InfomapBase::maxTreeDepth() const +{ + unsigned int maxDepth = 0; + for (auto it = root().begin_tree(); !it.isEnd(); ++it) { + const InfoNode& node = *it; + if (node.isLeaf()) { + if (it.depth() > maxDepth) { + maxDepth = it.depth(); + } + } + } + return maxDepth; +} + +// =================================================== +// Run +// =================================================== + +void InfomapBase::run(const std::string& parameters) +{ + if (!isMainInfomap()) { + runPartition(); + return; + } + + m_elapsedTime = Stopwatch(true); + m_startDate = Date(); + + std::string currentParameters = io::Str() << m_initialParameters << (parameters.empty() ? "" : " ") << parameters; + if (currentParameters != m_currentParameters) { + m_currentParameters = currentParameters; + setConfig(Config(m_currentParameters, isCLI)); + m_network.setConfig(*this); + } + + Log::init(verbosity, silent, verboseNumberPrecision); + + Log() << "=======================================================\n"; + Log() << " Infomap v" << INFOMAP_VERSION << " starts at " << m_startDate << "\n"; + Log() << " -> Input network: " << networkFile << "\n"; + if (noFileOutput) + Log() << " -> No file output!\n"; + else + Log() << " -> Output path: " << outDirectory << "\n"; + if (!parsedOptions.empty()) { + for (unsigned int i = 0; i < parsedOptions.size(); ++i) + Log() << (i == 0 ? " -> Configuration: " : " ") << parsedOptions[i] << "\n"; + } + if (!m_initialPartition.empty()) { + Log() << " -> " << m_initialPartition.size() << " initial module ids provided\n"; + } + Log() << "=======================================================\n"; +#ifdef _OPENMP +#pragma omp parallel +#pragma omp master + { + Log() << " OpenMP " << _OPENMP << " detected with " << omp_get_num_threads() << " threads...\n"; + } +#endif + + m_network.postProcessInputData(); + if (m_network.numNodes() == 0) { + m_network.readInputData(networkFile); + } + + if (!metaDataFile.empty()) { + initMetaData(metaDataFile); + } + + run(m_network); + + Log() << "===================================================\n"; + Log() << " Infomap ends at " << m_endDate << "\n"; + Log() << " (Elapsed time: " << m_elapsedTime << ")\n"; + Log() << "===================================================\n"; +} + +void InfomapBase::run(Network& network) +{ + if (!isMainInfomap()) + throw std::logic_error("Can't run a non-main Infomap with an input network"); + + if (network.numNodes() == 0) { + network.postProcessInputData(); + if (network.numNodes() == 0) { + throw std::domain_error("Network is empty"); + } + } + + if (printStateNetwork) { + std::string filename = outDirectory + outName + "_states.net"; + Log() << "Writing state network to '" << filename << "'... "; + network.writeStateNetwork(filename); + Log() << "done!\n"; + } + + if (printPajekNetwork) { + std::string filename; + if (printStates()) { + filename = outDirectory + outName + "_states_as_physical.net"; + Log() << "Writing state network as first order Pajek network to '" << filename << "'... "; + } else { + // Non-memory input + filename = outDirectory + outName + ".net"; + Log() << "Writing Pajek network to '" << filename << "'... "; + } + network.writePajekNetwork(filename); + Log() << "done!\n"; + } + + if (network.haveMemoryInput()) { + Log() << " -> Found higher order network input, using the Map Equation for higher order network flows\n"; + setStateInput(); + setStateOutput(); + + if (network.isMultilayerNetwork() && !isMultilayerNetwork()) { + setMultilayerInput(); + } + } else { + if (haveMemory() || network.higherOrderInputMethodCalled()) { + Log() << " -> Warning: Higher order network specified but no higher order input found.\n"; + // Use state output anyway for consistency even in the special case when input is first order + setStateOutput(); + } + Log() << " -> Ordinary network input, using the Map Equation for first order network flows\n"; + } + + if (network.haveDirectedInput() && isUndirectedFlow()) { + Log() << " -> Notice: Directed input found, changing flow model from '" << flowModel << "' to '" << FlowModel(FlowModel::directed) << "'\n"; + flowModel = FlowModel::directed; + } + network.setConfig(*this); + + calculateFlow(network, *this); + + if (network.isBipartite()) { + bipartite = true; + } + + initNetwork(network); + + if (numLeafNodes() == 0) + throw std::domain_error("No nodes to partition"); + + if (printFlowNetwork) { + std::string filename; + if (printStates()) { + filename = outDirectory + outName + "_states_as_physical_flow.net"; + Log() << "Writing flow state network as first order Pajek network to '" << filename << "'... "; + } else { + // Non-memory input + filename = outDirectory + outName + "_flow.net"; + Log() << "Writing flow network to '" << filename << "'... "; + } + network.writePajekNetwork(filename, true); + Log() << "done!\n"; + } + + // If used as a library, we may want to reuse the network instance, else clear to use less memory + // TODO: May have to use some meta data for output? + if (isCLI) { + network.clearLinks(); + } + + if (haveMemory()) + Log(2) << "Run Infomap with memory...\n"; + else + Log(2) << "Run Infomap...\n"; + + std::ostringstream bestSolutionStatistics; + unsigned int bestNumLevels = 0; + double bestHierarchicalCodelength = std::numeric_limits::max(); + m_codelengths.clear(); + NodePaths bestTree(numLeafNodes()); + unsigned int bestTrialIndex = 0; + + unsigned int numTrials = this->numTrials; + + for (unsigned int i = 0; i < numTrials; ++i) { + removeModules(); + auto startDate = Date(); + Stopwatch timer(true); + + if (isMainInfomap()) { + Log() << "\n"; + Log() << "================================================\n"; + Log() << "Trial " << (i + 1) << "/" << numTrials << " starting at " << startDate << "\n"; + Log() << "================================================\n"; + + if (!clusterDataFile.empty()) + initPartition(clusterDataFile, clusterDataIsHard, &network); + else if (!m_initialPartition.empty()) + initPartition(m_initialPartition, clusterDataIsHard); + } + + if (!noInfomap) + runPartition(); + else + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); + + if (haveHardPartition()) + restoreHardPartition(); + + if (isMainInfomap()) { + Log() << "\n=> Trial " << (i + 1) << "/" << numTrials << " finished in " << timer.getElapsedTimeInSec() << "s with codelength " << m_hierarchicalCodelength << "\n"; + m_codelengths.push_back(m_hierarchicalCodelength); + + if (printAllTrials && numTrials > 1) { + writeResult(static_cast(i + 1)); + } + + if (m_hierarchicalCodelength < bestHierarchicalCodelength - 1e-10) { + bestSolutionStatistics.clear(); + bestSolutionStatistics.str(""); + bestNumLevels = printPerLevelCodelength(root(), bestSolutionStatistics); + bestHierarchicalCodelength = m_hierarchicalCodelength; + bestTrialIndex = i; + root().sortChildrenOnFlow(); + writeResult(); + if (numTrials > 1) { + bestTree.clear(); + for (auto it(iterLeafNodes()); !it.isEnd(); ++it) { + bestTree.emplace_back(it->stateId, it.path()); + } + } + } + } + } + if (isMainInfomap()) { + m_elapsedTime.stop(); + m_endDate = Date(); + Log() << "\n\n"; + Log() << "================================================\n"; + Log() << "Summary after " << numTrials << (numTrials > 1 ? " trials\n" : " trial\n"); + Log() << "================================================\n"; + if (numTrials > 1) { + if (bestTrialIndex < numTrials - 1) { + // Restore Infomap tree to best solution + initTree(bestTree); + writeResult(); // Overwrite result to get total elapsed time in output file header + } + + Log() << std::fixed << std::setprecision(9); + double averageCodelength = 0.0; + double minCodelength = m_codelengths[0]; + double maxCodelength = m_codelengths[0]; + Log() << "Codelengths: ["; + for (auto codelength : m_codelengths) { + Log() << codelength << ", "; + averageCodelength += codelength; + minCodelength = std::min(minCodelength, codelength); + maxCodelength = std::max(maxCodelength, codelength); + } + averageCodelength /= numTrials; + Log() << "\b\b]\n"; + Log() << "[min, average, max] codelength: [" << minCodelength << ", " << averageCodelength << ", " << maxCodelength << "]\n\n"; + } + + Log() << "Best end modular solution in " << bestNumLevels << " levels"; + if (bestHierarchicalCodelength > m_oneLevelCodelength) + Log() << " (warning: worse than one-level solution)"; + Log() << ":\n"; + Log() << bestSolutionStatistics.str() << '\n'; + } +} + +// =================================================== +// Run: Init: * +// =================================================== + +InfomapBase& InfomapBase::initMetaData(const std::string& metaDataFile) +{ + m_network.readMetaData(metaDataFile); + return *this; +} + +InfomapBase& InfomapBase::initNetwork(Network& network) +{ + if (network.numNodes() == 0) + throw std::domain_error("No nodes in network"); + if (m_root.childDegree() > 0) { + m_root.deleteChildren(); + m_leafNodes.clear(); + } + generateSubNetwork(network); + + initOptimizer(); + + init(); + return *this; +} + +InfomapBase& InfomapBase::initNetwork(InfoNode& parent, bool asSuperNetwork) +{ + generateSubNetwork(parent); + + if (asSuperNetwork) + transformNodeFlowToEnterFlow(m_root); + + init(); + return *this; +} + +InfomapBase& InfomapBase::initPartition(const std::string& clusterDataFile, bool hard, const Network* network) +{ + FileURI file(clusterDataFile); + ClusterMap clusterMap; + if (this->isMultilayerNetwork() && network != nullptr) { + auto map = network->layerNodeToStateId(); + clusterMap.readClusterData(clusterDataFile, false, &map); + } else { + clusterMap.readClusterData(clusterDataFile); + } + + Log() << "Init partition from file '" << clusterDataFile << "'... "; + + const auto& ext = clusterMap.extension(); + + if (ext == "tree" || ext == "ftree") { + initTree(clusterMap.nodePaths()); + } else if (ext == "clu") { + initPartition(clusterMap.clusterIds(), hard); + } + + Log() << "done! Generated " << numLevels() << " levels with codelength " << getIndexCodelength() << " + " << (m_hierarchicalCodelength - getIndexCodelength()) << " = " << io::toPrecision(m_hierarchicalCodelength) << '\n'; + + return *this; +} + +InfomapBase& InfomapBase::initTree(const NodePaths& tree) +{ + Log(4) << "Init tree... " << std::setprecision(9); + auto maxDepth = 2; + std::map nodeIdToIndex; + auto leafIndex = 0; + for (auto& leafNode : m_leafNodes) { + // Also detach leaf nodes to delete all modules, safe to call multiple times + leafNode->parent->releaseChildren(); + // Set parent to nullptr to be able to collect any orphaned nodes in the end + leafNode->parent = nullptr; + nodeIdToIndex[leafNode->stateId] = leafIndex; + ++leafIndex; + } + m_root.deleteChildren(); + + auto numNodesFound = 0; + auto numNodesNotInNetwork = 0; + for (const auto& nodePath : tree) { + ++numNodesFound; + InfoNode* node = &root(); + auto depth = 0; + const auto& path = nodePath.second; + const auto nodeId = nodePath.first; + InfoNode* leafNode = nullptr; + + try { + auto nodeIndex = nodeIdToIndex.at(nodeId); + leafNode = m_leafNodes[nodeIndex]; + } catch (std::exception& e) { + ++numNodesNotInNetwork; + continue; + } + + for (size_t i = 0; i < path.size(); ++i) { + auto childNumber = path[i]; // 1-based indexing + + // Create new node if path doesn't exist + // TODO: Check correct tree indexing? + if (node->childDegree() < childNumber) { + InfoNode* child = leafNode; + if (i + 1 < path.size()) { + child = new InfoNode(); + } + node->addChild(child); + } + + node = node->lastChild; + ++depth; + } + maxDepth = std::max(maxDepth, depth); + } + + if (numNodesNotInNetwork > 0) { + Log(1) << "\n -> " << numNodesNotInNetwork << "/" << numNodesFound << " nodes in tree not found in network."; + } + + auto numNodesAddedToNeighbouringModules = 0; + auto numNodesWithoutClusterInfo = 0; + + // Set orphaned nodes to their own or neighbouring module + for (auto& leafNode : m_leafNodes) { + if (leafNode->parent != nullptr) { + continue; + } + + ++numNodesWithoutClusterInfo; + if (assignToNeighbouringModule) { + // Take first neighbour that has a module assigned + for (auto& edge : leafNode->outEdges()) { + if (edge->target->parent != nullptr) { + edge->target->parent->addChild(leafNode); + ++numNodesAddedToNeighbouringModules; + break; + } + } + // Check incoming links if still orphan + if (leafNode->parent == nullptr) { + for (auto& edge : leafNode->inEdges()) { + if (edge->source->parent != nullptr) { + edge->source->parent->addChild(leafNode); + ++numNodesAddedToNeighbouringModules; + break; + } + } + } + // Set to own module if no neighbour module available + if (leafNode->parent == nullptr) { + auto module = new InfoNode(); + root().addChild(module); + module->addChild(leafNode); + } + } else { + // Set to own module if no neighbour module available + auto module = new InfoNode(); + root().addChild(module); + module->addChild(leafNode); + } + } + if (numNodesWithoutClusterInfo > 0) { + if (assignToNeighbouringModule) { + Log() << "\n -> " << numNodesWithoutClusterInfo << " nodes not found in tree, " << numNodesAddedToNeighbouringModules << " are put into neighbouring modules and " << (numNodesWithoutClusterInfo - numNodesAddedToNeighbouringModules) << " in separate."; + } else { + Log() << "\n -> " << numNodesWithoutClusterInfo << " nodes not found in tree are put into separate modules."; + } + } + + aggregateFlowValuesFromLeafToRoot(); + initTree(); + initNetwork(); + m_numNonTrivialTopModules = calculateNumNonTrivialTopModules(); + // Init partition to calculate indexCodelength and moduleCodelength + if (haveModules()) + setActiveNetworkFromChildrenOfRoot(); + else + setActiveNetworkFromLeafs(); + initPartition(); + + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); + Log() << "\n -> Initiated to codelength " << m_hierarchicalCodelength << " in " << maxDepth << " levels with " << numTopModules() << " top modules.\n"; + Log() << std::setprecision(6); + return *this; +} + +/** + * clusterIds is a map from nodeId -> clusterId + */ +InfomapBase& InfomapBase::initPartition(const std::map& clusterIds, bool hard) +{ + // Generate map from node id to index in leaf node vector + std::map nodeIdToIndex; + unsigned int leafIndex = 0; + for (auto& nodePtr : m_leafNodes) { + auto& leafNode = *nodePtr; + nodeIdToIndex[leafNode.stateId] = leafIndex; + ++leafIndex; + } + + // Remap clusterIds to vector from leaf node index to module index instead of nodeId -> clusterId + std::map> clusterIdToNodeIds; + for (auto it : clusterIds) { + clusterIdToNodeIds[it.second].insert(it.first); + } + unsigned int numNodes = numLeafNodes(); + std::vector modules(numNodes); + std::vector selectedNodes(numNodes, 0); + unsigned int moduleIndex = 0; + for (const auto& it : clusterIdToNodeIds) { + auto& nodes = it.second; + for (auto& nodeId : nodes) { + auto nodeIndex = nodeIdToIndex[nodeId]; + modules[nodeIndex] = moduleIndex; + ++selectedNodes[nodeIndex]; + } + ++moduleIndex; + } + + unsigned int numNodesWithoutClusterInfo = 0; + for (auto& count : selectedNodes) { + if (count == 0) { + ++numNodesWithoutClusterInfo; + } + } + + if (numNodesWithoutClusterInfo == 0) { + return initPartition(modules, hard); + } + + if (assignToNeighbouringModule) { + Log() << "\n -> " << numNodesWithoutClusterInfo << " nodes not found in cluster file are put into neighbouring modules if possible. "; + for (unsigned int i = 0; i < numNodes; ++i) { + if (selectedNodes[i] == 0) { + // Check out edges greedily for connected modules + auto& node = *m_leafNodes[i]; + for (auto& e : node.outEdges()) { + auto& edge = *e; + auto targetNodeIndex = nodeIdToIndex[edge.target->stateId]; + if (selectedNodes[targetNodeIndex] != 0) { + selectedNodes[i] = 1; + modules[i] = modules[targetNodeIndex]; + break; + } + } + if (selectedNodes[i] == 0) { + // Check in edges greedily for connected modules + for (auto& e : node.inEdges()) { + auto& edge = *e; + auto sourceNodeIndex = nodeIdToIndex[edge.source->stateId]; + if (selectedNodes[sourceNodeIndex] != 0) { + selectedNodes[i] = 1; + modules[i] = modules[sourceNodeIndex]; + break; + } + } + } + if (selectedNodes[i] == 0) { + // No connected node with a module index, fall back to create new module + selectedNodes[i] = 1; + modules[i] = moduleIndex; + ++moduleIndex; + } + } + } + } else { + Log() << "\n -> " << numNodesWithoutClusterInfo << " nodes not found in cluster file are put into separate modules. "; + // Put non-selected nodes in its own module + for (unsigned int i = 0; i < numNodes; ++i) { + if (selectedNodes[i] == 0) { + modules[i] = moduleIndex; + ++moduleIndex; + } + } + } + + return initPartition(modules); +} + +InfomapBase& InfomapBase::initPartition(std::vector>& clusters, bool hard) +{ + Log(3) << "\n -> Init " << (hard ? "hard" : "soft") << " partition... " << std::flush; + unsigned int numNodes = numLeafNodes(); + // Get module indices from the merge structure + std::vector modules(numNodes); + std::vector selectedNodes(numNodes, 0); + unsigned int moduleIndex = 0; + + for (auto& cluster : clusters) { + if (cluster.empty()) + continue; + for (auto id : cluster) { + ++selectedNodes[id]; + modules[id] = moduleIndex; + } + ++moduleIndex; + } + + // Put non-selected nodes in its own module + unsigned int numNodesWithoutClusterInfo = 0; + for (unsigned int i = 0; i < numNodes; ++i) { + if (selectedNodes[i] == 0) { + modules[i] = moduleIndex; + ++moduleIndex; + ++numNodesWithoutClusterInfo; + } + } + if (numNodesWithoutClusterInfo > 0) + Log() << "\n -> " << numNodesWithoutClusterInfo << " nodes not found in cluster file are put into separate modules. "; + + return initPartition(modules, hard); +} + +InfomapBase& InfomapBase::initPartition(std::vector& modules, bool hard) +{ + removeModules(); + setActiveNetworkFromLeafs(); + initPartition(); // TODO: confusing same name, should be able to init default without arguments here too + moveActiveNodesToPredefinedModules(modules); + consolidateModules(false); + + if (hard) { + // Save the original network + m_originalLeafNodes.swap(m_leafNodes); + + // Use the pre-partitioned network as the new leaf network + unsigned int numNodesInNewNetwork = numTopModules(); + m_leafNodes.resize(numNodesInNewNetwork); + unsigned int nodeIndex = 0; + unsigned int numLinksInNewNetwork = 0; + for (InfoNode& node : m_root) { + m_leafNodes[nodeIndex] = &node; + // Collapse children + node.collapseChildren(); + numLinksInNewNetwork += node.outDegree(); + ++nodeIndex; + } + + Log(1) << "\n -> Hard-partitioned the network to " << numNodesInNewNetwork << " nodes and " << numLinksInNewNetwork << " links with codelength " << *this << '\n'; + } else { + Log(1) << "\n -> Initiated to codelength " << *this << " in " << numTopModules() << " top modules.\n"; + } + m_hierarchicalCodelength = getCodelength(); + + return *this; +} + +void InfomapBase::generateSubNetwork(Network& network) +{ + unsigned int numNodes = network.numNodes(); + auto& metaData = network.metaData(); + numMetaDataDimensions = network.numMetaDataColumns(); + + Log() << "Build internal network with " << numNodes << " nodes and " << network.numLinks() << " links...\n"; + if (!metaData.empty()) { + Log() << "and " << metaData.size() << " meta-data records in " << numMetaDataDimensions << " dimensions\n"; + } + + m_leafNodes.reserve(numNodes); + double sumNodeFlow = 0.0; + double sumTeleFlow = 0.0; + std::map nodeIndexMap; + for (auto& nodeIt : network.nodes()) { + auto& networkNode = nodeIt.second; + auto* node = new InfoNode(networkNode.flow, networkNode.id, networkNode.physicalId, networkNode.layerId); + node->data.teleportWeight = networkNode.weight; + node->data.teleportFlow = networkNode.teleFlow; + node->data.exitFlow = networkNode.exitFlow; + node->data.enterFlow = networkNode.enterFlow; + if (haveMetaData()) { + auto meta = metaData.find(networkNode.id); + if (meta != metaData.end()) { + node->metaData = meta->second; + } else { + node->metaData = std::vector(numMetaDataDimensions, -1); + } + } + sumNodeFlow += networkNode.flow; + sumTeleFlow += networkNode.teleFlow; + m_root.addChild(node); + nodeIndexMap[networkNode.id] = m_leafNodes.size(); + m_leafNodes.push_back(node); + } + m_root.data.flow = sumNodeFlow; + m_root.data.teleportFlow = sumTeleFlow; + // m_calculateEnterExitFlow = true; //TODO: Implement always in flow calculation + if (!this->regularized) { + m_calculateEnterExitFlow = true; + } + BiasedMapEquation::setNetworkProperties(network); + + if (std::abs(sumNodeFlow - 1.0) > 1e-10) + Log() << "Warning, total flow on nodes differs from 1.0 by " << sumNodeFlow - 1.0 << ".\n"; + + bool changeMarkovTime = std::abs(markovTime - 1) > 1e-3; + if (changeMarkovTime) { + Log() << " -> Rescale link flow with global Markov time " << markovTime << "\n"; + } + + for (auto& linkIt : network.nodeLinkMap()) { + unsigned int linkSourceId = linkIt.first.id; + unsigned int sourceIndex = nodeIndexMap[linkSourceId]; + const auto& subLinks = linkIt.second; + for (auto& subIt : subLinks) { + unsigned int linkTargetId = subIt.first.id; + unsigned int targetIndex = nodeIndexMap[linkTargetId]; + // Ignore self-links in optimization as it doesn't change enter/exit flow on modular level + if (sourceIndex != targetIndex) { + auto& linkData = subIt.second; + m_leafNodes[sourceIndex]->addOutEdge(*m_leafNodes[targetIndex], linkData.weight, linkData.flow * markovTime); + } + } + } + + if (variableMarkovTime) { + Log() << " -> Rescale link flow with variable Markov time\n"; + if (std::abs(variableMarkovTimeDamping - 1) > 1e-9) { + Log() << " -> Use variable Markov time strength " << variableMarkovTimeDamping << "\n"; + } + } + + double maxEntropy = 0.0; + double maxFlow = 0.0; + double entropyRate = 0.0; + unsigned int maxDegree = 0; + unsigned int maxOutDegree = 0; + unsigned int maxInDegree = 0; + double totDegree = network.sumDegree(); + std::vector entropies(numNodes, 0); + + for (unsigned i = 0; i < numNodes; ++i) { + InfoNode& node = *m_leafNodes[i]; + maxDegree = std::max(maxDegree, node.degree()); + maxOutDegree = std::max(maxOutDegree, node.outDegree()); + maxInDegree = std::max(maxInDegree, node.inDegree()); + double entropy = 0; + double sumOut = 0; + for (InfoEdge* e : node.outEdges()) { + entropy -= infomath::plogp(e->data.weight); + sumOut += e->data.weight; + } + if (isUndirectedFlow()) { + for (InfoEdge* e : node.inEdges()) { + entropy -= infomath::plogp(e->data.weight); + sumOut += e->data.weight; + } + } + entropy = sumOut > 1e-9 ? (entropy + infomath::plogp(sumOut)) / sumOut : 0; + maxEntropy = std::max(maxEntropy, entropy); + entropyRate += m_leafNodes[i]->data.flow * entropy; + maxFlow = std::max(maxFlow, node.data.flow); + entropies[i] = entropy; // Store for undirected networks + } + + m_entropyRate = entropyRate; + m_maxEntropy = maxEntropy; + m_maxFlow = maxFlow; + + double minLocalScale = variableMarkovTimeMinLocalScale; + double damping = variableMarkovTimeDamping; + + double maxScale = infomath::linlog(maxFlow * totDegree, damping); + + if (variableMarkovTime) { + if (damping < 0) { + maxScale = infomath::linlog(pow(2.0, maxEntropy), -damping); + } + for (unsigned i = 0; i < numNodes; ++i) { + InfoNode& node = *m_leafNodes[i]; + double localScale = damping < 0 ? infomath::linlog(pow(2.0, entropies[i]), -damping) : infomath::linlog(std::max(minLocalScale, node.data.flow * totDegree), damping); + for (InfoEdge* e : node.outEdges()) { + if (isUndirectedFlow()) { + double oppositeLocalScale = damping < 0 ? infomath::linlog(pow(2.0, entropies[nodeIndexMap[e->target->stateId]]), -damping) : infomath::linlog(std::max(minLocalScale, e->target->data.flow * totDegree), damping); + localScale = std::max(localScale, oppositeLocalScale); + } + double localMarkovTimeScale = maxScale / std::max(minLocalScale, localScale); + e->data.flow *= localMarkovTimeScale; + network.nodeLinkMap()[e->source->stateId][e->target->stateId].flow = e->data.flow; + } + } + } +} + +void InfomapBase::generateSubNetwork(InfoNode& parent) +{ + // Store parent module + m_root.owner = &parent; + m_root.data = parent.data; + + unsigned int numNodes = parent.childDegree(); + m_leafNodes.resize(numNodes); + + Log(1) << "Generate sub network with " << numNodes << " nodes...\n"; + + unsigned int childIndex = 0; + for (InfoNode& node : parent) { + auto* clonedNode = new InfoNode(node); + clonedNode->initClean(); + m_root.addChild(clonedNode); + node.index = childIndex; // Set index to its place in this subnetwork to be able to find edge target below + m_leafNodes[childIndex] = clonedNode; + ++childIndex; + } + + InfoNode* parentPtr = &parent; + // Clone edges + for (InfoNode& node : parent) { + for (InfoEdge* e : node.outEdges()) { + InfoEdge& edge = *e; + // If neighbour node is within the same module, add the link to this subnetwork. + if (edge.target->parent == parentPtr) { + m_leafNodes[edge.source->index]->addOutEdge(*m_leafNodes[edge.target->index], edge.data.weight, edge.data.flow); + } + } + } +} + +void InfomapBase::init() +{ + Log(3) << "InfomapBase::init()...\n"; + + if (m_calculateEnterExitFlow && isMainInfomap()) + initEnterExitFlow(); + + initNetwork(); + + m_oneLevelCodelength = calcCodelength(m_root); + Log() << " -> One-level codelength: " << m_oneLevelCodelength << '\n'; +} + +// =================================================== +// Run: * +// =================================================== + +void InfomapBase::hierarchicalPartition() +{ + Log(1) << "Hierarchical partition...\n"; + + const auto depth = maxTreeDepth(); + if (depth > 2) { + Log(1) << "Continuing from a tree with " << depth << " levels...\n"; + + if (fastHierarchicalSolution == 0) { + Log(1) << "Removing sub modules...\n"; + removeSubModules(true); + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); + } + + else if (fastHierarchicalSolution == 1) { + Log(1) << "Fine-tune bottom modules... "; + bool isSilent = isMainInfomap() && Log::isSilent(); + + double codelengthBefore = 0.0; + double codelengthAfter = 0.0; + + for (InfoNode& module : m_root.infomapTree()) { + if (!module.isLeaf() && module.firstChild->isLeafModule()) { + codelengthBefore += module.codelength; + auto numLeafs = 0; + for (auto& leafModule : module) { + numLeafs += leafModule.childDegree(); + } + + std::vector modules(numLeafs); + std::vector leafs(numLeafs); + + auto i = 0; + for (auto it = module.begin_tree(); !it.isEnd(); ++it) { + if (it->isLeaf()) { + modules[i] = it.moduleIndex(); + leafs[i] = it.current(); + ++i; + } + } + + module.replaceChildrenWithGrandChildren(); + + auto& subInfomap = getSubInfomap(module).initNetwork(module); + + subInfomap.initPartition(modules); + + // Run two-level partition + find hierarchically super modules (skip recursion) + subInfomap.setOnlySuperModules(true).run(); + + // Collect sub Infomap modules + i = 0; + for (auto& subLeafPtr : subInfomap.leafNodes()) { + modules[i] = subLeafPtr->index; + ++i; + } + + // Create new sub modules + std::vector subModules(numLeafs, nullptr); + module.releaseChildren(); + + for (auto j = 0; j < numLeafs; ++j) { + InfoNode* leaf = leafs[j]; + unsigned int moduleIndex = modules[j]; + if (subModules[moduleIndex] == nullptr) { + subModules[moduleIndex] = new InfoNode(subInfomap.leafNodes()[j]->parent->data); + subModules[moduleIndex]->index = moduleIndex; + module.addChild(subModules[moduleIndex]); + } + subModules[moduleIndex]->addChild(leaf); + } + module.disposeInfomap(); + module.codelength = calcCodelength(module); + codelengthAfter += module.codelength; + } + } + + if (isMainInfomap()) + Log::setSilent(isSilent); + + const double diffCodelength = codelengthBefore - codelengthAfter; + Log() << "done! Codelength improvement " << (diffCodelength / codelengthBefore) * 100 << "% to codelength " << codelengthAfter << "\n"; + } + + recursivePartition(); + return; + } + + partition(); + + if (numTopModules() == 1 || numTopModules() == numLeafNodes()) { + Log(1) << "Trivial partition, skip search for hierarchical solution.\n"; + return; + } + + if (numTopModules() > preferredNumberOfModules) { + findHierarchicalSuperModules(); + } + + if (onlySuperModules) { + removeSubModules(true); + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); + return; + } + + if (fastHierarchicalSolution >= 2) { + // FIXME Calculate individual module codelengths and store on the modules? + return; + } + + if (fastHierarchicalSolution == 0) { + removeSubModules(true); + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); + } + + recursivePartition(); +} + +void InfomapBase::partition() +{ + auto oldPrecision = Log::precision(); + Log(0, 0) << "Two-level compression: " << std::setprecision(2) << std::flush; + Log(1) << "Trying to find modular structure... \n"; + double initialCodelength = m_oneLevelCodelength; + double oldCodelength = initialCodelength; + + m_tuneIterationIndex = 0; + findTopModulesRepeatedly(levelAggregationLimit); + + double newCodelength = getCodelength(); + double compression = oldCodelength < 1e-16 ? 0.0 : (oldCodelength - newCodelength) / oldCodelength; + Log(0, 0) << (compression * 100) << "% " << std::flush; + oldCodelength = newCodelength; + + bool doFineTune = true; + bool coarseTuned = false; + while (numTopModules() > 1 && (m_tuneIterationIndex + 1) != tuneIterationLimit) { + ++m_tuneIterationIndex; + if (doFineTune) { + Log(3) << "\n"; + Log(1, 3) << "Fine tune... " << std::flush; + unsigned int numEffectiveLoops = fineTune(); + if (numEffectiveLoops > 0) { + Log(1, 3) << " -> done in " << numEffectiveLoops << " effective loops to codelength " << *this << " in " << numTopModules() << " modules.\n"; + // Continue to merge fine-tuned modules + findTopModulesRepeatedly(levelAggregationLimit); + } else { + Log(1, 3) << "no improvement.\n"; + } + } else { + coarseTuned = true; + if (!noCoarseTune) { + Log(3) << "\n"; + Log(1, 3) << "Coarse tune... " << std::flush; + unsigned int numEffectiveLoops = coarseTune(); + if (numEffectiveLoops > 0) { + Log(1, 3) << "done in " << numEffectiveLoops << " effective loops to codelength " << *this << " in " << numTopModules() << " modules.\n"; + // Continue to merge fine-tuned modules + findTopModulesRepeatedly(levelAggregationLimit); + } else { + Log(1, 3) << "no improvement.\n"; + } + } + } + newCodelength = getCodelength(); + compression = oldCodelength < 1e-16 ? 0.0 : (oldCodelength - newCodelength) / oldCodelength; + bool isImprovement = newCodelength <= oldCodelength - minimumCodelengthImprovement && newCodelength < oldCodelength - initialCodelength * minimumRelativeTuneIterationImprovement; + if (!isImprovement) { + // Make sure coarse-tuning have been tried + if (coarseTuned) + break; + } else { + oldCodelength = newCodelength; + } + Log(0, 0) << (compression * 100) << "% " << std::flush; + doFineTune = !doFineTune; + } + + Log(0, 0) << std::setprecision(oldPrecision) << '\n'; + Log() << "Partitioned to codelength " << *this << " in " << numTopModules(); + if (m_numNonTrivialTopModules != numTopModules()) + Log() << " (" << m_numNonTrivialTopModules << " non-trivial)"; + Log() << " modules.\n"; + + if (!preferModularSolution && preferredNumberOfModules == 0 && haveNonTrivialModules() && getCodelength() > getOneLevelCodelength()) { + Log() << "Worse codelength than one-level codelength, putting all nodes in one module... "; + + // Create new single module between modules and root + auto& module = root().replaceChildrenWithOneNode(); + module.data = m_root.data; + module.index = 0; + for (auto& node : module) { + node.index = 0; + } + module.codelength = getOneLevelCodelength(); + m_hierarchicalCodelength = getOneLevelCodelength(); + + } else { + // Set consolidated cluster index on nodes and modules + for (auto clusterIt = m_root.begin_tree(); !clusterIt.isEnd(); ++clusterIt) { + clusterIt->index = clusterIt.moduleIndex(); + } + + // Calculate individual module codelengths and store on the modules + calcCodelengthOnTree(root(), false); + m_root.codelength = getIndexCodelength(); + m_hierarchicalCodelength = getCodelength(); + } + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); +} + +void InfomapBase::restoreHardPartition() +{ + // Collect all leaf nodes in a separate sequence to be able to iterate independent of tree structure + std::vector leafNodes(numLeafNodes()); + unsigned int leafIndex = 0; + for (InfoNode& node : m_root.infomapTree()) { + if (node.isLeaf()) { + leafNodes[leafIndex] = &node; + ++leafIndex; + } + } + // Expand all children + unsigned int numExpandedChildren = 0; + unsigned int numExpandedNodes = 0; + for (InfoNode* node : leafNodes) { + ++numExpandedNodes; + numExpandedChildren += node->expandChildren(); + node->replaceWithChildren(); + } + + // Swap back original leaf nodes + m_originalLeafNodes.swap(m_leafNodes); + + Log(1) << "Expanded " << numExpandedNodes << " hard modules to " << numExpandedChildren << " original nodes.\n"; +} + +// =================================================== +// Run: Init: * +// =================================================== + +void InfomapBase::initEnterExitFlow() +{ + // Not done in Bayesian + // TODO: Skip this, always add enter/exit/tele flow from flow calculator + // Calculate enter/exit + double alpha = teleportationProbability; + double beta = 1.0 - alpha; + + for (auto* n : m_leafNodes) { + n->data.enterFlow = n->data.exitFlow = 0.0; + } + if (!isUndirectedClustering()) { + for (auto* n : m_leafNodes) { + auto& node = *n; + node.data.teleportFlow = alpha * node.data.flow; + node.data.teleportSourceFlow = node.data.flow; + if (node.isDangling()) { + node.data.teleportFlow = node.data.flow; + node.data.danglingFlow = node.data.flow; + m_sumDanglingFlow += node.data.flow; + } + } + for (auto* n : m_leafNodes) { + auto& node = *n; + for (InfoEdge* e : node.outEdges()) { + InfoEdge& edge = *e; + // Self-links not included here, should not add to enter and exit flow in its enclosing module + edge.source->data.exitFlow += edge.data.flow; + edge.target->data.enterFlow += edge.data.flow; + } + if (recordedTeleportation) { + // Don't let self-teleportation add to the enter/exit flow (i.e. multiply with (1.0 - node.data.teleportWeight)) + node.data.exitFlow += (alpha * node.data.flow + beta * node.data.danglingFlow) * (1.0 - node.data.teleportWeight); + node.data.enterFlow += (alpha * (1.0 - node.data.flow) + beta * (m_sumDanglingFlow - node.data.danglingFlow)) * node.data.teleportWeight; + } + } + } else { + for (auto* n : m_leafNodes) { + auto& node = *n; + node.data.teleportFlow = alpha * node.data.flow; + node.data.teleportSourceFlow = node.data.flow; + if (node.isDangling()) { + node.data.teleportFlow = node.data.flow; + node.data.danglingFlow = node.data.flow; + } + for (InfoEdge* e : node.outEdges()) { + InfoEdge& edge = *e; + // Self-links not included here, should not add to enter and exit flow in its enclosing module + double halfFlow = edge.data.flow / 2; + edge.source->data.exitFlow += halfFlow; + edge.target->data.exitFlow += halfFlow; + edge.source->data.enterFlow += halfFlow; + edge.target->data.enterFlow += halfFlow; + } + } + } +} + +// Aggregate node and enter/exit flow to all tree nodes +void InfomapBase::aggregateFlowValuesFromLeafToRoot() +{ + // Aggregate flow from leaf nodes to root node + unsigned int numLevels = 0; + root().data.flow = 0.0; + for (auto it = root().begin_post_depth_first(); !it.isEnd(); ++it) { + auto& node = *it; + if (!node.isRoot()) + node.parent->data += node.data; + // Don't aggregate enter and exit flow + if (!node.isLeaf()) { + node.index = it.depth(); // Use index to store the depth on modules + node.data.enterFlow = 0.0; + node.data.exitFlow = 0.0; + } else + numLevels = std::max(numLevels, it.depth()); + } + + if (std::abs(root().data.flow - 1.0) > 1e-10) { + Log() << "Warning, aggregated flow is not exactly 1.0, but " << std::setprecision(10) << root().data.flow << std::setprecision(9) << ".\n"; + } + + // Aggregate enter and exit flow between modules + for (auto& leafNode : m_leafNodes) { + auto& leafNodeSource = *leafNode; + for (InfoEdge* e : leafNodeSource.outEdges()) { + auto& edge = *e; + auto& leafNodeTarget = edge.target; + double linkFlow = edge.data.flow; + double halfFlow = linkFlow / 2; + + InfoNode* node1 = leafNodeSource.parent; + InfoNode* node2 = leafNodeTarget->parent; + + if (node1 == node2) + continue; + + // First aggregate link flow until equal depth + while (node1->index > node2->index) { + if (isUndirectedClustering()) { + node1->data.exitFlow += halfFlow; + node1->data.enterFlow += halfFlow; + } else { + node1->data.exitFlow += linkFlow; + } + node1 = node1->parent; + } + while (node2->index > node1->index) { + if (isUndirectedClustering()) { + node2->data.enterFlow += halfFlow; + node2->data.exitFlow += halfFlow; + } else { + node2->data.enterFlow += linkFlow; + } + node2 = node2->parent; + } + + // Then aggregate link flow until equal parent + while (node1 != node2) { + if (isUndirectedClustering()) { + node1->data.exitFlow += halfFlow; + node1->data.enterFlow += halfFlow; + node2->data.enterFlow += halfFlow; + node2->data.exitFlow += halfFlow; + } else { + node1->data.exitFlow += linkFlow; + node2->data.enterFlow += linkFlow; + } + node1 = node1->parent; + node2 = node2->parent; + } + } + } + if (recordedTeleportation) { + Log() << "\n\nAggregating enter/exit flow for recorded teleportation, sum teleFlow: " << m_root.data.teleportFlow << "\n"; + + for (auto& node : m_root.infomapTree()) { + if (!node.isLeaf()) { + // Don't code self-teleportation + + node.data.enterFlow += (m_root.data.teleportFlow - node.data.teleportFlow) * node.data.teleportWeight; + node.data.exitFlow += node.data.teleportFlow * (1.0 - node.data.teleportWeight); + } + } + } +} + +double InfomapBase::calcCodelengthOnTree(InfoNode& root, bool includeRoot) const +{ + double totalCodelength = 0.0; + // Calculate enter/exit flow (assuming 0 by default) + for (auto& node : root.infomapTree()) { + if (node.isLeaf() || (!includeRoot && node.isRoot())) + continue; + node.codelength = calcCodelength(node); + totalCodelength += node.codelength; + } + return totalCodelength; +} + +// =================================================== +// Run: Partition: * +// =================================================== + +void InfomapBase::setActiveNetworkFromChildrenOfRoot() +{ + m_moduleNodes.resize(m_root.childDegree()); + unsigned int i = 0; + for (auto& node : m_root) + m_moduleNodes[i++] = &node; + m_activeNetwork = &m_moduleNodes; +} + +void InfomapBase::findTopModulesRepeatedly(unsigned int maxLevels) +{ + Log(1, 2) << "Iteration " << (m_tuneIterationIndex + 1) << ", moving "; + Log(3) << "\nIteration " << (m_tuneIterationIndex + 1) << ":\n"; + m_aggregationLevel = 0; + unsigned int numLevelsConsolidated = numLevels() - 1; + if (maxLevels == 0) + maxLevels = std::numeric_limits::max(); + + std::string initialCodelength; + + // Reapply core algorithm on modular network, replacing modules with super modules + while (numTopModules() > 1 && numLevelsConsolidated != maxLevels) { + if (haveModules()) + setActiveNetworkFromChildrenOfRoot(); + else + setActiveNetworkFromLeafs(); + initPartition(); + if (m_aggregationLevel == 0) { + initialCodelength = io::Str() << "" << *this; + } + + Log(1, 2) << activeNetwork().size() << "*" << std::flush; + Log(3) << "Level " << (numLevelsConsolidated + 1) << " (codelength: " << *this << "): Moving " << activeNetwork().size() << " nodes... " << std::flush; + // Core loop, merging modules + unsigned int numOptimizationLoops = optimizeActiveNetwork(); + + Log(1, 2) << numOptimizationLoops << ", " << std::flush; + Log(3) << "done! -> codelength " << *this << " in " << numActiveModules() << " modules.\n"; + + // If no improvement, revert codelength terms to the last consolidated state + if (haveModules() && restoreConsolidatedOptimizationPointIfNoImprovement()) { + Log(3) << "-> Restored to codelength " << *this << " in " << numTopModules() << " modules.\n"; + break; + } + + // Consolidate modules + bool replaceExistingModules = haveModules(); + consolidateModules(replaceExistingModules); + ++numLevelsConsolidated; + ++m_aggregationLevel; + } + m_aggregationLevel = 0; + + m_numNonTrivialTopModules = calculateNumNonTrivialTopModules(); + + Log(1, 2) << (m_isCoarseTune ? "modules" : "nodes") << "*loops from codelength " << initialCodelength << " to codelength " << *this << " in " << numTopModules() << " modules. (" << m_numNonTrivialTopModules << " non-trivial modules)\n"; +} + +unsigned int InfomapBase::fineTune() +{ + if (numLevels() != 2) + throw std::logic_error("InfomapBase::fineTune() called but numLevels != 2"); + + setActiveNetworkFromLeafs(); + initPartition(); + + // Make sure module nodes have correct index //TODO: Assume always correct here? + unsigned int moduleIndex = 0; + for (auto& module : m_root) { + module.index = moduleIndex++; + } + + // Put leaf modules in existing modules + std::vector modules(numLeafNodes()); + for (unsigned int i = 0; i < numLeafNodes(); ++i) { + modules[i] = m_leafNodes[i]->parent->index; + } + moveActiveNodesToPredefinedModules(modules); + + Log(3) << " -> moved to codelength " << *this << " in " << numActiveModules() << " existing modules. Try tuning...\n"; + + // Continue to optimize from there to tune leaf nodes + unsigned int numEffectiveLoops = optimizeActiveNetwork(); + if (numEffectiveLoops == 0) { + restoreConsolidatedOptimizationPointIfNoImprovement(); + Log(4) << "Fine-tune didn't improve solution, restoring last.\n"; + } else { + // Delete existing modules and consolidate fine-tuned modules + root().replaceChildrenWithGrandChildren(); + consolidateModules(false); + Log(4) << "Fine-tune done in " << numEffectiveLoops << " effective loops to codelength " << *this << " in " << numTopModules() << " modules.\n"; + } + + return numEffectiveLoops; +} + +unsigned int InfomapBase::coarseTune() +{ + if (numLevels() != 2) + throw std::logic_error("InfomapBase::coarseTune() called but numLevels != 2"); + + Log(4) << "Coarse-tune...\nPartition each module in sub-modules for coarse tune...\n"; + + bool isSilent = false; + if (isMainInfomap()) { + isSilent = Log::isSilent(); + Log::setSilent(true); + } + + unsigned int moduleIndexOffset = 0; + for (auto& node : m_root) { + // Don't search for sub-modules in too small modules + if (node.childDegree() < 2) { + for (auto& child : node) { + child.index = moduleIndexOffset; + } + moduleIndexOffset += 1; + continue; + } else { + InfomapBase& subInfomap = getSubInfomap(node) + .setTwoLevel(true) + .setTuneIterationLimit(1); + subInfomap.initNetwork(node).run(); + + auto originalLeafIt = node.begin_child(); + for (auto& subLeafPtr : subInfomap.leafNodes()) { + InfoNode& subLeaf = *subLeafPtr; + originalLeafIt->index = subLeaf.index + moduleIndexOffset; + ++originalLeafIt; + } + moduleIndexOffset += subInfomap.numTopModules(); + + node.disposeInfomap(); + } + } + + if (isMainInfomap()) + Log::setSilent(isSilent); + + Log(4) << "Move leaf nodes to " << moduleIndexOffset << " sub-modules... \n"; + // Put leaf modules in the calculated sub-modules + std::vector subModules(numLeafNodes()); + for (unsigned int i = 0; i < numLeafNodes(); ++i) { + subModules[i] = m_leafNodes[i]->index; + } + + setActiveNetworkFromLeafs(); + initPartition(); + moveActiveNodesToPredefinedModules(subModules); + + Log(4) << "Moved to " << numActiveModules() << " modules...\n"; + + // Replace existing modules but store that structure on the sub-modules + consolidateModules(true); + + Log(4) << "Consolidated " << numTopModules() << " sub-modules to codelength " << *this << '\n'; + + Log(4) << "Move sub-modules to former modular structure... \n"; + // Put sub-modules in the former modular structure + std::vector modules(numTopModules()); + unsigned int iModule = 0; + for (auto& subModule : m_root) { + modules[iModule++] = subModule.index; + } + + setActiveNetworkFromChildrenOfRoot(); + initPartition(); + // Move sub-modules to former modular structure + moveActiveNodesToPredefinedModules(modules); + + Log(4) << "Tune sub-modules from codelength " << *this << " in " << numActiveModules() << " modules... \n"; + // Continue to optimize from there to tune sub-modules + unsigned int numEffectiveLoops = optimizeActiveNetwork(); + Log(4) << "Tuned sub-modules in " << numEffectiveLoops << " effective loops to codelength " << *this << " in " << numActiveModules() << " modules.\n"; + consolidateModules(true); + Log(4) << "Consolidated tuned sub-modules to codelength " << *this << " in " << numTopModules() << " modules.\n"; + return numEffectiveLoops; +} + +unsigned int InfomapBase::calculateNumNonTrivialTopModules() const +{ + if (root().childDegree() == 1) + return 0; + unsigned int numNonTrivialTopModules = 0; + for (auto& module : m_root) { + if (module.childDegree() > 1) + ++numNonTrivialTopModules; + } + return numNonTrivialTopModules; +} + +unsigned int InfomapBase::calculateMaxDepth() const +{ + unsigned int maxDepth = 0; + for (auto it(m_root.begin_tree()); !it.isEnd(); ++it) { + if (it->isLeaf()) { + maxDepth = std::max(maxDepth, it.depth()); + } + } + return maxDepth; +} + +unsigned int InfomapBase::findHierarchicalSuperModulesFast(unsigned int superLevelLimit) +{ + if (superLevelLimit == 0) + return 0; + + unsigned int numLevelsCreated = 0; + double oldIndexLength = getIndexCodelength(); + double hierarchicalCodelength = getCodelength(); + double workingHierarchicalCodelength = hierarchicalCodelength; + + Log(1) << "\nFind hierarchical super modules iteratively...\n"; + Log(0, 0) << "Fast super-level compression: " << std::setprecision(2) << std::flush; + + // Add index codebooks as long as the code gets shorter + do { + Log(1) << "Iteration " << numLevelsCreated + 1 << ", finding super modules fast to " << numTopModules() << (haveModules() ? " modules" : " nodes") << "... \n"; + + if (haveModules()) { + setActiveNetworkFromChildrenOfRoot(); + transformNodeFlowToEnterFlow(m_root); + initSuperNetwork(); + } else { + setActiveNetworkFromLeafs(); + } + + initPartition(); + + unsigned int numEffectiveLoops = optimizeActiveNetwork(); + + double codelength = getCodelength(); + double indexCodelength = getIndexCodelength(); + unsigned int numSuperModules = numActiveModules(); + bool trivialSolution = numSuperModules == 1 || numSuperModules == activeNetwork().size(); + + bool acceptSolution = !trivialSolution && codelength < oldIndexLength - minimumCodelengthImprovement; + // Force at least one modular level! + bool acceptByForce = !acceptSolution && !haveModules(); + if (acceptByForce) + acceptSolution = true; + + workingHierarchicalCodelength += codelength - oldIndexLength; + + Log(0, 0) << hideIf(!acceptSolution) << ((hierarchicalCodelength - workingHierarchicalCodelength) / hierarchicalCodelength * 100) << "% " << std::flush; + Log(1) << " -> Found " << numActiveModules() << " super modules in " << numEffectiveLoops << " effective loops with hierarchical codelength " << indexCodelength << " + " << (workingHierarchicalCodelength - indexCodelength) << " = " << workingHierarchicalCodelength << (acceptSolution ? "\n" : ", discarding the solution.\n") << std::flush; + Log(1) << oldIndexLength << " -> " << *this << "\n"; + + if (!acceptSolution) { + restoreConsolidatedOptimizationPointIfNoImprovement(true); + break; + } + + // Consolidate the dynamic modules without replacing any existing ones. + consolidateModules(false); + + hierarchicalCodelength = workingHierarchicalCodelength; + oldIndexLength = indexCodelength; + + ++numLevelsCreated; + + m_numNonTrivialTopModules = calculateNumNonTrivialTopModules(); + + } while (m_numNonTrivialTopModules > 1 && numLevelsCreated != superLevelLimit); + + // Restore the temporary transformation of flow to enter flow on super modules + resetFlowOnModules(); + + Log(0, 0) << "to codelength " << io::toPrecision(hierarchicalCodelength) << " in " << numTopModules() << " top modules.\n"; + Log(1) << "Finding super modules done! Added " << numLevelsCreated << " levels with hierarchical codelength " << io::toPrecision(hierarchicalCodelength) << " in " << numTopModules() << " top modules.\n"; + + // Calculate and store hierarchical codelengths + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); + + return numLevelsCreated; +} + +unsigned int InfomapBase::findHierarchicalSuperModules(unsigned int superLevelLimit) +{ + if (superLevelLimit == 0) + return 0; + + unsigned int numLevelsCreated = 0; + double oldIndexLength = getIndexCodelength(); + double hierarchicalCodelength = getCodelength(); + double workingHierarchicalCodelength = hierarchicalCodelength; + + if (!haveModules()) + throw std::logic_error("Trying to find hierarchical super modules without any modules"); + + Log(1) << "\nFind hierarchical super modules iteratively...\n"; + Log(0, 0) << "Super-level compression: " << std::setprecision(2) << std::flush; + + // Add index codebooks as long as the code gets shorter + do { + Log(1) << "Iteration " << numLevelsCreated + 1 << ", finding super modules to " << numTopModules() << " modules... \n"; + bool isSilent = false; + if (isMainInfomap()) { + isSilent = Log::isSilent(); + Log::setSilent(true); + } + InfoNode tmp(m_root.data); // Temporary owner for the super Infomap instance + auto& superInfomap = getSuperInfomap(tmp) + .setTwoLevel(true); + superInfomap.initNetwork(m_root, true); //.initSuperNetwork(); + superInfomap.run(); + if (isMainInfomap()) { + Log::setSilent(isSilent); + } + double superCodelength = superInfomap.getCodelength(); + double superIndexCodelength = superInfomap.getIndexCodelength(); + + unsigned int numSuperModules = superInfomap.numTopModules(); + bool trivialSolution = numSuperModules == 1 || numSuperModules == numTopModules(); + + if (trivialSolution) { + Log(1) << "failed to find non-trivial super modules.\n"; + break; + } + + bool improvedCodelength = superCodelength < oldIndexLength - minimumCodelengthImprovement; + if (!improvedCodelength) { + Log(1) << "two-level index codebook not improved over one-level.\n"; + break; + } + + workingHierarchicalCodelength += superCodelength - oldIndexLength; + + Log(0, 0) << ((hierarchicalCodelength - workingHierarchicalCodelength) + / hierarchicalCodelength * 100) + << "% " << std::flush; + Log(1) << " -> Found " << numSuperModules << " super modules in with hierarchical codelength " << superIndexCodelength << " + " << (superCodelength - superIndexCodelength) << " + " << (workingHierarchicalCodelength - superCodelength) << " = " << workingHierarchicalCodelength << '\n'; + + // Merge current top modules to two-level solution found in the super Infomap instance. + std::vector modules(numTopModules()); + unsigned int iModule = 0; + for (InfoNode* n : superInfomap.leafNodes()) { + modules[iModule++] = n->index; + } + + setActiveNetworkFromChildrenOfRoot(); + initPartition(); + // Move top modules to super modules + moveActiveNodesToPredefinedModules(modules); + + // Consolidate the dynamic modules without replacing any existing ones. + consolidateModules(false); + + Log(1) << "Consolidated " << numTopModules() << " super modules. Index codelength: " << oldIndexLength << " -> " << *this << "\n"; + + hierarchicalCodelength = workingHierarchicalCodelength; + oldIndexLength = superIndexCodelength; + + ++numLevelsCreated; + + m_numNonTrivialTopModules = calculateNumNonTrivialTopModules(); + + } while (m_numNonTrivialTopModules > 1 && numLevelsCreated != superLevelLimit); + + // Restore the temporary transformation of flow to enter flow on super modules + resetFlowOnModules(); + + Log(0, 0) << "to codelength " << io::toPrecision(hierarchicalCodelength) << " in " << numTopModules() << " top modules.\n"; + Log(1) << "Finding super modules done! Added " << numLevelsCreated << " levels with hierarchical codelength " << io::toPrecision(hierarchicalCodelength) << " in " << numTopModules() << " top modules.\n"; + + // Calculate and store hierarchical codelengths + m_hierarchicalCodelength = calcCodelengthOnTree(root(), true); + + return numLevelsCreated; +} + +void InfomapBase::transformNodeFlowToEnterFlow(InfoNode& parent) +{ + double sumFlow = 0.0; + for (auto& module : m_root) { + module.data.flow = module.data.enterFlow; + sumFlow += module.data.flow; + } + parent.data.flow = sumFlow; +} + +void InfomapBase::resetFlowOnModules() +{ + // Reset flow on all modules + for (auto& module : m_root.infomapTree()) { + if (!module.isLeaf()) + module.data.flow = 0.0; + } + // Aggregate flow from leaf nodes up in the tree + for (InfoNode* n : m_leafNodes) { + double leafNodeFlow = n->data.flow; + InfoNode* module = n->parent; + do { + module->data.flow += leafNodeFlow; + module = module->parent; + } while (module != nullptr); + } +} + +unsigned int InfomapBase::removeModules() +{ + unsigned int numLevelsDeleted = 0; + while (numLevels() > 1) { + m_root.replaceChildrenWithGrandChildren(); + ++numLevelsDeleted; + } + if (numLevelsDeleted > 0) { + Log(2) << "Removed " << numLevelsDeleted << " levels of modules.\n"; + } + return numLevelsDeleted; +} + +unsigned int InfomapBase::removeSubModules(bool recalculateCodelengthOnTree) +{ + unsigned int numLevelsDeleted = 0; + while (numLevels() > 2) { + for (InfoNode& module : m_root) + module.replaceChildrenWithGrandChildren(); + ++numLevelsDeleted; + } + if (numLevelsDeleted > 0) { + Log(2) << "Removed " << numLevelsDeleted << " levels of sub-modules.\n"; + if (recalculateCodelengthOnTree) + calcCodelengthOnTree(root(), false); + } + return numLevelsDeleted; +} + +unsigned int InfomapBase::recursivePartition() +{ + double indexCodelength = getIndexCodelength(); + double hierarchicalCodelength = m_hierarchicalCodelength; + + Log(0, 0) << "\nRecursive sub-structure compression: " << std::flush; + + PartitionQueue partitionQueue; + if (fastHierarchicalSolution > 0) { + queueLeafModules(partitionQueue); + Log(1) << "\nFind sub modules recursively from " << partitionQueue.size() << " sub modules on level " << numLevels() - 2; + } else { + queueTopModules(partitionQueue); + Log(1) << "\nFind sub modules recursively from " << partitionQueue.size() << " top modules"; + double moduleCodelength = 0.0; + for (auto& module : m_root) + moduleCodelength += module.codelength; + hierarchicalCodelength = indexCodelength + moduleCodelength; + } + Log(1) << " with codelength: " << indexCodelength << " + " << (hierarchicalCodelength - indexCodelength) << " = " << io::toPrecision(hierarchicalCodelength) << '\n'; + + double sumConsolidatedCodelength = hierarchicalCodelength - partitionQueue.moduleCodelength; + + bool isSilent = false; + if (isMainInfomap()) { + isSilent = Log::isSilent(); + } + + while (partitionQueue.size() > 0) { + Log(1) << "Level " << partitionQueue.level << ": " << (partitionQueue.flow * 100) << "% of the flow in " << partitionQueue.size() << " modules. Partitioning... " << std::setprecision(6) << std::flush; + + if (isMainInfomap()) + Log::setSilent(true); + + // Partition all modules in the queue and fill up the next level queue + PartitionQueue nextLevelQueue; + processPartitionQueue(partitionQueue, nextLevelQueue); + + if (isMainInfomap()) + Log::setSilent(isSilent); + + double leftToImprove = partitionQueue.moduleCodelength; + sumConsolidatedCodelength += partitionQueue.indexCodelength + partitionQueue.leafCodelength; + double limitCodelength = sumConsolidatedCodelength + leftToImprove; + + Log(0, 0) << ((hierarchicalCodelength - limitCodelength) / hierarchicalCodelength) * 100 << "% " << std::flush; + Log(1) << "done! Codelength: " << partitionQueue.indexCodelength << " + " << partitionQueue.leafCodelength << " (+ " << leftToImprove << " left to improve)" + << " -> limit: " << io::toPrecision(limitCodelength) << " bits.\n"; + + hierarchicalCodelength = limitCodelength; + + partitionQueue.swap(nextLevelQueue); + } + + // Store resulting hierarchical codelength + m_hierarchicalCodelength = hierarchicalCodelength; + + Log(0, 0) << ". Found " << partitionQueue.level << " levels with codelength " << io::toPrecision(hierarchicalCodelength) << "\n"; + Log(1) << " -> Found " << partitionQueue.level << " levels with codelength " << io::toPrecision(hierarchicalCodelength) << "\n"; + + return partitionQueue.level; +} + +void InfomapBase::queueTopModules(PartitionQueue& partitionQueue) +{ + // Add modules to partition queue + unsigned int numNonTrivialModules = 0; + partitionQueue.resize(numTopModules()); + double sumFlow = 0.0; + double sumNonTrivialFlow = 0.0; + double sumModuleCodelength = 0.0; + unsigned int moduleIndex = 0; + for (auto& module : m_root) { + partitionQueue[moduleIndex] = &module; + sumFlow += module.data.flow; + sumModuleCodelength += module.codelength; + if (module.childDegree() > 1) { + ++numNonTrivialModules; + sumNonTrivialFlow += module.data.flow; + } + ++moduleIndex; + } + partitionQueue.flow = sumFlow; + partitionQueue.numNonTrivialModules = numNonTrivialModules; + partitionQueue.nonTrivialFlow = sumNonTrivialFlow; + partitionQueue.indexCodelength = getIndexCodelength(); + partitionQueue.moduleCodelength = sumModuleCodelength; + partitionQueue.level = 1; +} + +void InfomapBase::queueLeafModules(PartitionQueue& partitionQueue) +{ + unsigned int numLeafModules = 0; + for (auto& node : m_root.infomapTree()) { + if (node.isLeafModule()) + ++numLeafModules; + } + + // Add modules to partition queue + partitionQueue.resize(numLeafModules); + unsigned int numNonTrivialModules = 0; + double sumFlow = 0.0; + double sumNonTrivialFlow = 0.0; + double sumModuleCodelength = 0.0; + unsigned int moduleIndex = 0; + unsigned int maxDepth = 0; + for (auto it = m_root.begin_tree(); !it.isEnd(); ++it) { + if (it->isLeafModule()) { + auto& module = *it; + partitionQueue[moduleIndex] = it.current(); + sumFlow += module.data.flow; + sumModuleCodelength += module.codelength; + if (module.childDegree() > 1) { + ++numNonTrivialModules; + sumNonTrivialFlow += module.data.flow; + } + maxDepth = std::max(maxDepth, it.depth()); + ++moduleIndex; + } + } + partitionQueue.flow = sumFlow; + partitionQueue.numNonTrivialModules = numNonTrivialModules; + partitionQueue.nonTrivialFlow = sumNonTrivialFlow; + partitionQueue.indexCodelength = getIndexCodelength(); + partitionQueue.moduleCodelength = sumModuleCodelength; + partitionQueue.level = maxDepth; +} + +bool InfomapBase::processPartitionQueue(PartitionQueue& queue, PartitionQueue& nextLevelQueue) const +{ + PartitionQueue::size_t numModules = queue.size(); + std::vector indexCodelengths(numModules, 0.0); + std::vector moduleCodelengths(numModules, 0.0); + std::vector leafCodelengths(numModules, 0.0); + std::vector subQueues(numModules); + +#pragma omp parallel for schedule(dynamic) + for (PartitionQueue::size_t moduleIndex = 0; moduleIndex < numModules; ++moduleIndex) { + InfoNode& module = *queue[moduleIndex]; + + module.codelength = calcCodelength(module); + // Delete former sub-structure if exists + if (module.disposeInfomap()) + module.codelength = calcCodelength(module); + + // If only trivial substructure is to be found, no need to create infomap instance to find sub-module structures. + if (module.childDegree() <= 2) { + module.codelength = calcCodelength(module); + leafCodelengths[moduleIndex] = module.codelength; + continue; + } + + double oldModuleCodelength = module.codelength; + PartitionQueue& subQueue = subQueues[moduleIndex]; + subQueue.level = queue.level + 1; + + auto& subInfomap = getSubInfomap(module) + .initNetwork(module); + // Run two-level partition + find hierarchically super modules (skip recursion) + subInfomap.setOnlySuperModules(true).run(); + + double subCodelength = subInfomap.getHierarchicalCodelength(); + double subIndexCodelength = subInfomap.root().codelength; + double subModuleCodelength = subCodelength - subIndexCodelength; + InfoNode& subRoot = *module.getInfomapRoot(); + unsigned int numSubModules = subRoot.childDegree(); + bool trivialSubPartition = numSubModules == 1 || numSubModules == module.childDegree(); + bool improvedCodelength = subCodelength < oldModuleCodelength - minimumCodelengthImprovement; + + if (trivialSubPartition || !improvedCodelength) { + Log(1) << "Disposing unaccepted sub Infomap instance.\n"; + module.disposeInfomap(); + module.codelength = oldModuleCodelength; + subQueue.skip = true; + leafCodelengths[moduleIndex] = module.codelength; + } else { + // Improvement + subInfomap.queueTopModules(subQueue); + indexCodelengths[moduleIndex] = subIndexCodelength; + moduleCodelengths[moduleIndex] = subModuleCodelength; + } + } + + double sumLeafCodelength = 0.0; + double sumIndexCodelength = 0.0; + double sumModuleCodelengths = 0.0; + PartitionQueue::size_t nextLevelSize = 0; + for (PartitionQueue::size_t moduleIndex = 0; moduleIndex < numModules; ++moduleIndex) { + nextLevelSize += subQueues[moduleIndex].skip ? 0 : subQueues[moduleIndex].size(); + sumLeafCodelength += leafCodelengths[moduleIndex]; + sumIndexCodelength += indexCodelengths[moduleIndex]; + sumModuleCodelengths += moduleCodelengths[moduleIndex]; + } + + queue.indexCodelength = sumIndexCodelength; + queue.leafCodelength = sumLeafCodelength; + queue.moduleCodelength = sumModuleCodelengths; + + // Collect the sub-queues and build the next-level queue + nextLevelQueue.level = queue.level + 1; + nextLevelQueue.resize(nextLevelSize); + PartitionQueue::size_t nextLevelIndex = 0; + for (PartitionQueue::size_t moduleIndex = 0; moduleIndex < numModules; ++moduleIndex) { + PartitionQueue& subQueue = subQueues[moduleIndex]; + if (!subQueue.skip) { + for (PartitionQueue::size_t subIndex = 0; subIndex < subQueue.size(); ++subIndex) { + nextLevelQueue[nextLevelIndex++] = subQueue[subIndex]; + } + nextLevelQueue.flow += subQueue.flow; + nextLevelQueue.nonTrivialFlow += subQueue.nonTrivialFlow; + nextLevelQueue.numNonTrivialModules += subQueue.numNonTrivialModules; + } + } + + return nextLevelSize > 0; +} + +// =================================================== +// Write output +// =================================================== + +void InfomapBase::writeResult(int trial) +{ + if (noFileOutput) + return; + + io::Str s; + s << outDirectory + outName; + + if (printAllTrials && trial != -1 && numTrials > 1) { + s << "_trial_" << trial; + } + + std::string basename = s; + + if (printTree) { + std::string filename = basename + ".tree"; + + if (!printStates()) { + Log() << "Write tree to " << filename << "... "; + writeTree(filename); + Log() << "done!\n"; + } else { + // Write both physical and state level + Log() << "Write physical tree to " << filename << "... "; + writeTree(filename); + Log() << "done!\n"; + std::string filenameStates = basename + "_states.tree"; + Log() << "Write state tree to " << filenameStates << "... "; + writeTree(filenameStates, true); + Log() << "done!\n"; + } + } + + if (printFlowTree) { + std::string filename = basename + ".ftree"; + + if (!printStates()) { + Log() << "Write flow tree to " << filename << "... "; + writeFlowTree(filename); + Log() << "done!\n"; + } else { + // Write both physical and state level + Log() << "Write physical flow tree to " << filename << "... "; + writeFlowTree(filename, false); + Log() << "done!\n"; + std::string filenameStates = basename + "_states.ftree"; + Log() << "Write state flow tree to " << filenameStates << "... "; + writeFlowTree(filenameStates, true); + Log() << "done!\n"; + } + } + + if (printNewick) { + std::string filename = basename + ".nwk"; + + if (!printStates()) { + Log() << "Write Newick tree to " << filename << "... "; + writeNewickTree(filename); + Log() << "done!\n"; + } else { + // Write both physical and state level + Log() << "Write physical Newick tree to " << filename << "... "; + writeNewickTree(filename, false); + Log() << "done!\n"; + std::string filenameStates = basename + "_states.nwk"; + Log() << "Write state Newick tree to " << filenameStates << "... "; + writeNewickTree(filenameStates, true); + Log() << "done!\n"; + } + } + + if (printJson) { + std::string filename = basename + ".json"; + const bool writeLinks = false; + + if (!printStates()) { + Log() << "Write JSON tree to " << filename << "... "; + writeJsonTree(filename, false, writeLinks); + Log() << "done!\n"; + } else { + // Write both physical and state level + Log() << "Write physical JSON tree to " << filename << "... "; + writeJsonTree(filename, false, writeLinks); + Log() << "done!\n"; + std::string filenameStates = basename + "_states.json"; + Log() << "Write state JSON tree to " << filenameStates << "... "; + writeJsonTree(filenameStates, true, writeLinks); + Log() << "done!\n"; + } + } + + if (printCsv) { + std::string filename = basename + ".csv"; + + if (!printStates()) { + Log() << "Write CSV tree to " << filename << "... "; + writeCsvTree(filename); + Log() << "done!\n"; + } else { + // Write both physical and state level + Log() << "Write physical CSV tree to " << filename << "... "; + writeCsvTree(filename, false); + Log() << "done!\n"; + std::string filenameStates = basename + "_states.csv"; + Log() << "Write state CSV tree to " << filenameStates << "... "; + writeCsvTree(filenameStates, true); + Log() << "done!\n"; + } + } + + if (printClu) { + std::string filename = basename + ".clu"; + if (!printStates()) { + Log() << "Write node modules to " << filename << "... "; + writeClu(filename, false, cluLevel); + Log() << "done!\n"; + } else { + // Write both physical and state level + Log() << "Write physical node modules to " << filename << "... "; + writeClu(filename, false, cluLevel); + Log() << "done!\n"; + std::string filenameStates = basename + "_states.clu"; + Log() << "Write state node modules to " << filenameStates << "... "; + writeClu(filenameStates, true, cluLevel); + Log() << "done!\n"; + } + } +} + +unsigned int printPerLevelCodelength(const InfoNode& parent, std::ostream& out) +{ + std::vector perLevelStats; + aggregatePerLevelCodelength(parent, perLevelStats); + + unsigned int numLevels = perLevelStats.size(); + + out << "Per level number of modules: ["; + for (unsigned int i = 0; i < numLevels - 1; ++i) { + out << io::padValue(perLevelStats[i].numModules, 11) << ", "; + } + out << io::padValue(perLevelStats[numLevels - 1].numModules, 11) << "]"; + unsigned int sumNumModules = 0; + for (unsigned int i = 0; i < numLevels; ++i) + sumNumModules += perLevelStats[i].numModules; + out << " (sum: " << sumNumModules << ")\n"; + + out << "Per level number of leaf nodes: ["; + for (unsigned int i = 0; i < numLevels - 1; ++i) { + out << io::padValue(perLevelStats[i].numLeafNodes, 11) << ", "; + } + out << io::padValue(perLevelStats[numLevels - 1].numLeafNodes, 11) << "]"; + unsigned int sumNumLeafNodes = 0; + for (unsigned int i = 0; i < numLevels; ++i) + sumNumLeafNodes += perLevelStats[i].numLeafNodes; + out << " (sum: " << sumNumLeafNodes << ")\n"; + + out << "Per level average child degree: ["; + double childDegree = perLevelStats[0].numNodes(); + double sumAverageChildDegree = childDegree * childDegree; + if (numLevels > 1) { + out << io::padValue(perLevelStats[0].numModules, 11) << ", "; + } + for (unsigned int i = 1; i < numLevels - 1; ++i) { + childDegree = perLevelStats[i].numNodes() * 1.0 / perLevelStats[i - 1].numModules; + sumAverageChildDegree += childDegree * perLevelStats[i].numNodes(); + out << io::padValue(childDegree, 11) << ", "; + } + if (numLevels > 1) { + childDegree = perLevelStats[numLevels - 1].numNodes() * 1.0 / perLevelStats[numLevels - 2].numModules; + sumAverageChildDegree += childDegree * perLevelStats[numLevels - 1].numNodes(); + } + out << io::padValue(childDegree, 11) << "]"; + out << " (average: " << sumAverageChildDegree / (sumNumModules + sumNumLeafNodes) << ")\n"; + + out << std::fixed << std::setprecision(9); + out << "Per level codelength for modules: ["; + for (unsigned int i = 0; i < numLevels - 1; ++i) { + out << perLevelStats[i].indexLength << ", "; + } + out << perLevelStats[numLevels - 1].indexLength << "]"; + double sumIndexLengths = 0.0; + for (unsigned int i = 0; i < numLevels; ++i) + sumIndexLengths += perLevelStats[i].indexLength; + out << " (sum: " << sumIndexLengths << ")\n"; + + out << "Per level codelength for leaf nodes: ["; + for (unsigned int i = 0; i < numLevels - 1; ++i) { + out << perLevelStats[i].leafLength << ", "; + } + out << perLevelStats[numLevels - 1].leafLength << "]"; + + double sumLeafLengths = 0.0; + for (unsigned int i = 0; i < numLevels; ++i) + sumLeafLengths += perLevelStats[i].leafLength; + out << " (sum: " << sumLeafLengths << ")\n"; + + out << "Per level codelength total: ["; + for (unsigned int i = 0; i < numLevels - 1; ++i) { + out << perLevelStats[i].codelength() << ", "; + } + out << perLevelStats[numLevels - 1].codelength() << "]"; + + double sumCodelengths = 0.0; + for (unsigned int i = 0; i < numLevels; ++i) + sumCodelengths += perLevelStats[i].codelength(); + out << " (sum: " << sumCodelengths << ")\n"; + + return numLevels; +} + +void aggregatePerLevelCodelength(const InfoNode& parent, std::vector& perLevelStat, unsigned int level) +{ + if (perLevelStat.size() < level + 1) + perLevelStat.resize(level + 1); + + if (parent.firstChild->isLeaf()) { + perLevelStat[level].numLeafNodes += parent.childDegree(); + perLevelStat[level].leafLength += parent.codelength; + return; + } + + perLevelStat[level].numModules += parent.childDegree(); + perLevelStat[level].indexLength += parent.codelength; + + for (auto& module : parent) { + if (module.getInfomapRoot() != nullptr) + aggregatePerLevelCodelength(*module.getInfomapRoot(), perLevelStat, level + 1); + else + aggregatePerLevelCodelength(module, perLevelStat, level + 1); + } +} + +void InfomapBase::initOptimizer(bool forceNoMemory) +{ + if (haveMetaData()) { + m_optimizer = std::make_unique>(); + } else if (haveMemory() && !forceNoMemory) { + m_optimizer = std::make_unique>(); + } else { + m_optimizer = std::make_unique>(); + } + m_optimizer->init(this); +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h b/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h new file mode 100644 index 00000000000..01b87e06bec --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h @@ -0,0 +1,583 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMAP_BASE_H_ +#define INFOMAP_BASE_H_ + +#include "InfomapConfig.h" +#include "InfoEdge.h" +#include "InfoNode.h" +#include "InfomapOptimizerBase.h" +#include "iterators/InfomapIterator.h" +#include "../io/ClusterMap.h" +#include "../io/Network.h" +#include "../io/Output.h" +#include "../utils/Log.h" +#include "../utils/Date.h" +#include "../utils/Stopwatch.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace infomap { + +namespace detail { + class PartitionQueue; + struct PerLevelStat; +} // namespace detail + +class InfomapBase : public InfomapConfig { + template + friend class InfomapOptimizer; + + void initOptimizer(bool forceNoMemory = false); + +public: + using PartitionQueue = detail::PartitionQueue; + + InfomapBase() : InfomapConfig() { initOptimizer(); } + + explicit InfomapBase(const Config& conf) : InfomapConfig(conf), m_network(conf) { initOptimizer(); } + + explicit InfomapBase(const std::string& flags, bool isCli = false) : InfomapConfig(flags, isCli) + { + initOptimizer(); + m_network.setConfig(*this); + m_initialParameters = m_currentParameters = flags; + } + + virtual ~InfomapBase() = default; + + // =================================================== + // Iterators + // =================================================== + + InfomapIterator iterTree(int maxClusterLevel = 1) { return { &root(), maxClusterLevel }; } + + InfomapIteratorPhysical iterTreePhysical(int maxClusterLevel = 1) { return { &root(), maxClusterLevel }; } + + InfomapModuleIterator iterModules(int maxClusterLevel = 1) { return { &root(), maxClusterLevel }; } + + InfomapLeafModuleIterator iterLeafModules(int maxClusterLevel = 1) { return { &root(), maxClusterLevel }; } + + InfomapLeafIterator iterLeafNodes(int maxClusterLevel = 1) { return { &root(), maxClusterLevel }; } + + InfomapLeafIteratorPhysical iterLeafNodesPhysical(int maxClusterLevel = 1) { return { &root(), maxClusterLevel }; } + + InfomapIterator begin(int maxClusterLevel = 1) { return { &root(), maxClusterLevel }; } + + InfomapIterator end() const { return InfomapIterator(nullptr); } + + // =================================================== + // Getters + // =================================================== + + Network& network() { return m_network; } + const Network& network() const { return m_network; } + + InfoNode& root() { return m_root; } + const InfoNode& root() const { return m_root; } + + unsigned int numLeafNodes() const { return m_leafNodes.size(); } + + const std::vector& leafNodes() const { return m_leafNodes; } + + unsigned int numTopModules() const { return m_root.childDegree(); } + + unsigned int numActiveModules() const { return m_optimizer->numActiveModules(); } + + unsigned int numNonTrivialTopModules() const { return m_numNonTrivialTopModules; } + + bool haveModules() const { return !m_root.isLeaf() && !m_root.firstChild->isLeaf(); } + + bool haveNonTrivialModules() const { return numNonTrivialTopModules() > 0; } + + /** + * Number of node levels below the root in current Infomap instance, 1 if no modules + */ + unsigned int numLevels() const; + + /** + * Get maximum depth of any child in the tree, following possible sub Infomap instances + */ + unsigned int maxTreeDepth() const; + + double getCodelength() const { return m_optimizer->getCodelength(); } + + double getMetaCodelength(bool unweighted = false) const { return m_optimizer->getMetaCodelength(unweighted); } + + double codelength() const { return m_hierarchicalCodelength; } + + const std::vector& codelengths() const { return m_codelengths; } + + double getIndexCodelength() const { return m_optimizer->getIndexCodelength(); } + + double getModuleCodelength() const { return m_hierarchicalCodelength - m_optimizer->getIndexCodelength(); } + + double getHierarchicalCodelength() const { return m_hierarchicalCodelength; } + + double getOneLevelCodelength() const { return m_oneLevelCodelength; } + + double getRelativeCodelengthSavings() const + { + auto oneLevelCodelength = getOneLevelCodelength(); + return oneLevelCodelength < 1e-16 ? 0 : 1.0 - codelength() / oneLevelCodelength; + } + + double getEntropyRate() { return m_entropyRate; } + double getMaxEntropy() { return m_maxEntropy; } + double getMaxFlow() { return m_maxFlow; } + + const Date& getStartDate() const { return m_startDate; } + const Stopwatch& getElapsedTime() const { return m_elapsedTime; } + + std::vector& activeNetwork() const { return *m_activeNetwork; } + + std::map> getMultilevelModules(bool states = false); + + // =================================================== + // IO + // =================================================== + + std::ostream& toString(std::ostream& out) const { return m_optimizer->toString(out); } + + // =================================================== + // Run + // =================================================== + + using InitialPartition = std::map; + + const InitialPartition& getInitialPartition() const { return m_initialPartition; } + + InfomapBase& setInitialPartition(const InitialPartition& moduleIds) + { + m_initialPartition = moduleIds; + return *this; + } + + void run(const std::string& parameters = ""); + + void run(Network& network); + +private: + bool isFullNetwork() const { return m_isMain && m_aggregationLevel == 0; } + bool isFirstLoop() const { return m_tuneIterationIndex == 0 && isFullNetwork(); } + + InfomapBase* getNewInfomapInstance() const { return new InfomapBase(getConfig()); } + InfomapBase* getNewInfomapInstanceWithoutMemory() const + { + auto im = new InfomapBase(); + im->initOptimizer(true); + return im; + } + + InfomapBase& getSubInfomap(InfoNode& node) const + { + return node.setInfomap(getNewInfomapInstance()) + .setIsMain(false) + .setSubLevel(m_subLevel + 1) + .setNonMainConfig(*this); + } + + InfomapBase& getSuperInfomap(InfoNode& node) const + { + return node.setInfomap(getNewInfomapInstanceWithoutMemory()) + .setIsMain(false) + .setSubLevel(m_subLevel + SUPER_LEVEL_ADDITION) + .setNonMainConfig(*this); + } + + /** + * Only the main infomap reads an external cluster file if exist + */ + InfomapBase& setIsMain(bool isMain) + { + m_isMain = isMain; + return *this; + } + + InfomapBase& setSubLevel(unsigned int level) + { + m_subLevel = level; + return *this; + } + + bool isTopLevel() const { return (m_subLevel & (SUPER_LEVEL_ADDITION - 1)) == 0; } + + bool isSuperLevelOnTopLevel() const { return m_subLevel == SUPER_LEVEL_ADDITION; } + + bool isMainInfomap() const { return m_isMain; } + + bool haveHardPartition() const { return !m_originalLeafNodes.empty(); } + + // =================================================== + // Run: * + // =================================================== + + InfomapBase& initNetwork(Network& network); + InfomapBase& initNetwork(InfoNode& parent, bool asSuperNetwork = false); + + void generateSubNetwork(Network& network); + void generateSubNetwork(InfoNode& parent); + + /** + * Init categorical meta data on all nodes from a file with the following format: + * # nodeId metaData + * 1 1 + * 2 1 + * 3 2 + * 4 2 + * 5 3 + * + */ + InfomapBase& initMetaData(const std::string& metaDataFile); + + /** + * Provide an initial partition of the network. + * + * @param clusterDataFile A .clu file containing cluster data. + * @param hard If true, the provided clusters will not be splitted. This reduces the + * effective network size during the optimization phase but the hard partitions are + * after that replaced by the original nodes. + */ + InfomapBase& initPartition(const std::string& clusterDataFile, bool hard = false, const Network* network = nullptr); + + /** + * Provide an initial partition of the network. + * + * @param clusterIds map from nodeId to clusterId, doesn't have to be complete + * @param hard If true, the provided clusters will not be splitted. This reduces the + * effective network size during the optimization phase but the hard partitions are + * after that replaced by the original nodes. + */ + InfomapBase& initPartition(const std::map& clusterIds, bool hard = false); + + /** + * Provide an initial partition of the network. + * + * @param clusters Each sub-vector contain node IDs for all nodes that should be merged. + * @param hard If true, the provided clusters will not be splitted. This reduces the + * effective network size during the optimization phase but the hard partitions are + * after that replaced by the original nodes. + */ + InfomapBase& initPartition(std::vector>& clusters, bool hard = false); + + /** + * Provide an initial partition of the network. + * + * @param modules Module indices for each node + */ + InfomapBase& initPartition(std::vector& modules, bool hard = false); + + /** + * Provide an initial hierarchical partition of the network + * + * @param tree A tree path for each node + */ + InfomapBase& initTree(const NodePaths& tree); + + void init(); + + void runPartition() + { + if (twoLevel) + partition(); + else + hierarchicalPartition(); + } + + void restoreHardPartition(); + + void writeResult(int trial = -1); + + // =================================================== + // runPartition: * + // =================================================== + + void hierarchicalPartition(); + + void partition(); + + // =================================================== + // runPartition: init: * + // =================================================== + + /** + * Done in network? + */ + void initEnterExitFlow(); + + void aggregateFlowValuesFromLeafToRoot(); + + // Init terms that is constant for the whole network + void initTree() { return m_optimizer->initTree(); } + + void initNetwork() { return m_optimizer->initNetwork(); } + + void initSuperNetwork() { return m_optimizer->initSuperNetwork(); } + + double calcCodelength(const InfoNode& parent) const { return m_optimizer->calcCodelength(parent); } + + /** + * Calculate and store codelength on all modules in the tree + * @param includeRoot Also calculate the codelength on the root node + * @return the hierarchical codelength + */ + double calcCodelengthOnTree(InfoNode& root, bool includeRoot = true) const; + + // =================================================== + // Run: Partition: * + // =================================================== + + void setActiveNetworkFromLeafs() { m_activeNetwork = &m_leafNodes; } + + void setActiveNetworkFromChildrenOfRoot(); + + void initPartition() { return m_optimizer->initPartition(); } + + void findTopModulesRepeatedly(unsigned int maxLevels); + + unsigned int fineTune(); + + unsigned int coarseTune(); + + /** + * Return the number of effective core loops, i.e. not the last if not at coreLoopLimit + */ + unsigned int optimizeActiveNetwork() { return m_optimizer->optimizeActiveNetwork(); } + + void moveActiveNodesToPredefinedModules(std::vector& modules) + { + return m_optimizer->moveActiveNodesToPredefinedModules(modules); + } + + void consolidateModules(bool replaceExistingModules = true) + { + return m_optimizer->consolidateModules(replaceExistingModules); + } + + unsigned int calculateNumNonTrivialTopModules() const; + + unsigned int calculateMaxDepth() const; + + // =================================================== + // Partition: findTopModulesRepeatedly: * + // =================================================== + + /** + * Return true if restored to consolidated optimization state + */ + bool restoreConsolidatedOptimizationPointIfNoImprovement(bool forceRestore = false) + { + return m_optimizer->restoreConsolidatedOptimizationPointIfNoImprovement(forceRestore); + } + + // =================================================== + // Run: Hierarchical Partition: * + // =================================================== + + /** + * Find super modules applying the whole two-level algorithm on the + * top modules iteratively + * @param levelLimit The maximum number of super module levels allowed + * @return number of levels created + */ + unsigned int findHierarchicalSuperModules(unsigned int superLevelLimit = std::numeric_limits::max()); + + /** + * Find super modules fast by merge and consolidate top modules iteratively + * @param levelLimit The maximum number of super module levels allowed + * @return number of levels created + */ + unsigned int findHierarchicalSuperModulesFast(unsigned int superLevelLimit = std::numeric_limits::max()); + + void transformNodeFlowToEnterFlow(InfoNode& parent); + + void resetFlowOnModules(); + + unsigned int removeModules(); + + unsigned int removeSubModules(bool recalculateCodelengthOnTree); + + unsigned int recursivePartition(); + + void queueTopModules(PartitionQueue& partitionQueue); + + void queueLeafModules(PartitionQueue& partitionQueue); + + bool processPartitionQueue(PartitionQueue& queue, PartitionQueue& nextLevel) const; + +public: + // =================================================== + // Output: * + // =================================================== + + /** + * Write tree to a .tree file. + * @param filename the filename for the output file. If empty, use default + * based on output directory and input file name + * @param states if memory network, print the state-level network without merging physical nodes within modules + * @return the filename written to + */ + std::string writeTree(const std::string& filename = "", bool states = false) { return infomap::writeTree(*this, m_network, filename, states); } + + /** + * Write flow tree to a .ftree file. + * This is the same as a .tree file but appended with links aggregated + * within modules on all levels in the tree + * @param filename the filename for the output file. If empty, use default + * based on output directory and input file name + * @param states if memory network, print the state-level network without merging physical nodes within modules + * @return the filename written to + */ + std::string writeFlowTree(const std::string& filename = "", bool states = false) { return infomap::writeFlowTree(*this, m_network, filename, states); } + + /** + * Write Newick tree to a .tre file. + * @param filename the filename for the output file. If empty, use default + * based on output directory and input file name + * @param states if memory network, print the state-level network without merging physical nodes within modules + * @return the filename written to + */ + std::string writeNewickTree(const std::string& filename = "", bool states = false) { return infomap::writeNewickTree(*this, filename, states); } + + std::string writeJsonTree(const std::string& filename = "", bool states = false, bool writeLinks = false) { return infomap::writeJsonTree(*this, m_network, filename, states, writeLinks); } + + std::string writeCsvTree(const std::string& filename = "", bool states = false) { return infomap::writeCsvTree(*this, m_network, filename, states); } + + /** + * Write tree to a .clu file. + * @param filename the filename for the output file. If empty, use default + * based on output directory and input file name + * @param states if memory network, print the state-level network without merging physical nodes within modules + * @param moduleIndexLevel the depth from the root on which to advance module index. + * Value 1 (default) will give the module index on the coarsest level, 2 the level below and so on. + * Value -1 will give the module index for the lowest level, i.e. the finest modular structure. + * @return the filename written to + */ + std::string writeClu(const std::string& filename = "", bool states = false, int moduleIndexLevel = 1) { return infomap::writeClu(*this, m_network, filename, states, moduleIndexLevel); } + +private: + // =================================================== + // Debug: * + // =================================================== + + void printDebug() const { return m_optimizer->printDebug(); } + + // =================================================== + // Members + // =================================================== + +protected: + InfoNode m_root; + std::vector m_leafNodes; + std::vector m_moduleNodes; + std::vector* m_activeNetwork = nullptr; + + std::vector m_originalLeafNodes; + + Network m_network; + InitialPartition m_initialPartition = {}; // nodeId -> moduleId + + const unsigned int SUPER_LEVEL_ADDITION = 1 << 20; + bool m_isMain = true; + unsigned int m_subLevel = 0; + + bool m_calculateEnterExitFlow = false; + + double m_oneLevelCodelength = 0.0; + unsigned int m_numNonTrivialTopModules = 0; + unsigned int m_tuneIterationIndex = 0; + bool m_isCoarseTune = false; + unsigned int m_aggregationLevel = 0; + + double m_hierarchicalCodelength = 0.0; + std::vector m_codelengths; + double m_entropyRate = 0.0; + double m_maxEntropy = 0.0; + double m_maxFlow = 0.0; + + double m_sumDanglingFlow = 0.0; + + Date m_startDate; + Date m_endDate; + Stopwatch m_elapsedTime = Stopwatch(false); + std::string m_initialParameters; + std::string m_currentParameters; + + std::unique_ptr m_optimizer; +}; + +/** + * Print per level statistics + */ +unsigned int printPerLevelCodelength(const InfoNode& parent, std::ostream& out); + +void aggregatePerLevelCodelength(const InfoNode& parent, std::vector& perLevelStat, unsigned int level = 0); + +namespace detail { + + struct PerLevelStat { + double codelength() const { return indexLength + leafLength; } + + unsigned int numNodes() const { return numModules + numLeafNodes; } + + unsigned int numModules = 0; + unsigned int numLeafNodes = 0; + double indexLength = 0.0; + double leafLength = 0.0; + }; + + class PartitionQueue { + using PendingModule = InfoNode*; + + std::deque m_queue; + + public: + unsigned int level = 1; + unsigned int numNonTrivialModules = 0; + double flow = 0.0; + double nonTrivialFlow = 0.0; + bool skip = false; + double indexCodelength = 0.0; // Consolidated + double leafCodelength = 0.0; // Consolidated + double moduleCodelength = 0.0; // Left to improve on next level + + using size_t = std::deque::size_type; + + void swap(PartitionQueue& other) noexcept + { + std::swap(level, other.level); + std::swap(numNonTrivialModules, other.numNonTrivialModules); + std::swap(flow, other.flow); + std::swap(nonTrivialFlow, other.nonTrivialFlow); + std::swap(skip, other.skip); + std::swap(indexCodelength, other.indexCodelength); + std::swap(leafCodelength, other.leafCodelength); + std::swap(moduleCodelength, other.moduleCodelength); + m_queue.swap(other.m_queue); + } + + size_t size() const { return m_queue.size(); } + + void resize(size_t size) { m_queue.resize(size); } + + PendingModule& operator[](size_t i) { return m_queue[i]; } + }; + +} // namespace detail + +} // namespace infomap + +#endif // INFOMAP_BASE_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapConfig.h b/src/vendor/cigraph/vendor/infomap/src/core/InfomapConfig.h new file mode 100644 index 00000000000..e6ff0b898b8 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapConfig.h @@ -0,0 +1,137 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMAP_CONFIG_H_ +#define INFOMAP_CONFIG_H_ + +#include "../io/Config.h" +#include "../utils/Random.h" +#include "../utils/Log.h" +#include + +namespace infomap { + +template +class InfomapConfig : public Config { +public: + InfomapConfig() = default; + + InfomapConfig(const std::string& flags, bool isCli = false) : InfomapConfig(Config(flags, isCli)) { } + + InfomapConfig(const Config& conf) : Config(conf), m_rand(/* conf.seedToRandomNumberGenerator */) + { + Log::precision(conf.verboseNumberPrecision); + } + + virtual ~InfomapConfig() = default; + + InfomapConfig(const InfomapConfig&) = default; + InfomapConfig& operator=(const InfomapConfig&) = default; + InfomapConfig(InfomapConfig&&) noexcept = default; + InfomapConfig& operator=(InfomapConfig&&) noexcept = default; + +private: + Infomap& get() + { + return static_cast(*this); + } + +protected: + Random m_rand; + +public: + Config& getConfig() + { + return *this; + } + + const Config& getConfig() const + { + return *this; + } + + Infomap& setConfig(const Config& conf) + { + *this = conf; + /* m_rand.seed(conf.seedToRandomNumberGenerator); */ + Log::precision(conf.verboseNumberPrecision); + return get(); + } + + Infomap& setNonMainConfig(const Config& conf) + { + cloneAsNonMain(conf); + return get(); + } + + Infomap& setNumTrials(unsigned int N) + { + numTrials = N; + return get(); + } + + Infomap& setVerbosity(unsigned int level) + { + verbosity = level; + return get(); + } + + Infomap& setTwoLevel(bool value) + { + twoLevel = value; + return get(); + } + + Infomap& setTuneIterationLimit(unsigned int value) + { + tuneIterationLimit = value; + return get(); + } + + Infomap& setFastHierarchicalSolution(unsigned int level) + { + fastHierarchicalSolution = level; + return get(); + } + + Infomap& setOnlySuperModules(bool value) + { + onlySuperModules = value; + return get(); + } + + Infomap& setNoCoarseTune(bool value) + { + noCoarseTune = value; + return get(); + } + + Infomap& setNoInfomap(bool value = true) + { + noInfomap = value; + return get(); + } + + Infomap& setMarkovTime(double codeRate) + { + markovTime = codeRate; + return get(); + } + + Infomap& setDirected(bool value) + { + directed = value; + flowModel = directed ? FlowModel::directed : FlowModel::undirected; + return get(); + } +}; + +} // namespace infomap + +#endif // INFOMAP_CONFIG_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h new file mode 100644 index 00000000000..e534992556e --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h @@ -0,0 +1,764 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMAP_OPTIMIZER_H_ +#define INFOMAP_OPTIMIZER_H_ + +#include "InfomapOptimizerBase.h" +#include "InfomapBase.h" +#include "../utils/VectorMap.h" +#include "../utils/infomath.h" +#include "InfoNode.h" +#include "FlowData.h" + +#include +#include + +namespace infomap { + +template +class InfomapOptimizer : public InfomapOptimizerBase { + using FlowDataType = FlowData; + using DeltaFlowDataType = typename Objective::DeltaFlowDataType; + +public: + void init(InfomapBase* infomap) override + { + m_infomap = infomap; + m_objective.init(infomap->getConfig()); + this->setInterruptionHandler(infomap->getConfig().interruptionHandler); + } + + // =================================================== + // IO + // =================================================== + + std::ostream& toString(std::ostream& out) const override { return out << m_objective; } + + // =================================================== + // Getters + // =================================================== + + double getCodelength() const override { return m_objective.getCodelength(); } + + double getIndexCodelength() const override { return m_objective.getIndexCodelength(); } + + double getModuleCodelength() const override { return m_objective.getModuleCodelength(); } + + double getMetaCodelength(bool unweighted = false) const override; + +protected: + unsigned int numActiveModules() const override { return m_infomap->activeNetwork().size() - m_emptyModules.size(); } + + // =================================================== + // Run: Init: * + // =================================================== + + // Init terms that is constant for the whole network + void initTree() override; + + void initNetwork() override; + + void initSuperNetwork() override; + + double calcCodelength(const InfoNode& parent) const override { return m_objective.calcCodelength(parent); } + + // =================================================== + // Run: Partition: * + // =================================================== + + void initPartition() override; + + void moveActiveNodesToPredefinedModules(std::vector& modules) override; + + bool moveNodeToPredefinedModule(InfoNode& current, unsigned int module); + + unsigned int optimizeActiveNetwork() override; + + unsigned int tryMoveEachNodeIntoBestModule() override; + + unsigned int tryMoveEachNodeIntoBestModuleInParallel() override; + + void consolidateModules(bool replaceExistingModules = true) override; + + bool restoreConsolidatedOptimizationPointIfNoImprovement(bool forceRestore = false) override; + + // =================================================== + // Debug: * + // =================================================== + + void printDebug() override { m_objective.printDebug(); } + + // =================================================== + // Protected members + // =================================================== + + InfomapBase* m_infomap = nullptr; + Objective m_objective; + Objective m_consolidatedObjective; + std::vector m_moduleFlowData; + std::vector m_moduleMembers; + std::vector m_emptyModules; +}; + +// =================================================== +// Getters +// =================================================== + +template <> +inline double InfomapOptimizer::getMetaCodelength(bool unweighted) const +{ + return m_objective.getMetaCodelength(unweighted); +} + +template +inline double InfomapOptimizer::getMetaCodelength(bool /*unweighted*/) const +{ + return 0.0; +} + +// =================================================== +// Run: Init: * +// =================================================== + +template +inline void InfomapOptimizer::initTree() +{ + Log(4) << "InfomapOptimizer::initTree()...\n"; + m_objective.initTree(m_infomap->root()); +} + +template +inline void InfomapOptimizer::initNetwork() +{ + Log(4) << "InfomapOptimizer::initNetwork()...\n"; + m_objective.initNetwork(m_infomap->root()); + + if (!m_infomap->isMainInfomap()) + m_objective.initSubNetwork(m_infomap->root()); // TODO: Already called in initNetwork? +} + +template +inline void InfomapOptimizer::initSuperNetwork() +{ + Log(4) << "InfomapOptimizer::initSuperNetwork()...\n"; + m_objective.initSuperNetwork(m_infomap->root()); +} + +// =================================================== +// Run: Partition: * +// =================================================== + +template +void InfomapOptimizer::initPartition() +{ + auto& network = m_infomap->activeNetwork(); + Log(4) << "InfomapOptimizer::initPartition() with " << network.size() << " nodes...\n"; + + // Init one module for each node + auto numNodes = network.size(); + m_moduleFlowData.resize(numNodes); + m_moduleMembers.assign(numNodes, 1); + m_emptyModules.clear(); + m_emptyModules.reserve(numNodes); + + unsigned int i = 0; + for (auto& nodePtr : network) { + InfoNode& node = *nodePtr; + node.index = i; // Unique module index for each node + m_moduleFlowData[i] = node.data; + node.dirty = true; + ++i; + } + + m_objective.initPartition(network); +} + +template +void InfomapOptimizer::moveActiveNodesToPredefinedModules(std::vector& modules) +{ + auto& network = m_infomap->activeNetwork(); + auto numNodes = network.size(); + if (modules.size() != numNodes) + throw std::length_error("Size of predefined modules differ from size of active network."); + + for (unsigned int i = 0; i < numNodes; ++i) { + moveNodeToPredefinedModule(*network[i], modules[i]); + } +} + +template +bool InfomapOptimizer::moveNodeToPredefinedModule(InfoNode& current, unsigned int newModule) +{ + unsigned int oldM = current.index; + unsigned int newM = newModule; + + if (newM == oldM) { + return false; + } + + DeltaFlowDataType oldModuleDelta(oldM, 0.0, 0.0); + DeltaFlowDataType newModuleDelta(newM, 0.0, 0.0); + + // For all outlinks + for (auto& e : current.outEdges()) { + auto& edge = *e; + unsigned int otherModule = edge.target->index; + if (otherModule == oldM) { + oldModuleDelta.deltaExit += edge.data.flow; + } else if (otherModule == newM) { + newModuleDelta.deltaExit += edge.data.flow; + } + } + // For all inlinks + for (auto& e : current.inEdges()) { + auto& edge = *e; + unsigned int otherModule = edge.source->index; + if (otherModule == oldM) { + oldModuleDelta.deltaEnter += edge.data.flow; + } else if (otherModule == newM) { + newModuleDelta.deltaEnter += edge.data.flow; + } + } + + // For recorded teleportation + if (m_infomap->recordedTeleportation) { + auto& oldModuleFlowData = m_moduleFlowData[oldM]; + double deltaEnterOld = (oldModuleFlowData.teleportFlow - current.data.teleportFlow) * current.data.teleportWeight; + double deltaExitOld = current.data.teleportFlow * (oldModuleFlowData.teleportWeight - current.data.teleportWeight); + oldModuleDelta.deltaEnter += deltaEnterOld; + oldModuleDelta.deltaExit += deltaExitOld; + + auto& newModuleFlowData = m_moduleFlowData[newM]; + double deltaEnterNew = current.data.teleportFlow * newModuleFlowData.teleportWeight; + double deltaExitNew = newModuleFlowData.teleportFlow * current.data.teleportWeight; + newModuleDelta.deltaEnter += deltaEnterNew; + newModuleDelta.deltaExit += deltaExitNew; + } + // Update empty module vector + if (m_moduleMembers[newM] == 0) { + m_emptyModules.pop_back(); + } + if (m_moduleMembers[current.index] == 1) { + m_emptyModules.push_back(oldM); + } + + m_objective.updateCodelengthOnMovingNode(current, oldModuleDelta, newModuleDelta, m_moduleFlowData, m_moduleMembers); + + m_moduleMembers[oldM] -= 1; + m_moduleMembers[newM] += 1; + + current.index = newM; + return true; +} + +template +inline unsigned int InfomapOptimizer::optimizeActiveNetwork() +{ + unsigned int coreLoopCount = 0; + unsigned int numEffectiveLoops = 0; + double oldCodelength = m_objective.getCodelength(); + unsigned int loopLimit = m_infomap->coreLoopLimit; + unsigned int minRandLoop = 2; + if (loopLimit >= minRandLoop && m_infomap->randomizeCoreLoopLimit) + loopLimit = m_infomap->m_rand.randInt(minRandLoop, loopLimit); + if (m_infomap->m_aggregationLevel > 0 || m_infomap->m_isCoarseTune) { + loopLimit = 20; + } + + do { + ++coreLoopCount; + unsigned int numNodesMoved = m_infomap->innerParallelization + ? tryMoveEachNodeIntoBestModuleInParallel() + : tryMoveEachNodeIntoBestModule(); + // Break if not enough improvement + if (numNodesMoved == 0 || m_objective.getCodelength() >= oldCodelength - m_infomap->minimumCodelengthImprovement) + break; + ++numEffectiveLoops; + oldCodelength = m_objective.getCodelength(); + } while (coreLoopCount != loopLimit); + + return numEffectiveLoops; +} + +template +unsigned int InfomapOptimizer::tryMoveEachNodeIntoBestModule() +{ + // Get random enumeration of nodes + auto& network = m_infomap->activeNetwork(); + std::vector nodeEnumeration(network.size()); + m_infomap->m_rand.getRandomizedIndexVector(nodeEnumeration); + + auto numNodes = nodeEnumeration.size(); + unsigned int numMoved = 0; + + // Create map with module links + VectorMap deltaFlow(numNodes); + + for (unsigned int i = 0; i < numNodes; ++i) { + InfoNode& current = *network[nodeEnumeration[i]]; + + this->checkInterruption(); + + if (!current.dirty) + continue; + + // If other nodes have moved here, don't move away on first loop + if (m_moduleMembers[current.index] > 1 && m_infomap->isFirstLoop() && m_infomap->tuneIterationLimit != 1) + continue; + + // If no links connecting this node with other nodes, it won't move into others, + // and others won't move into this. TODO: Always best leave it alone? + // For memory networks, don't skip try move to same physical node! + + deltaFlow.startRound(); + + // For all outlinks + for (auto& e : current.outEdges()) { + auto& edge = *e; + InfoNode* neighbour = edge.target; + deltaFlow.add(neighbour->index, DeltaFlowDataType(neighbour->index, edge.data.flow, 0.0)); + } + // For all inlinks + for (auto& e : current.inEdges()) { + auto& edge = *e; + InfoNode* neighbour = edge.source; + deltaFlow.add(neighbour->index, DeltaFlowDataType(neighbour->index, 0.0, edge.data.flow)); + } + + // For not moving + deltaFlow.add(current.index, DeltaFlowDataType(current.index, 0.0, 0.0)); + DeltaFlowDataType& oldModuleDelta = deltaFlow[current.index]; + oldModuleDelta.module = current.index; // Make sure index is correct if created new + + // Option to move to empty module (if node not already alone) + if (m_moduleMembers[current.index] > 1 && !m_emptyModules.empty()) { + deltaFlow.add(m_emptyModules.back(), DeltaFlowDataType(m_emptyModules.back(), 0.0, 0.0)); + } + + // For memory networks + m_objective.addMemoryContributions(current, oldModuleDelta, deltaFlow); + + auto& moduleDeltaEnterExit = deltaFlow.values(); + unsigned int numModuleLinks = deltaFlow.size(); + + // For recorded teleportation + if (m_infomap->recordedTeleportation) { + for (unsigned int j = 0; j < numModuleLinks; ++j) { + auto& deltaEnterExit = moduleDeltaEnterExit[j]; + auto moduleIndex = deltaEnterExit.module; + if (moduleIndex == current.index) { + auto& oldModuleFlowData = m_moduleFlowData[moduleIndex]; + double deltaEnterOld = (oldModuleFlowData.teleportFlow - current.data.teleportFlow) * current.data.teleportWeight; + double deltaExitOld = current.data.teleportFlow * (oldModuleFlowData.teleportWeight - current.data.teleportWeight); + deltaFlow.add(moduleIndex, DeltaFlowDataType(moduleIndex, deltaExitOld, deltaEnterOld)); + } else { + auto& newModuleFlowData = m_moduleFlowData[moduleIndex]; + double deltaEnterNew = newModuleFlowData.teleportFlow * current.data.teleportWeight; + double deltaExitNew = current.data.teleportFlow * newModuleFlowData.teleportWeight; + deltaFlow.add(moduleIndex, DeltaFlowDataType(moduleIndex, deltaExitNew, deltaEnterNew)); + } + } + } + + // Randomize link order for optimized search + std::vector moduleEnumeration(numModuleLinks); + m_infomap->m_rand.getRandomizedIndexVector(moduleEnumeration); + + DeltaFlowDataType bestDeltaModule(oldModuleDelta); + double bestDeltaCodelength = 0.0; + DeltaFlowDataType strongestConnectedModule(oldModuleDelta); + double deltaCodelengthOnStrongestConnectedModule = 0.0; + + // Find the move that minimizes the description length + for (unsigned int k = 0; k < numModuleLinks; ++k) { + auto j = moduleEnumeration[k]; + unsigned int otherModule = moduleDeltaEnterExit[j].module; + if (otherModule != current.index) { + double deltaCodelength = m_objective.getDeltaCodelengthOnMovingNode(current, + oldModuleDelta, + moduleDeltaEnterExit[j], + m_moduleFlowData, + m_moduleMembers); + + if (deltaCodelength < bestDeltaCodelength - m_infomap->minimumSingleNodeCodelengthImprovement) { + bestDeltaModule = moduleDeltaEnterExit[j]; + bestDeltaCodelength = deltaCodelength; + } + + // Save strongest connected module to prefer if codelength improvement equal + if (moduleDeltaEnterExit[j].deltaExit > strongestConnectedModule.deltaExit) { + strongestConnectedModule = moduleDeltaEnterExit[j]; + deltaCodelengthOnStrongestConnectedModule = deltaCodelength; + } + } + } + + // Prefer strongest connected module if equal delta codelength + if (strongestConnectedModule.module != bestDeltaModule.module && deltaCodelengthOnStrongestConnectedModule <= bestDeltaCodelength + m_infomap->minimumSingleNodeCodelengthImprovement) { + bestDeltaModule = strongestConnectedModule; + } + + // Make best possible move + if (bestDeltaModule.module != current.index) { + unsigned int bestModuleIndex = bestDeltaModule.module; + // Update empty module vector + if (m_moduleMembers[bestModuleIndex] == 0) { + m_emptyModules.pop_back(); + } + if (m_moduleMembers[current.index] == 1) { + m_emptyModules.push_back(current.index); + } + + m_objective.updateCodelengthOnMovingNode(current, oldModuleDelta, bestDeltaModule, m_moduleFlowData, m_moduleMembers); + + m_moduleMembers[current.index] -= 1; + m_moduleMembers[bestModuleIndex] += 1; + + unsigned int oldModuleIndex = current.index; + current.index = bestModuleIndex; + + ++numMoved; + + InfoNode* nodeInOldModule = ¤t; + unsigned int numLinkedNodesInOldModule = 0; + // Mark neighbours as dirty + for (auto& e : current.outEdges()) { + e->target->dirty = true; + if (e->target->index == oldModuleIndex) { + nodeInOldModule = e->target; + ++numLinkedNodesInOldModule; + } + } + for (auto& e : current.inEdges()) { + e->source->dirty = true; + if (e->source->index == oldModuleIndex) { + nodeInOldModule = e->source; + ++numLinkedNodesInOldModule; + } + } + + // Move single connected nodes to same module + if (numLinkedNodesInOldModule == 1 && m_moduleMembers[oldModuleIndex] == 1) { + moveNodeToPredefinedModule(*nodeInOldModule, bestModuleIndex); + ++numMoved; + // Mark neighbours as dirty + if (nodeInOldModule->degree() > 1) { + for (auto& e : nodeInOldModule->outEdges()) + e->target->dirty = true; + for (auto& e : nodeInOldModule->inEdges()) + e->source->dirty = true; + } + } + } else { + current.dirty = false; + } + } + + return numMoved; +} + +/** + * Minimize the codelength by trying to move each node into best module, in parallel. + * + * For each node: + * 1. Calculate the change in codelength for a move to each of its neighbouring modules or to an empty module + * 2. Move to the one that reduces the codelength the most, if any. + * + * @return The number of nodes moved. + */ +template +unsigned int InfomapOptimizer::tryMoveEachNodeIntoBestModuleInParallel() +{ + // Get random enumeration of nodes + auto& network = m_infomap->activeNetwork(); + std::vector nodeEnumeration(network.size()); + m_infomap->m_rand.getRandomizedIndexVector(nodeEnumeration); + + auto numNodes = nodeEnumeration.size(); + unsigned int numMoved = 0; + unsigned int numInvalidMoves = 0; + +#pragma omp parallel for schedule(dynamic) // Use dynamic scheduling as some threads could end early + for (unsigned int i = 0; i < numNodes; ++i) { + // Pick nodes in random order + InfoNode& current = *network[nodeEnumeration[i]]; + + if (!current.dirty) + continue; + + // If other nodes have moved here, don't move away on first loop + if (m_moduleMembers[current.index] > 1 && m_infomap->isFirstLoop() && m_infomap->tuneIterationLimit != 1) + continue; + + // If no links connecting this node with other nodes, it won't move into others, + // and others won't move into this. TODO: Always best leave it alone? + // For memory networks, don't skip try move to same physical node! + + // Create map with module links + VectorMap deltaFlow(numNodes); + + // For all outlinks + for (auto& e : current.outEdges()) { + auto& edge = *e; + InfoNode* neighbour = edge.target; + deltaFlow.add(neighbour->index, DeltaFlowDataType(neighbour->index, edge.data.flow, 0.0)); + } + // For all inlinks + for (auto& e : current.inEdges()) { + auto& edge = *e; + InfoNode* neighbour = edge.source; + deltaFlow.add(neighbour->index, DeltaFlowDataType(neighbour->index, 0.0, edge.data.flow)); + } + + // For not moving + deltaFlow.add(current.index, DeltaFlowDataType(current.index, 0.0, 0.0)); + DeltaFlowDataType& oldModuleDelta = deltaFlow[current.index]; + oldModuleDelta.module = current.index; // Make sure index is correct if created new + + // Option to move to empty module (if node not already alone) + if (m_moduleMembers[current.index] > 1 && !m_emptyModules.empty()) { + // deltaFlow[m_emptyModules.back()] += DeltaFlowDataType(m_emptyModules.back(), 0.0, 0.0); + deltaFlow.add(m_emptyModules.back(), DeltaFlowDataType(m_emptyModules.back(), 0.0, 0.0)); + } + + // For memory networks + m_objective.addMemoryContributions(current, oldModuleDelta, deltaFlow); + + auto& moduleDeltaEnterExit = deltaFlow.values(); + unsigned int numModuleLinks = deltaFlow.size(); + + // Randomize link order for optimized search + if (numModuleLinks > 2) { + for (unsigned int j = 0; j < numModuleLinks - 2; ++j) { + unsigned int randPos = m_infomap->m_rand.randInt(j + 1, numModuleLinks - 1); + swap(moduleDeltaEnterExit[j], moduleDeltaEnterExit[randPos]); + } + } + + DeltaFlowDataType bestDeltaModule(oldModuleDelta); + double bestDeltaCodelength = 0.0; + DeltaFlowDataType strongestConnectedModule(oldModuleDelta); + double deltaCodelengthOnStrongestConnectedModule = 0.0; + + // Find the move that minimizes the description length + for (unsigned int j = 0; j < deltaFlow.size(); ++j) { + unsigned int otherModule = moduleDeltaEnterExit[j].module; + if (otherModule != current.index) { + double deltaCodelength = m_objective.getDeltaCodelengthOnMovingNode(current, + oldModuleDelta, + moduleDeltaEnterExit[j], + m_moduleFlowData, + m_moduleMembers); + + if (deltaCodelength < bestDeltaCodelength - m_infomap->minimumSingleNodeCodelengthImprovement) { + bestDeltaModule = moduleDeltaEnterExit[j]; + bestDeltaCodelength = deltaCodelength; + } + + // Save strongest connected module to prefer if codelength improvement equal + if (moduleDeltaEnterExit[j].deltaExit > strongestConnectedModule.deltaExit) { + strongestConnectedModule = moduleDeltaEnterExit[j]; + deltaCodelengthOnStrongestConnectedModule = deltaCodelength; + } + } + } + + // Prefer strongest connected module if equal delta codelength + if (strongestConnectedModule.module != bestDeltaModule.module && deltaCodelengthOnStrongestConnectedModule <= bestDeltaCodelength + m_infomap->minimumSingleNodeCodelengthImprovement) { + bestDeltaModule = strongestConnectedModule; + } + + // Make best possible move + if (bestDeltaModule.module == current.index) { + current.dirty = false; + continue; + } else { +#pragma omp critical(moveUpdate) + { + unsigned int bestModuleIndex = bestDeltaModule.module; + unsigned int oldModuleIndex = current.index; + + bool validMove = bestModuleIndex == m_emptyModules.back() + // Check validity of move to empty target + ? m_moduleMembers[oldModuleIndex] > 1 && !m_emptyModules.empty() + // Not valid if the best module is empty now but not when decided + : m_moduleMembers[bestModuleIndex] > 0; + + if (validMove) { + // Recalculate delta codelength for proposed move to see if still an improvement + oldModuleDelta = DeltaFlowDataType(oldModuleIndex, 0.0, 0.0); + DeltaFlowDataType newModuleDelta(bestModuleIndex, 0.0, 0.0); + + // For all outlinks + for (auto& e : current.outEdges()) { + auto& edge = *e; + unsigned int otherModule = edge.target->index; + if (otherModule == oldModuleIndex) + oldModuleDelta.deltaExit += edge.data.flow; + else if (otherModule == bestModuleIndex) + newModuleDelta.deltaExit += edge.data.flow; + } + // For all inlinks + for (auto& e : current.inEdges()) { + auto& edge = *e; + unsigned int otherModule = edge.source->index; + if (otherModule == oldModuleIndex) + oldModuleDelta.deltaEnter += edge.data.flow; + else if (otherModule == bestModuleIndex) + newModuleDelta.deltaEnter += edge.data.flow; + } + + // For memory networks + m_objective.addMemoryContributions(current, oldModuleDelta, deltaFlow); + + double deltaCodelength = m_objective.getDeltaCodelengthOnMovingNode(current, + oldModuleDelta, + newModuleDelta, + m_moduleFlowData, + m_moduleMembers); + + if (deltaCodelength < 0.0 - m_infomap->minimumSingleNodeCodelengthImprovement) { + // Update empty module vector + if (m_moduleMembers[bestModuleIndex] == 0) { + m_emptyModules.pop_back(); + } + if (m_moduleMembers[oldModuleIndex] == 1) { + m_emptyModules.push_back(oldModuleIndex); + } + + m_objective.updateCodelengthOnMovingNode(current, oldModuleDelta, bestDeltaModule, m_moduleFlowData, m_moduleMembers); + + m_moduleMembers[oldModuleIndex] -= 1; + m_moduleMembers[bestModuleIndex] += 1; + + current.index = bestModuleIndex; + + ++numMoved; + + // Mark neighbours as dirty + for (auto& e : current.outEdges()) + e->target->dirty = true; + for (auto& e : current.inEdges()) + e->source->dirty = true; + } else { + ++numInvalidMoves; + } + } else { + ++numInvalidMoves; + } + } + } + } + + return numMoved + numInvalidMoves; +} + +template +inline void InfomapOptimizer::consolidateModules(bool replaceExistingModules) +{ + auto& network = m_infomap->activeNetwork(); + auto numNodes = network.size(); + std::vector modules(numNodes, nullptr); + + InfoNode& firstActiveNode = *network[0]; + auto level = firstActiveNode.depth(); + auto leafLevel = m_infomap->numLevels(); + + if (leafLevel == 1) + replaceExistingModules = false; + + // Release children pointers on current parent(s) to put new modules between + for (auto& n : network) { + n->parent->releaseChildren(); // Safe to call multiple times + } + + // Create the new module nodes and re-parent the active network from its common parent to the new module level + for (unsigned int i = 0; i < numNodes; ++i) { + InfoNode* node = network[i]; + unsigned int moduleIndex = node->index; + if (modules[moduleIndex] == nullptr) { + modules[moduleIndex] = new InfoNode(m_moduleFlowData[moduleIndex]); + modules[moduleIndex]->index = moduleIndex; + node->parent->addChild(modules[moduleIndex]); + } + modules[moduleIndex]->addChild(node); + } + + using NodePair = std::pair; + using EdgeMap = std::map; + EdgeMap moduleLinks; + + for (auto& node : network) { + unsigned int module1 = node->index; + for (auto& e : node->outEdges()) { + InfoEdge& edge = *e; + unsigned int module2 = edge.target->index; + if (module1 != module2) { + // Use new variables to not swap module1 + unsigned int m1 = module1, m2 = module2; + // If undirected, the order may be swapped to aggregate the edge on an opposite one + if (m_infomap->isUndirectedClustering() && m1 > m2) + std::swap(m1, m2); + auto ret = moduleLinks.insert(std::make_pair(NodePair(m1, m2), edge.data.flow)); + if (!ret.second) { + ret.first->second += edge.data.flow; + } + } + } + } + + // Add the aggregated edge flow structure to the new modules + for (auto& e : moduleLinks) { + const auto& nodePair = e.first; + modules[nodePair.first]->addOutEdge(*modules[nodePair.second], 0.0, e.second); + } + + if (replaceExistingModules) { + if (level == 1) { + Log(4) << "Consolidated super modules, removing old modules...\n"; + for (auto& node : network) + node->replaceWithChildren(); + } else if (level == 2) { + Log(4) << "Consolidated sub-modules, removing modules...\n"; + unsigned int moduleIndex = 0; + for (InfoNode& module : m_infomap->root()) { + // Store current modular structure on the sub-modules + for (auto& subModule : module) + subModule.index = moduleIndex; + ++moduleIndex; + } + m_infomap->root().replaceChildrenWithGrandChildren(); + } + } + + // Calculate the number of non-trivial modules + m_infomap->m_numNonTrivialTopModules = 0; + for (auto& module : m_infomap->root()) { + if (module.childDegree() != 1) + ++m_infomap->m_numNonTrivialTopModules; + } + + m_objective.consolidateModules(modules); + m_consolidatedObjective = m_objective; +} + +template +inline bool InfomapOptimizer::restoreConsolidatedOptimizationPointIfNoImprovement(bool forceRestore) +{ + if (forceRestore || m_objective.getCodelength() >= m_consolidatedObjective.getCodelength() - m_infomap->minimumSingleNodeCodelengthImprovement) { + m_objective = m_consolidatedObjective; + return true; + } + return false; +} + +} /* namespace infomap */ + +#endif // INFOMAP_OPTIMIZER_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h new file mode 100644 index 00000000000..7d89262bdb9 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h @@ -0,0 +1,111 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMAP_OPTIMIZER_BASE_H_ +#define INFOMAP_OPTIMIZER_BASE_H_ + +#include "InfomapBase.h" +#include "InfoNode.h" +#include "FlowData.h" +#include + +namespace infomap { + +class InfomapOptimizerBase { + friend class InfomapBase; + using FlowDataType = FlowData; + +public: + InfomapOptimizerBase() = default; + + virtual ~InfomapOptimizerBase() = default; + + virtual void init(InfomapBase* infomap) = 0; + + // =================================================== + // IO + // =================================================== + + virtual std::ostream& toString(std::ostream& out) const = 0; + + // =================================================== + // Getters + // =================================================== + + virtual double getCodelength() const = 0; + + virtual double getIndexCodelength() const = 0; + + virtual double getModuleCodelength() const = 0; + + virtual double getMetaCodelength(bool /*unweighted*/ = false) const { return 0.0; } + + void setInterruptionHandler(interruptionHandlerFn *interruptionHandler) { + this->interruptionHandler = interruptionHandler; + } + +protected: + virtual unsigned int numActiveModules() const = 0; + + void checkInterruption() { + if (interruptionHandler) { + if (interruptionHandler()) { + throw infomap::InterruptException(); + } + } + } + + // =================================================== + // Run: Init: * + // =================================================== + + // Init terms that is constant for the whole network + virtual void initTree() = 0; + + virtual void initNetwork() = 0; + + virtual void initSuperNetwork() = 0; + + virtual double calcCodelength(const InfoNode& parent) const = 0; + + // =================================================== + // Run: Partition: * + // =================================================== + + virtual void initPartition() = 0; + + virtual void moveActiveNodesToPredefinedModules(std::vector& modules) = 0; + + virtual unsigned int optimizeActiveNetwork() = 0; + + virtual unsigned int tryMoveEachNodeIntoBestModule() = 0; + + // virtual unsigned int tryMoveEachNodeIntoBestModuleLocal() = 0; + + virtual unsigned int tryMoveEachNodeIntoBestModuleInParallel() = 0; + + virtual void consolidateModules(bool replaceExistingModules = true) = 0; + + virtual bool restoreConsolidatedOptimizationPointIfNoImprovement(bool forceRestore = false) = 0; + + // =================================================== + // Debug: * + // =================================================== + + virtual void printDebug() = 0; + +private: + + interruptionHandlerFn *interruptionHandler = NULL; + +}; + +} /* namespace infomap */ + +#endif // INFOMAP_OPTIMIZER_BASE_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h new file mode 100644 index 00000000000..64860f6244e --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h @@ -0,0 +1,337 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef MAPEQUATION_H_ +#define MAPEQUATION_H_ + +#include "../utils/infomath.h" +#include "../utils/convert.h" +#include "../io/Config.h" +#include "../utils/Log.h" +#include "../utils/VectorMap.h" +#include "InfoNode.h" +#include "FlowData.h" +#include +#include +#include + +namespace infomap { + +class InfoNode; + +template +class MapEquation { + using ME = MapEquation; + +public: + MapEquation() = default; + + MapEquation(const MapEquation& other) = default; + + MapEquation& operator=(const MapEquation& other) = default; + + MapEquation(MapEquation&& other) noexcept = default; + + MapEquation& operator=(MapEquation&& other) noexcept = default; + + virtual ~MapEquation() = default; + + // =================================================== + // Getters + // =================================================== + + virtual double getIndexCodelength() const { return indexCodelength; } + + virtual double getModuleCodelength() const { return moduleCodelength; } + + virtual double getCodelength() const { return codelength; } + + // =================================================== + // IO + // =================================================== + + virtual std::ostream& print(std::ostream& out) const + { + return out << indexCodelength << " + " << moduleCodelength << " = " << io::toPrecision(codelength); + } + + // =================================================== + // Init + // =================================================== + + virtual void init(const Config&) + { + Log(3) << "MapEquation::init()...\n"; + } + + virtual void initTree(InfoNode& /*root*/) = 0; + + virtual void initNetwork(InfoNode& root) + { + Log(3) << "MapEquation::initNetwork()...\n"; + + nodeFlow_log_nodeFlow = 0.0; + for (InfoNode& node : root) { + nodeFlow_log_nodeFlow += infomath::plogp(node.data.flow); + } + ME::initSubNetwork(root); + } + + virtual void initSuperNetwork(InfoNode& root) + { + Log(3) << "MapEquation::initSuperNetwork()...\n"; + + nodeFlow_log_nodeFlow = 0.0; + for (InfoNode& node : root) { + nodeFlow_log_nodeFlow += infomath::plogp(node.data.enterFlow); + } + } + + virtual void initSubNetwork(InfoNode& root) + { + exitNetworkFlow = root.data.exitFlow; + exitNetworkFlow_log_exitNetworkFlow = infomath::plogp(exitNetworkFlow); + } + + virtual void initPartition(std::vector& nodes) { ME::calculateCodelength(nodes); } + + // =================================================== + // Codelength + // =================================================== + + virtual double calcCodelength(const InfoNode& parent) const + { + return parent.isLeafModule() ? ME::calcCodelengthOnModuleOfLeafNodes(parent) : ME::calcCodelengthOnModuleOfModules(parent); + } + + virtual void addMemoryContributions(InfoNode& /*current*/, DeltaFlowDataType& /*oldModuleDelta*/, DeltaFlowDataType& /*newModuleDelta*/) { } + + virtual void addMemoryContributions(InfoNode& /*current*/, DeltaFlowDataType& /*oldModuleDelta*/, VectorMap& /*moduleDeltaFlow*/) { } + + virtual double getDeltaCodelengthOnMovingNode(InfoNode& current, + DeltaFlowDataType& oldModuleDelta, + DeltaFlowDataType& newModuleDelta, + std::vector& moduleFlowData, + std::vector& /*moduleMembers*/); + + // =================================================== + // Consolidation + // =================================================== + + virtual void updateCodelengthOnMovingNode(InfoNode& current, + DeltaFlowDataType& oldModuleDelta, + DeltaFlowDataType& newModuleDelta, + std::vector& moduleFlowData, + std::vector& /*moduleMembers*/); + + virtual void consolidateModules(std::vector& /*modules*/) = 0; + + // =================================================== + // Debug + // =================================================== + + virtual void printDebug() const + { + std::cout << "(enterFlow_log_enterFlow: " << enterFlow_log_enterFlow << ", " + << "enter_log_enter: " << enter_log_enter << ", " + << "exitNetworkFlow_log_exitNetworkFlow: " << exitNetworkFlow_log_exitNetworkFlow << ") "; + } + +protected: + // =================================================== + // Protected member functions + // =================================================== + + virtual double calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const; + + virtual double calcCodelengthOnModuleOfModules(const InfoNode& parent) const; + + virtual void calculateCodelength(std::vector& nodes) + { + ME::calculateCodelengthTerms(nodes); + ME::calculateCodelengthFromCodelengthTerms(); + } + + virtual void calculateCodelengthTerms(std::vector& nodes); + + virtual void calculateCodelengthFromCodelengthTerms() + { + indexCodelength = enterFlow_log_enterFlow - enter_log_enter - exitNetworkFlow_log_exitNetworkFlow; + moduleCodelength = -exit_log_exit + flow_log_flow - nodeFlow_log_nodeFlow; + codelength = indexCodelength + moduleCodelength; + } + +public: + // =================================================== + // Public member variables + // =================================================== + + double codelength = 0.0; + double indexCodelength = 0.0; + double moduleCodelength = 0.0; + +protected: + // =================================================== + // Protected member variables + // =================================================== + + double nodeFlow_log_nodeFlow = 0.0; // constant while the leaf network is the same + double flow_log_flow = 0.0; // node.(flow + exitFlow) + double exit_log_exit = 0.0; + double enter_log_enter = 0.0; + double enterFlow = 0.0; + double enterFlow_log_enterFlow = 0.0; + + // For hierarchical + double exitNetworkFlow = 0.0; + double exitNetworkFlow_log_exitNetworkFlow = 0.0; +}; + +template +double MapEquation::getDeltaCodelengthOnMovingNode(InfoNode& current, DeltaFlowDataType& oldModuleDelta, DeltaFlowDataType& newModuleDelta, std::vector& moduleFlowData, std::vector&) +{ + using infomath::plogp; + unsigned int oldModule = oldModuleDelta.module; + unsigned int newModule = newModuleDelta.module; + double deltaEnterExitOldModule = oldModuleDelta.deltaEnter + oldModuleDelta.deltaExit; + double deltaEnterExitNewModule = newModuleDelta.deltaEnter + newModuleDelta.deltaExit; + + double delta_enter = plogp(enterFlow + deltaEnterExitOldModule - deltaEnterExitNewModule) - enterFlow_log_enterFlow; + + double delta_enter_log_enter = -plogp(moduleFlowData[oldModule].enterFlow) + - plogp(moduleFlowData[newModule].enterFlow) + + plogp(moduleFlowData[oldModule].enterFlow - current.data.enterFlow + deltaEnterExitOldModule) + + plogp(moduleFlowData[newModule].enterFlow + current.data.enterFlow - deltaEnterExitNewModule); + + double delta_exit_log_exit = -plogp(moduleFlowData[oldModule].exitFlow) + - plogp(moduleFlowData[newModule].exitFlow) + + plogp(moduleFlowData[oldModule].exitFlow - current.data.exitFlow + deltaEnterExitOldModule) + + plogp(moduleFlowData[newModule].exitFlow + current.data.exitFlow - deltaEnterExitNewModule); + + double delta_flow_log_flow = -plogp(moduleFlowData[oldModule].exitFlow + moduleFlowData[oldModule].flow) + - plogp(moduleFlowData[newModule].exitFlow + moduleFlowData[newModule].flow) + + plogp(moduleFlowData[oldModule].exitFlow + moduleFlowData[oldModule].flow + - current.data.exitFlow - current.data.flow + deltaEnterExitOldModule) + + plogp(moduleFlowData[newModule].exitFlow + moduleFlowData[newModule].flow + + current.data.exitFlow + current.data.flow - deltaEnterExitNewModule); + + double deltaL = delta_enter - delta_enter_log_enter - delta_exit_log_exit + delta_flow_log_flow; + return deltaL; +} + +template +void MapEquation::updateCodelengthOnMovingNode(InfoNode& current, DeltaFlowDataType& oldModuleDelta, DeltaFlowDataType& newModuleDelta, std::vector& moduleFlowData, std::vector&) +{ + using infomath::plogp; + unsigned int oldModule = oldModuleDelta.module; + unsigned int newModule = newModuleDelta.module; + double deltaEnterExitOldModule = oldModuleDelta.deltaEnter + oldModuleDelta.deltaExit; + double deltaEnterExitNewModule = newModuleDelta.deltaEnter + newModuleDelta.deltaExit; + + enterFlow -= moduleFlowData[oldModule].enterFlow + moduleFlowData[newModule].enterFlow; + enter_log_enter -= plogp(moduleFlowData[oldModule].enterFlow) + plogp(moduleFlowData[newModule].enterFlow); + exit_log_exit -= plogp(moduleFlowData[oldModule].exitFlow) + plogp(moduleFlowData[newModule].exitFlow); + flow_log_flow -= plogp(moduleFlowData[oldModule].exitFlow + moduleFlowData[oldModule].flow) + plogp(moduleFlowData[newModule].exitFlow + moduleFlowData[newModule].flow); + + moduleFlowData[oldModule] -= current.data; + moduleFlowData[newModule] += current.data; + + moduleFlowData[oldModule].enterFlow += deltaEnterExitOldModule; + moduleFlowData[oldModule].exitFlow += deltaEnterExitOldModule; + moduleFlowData[newModule].enterFlow -= deltaEnterExitNewModule; + moduleFlowData[newModule].exitFlow -= deltaEnterExitNewModule; + + enterFlow += moduleFlowData[oldModule].enterFlow + moduleFlowData[newModule].enterFlow; + enter_log_enter += plogp(moduleFlowData[oldModule].enterFlow) + plogp(moduleFlowData[newModule].enterFlow); + exit_log_exit += plogp(moduleFlowData[oldModule].exitFlow) + plogp(moduleFlowData[newModule].exitFlow); + flow_log_flow += plogp(moduleFlowData[oldModule].exitFlow + moduleFlowData[oldModule].flow) + plogp(moduleFlowData[newModule].exitFlow + moduleFlowData[newModule].flow); + + enterFlow_log_enterFlow = plogp(enterFlow); + + indexCodelength = enterFlow_log_enterFlow - enter_log_enter - exitNetworkFlow_log_exitNetworkFlow; + moduleCodelength = -exit_log_exit + flow_log_flow - nodeFlow_log_nodeFlow; + codelength = indexCodelength + moduleCodelength; +} + +template +double MapEquation::calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const +{ + double parentFlow = parent.data.flow; + double parentExit = parent.data.exitFlow; + double totalParentFlow = parentFlow + parentExit; + if (totalParentFlow < 1e-16) + return 0.0; + + double indexLength = 0.0; + for (const auto& node : parent) { + indexLength -= infomath::plogp(node.data.flow / totalParentFlow); + } + indexLength -= infomath::plogp(parentExit / totalParentFlow); + + indexLength *= totalParentFlow; + + return indexLength; +} + +template +double MapEquation::calcCodelengthOnModuleOfModules(const InfoNode& parent) const +{ + double parentFlow = parent.data.flow; + double parentExit = parent.data.exitFlow; + if (parentFlow < 1e-16) + return 0.0; + + // H(x) = -xlog(x), T = q + SUM(p), q = exitFlow, p = enterFlow + // Normal format + // L = q * -log(q/T) + SUM(p * -log(p/T)) + // Compact format + // L = T * ( H(q/T) + SUM( H(p/T) ) ) + // Expanded format + // L = q * -log(q) - q * -log(T) + SUM( p * -log(p) - p * -log(T) ) + // = T * log(T) - q*log(q) - SUM( p*log(p) ) + // = -H(T) + H(q) + SUM(H(p)) + // As T is not known, use expanded format to avoid two loops + double sumEnter = 0.0; + double sumEnterLogEnter = 0.0; + for (const auto& node : parent) { + sumEnter += node.data.enterFlow; // rate of enter to finer level + sumEnterLogEnter += infomath::plogp(node.data.enterFlow); + } + // The possibilities from this module: Either exit to coarser level or enter one of its children + double totalCodewordUse = parentExit + sumEnter; + + return infomath::plogp(totalCodewordUse) - sumEnterLogEnter - infomath::plogp(parentExit); +} + +template +void MapEquation::calculateCodelengthTerms(std::vector& nodes) +{ + enter_log_enter = 0.0; + flow_log_flow = 0.0; + exit_log_exit = 0.0; + enterFlow = 0.0; + + // For each module + for (InfoNode* n : nodes) { + InfoNode& node = *n; + // own node/module codebook + flow_log_flow += infomath::plogp(node.data.flow + node.data.exitFlow); + + // use of index codebook + enter_log_enter += infomath::plogp(node.data.enterFlow); + exit_log_exit += infomath::plogp(node.data.exitFlow); + enterFlow += node.data.enterFlow; + } + enterFlow += exitNetworkFlow; + enterFlow_log_enterFlow = infomath::plogp(enterFlow); +} + +} // namespace infomap + +#endif // MAPEQUATION_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp new file mode 100644 index 00000000000..cc19e770af5 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp @@ -0,0 +1,449 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "MemMapEquation.h" +#include "FlowData.h" +#include "InfoNode.h" + +#include +#include +#include +#include +#include + +namespace infomap { + +// =================================================== +// IO +// =================================================== + +std::ostream& MemMapEquation::print(std::ostream& out) const +{ + return out << indexCodelength << " + " << moduleCodelength << " = " << io::toPrecision(codelength); +} + +std::ostream& operator<<(std::ostream& out, const MemMapEquation& mapEq) +{ + return mapEq.print(out); +} + +// =================================================== +// Init +// =================================================== + +void MemMapEquation::init(const Config& /*config*/) +{ + Log(3) << "MemMapEquation::init()...\n"; +} + +void MemMapEquation::initNetwork(InfoNode& root) +{ + initPhysicalNodes(root); +} + +void MemMapEquation::initSuperNetwork(InfoNode& /*root*/) +{ + // TODO: How use enterFlow instead of flow +} + +void MemMapEquation::initSubNetwork(InfoNode& /*root*/) +{ + // Base::initSubNetwork(root); +} + +void MemMapEquation::initPartition(std::vector& nodes) +{ + initPartitionOfPhysicalNodes(nodes); + + calculateCodelength(nodes); +} + +void MemMapEquation::initPhysicalNodes(InfoNode& root) +{ + bool notInitiatedOnRoot = root.physicalNodes.empty(); + if (notInitiatedOnRoot) { + // Assume leaf nodes directly under the root node + std::unordered_map physicalNodes; + unsigned int maxPhysicalId = 0; + unsigned int minPhysicalId = std::numeric_limits::max(); + for (auto it(root.begin_leaf_nodes()); !it.isEnd(); ++it) { + InfoNode& node = *it; + physicalNodes[node.physicalId] += node.data.flow; + minPhysicalId = std::min(minPhysicalId, node.physicalId); + maxPhysicalId = std::max(maxPhysicalId, node.physicalId); + } + + // Re-index physical nodes if necessary + std::map toZeroBasedIndex; + if (maxPhysicalId - minPhysicalId + 1 > m_numPhysicalNodes) { + unsigned int zeroBasedPhysicalId = 0; + for (const auto& physNode : physicalNodes) { + toZeroBasedIndex.insert(std::make_pair(physNode.first, zeroBasedPhysicalId++)); + } + } + + for (const auto& physNode : physicalNodes) { + unsigned int zeroBasedIndex = !toZeroBasedIndex.empty() ? toZeroBasedIndex[physNode.first] : (physNode.first - minPhysicalId); + root.physicalNodes.emplace_back(zeroBasedIndex, physNode.second); + } + } + auto firstLeafIt = root.begin_leaf_nodes(); + auto depth = firstLeafIt.depth(); + bool notInitiatedOnLeafNodes = firstLeafIt->physicalNodes.empty(); + if (notInitiatedOnLeafNodes) { + Log(3) << "MemMapEquation::initPhysicalNodesOnOriginalNetwork()...\n"; + std::set setOfPhysicalNodes; + unsigned int maxPhysicalId = 0; + unsigned int minPhysicalId = std::numeric_limits::max(); + for (auto it(root.begin_leaf_nodes()); !it.isEnd(); ++it) { + InfoNode& node = *it; + setOfPhysicalNodes.insert(node.physicalId); + maxPhysicalId = std::max(maxPhysicalId, node.physicalId); + minPhysicalId = std::min(minPhysicalId, node.physicalId); + } + + m_numPhysicalNodes = setOfPhysicalNodes.size(); + + // Re-index physical nodes if necessary + std::map toZeroBasedIndex; + if (maxPhysicalId - minPhysicalId + 1 > m_numPhysicalNodes) { + unsigned int zeroBasedPhysicalId = 0; + for (unsigned int physIndex : setOfPhysicalNodes) { + toZeroBasedIndex.insert(std::make_pair(physIndex, zeroBasedPhysicalId++)); + } + } + + for (auto it(root.begin_leaf_nodes()); !it.isEnd(); ++it) { + InfoNode& node = *it; + unsigned int zeroBasedIndex = !toZeroBasedIndex.empty() ? toZeroBasedIndex[node.physicalId] : (node.physicalId - minPhysicalId); + node.physicalNodes.emplace_back(zeroBasedIndex, node.data.flow); + } + + // If leaf nodes was not directly under root, make sure leaf modules have + // physical nodes defined also + if (depth > 1) { + for (auto it(root.begin_leaf_modules()); !it.isEnd(); ++it) { + InfoNode& module = *it; + std::map physToFlow; + for (auto& node : module) { + for (PhysData& physData : node.physicalNodes) { + physToFlow[physData.physNodeIndex] += physData.sumFlowFromM2Node; + } + } + for (auto& physFlow : physToFlow) { + module.physicalNodes.emplace_back(physFlow.first, physFlow.second); + } + } + } + } else { + // Either a sub-network (without modules) or the whole network with reconstructed tree + if (depth == 1) { + // new sub-network + Log(3) << "MemMapEquation::initPhysicalNodesOnSubNetwork()...\n"; + std::set setOfPhysicalNodes; + unsigned int maxPhysNodeIndex = 0; + unsigned int minPhysNodeIndex = std::numeric_limits::max(); + + // Collect all physical nodes in this sub network + for (InfoNode& node : root) { + for (PhysData& physData : node.physicalNodes) { + setOfPhysicalNodes.insert(physData.physNodeIndex); + maxPhysNodeIndex = std::max(maxPhysNodeIndex, physData.physNodeIndex); + minPhysNodeIndex = std::min(minPhysNodeIndex, physData.physNodeIndex); + } + } + + m_numPhysicalNodes = setOfPhysicalNodes.size(); + + // Re-index physical nodes if needed (not required when reconstructing tree) + if (maxPhysNodeIndex >= m_numPhysicalNodes) { + std::map toZeroBasedIndex; + if (maxPhysNodeIndex - minPhysNodeIndex + 1 > m_numPhysicalNodes) { + unsigned int zeroBasedPhysicalId = 0; + for (unsigned int physIndex : setOfPhysicalNodes) { + toZeroBasedIndex.insert(std::make_pair(physIndex, zeroBasedPhysicalId++)); + } + } + + for (InfoNode& node : root) { + for (PhysData& physData : node.physicalNodes) { + unsigned int zeroBasedIndex = !toZeroBasedIndex.empty() ? toZeroBasedIndex[physData.physNodeIndex] : (physData.physNodeIndex - minPhysNodeIndex); + physData.physNodeIndex = zeroBasedIndex; + } + } + } + } else { + // whole network with reconstructed tree + for (auto it(root.begin_leaf_modules()); !it.isEnd(); ++it) { + InfoNode& module = *it; + std::map physToFlow; + for (auto& node : module) { + for (PhysData& physData : node.physicalNodes) { + physToFlow[physData.physNodeIndex] += physData.sumFlowFromM2Node; + } + } + for (auto& physFlow : physToFlow) { + module.physicalNodes.emplace_back(physFlow.first, physFlow.second); + } + } + } + } +} + +void MemMapEquation::initPartitionOfPhysicalNodes(std::vector& nodes) +{ + Log(4) << "MemMapEquation::initPartitionOfPhysicalNodes()...\n"; + m_physToModuleToMemNodes.clear(); + m_physToModuleToMemNodes.resize(m_numPhysicalNodes); + + for (auto& n : nodes) { + InfoNode& node = *n; + unsigned int moduleIndex = node.index; // Assume unique module index for all nodes in this initiation phase + + for (PhysData& physData : node.physicalNodes) { + m_physToModuleToMemNodes[physData.physNodeIndex].insert(m_physToModuleToMemNodes[physData.physNodeIndex].end(), + std::make_pair(moduleIndex, MemNodeSet(1, physData.sumFlowFromM2Node))); + } + } + + m_memoryContributionsAdded = false; +} + +// =================================================== +// Codelength +// =================================================== + +void MemMapEquation::calculateCodelength(std::vector& nodes) +{ + calculateCodelengthTerms(nodes); + + calculateNodeFlow_log_nodeFlow(); + + calculateCodelengthFromCodelengthTerms(); +} + +void MemMapEquation::calculateNodeFlow_log_nodeFlow() +{ + nodeFlow_log_nodeFlow = 0.0; + for (unsigned int i = 0; i < m_numPhysicalNodes; ++i) { + const ModuleToMemNodes& moduleToMemNodes = m_physToModuleToMemNodes[i]; + for (const auto& moduleToMemNode : moduleToMemNodes) + nodeFlow_log_nodeFlow += infomath::plogp(moduleToMemNode.second.sumFlow); + } +} + +double MemMapEquation::calcCodelength(const InfoNode& parent) const +{ + if (parent.isLeafModule()) { + return calcCodelengthOnModuleOfLeafNodes(parent); + } + // Use first-order model on index codebook + return Base::calcCodelengthOnModuleOfModules(parent); +} + +double MemMapEquation::calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const +{ + if (parent.numPhysicalNodes() == 0) { + return Base::calcCodelength(parent); // Infomap root node + } + + // TODO: For ordinary networks, flow should be used instead of enter flow + // for leaf nodes, what about memory networks? sumFlowFromM2Node vs sumEnterFlowFromM2Node? + double parentFlow = parent.data.flow; + double parentExit = parent.data.exitFlow; + double totalParentFlow = parentFlow + parentExit; + if (totalParentFlow < 1e-16) + return 0.0; + + double indexLength = 0.0; + + for (const PhysData& physData : parent.physicalNodes) { + indexLength -= infomath::plogp(physData.sumFlowFromM2Node / totalParentFlow); + } + indexLength -= infomath::plogp(parentExit / totalParentFlow); + + indexLength *= totalParentFlow; + + return indexLength; +} + +void MemMapEquation::addMemoryContributions(InfoNode& current, + MemDeltaFlow& oldModuleDelta, + VectorMap& moduleDeltaFlow) +{ + // Overlapping modules + /* + * delta = old.first + new.first + old.second - new.second. + * Two cases: (p(x) = plogp(x)) + * Moving to a module that already have that physical node: (old: p1, p2, new p3, moving p2 -> old:p1, new p2,p3) + * Then old.second = new.second = plogp(physicalNodeSize) -> cancelation -> delta = p(p1) - p(p1+p2) + p(p2+p3) - p(p3) + * Moving to a module that not have that physical node: (old: p1, p2, new -, moving p2 -> old: p1, new: p2) + * Then new.first = new.second = 0 -> delta = p(p1) - p(p1+p2) + p(p2). + */ + auto& physicalNodes = current.physicalNodes; + unsigned int numPhysicalNodes = physicalNodes.size(); + for (unsigned int i = 0; i < numPhysicalNodes; ++i) { + PhysData& physData = physicalNodes[i]; + ModuleToMemNodes& moduleToMemNodes = m_physToModuleToMemNodes[physData.physNodeIndex]; + for (const auto& moduleToMemNode : moduleToMemNodes) { + unsigned int moduleIndex = moduleToMemNode.first; + auto& memNodeSet = moduleToMemNode.second; + if (moduleIndex == current.index) // From where the multiple assigned node is moved + { + double oldPhysFlow = memNodeSet.sumFlow; + double newPhysFlow = memNodeSet.sumFlow - physData.sumFlowFromM2Node; + oldModuleDelta.sumDeltaPlogpPhysFlow += infomath::plogp(newPhysFlow) - infomath::plogp(oldPhysFlow); + oldModuleDelta.sumPlogpPhysFlow += infomath::plogp(physData.sumFlowFromM2Node); + } else // To where the multiple assigned node is moved + { + double oldPhysFlow = memNodeSet.sumFlow; + double newPhysFlow = memNodeSet.sumFlow + physData.sumFlowFromM2Node; + + double sumDeltaPlogpPhysFlow = infomath::plogp(newPhysFlow) - infomath::plogp(oldPhysFlow); + double sumPlogpPhysFlow = infomath::plogp(physData.sumFlowFromM2Node); + moduleDeltaFlow.add(moduleIndex, MemDeltaFlow(moduleIndex, 0.0, 0.0, sumDeltaPlogpPhysFlow, sumPlogpPhysFlow)); + } + } + } + m_memoryContributionsAdded = true; +} + +double MemMapEquation::getDeltaCodelengthOnMovingNode(InfoNode& current, + MemDeltaFlow& oldModuleDelta, + MemDeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) +{ + double deltaL = Base::getDeltaCodelengthOnMovingNode(current, oldModuleDelta, newModuleDelta, moduleFlowData, moduleMembers); + + double delta_nodeFlow_log_nodeFlow = oldModuleDelta.sumDeltaPlogpPhysFlow + newModuleDelta.sumDeltaPlogpPhysFlow + oldModuleDelta.sumPlogpPhysFlow - newModuleDelta.sumPlogpPhysFlow; + + return deltaL - delta_nodeFlow_log_nodeFlow; +} + +// =================================================== +// Consolidation +// =================================================== + +void MemMapEquation::updateCodelengthOnMovingNode(InfoNode& current, + MemDeltaFlow& oldModuleDelta, + MemDeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) +{ + Base::updateCodelengthOnMovingNode(current, oldModuleDelta, newModuleDelta, moduleFlowData, moduleMembers); + if (m_memoryContributionsAdded) + updatePhysicalNodes(current, oldModuleDelta.module, newModuleDelta.module); + else + addMemoryContributionsAndUpdatePhysicalNodes(current, oldModuleDelta, newModuleDelta); + + double delta_nodeFlow_log_nodeFlow = oldModuleDelta.sumDeltaPlogpPhysFlow + newModuleDelta.sumDeltaPlogpPhysFlow + oldModuleDelta.sumPlogpPhysFlow - newModuleDelta.sumPlogpPhysFlow; + + nodeFlow_log_nodeFlow += delta_nodeFlow_log_nodeFlow; + moduleCodelength -= delta_nodeFlow_log_nodeFlow; + codelength -= delta_nodeFlow_log_nodeFlow; +} + +void MemMapEquation::updatePhysicalNodes(InfoNode& current, unsigned int oldModuleIndex, unsigned int bestModuleIndex) +{ + // For all multiple assigned nodes + for (const auto& physData : current.physicalNodes) { + ModuleToMemNodes& moduleToMemNodes = m_physToModuleToMemNodes[physData.physNodeIndex]; + + // Remove contribution to old module + auto overlapIt = moduleToMemNodes.find(oldModuleIndex); + if (overlapIt == moduleToMemNodes.end()) + throw std::length_error(io::Str() << "Couldn't find old module " << oldModuleIndex << " in physical node " << physData.physNodeIndex); + + MemNodeSet& oldMemNodeSet = overlapIt->second; + oldMemNodeSet.sumFlow -= physData.sumFlowFromM2Node; + if (--oldMemNodeSet.numMemNodes == 0) + moduleToMemNodes.erase(overlapIt); + + // Add contribution to new module + overlapIt = moduleToMemNodes.find(bestModuleIndex); + if (overlapIt == moduleToMemNodes.end()) { + moduleToMemNodes.insert(std::make_pair(bestModuleIndex, MemNodeSet(1, physData.sumFlowFromM2Node))); + } else { + MemNodeSet& newMemNodeSet = overlapIt->second; + ++newMemNodeSet.numMemNodes; + newMemNodeSet.sumFlow += physData.sumFlowFromM2Node; + } + } +} + +void MemMapEquation::addMemoryContributionsAndUpdatePhysicalNodes(InfoNode& current, MemDeltaFlow& oldModuleDelta, MemDeltaFlow& newModuleDelta) +{ + unsigned int oldModuleIndex = oldModuleDelta.module; + unsigned int bestModuleIndex = newModuleDelta.module; + + // For all multiple assigned nodes + for (const auto& physData : current.physicalNodes) { + ModuleToMemNodes& moduleToMemNodes = m_physToModuleToMemNodes[physData.physNodeIndex]; + + // Remove contribution to old module + auto overlapIt = moduleToMemNodes.find(oldModuleIndex); + if (overlapIt == moduleToMemNodes.end()) + throw std::length_error("Couldn't find old module among physical node assignments."); + + MemNodeSet& oldMemNodeSet = overlapIt->second; + double oldPhysFlow = oldMemNodeSet.sumFlow; + double newPhysFlow = oldMemNodeSet.sumFlow - physData.sumFlowFromM2Node; + oldModuleDelta.sumDeltaPlogpPhysFlow += infomath::plogp(newPhysFlow) - infomath::plogp(oldPhysFlow); + oldModuleDelta.sumPlogpPhysFlow += infomath::plogp(physData.sumFlowFromM2Node); + oldMemNodeSet.sumFlow -= physData.sumFlowFromM2Node; + if (--oldMemNodeSet.numMemNodes == 0) + moduleToMemNodes.erase(overlapIt); + + // Add contribution to new module + overlapIt = moduleToMemNodes.find(bestModuleIndex); + if (overlapIt == moduleToMemNodes.end()) { + moduleToMemNodes.insert(std::make_pair(bestModuleIndex, MemNodeSet(1, physData.sumFlowFromM2Node))); + oldPhysFlow = 0.0; + newPhysFlow = physData.sumFlowFromM2Node; + newModuleDelta.sumDeltaPlogpPhysFlow += infomath::plogp(newPhysFlow) - infomath::plogp(oldPhysFlow); + newModuleDelta.sumPlogpPhysFlow += infomath::plogp(physData.sumFlowFromM2Node); + } else { + MemNodeSet& newMemNodeSet = overlapIt->second; + oldPhysFlow = newMemNodeSet.sumFlow; + newPhysFlow = newMemNodeSet.sumFlow + physData.sumFlowFromM2Node; + newModuleDelta.sumDeltaPlogpPhysFlow += infomath::plogp(newPhysFlow) - infomath::plogp(oldPhysFlow); + newModuleDelta.sumPlogpPhysFlow += infomath::plogp(physData.sumFlowFromM2Node); + ++newMemNodeSet.numMemNodes; + newMemNodeSet.sumFlow += physData.sumFlowFromM2Node; + } + } +} + +void MemMapEquation::consolidateModules(std::vector& modules) +{ + std::map> validate; + + for (unsigned int i = 0; i < m_numPhysicalNodes; ++i) { + ModuleToMemNodes& modToMemNodes = m_physToModuleToMemNodes[i]; + for (const auto& modToMemNode : modToMemNodes) { + if (++validate[modToMemNode.first][i] > 1) + throw std::domain_error("[InfomapGreedy::consolidateModules] Error updating physical nodes: duplication error"); + + modules[modToMemNode.first]->physicalNodes.emplace_back(i, modToMemNode.second.sumFlow); + } + } +} + +// =================================================== +// Debug +// =================================================== + +void MemMapEquation::printDebug() const +{ + std::cout << "MemMapEquation::m_numPhysicalNodes: " << m_numPhysicalNodes << "\n"; + Base::printDebug(); +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h new file mode 100644 index 00000000000..b7a8d969407 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h @@ -0,0 +1,172 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef MEM_MAPEQUATION_H_ +#define MEM_MAPEQUATION_H_ + +#include "MapEquation.h" +#include "FlowData.h" +#include "../utils/Log.h" +#include +#include +#include +#include + +namespace infomap { + +class InfoNode; +struct MemNodeSet; + +class MemMapEquation : private MapEquation { + using Base = MapEquation; + +public: + using FlowDataType = FlowData; + using DeltaFlowDataType = MemDeltaFlow; + + // =================================================== + // Getters + // =================================================== + + using Base::getIndexCodelength; + + using Base::getModuleCodelength; + + using Base::getCodelength; + + // =================================================== + // IO + // =================================================== + + std::ostream& print(std::ostream& out) const override; + friend std::ostream& operator<<(std::ostream&, const MemMapEquation&); + + // =================================================== + // Init + // =================================================== + + void init(const Config& config) override; + + void initTree(InfoNode& /*root*/) override { } + + void initNetwork(InfoNode& root) override; + + void initSuperNetwork(InfoNode& root) override; + + void initSubNetwork(InfoNode& root) override; + + void initPartition(std::vector& nodes) override; + + // =================================================== + // Codelength + // =================================================== + + double calcCodelength(const InfoNode& parent) const override; + + void addMemoryContributions(InfoNode& current, MemDeltaFlow& oldModuleDelta, VectorMap& moduleDeltaFlow) override; + + double getDeltaCodelengthOnMovingNode(InfoNode& current, + MemDeltaFlow& oldModuleDelta, + MemDeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) override; + + // =================================================== + // Consolidation + // =================================================== + + void updateCodelengthOnMovingNode(InfoNode& current, + MemDeltaFlow& oldModuleDelta, + MemDeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) override; + + void consolidateModules(std::vector& modules) override; + + // =================================================== + // Debug + // =================================================== + + void printDebug() const override; + +private: + // =================================================== + // Private member functions + // =================================================== + double calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const override; + + // =================================================== + // Init + // =================================================== + + void initPhysicalNodes(InfoNode& root); + + void initPartitionOfPhysicalNodes(std::vector& nodes); + + // =================================================== + // Codelength + // =================================================== + + void calculateCodelength(std::vector& nodes) override; + + using Base::calculateCodelengthTerms; + + using Base::calculateCodelengthFromCodelengthTerms; + + void calculateNodeFlow_log_nodeFlow(); + + // =================================================== + // Consolidation + // =================================================== + + void updatePhysicalNodes(InfoNode& current, unsigned int oldModuleIndex, unsigned int bestModuleIndex); + + void addMemoryContributionsAndUpdatePhysicalNodes(InfoNode& current, MemDeltaFlow& oldModuleDelta, MemDeltaFlow& newModuleDelta); + +public: + // =================================================== + // Public member variables + // =================================================== + + using Base::codelength; + using Base::indexCodelength; + using Base::moduleCodelength; + +private: + // =================================================== + // Private member variables + // =================================================== + + using Base::enter_log_enter; + using Base::enterFlow; + using Base::enterFlow_log_enterFlow; + using Base::exit_log_exit; + using Base::flow_log_flow; // node.(flow + exitFlow) + using Base::nodeFlow_log_nodeFlow; // constant while the leaf network is the same + + // For hierarchical + using Base::exitNetworkFlow; + using Base::exitNetworkFlow_log_exitNetworkFlow; + + using ModuleToMemNodes = std::map; + + std::vector m_physToModuleToMemNodes; // vector[physicalNodeID] map + unsigned int m_numPhysicalNodes = 0; + bool m_memoryContributionsAdded = false; +}; + +struct MemNodeSet { + MemNodeSet(unsigned int numMemNodes, double sumFlow) : numMemNodes(numMemNodes), sumFlow(sumFlow) { } + unsigned int numMemNodes; // use counter to check for zero to avoid round-off errors in sumFlow + double sumFlow; +}; + +} // namespace infomap + +#endif // MEM_MAPEQUATION_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp new file mode 100644 index 00000000000..e19d931dcef --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp @@ -0,0 +1,269 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "MetaMapEquation.h" +#include "FlowData.h" +#include "InfoNode.h" + +#include +#include + +namespace infomap { + +double MetaMapEquation::getModuleCodelength() const +{ + return moduleCodelength + metaCodelength * metaDataRate; +} + +double MetaMapEquation::getCodelength() const +{ + return codelength + metaCodelength * metaDataRate; +} + +// =================================================== +// IO +// =================================================== + +std::ostream& MetaMapEquation::print(std::ostream& out) const +{ + return out << indexCodelength << " + " << moduleCodelength << " + " << metaCodelength << " = " << io::toPrecision(getCodelength()); +} + +std::ostream& operator<<(std::ostream& out, const MetaMapEquation& mapEq) +{ + return mapEq.print(out); +} + +// =================================================== +// Init +// =================================================== + +void MetaMapEquation::init(const Config& config) +{ + Log(3) << "MetaMapEquation::init()...\n"; + numMetaDataDimensions = config.numMetaDataDimensions; + metaDataRate = config.metaDataRate; + weightByFlow = !config.unweightedMetaData; +} + +void MetaMapEquation::initTree(InfoNode& root) +{ + Log(3) << "MetaMapEquation::initTree()...\n"; + initMetaNodes(root); +} + +void MetaMapEquation::initNetwork(InfoNode& root) +{ + Log(3) << "MetaMapEquation::initNetwork()...\n"; + Base::initNetwork(root); + m_unweightedNodeFlow = 1.0 / root.childDegree(); +} + +void MetaMapEquation::initPartition(std::vector& nodes) +{ + initPartitionOfMetaNodes(nodes); + calculateCodelength(nodes); +} + +void MetaMapEquation::initMetaNodes(InfoNode& root) +{ + bool notInitiated = root.firstChild->metaCollection.empty(); + if (notInitiated) { + Log(3) << "MetaMapEquation::initMetaNodes()...\n"; + + for (auto it = root.begin_post_depth_first(); !it.isEnd(); ++it) { + auto& node = *it; + if (node.isRoot()) { + break; + } + if (node.isLeaf()) { + if (!node.metaData.empty()) { + // TODO: Use flow here and move weightByFlow choice to metaCollection, using flowCount? + double flow = weightByFlow ? node.data.flow : m_unweightedNodeFlow; + node.parent->metaCollection.add(node.metaData[0], flow); + } else { + throw std::length_error("A node is missing meta data using MetaMapEquation"); + } + } else { + node.parent->metaCollection.add(node.metaCollection); + } + } + } +} + +void MetaMapEquation::initPartitionOfMetaNodes(std::vector& nodes) +{ + Log(4) << "MetaMapEquation::initPartitionOfMetaNodes()...\n"; + m_moduleToMetaCollection.clear(); + + for (auto& n : nodes) { + InfoNode& node = *n; + unsigned int moduleIndex = node.index; // Assume unique module index for all nodes in this initiation phase + if (node.metaCollection.empty()) { + if (!node.metaData.empty()) { + double flow = weightByFlow ? node.data.flow : m_unweightedNodeFlow; + node.metaCollection.add(node.metaData[0], flow); + } else + throw std::length_error("A node is missing meta data using MetaMapEquation"); + } + m_moduleToMetaCollection[moduleIndex] = node.metaCollection; + } +} + +// =================================================== +// Codelength +// =================================================== + +void MetaMapEquation::calculateCodelength(std::vector& nodes) +{ + calculateCodelengthTerms(nodes); + + calculateCodelengthFromCodelengthTerms(); + + metaCodelength = 0.0; + + // Treat each node as a single module + for (InfoNode* n : nodes) { + InfoNode& node = *n; + metaCodelength += node.metaCollection.calculateEntropy(); + } +} + +double MetaMapEquation::calcCodelength(const InfoNode& parent) const +{ + return parent.isLeafModule() ? calcCodelengthOnModuleOfLeafNodes(parent) : Base::calcCodelengthOnModuleOfModules(parent); +} + +double MetaMapEquation::calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const +{ + double indexLength = Base::calcCodelength(parent); + + // Meta addition + MetaCollection metaCollection; + for (const InfoNode& node : parent) { + if (!node.metaCollection.empty()) + metaCollection.add(node.metaCollection); + else + metaCollection.add(node.metaData[0], weightByFlow ? node.data.flow : m_unweightedNodeFlow); // TODO: Initiate to collection and use all dimensions + } + + double _metaCodelength = metaCollection.calculateEntropy(); + + return indexLength + metaDataRate * _metaCodelength; +} + +double MetaMapEquation::getDeltaCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) +{ + double deltaL = Base::getDeltaCodelengthOnMovingNode(current, oldModuleDelta, newModuleDelta, moduleFlowData, moduleMembers); + + double deltaMetaL = 0.0; + + unsigned int oldModuleIndex = oldModuleDelta.module; + unsigned int newModuleIndex = newModuleDelta.module; + + // Remove codelength of old and new module before changes + deltaMetaL -= getCurrentModuleMetaCodelength(oldModuleIndex, current, 0); + deltaMetaL -= getCurrentModuleMetaCodelength(newModuleIndex, current, 0); + // Add codelength of old module with current node removed + deltaMetaL += getCurrentModuleMetaCodelength(oldModuleIndex, current, -1); + // Add codelength of old module with current node added + deltaMetaL += getCurrentModuleMetaCodelength(newModuleIndex, current, 1); + + return deltaL + deltaMetaL * metaDataRate; +} + +double MetaMapEquation::getCurrentModuleMetaCodelength(unsigned int module, InfoNode& current, int addRemoveOrNothing) +{ + auto& currentMetaCollection = m_moduleToMetaCollection[module]; + + double moduleMetaCodelength = 0.0; + + if (addRemoveOrNothing == 0) { + moduleMetaCodelength = currentMetaCollection.calculateEntropy(); + } + // If add or remove, do the change, calculate new codelength and then undo the change + else if (addRemoveOrNothing == 1) { + currentMetaCollection.add(current.metaCollection); + moduleMetaCodelength = currentMetaCollection.calculateEntropy(); + currentMetaCollection.remove(current.metaCollection); + } else { + currentMetaCollection.remove(current.metaCollection); + moduleMetaCodelength = currentMetaCollection.calculateEntropy(); + currentMetaCollection.add(current.metaCollection); + } + + return moduleMetaCodelength; +} + +// =================================================== +// Consolidation +// =================================================== + +void MetaMapEquation::updateCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) +{ + Base::updateCodelengthOnMovingNode(current, oldModuleDelta, newModuleDelta, moduleFlowData, moduleMembers); + + double deltaMetaL = 0.0; + + unsigned int oldModuleIndex = oldModuleDelta.module; + unsigned int newModuleIndex = newModuleDelta.module; + + // Remove codelength of old and new module before changes + deltaMetaL -= getCurrentModuleMetaCodelength(oldModuleIndex, current, 0); + deltaMetaL -= getCurrentModuleMetaCodelength(newModuleIndex, current, 0); + + // Update meta data from moving node + updateMetaData(current, oldModuleIndex, newModuleIndex); + + // Add codelength of old and new module after changes + deltaMetaL += getCurrentModuleMetaCodelength(oldModuleIndex, current, 0); + deltaMetaL += getCurrentModuleMetaCodelength(newModuleIndex, current, 0); + + metaCodelength += deltaMetaL; +} + +void MetaMapEquation::updateMetaData(InfoNode& current, unsigned int oldModuleIndex, unsigned int bestModuleIndex) +{ + // Remove meta id from old module (can be a set of meta ids when moving submodules in coarse tune) + auto& oldMetaCollection = m_moduleToMetaCollection[oldModuleIndex]; + oldMetaCollection.remove(current.metaCollection); + + // Add meta id to new module + auto& newMetaCollection = m_moduleToMetaCollection[bestModuleIndex]; + newMetaCollection.add(current.metaCollection); +} + +void MetaMapEquation::consolidateModules(std::vector& modules) +{ + for (auto& module : modules) { + if (module == nullptr) + continue; + module->metaCollection = m_moduleToMetaCollection[module->index]; + } +} + +// =================================================== +// Debug +// =================================================== + +void MetaMapEquation::printDebug() const +{ + std::cout << "MetaMapEquation\n"; + Base::printDebug(); +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h new file mode 100644 index 00000000000..79b3bd4b104 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h @@ -0,0 +1,183 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef META_MAPEQUATION_H_ +#define META_MAPEQUATION_H_ + +#include "MapEquation.h" +#include "FlowData.h" +#include "../utils/Log.h" +#include "../utils/MetaCollection.h" +#include +#include +#include +#include + +namespace infomap { + +class InfoNode; + +class MetaMapEquation : private MapEquation<> { + using Base = MapEquation<>; + +public: + using FlowDataType = FlowData; + using DeltaFlowDataType = DeltaFlow; + + // =================================================== + // Getters + // =================================================== + + using Base::getIndexCodelength; + + double getModuleCodelength() const override; + + double getCodelength() const override; + + double getMetaCodelength(bool unweighted = false) const + { + return unweighted ? metaCodelength : metaDataRate * metaCodelength; + }; + + // =================================================== + // IO + // =================================================== + + std::ostream& print(std::ostream& out) const override; + friend std::ostream& operator<<(std::ostream&, const MetaMapEquation&); + + // =================================================== + // Init + // =================================================== + + void init(const Config& config) override; + + void initTree(InfoNode& root) override; + + void initNetwork(InfoNode& root) override; + + using Base::initSuperNetwork; + + using Base::initSubNetwork; + + void initPartition(std::vector& nodes) override; + + // =================================================== + // Codelength + // =================================================== + + double calcCodelength(const InfoNode& parent) const override; + + using Base::addMemoryContributions; + + double getDeltaCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) override; + + // =================================================== + // Consolidation + // =================================================== + + void updateCodelengthOnMovingNode(InfoNode& current, + DeltaFlow& oldModuleDelta, + DeltaFlow& newModuleDelta, + std::vector& moduleFlowData, + std::vector& moduleMembers) override; + + void consolidateModules(std::vector& modules) override; + + // =================================================== + // Debug + // =================================================== + + void printDebug() const override; + +private: + // =================================================== + // Private member functions + // =================================================== + double calcCodelengthOnModuleOfLeafNodes(const InfoNode& parent) const override; + + // =================================================== + // Init + // =================================================== + + void initMetaNodes(InfoNode& root); + + void initPartitionOfMetaNodes(std::vector& nodes); + + // =================================================== + // Codelength + // =================================================== + + void calculateCodelength(std::vector& nodes) override; + + using Base::calculateCodelengthTerms; + + using Base::calculateCodelengthFromCodelengthTerms; + + // =================================================== + // Consolidation + // =================================================== + + void updateMetaData(InfoNode& current, unsigned int oldModuleIndex, unsigned int bestModuleIndex); + +public: + // =================================================== + // Public member variables + // =================================================== + + using Base::codelength; + using Base::indexCodelength; + using Base::moduleCodelength; + +private: + // =================================================== + // Private member functions + // =================================================== + + /** + * Get meta codelength of module of current node + * @param addRemoveOrNothing +1, -1 or 0 to calculate codelength + * as if current node was added, removed or untouched in current module + */ + double getCurrentModuleMetaCodelength(unsigned int module, InfoNode& current, int addRemoveOrNothing); + + // =================================================== + // Private member variables + // =================================================== + + using Base::enter_log_enter; + using Base::enterFlow; + using Base::enterFlow_log_enterFlow; + using Base::exit_log_exit; + using Base::flow_log_flow; // node.(flow + exitFlow) + using Base::nodeFlow_log_nodeFlow; // constant while the leaf network is the same + + // For hierarchical + using Base::exitNetworkFlow; + using Base::exitNetworkFlow_log_exitNetworkFlow; + + // For meta data + using ModuleMetaMap = std::map; // moduleId -> (metaId -> count) + + ModuleMetaMap m_moduleToMetaCollection; + + unsigned int numMetaDataDimensions = 0; + double metaDataRate = 1.0; + bool weightByFlow = true; + double metaCodelength = 0.0; + double m_unweightedNodeFlow = 0.0; +}; + +} // namespace infomap + +#endif // META_MAPEQUATION_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.cpp b/src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.cpp new file mode 100644 index 00000000000..464428c1e16 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.cpp @@ -0,0 +1,329 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "StateNetwork.h" +#include "../utils/FlowCalculator.h" +#include "../utils/Log.h" +#include "../io/SafeFile.h" +#include +#include + +namespace infomap { + +std::pair StateNetwork::addStateNode(const StateNode& node) +{ + auto ret = m_nodes.insert(StateNetwork::NodeMap::value_type(node.id, node)); + if (ret.second) { + // If state node didn't exist, also create the associated physical node + addPhysicalNode(node.physicalId); + if (node.id != node.physicalId) { + m_haveMemoryInput = true; + } + } + return ret; +} + +std::pair StateNetwork::addStateNode(unsigned int id, unsigned int physId) +{ + m_higherOrderInputMethodCalled = true; + return addStateNode(StateNode(id, physId)); +} + +std::pair StateNetwork::addNode(unsigned int id) +{ + return addStateNode(StateNode(id)); +} + +std::pair StateNetwork::addNode(unsigned int id, double weight) +{ + auto ret = addNode(id); + auto& node = ret.first->second; + node.weight = weight; + return ret; +} + +std::pair StateNetwork::addNode(unsigned int id, std::string name) +{ + m_names[id] = std::move(name); + return addNode(id); +} + +std::pair StateNetwork::addNode(unsigned int id, std::string name, double weight) +{ + m_names[id] = std::move(name); + return addNode(id, weight); +} + +StateNetwork::PhysNode& StateNetwork::addPhysicalNode(unsigned int physId) +{ + auto& physNode = m_physNodes[physId]; + physNode.physId = physId; + m_sumNodeWeight += 1.0; + return physNode; +} + +StateNetwork::PhysNode& StateNetwork::addPhysicalNode(unsigned int physId, double weight) +{ + auto& physNode = addPhysicalNode(physId); + physNode.weight = weight; + m_sumNodeWeight += weight; + return physNode; +} + +StateNetwork::PhysNode& StateNetwork::addPhysicalNode(unsigned int physId, const std::string& name) +{ + auto& physNode = addPhysicalNode(physId); + m_names[physId] = name; + m_sumNodeWeight += 1.0; + return physNode; +} + +StateNetwork::PhysNode& StateNetwork::addPhysicalNode(unsigned int physId, double weight, const std::string& name) +{ + auto& physNode = addPhysicalNode(physId); + physNode.weight = weight; + m_sumNodeWeight += weight; + m_names[physId] = name; + return physNode; +} + +std::pair::iterator, bool> StateNetwork::addName(unsigned int id, const std::string& name) +{ + return m_names.insert(std::make_pair(id, name)); +} + +bool StateNetwork::addLink(unsigned int sourceId, unsigned int targetId, double weight) +{ + if (weight < m_config.weightThreshold || weight <= 0) { + ++m_numLinksIgnoredByWeightThreshold; + m_totalLinkWeightIgnored += weight; + return false; + } + m_totalLinkWeightAdded += weight; + + if (sourceId == targetId) { + ++m_numSelfLinksFound; + if (m_config.noSelfLinks) { + return false; + } + ++m_numSelfLinks; + m_sumSelfLinkWeight += weight; + } + + addNode(sourceId); + addNode(targetId); + + ++m_numLinks; + m_sumLinkWeight += weight; + + bool addedNewLink = true; + + // Aggregate link weights if they are defined more than once + auto& outLinks = m_nodeLinkMap[sourceId]; + if (outLinks.empty()) { + outLinks[targetId] = weight; + } else { + auto ret = outLinks.insert(std::make_pair(StateNode(targetId), LinkData(weight))); + auto& linkData = ret.first->second; + if (!ret.second) { + linkData.weight += weight; + ++m_numAggregatedLinks; + --m_numLinks; + addedNewLink = false; + } else { + linkData.weight = weight; + } + } + m_outWeights[sourceId] += weight; + return addedNewLink; +} + +bool StateNetwork::addLink(unsigned int sourceId, unsigned int targetId, unsigned long weight) +{ + return addLink(sourceId, targetId, static_cast(weight)); +} + +bool StateNetwork::removeLink(unsigned int sourceId, unsigned int targetId) +{ + auto itSource = m_nodeLinkMap.find(sourceId); + if (itSource == m_nodeLinkMap.end()) { + return false; + } + + auto& targetMap = itSource->second; + auto itTarget = targetMap.find(targetId); + + if (itTarget == targetMap.end()) { + return false; + } + + double weight = itTarget->second.weight; + + targetMap.erase(itTarget); + if (targetMap.empty()) { + m_nodeLinkMap.erase(itSource); + } else { + --m_numAggregatedLinks; + } + + --m_numLinks; + m_sumLinkWeight -= weight; + m_totalLinkWeightAdded -= weight; + + if (sourceId == targetId) { + --m_numSelfLinksFound; + --m_numSelfLinks; + m_sumSelfLinkWeight -= weight; + } + + m_outWeights[sourceId] -= weight; + + return true; +} + +bool StateNetwork::undirectedToDirected() +{ + // Collect links in separate data structure to not risk iterating newly added links + if (!m_config.isUndirectedFlow()) { + return false; + } + std::deque oppositeLinks; + for (auto& linkIt : m_nodeLinkMap) { + unsigned int sourceId = linkIt.first.id; + const auto& subLinks = linkIt.second; + for (auto& subIt : subLinks) { + unsigned int targetId = subIt.first.id; + if (targetId == sourceId) { + continue; // Self-links are treated as directed on undirected networks + } + double weight = subIt.second.weight; + oppositeLinks.emplace_back(targetId, sourceId, weight); + } + } + for (auto& link : oppositeLinks) { + addLink(link.source, link.target, link.weight); + } + return true; +} + +void StateNetwork::clearLinks() +{ + m_nodeLinkMap.clear(); +} + +void StateNetwork::clear() +{ + m_nodes.clear(); + m_nodeLinkMap.clear(); + m_physNodes.clear(); + m_outWeights.clear(); + m_names.clear(); + + m_haveDirectedInput = false; + m_haveMemoryInput = false; + m_numStateNodesFound = 0; + m_numLinks = 0; + m_numSelfLinksFound = 0; + m_sumLinkWeight = 0.0; + m_numSelfLinks = 0; + m_sumSelfLinkWeight = 0.0; + m_numAggregatedLinks = 0; + m_totalLinkWeightAdded = 0.0; + m_numLinksIgnoredByWeightThreshold = 0; + m_totalLinkWeightIgnored = 0.0; +} + +void StateNetwork::writeStateNetwork(const std::string& filename) const +{ + if (filename.empty()) + throw std::runtime_error("writeStateNetwork called with empty filename"); + + SafeOutFile outFile(filename); + + outFile << "# v" << INFOMAP_VERSION << "\n" + << "# ./Infomap " << m_config.parsedString << "\n"; + + if (!m_names.empty()) { + outFile << "*Vertices\n"; + for (auto& nameIt : m_names) { + auto& physId = nameIt.first; + auto& name = nameIt.second; + outFile << physId << " \"" << name << "\"\n"; + } + } + + outFile << "*States\n"; + outFile << "# stateId physicalId\n"; + for (const auto& nodeIt : nodes()) { + const auto& node = nodeIt.second; + outFile << node.id << " " << node.physicalId; + // Optional name + if (!node.name.empty()) + outFile << " \"" << node.name << "\""; + outFile << "\n"; + } + + outFile << "*Links\n"; + for (auto& linkIt : m_nodeLinkMap) { + for (auto& subIt : linkIt.second) { + outFile << linkIt.first.id << " " << subIt.first.id << " " << subIt.second.weight << "\n"; + } + } +} + +void StateNetwork::writePajekNetwork(const std::string& filename, bool printFlow) const +{ + if (filename.empty()) + throw std::runtime_error("writePajekNetwork called with empty filename"); + + SafeOutFile outFile(filename); + + outFile << "# v" << INFOMAP_VERSION << "\n" + << "# ./Infomap " << m_config.parsedString << "\n"; + if (haveMemoryInput()) + outFile << "# State network as physical network\n"; + + outFile << "*Vertices\n"; + outFile << "#id name " << (printFlow ? "flow" : "weight") << "\n"; + for (const auto& nodeIt : nodes()) { + const auto& node = nodeIt.second; + outFile << node.id << " \""; + // Name, default to id + const auto& nameIt = haveMemoryInput() ? m_names.end() : m_names.find(node.id); + if (nameIt != m_names.end()) + outFile << nameIt->second; + else + outFile << node.id; + outFile << "\" " << (printFlow ? node.flow : node.weight) << "\n"; + } + + outFile << (m_config.printAsUndirected() ? "*Edges" : "*Arcs") << "\n"; + outFile << "#source target " << (printFlow ? "flow" : "weight") << "\n"; + for (auto& linkIt : m_nodeLinkMap) { + for (auto& subIt : linkIt.second) { + auto& linkData = subIt.second; + outFile << linkIt.first.id << " " << subIt.first.id << " " << (printFlow ? linkData.flow : linkData.weight) << "\n"; + } + } +} + +std::pair StateNetwork::addStateNodeWithAutogeneratedId(unsigned int physId) +{ + // Keys sorted with std::less comparator, so last key is the largest + unsigned int stateId = m_nodes.empty() ? 0 : m_nodes.crbegin()->first + 1; + return addStateNode(stateId, physId); +} + +std::pair StateNetwork::addStateNodeWithDeterministicId(unsigned int physId, unsigned int layerId, unsigned int numLayersLog2) +{ + unsigned int stateId = physId << (numLayersLog2 + 1) | layerId; + return addStateNode(stateId, physId); +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.h b/src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.h new file mode 100644 index 00000000000..97b43084228 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/StateNetwork.h @@ -0,0 +1,216 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef STATE_NETWORK_H_ +#define STATE_NETWORK_H_ + +#include "../io/Config.h" +#include +#include +#include +#include +#include + +namespace infomap { + +class StateNetwork { +public: + struct StateNode { + unsigned int id = 0; + unsigned int physicalId = 0; + std::string name; + unsigned int layerId = 0; + double weight = 1.0; + double flow = 0.0; + double enterFlow = 0.0; + double exitFlow = 0.0; + double teleFlow = 0.0; + + StateNode(unsigned int id = 0) : id(id), physicalId(id) { } + + StateNode(unsigned int id, unsigned int physicalId) : id(id), physicalId(physicalId) { } + + StateNode(unsigned int id, unsigned int physicalId, std::string name) : id(id), physicalId(physicalId), name(std::move(name)) { } + + bool operator==(const StateNode& rhs) const { return id == rhs.id; } + bool operator!=(const StateNode& rhs) const { return id != rhs.id; } + bool operator<(const StateNode& rhs) const { return id < rhs.id; } + }; + + struct PhysNode { + unsigned int physId = 0; + double weight = 1.0; + PhysNode(unsigned int physId) : physId(physId) { } + PhysNode(unsigned int physId, double weight) : physId(physId), weight(weight) { } + PhysNode(double weight = 1.0) : weight(weight) { } + }; + + struct LinkData { + double weight = 1.0; + double flow = 0.0; + + LinkData(double weight = 1.0) : weight(weight) { } + + LinkData& operator+=(double w) + { + weight += w; + return *this; + } + }; + + struct StateLink { + StateLink(unsigned int sourceIndex = 0, unsigned int targetIndex = 0, double weight = 0.0) + : source(sourceIndex), + target(targetIndex), + weight(weight), + flow(weight) { } + + unsigned int source; + unsigned int target; + double weight; + double flow; + }; + + // Unique state id to state node + using NodeMap = std::map; + using OutLinkMap = std::map; + using NodeLinkMap = std::map; + +protected: + friend class FlowCalculator; + // Config + Config m_config; + // Network + bool m_haveDirectedInput = false; + bool m_haveMemoryInput = false; + bool m_higherOrderInputMethodCalled = false; + NodeMap m_nodes; // Nodes indexed by state id (equal physical id for first-order networks) + NodeLinkMap m_nodeLinkMap; + unsigned int m_numStateNodesFound = 0; + double m_sumNodeWeight = 0.0; + unsigned int m_numLinks = 0; + double m_sumLinkWeight = 0.0; + unsigned int m_numSelfLinksFound = 0; + unsigned int m_numSelfLinks = 0; + double m_sumSelfLinkWeight = 0.0; + unsigned int m_numAggregatedLinks = 0; + double m_totalLinkWeightAdded = 0.0; + unsigned int m_numLinksIgnoredByWeightThreshold = 0; + double m_totalLinkWeightIgnored = 0.0; + std::map m_outWeights; + bool m_haveNodeWeights = false; + bool m_haveStateNodeWeights = false; + bool m_haveFileInput = false; + // Attributes + std::map m_names; + std::map m_physNodes; + + // Bipartite + unsigned int m_bipartiteStartId = 0; + +public: + StateNetwork() : m_config(Config()) { } + StateNetwork(Config config) : m_config(std::move(config)) { } + virtual ~StateNetwork() = default; + + StateNetwork(const StateNetwork&) = delete; + StateNetwork& operator=(const StateNetwork&) = delete; + StateNetwork(StateNetwork&&) = delete; + StateNetwork& operator=(StateNetwork&&) = delete; + + // Config + void setConfig(const Config& config) { m_config = config; } + + // Mutators + std::pair addStateNode(const StateNode& node); + std::pair addStateNode(unsigned int id, unsigned int physId); + std::pair addNode(unsigned int id); + std::pair addNode(unsigned int id, std::string name); + std::pair addNode(unsigned int id, double weight); + std::pair addNode(unsigned int id, std::string, double weight); + PhysNode& addPhysicalNode(unsigned int physId); + PhysNode& addPhysicalNode(unsigned int physId, double weight); + PhysNode& addPhysicalNode(unsigned int physId, const std::string& name); + PhysNode& addPhysicalNode(unsigned int physId, double weight, const std::string& name); + std::pair::iterator, bool> addName(unsigned int id, const std::string&); + bool addLink(unsigned int sourceId, unsigned int targetId, double weight = 1.0); + bool addLink(unsigned int sourceId, unsigned int targetId, unsigned long weight); + + /** + * Remove link + * Note: It will not remove nodes if they become dangling + */ + bool removeLink(unsigned int sourceId, unsigned int targetId); + + // Expand each undirected link to two opposite directed links + bool undirectedToDirected(); + + /** + * Clear all network data and reset to default state. + */ + virtual void clear(); + + /** + * Clear link data but keep node data. + */ + virtual void clearLinks(); + + // Getters + const NodeMap& nodes() const { return m_nodes; } + unsigned int numNodes() const { return m_nodes.size(); } + unsigned int numPhysicalNodes() const { return m_physNodes.size(); } + double sumNodeWeight() const { return m_sumNodeWeight; } + const NodeLinkMap& nodeLinkMap() const { return m_nodeLinkMap; } + NodeLinkMap& nodeLinkMap() { return m_nodeLinkMap; } + unsigned int numLinks() const { return m_numLinks; } + double sumLinkWeight() const { return m_sumLinkWeight; } + unsigned int numSelfLinks() const { return m_numSelfLinks; } + double sumSelfLinkWeight() const { return m_sumSelfLinkWeight; } + // Use convention of counting self-links only once, treating them as directed + double sumWeightedDegree() const { return 2 * sumLinkWeight() - (m_config.isUndirectedFlow() ? sumSelfLinkWeight() : 0); } + unsigned int sumDegree() const { return 2 * numLinks() - (m_config.isUndirectedFlow() ? numSelfLinks() : 0); } + std::map& outWeights() { return m_outWeights; } + std::map& names() { return m_names; } + const std::map& names() const { return m_names; } + bool haveNodeWeights() const { return m_haveNodeWeights; } + bool haveStateNodeWeights() const { return m_haveStateNodeWeights; } + bool haveFileInput() const { return m_haveFileInput; } + + virtual const std::map>& metaData() const = 0; + + bool haveDirectedInput() const { return m_haveDirectedInput; } + bool haveMemoryInput() const { return m_haveMemoryInput; } + bool higherOrderInputMethodCalled() const { return m_higherOrderInputMethodCalled; } + // Bipartite + bool isBipartite() const { return m_bipartiteStartId > 0; } + unsigned int bipartiteStartId() const { return m_bipartiteStartId; } + void setBipartiteStartId(unsigned int value) { m_bipartiteStartId = value; } + + /** + * Write state network to file. + */ + void writeStateNetwork(const std::string& filename) const; + + /** + * Write state network as first-order Pajek network, where + * state nodes are treated as physical nodes. + * For a non-memory input, the state nodes are equivalent to + * physical nodes. + */ + void writePajekNetwork(const std::string& filename, bool printFlow = false) const; + +protected: + std::pair addStateNodeWithAutogeneratedId(unsigned int physId); + + std::pair addStateNodeWithDeterministicId(unsigned int physId, unsigned int layerId, unsigned int numLayersLog2); +}; + +} // namespace infomap + +#endif // STATE_NETWORK_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.cpp b/src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.cpp new file mode 100644 index 00000000000..433d9edd242 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.cpp @@ -0,0 +1,238 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "InfomapIterator.h" +#include "../InfoNode.h" +#include +#include // std::pair + +namespace infomap { + +InfomapIterator& InfomapIterator::operator++() noexcept +{ + const auto root = m_current->getInfomapRoot(); + auto current = root ? root : m_current; + + if (current->firstChild) { + current = current->firstChild; + ++m_depth; + m_path.push_back(1); + } else { + // Current node is a leaf + // Presupposes that the next pointer can't reach out from the current parent. + + bool tryNext = true; + + while (tryNext) { + tryNext = false; + + while (!current->next) { + if (current->owner) { + current = current->owner; + + if (current == m_root) { // Check if back to beginning + m_current = nullptr; + return *this; + } + + tryNext = true; + break; + } + if (current->parent) { + current = current->parent; + --m_depth; + m_path.pop_back(); + + if (current == m_root) { // Check if back to beginning + m_current = nullptr; + return *this; + } + } else { // null also if no children in first place + m_current = nullptr; + return *this; + } + } + } + + current = current->next; + + if (!current->isLeaf() && (static_cast(m_moduleIndexLevel) >= m_depth)) { + ++m_moduleIndex; + } + + ++m_path.back(); + } + + m_current = current; + return *this; +} + +double InfomapIterator::modularCentrality() const noexcept +{ + if (m_current->parent == nullptr) { + // The root node has no modular centrality + return 0.0; + } + + const auto p_m = m_current->parent->data.flow; + const auto p_u = m_current->data.flow; + const auto p_diff = p_m - p_u; + + if (p_diff > 0.0) { + return -p_diff * std::log2(p_diff / p_m); + } + + return 0.0; +} + +// ------------------------------------- +// InfomapModuleIterator +// ------------------------------------- + +InfomapIterator& InfomapModuleIterator::operator++() noexcept +{ + InfomapIterator::operator++(); + while (!isEnd() && m_current->isLeaf()) { + InfomapIterator::operator++(); + } + return *this; +} + +// ------------------------------------- +// InfomapLeafModuleIterator +// ------------------------------------- + +void InfomapLeafModuleIterator::init() noexcept +{ + while (!isEnd() && !m_current->isLeafModule()) { + InfomapIterator::operator++(); + } +} + +InfomapIterator& InfomapLeafModuleIterator::operator++() noexcept +{ + InfomapIterator::operator++(); + while (!isEnd() && !m_current->isLeafModule()) { + InfomapIterator::operator++(); + } + return *this; +} + +// ------------------------------------- +// InfomapLeafIterator +// ------------------------------------- + +void InfomapLeafIterator::init() noexcept +{ + while (!isEnd() && !m_current->isLeaf()) { + InfomapIterator::operator++(); + } +} + +InfomapIterator& InfomapLeafIterator::operator++() noexcept +{ + InfomapIterator::operator++(); + while (!isEnd() && !m_current->isLeaf()) { + InfomapIterator::operator++(); + } + return *this; +} + +// ------------------------------------- +// InfomapIteratorPhysical +// ------------------------------------- + +InfomapIterator& InfomapIteratorPhysical::operator++() noexcept +{ + if (m_physNodes.empty()) { + // Iterate modules + InfomapIterator::operator++(); + if (isEnd()) { + return *this; + } + if (m_current->isLeaf()) { + // Copy current iterator to restart after iterating through the leaf nodes + auto firstLeafIt = *this; + // If on a leaf node, loop through and aggregate to physical nodes + while (!isEnd() && m_current->isLeaf()) { + auto ret = m_physNodes.insert(std::make_pair(m_current->physicalId, InfoNode(*m_current))); + auto& physNode = ret.first->second; + if (ret.second) { + // New physical node, use same parent as the state leaf node + physNode.parent = m_current->parent; + } else { + // Not inserted, add flow to existing physical node + // TODO: If exitFlow should be correct, flow between memory nodes within same physical node should be subtracted. + physNode.data += m_current->data; + } + physNode.stateNodes.push_back(m_current->stateId); + InfomapIterator::operator++(); + } + // Store current iterator to continue with after iterating physical leaf nodes + m_oldIter = *this; + // Reset path/depth/moduleIndex to values for first leaf node + m_path = firstLeafIt.m_path; + m_depth = firstLeafIt.m_depth; + m_moduleIndex = firstLeafIt.m_moduleIndex; + // Set current node to the first physical node + m_physIter = m_physNodes.begin(); + m_current = &m_physIter->second; + } + } else { + // Iterate physical nodes instead of leaf state nodes + ++m_physIter; + ++m_path.back(); + if (m_physIter == m_physNodes.end()) { + // End of leaf nodes + m_physNodes.clear(); + m_path.pop_back(); + // reset iterator to the one after the leaf nodes + *this = m_oldIter; + } else { + // Set iterator node to the currently iterated physical node + m_current = &m_physIter->second; + } + } + return *this; +} + +// ------------------------------------- +// InfomapLeafIteratorPhysical +// ------------------------------------- + +void InfomapLeafIteratorPhysical::init() noexcept +{ + while (!isEnd() && !m_current->isLeaf()) { + InfomapIteratorPhysical::operator++(); + } +} + +InfomapIterator& InfomapLeafIteratorPhysical::operator++() noexcept +{ + InfomapIteratorPhysical::operator++(); + while (!isEnd() && !m_current->isLeaf()) { + InfomapIteratorPhysical::operator++(); + } + return *this; +} + +// ------------------------------------- +// InfomapParentIterator +// ------------------------------------- + +InfomapParentIterator& InfomapParentIterator::operator++() noexcept +{ + m_current = m_current->parent; + if (m_current != nullptr && m_current->owner != nullptr) { + m_current = m_current->owner; + } + return *this; +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.h b/src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.h new file mode 100644 index 00000000000..ac7f6d136db --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.h @@ -0,0 +1,341 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMAP_ITERATOR_H_ +#define INFOMAP_ITERATOR_H_ + +#include +#include +#include + +namespace infomap { + +class InfoNode; + +/** + * Pre processing depth first iterator that explores sub-Infomap instances + * Note: + * This iterator presupposes that the next pointer of a node can't reach a node with a different parent. + */ +struct InfomapIterator { +protected: + InfoNode* m_root = nullptr; + InfoNode* m_current = nullptr; + int m_moduleIndexLevel = -1; + unsigned int m_moduleIndex = 0; + std::deque m_path; // The tree path to current node (indexing starting from one!) + unsigned int m_depth = 0; + +public: + InfomapIterator() = default; + + InfomapIterator(InfoNode* nodePointer, int moduleIndexLevel = -1) + : m_root(nodePointer), m_current(nodePointer), m_moduleIndexLevel(moduleIndexLevel) { } + + virtual ~InfomapIterator() = default; + InfomapIterator(const InfomapIterator&) = default; + InfomapIterator& operator=(const InfomapIterator&) = default; + InfomapIterator(InfomapIterator&&) noexcept = default; + InfomapIterator& operator=(InfomapIterator&&) noexcept = default; + + InfoNode* current() noexcept { return m_current; } + + const InfoNode* current() const noexcept { return m_current; } + + InfoNode& operator*() noexcept { return *m_current; } + + const InfoNode& operator*() const noexcept { return *m_current; } + + InfoNode* operator->() noexcept { return m_current; } + + const InfoNode* operator->() const noexcept { return m_current; } + + bool operator==(const InfomapIterator& other) const noexcept { return m_current == other.m_current; } + + bool operator!=(const InfomapIterator& other) const noexcept { return m_current != other.m_current; } + + virtual InfomapIterator& operator++() noexcept; + + virtual InfomapIterator operator++(int) noexcept + { + InfomapIterator copy(*this); + ++(*this); + return copy; + } + + virtual InfomapIterator& stepForward() noexcept + { + ++(*this); + return *this; + } + + const std::deque& path() const noexcept { return m_path; } + + unsigned int moduleIndex() const noexcept { return m_moduleIndex; } + + unsigned int moduleId() const noexcept { return m_moduleIndex + 1; } + + unsigned int childIndex() const noexcept { return m_path.empty() ? 0 : m_path.back() - 1; } + + unsigned int depth() const noexcept { return m_depth; } + + double modularCentrality() const noexcept; + + bool isEnd() const noexcept { return m_current == nullptr; } +}; + +struct InfomapModuleIterator : public InfomapIterator { +public: + InfomapModuleIterator() : InfomapIterator() { } + + InfomapModuleIterator(InfoNode* nodePointer, int moduleIndexLevel = -1) : InfomapIterator(nodePointer, moduleIndexLevel) { } + + ~InfomapModuleIterator() override = default; + InfomapModuleIterator(const InfomapModuleIterator&) = default; + InfomapModuleIterator& operator=(const InfomapModuleIterator&) = default; + InfomapModuleIterator(InfomapModuleIterator&&) = default; + InfomapModuleIterator& operator=(InfomapModuleIterator&&) = default; + + InfomapIterator& operator++() noexcept override; + + InfomapIterator operator++(int) noexcept override + { + InfomapModuleIterator copy(*this); + ++(*this); + return std::move(copy); + } + + using InfomapIterator::childIndex; + using InfomapIterator::current; + using InfomapIterator::depth; + using InfomapIterator::modularCentrality; + using InfomapIterator::path; +}; + +struct InfomapLeafModuleIterator : public InfomapIterator { +public: + InfomapLeafModuleIterator() : InfomapIterator() { } + + InfomapLeafModuleIterator(InfoNode* nodePointer, int moduleIndexLevel = -1) + : InfomapIterator(nodePointer, moduleIndexLevel) { init(); } + + ~InfomapLeafModuleIterator() override = default; + InfomapLeafModuleIterator(const InfomapLeafModuleIterator& other) : InfomapIterator(other) { init(); } + InfomapLeafModuleIterator& operator=(const InfomapLeafModuleIterator&) = default; + InfomapLeafModuleIterator(InfomapLeafModuleIterator&&) = default; + InfomapLeafModuleIterator& operator=(InfomapLeafModuleIterator&&) = default; + + /** + * Iterate to first leaf module + */ + void init() noexcept; + + InfomapIterator& operator++() noexcept override; + + InfomapIterator operator++(int) noexcept override + { + InfomapLeafModuleIterator copy(*this); + ++(*this); + return std::move(copy); + } + + using InfomapIterator::childIndex; + using InfomapIterator::current; + using InfomapIterator::depth; + using InfomapIterator::modularCentrality; + using InfomapIterator::path; +}; + +struct InfomapLeafIterator : public InfomapIterator { +public: + InfomapLeafIterator() : InfomapIterator() { } + + InfomapLeafIterator(InfoNode* nodePointer, int moduleIndexLevel = -1) + : InfomapIterator(nodePointer, moduleIndexLevel) { init(); } + + ~InfomapLeafIterator() override = default; + InfomapLeafIterator(const InfomapLeafIterator& other) : InfomapIterator(other) { init(); } + InfomapLeafIterator& operator=(const InfomapLeafIterator&) = default; + InfomapLeafIterator(InfomapLeafIterator&&) = default; + InfomapLeafIterator& operator=(InfomapLeafIterator&&) = default; + + /** + * Iterate to first leaf node + */ + void init() noexcept; + + InfomapIterator& operator++() noexcept override; + + InfomapIterator operator++(int) noexcept override + { + InfomapLeafIterator copy(*this); + ++(*this); + return std::move(copy); + } + + using InfomapIterator::childIndex; + using InfomapIterator::current; + using InfomapIterator::depth; + using InfomapIterator::modularCentrality; + using InfomapIterator::path; +}; + +/** + * Iterate over the whole tree, collecting physical nodes within same leaf modules + * Note: The physical nodes are created when entering the parent module and removed + * when leaving the module. The tree will not be modified. + */ +struct InfomapIteratorPhysical : public InfomapIterator { +protected: + std::map m_physNodes; + std::map::iterator m_physIter; + InfomapIterator m_oldIter; + +public: + InfomapIteratorPhysical() : InfomapIterator() { } + + InfomapIteratorPhysical(InfoNode* nodePointer, int moduleIndexLevel = -1) + : InfomapIterator(nodePointer, moduleIndexLevel) { } + + ~InfomapIteratorPhysical() override = default; + InfomapIteratorPhysical(const InfomapIteratorPhysical&) = default; + InfomapIteratorPhysical(const InfomapIterator& other) : InfomapIterator(other) { } + + InfomapIteratorPhysical(InfomapIteratorPhysical&&) = default; + InfomapIteratorPhysical& operator=(const InfomapIteratorPhysical&) = default; + + // Don't allow moving from this iterator as we use the old iterator in operator++ + InfomapIteratorPhysical& operator=(InfomapIteratorPhysical&&) = delete; + + InfomapIteratorPhysical& operator=(const InfomapIterator& other) + { + InfomapIterator::operator=(other); + return *this; + } + + InfomapIterator& operator++() noexcept override; + + InfomapIterator operator++(int) noexcept override + { + InfomapIteratorPhysical copy(*this); + ++(*this); + return std::move(copy); + } + + using InfomapIterator::childIndex; + using InfomapIterator::current; + using InfomapIterator::depth; + using InfomapIterator::modularCentrality; + using InfomapIterator::path; +}; + +/** + * Iterate over all physical leaf nodes, joining physical nodes within same leaf modules + * Note: The physical nodes are created when entering the parent module and removed + * when leaving the module. The tree will not be modified. + */ +struct InfomapLeafIteratorPhysical : public InfomapIteratorPhysical { +public: + InfomapLeafIteratorPhysical() : InfomapIteratorPhysical() { } + + InfomapLeafIteratorPhysical(InfoNode* nodePointer, int moduleIndexLevel = -1) + : InfomapIteratorPhysical(nodePointer, moduleIndexLevel) { init(); } + + InfomapLeafIteratorPhysical(const InfomapLeafIteratorPhysical& other) + : InfomapIteratorPhysical(other) { init(); } + + ~InfomapLeafIteratorPhysical() override = default; + InfomapLeafIteratorPhysical(InfomapLeafIteratorPhysical&&) = default; + InfomapLeafIteratorPhysical& operator=(const InfomapLeafIteratorPhysical&) = default; + + // Don't allow moving from this iterator as we use the old iterator in operator++ + InfomapLeafIteratorPhysical& operator=(InfomapLeafIteratorPhysical&&) = delete; + + /** + * Iterate to first leaf node + */ + void init() noexcept; + + InfomapIterator& operator++() noexcept override; + + InfomapIterator operator++(int) noexcept override + { + InfomapLeafIteratorPhysical copy(*this); + ++(*this); + return std::move(copy); + } + + using InfomapIteratorPhysical::childIndex; + using InfomapIteratorPhysical::current; + using InfomapIteratorPhysical::depth; + using InfomapIteratorPhysical::modularCentrality; + using InfomapIteratorPhysical::path; +}; + +/** + * Iterate parent by parent until it is nullptr, + * moving up through possible sub infomap instances + * on the way + */ +struct InfomapParentIterator { +protected: + InfoNode* m_current = nullptr; + +public: + InfomapParentIterator() = default; + + InfomapParentIterator(InfoNode* nodePointer) : m_current(nodePointer) { } + + ~InfomapParentIterator() = default; + + InfomapParentIterator(const InfomapParentIterator&) = default; + + InfomapParentIterator& operator=(const InfomapParentIterator&) = default; + + InfomapParentIterator(InfomapParentIterator&&) = default; + + InfomapParentIterator& operator=(InfomapParentIterator&&) = default; + + InfoNode* current() noexcept { return m_current; } + + const InfoNode* current() const noexcept { return m_current; } + + InfoNode& operator*() noexcept { return *m_current; } + + const InfoNode& operator*() const noexcept { return *m_current; } + + InfoNode* operator->() noexcept { return m_current; } + + const InfoNode* operator->() const noexcept { return m_current; } + + bool operator==(const InfomapParentIterator& other) const noexcept { return m_current == other.m_current; } + + bool operator!=(const InfomapParentIterator& other) const noexcept { return m_current != other.m_current; } + + InfomapParentIterator& operator++() noexcept; + + InfomapParentIterator operator++(int) noexcept + { + InfomapParentIterator copy(*this); + ++(*this); + return copy; + } + + InfomapParentIterator& stepForward() noexcept + { + ++(*this); + return *this; + } + + bool isEnd() const noexcept { return m_current == nullptr; } +}; + +} // namespace infomap + +#endif // INFOMAP_ITERATOR_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/iterators/IterWrapper.h b/src/vendor/cigraph/vendor/infomap/src/core/iterators/IterWrapper.h new file mode 100644 index 00000000000..f043eb6dd23 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/iterators/IterWrapper.h @@ -0,0 +1,32 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef ITER_WRAPPER_H_ +#define ITER_WRAPPER_H_ + +namespace infomap { + +template +class IterWrapper { + Iter m_begin, m_end; + +public: + IterWrapper(Iter begin, Iter end) : m_begin(begin), m_end(end) { } + + template + IterWrapper(Container& container) : m_begin(container.begin()), m_end(container.end()) { } + + Iter begin() noexcept { return m_begin; }; + + Iter end() noexcept { return m_end; }; +}; + +} // namespace infomap + +#endif // ITER_WRAPPER_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/iterators/infomapIterators.h b/src/vendor/cigraph/vendor/infomap/src/core/iterators/infomapIterators.h new file mode 100644 index 00000000000..2d13ffe1a84 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/iterators/infomapIterators.h @@ -0,0 +1,369 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMAP_ITERATORS_H_ +#define INFOMAP_ITERATORS_H_ + +#include "treeIterators.h" +#include +#include + +namespace infomap { + +/** + * Child iterator. + */ +template // pointer or const pointer +class InfomapChildIterator { + using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename iterator_traits::value_type; + using difference_type = typename iterator_traits::difference_type; + using reference = typename iterator_traits::reference; + using pointer = typename iterator_traits::pointer; + +protected: + NodePointerType m_root = nullptr; + NodePointerType m_current = nullptr; + +public: + InfomapChildIterator() = default; + + InfomapChildIterator(const NodePointerType& nodePointer) + : m_root(nodePointer), m_current(nodePointer) { init(); } + + InfomapChildIterator(const InfomapChildIterator& other) + : m_root(other.m_root), m_current(other.m_current) { } + + InfomapChildIterator& operator=(const InfomapChildIterator& other) + { + m_root = other.m_root; + m_current = other.m_current; + return *this; + } + + void init() + { + if (m_root != nullptr) { + NodePointerType infomapRoot = m_root->getInfomapRoot(); + if (infomapRoot != nullptr) { + m_root = infomapRoot; + } + } + m_current = m_root == nullptr ? nullptr : m_root->firstChild; + } + + pointer current() const { return m_current; } + + reference operator*() const { return *m_current; } + + pointer operator->() const { return m_current; } + + bool operator==(const InfomapChildIterator& rhs) const { return m_current == rhs.m_current; } + + bool operator!=(const InfomapChildIterator& rhs) const { return m_current != rhs.m_current; } + + bool isEnd() const { return m_current == nullptr; } + + InfomapChildIterator& operator++() + { + m_current = m_current->next; + if (m_current != nullptr && m_current->parent != m_root) { + m_current = nullptr; + } + return *this; + } + + InfomapChildIterator operator++(int) + { + InfomapChildIterator copy(*this); + ++(*this); + return copy; + } + + InfomapChildIterator& operator--() + { + m_current = m_current->previous; + if (m_current != nullptr && m_current->parent != m_root) { + m_current = nullptr; + } + return *this; + } + + InfomapChildIterator operator--(int) + { + InfomapChildIterator copy(*this); + --(*this); + return copy; + } +}; + +/** + * Pre processing depth first iterator that explores sub-Infomap instances + * Note: This iterator presupposes that the next pointer of a node can't reach a node with a different parent. + */ +template +class InfomapClusterIterator : public DepthFirstIteratorBase { +protected: + using Base = DepthFirstIteratorBase; + + unsigned int m_moduleIndex = 0; + int m_moduleIndexLevel = -1; + + using Base::m_current; + using Base::m_depth; + +public: + InfomapClusterIterator() : Base() { } + + InfomapClusterIterator(const NodePointerType& nodePointer, int moduleIndexLevel = -1) + : Base(nodePointer), m_moduleIndexLevel(moduleIndexLevel) + { + init(); + } + + InfomapClusterIterator(const InfomapClusterIterator& other) + : Base(other), m_moduleIndex(other.m_moduleIndex), m_moduleIndexLevel(other.m_moduleIndexLevel) { } + + virtual void init() { moveToInfomapRootIfExist(); } + + void moveToInfomapRootIfExist() + { + if (m_current != nullptr) { + NodePointerType infomapRoot = m_current->getInfomapRoot(); + if (infomapRoot != nullptr) { + m_current = infomapRoot; + } + } + } + + InfomapClusterIterator& operator=(const InfomapClusterIterator& other) + { + Base::operator=(other); + m_moduleIndex = other.m_moduleIndex; + m_moduleIndexLevel = other.m_moduleIndexLevel; + return *this; + } + + InfomapClusterIterator& operator++() + { + NodePointerType curr = Base::m_current; + + if (curr->firstChild != nullptr) { + curr = curr->firstChild; + ++m_depth; + } else { + // Current node is a leaf + // Presupposes that the next pointer can't reach out from the current parent. + tryNext: + while (curr->next == nullptr) { + if (curr->parent != nullptr) { + curr = curr->parent; + --m_depth; + if (curr == Base::m_root) // Check if back to beginning + { + m_current = nullptr; + return *this; + } + if (m_moduleIndexLevel < 0) { + if (curr->isLeafModule()) // TODO: Generalize to -2 for second level to bottom + ++m_moduleIndex; + } else if (static_cast(m_moduleIndexLevel) == m_depth) + ++m_moduleIndex; + } else { + NodePointerType infomapOwner = curr->owner; + if (infomapOwner != nullptr) { + curr = infomapOwner; + if (curr == Base::m_root) // Check if back to beginning + { + m_current = nullptr; + return *this; + } + goto tryNext; + } else // null also if no children in first place + { + m_current = nullptr; + return *this; + } + } + } + curr = curr->next; + } + m_current = curr; + moveToInfomapRootIfExist(); + return *this; + } + + InfomapClusterIterator operator++(int) + { + InfomapClusterIterator copy(*this); + ++(*this); + return copy; + } + + InfomapClusterIterator next() + { + InfomapClusterIterator copy(*this); + return ++copy; + } + + InfomapClusterIterator& stepForward() + { + ++(*this); + return *this; + } + + unsigned int moduleIndex() const + { + return m_moduleIndex; + } +}; + +/** + * Pre processing depth first iterator that explores sub-Infomap instances + * Note: This iterator presupposes that the next pointer of a node can't reach a node with a different parent. + */ +template +class InfomapDepthFirstIterator : public DepthFirstIteratorBase { +protected: + using Base = DepthFirstIteratorBase; + + std::deque m_path; // The child index path to current node + unsigned int m_moduleIndex = 0; + int m_moduleIndexLevel = -1; + + using Base::m_current; + using Base::m_depth; + +public: + InfomapDepthFirstIterator() : Base() { } + + InfomapDepthFirstIterator(const NodePointerType& nodePointer, int moduleIndexLevel = -1) + : Base(nodePointer), + m_moduleIndexLevel(moduleIndexLevel) + { + init(); + } + + InfomapDepthFirstIterator(const InfomapDepthFirstIterator& other) + : Base(other), + m_path(other.m_path), + m_moduleIndex(other.m_moduleIndex), + m_moduleIndexLevel(other.m_moduleIndexLevel) + { + } + + InfomapDepthFirstIterator& operator=(const InfomapDepthFirstIterator& other) + { + Base::operator=(other); + m_path = other.m_path; + m_moduleIndex = other.m_moduleIndex; + m_moduleIndexLevel = other.m_moduleIndexLevel; + return *this; + } + + virtual void init() + { + moveToInfomapRootIfExist(); + } + + void moveToInfomapRootIfExist() + { + if (m_current != nullptr) { + NodePointerType infomapRoot = m_current->getInfomapRoot(); + if (infomapRoot != nullptr) { + m_current = infomapRoot; + } + } + } + + InfomapDepthFirstIterator& operator++() + { + NodePointerType curr = Base::m_current; + + if (curr->firstChild != nullptr) { + curr = curr->firstChild; + ++m_depth; + m_path.push_back(0); + } else { + // Current node is a leaf + // Presupposes that the next pointer can't reach out from the current parent. + tryNext: + while (curr->next == nullptr) { + if (curr->parent != nullptr) { + curr = curr->parent; + --m_depth; + m_path.pop_back(); + if (curr == Base::m_root) // Check if back to beginning + { + m_current = nullptr; + return *this; + } + if (m_moduleIndexLevel < 0) { + if (curr->isLeafModule()) // TODO: Generalize to -2 for second level to bottom + ++m_moduleIndex; + } else if (static_cast(m_moduleIndexLevel) == m_depth) + ++m_moduleIndex; + } else { + NodePointerType infomapOwner = curr->owner; + if (infomapOwner != nullptr) { + curr = infomapOwner; + if (curr == Base::m_root) // Check if back to beginning + { + m_current = nullptr; + return *this; + } + goto tryNext; + } else // null also if no children in first place + { + m_current = nullptr; + return *this; + } + } + } + curr = curr->next; + ++m_path.back(); + } + m_current = curr; + moveToInfomapRootIfExist(); + return *this; + } + + InfomapDepthFirstIterator operator++(int) + { + InfomapDepthFirstIterator copy(*this); + ++(*this); + return copy; + } + + InfomapDepthFirstIterator next() + { + InfomapDepthFirstIterator copy(*this); + return ++copy; + } + + InfomapDepthFirstIterator& stepForward() + { + ++(*this); + return *this; + } + + const std::deque& path() const + { + return m_path; + } + + unsigned int moduleIndex() const + { + return m_moduleIndex; + } +}; + +} // namespace infomap + +#endif // INFOMAP_ITERATORS_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/core/iterators/treeIterators.h b/src/vendor/cigraph/vendor/infomap/src/core/iterators/treeIterators.h new file mode 100644 index 00000000000..7717e208f79 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/core/iterators/treeIterators.h @@ -0,0 +1,628 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef TREE_ITERATORS_H_ +#define TREE_ITERATORS_H_ + +#include +#include +#include + +namespace infomap { + +#ifndef ASSERT +#include +#define ASSERT(x) assert(x) +#endif + +using std::iterator_traits; + +/** + * Child iterator. + */ +template // pointer or const pointer +class ChildIterator { + using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename iterator_traits::value_type; + using difference_type = typename iterator_traits::difference_type; + using reference = typename iterator_traits::reference; + using pointer = typename iterator_traits::pointer; + +protected: + NodePointerType m_root = nullptr; + NodePointerType m_current = nullptr; + +public: + ChildIterator() = default; + + ChildIterator(const NodePointerType& nodePointer) + : m_root(nodePointer), m_current(nodePointer == nullptr ? nullptr : nodePointer->firstChild) { } + + ChildIterator(const ChildIterator& other) + : m_root(other.m_root), m_current(other.m_current) { } + + ChildIterator& operator=(const ChildIterator& other) + { + m_root = other.m_root; + m_current = other.m_current; + return *this; + } + + pointer current() const { return m_current; } + + reference operator*() const { return *m_current; } + + pointer operator->() const { return m_current; } + + bool operator==(const ChildIterator& rhs) const { return m_current == rhs.m_current; } + + bool operator!=(const ChildIterator& rhs) const { return !(m_current == rhs.m_current); } + + bool isEnd() const { return m_current == nullptr; } + + ChildIterator& operator++() + { + m_current = m_current->next; + if (m_current != nullptr && m_current->parent != m_root) { + m_current = nullptr; + } + return *this; + } + + ChildIterator operator++(int) + { + ChildIterator copy(*this); + ++(*this); + return copy; + } + + ChildIterator& operator--() + { + m_current = m_current->previous; + if (m_current != nullptr && m_current->parent != m_root) { + m_current = nullptr; + } + return *this; + } + + ChildIterator operator--(int) + { + ChildIterator copy(*this); + --(*this); + return copy; + } +}; + +/** + * Tree iterator. + */ +template // pointer or const pointer +class TreeIterator { + using iterator_category = std::forward_iterator_tag; + using value_type = typename iterator_traits::value_type; + using difference_type = typename iterator_traits::difference_type; + using reference = typename iterator_traits::reference; + using pointer = typename iterator_traits::pointer; + +protected: + NodePointerType m_root = nullptr; + NodePointerType m_current = nullptr; + int m_moduleIndexLevel = -1; + unsigned int m_moduleIndex = 0; + std::deque m_path; // The child index path to current node + unsigned int m_depth = 0; + +public: + TreeIterator() = default; + + TreeIterator(NodePointerType nodePointer, int moduleIndexLevel = -1) + : m_root(nodePointer), + m_current(nodePointer), + m_moduleIndexLevel(moduleIndexLevel) { } + + TreeIterator(const TreeIterator& other) + : m_root(other.m_root), + m_current(other.m_current), + m_moduleIndexLevel(other.m_moduleIndexLevel), + m_moduleIndex(other.m_moduleIndex), + m_path(other.m_path), + m_depth(other.m_depth) { } + + virtual ~TreeIterator() = default; + + TreeIterator& operator=(const TreeIterator& other) + { + m_root = other.m_root; + m_current = other.m_current; + m_moduleIndexLevel = other.m_moduleIndexLevel; + m_moduleIndex = other.m_moduleIndex; + m_path = other.m_path; + m_depth = other.m_depth; + return *this; + } + + pointer current() const { return m_current; } + + reference operator*() const { return *m_current; } + + pointer operator->() const { return m_current; } + + bool operator==(const TreeIterator& rhs) const { return m_current == rhs.m_current; } + + bool operator!=(const TreeIterator& rhs) const { return !(m_current == rhs.m_current); } + + const std::deque& path() const { return m_path; } + + unsigned int moduleIndex() const { return m_moduleIndex; } + + unsigned int depth() const { return m_depth; } + + bool isEnd() const { return m_current == nullptr; } + + TreeIterator& operator++() + { + NodePointerType curr = m_current; + NodePointerType infomapRoot = curr->getInfomapRoot(); + if (infomapRoot != nullptr) { + curr = infomapRoot; + } + + if (curr->firstChild != nullptr) { + curr = curr->firstChild; + ++m_depth; + m_path.push_back(0); + } else { + // Current node is a leaf + // Presupposes that the next pointer can't reach out from the current parent. + tryNext: + while (curr->next == nullptr) { + if (curr->parent != nullptr) { + curr = curr->parent; + --m_depth; + m_path.pop_back(); + if (curr == m_root) // Check if back to beginning + { + m_current = nullptr; + return *this; + } + if (m_moduleIndexLevel < 0) { + if (curr->isLeafModule()) // TODO: Generalize to -2 for second level to bottom + ++m_moduleIndex; + } else if (static_cast(m_moduleIndexLevel) == m_depth) + ++m_moduleIndex; + } else { + NodePointerType infomapOwner = curr->owner; + if (infomapOwner != nullptr) { + curr = infomapOwner; + if (curr == m_root) // Check if back to beginning + { + m_current = nullptr; + return *this; + } + goto tryNext; + } else // null also if no children in first place + { + m_current = nullptr; + return *this; + } + } + } + curr = curr->next; + ++m_path.back(); + } + m_current = curr; + return *this; + } + + TreeIterator operator++(int) + { + TreeIterator copy(*this); + ++(*this); + return copy; + } + + TreeIterator& stepForward() + { + ++(*this); + return *this; + } +}; + +/** + * Base node iterator. + */ +template +struct node_iterator_base { + using iterator_category = iterator_tag; + using value_type = typename iterator_traits::value_type; + using difference_type = typename iterator_traits::difference_type; + using reference = typename iterator_traits::reference; + using pointer = typename iterator_traits::pointer; + + node_iterator_base() : m_current(nullptr) { } + + node_iterator_base(const NodePointerType& nodePointer) : m_current(nodePointer) { } + + node_iterator_base(const node_iterator_base& other) : m_current(other.m_current) { } + + node_iterator_base& operator=(const node_iterator_base& other) + { + m_current = other.m_current; + return *this; + } + + virtual ~node_iterator_base() = default; + + pointer base() const { return m_current; } + + reference operator*() const { return *m_current; } + + pointer operator->() const { return m_current; } + + bool operator==(const node_iterator_base& rhs) const { return m_current == rhs.m_current; } + + bool operator!=(const node_iterator_base& rhs) const { return !(m_current == rhs.m_current); } + + bool isEnd() const { return m_current == nullptr; } + +protected: + NodePointerType m_current; +}; + +template +class DepthFirstIteratorBase : public node_iterator_base { + using Base = node_iterator_base; + +public: + DepthFirstIteratorBase() : Base(), m_root(nullptr), m_depth(0) { } + + DepthFirstIteratorBase(const NodePointerType& nodePointer) : Base(nodePointer), m_root(nodePointer), m_depth(0) { } + + DepthFirstIteratorBase(const DepthFirstIteratorBase& other) : Base(other), m_root(other.m_root), m_depth(other.m_depth) { } + + DepthFirstIteratorBase& operator=(const DepthFirstIteratorBase& other) + { + Base::operator=(other); + m_root = other.m_root; + m_depth = other.m_depth; + return *this; + } + + unsigned int depth() const { return m_depth; } + +protected: + NodePointerType m_root; + unsigned int m_depth; + using Base::m_current; +}; + +/** + * Pre processing depth first iterator + * Note: + * This iterator presupposes that the next pointer of a node can't reach a node with a different parent. + */ +template +class DepthFirstIterator : public DepthFirstIteratorBase { + using Base = DepthFirstIteratorBase; + +public: + DepthFirstIterator() : Base() { } + + DepthFirstIterator(const NodePointerType& nodePointer) : Base(nodePointer) { } + + DepthFirstIterator(const DepthFirstIterator& other) : Base(other) { } + + DepthFirstIterator& operator=(const DepthFirstIterator& other) + { + Base::operator=(other); + return *this; + } + + DepthFirstIterator& operator++() + { + NodePointerType curr = Base::m_current; + if (curr->firstChild != nullptr) { + curr = curr->firstChild; + ++Base::m_depth; + } else { + // Presupposes that the next pointer can't reach out from the current parent. + while (curr->next == nullptr) { + curr = curr->parent; + --Base::m_depth; + if (curr == Base::m_root || curr == nullptr) // 0 if no children in first place + { + Base::m_current = nullptr; + return *this; + } + } + curr = curr->next; + } + Base::m_current = curr; + return *this; + } + + DepthFirstIterator operator++(int) + { + auto copy(*this); + ++(*this); + return copy; + } + + DepthFirstIterator next() + { + auto copy(*this); + return ++copy; + } +}; + +/** + * Post processing depth first iterator + * Note: + * This iterator presupposes that the next pointer of a node can't reach a node with a different parent. + */ +template +class DepthFirstIterator : public DepthFirstIteratorBase { + using Base = DepthFirstIteratorBase; + +public: + DepthFirstIterator() : Base() { } + + DepthFirstIterator(const NodePointerType& nodePointer) : Base(nodePointer) { init(); } + + DepthFirstIterator(const DepthFirstIterator& other) : Base(other) { } + + DepthFirstIterator& operator=(const DepthFirstIterator& other) + { + Base::operator=(other); + return *this; + } + + void init() + { + if (Base::m_current != nullptr) { + while (Base::m_current->firstChild != nullptr) { + Base::m_current = Base::m_current->firstChild; + ++Base::m_depth; + } + } + } + + DepthFirstIterator& operator++() + { + // The root should be the last node + if (Base::m_current == Base::m_root) { + Base::m_current = nullptr; + return *this; + } + + NodePointerType curr = Base::m_current; + if (curr->next != nullptr) { + curr = curr->next; + while (curr->firstChild != nullptr) { + curr = curr->firstChild; + ++Base::m_depth; + } + } else { + curr = curr->parent; + --Base::m_depth; + } + + Base::m_current = curr; + + return *this; + } + + DepthFirstIterator operator++(int) + { + DepthFirstIterator copy(*this); + ++(*this); + return copy; + } + + DepthFirstIterator + next() + { + DepthFirstIterator copy(*this); + return ++copy; + } +}; + +/** + * Leaf node iterator + */ +template +class LeafNodeIterator : public DepthFirstIteratorBase { + using Base = DepthFirstIteratorBase; + +public: + LeafNodeIterator() : Base() { } + + LeafNodeIterator(const NodePointerType& nodePointer) : Base(nodePointer) { init(); } + + LeafNodeIterator(const LeafNodeIterator& other) : Base(other) { } + + LeafNodeIterator& operator=(const LeafNodeIterator& other) + { + Base::operator=(other); + return *this; + } + + void init() + { + if (Base::m_current != nullptr) { + while (Base::m_current->firstChild != nullptr) { + Base::m_current = Base::m_current->firstChild; + ++Base::m_depth; + } + } + } + + LeafNodeIterator& operator++() + { + ASSERT(Base::m_current != nullptr); + while (Base::m_current->next == nullptr || Base::m_current->next->parent != Base::m_current->parent) { + Base::m_current = Base::m_current->parent; + --Base::m_depth; + if (Base::m_current == nullptr) + return *this; + } + + Base::m_current = Base::m_current->next; + + if (Base::m_current != nullptr) { + while (Base::m_current->firstChild != nullptr) { + Base::m_current = Base::m_current->firstChild; + ++Base::m_depth; + } + } + return *this; + } + + LeafNodeIterator operator++(int) + { + LeafNodeIterator copy(*this); + ++(*this); + return copy; + } + + LeafNodeIterator next() + { + LeafNodeIterator copy(*this); + return ++copy; + } +}; + +/** + * Leaf module iterator + */ +template +class LeafModuleIterator : public DepthFirstIteratorBase { + using Base = DepthFirstIteratorBase; + +public: + LeafModuleIterator() : Base() { } + + LeafModuleIterator(const NodePointerType& nodePointer) : Base(nodePointer) { init(); } + + LeafModuleIterator(const LeafModuleIterator& other) : Base(other) { } + + LeafModuleIterator& operator=(const LeafModuleIterator& other) + { + Base::operator=(other); + init(); + return *this; + } + + void init() + { + if (Base::m_current != nullptr) { + if (Base::m_current->firstChild == nullptr) { + Base::m_current = nullptr; // End directly if no module + } else { + while (Base::m_current->firstChild->firstChild != nullptr) { + Base::m_current = Base::m_current->firstChild; + ++Base::m_depth; + } + } + } + } + + LeafModuleIterator& operator++() + { + ASSERT(Base::m_current != nullptr); + while (Base::m_current->next == nullptr || Base::m_current->next->parent != Base::m_current->parent) { + Base::m_current = Base::m_current->parent; + --Base::m_depth; + if (Base::m_current == nullptr) + return *this; + } + + Base::m_current = Base::m_current->next; + + if (Base::m_current != nullptr) { + if (Base::m_current->firstChild == nullptr) { + Base::m_current = Base::m_current->parent; + } else { + while (Base::m_current->firstChild->firstChild != nullptr) { + Base::m_current = Base::m_current->firstChild; + ++Base::m_depth; + } + } + } + return *this; + } + + LeafModuleIterator operator++(int) + { + LeafModuleIterator copy(*this); + ++(*this); + return copy; + } + + LeafModuleIterator next() + { + LeafModuleIterator copy(*this); + return ++copy; + } +}; + +/** + * Sibling iterator. + */ +template // pointer or const pointer +class SiblingIterator : public node_iterator_base { + using Base = node_iterator_base; + +public: + using self_type = SiblingIterator; + + SiblingIterator() : Base() { } + + SiblingIterator(const NodePointerType& nodePointer) : Base(nodePointer) { } + + SiblingIterator(const SiblingIterator& other) : Base(other) { } + + SiblingIterator& operator=(const SiblingIterator& other) + { + Base::operator=(other); + return *this; + } + + SiblingIterator& operator++() + { + ASSERT(Base::m_current != nullptr); + Base::m_current = Base::m_current->next; + return *this; + } + + SiblingIterator operator++(int) + { + SiblingIterator copy(*this); + ++(*this); + return copy; + } + + SiblingIterator& operator--() + { + ASSERT(Base::m_current != nullptr); + Base::m_current = Base::m_current->previous; + return *this; + } + + SiblingIterator operator--(int) + { + SiblingIterator copy(*this); + --(*this); + return copy; + } +}; + +} // namespace infomap + +#endif // TREE_ITERATORS_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.cpp b/src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.cpp new file mode 100644 index 00000000000..1de468c739c --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.cpp @@ -0,0 +1,189 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "ClusterMap.h" +#include "SafeFile.h" +#include "../utils/Log.h" +#include "../utils/FileURI.h" +#include + +namespace infomap { + +void ClusterMap::readClusterData(const std::string& filename, bool includeFlow, const std::map>* layerNodeToStateId) +{ + FileURI file(filename); + m_extension = file.getExtension(); + if (m_extension == "tree" || m_extension == "ftree") { + return readTree(filename, includeFlow, layerNodeToStateId); + } + if (m_extension == "clu") { + return readClu(filename, includeFlow, layerNodeToStateId); + } + throw std::runtime_error(io::Str() << "Input cluster data from file '" << filename << "' is of unknown extension '" << m_extension << "'. Must be 'clu' or 'tree'."); +} + +/** + * Sample from .tree file +# Codelength = 3.46227314 bits. +# path flow name physicalId +1:1:1 0.0384615 "1" 1 +1:1:2 0.025641 "2" 2 +1:1:3 0.0384615 "3" 3 +1:2:1 0.0384615 "4" 4 + */ +void ClusterMap::readTree(const std::string& filename, bool includeFlow, const std::map>* layerNodeToStateId) +{ + bool isMultilayer = layerNodeToStateId != nullptr; + + SafeInFile input(filename); + std::string line; + std::istringstream lineStream; + std::istringstream pathStream; + m_nodePaths.clear(); + + unsigned int lineNr = 0; + + while (!std::getline(input, line).fail()) { + ++lineNr; + if (line.length() == 0) + continue; + if (line[0] == '#') { + continue; + } + if (line[0] == '*') { + break; + } + + lineStream.clear(); + lineStream.str(line); + + std::string pathString; + double flow; + std::string name; + unsigned int stateId; + unsigned int nodeId; + unsigned int layerId; + if (!(lineStream >> pathString)) + throw std::runtime_error(io::Str() << "Couldn't parse tree path from line '" << line << "'"); + if (!(lineStream >> flow)) + throw std::runtime_error(io::Str() << "Couldn't parse node flow from line '" << line << "'"); + // Get the name by extracting the rest of the stream until the first quotation mark and then the last. + if (!getline(lineStream, name, '"')) + throw std::runtime_error(io::Str() << "Can't parse node name from line " << lineNr << " ('" << line << "')."); + if (!getline(lineStream, name, '"')) + throw std::runtime_error(io::Str() << "Can't parse node name from line " << lineNr << " ('" << line << "')."); + if (!(lineStream >> stateId)) + throw std::runtime_error(io::Str() << "Couldn't parse node id from line '" << line << "'"); + if (lineStream >> nodeId) { + m_isHigherOrder = true; + } else if (m_isHigherOrder) { + throw std::runtime_error(io::Str() << "Missing state id for node on line '" << line << "'."); + } + if (isMultilayer && !(lineStream >> layerId)) + throw std::runtime_error(io::Str() << "Couldn't parse layer id from line '" << line << "'"); + + bool multilayerNodeFound = false; + + if (isMultilayer) { + // get new state id from map + auto it = layerNodeToStateId->find(layerId); + + if (it != layerNodeToStateId->end()) { + auto nodeIdToStateId = it->second.find(nodeId); + if (nodeIdToStateId != it->second.end()) { + stateId = nodeIdToStateId->second; + multilayerNodeFound = true; + } + } + } + + if (isMultilayer && !multilayerNodeFound) { + continue; + } + + pathStream.clear(); + pathStream.str(pathString); + unsigned int childNumber; + + Path path; + while (pathStream >> childNumber) { + pathStream.get(); // Extract the delimiting character also + if (childNumber == 0) + throw std::runtime_error("There is a '0' in the tree path, lowest allowed integer is 1."); + path.push_back(childNumber); // Keep 1-based indexing in path + } + + m_nodePaths.emplace_back(stateId, path); + + if (includeFlow) + m_flowData[stateId] = flow; + } +} + +void ClusterMap::readClu(const std::string& filename, bool includeFlow, const std::map>* layerNodeToStateId) +{ + auto isMultilayer = layerNodeToStateId != nullptr; + + Log() << "Read initial partition from '" << filename << "'... " << std::flush; + SafeInFile input(filename); + std::string line; + std::istringstream lineStream; + std::map clusterData; + + while (!std::getline(input, line).fail()) { + if (line.length() == 0 || line[0] == '#' || line[0] == '*') + continue; + + lineStream.clear(); + lineStream.str(line); + // # state_id module flow node_id layer_id + + unsigned int stateId; + unsigned int nodeId; + unsigned int moduleId; + unsigned int layerId; + + if (!(lineStream >> stateId >> moduleId)) + throw std::runtime_error(io::Str() << "Couldn't parse node key and cluster id from line '" << line << "'"); + + auto flow = 0.0; + if (lineStream >> flow) { + if (includeFlow) + m_flowData[stateId] = flow; + } + + auto multilayerNodeFound = false; + if (isMultilayer) { + if (!(lineStream >> nodeId)) + throw std::runtime_error(io::Str() << "Couldn't parse node key from line '" << line << "'"); + + if (!(lineStream >> layerId)) + throw std::runtime_error(io::Str() << "Couldn't parse layer id from line '" << line << "'"); + + // get new state id from map + auto it = layerNodeToStateId->find(layerId); + + if (it != layerNodeToStateId->end()) { + auto nodeIdToStateId = it->second.find(nodeId); + if (nodeIdToStateId != it->second.end()) { + stateId = nodeIdToStateId->second; + multilayerNodeFound = true; + } + } + } + + if (isMultilayer && !multilayerNodeFound) { + continue; + } + + m_clusterIds[stateId] = moduleId; + } +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.h b/src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.h new file mode 100644 index 00000000000..5526663c334 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/ClusterMap.h @@ -0,0 +1,52 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef CLUSTER_MAP_H_ +#define CLUSTER_MAP_H_ + +#include +#include +#include +#include + +namespace infomap { + +using Path = std::deque; // 1-based indexing + +using NodePath = std::pair; + +using NodePaths = std::vector; + +class ClusterMap { +public: + void readClusterData(const std::string& filename, bool includeFlow = false, const std::map>* layerNodeToStateId = nullptr); + + const std::map& clusterIds() const noexcept + { + return m_clusterIds; + } + + const NodePaths& nodePaths() const noexcept { return m_nodePaths; } + + const std::string& extension() const noexcept { return m_extension; } + +private: + void readTree(const std::string& filename, bool includeFlow, const std::map>* layerNodeToStateId = nullptr); + void readClu(const std::string& filename, bool includeFlow, const std::map>* layerNodeToStateId = nullptr); + + std::map m_clusterIds; + std::map m_flowData; + NodePaths m_nodePaths; + std::string m_extension; + bool m_isHigherOrder = false; +}; + +} // namespace infomap + +#endif // CLUSTER_MAP_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/io/Config.cpp b/src/vendor/cigraph/vendor/infomap/src/io/Config.cpp new file mode 100644 index 00000000000..ce6a80fc4eb --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/Config.cpp @@ -0,0 +1,264 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "Config.h" +#include "ProgramInterface.h" +#include "SafeFile.h" +#include "../utils/FileURI.h" +#include "../utils/Log.h" +#include +#include + +namespace infomap { + +constexpr int FlowModel::undirected; +constexpr int FlowModel::directed; +constexpr int FlowModel::undirdir; +constexpr int FlowModel::outdirdir; +constexpr int FlowModel::rawdir; +constexpr int FlowModel::precomputed; + +Config::Config(const std::string& flags, bool isCLI) : isCLI(isCLI) +{ + ProgramInterface api("Infomap", + "Implementation of the Infomap clustering algorithm based on the Map Equation (see www.mapequation.org)", + INFOMAP_VERSION); + + api.setGroups({ "Input", "Algorithm", "Accuracy", "Output" }); + + std::vector optionalOutputDir; // Used if !isCLI + // --------------------- Input options --------------------- + if (isCLI) { + api.addNonOptionArgument(networkFile, "network_file", "File containing the network data. Assumes a link list format if no Pajek formatted heading.", "Input"); + } else { + api.addOptionArgument(networkFile, "input", "File containing the network data. Assumes a link list format if no Pajek formatted heading.", ArgType::path, "Input"); + } + + api.addOptionArgument(skipAdjustBipartiteFlow, "skip-adjust-bipartite-flow", "Skip distributing all flow from the bipartite nodes to the primary nodes.", "Input", true); + + api.addOptionArgument(bipartiteTeleportation, "bipartite-teleportation", "Teleport like the bipartite flow instead of two-step (unipartite) teleportation.", "Input", true); + + api.addOptionArgument(weightThreshold, "weight-threshold", "Limit the number of links to read from the network. Ignore links with less weight than the threshold.", ArgType::number, "Input", 0.0, true); + + bool deprecated_includeSelfLinks = false; + api.addOptionArgument(deprecated_includeSelfLinks, 'k', "include-self-links", "DEPRECATED. Include self links by default now, exclude with --no-self-links.", "Input", true).setHidden(true); + + api.addOptionArgument(noSelfLinks, "no-self-links", "Exclude self links in the input network.", "Input", true); + + api.addOptionArgument(nodeLimit, "node-limit", "Limit the number of nodes to read from the network. Ignore links connected to ignored nodes.", ArgType::integer, "Input", 1u, true); + + api.addOptionArgument(matchableMultilayerIds, "matchable-multilayer-ids", "Construct state ids from node and layer ids that are consistent across networks for the same max number of layers. Set to at least the largest layer id among networks to match.", ArgType::integer, "Input", 1u, true); + + api.addOptionArgument(clusterDataFile, 'c', "cluster-data", "Provide an initial two-level (clu format) or multi-layer (tree format) solution.", ArgType::path, "Input"); + + api.addOptionArgument(assignToNeighbouringModule, "assign-to-neighbouring-module", "Assign nodes without module assignments (from --cluster-data) to the module assignment of a neighbouring node if possible.", "Input", true); + + api.addOptionArgument(metaDataFile, "meta-data", "Provide meta data (clu format) that should be encoded.", ArgType::path, "Input", true); + + api.addOptionArgument(metaDataRate, "meta-data-rate", "Metadata encoding rate. Default is to encode each step.", ArgType::number, "Input", 0.0, true); + + api.addOptionArgument(unweightedMetaData, "meta-data-unweighted", "Don't weight meta data by node flow.", "Input", true); + + api.addOptionArgument(noInfomap, "no-infomap", "Don't run the optimizer. Useful to calculate codelength of provided cluster data or to print non-modular statistics.", "Input"); + + // --------------------- Output options --------------------- + + api.addOptionArgument(outName, "out-name", "Name for the output files, e.g. [output_directory]/[out-name].tree", ArgType::string, "Output", true); + + api.addOptionArgument(noFileOutput, '0', "no-file-output", "Don't write output to file.", "Output", true); + + api.addOptionArgument(printTree, "tree", "Write a tree file with the modular hierarchy. Automatically enabled if no other output is specified.", "Output"); + + api.addOptionArgument(printFlowTree, "ftree", "Write a ftree file with the modular hierarchy including aggregated links between (nested) modules. (Used by Network Navigator)", "Output"); + + api.addOptionArgument(printClu, "clu", "Write a clu file with the top cluster ids for each node.", "Output"); + + api.addOptionArgument(cluLevel, "clu-level", "For clu output, print modules at specified depth from root. Use -1 for bottom level modules.", ArgType::integer, "Output", -1, true); + + api.addOptionArgument(outputFormats, 'o', "output", "Comma-separated output formats without spaces, e.g. -o clu,tree,ftree. Options: clu, tree, ftree, newick, json, csv, network, states, flow.", ArgType::list, "Output", true); + + api.addOptionArgument(hideBipartiteNodes, "hide-bipartite-nodes", "Project bipartite solution to unipartite.", "Output", true); + + api.addOptionArgument(printAllTrials, "print-all-trials", "Print all trials to separate files.", "Output", true); + + // --------------------- Core algorithm options --------------------- + api.addOptionArgument(twoLevel, '2', "two-level", "Optimize a two-level partition of the network. Default is multi-level.", "Algorithm"); + + std::string flowModelArg; + + api.addOptionArgument(flowModelArg, 'f', "flow-model", "Specify flow model. Options: undirected, directed, undirdir, outdirdir, rawdir, precomputed.", ArgType::option, "Algorithm"); + + api.addOptionArgument(directed, 'd', "directed", "Assume directed links. Shorthand for '--flow-model directed'.", "Algorithm"); + + api.addOptionArgument(recordedTeleportation, 'e', "recorded-teleportation", "If teleportation is used to calculate the flow, also record it when minimizing codelength.", "Algorithm", true); + + api.addOptionArgument(useNodeWeightsAsFlow, "use-node-weights-as-flow", "Use node weights (from api or after names in Pajek format) as flow, normalized to sum to 1", "Algorithm", true); + + api.addOptionArgument(teleportToNodes, "to-nodes", "Teleport to nodes instead of to links, assuming uniform node weights if no such input data.", "Algorithm", true); + + api.addOptionArgument(teleportationProbability, 'p', "teleportation-probability", "Probability of teleporting to a random node or link.", ArgType::probability, "Algorithm", 0.0, 1.0, true); + + api.addOptionArgument(regularized, "regularized", "Effectively add a fully connected Bayesian prior network to not overfit due to missing links. Implies recorded teleportation", "Algorithm", true); + + api.addOptionArgument(regularizationStrength, "regularization-strength", "Adjust relative strength of Bayesian prior network with this multiplier.", ArgType::number, "Algorithm", 0.0, true); + + api.addOptionArgument(entropyBiasCorrection, "entropy-corrected", "Correct for negative entropy bias in small samples (many modules).", "Algorithm", true); + + api.addOptionArgument(entropyBiasCorrectionMultiplier, "entropy-correction-strength", "Increase or decrease the default entropy correction with this factor.", ArgType::number, "Algorithm", true); + + api.addOptionArgument(markovTime, "markov-time", "Scale link flow to change the cost of moving between modules. Higher values results in fewer modules.", ArgType::number, "Algorithm", 0.0, true); + + api.addOptionArgument(variableMarkovTime, "variable-markov-time", "Increase Markov time locally to level out link flow. Reduces risk of overpartitioning sparse areas while keeping high resolution in dense areas.", "Algorithm", true); + + api.addOptionArgument(variableMarkovTimeDamping, "variable-markov-damping", "Damping parameter for variable Markov time, to scale with local effective degree (0) or local entropy (1).", ArgType::number, "Algorithm", true); + + api.addOptionArgument(variableMarkovTimeMinLocalScale, "variable-markov-min-scale", "Minimum local scale for nodes with zero entropy to avoid division by zero. Local Markov time is max scale divided by local scale.", ArgType::number, "Algorithm", true); + + // api.addOptionArgument(markovTimeNoSelfLinks, "markov-time-no-self-links", "For testing.", "Algorithm", true); + + api.addOptionArgument(preferredNumberOfModules, "preferred-number-of-modules", "Penalize solutions the more they differ from this number.", ArgType::integer, "Algorithm", 1u, true); + + api.addOptionArgument(multilayerRelaxRate, "multilayer-relax-rate", "Probability to relax the constraint to move only in the current layer.", ArgType::probability, "Algorithm", 0.0, 1.0, true); + + api.addOptionArgument(multilayerRelaxLimit, "multilayer-relax-limit", "Number of neighboring layers in each direction to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", -1, true); + + api.addOptionArgument(multilayerRelaxLimitUp, "multilayer-relax-limit-up", "Number of neighboring layers with higher id to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", -1, true); + + api.addOptionArgument(multilayerRelaxLimitDown, "multilayer-relax-limit-down", "Number of neighboring layers with lower id to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", -1, true); + + api.addOptionArgument(multilayerRelaxByJensenShannonDivergence, "multilayer-relax-by-jsd", "Relax proportional to the out-link similarity measured by the Jensen-Shannon divergence.", "Algorithm", true); + + // --------------------- Performance and accuracy options --------------------- + // api.addOptionArgument(seedToRandomNumberGenerator, 's', "seed", "A seed (integer) to the random number generator for reproducible results.", ArgType::integer, "Accuracy", 1ul); + + api.addOptionArgument(numTrials, 'N', "num-trials", "Number of outer-most loops to run before picking the best solution.", ArgType::integer, "Accuracy", 1u); + + api.addOptionArgument(coreLoopLimit, 'M', "core-loop-limit", "Limit the number of loops that tries to move each node into the best possible module.", ArgType::integer, "Accuracy", 1u, true); + + api.addOptionArgument(levelAggregationLimit, 'L', "core-level-limit", "Limit the number of times the core loops are reapplied on existing modular network to search bigger structures.", ArgType::integer, "Accuracy", 1u, true); + + api.addOptionArgument(tuneIterationLimit, 'T', "tune-iteration-limit", "Limit the number of main iterations in the two-level partition algorithm. 0 means no limit.", ArgType::integer, "Accuracy", 1u, true); + + api.addOptionArgument(minimumCodelengthImprovement, "core-loop-codelength-threshold", "Minimum codelength threshold for accepting a new solution in core loop.", ArgType::number, "Accuracy", 0.0, true); + + api.addOptionArgument(minimumRelativeTuneIterationImprovement, "tune-iteration-relative-threshold", "Set codelength improvement threshold of each new tune iteration to 'f' times the initial two-level codelength.", ArgType::number, "Accuracy", 0.0, true); + + api.addIncrementalOptionArgument(fastHierarchicalSolution, 'F', "fast-hierarchical-solution", "Find top modules fast. Use -FF to keep all fast levels. Use -FFF to skip recursive part.", "Accuracy", true); + + api.addOptionArgument(preferModularSolution, "prefer-modular-solution", "Prefer modular solutions even if they are worse than putting all nodes in one module.", "Accuracy", true); + + api.addOptionArgument(innerParallelization, "inner-parallelization", "Parallelize the inner-most loop for greater speed. This may give some accuracy tradeoff.", "Accuracy", true); + + api.addOptionalNonOptionArguments(optionalOutputDir, "out_directory", "Directory to write the results to.", "Output"); + + api.addIncrementalOptionArgument(verbosity, 'v', "verbose", "Verbose output on the console. Add additional 'v' flags to increase verbosity up to -vvv.", "Output"); + + api.addOptionArgument(silent, "silent", "No output on the console.", "Output"); + + api.parseArgs(flags); + + if (deprecated_includeSelfLinks) { + throw std::runtime_error("The --include-self-links flag is deprecated to include self links by default. Use --no-self-links to exclude."); + } + + if (!optionalOutputDir.empty()) + outDirectory = optionalOutputDir[0]; + + if (!isCLI && outDirectory.empty()) + noFileOutput = true; + + if (!noFileOutput && outDirectory.empty() && isCLI) { + throw std::runtime_error("Missing out_directory"); + } + + if (flowModelArg == "directed" || directed) { + setFlowModel(FlowModel::directed); + } else if (flowModelArg == "undirected") { + setFlowModel(FlowModel::undirected); + } else if (flowModelArg == "undirdir") { + setFlowModel(FlowModel::undirdir); + } else if (flowModelArg == "outdirdir") { + setFlowModel(FlowModel::outdirdir); + } else if (flowModelArg == "rawdir") { + setFlowModel(FlowModel::rawdir); + } else if (flowModelArg == "precomputed") { + setFlowModel(FlowModel::precomputed); + } else if (!flowModelArg.empty()) { + throw std::runtime_error(io::Str() << "Unrecognized flow model: '" << flowModelArg << "'"); + } + + if (regularized) { + recordedTeleportation = true; + } + + if (*--outDirectory.end() != '/') + outDirectory.append("/"); + + if (haveOutput() && !isDirectoryWritable(outDirectory)) + throw std::runtime_error(io::Str() << "Can't write to directory '" << outDirectory << "'. Check that the directory exists and that you have write permissions."); + + if (outName.empty()) { + outName = !networkFile.empty() ? FileURI(networkFile).getName() : "no-name"; + } + + if (noInfomap) { + numTrials = 1; + } + + parsedString = flags; + parsedOptions = api.getUsedOptionArguments(); + + if (printAllTrials && numTrials < 2) { + printAllTrials = false; + } + + adaptDefaults(); + + Log::init(verbosity, silent, verboseNumberPrecision); +} + +void Config::adaptDefaults() +{ + auto outputs = io::split(outputFormats, ','); + for (std::string& o : outputs) { + if (o == "clu") { + printClu = true; + } else if (o == "tree") { + printTree = true; + } else if (o == "ftree") { + printFlowTree = true; + } else if (o == "newick") { + printNewick = true; + } else if (o == "json") { + printJson = true; + } else if (o == "csv") { + printCsv = true; + } else if (o == "network") { + printPajekNetwork = true; + } else if (o == "flow") { + printFlowNetwork = true; + } else if (o == "states") { + printStateNetwork = true; + } else { + throw std::runtime_error(io::Str() << "Unrecognized output format: '" << o << "'."); + } + } + + // Of no output format specified, use tree as default (if not used as a library). + if (isCLI && !haveModularResultOutput()) { + printTree = true; + } +} + +std::ostream& operator<<(std::ostream& out, FlowModel f) +{ + return out << flowModelToString(f); +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/io/Config.h b/src/vendor/cigraph/vendor/infomap/src/io/Config.h new file mode 100644 index 00000000000..c7ce6112c04 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/Config.h @@ -0,0 +1,268 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#include "../utils/Date.h" +#include "../version.h" +#include "ProgramInterface.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace infomap { + +struct FlowModel { + static constexpr int undirected = 0; + static constexpr int directed = 1; + static constexpr int undirdir = 2; + static constexpr int outdirdir = 3; + static constexpr int rawdir = 4; + static constexpr int precomputed = 5; + + int value = 0; + + FlowModel(int val) : value(val) { } + FlowModel& operator=(int val) + { + value = val; + return *this; + } + + operator int&() { return value; } + operator int() const { return value; } +}; + +std::ostream& operator<<(std::ostream& out, FlowModel f); + +inline const char* flowModelToString(const FlowModel& flowModel) +{ + switch (flowModel) { + case FlowModel::directed: + return "directed"; + case FlowModel::undirdir: + return "undirdir"; + case FlowModel::outdirdir: + return "outdirdir"; + case FlowModel::rawdir: + return "rawdir"; + case FlowModel::precomputed: + return "precomputed"; + case FlowModel::undirected: + default: + return "undirected"; + } +} + +struct Config { + // Input + bool isCLI = false; + std::string networkFile; + std::vector additionalInput; + bool stateInput = false; + bool stateOutput = false; + bool multilayerInput = false; + double weightThreshold = 0.0; + bool bipartite = false; + bool skipAdjustBipartiteFlow = false; + bool bipartiteTeleportation = false; + bool noSelfLinks = false; // Replaces includeSelfLinks + unsigned int nodeLimit = 0; + unsigned int matchableMultilayerIds = 0; + std::string clusterDataFile; + std::string metaDataFile; + double metaDataRate = 1.0; + bool unweightedMetaData = false; + unsigned int numMetaDataDimensions = 0; + bool clusterDataIsHard = false; // FIXME Not used + bool assignToNeighbouringModule = false; + bool noInfomap = false; + + FlowModel flowModel = FlowModel::undirected; + bool flowModelIsSet = false; + bool directed = false; + bool useNodeWeightsAsFlow = false; + bool teleportToNodes = false; + double markovTime = 1.0; + bool variableMarkovTime = false; + double variableMarkovTimeDamping = 1.0; // 0 for linear scaling, 1 for log scaled. + double variableMarkovTimeMinLocalScale = 1; // Correspond to two links in undirected unweighted networks. Avoids division by zero. + bool markovTimeNoSelfLinks = false; + double multilayerRelaxRate = 0.15; + int multilayerRelaxLimit = -1; // Amount of layers allowed to jump up or down + int multilayerRelaxLimitUp = -1; // One-sided limit to higher layers + int multilayerRelaxLimitDown = -1; // One-sided limit to lower layers + double multilayerJSRelaxRate = 0.15; + bool multilayerRelaxByJensenShannonDivergence = false; + int multilayerJSRelaxLimit = -1; + + // Clustering + bool twoLevel = false; + bool noCoarseTune = false; + bool recordedTeleportation = false; + bool regularized = false; // Add a Bayesian prior network with recorded teleportation (sets recordedTeleportation and teleportToNodes to true) + double regularizationStrength = 1.0; // Scale Bayesian prior constant ln(N)/N with this factor + double teleportationProbability = 0.15; + unsigned int preferredNumberOfModules = 0; + bool entropyBiasCorrection = false; + double entropyBiasCorrectionMultiplier = 1; + /* unsigned long seedToRandomNumberGenerator = 123; */ + + // Performance and accuracy + unsigned int numTrials = 1; + double minimumCodelengthImprovement = 1e-10; + double minimumSingleNodeCodelengthImprovement = 1e-16; + bool randomizeCoreLoopLimit = false; + unsigned int coreLoopLimit = 10; + unsigned int levelAggregationLimit = 0; + unsigned int tuneIterationLimit = 0; // Iterations of fine-tune/coarse-tune in two-level partition + double minimumRelativeTuneIterationImprovement = 1e-5; + bool onlySuperModules = false; + unsigned int fastHierarchicalSolution = 0; + bool preferModularSolution = false; + bool innerParallelization = false; + + // Output + std::string outDirectory; + std::string outName; + std::string outputFormats; + bool printTree = false; + bool printFlowTree = false; + bool printNewick = false; + bool printJson = false; + bool printCsv = false; + bool printClu = false; + bool printAllTrials = false; + int cluLevel = 1; // Write modules at specified depth from root. 1, 2, ... or -1 for bottom level + bool printFlowNetwork = false; + bool printPajekNetwork = false; + bool printStateNetwork = false; + bool noFileOutput = false; + unsigned int verbosity = 0; + unsigned int verboseNumberPrecision = 9; + bool silent = false; + bool hideBipartiteNodes = false; + + // Other + Date startDate; + std::string version = INFOMAP_VERSION; + std::string parsedString; + std::vector parsedOptions; + infomap::interruptionHandlerFn *interruptionHandler = NULL; + + Config() = default; + + explicit Config(const std::string& flags, bool isCLI = false); + + Config& cloneAsNonMain(const Config& other) + { + isCLI = other.isCLI; + networkFile = other.networkFile; + additionalInput = other.additionalInput; + stateInput = other.stateInput; + stateOutput = other.stateOutput; + multilayerInput = other.multilayerInput; + weightThreshold = other.weightThreshold; + bipartite = other.bipartite; + skipAdjustBipartiteFlow = other.skipAdjustBipartiteFlow; + bipartiteTeleportation = other.bipartiteTeleportation; + noSelfLinks = other.noSelfLinks; + nodeLimit = other.nodeLimit; + matchableMultilayerIds = other.matchableMultilayerIds; + metaDataRate = other.metaDataRate; + unweightedMetaData = other.unweightedMetaData; + numMetaDataDimensions = other.numMetaDataDimensions; + assignToNeighbouringModule = other.assignToNeighbouringModule; + noInfomap = other.noInfomap; + flowModel = other.flowModel; + flowModelIsSet = other.flowModelIsSet; + directed = other.directed; + useNodeWeightsAsFlow = other.useNodeWeightsAsFlow; + teleportToNodes = other.teleportToNodes; + markovTime = other.markovTime; + variableMarkovTime = other.variableMarkovTime; + variableMarkovTimeDamping = other.variableMarkovTimeDamping; + markovTimeNoSelfLinks = other.markovTimeNoSelfLinks; + multilayerRelaxRate = other.multilayerRelaxRate; + multilayerRelaxLimit = other.multilayerRelaxLimit; + multilayerRelaxLimitUp = other.multilayerRelaxLimitUp; + multilayerRelaxLimitDown = other.multilayerRelaxLimitDown; + multilayerJSRelaxRate = other.multilayerJSRelaxRate; + multilayerRelaxByJensenShannonDivergence = other.multilayerRelaxByJensenShannonDivergence; + multilayerJSRelaxLimit = other.multilayerJSRelaxLimit; + twoLevel = other.twoLevel; + noCoarseTune = other.noCoarseTune; + recordedTeleportation = other.recordedTeleportation; + regularized = other.regularized; + regularizationStrength = other.regularizationStrength; + teleportationProbability = other.teleportationProbability; + entropyBiasCorrection = other.entropyBiasCorrection; + entropyBiasCorrectionMultiplier = other.entropyBiasCorrectionMultiplier; + // seedToRandomNumberGenerator = other.seedToRandomNumberGenerator; + minimumCodelengthImprovement = other.minimumCodelengthImprovement; + minimumSingleNodeCodelengthImprovement = other.minimumSingleNodeCodelengthImprovement; + randomizeCoreLoopLimit = other.randomizeCoreLoopLimit; + minimumRelativeTuneIterationImprovement = other.minimumRelativeTuneIterationImprovement; + preferModularSolution = other.preferModularSolution; + innerParallelization = other.innerParallelization; + outDirectory = other.outDirectory; + outName = other.outName; + outputFormats = other.outputFormats; + verbosity = other.verbosity; + verboseNumberPrecision = other.verboseNumberPrecision; + startDate = other.startDate; + version = other.version; + return *this; + } + + void adaptDefaults(); + + void setStateInput() { stateInput = true; } + + void setStateOutput() { stateOutput = true; } + + void setMultilayerInput() { multilayerInput = true; } + + void setFlowModel(FlowModel value) + { + flowModel = value; + flowModelIsSet = true; + } + + bool isUndirectedClustering() const { return flowModel == FlowModel::undirected; } + + bool isUndirectedFlow() const { return flowModel == FlowModel::undirected || flowModel == FlowModel::undirdir; } + + bool printAsUndirected() const { return isUndirectedClustering(); } + + bool isMultilayerNetwork() const { return multilayerInput || !additionalInput.empty(); } + bool isBipartite() const { return bipartite; } + + bool haveMemory() const { return stateInput; } + bool printStates() const { return stateOutput; } + + bool haveMetaData() const { return !metaDataFile.empty() || numMetaDataDimensions != 0; } + + bool haveOutput() const { return !noFileOutput; } + + bool haveModularResultOutput() const + { + return printTree || printFlowTree || printNewick || printJson || printCsv || printClu; + } +}; + +} // namespace infomap + +#endif // CONFIG_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/io/Network.cpp b/src/vendor/cigraph/vendor/infomap/src/io/Network.cpp new file mode 100644 index 00000000000..b405fd7a676 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/Network.cpp @@ -0,0 +1,990 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "Network.h" +#include "../io/SafeFile.h" +#include "../utils/FileURI.h" +#include "../utils/Log.h" + +#include +#include +#include + +namespace infomap { + +using std::make_pair; + +void Network::init() +{ + initValidHeadings(); + m_multilayerStateIdBitShift = static_cast(std::ceil(std::log2(m_config.matchableMultilayerIds))); +} + +void Network::initValidHeadings() +{ + auto& headingsPajek = m_validHeadings["pajek"]; + headingsPajek.insert("*vertices"); + headingsPajek.insert("*edges"); + headingsPajek.insert("*arcs"); + + auto& headingsLinklist = m_validHeadings["link-list"]; + headingsLinklist.insert("*links"); + headingsLinklist.insert("*edges"); + headingsLinklist.insert("*arcs"); + + auto& headingsBipartite = m_validHeadings["bipartite"]; + headingsBipartite.insert("*vertices"); + headingsBipartite.insert("*bipartite"); + + auto& headingsStates = m_validHeadings["states"]; + headingsStates.insert("*vertices"); + headingsStates.insert("*states"); + headingsStates.insert("*edges"); + headingsStates.insert("*arcs"); + headingsStates.insert("*links"); + headingsStates.insert("*contexts"); + auto& ignoreHeadingsStates = m_ignoreHeadings["states"]; + ignoreHeadingsStates.insert("*edges"); + ignoreHeadingsStates.insert("*contexts"); + + auto& headingsMultilayer = m_validHeadings["multilayer"]; + headingsMultilayer.insert("*vertices"); + headingsMultilayer.insert("*multiplex"); + headingsMultilayer.insert("*multilayer"); + headingsMultilayer.insert("*intra"); + headingsMultilayer.insert("*inter"); + + auto& headingsGeneral = m_validHeadings["general"]; + headingsGeneral.insert("*vertices"); + headingsGeneral.insert("*states"); + headingsGeneral.insert("*multilayer"); + headingsGeneral.insert("*intra"); + headingsGeneral.insert("*inter"); + headingsGeneral.insert("*paths"); + headingsGeneral.insert("*edges"); + headingsGeneral.insert("*arcs"); + headingsGeneral.insert("*links"); + headingsGeneral.insert("*contexts"); + headingsGeneral.insert("*bipartite"); + auto& ignoreHeadingsGeneral = m_ignoreHeadings["general"]; + ignoreHeadingsGeneral.insert("*contexts"); +} + +void Network::clear() +{ + StateNetwork::clear(); + m_networks.clear(); + m_interLinks.clear(); + m_layerNodeToStateId.clear(); + m_sumIntraOutWeight.clear(); + m_layers.clear(); + m_numInterLayerLinks = 0; + m_numIntraLayerLinks = 0; + + // Bipartite + m_bipartiteStartId = 0; + + // Meta data + m_metaData.clear(); + m_numMetaDataColumns = 0; +} + +void Network::readInputData(std::string filename, bool accumulate) +{ + if (!accumulate) { + clear(); + } + if (filename.empty()) + filename = m_config.networkFile; + if (filename.empty()) { + throw std::runtime_error("No input file to read network"); + } + FileURI networkFilename(filename, false); + + parseNetwork(filename); + printSummary(); +} + +void Network::parseNetwork(const std::string& filename) +{ + Log() << "Parsing " << (m_config.isUndirectedFlow() ? "undirected" : "directed") << " network from file '" << filename << "'...\n"; + + parseNetwork(filename, m_validHeadings["general"], m_ignoreHeadings["general"]); +} + +void Network::parseNetwork(const std::string& filename, const InsensitiveStringSet& validHeadings, const InsensitiveStringSet& ignoreHeadings, const std::string& startHeading) +{ + m_haveFileInput = true; + SafeInFile input(filename); + + // Parse standard links by default until possible heading is reached + std::string heading = startHeading.length() > 0 ? startHeading : parseLinks(input); + + while (heading.length() > 0 && heading[0] == '*') { + std::string headingLowerCase = io::tolower(io::firstWord(heading)); + if (validHeadings.count(headingLowerCase) == 0) { + throw std::runtime_error(io::Str() << "Unrecognized heading in network file: '" << headingLowerCase << "'."); + } + if (ignoreHeadings.count(headingLowerCase) > 0) { + heading = ignoreSection(input, headingLowerCase); + } else if (headingLowerCase == "*vertices") { + heading = parseVertices(input, heading); + } else if (headingLowerCase == "*states") { + heading = parseStateNodes(input, heading); + } else if (headingLowerCase == "*edges") { + if (!m_config.isUndirectedFlow()) + Log() << "\n --> Notice: Links marked as undirected but parsed as directed.\n"; + heading = parseLinks(input); + } else if (headingLowerCase == "*arcs") { + if (m_config.isUndirectedFlow()) + Log() << "\n --> Notice: Links marked as directed but parsed as undirected.\n"; + heading = parseLinks(input); + } else if (headingLowerCase == "*links") { + heading = parseLinks(input); + } else if (headingLowerCase == "*multilayer" || headingLowerCase == "*multiplex") { + heading = parseMultilayerLinks(input); + } else if (headingLowerCase == "*intra") { + heading = parseMultilayerIntraLinks(input); + } else if (headingLowerCase == "*inter") { + heading = parseMultilayerInterLinks(input); + } else if (headingLowerCase == "*bipartite") { + heading = parseBipartiteLinks(input, heading); + } else { + heading = ignoreSection(input, headingLowerCase); + } + } + + postProcessInputData(); + Log() << "Done!\n"; +} + +void Network::postProcessInputData() +{ + if (!m_networks.empty()) { + generateStateNetworkFromMultilayer(); + } + + if (!haveMemoryInput()) { + // If no memory input, add physical nodes as state nodes to not miss unconnected nodes + for (auto& it : m_physNodes) { + addNode(it.second.physId, it.second.weight); + } + } +} + +void Network::readMetaData(const std::string& filename) +{ + Log() << "Parsing meta data from '" << filename << "'...\n"; + SafeInFile input(filename); + std::string line; + while (!std::getline(input, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + m_extractor.clear(); + m_extractor.str(line); + + unsigned int nodeId; + if (!(m_extractor >> nodeId)) + throw std::runtime_error(io::Str() << "Can't parse node id from line '" << line << "'"); + + std::vector metaData; + unsigned int metaId; + while (m_extractor >> metaId) { + metaData.push_back(metaId); + } + if (metaData.empty()) + throw std::runtime_error(io::Str() << "Can't parse any meta data from line '" << line << "'"); + + addMetaData(nodeId, metaData); + } + Log() << " -> Parsed " << m_numMetaDataColumns << " columns of meta data for " << m_metaData.size() << " nodes.\n"; +} +////////////////////////////////////////////////////////////////////////////////////////// +// +// HELPER METHODS +// +////////////////////////////////////////////////////////////////////////////////////////// + +std::string Network::parseVertices(std::ifstream& file, const std::string& /*heading*/) +{ + Log() << " Parsing vertices...\n" + << std::flush; + std::string line; + while (!std::getline(file, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + m_extractor.clear(); + m_extractor.str(line); + + unsigned int id = 0; + if (!(m_extractor >> id)) + throw std::runtime_error(io::Str() << "Can't parse node id from line '" << line << "'"); + + auto nameStart = line.find_first_of('\"'); + auto nameEnd = line.find_last_of('\"'); + std::string name; + if (nameStart < nameEnd) { + name = std::string(line.begin() + nameStart + 1, line.begin() + nameEnd); + line = line.substr(nameEnd + 1); + m_extractor.clear(); + m_extractor.str(line); + } else { + if (!(m_extractor >> name)) + throw std::runtime_error(io::Str() << "Can't parse node name from line '" << line << "'"); + } + double weight = 1.0; + if ((m_extractor >> weight)) { + m_haveNodeWeights = true; + if (weight < 0) + throw std::runtime_error(io::Str() << "Negative node weight (" << weight << ") from line '" << line << "'"); + } + + addPhysicalNode(id, weight, name); + } + Log() << " -> " << m_physNodes.size() << " physical nodes added\n"; + return line; +} + +std::string Network::parseStateNodes(std::ifstream& file, const std::string& /*heading*/) +{ + m_higherOrderInputMethodCalled = true; + Log() << " Parsing state nodes...\n" + << std::flush; + std::string line; + while (!std::getline(file, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + StateNode stateNode; + parseStateNode(line, stateNode); + + addStateNode(stateNode); + addPhysicalNode(stateNode.physicalId); + + ++m_numStateNodesFound; + } + Log() << " -> " << m_numStateNodesFound << " state nodes added\n"; + return line; +} + +std::string Network::parseLinks(std::ifstream& file) +{ + // This is the default action, so check for links before printing + bool parsingLinks = false; + std::string line; + while (!std::getline(file, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + if (!parsingLinks) { + parsingLinks = true; + Log() << " Parsing links...\n" + << std::flush; + } + + unsigned int n1, n2; + double weight; + parseLink(line, n1, n2, weight); + + addLink(n1, n2, weight); + } + if (parsingLinks) + Log() << " -> " << m_numLinks << " links\n"; + return line; +} + +std::string Network::parseMultilayerLinks(std::ifstream& file) +{ + Log() << " Parsing multilayer links...\n" + << std::flush; + + if (m_config.matchableMultilayerIds > 0) { + Log() << " Creating matchable state ids using: nodeId << (log2(" << m_config.matchableMultilayerIds << ") + 1) | layerId\n"; + } + + std::string line; + while (!std::getline(file, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + unsigned int layer1, n1, layer2, n2; + double weight; + parseMultilayerLink(line, layer1, n1, layer2, n2, weight); + + // TODO: This explicit multilayer format can allow undirected but not the inter/intra format, clear? + addMultilayerLink(layer1, n1, layer2, n2, weight); + } + Log() << " -> " << (m_numIntraLayerLinks + m_numInterLayerLinks) << " links in " << m_layers.size() << " layers\n"; + Log() << " -> " << m_numIntraLayerLinks << " intra-layer links\n"; + Log() << " -> " << m_numInterLayerLinks << " inter-layer links\n"; + return line; +} + +std::string Network::parseMultilayerIntraLinks(std::ifstream& file) +{ + Log() << " Parsing intra-layer links...\n" + << std::flush; + + if (m_config.matchableMultilayerIds > 0) { + Log() << " Creating matchable state ids using: nodeId << (log2(" << m_config.matchableMultilayerIds << ") + 1) | layerId\n"; + } + + std::string line; + while (!std::getline(file, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + unsigned int layer, n1, n2; + double weight; + parseMultilayerIntraLink(line, layer, n1, n2, weight); + + addMultilayerIntraLink(layer, n1, n2, weight); + } + Log() << " -> " << m_numIntraLayerLinks << " intra-layer links\n"; + return line; +} + +std::string Network::parseMultilayerInterLinks(std::ifstream& file) +{ + Log() << " Parsing inter-layer links...\n" + << std::flush; + std::string line; + while (!std::getline(file, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + unsigned int layer1, n, layer2; + double weight; + parseMultilayerInterLink(line, layer1, n, layer2, weight); + + addMultilayerInterLink(layer1, n, layer2, weight); + } + Log() << " -> " << m_numInterLayerLinks << " inter-layer links\n"; + return line; +} + +std::string Network::parseBipartiteLinks(std::ifstream& file, const std::string& heading) +{ + Log() << " Parsing bipartite links...\n"; + // Extract break point for bipartite links + m_extractor.clear(); + m_extractor.str(heading); + std::string tmp; + if (!(m_extractor >> tmp >> m_bipartiteStartId)) + throw std::runtime_error(io::Str() << "Can't parse bipartite start id from line '" << heading << "'"); + + Log() << " -> Using bipartite start id " << m_bipartiteStartId << "\n"; + m_config.bipartite = true; + std::string line; + while (!std::getline(file, line).fail()) { + if (line.length() == 0 || line[0] == '#') + continue; + + if (line[0] == '*') + break; + + unsigned int n1, n2; + double weight; + parseLink(line, n1, n2, weight); + bool sourceIsFeature = n1 >= m_bipartiteStartId; + bool targetIsFeature = n2 >= m_bipartiteStartId; + if (sourceIsFeature == targetIsFeature) { + throw std::runtime_error(io::Str() << "Bipartite link '" << line << "' must cross bipartite start id " << m_bipartiteStartId << "."); + } + addLink(n1, n2, weight); + } + return line; +} + +std::string Network::ignoreSection(std::ifstream& file, const std::string& heading) +{ + Log() << "(Ignoring section " << heading << ") "; + std::string line; + while (!std::getline(file, line).fail()) { + if (line[0] == '*') + break; + } + return line; +} + +void Network::parseStateNode(const std::string& line, StateNetwork::StateNode& stateNode) +{ + m_extractor.clear(); + m_extractor.str(line); + if (!(m_extractor >> stateNode.id >> stateNode.physicalId)) + throw std::runtime_error(io::Str() << "Can't parse any state node from line '" << line << "'"); + + // Optional name enclosed in double quotes + auto nameStart = line.find_first_of('\"', m_extractor.tellg()); + auto nameEnd = line.find_last_of('\"'); + if (nameStart < nameEnd) { + stateNode.name = std::string(line.begin() + nameStart + 1, line.begin() + nameEnd); + m_extractor.seekg(nameEnd + 1); + } + // Optional weight, default to 1.0 + if ((m_extractor >> stateNode.weight)) { + m_haveStateNodeWeights = true; + if (stateNode.weight < 0) + throw std::runtime_error(io::Str() << "Negative state node weight (" << stateNode.weight << ") from line '" << line << "'"); + } +} + +void Network::parseLink(const std::string& line, unsigned int& n1, unsigned int& n2, double& weight) +{ + m_extractor.clear(); + m_extractor.str(line); + if (!(m_extractor >> n1 >> n2)) + throw std::runtime_error(io::Str() << "Can't parse link data from line '" << line << "'"); + (m_extractor >> weight) || (weight = 1.0); +} + +void Network::parseMultilayerLink(const std::string& line, unsigned int& layer1, unsigned int& n1, unsigned int& layer2, unsigned int& n2, double& weight) +{ + m_extractor.clear(); + m_extractor.str(line); + if (!(m_extractor >> layer1 >> n1 >> layer2 >> n2)) + throw std::runtime_error(io::Str() << "Can't parse multilayer link data from line '" << line << "'"); + (m_extractor >> weight) || (weight = 1.0); +} + +void Network::parseMultilayerIntraLink(const std::string& line, unsigned int& layer, unsigned int& n1, unsigned int& n2, double& weight) +{ + m_extractor.clear(); + m_extractor.str(line); + if (!(m_extractor >> layer >> n1 >> n2)) + throw std::runtime_error(io::Str() << "Can't parse intra-multilayer link data from line '" << line << "'"); + (m_extractor >> weight) || (weight = 1.0); +} + +void Network::parseMultilayerInterLink(const std::string& line, unsigned int& layer1, unsigned int& n, unsigned int& layer2, double& weight) +{ + m_extractor.clear(); + m_extractor.str(line); + if (!(m_extractor >> layer1 >> n >> layer2)) + throw std::runtime_error(io::Str() << "Can't parse inter-multilayer link data from line '" << line << "'"); + (m_extractor >> weight) || (weight = 1.0); + if (layer1 == layer2) + throw std::runtime_error(io::Str() << "Inter-layer link from line '" << line << "' doesn't go between different layers."); + // TODO: Same as intra-layer self-link? +} + +void Network::printSummary() +{ + Log() << "-------------------------------------\n"; + if (haveMemoryInput()) { + Log() << " -> " << numNodes() << " state nodes\n"; + Log() << " -> " << numPhysicalNodes() << " physical nodes\n"; + } else { + if (m_bipartiteStartId > 0) + Log() << " -> " << numNodes() << " bipartite nodes\n"; + else + Log() << " -> " << numNodes() << " nodes\n"; + } + Log() << " -> " << numLinks() << " links with total weight " << m_totalLinkWeightAdded << "\n"; + if (m_numLinksIgnoredByWeightThreshold > 0) { + Log() << " -> " << m_numLinksIgnoredByWeightThreshold << " links ignored by weight threshold with total weight " << m_totalLinkWeightIgnored << " (" << io::toPrecision(m_totalLinkWeightIgnored / (m_totalLinkWeightIgnored + m_totalLinkWeightAdded) * 100, 1, true) << "%)\n"; + } +} + +void Network::addMultilayerLink(unsigned int layer1, unsigned int n1, unsigned int layer2, unsigned int n2, double weight) +{ + m_higherOrderInputMethodCalled = true; + if (weight < m_config.weightThreshold) { + ++m_numLinksIgnoredByWeightThreshold; + m_totalLinkWeightIgnored += weight; + return; + } + unsigned int stateId1 = addMultilayerNode(layer1, n1); + unsigned int stateId2 = addMultilayerNode(layer2, n2); + + if (stateId1 == stateId2) { + // TODO: Handle self-links? + } + + if (layer1 == layer2) { + ++m_numIntraLayerLinks; + m_sumIntraOutWeight[layer1][n1] += weight; // TODO: Not used? Add on target also if undirected (not inter/intra format)? + } else { + ++m_numInterLayerLinks; + } + + addLink(stateId1, stateId2, weight); +} + +void Network::generateStateNetworkFromMultilayer() +{ + // As inter-layer links is directed to neighbouring nodes in target layer, + // the symmetry is broken so we need directed links for inter-layer flow + m_haveDirectedInput = true; + if (m_config.isUndirectedFlow()) { + // TODO: Don't allow undirdir/outdirdir/rawdir? + // Expand each undirected intra-layer link to two opposite directed links + Log() << " -> Expanding undirected links to directed...\n"; + for (auto& layerIt : m_networks) { + auto& network = layerIt.second; + network.undirectedToDirected(); + } + } + + if (!m_interLinks.empty()) { + generateStateNetworkFromMultilayerWithInterLinks(); + } else { + generateStateNetworkFromMultilayerWithSimulatedInterLinks(); + } + m_networks.clear(); + m_interLinks.clear(); +} + +void Network::generateStateNetworkFromMultilayerWithInterLinks() +{ + Log() << "Generating state network from multilayer networks with inter-layer links...\n" + << std::flush; + // First add intra-layer links + for (auto& layerIt : m_networks) { + unsigned int layer1 = layerIt.first; + auto& network = layerIt.second; + for (auto& linkIt : network.nodeLinkMap()) { + auto& source = linkIt.first; + const auto& subLinks = linkIt.second; + for (auto& subIt : subLinks) { + auto& target = subIt.first; + double linkWeight = subIt.second.weight; + addMultilayerLink(layer1, source.physicalId, layer1, target.physicalId, linkWeight); + } + } + } + + Log() << "Connecting layers...\n"; + // Connect layers with inter-layer links spread out in target layer + for (auto& it : m_interLinks) { + auto& layerNode = it.first; + unsigned int layer1 = layerNode.layer; + unsigned int physId = layerNode.node; + unsigned int stateId1 = addMultilayerNode(layer1, physId); + for (auto& it2 : it.second) { + unsigned int layer2 = it2.first; + double interWeight = it2.second; + auto& targetNetwork = m_networks[layer2]; + + std::map>& targetLinks = targetNetwork.nodeLinkMap(); + auto& outlinks = targetLinks[StateNode(physId)]; + if (outlinks.empty()) { + continue; + } + auto& targetOutWeights = targetNetwork.outWeights(); + double sumIntraOutWeightTargetLayer = targetOutWeights[physId]; + + for (auto& outLink : outlinks) { + auto& targetPhysId = outLink.first.physicalId; + auto& linkData = outLink.second; + double intraWeight = linkData.weight; + unsigned int stateId2i = addMultilayerNode(layer2, targetPhysId); + + double weight = sumIntraOutWeightTargetLayer == 0.0 ? 0.0 : interWeight * intraWeight / sumIntraOutWeightTargetLayer; + + addLink(stateId1, stateId2i, weight); + ++m_numInterLayerLinks; // TODO: Count all as one? + } + } + } + if (m_config.isUndirectedFlow()) { + // For undirected inter-layer links, expand and add in other direction too + for (auto& it : m_interLinks) { + auto& layerNode = it.first; + unsigned int layer2 = layerNode.layer; + unsigned int physId = layerNode.node; + auto& targetNetwork = m_networks[layer2]; + std::map>& targetLinks = targetNetwork.nodeLinkMap(); + auto& outlinks = targetLinks[StateNode(physId)]; + if (outlinks.empty()) { + continue; + } + auto& targetOutWeights = targetNetwork.outWeights(); + double sumIntraOutWeightTargetLayer = targetOutWeights[physId]; + for (auto& it2 : it.second) { + unsigned int layer1 = it2.first; + double interWeight = it2.second; + unsigned int stateId1 = addMultilayerNode(layer1, physId); + + for (auto& outLink : outlinks) { + auto& targetPhysId = outLink.first.physicalId; + auto& linkData = outLink.second; + double intraWeight = linkData.weight; + unsigned int stateId2i = addMultilayerNode(layer2, targetPhysId); + + double weight = sumIntraOutWeightTargetLayer == 0.0 ? 0.0 : interWeight * intraWeight / sumIntraOutWeightTargetLayer; + + addLink(stateId1, stateId2i, weight); + ++m_numInterLayerLinks; // TODO: Count all as one? + } + } + } + } +} + +void Network::generateStateNetworkFromMultilayerWithSimulatedInterLinks() +{ + Log() << "Generating state network from multilayer networks with simulated inter-layer links...\n" + << std::flush; + double relaxRate = m_config.multilayerRelaxRate; + + int maxRelaxLimit = m_networks.size(); + int relaxLimitSymmetric = m_config.multilayerRelaxLimit < 0 ? maxRelaxLimit : m_config.multilayerRelaxLimit; + int relaxLimitDown = m_config.multilayerRelaxLimitDown < 0 ? relaxLimitSymmetric : std::min(relaxLimitSymmetric, m_config.multilayerRelaxLimitDown); + int relaxLimitUp = m_config.multilayerRelaxLimitUp < 0 ? relaxLimitSymmetric : std::min(relaxLimitSymmetric, m_config.multilayerRelaxLimitUp); + auto haveUpOrDownLimit = m_config.multilayerRelaxLimitDown >= 0 || m_config.multilayerRelaxLimitUp >= 0; + + Log() << "-> " << m_networks.size() << " networks\n"; + Log() << "-> Relax rate: " << relaxRate << "\n"; + if (haveUpOrDownLimit) { + Log() << "-> Relax limit up: " << relaxLimitUp << (relaxLimitUp == maxRelaxLimit ? " (no limit)\n" : "\n"); + Log() << "-> Relax limit down: " << relaxLimitDown << (relaxLimitDown == maxRelaxLimit ? " (no limit)\n" : "\n"); + } else if (m_config.multilayerRelaxLimit >= 0) { + Log() << "-> Relax limit: " << m_config.multilayerRelaxLimit << "\n"; + } + + auto withinRelaxLimit = [relaxLimitDown, relaxLimitUp](auto& layer1, auto& layer2) { + int diff = layer1 - layer2; + return layer1 >= layer2 ? diff <= relaxLimitDown : -diff <= relaxLimitUp; + }; + + if (m_config.multilayerRelaxByJensenShannonDivergence) { + Log() << "-> Using Jensen-Shannon Divergence\n"; + + for (unsigned int nodeId = 0; nodeId <= m_maxNodeIdInIntraLayerNetworks; ++nodeId) { + unsigned int layer2from = 0; + + // Calculate Jensen-Shannon similarity between all layers such that layer1 >= layer2, + // and then use its symmetry for layer2 > layer1 + std::map> jsRelaxWeights; + std::map jsTotWeight; + + for (unsigned int layer1 = 0; layer1 < m_networks.size(); ++layer1) { + unsigned int layer2to = layer1 + 1; + // Limit possible jumps to close by layers + if (m_config.multilayerRelaxLimit >= 0) { + layer2from = ((int)layer1 - m_config.multilayerRelaxLimit) < 0 ? 0 : layer1 - m_config.multilayerRelaxLimit; + } + + auto& layer1LinkMap = m_networks[layer1].nodeLinkMap(); + auto& layer1OutLinks = layer1LinkMap[StateNode(nodeId)]; + // Skip dangling nodes, because they have no information to calculate similarity + if (layer1OutLinks.empty()) + continue; + + double sumOutLinkWeightLayer1 = m_networks[layer1].outWeights()[nodeId]; + + for (unsigned int layer2 = layer2from; layer2 < layer2to; ++layer2) { + auto& layer2LinkMap = m_networks[layer2].nodeLinkMap(); + auto& layer2OutLinks = layer2LinkMap[StateNode(nodeId)]; + if (layer2OutLinks.empty()) + continue; + + double sumOutLinkWeightLayer2 = m_networks[layer2].outWeights()[nodeId]; + + bool intersect; + double div = calculateJensenShannonDivergence(intersect, layer1OutLinks, sumOutLinkWeightLayer1, layer2OutLinks, sumOutLinkWeightLayer2); + double jsWeight = 1.0 - div; + if (intersect && (jsWeight >= m_config.multilayerJSRelaxLimit)) { + jsTotWeight[layer1] += jsWeight; + jsRelaxWeights[layer1][layer2] = jsWeight; + if (layer1 != layer2) { + jsTotWeight[layer2] += jsWeight; + jsRelaxWeights[layer2][layer1] = jsWeight; + } + } + } + } + + // Second loop over all pairs of layers + unsigned int layer2to = m_networks.size(); + + for (unsigned int layer1 = 0; layer1 < m_networks.size(); ++layer1) { + // Limit possible jumps to close by layers + if (m_config.multilayerRelaxLimit >= 0) { + layer2from = ((int)layer1 - m_config.multilayerRelaxLimit) < 0 ? 0 : layer1 - m_config.multilayerRelaxLimit; + layer2to = (layer1 + m_config.multilayerRelaxLimit) > m_networks.size() ? m_networks.size() : layer1 + m_config.multilayerRelaxLimit; + } + + double sumOutLinkWeightLayer1 = m_networks[layer1].outWeights()[nodeId]; + + auto jsRelaxWeightsLayer1It = jsRelaxWeights.find(layer1); + auto jsTotWeightIt = jsTotWeight.find(layer1); + + // Create inter-links to the intra-connected nodes in other layers + for (unsigned int layer2 = layer2from; layer2 < layer2to; ++layer2) { + if (jsRelaxWeightsLayer1It != jsRelaxWeights.end()) { + auto jsRelaxWeightsIt = jsRelaxWeightsLayer1It->second.find(layer2); + if (jsRelaxWeightsIt != jsRelaxWeightsLayer1It->second.end()) { + bool isIntra = layer2 == layer1; + + // Create inter-links to the outgoing nodes in the target layer + double linkWeightNormalizationFactor; + if (isIntra) { + linkWeightNormalizationFactor = 1; + } else { + linkWeightNormalizationFactor = jsRelaxWeightsIt->second * relaxRate / (1.0 - relaxRate) * sumOutLinkWeightLayer1 / jsTotWeightIt->second; + } + + auto& targetLinks = m_networks[layer2].nodeLinkMap(); + auto& targetOutlinks = targetLinks[StateNode(nodeId)]; + if (targetOutlinks.empty()) { + continue; + } + for (auto& outLink : targetOutlinks) { + auto& n2 = outLink.first.physicalId; + auto& linkData = outLink.second; + double intraWeight = linkData.weight; + // Add intra link weight as teleport weight to source node + unsigned int stateId1 = addMultilayerNode(layer1, nodeId, intraWeight); + unsigned int stateId2i = addMultilayerNode(layer2, n2, 0.0); + + double weight = intraWeight == 0.0 ? 0.0 : linkWeightNormalizationFactor * intraWeight; + addLink(stateId1, stateId2i, weight); + ++m_numInterLayerLinks; + } + } + } + } + } + } + + return; + } + + for (auto& it1 : m_networks) { + auto layer1 = it1.first; + auto& network1 = it1.second; + + for (auto& n1It : network1.nodes()) { + auto& n1 = n1It.first; + unsigned int stateId1 = addMultilayerNode(layer1, n1); + + double sumOutLinkWeightLayer1 = network1.outWeights()[n1]; + double sumOutWeightAllLayers = 0.0; + + for (auto& it2 : m_networks) { + auto layer2 = it2.first; + if (!withinRelaxLimit(layer1, layer2)) { + continue; + } + auto& network2 = it2.second; + sumOutWeightAllLayers += network2.outWeights()[n1]; + } + + if (sumOutWeightAllLayers <= 0) { + continue; + } + for (auto& it2 : m_networks) { + auto layer2 = it2.first; + if (!withinRelaxLimit(layer1, layer2)) { + continue; + } + auto& network2 = it2.second; + bool isIntra = layer2 == layer1; + + double linkWeightNormalizationFactor = relaxRate / sumOutWeightAllLayers; + if (isIntra) { + linkWeightNormalizationFactor += (1.0 - relaxRate) / sumOutLinkWeightLayer1; + } + + auto& targetLinks = network2.nodeLinkMap(); + auto& targetOutlinks = targetLinks[StateNode(n1)]; + if (targetOutlinks.empty()) { + continue; + } + for (auto& outLink : targetOutlinks) { + auto& n2 = outLink.first.physicalId; + auto& linkData = outLink.second; + double intraWeight = linkData.weight; + unsigned int stateId2i = addMultilayerNode(layer2, n2); + + double weight = intraWeight == 0.0 ? 0.0 : linkWeightNormalizationFactor * intraWeight; + addLink(stateId1, stateId2i, weight); + ++m_numInterLayerLinks; // TODO: Count all as one? + } + } + } + } +} + +double Network::calculateJensenShannonDivergence(bool& intersect, const OutLinkMap& layer1OutLinks, double sumOutLinkWeightLayer1, const OutLinkMap& layer2OutLinks, double sumOutLinkWeightLayer2) +{ + intersect = false; + double h1 = 0.0; // The entropy rate of the node in the first layer + double h2 = 0.0; // The entropy rate of the node in the second layer + double h12 = 0.0; // The entropy rate of the lumped node + // The out-link weights of the nodes + double ow1 = sumOutLinkWeightLayer1; + double ow2 = sumOutLinkWeightLayer2; + // Normalized weights over node in layer 1 and 2 + double pi1 = ow1 / (ow1 + ow2); + double pi2 = ow2 / (ow1 + ow2); + + auto layer1OutLinkIt = layer1OutLinks.begin(); + auto layer2OutLinkIt = layer2OutLinks.begin(); + auto layer1OutLinkItEnd = layer1OutLinks.end(); + auto layer2OutLinkItEnd = layer2OutLinks.end(); + while (layer1OutLinkIt != layer1OutLinkItEnd && layer2OutLinkIt != layer2OutLinkItEnd) { + int diff = layer1OutLinkIt->first.id - layer2OutLinkIt->first.id; + if (diff < 0) { + // If the first state node has a link that the second has not + double p1 = layer1OutLinkIt->second.weight / ow1; + h1 -= p1 * log2(p1); + double p12 = pi1 * layer1OutLinkIt->second.weight / ow1; + h12 -= p12 * log2(p12); + layer1OutLinkIt++; + } else if (diff > 0) { + // If the second state node has a link that the second has not + double p2 = layer2OutLinkIt->second.weight / ow2; + h2 -= p2 * log2(p2); + double p12 = pi2 * layer2OutLinkIt->second.weight / ow2; + h12 -= p12 * log2(p12); + layer2OutLinkIt++; + } else { // If both state nodes have the link + intersect = true; + double p1 = layer1OutLinkIt->second.weight / ow1; + h1 -= p1 * log2(p1); + double p2 = layer2OutLinkIt->second.weight / ow2; + h2 -= p2 * log2(p2); + double p12 = pi1 * layer1OutLinkIt->second.weight / ow1 + pi2 * layer2OutLinkIt->second.weight / ow2; + h12 -= p12 * log2(p12); + layer1OutLinkIt++; + layer2OutLinkIt++; + } + } + + while (layer1OutLinkIt != layer1OutLinkItEnd) { + // If the first state node has a link that the second has not + double p1 = layer1OutLinkIt->second.weight / ow1; + h1 -= p1 * log2(p1); + double p12 = pi1 * layer1OutLinkIt->second.weight / ow1; + h12 -= p12 * log2(p12); + layer1OutLinkIt++; + } + + while (layer2OutLinkIt != layer2OutLinkItEnd) { + // If the second state node has a link that the second has not + double p2 = layer2OutLinkIt->second.weight / ow2; + h2 -= p2 * log2(p2); + double p12 = pi2 * layer2OutLinkIt->second.weight / ow2; + h12 -= p12 * log2(p12); + layer2OutLinkIt++; + } + + double div = (pi1 + pi2) * h12 - pi1 * h1 - pi2 * h2; + + // Fix precision problems + if (div < 0.0) + div = 0.0; + else if (div > 1.0) + div = 1.0; + + return div; +} + +void Network::simulateInterLayerLinks() +{ +} + +void Network::addMultilayerIntraLink(unsigned int layer, unsigned int n1, unsigned int n2, double weight) +{ + m_higherOrderInputMethodCalled = true; + bool added = m_networks[layer].addLink(n1, n2, weight); + if (added) { + ++m_numIntraLayerLinks; + m_maxNodeIdInIntraLayerNetworks = std::max(m_maxNodeIdInIntraLayerNetworks, std::max(n1, n2)); + } +} + +void Network::addMultilayerInterLink(unsigned int layer1, unsigned int n, unsigned int layer2, double interWeight) +{ + if (layer1 == layer2) { + throw std::runtime_error(io::Str() << "Inter-layer link (layer1, node, layer2): " << layer1 << ", " << n << ", " << layer2 << " must have layer1 != layer2"); + } + m_higherOrderInputMethodCalled = true; + + auto& interLinks = m_interLinks[LayerNode(layer1, n)]; + auto it = interLinks.find(layer2); + + if (it == interLinks.end()) { + ++m_numInterLayerLinks; + } + interLinks[layer2] += interWeight; +} + +unsigned int Network::addMultilayerNode(unsigned int layerId, unsigned int physicalId, double weight) +{ + m_higherOrderInputMethodCalled = true; + + // Create state node if not already exist, return state node id + auto& layerIt = m_layerNodeToStateId[layerId]; + auto it = layerIt.find(physicalId); + + if (it != layerIt.end()) { + return it->second; + } + + bool matchableMultilayerIds = m_config.matchableMultilayerIds != 0; + + if (matchableMultilayerIds && layerId > m_config.matchableMultilayerIds) { + throw std::runtime_error(io::Str() << "Cannot add node with layer " << layerId << " to network with matchable multilayer ids using largest layer id " << m_config.matchableMultilayerIds); + } + + auto ret = matchableMultilayerIds + ? addStateNodeWithDeterministicId(physicalId, layerId, m_multilayerStateIdBitShift) + : addStateNodeWithAutogeneratedId(physicalId); + auto& stateNode = ret.first->second; + stateNode.layerId = layerId; + stateNode.weight = weight; + m_layerNodeToStateId[layerId][physicalId] = stateNode.id; + m_layers.insert(layerId); + return stateNode.id; +} + +void Network::addMetaData(unsigned int nodeId, int meta) +{ + std::vector metaData(1, meta); + addMetaData(nodeId, metaData); +} + +void Network::addMetaData(unsigned int nodeId, const std::vector& metaData) +{ + m_metaData[nodeId] = metaData; + if (m_numMetaDataColumns == 0) { + m_numMetaDataColumns = metaData.size(); + } else if (metaData.size() != m_numMetaDataColumns) { + throw std::runtime_error(io::Str() << "Must have same number of dimensions in meta data, error trying to add meta data '" << io::stringify(metaData, ",") << "' on node " << nodeId << "."); + } +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/io/Network.h b/src/vendor/cigraph/vendor/infomap/src/io/Network.h new file mode 100644 index 00000000000..a801db6927c --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/Network.h @@ -0,0 +1,214 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef NETWORK_H_ +#define NETWORK_H_ + +#include "Config.h" +#include "../core/StateNetwork.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace infomap { + +struct LayerNode; + +class Network : public StateNetwork { +private: + // Helpers + std::istringstream m_extractor; + + // Multilayer + std::map m_networks; // intra-layer links + std::map> m_interLinks; + // { layer -> { physId -> stateId }} + std::map> m_layerNodeToStateId; + std::map> m_sumIntraOutWeight; + std::set m_layers; + unsigned int m_numInterLayerLinks = 0; + unsigned int m_numIntraLayerLinks = 0; + unsigned int m_maxNodeIdInIntraLayerNetworks = 0; + + unsigned int m_multilayerStateIdBitShift = 0; + + // Meta data + std::map> m_metaData; + unsigned int m_numMetaDataColumns = 0; + + using InsensitiveStringSet = std::set; + + std::map m_ignoreHeadings; + std::map m_validHeadings; // { + // { "pajek", {"*Vertices", "*Edges", "*Arcs"} }, + // { "link-list", {"*Links"} }, + // { "bipartite", {"*Vertices", "*Bipartite"} }, + // { "general", {"*Vertices", "*States", "*Edges", "*Arcs", "*Links", "*Context"} } + // }; + +public: + Network() : StateNetwork() { init(); } + explicit Network(const Config& config) : StateNetwork(config) { init(); } + explicit Network(const std::string& flags) : StateNetwork(Config(flags)) { init(); } + ~Network() override = default; + + Network(const Network&) = delete; + Network& operator=(const Network&) = delete; + Network(Network&&) = delete; + Network& operator=(Network&&) = delete; + + void clear() override; + + /** + * Parse network data from file and generate network + * @param filename input network + * @param accumulate add to possibly existing network data (default), else clear before. + */ + virtual void readInputData(std::string filename = "", bool accumulate = true); + + /** + * Init categorical meta data on all nodes from a file with the following format: + * # nodeId metaData + * 1 1 + * 2 1 + * 3 2 + * 4 2 + * 5 3 + * @param filename input filename for metadata + */ + virtual void readMetaData(const std::string& filename); + + unsigned int numMetaDataColumns() const { return m_numMetaDataColumns; } + const std::map>& metaData() const override { return m_metaData; } + + bool isMultilayerNetwork() const { return !m_layerNodeToStateId.empty(); } + const std::map>& layerNodeToStateId() const { return m_layerNodeToStateId; } + + void postProcessInputData(); + void generateStateNetworkFromMultilayer(); + void generateStateNetworkFromMultilayerWithInterLinks(); + void generateStateNetworkFromMultilayerWithSimulatedInterLinks(); + void simulateInterLayerLinks(); + + /** + * Create state node corresponding to this multilayer node if not already exist + * @return state node id + */ + unsigned int addMultilayerNode(unsigned int layerId, unsigned int physicalId, double weight = 1.0); + + void addMultilayerLink(unsigned int layer1, unsigned int n1, unsigned int layer2, unsigned int n2, double weight); + + /** + * Create an intra-layer link + */ + void addMultilayerIntraLink(unsigned int layer, unsigned int n1, unsigned int n2, double weight); + + /** + * Create links between (layer1,n) and (layer2,m) for all m connected to n in layer 2. + * The weight is distributed proportionally. + * TODO: This is done later.. + */ + void addMultilayerInterLink(unsigned int layer1, unsigned int n, unsigned int layer2, double interWeight); + + void addMetaData(unsigned int nodeId, int meta); + + void addMetaData(unsigned int nodeId, const std::vector& metaData); + +private: + void init(); + void initValidHeadings(); + + void parseNetwork(const std::string& filename); + void parseNetwork(const std::string& filename, const InsensitiveStringSet& validHeadings, const InsensitiveStringSet& ignoreHeadings, const std::string& startHeading = ""); + + // Helper methods + + /** + * Parse vertices under the heading + * @return The line after the vertices + */ + std::string parseVertices(std::ifstream& file, const std::string& heading); + std::string parseStateNodes(std::ifstream& file, const std::string& heading); + + std::string parseLinks(std::ifstream& file); + + /** + * Parse multilayer links from a *multilayer section + */ + std::string parseMultilayerLinks(std::ifstream& file); + + /** + * Parse multilayer links from an *intra section + */ + std::string parseMultilayerIntraLinks(std::ifstream& file); + + /** + * Parse multilayer links from an *inter section + */ + std::string parseMultilayerInterLinks(std::ifstream& file); + + std::string parseBipartiteLinks(std::ifstream& file, const std::string& heading); + + static std::string ignoreSection(std::ifstream& file, const std::string& heading); + + void parseStateNode(const std::string& line, StateNetwork::StateNode& stateNode); + + /** + * Parse a string of link data. + * If no weight data can be extracted, the default value 1.0 will be used. + * @throws an error if not both node ids can be extracted. + */ + void parseLink(const std::string& line, unsigned int& n1, unsigned int& n2, double& weight); + + /** + * Parse a string of multilayer link data. + * If no weight data can be extracted, the default value 1.0 will be used. + * @throws an error if not both node and layer ids can be extracted. + */ + void parseMultilayerLink(const std::string& line, unsigned int& layer1, unsigned int& n1, unsigned int& layer2, unsigned int& n2, double& weight); + + /** + * Parse a string of intra-multilayer link data. + * If no weight data can be extracted, the default value 1.0 will be used. + * @throws an error if not both node and layer ids can be extracted. + */ + void parseMultilayerIntraLink(const std::string& line, unsigned int& layer, unsigned int& n1, unsigned int& n2, double& weight); + + /** + * Parse a string of inter-multilayer link data. + * If no weight data can be extracted, the default value 1.0 will be used. + * @throws an error if not both node and layer ids can be extracted. + */ + void parseMultilayerInterLink(const std::string& line, unsigned int& layer1, unsigned int& n, unsigned int& layer2, double& weight); + + static double calculateJensenShannonDivergence(bool& intersect, const OutLinkMap& layer1OutLinks, double sumOutLinkWeightLayer1, const OutLinkMap& layer2OutLinks, double sumOutLinkWeightLayer2); + + void printSummary(); +}; + +struct LayerNode { + unsigned int layer, node; + explicit LayerNode(unsigned int layer = 0, unsigned int node = 0) : layer(layer), node(node) { } + + bool operator<(const LayerNode other) const + { + return layer == other.layer ? node < other.node : layer < other.layer; + } +}; + +} // namespace infomap + +#endif // NETWORK_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/io/Output.cpp b/src/vendor/cigraph/vendor/infomap/src/io/Output.cpp new file mode 100644 index 00000000000..79f116ccbb0 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/Output.cpp @@ -0,0 +1,629 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "Output.h" +#include "../core/InfomapBase.h" +#include "../core/StateNetwork.h" +#include "../io/SafeFile.h" + +namespace infomap { + +std::string getOutputFilename(const InfomapBase& im, const std::string& filename, const std::string& ext, bool states) +{ + if (!filename.empty()) { + return filename; + } + + auto defaultFilename = im.outDirectory + im.outName; + + if (im.haveMemory() && states) { + defaultFilename += "_states"; + } + + return defaultFilename + ext; +} + +std::string getOutputFileHeader(const InfomapBase& im, const StateNetwork& network, bool states) +{ + std::string bipartiteInfo = io::Str() << "\n# bipartite start id " << network.bipartiteStartId(); + return io::Str() << "# v" << INFOMAP_VERSION << "\n" + << "# ./Infomap " << im.parsedString << "\n" + << "# started at " << im.getStartDate() << "\n" + << "# completed in " << im.getElapsedTime().getElapsedTimeInSec() << " s\n" + << "# partitioned into " << im.maxTreeDepth() << " levels with " << im.numTopModules() << " top modules\n" + << "# codelength " << im.codelength() << " bits\n" + << "# relative codelength savings " << im.getRelativeCodelengthSavings() * 100 << "%\n" + << "# flow model " << flowModelToString(im.flowModel) + << (im.haveMemory() ? "\n# higher order" : "") + << (im.haveMemory() ? states ? "\n# state level" : "\n# physical level" : "") + << (network.isBipartite() ? bipartiteInfo : ""); +} + +std::string getNodeName(const std::map& names, const InfoNode& node) +{ + try { + return names.at(node.physicalId); + } catch (...) { + return io::stringify(node.physicalId); + } +} + +std::string writeClu(InfomapBase& im, const StateNetwork& network, const std::string& filename, bool states, int moduleIndexLevel) +{ + auto outputFilename = getOutputFilename(im, filename, ".clu", states); + SafeOutFile outFile { outputFilename }; + + outFile << std::setprecision(9); + outFile << getOutputFileHeader(im, network, states) << "\n"; + outFile << "# module level " << moduleIndexLevel << "\n"; + outFile << std::resetiosflags(std::ios::floatfield) << std::setprecision(6); + + if (states) { + outFile << "# state_id module flow node_id"; + if (im.isMultilayerNetwork()) + outFile << " layer_id"; + outFile << '\n'; + } else { + outFile << "# node_id module flow\n"; + } + + const auto shouldHideBipartiteNodes = im.isBipartite() && im.hideBipartiteNodes; + const auto bipartiteStartId = shouldHideBipartiteNodes ? network.bipartiteStartId() : 0; + + if (im.haveMemory() && !states) { + for (auto it(im.iterTreePhysical(moduleIndexLevel)); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + outFile << node.physicalId << " " << it.moduleId() << " " << node.data.flow << "\n"; + } + } + } else { + for (auto it(im.iterTree(moduleIndexLevel)); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + if (states) { + outFile << node.stateId << " " << it.moduleId() << " " << node.data.flow << " " << node.physicalId; + if (im.isMultilayerNetwork()) + outFile << " " << node.layerId; + outFile << "\n"; + } else + outFile << node.physicalId << " " << it.moduleId() << " " << node.data.flow << "\n"; + } + } + } + return outputFilename; +} + +void writeTree(InfomapBase& im, const StateNetwork& network, std::ostream& outStream, bool states) +{ + auto oldPrecision = outStream.precision(); + outStream << std::setprecision(9); + outStream << getOutputFileHeader(im, network, states) << "\n"; + outStream << std::setprecision(6); + + if (states) { + outStream << "# path flow name state_id node_id"; + if (im.isMultilayerNetwork()) + outStream << " layer_id"; + outStream << '\n'; + } else { + outStream << "# path flow name node_id\n"; + } + + const auto shouldHideBipartiteNodes = !im.printFlowTree && im.isBipartite() && im.hideBipartiteNodes; + const auto bipartiteStartId = shouldHideBipartiteNodes ? network.bipartiteStartId() : 0; + + // TODO: Make a general iterator where merging physical nodes depend on a parameter rather than type to be able to DRY here + if (im.haveMemory() && !states) { + for (auto it(im.iterTreePhysical()); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + auto& path = it.path(); + + outStream << io::stringify(path, ":") << " " << node.data.flow << " \"" << getNodeName(network.names(), node) << "\" " << node.physicalId << '\n'; + } + } + } else { + for (auto it(im.iterTree()); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + auto& path = it.path(); + + outStream << io::stringify(path, ":") << " " << node.data.flow << " \"" << getNodeName(network.names(), node) << "\" "; + + if (states) { + outStream << node.stateId << " " << node.physicalId; + if (im.isMultilayerNetwork()) + outStream << " " << node.layerId; + outStream << '\n'; + } else { + outStream << node.physicalId << '\n'; + } + } + } + } + + outStream << std::setprecision(oldPrecision); +} + +using Link = std::pair; +using LinkMap = std::map; + +std::map aggregateModuleLinks(InfomapBase& im, bool states) +{ + // Aggregate links between each module. Rest is aggregated as exit flow + + // Links on nodes within sub infomap instances doesn't have links outside the root + // so iterate over links on main instance and map to infomap tree iterator + bool mergePhysicalNodes = im.haveMemory() && !states; + + // Map state id to parent in infomap tree iterator + std::map stateIdToParent; + std::map stateIdToChildIndex; + + if (mergePhysicalNodes) { + for (auto it(im.iterTreePhysical()); !it.isEnd(); ++it) { + if (it->isLeaf()) { + for (auto stateId : it->stateNodes) { + stateIdToParent[stateId] = it->parent; + stateIdToChildIndex[stateId] = it.childIndex(); + } + } else { + // Use stateId to store depth on modules to simplify link aggregation + it->stateId = it.depth(); + it->index = it.childIndex(); + } + } + } else { + for (auto it(im.iterTree()); !it.isEnd(); ++it) { + if (it->isLeaf()) { + stateIdToParent[it->stateId] = it->parent; + stateIdToChildIndex[it->stateId] = it.childIndex(); + } else { + // Use stateId to store depth on modules to simplify link aggregation + it->stateId = it.depth(); + it->index = it.childIndex(); + } + } + } + + std::map moduleLinks; + + for (auto& leaf : im.leafNodes()) { + for (auto& link : leaf->outEdges()) { + double flow = link->data.flow; + InfoNode* sourceParent = stateIdToParent[link->source->stateId]; + InfoNode* targetParent = stateIdToParent[link->target->stateId]; + + auto sourceDepth = sourceParent->calculatePath().size() + 1; + auto targetDepth = targetParent->calculatePath().size() + 1; + + auto sourceChildIndex = stateIdToChildIndex[link->source->stateId]; + auto targetChildIndex = stateIdToChildIndex[link->target->stateId]; + + auto sourceParentIt = InfomapParentIterator(sourceParent); + auto targetParentIt = InfomapParentIterator(targetParent); + + // Iterate to same depth + // First raise target + while (targetDepth > sourceDepth) { + ++targetParentIt; + --targetDepth; + } + + // Raise source to same depth + while (sourceDepth > targetDepth) { + ++sourceParentIt; + --sourceDepth; + } + + auto currentDepth = sourceDepth; + // Add link if same parent + + while (currentDepth > 0) { + if (sourceParentIt == targetParentIt) { + // Skip self-links + if (sourceChildIndex != targetChildIndex) { + auto parentId = io::stringify(sourceParentIt->calculatePath(), ":"); + auto& linkMap = moduleLinks[parentId]; + linkMap[std::make_pair(sourceChildIndex + 1, targetChildIndex + 1)] += flow; + } + } + + sourceChildIndex = sourceParentIt->index; + targetChildIndex = targetParentIt->index; + + ++sourceParentIt; + ++targetParentIt; + + --currentDepth; + } + } + } + + return moduleLinks; +} + +void writeTreeLinks(InfomapBase& im, std::ostream& outStream, bool states) +{ + auto oldPrecision = outStream.precision(); + outStream << std::setprecision(6); + + auto moduleLinks = aggregateModuleLinks(im, states); + + outStream << "*Links " << (im.isUndirectedFlow() ? "undirected" : "directed") << "\n"; + outStream << "#*Links path enterFlow exitFlow numEdges numChildren\n"; + + // Use stateId to store depth on modules to optimize link aggregation + for (auto it(im.iterModules()); !it.isEnd(); ++it) { + auto parentId = io::stringify(it.path(), ":"); + auto& module = *it; + auto& links = moduleLinks[parentId]; + + outStream << "*Links " << (parentId.empty() ? "root" : parentId) << " " << module.data.enterFlow << " " << module.data.exitFlow << " " << links.size() << " " << module.infomapChildDegree() << "\n"; + + for (auto itLink : links) { + unsigned int sourceId = itLink.first.first; + unsigned int targetId = itLink.first.second; + double flow = itLink.second; + outStream << sourceId << " " << targetId << " " << flow << "\n"; + } + } + + outStream << std::setprecision(oldPrecision); +} + +void writeNewickTree(InfomapBase& im, std::ostream& outStream, bool states) +{ + auto oldPrecision = outStream.precision(); + outStream << std::setprecision(6); + + auto isRoot = true; + unsigned int lastDepth = 0; + std::vector flowStack; + + auto writeNewickNode = [&](const InfoNode& node, unsigned int depth) { + if (depth > lastDepth || isRoot) { + outStream << "("; + flowStack.push_back(node.data.flow); + if (node.isLeaf()) + outStream << (states ? node.stateId : node.physicalId) << ":" << node.data.flow; + } else if (depth == lastDepth) { + outStream << ","; + flowStack[flowStack.size() - 1] = node.data.flow; + if (node.isLeaf()) { + outStream << (states ? node.stateId : node.physicalId) << ":" << node.data.flow; + } + } else { + // depth < lastDepth + while (flowStack.size() > depth + 1) { + flowStack.pop_back(); + outStream << "):" << flowStack.back(); + } + flowStack[flowStack.size() - 1] = node.data.flow; + outStream << ","; + } + lastDepth = depth; + isRoot = false; + }; + + // TODO: Make a general iterator where merging physical nodes depend on a parameter rather than type to be able to DRY here + if (im.haveMemory() && !states) { + for (auto it(im.iterTreePhysical()); !it.isEnd(); ++it) { + writeNewickNode(*it, it.depth()); + } + } else { + for (auto it(im.iterTree()); !it.isEnd(); ++it) { + writeNewickNode(*it, it.depth()); + } + } + while (flowStack.size() > 1) { + flowStack.pop_back(); + outStream << "):" << flowStack.back(); + } + outStream << ");\n"; + outStream << std::setprecision(oldPrecision); +} + +void writeJsonTree(InfomapBase& im, const StateNetwork& network, std::ostream& outStream, bool states, bool writeLinks) +{ + auto oldPrecision = outStream.precision(); + + outStream << "{"; + + outStream << "\"version\":\"v" << INFOMAP_VERSION << "\"," + << "\"args\":\"" << im.parsedString << "\"," + << "\"startedAt\":\"" << im.getStartDate() << "\"," + << "\"completedIn\":" << im.getElapsedTime().getElapsedTimeInSec() << "," + << "\"codelength\":" << im.codelength() << "," + << "\"numLevels\":" << im.maxTreeDepth() << "," + << "\"numTopModules\":" << im.numTopModules() << "," + << "\"relativeCodelengthSavings\":" << im.getRelativeCodelengthSavings() << "," + << "\"directed\":" << (im.isUndirectedFlow() ? "false" : "true") << "," + << "\"flowModel\": \"" << flowModelToString(im.flowModel) << "\"," + << "\"higherOrder\":" << (im.haveMemory() ? "true" : "false") << ","; + + if (im.haveMemory()) { + outStream << "\"stateLevel\":" << (states ? "true" : "false") << ","; + } + + if (im.isBipartite()) { + outStream << "\"bipartiteStartId\":" << network.bipartiteStartId() << ","; + } + + outStream << std::setprecision(6); + + outStream << "\"nodes\":["; + + const auto shouldHideBipartiteNodes = im.isBipartite() && im.hideBipartiteNodes; + const auto bipartiteStartId = shouldHideBipartiteNodes ? network.bipartiteStartId() : 0; + + auto metaData = network.metaData(); + auto writeMeta = [&metaData](auto& outStream, auto nodeId) { + outStream << "\"metadata\":{"; + auto meta = metaData[nodeId]; + for (unsigned int i = 0; i < meta.size(); ++i) { + outStream << '"' << i << "\":" + << '"' << meta[i] << '"'; // metadata class as string to highlight that this is a categorical variable + if (i < meta.size() - 1) + outStream << ','; + } + outStream << "},"; + }; + + // don't append a comma after the last entry + auto first = true; + + if (im.haveMemory() && !states) { + for (auto it(im.iterTreePhysical()); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + const auto path = io::stringify(it.path(), ","); + + if (first) { + first = false; + } else { + outStream << ","; + } + + outStream << "{" + << "\"path\":[" << path << "]," + << "\"name\":\"" << getNodeName(network.names(), node) << "\"," + << "\"flow\":" << node.data.flow << "," + << "\"mec\":" << it.modularCentrality() << "," + << "\"id\":" << node.physicalId << "}"; + } + } + } else { + const auto multilevelModules = im.getMultilevelModules(states); + + for (auto it(im.iterTree()); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + if (first) { + first = false; + } else { + outStream << ","; + } + + const auto path = io::stringify(it.path(), ", "); + const auto modules = im.haveModules() ? io::stringify(multilevelModules.at(states ? node.stateId : node.physicalId), ", ") : "1"; + + outStream << "{" + << "\"path\":[" << path << "]," + << "\"modules\":[" << modules << "]," + << "\"name\":\"" << getNodeName(network.names(), node) << "\"," + << "\"flow\":" << node.data.flow << "," + << "\"mec\":" << it.modularCentrality() << ","; + + // can't currently use both memory and meta map equation + if (im.haveMetaData() && !states) { + writeMeta(outStream, node.physicalId); + } + + if (states) { + outStream << "\"stateId\":" << node.stateId << ","; + if (im.isMultilayerNetwork()) + outStream << "\"layerId\":" << node.layerId << ","; + } + + outStream << "\"id\":" << node.physicalId << "}"; + } + } + } + + outStream << "],"; // tree + + // ------------- + // Write modules + // ------------- + + // Uses stateId to store depth on modules to optimize link aggregation + auto moduleLinks = aggregateModuleLinks(im, states); + + first = true; + + outStream << "\"modules\":["; + + for (auto it(im.iterModules()); !it.isEnd(); ++it) { + const auto parentId = io::stringify(it.path(), ":"); + const auto& module = *it; + const auto& links = moduleLinks[parentId]; + const auto path = io::stringify(it.path(), ","); + + if (first) { + first = false; + } else { + outStream << ","; + } + + outStream << "{"; + + outStream << "\"path\":[" << (parentId.empty() ? "0" : path) << "]," + << "\"enterFlow\":" << module.data.enterFlow << ',' + << "\"exitFlow\":" << module.data.exitFlow << ',' + << "\"numEdges\":" << links.size() << ',' + << "\"numChildren\":" << module.infomapChildDegree() << ',' + << "\"codelength\":" << module.codelength; + + if (writeLinks) { + outStream << "," + << "\"links\":["; + + auto firstLink = true; + + for (auto itLink : links) { + if (firstLink) { + firstLink = false; + } else { + outStream << ","; + } + + unsigned int sourceId = itLink.first.first; + unsigned int targetId = itLink.first.second; + double flow = itLink.second; + outStream << "{\"source\":" << sourceId << ",\"target\":" << targetId << ",\"flow\":" << flow << "}"; + } + outStream << "]"; // links + } + + outStream << "}"; + } + + outStream << "]"; // modules + + outStream << "}"; + + outStream << std::setprecision(oldPrecision); +} + +void writeCsvTree(InfomapBase& im, const StateNetwork& network, std::ostream& outStream, bool states) +{ + auto oldPrecision = outStream.precision(); + outStream << std::setprecision(6); + + outStream << "path,flow,name,"; + + if (im.haveMemory() && !states) { + outStream << "node_id\n"; + } else { + if (states) { + outStream << "state_id,"; + if (im.isMultilayerNetwork()) + outStream << "layer_id,"; + } + outStream << "node_id\n"; + } + + const auto shouldHideBipartiteNodes = im.isBipartite() && im.hideBipartiteNodes; + const auto bipartiteStartId = shouldHideBipartiteNodes ? network.bipartiteStartId() : 0; + + if (im.haveMemory() && !states) { + for (auto it(im.iterTreePhysical()); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + const auto path = io::stringify(it.path(), ":"); + outStream << path << ',' << node.data.flow << ",\"" << getNodeName(network.names(), node) << "\"," << node.physicalId << '\n'; + } + } + } else { + for (auto it(im.iterTree()); !it.isEnd(); ++it) { + InfoNode& node = *it; + if (node.isLeaf()) { + if (shouldHideBipartiteNodes && node.physicalId >= bipartiteStartId) { + continue; + } + + const auto path = io::stringify(it.path(), ":"); + outStream << path << ',' << node.data.flow << ",\"" << getNodeName(network.names(), node) << "\","; + + if (states) { + outStream << node.stateId << ','; + if (im.isMultilayerNetwork()) + outStream << node.layerId << ','; + } + + outStream << node.physicalId << '\n'; + } + } + } + + outStream << std::setprecision(oldPrecision); +} + +std::string writeTree(InfomapBase& im, const StateNetwork& network, const std::string& filename, bool states) +{ + auto outputFilename = getOutputFilename(im, filename, ".tree", states); + SafeOutFile outFile { outputFilename }; + writeTree(im, network, outFile, states); + return outputFilename; +} + +std::string writeFlowTree(InfomapBase& im, const StateNetwork& network, const std::string& filename, bool states) +{ + auto outputFilename = getOutputFilename(im, filename, ".ftree", states); + SafeOutFile outFile { outputFilename }; + writeTree(im, network, outFile, states); + writeTreeLinks(im, outFile, states); + return outputFilename; +} + +std::string writeNewickTree(InfomapBase& im, const std::string& filename, bool states) +{ + auto outputFilename = getOutputFilename(im, filename, ".nwk", states); + SafeOutFile outFile { outputFilename }; + writeNewickTree(im, outFile, states); + return outputFilename; +} + +std::string writeJsonTree(InfomapBase& im, const StateNetwork& network, const std::string& filename, bool states, bool writeLinks) +{ + auto outputFilename = getOutputFilename(im, filename, ".json", states); + SafeOutFile outFile { outputFilename }; + writeJsonTree(im, network, outFile, states, writeLinks); + return outputFilename; +} + +std::string writeCsvTree(InfomapBase& im, const StateNetwork& network, const std::string& filename, bool states) +{ + auto outputFilename = getOutputFilename(im, filename, ".csv", states); + SafeOutFile outFile { outputFilename }; + writeCsvTree(im, network, outFile, states); + return outputFilename; +} + +} // namespace infomap \ No newline at end of file diff --git a/src/vendor/cigraph/vendor/infomap/src/io/Output.h b/src/vendor/cigraph/vendor/infomap/src/io/Output.h new file mode 100644 index 00000000000..2b649835d93 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/Output.h @@ -0,0 +1,36 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef OUTPUT_H_ +#define OUTPUT_H_ + +#include +#include +#include + +namespace infomap { + +class InfomapBase; +class StateNetwork; + +std::string writeTree(InfomapBase&, const StateNetwork&, const std::string&, bool states); + +std::string writeFlowTree(InfomapBase&, const StateNetwork&, const std::string&, bool states); + +std::string writeNewickTree(InfomapBase&, const std::string&, bool states); + +std::string writeJsonTree(InfomapBase&, const StateNetwork&, const std::string&, bool states, bool writeLinks); + +std::string writeCsvTree(InfomapBase&, const StateNetwork&, const std::string&, bool states); + +std::string writeClu(InfomapBase&, const StateNetwork&, const std::string&, bool states, int moduleIndexLevel); + +} // namespace infomap + +#endif // OUTPUT_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp new file mode 100644 index 00000000000..5ddfd764423 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp @@ -0,0 +1,341 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "ProgramInterface.h" +#include "../utils/Log.h" + +#include +#include +#include +#include + +namespace infomap { + +const std::string ArgType::integer = "integer"; +const std::string ArgType::number = "number"; +const std::string ArgType::string = "string"; +const std::string ArgType::path = "path"; +const std::string ArgType::probability = "probability"; +const std::string ArgType::option = "option"; +const std::string ArgType::list = "list"; + +const std::unordered_map ArgType::toShort = { + { "integer", 'n' }, + { "number", 'f' }, + { "string", 's' }, + { "path", 'p' }, + { "probability", 'P' }, + { "option", 'o' }, + { "list", 'l' }, +}; + +ProgramInterface::ProgramInterface(std::string name, std::string shortDescription, std::string version) + : m_programName(std::move(name)), + m_shortProgramDescription(std::move(shortDescription)), + m_programVersion(std::move(version)) +{ + addIncrementalOptionArgument(m_displayHelp, 'h', "help", "Prints this help message. Use -hh to show advanced options.", "About"); + addOptionArgument(m_displayVersion, 'V', "version", "Display program version information.", "About"); + addOptionArgument(m_printJsonParameters, "print-json-parameters", "Print Infomap parameters in JSON.", "About").setHidden(true); +} + +void ProgramInterface::exitWithUsage(bool showAdvanced) const +{ + Log() << "Name:\n"; + Log() << " " << m_programName << " - " << m_shortProgramDescription << '\n'; + Log() << "\nUsage:\n"; + Log() << " " << m_executableName; + for (auto& nonOptionArgument : m_nonOptionArguments) + if (showAdvanced || !nonOptionArgument->isAdvanced) + Log() << " " << nonOptionArgument->variableName; + if (!m_optionArguments.empty()) + Log() << " [options]"; + Log() << '\n'; + + if (!m_programDescription.empty()) + Log() << "\nDescription:\n " << m_programDescription << '\n'; + + for (auto& nonOptionArgument : m_nonOptionArguments) + if (showAdvanced || !nonOptionArgument->isAdvanced) + Log() << "\n[" << nonOptionArgument->variableName << "]\n " << nonOptionArgument->description << '\n'; + + if (!m_optionArguments.empty()) + Log() << "\n[options]\n"; + + // First stringify the options part to get the maximum length + std::deque optionStrings(m_optionArguments.size()); + std::string::size_type maxLength = 0; + for (unsigned int i = 0; i < m_optionArguments.size(); ++i) { + auto& opt = *m_optionArguments[i]; + bool haveShort = opt.shortName != '\0'; + std::string optArgShort = opt.requireArgument ? (io::Str() << "<" << ArgType::toShort.at(opt.argumentName) << ">") : opt.incrementalArgument ? "[+]" + : std::string(3, ' '); + std::string optArgLong = opt.requireArgument ? (io::Str() << "<" << opt.argumentName << ">") : opt.incrementalArgument ? "[+]" + : std::string(3, ' '); + std::string shortOption = haveShort ? (io::Str() << " -" << opt.shortName << optArgShort) : std::string(7, ' '); + optionStrings[i] = io::Str() << shortOption << " --" << opt.longName << " " << optArgLong; + if (optionStrings[i].length() > maxLength) + maxLength = optionStrings[i].length(); + } + + std::vector groups { "About" }; + for (auto& group : m_groups) { + if (group != "About") + groups.push_back(group); + } + if (m_groups.empty()) + groups.emplace_back("All"); + + for (const auto& group : groups) { + if (group != "All") { + Log() << "\n" + << group << "\n"; + Log() << std::string(group.length(), '-') << "\n"; + } + for (unsigned int i = 0; i < m_optionArguments.size(); ++i) { + auto& opt = *m_optionArguments[i]; + if (group == "All" || opt.group == group) { + std::string::size_type numSpaces = maxLength + 3 - optionStrings[i].length(); + if (showAdvanced || !opt.isAdvanced) { + Log() << optionStrings[i] << std::string(numSpaces, ' ') << opt.description; + if (!opt.printNumericValue().empty()) + Log() << " (Default: " << opt.printNumericValue() << ")"; + Log() << "\n"; + } + } + } + } + Log() << '\n'; + std::exit(0); +} + +void ProgramInterface::exitWithVersionInformation() const +{ + Log() << m_programName << " version " << m_programVersion; +#ifdef _OPENMP + Log() << " compiled with OpenMP"; +#endif + Log() << '\n'; + Log() << "See www.mapequation.org for terms of use.\n"; + std::exit(0); +} + +void ProgramInterface::exitWithError(const std::string& message) const +{ + Log() << m_programName << " version " << m_programVersion; +#ifdef _OPENMP + Log() << " compiled with OpenMP"; +#endif + Log() << std::endl; + std::cerr << message << std::endl; + Log() << "Usage: " << m_executableName; + for (auto& nonOptionArgument : m_nonOptionArguments) + if (!nonOptionArgument->isAdvanced) + Log() << " " << nonOptionArgument->variableName; + if (!m_optionArguments.empty()) + Log() << " [options]"; + Log() << ". Run with option '-h' for more information.\n"; + std::exit(1); +} + +std::string toJson(const std::string& key, const std::string& value) +{ + return io::Str() << '"' << key << "\": \"" << value << '"'; +} + +std::string toJson(const std::string& key, bool value) +{ + return io::Str() << '"' << key << "\": " << (value ? "true" : "false"); +} + +template +std::string toJson(const std::string& key, Value value) +{ + return io::Str() << '"' << key << "\": " << value; +} + +std::string toJson(const Option& opt) +{ + return io::Str() << "{ " + << toJson("long", std::string(io::Str() << "--" << opt.longName)) << ", " + << toJson("short", opt.shortName != '\0' ? std::string(io::Str() << "-" << opt.shortName) : "") << ", " + << toJson("description", opt.description) << ", " + << toJson("group", opt.group) << ", " + << toJson("required", opt.requireArgument) << ", " + << toJson("advanced", opt.isAdvanced) << ", " + << toJson("incremental", opt.incrementalArgument) << ", " + << (opt.requireArgument + ? (io::Str() << toJson("longType", opt.argumentName) << ", " + << toJson("shortType", std::string(1, ArgType::toShort.at(opt.argumentName))) << ", " + << toJson("default", opt.printValue())) + : toJson("default", false)) + << " }"; +} + +void ProgramInterface::exitWithJsonParameters() const +{ + Log() << "{\n \"parameters\": [\n"; + + for (unsigned int i = 0; i < m_optionArguments.size(); ++i) { + auto& opt = *m_optionArguments[i]; + if (opt.hidden) + continue; + Log() << " " << toJson(opt); + if (i < m_optionArguments.size() - 1) { + Log() << ",\n"; + } else { + Log() << "\n"; + } + } + Log() << " ]\n}"; + + std::exit(0); +} + +void ProgramInterface::parseArgs(const std::string& args) +{ + // Map the options on short and long name, and check for duplication + std::map shortOptionMap; + std::map longOptionMap; + for (auto& optionArgument : m_optionArguments) { + auto& opt = *optionArgument; + if (opt.shortName != '\0') { + auto it = shortOptionMap.find(opt.shortName); + if (it != shortOptionMap.end()) + throw std::runtime_error(io::Str() << "Duplication of option '" << opt.shortName << "'"); + shortOptionMap.insert(std::make_pair(opt.shortName, &opt)); + } + + auto it = longOptionMap.find(opt.longName); + if (it != longOptionMap.end()) + throw std::runtime_error(io::Str() << "Duplication of option \"" << opt.longName << "\""); + longOptionMap.insert(std::make_pair(opt.longName, &opt)); + } + + // Split the flags on whitespace + std::vector flags; + std::istringstream argStream(args); + + { + std::string arg; + while (!(argStream >> arg).fail()) + flags.push_back(arg); + } + + std::deque nonOpts; + try { + for (unsigned int i = 0; i < flags.size(); ++i) { + bool flagValue = true; + unsigned int numArgsLeft = flags.size() - i - 1; + + const std::string& arg = flags[i]; + if (arg.length() == 0) + throw std::runtime_error("Illegal argument ''"); + + if (arg[0] != '-') { + nonOpts.push_back(arg); + } else { + if (arg.length() < 2) + throw std::runtime_error("Illegal argument '-'"); + + if (arg[1] == '-') { + // Long option + if (arg.length() < 3) + throw std::runtime_error("Illegal argument '--'"); + std::string longOpt = arg.substr(2); + auto it = longOptionMap.find(longOpt); + if (it == longOptionMap.end()) { + // Unrecognized option, check if it negates a recognised option with the '--no-' prefix + if (longOpt.compare(0, 3, "no-") == 0 && longOptionMap.find(std::string(longOpt, 3)) != longOptionMap.end()) { + longOpt = std::string(longOpt, 3); + it = longOptionMap.find(longOpt); + flagValue = false; + } else { + throw std::runtime_error(io::Str() << "Unrecognized option: '--" << longOpt << "'"); + } + } + auto& opt = *it->second; + if (!opt.requireArgument || opt.incrementalArgument) + opt.set(flagValue); + else { + if (numArgsLeft == 0) + throw std::runtime_error(io::Str() << "Option '" << opt.longName << "' requires argument"); + ++i; + if (!opt.parse(flags[i])) + throw std::runtime_error(io::Str() << "Cannot parse '" << flags[i] << "' as argument to option '" << opt.longName << "'. "); + } + } else { + // Short option(s) + for (unsigned int j = 1; j < arg.length(); ++j) { + char o = arg[j]; + unsigned int numCharsLeft = arg.length() - j - 1; + auto it = shortOptionMap.find(o); + if (it == shortOptionMap.end()) + throw std::runtime_error(io::Str() << "Unrecognized option: '-" << o << "'"); + auto& opt = *it->second; + if (!opt.requireArgument || opt.incrementalArgument) + opt.set(flagValue); + else { + std::string optArg; + if (numCharsLeft > 0) { + optArg = arg.substr(j + 1); + j = arg.length() - 1; + } else if (numArgsLeft) { + ++i; + optArg = flags[i]; + } else + throw std::runtime_error(io::Str() << "Option '" << opt.longName << "' requires argument"); + + if (!opt.parse(optArg)) + throw std::runtime_error(io::Str() << "Cannot parse '" << optArg << "' as argument to option '" << opt.longName << "'. "); + } + } + } + } + if (m_displayHelp > 0) + exitWithUsage(m_displayHelp > 1); + if (m_displayVersion) + exitWithVersionInformation(); + if (m_printJsonParameters) + exitWithJsonParameters(); + } + } catch (std::exception& e) { + exitWithError(e.what()); + } + + if (nonOpts.size() < numRequiredArguments()) + exitWithError("Missing required arguments."); + + unsigned int i = 0; + unsigned int numVectorArguments = nonOpts.size() - (m_nonOptionArguments.size() - 1); + while (!nonOpts.empty()) { + std::string arg = nonOpts.front(); + nonOpts.pop_front(); + if (m_nonOptionArguments[i]->isOptionalVector && numVectorArguments == 0) + ++i; + if (!m_nonOptionArguments[i]->parse(arg)) + exitWithError("Argument error."); + if (!m_nonOptionArguments[i]->isOptionalVector || --numVectorArguments == 0) + ++i; + } +} + +std::vector ProgramInterface::getUsedOptionArguments() const +{ + std::vector opts; + unsigned int numFlags = m_optionArguments.size(); + for (unsigned int i = 0; i < numFlags; ++i) { + auto& opt = *m_optionArguments[i]; + if (opt.used && opt.longName != "negate-next") + opts.emplace_back(opt); + } + return opts; +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h new file mode 100644 index 00000000000..d0e352d8ca3 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h @@ -0,0 +1,417 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef PROGRAM_INTERFACE_H_ +#define PROGRAM_INTERFACE_H_ + +#include "../utils/convert.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace infomap { + +class InterruptException : public std::exception { +public: + InterruptException() {}; +}; + +typedef bool interruptionHandlerFn(void); + +struct ArgType { + static const std::string integer; + static const std::string number; + static const std::string string; + static const std::string path; + static const std::string probability; + static const std::string option; + static const std::string list; + static const std::unordered_map toShort; +}; + +struct Option { + Option(char shortName, std::string longName, std::string desc, std::string group, bool isAdvanced, bool requireArgument = false, std::string argName = "") + : shortName(shortName), + longName(std::move(longName)), + description(std::move(desc)), + group(std::move(group)), + isAdvanced(isAdvanced), + requireArgument(requireArgument), + incrementalArgument(false), + argumentName(std::move(argName)) { } + + virtual ~Option() = default; + + Option(const Option&) = default; + Option& operator=(const Option&) = default; + Option(Option&&) = default; + Option& operator=(Option&&) = default; + + virtual bool parse(std::string const&) + { + used = true; + return true; + } + + virtual void set(bool value) + { + used = true; + negated = !value; + }; + + Option& setHidden(bool value) + { + hidden = value; + return *this; + } + + virtual std::ostream& printValue(std::ostream& out) const { return out; } + virtual std::string printValue() const { return ""; } + virtual std::string printNumericValue() const { return ""; } + + friend std::ostream& operator<<(std::ostream& out, const Option& option) + { + out << option.longName; + if (option.requireArgument) { + out << " = "; + option.printValue(out); + } + return out; + } + + char shortName; + std::string longName; + std::string description; + std::string group; + bool isAdvanced; + bool requireArgument; + bool incrementalArgument; + std::string argumentName; + bool hidden = false; + bool used = false; + bool negated = false; +}; + +struct IncrementalOption : Option { + IncrementalOption(unsigned int& target, char shortName, std::string longName, std::string desc, std::string group, bool isAdvanced) + : Option(shortName, std::move(longName), std::move(desc), std::move(group), isAdvanced, false), target(target) + { + incrementalArgument = true; + } + + bool parse(std::string const& value) override + { + Option::parse(value); + return ++target; + } + + void set(bool value) override + { + Option::set(value); + if (value) { + ++target; + } else if (target > 0) { + --target; + } + } + + std::ostream& printValue(std::ostream& out) const override { return out << target; } + std::string printValue() const override { return io::Str() << target; } + + unsigned int& target; +}; + +template +struct ArgumentOption : Option { + ArgumentOption(T& target, char shortName, std::string longName, std::string desc, std::string group, bool isAdvanced, std::string argName) + : Option(shortName, std::move(longName), std::move(desc), std::move(group), isAdvanced, true, std::move(argName)), target(target) { } + + bool parse(std::string const& value) override + { + Option::parse(value); + return io::stringToValue(value, target); + } + + std::string printValue() const override { return io::Str() << target; } + std::ostream& printValue(std::ostream& out) const override { return out << target; } + std::string printNumericValue() const override { return TypeInfo::isNumeric() ? printValue() : ""; } + + T& target; +}; + +template +struct LowerBoundArgumentOption : ArgumentOption { + LowerBoundArgumentOption(T& target, char shortName, std::string longName, std::string desc, std::string group, bool isAdvanced, std::string argName, T minValue) + : ArgumentOption(target, shortName, std::move(longName), std::move(desc), std::move(group), isAdvanced, std::move(argName)), minValue(minValue) { } + + bool parse(std::string const& value) override + { + auto ok = ArgumentOption::parse(value); + if (ArgumentOption::target < minValue) return false; + return ok; + } + + T minValue; +}; + +template +struct LowerUpperBoundArgumentOption : LowerBoundArgumentOption { + LowerUpperBoundArgumentOption(T& target, char shortName, std::string longName, std::string desc, std::string group, bool isAdvanced, std::string argName, T minValue, T maxValue) + : LowerBoundArgumentOption(target, shortName, std::move(longName), std::move(desc), std::move(group), isAdvanced, std::move(argName), minValue), maxValue(maxValue) { } + + bool parse(std::string const& value) override + { + auto ok = LowerBoundArgumentOption::parse(value); + if (LowerBoundArgumentOption::target > maxValue) return false; + return ok; + } + + T maxValue; +}; + +template <> +struct ArgumentOption : Option { + ArgumentOption(bool& target, char shortName, std::string longName, std::string desc, std::string group, bool isAdvanced) + : Option(shortName, std::move(longName), std::move(desc), std::move(group), isAdvanced, false), target(target) { } + + bool parse(std::string const& value) override + { + Option::parse(value); + return target = true; + } + + void set(bool value) override + { + Option::set(value); + target = value; + } + + std::ostream& printValue(std::ostream& out) const override { return out << target; } + std::string printValue() const override { return io::Str() << target; } + std::string printNumericValue() const override { return ""; } + + bool& target; +}; + +struct ParsedOption { + explicit ParsedOption(const Option& opt) + : shortName(opt.shortName), + longName(opt.longName), + description(opt.description), + group(opt.group), + isAdvanced(opt.isAdvanced), + requireArgument(opt.requireArgument), + incrementalArgument(opt.incrementalArgument), + argumentName(opt.argumentName), + negated(opt.negated), + value(opt.printValue()) { } + + friend std::ostream& operator<<(std::ostream& out, const ParsedOption& option) + { + if (option.negated) + out << "no "; + out << option.longName; + if (option.requireArgument) + out << " = " << option.value; + return out; + } + + char shortName; + std::string longName; + std::string description; + std::string group; + bool isAdvanced; + bool requireArgument; + bool incrementalArgument; + std::string argumentName; + bool negated; + std::string value; +}; + +struct TargetBase { + TargetBase(std::string variableName, std::string desc, std::string group, bool isAdvanced) + : variableName(std::move(variableName)), description(std::move(desc)), group(std::move(group)), isOptionalVector(false), isAdvanced(isAdvanced) { } + + virtual ~TargetBase() = default; + + TargetBase(const TargetBase&) = default; + TargetBase& operator=(const TargetBase&) = default; + TargetBase(TargetBase&&) = default; + TargetBase& operator=(TargetBase&&) = default; + + virtual bool parse(std::string const& value) = 0; + + std::string variableName; + std::string description; + std::string group; + bool isOptionalVector = false; + bool isAdvanced; +}; + +template +struct Target : TargetBase { + Target(T& target, std::string variableName, std::string desc, std::string group, bool isAdvanced) + : TargetBase(std::move(variableName), std::move(desc), std::move(group), isAdvanced), target(target) { } + + bool parse(std::string const& value) override + { + return io::stringToValue(value, target); + } + + T& target; +}; + +template +struct OptionalTargets : TargetBase { + OptionalTargets(std::vector& target, std::string variableName, std::string desc, std::string group, bool isAdvanced) + : TargetBase(std::move(variableName), std::move(desc), std::move(group), isAdvanced), targets(target) + { + isOptionalVector = true; + } + + bool parse(std::string const& value) override + { + T target; + bool ok = io::stringToValue(value, target); + if (ok) + targets.push_back(target); + return ok; + } + + std::vector& targets; +}; + +class ProgramInterface { +public: + ProgramInterface(std::string name, std::string shortDescription, std::string version); + + void setGroups(std::vector groups) { m_groups = std::move(groups); } + + template + void addNonOptionArgument(T& target, std::string variableName, std::string desc, std::string group, bool isAdvanced = false) + { + m_nonOptionArguments.emplace_back(new Target(target, std::move(variableName), std::move(desc), std::move(group), isAdvanced)); + } + + template + void addOptionalNonOptionArguments(std::vector& target, std::string variableName, std::string desc, std::string group, bool isAdvanced = false) + { + if (m_numOptionalNonOptionArguments != 0) + throw std::runtime_error("Can't have two non-option vector arguments"); + ++m_numOptionalNonOptionArguments; + m_nonOptionArguments.emplace_back(new OptionalTargets(target, std::move(variableName), std::move(desc), std::move(group), isAdvanced)); + } + + Option& addOptionArgument(char shortName, std::string longName, std::string description, std::string group, bool isAdvanced = false) + { + auto* o = new Option(shortName, std::move(longName), std::move(description), std::move(group), isAdvanced); + m_optionArguments.emplace_back(o); + return *o; + } + + Option& addIncrementalOptionArgument(unsigned int& target, char shortName, std::string longName, std::string description, std::string group, bool isAdvanced = false) + { + auto* o = new IncrementalOption(target, shortName, std::move(longName), std::move(description), std::move(group), isAdvanced); + m_optionArguments.emplace_back(o); + return *o; + } + + Option& addOptionArgument(bool& target, char shortName, std::string longName, std::string description, std::string group, bool isAdvanced = false) + { + auto* o = new ArgumentOption(target, shortName, std::move(longName), std::move(description), std::move(group), isAdvanced); + m_optionArguments.emplace_back(o); + return *o; + } + + // Without shortName + Option& addOptionArgument(bool& target, std::string longName, std::string description, std::string group, bool isAdvanced = false) + { + return addOptionArgument(target, '\0', std::move(longName), std::move(description), std::move(group), isAdvanced); + } + + template + Option& addOptionArgument(T& target, char shortName, std::string longName, std::string description, std::string argumentName, std::string group, bool isAdvanced = false) + { + auto* o = new ArgumentOption(target, shortName, std::move(longName), std::move(description), std::move(group), isAdvanced, std::move(argumentName)); + m_optionArguments.emplace_back(o); + return *o; + } + + template + Option& addOptionArgument(T& target, char shortName, std::string longName, std::string description, std::string argumentName, std::string group, T minValue, bool isAdvanced = false) + { + auto* o = new LowerBoundArgumentOption(target, shortName, std::move(longName), std::move(description), std::move(group), isAdvanced, std::move(argumentName), minValue); + m_optionArguments.emplace_back(o); + return *o; + } + + template + Option& addOptionArgument(T& target, char shortName, std::string longName, std::string description, std::string argumentName, std::string group, T minValue, T maxValue, bool isAdvanced = false) + { + auto* o = new LowerUpperBoundArgumentOption(target, shortName, std::move(longName), std::move(description), std::move(group), isAdvanced, std::move(argumentName), minValue, maxValue); + m_optionArguments.emplace_back(o); + return *o; + } + + // Without shortName + template + Option& addOptionArgument(T& target, std::string longName, std::string description, std::string argumentName, std::string group, bool isAdvanced = false) + { + return addOptionArgument(target, '\0', std::move(longName), std::move(description), std::move(argumentName), std::move(group), isAdvanced); + } + + template + Option& addOptionArgument(T& target, std::string longName, std::string description, std::string argumentName, std::string group, T minValue, bool isAdvanced = false) + { + return addOptionArgument(target, '\0', std::move(longName), std::move(description), std::move(argumentName), std::move(group), minValue, isAdvanced); + } + + template + Option& addOptionArgument(T& target, std::string longName, std::string description, std::string argumentName, std::string group, T minValue, T maxValue, bool isAdvanced = false) + { + return addOptionArgument(target, '\0', std::move(longName), std::move(description), std::move(argumentName), std::move(group), minValue, maxValue, isAdvanced); + } + + void parseArgs(const std::string& args); + + std::vector getUsedOptionArguments() const; + + unsigned int numRequiredArguments() const { return m_nonOptionArguments.size() - m_numOptionalNonOptionArguments; } + +private: + void exitWithUsage(bool showAdvanced) const; + void exitWithVersionInformation() const; + void exitWithError(const std::string& message) const; + void exitWithJsonParameters() const; + + std::deque> m_optionArguments; + std::deque> m_nonOptionArguments; + std::string m_programName = "Infomap"; + std::string m_shortProgramDescription; + std::string m_programVersion; + std::string m_programDescription; + std::vector m_groups; + std::string m_executableName = "Infomap"; + unsigned int m_displayHelp = 0; + bool m_displayVersion = false; + bool m_printJsonParameters = false; + + unsigned int m_numOptionalNonOptionArguments = 0; +}; + +} // namespace infomap + +#endif // PROGRAM_INTERFACE_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/io/SafeFile.h b/src/vendor/cigraph/vendor/infomap/src/io/SafeFile.h new file mode 100644 index 00000000000..967cd09bd5c --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/io/SafeFile.h @@ -0,0 +1,87 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef SAFEFILE_H_ +#define SAFEFILE_H_ + +#include "../utils/convert.h" +#include +#include +#include +#include +#include + +namespace infomap { + +using std::ifstream; +using std::ofstream; + +/** + * A wrapper for the C++ file stream class that automatically closes + * the file stream when the destructor is called. Allocate it on the + * stack to have it automatically closed when going out of scope. + * + * Note: + * In C++, the only code that can be guaranteed to be executed after an + * exception is thrown are the destructors of objects residing on the stack. + * + * You can exploit that fact to avoid resource leaks by tying all resources + * to the lifespan of an object allocated on the stack. This technique is + * called Resource Acquisition Is Initialization (RAII). + * + */ +class SafeInFile : public ifstream { +public: + SafeInFile(const std::string& filename, ios_base::openmode mode = ios_base::in) + : ifstream(filename, mode) + { + if (fail()) + throw std::runtime_error(io::Str() << "Error opening file '" << filename << "'. Check that the path points to a file and that you have read permissions."); + } + + ~SafeInFile() override + { + if (is_open()) + close(); + } +}; + +class SafeOutFile : public ofstream { +public: + SafeOutFile(const std::string& filename, ios_base::openmode mode = ios_base::out) + : ofstream(filename, mode) + { + if (fail()) + throw std::runtime_error(io::Str() << "Error opening file '" << filename << "'. Check that the directory you are writing to exists and that you have write permissions."); + } + + ~SafeOutFile() override + { + if (is_open()) + close(); + } +}; + +inline bool isDirectoryWritable(const std::string& dir) +{ + std::string path = io::Str() << dir << "_1nf0m4p_.tmp"; + bool ok = true; + try { + SafeOutFile out(path); + } catch (const std::runtime_error&) { + ok = false; + } + if (ok) + std::remove(path.c_str()); + return ok; +} + +} // namespace infomap + +#endif // SAFEFILE_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/Date.h b/src/vendor/cigraph/vendor/infomap/src/utils/Date.h new file mode 100644 index 00000000000..98feced1e41 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/Date.h @@ -0,0 +1,69 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef DATE_H_ +#define DATE_H_ + +#include +#include +#include + +namespace infomap { + +class ElapsedTime { +public: + ElapsedTime(double elapsedTime = 0.0) : m_elapsedTime(elapsedTime) { } + + double getSeconds() const { return m_elapsedTime; } + + friend std::ostream& operator<<(std::ostream& out, const ElapsedTime& elapsedTime) + { + auto temp = static_cast(std::floor(elapsedTime.getSeconds())); + if (temp > 60) { + if (temp > 3600) { + if (temp > 86400) { + out << temp / 86400 << "d "; + temp %= 86400; + } + out << temp / 3600 << "h "; + temp %= 3600; + } + out << temp / 60 << "m "; + temp %= 60; + out << temp << "s"; + } else { + out << temp << "s"; + } + return out; + } + +private: + double m_elapsedTime; +}; + +class Date { +public: + friend std::ostream& operator<<(std::ostream& out, const Date& date) + { + struct std::tm t = *localtime(&date.m_timeOfCreation); + return out << "" << (t.tm_year + 1900) << (t.tm_mon < 9 ? "-0" : "-") << (t.tm_mon + 1) << (t.tm_mday < 10 ? "-0" : "-") << t.tm_mday << (t.tm_hour < 10 ? " 0" : " ") << t.tm_hour << (t.tm_min < 10 ? ":0" : ":") << t.tm_min << (t.tm_sec < 10 ? ":0" : ":") << t.tm_sec << ""; + } + + ElapsedTime operator-(const Date& date) const + { + return { difftime(m_timeOfCreation, date.m_timeOfCreation) }; + } + +private: + std::time_t m_timeOfCreation = time(nullptr); +}; + +} // namespace infomap + +#endif // DATE_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/FileURI.cpp b/src/vendor/cigraph/vendor/infomap/src/utils/FileURI.cpp new file mode 100644 index 00000000000..c466d5872e0 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/FileURI.cpp @@ -0,0 +1,50 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "FileURI.h" +#include "convert.h" +#include +#include + +using std::string; + +namespace infomap { + +FileURI::FileURI(string filename, bool requireExtension) + : m_filename(std::move(filename)), m_requireExtension(requireExtension) +{ + auto getErrorMessage = [](const auto& name, auto requireExt) { + string s = io::Str() << "Filename '" << name << "' must match the pattern \"[dir/]name" << (requireExt ? ".extension\"" : "[.extension]\""); + return s; + }; + + auto name = m_filename; + auto pos = m_filename.find_last_of('/'); + if (pos != string::npos) { + if (pos == m_filename.length()) // File could not end with slash + throw std::invalid_argument(getErrorMessage(m_filename, m_requireExtension)); + m_directory = m_filename.substr(0, pos + 1); // Include the last slash in the directory + name = m_filename.substr(pos + 1); // No slash in the name + } else { + m_directory = ""; + } + + pos = name.find_last_of('.'); + if (pos == string::npos || pos == 0 || pos == name.length() - 1) { + if (pos != string::npos || m_requireExtension) + throw std::invalid_argument(getErrorMessage(m_filename, m_requireExtension)); + m_name = name; + m_extension = ""; + } else { + m_name = name.substr(0, pos); + m_extension = name.substr(pos + 1); + } +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/FileURI.h b/src/vendor/cigraph/vendor/infomap/src/utils/FileURI.h new file mode 100644 index 00000000000..8dc1511e69b --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/FileURI.h @@ -0,0 +1,54 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef FILEURI_H_ +#define FILEURI_H_ + +#include +#include + +namespace infomap { + +/** + * Filename class to simplify handling of parts of a filename. + * If a path is path/to/file.ext, the member methods of this class give these parts: + * getFilename -> "path/to/file.ext" + * getName -> "file" + * getExtension -> "ext" + * Can throw std::invalid_argument on creation. + */ +class FileURI { +public: + FileURI() = default; + + explicit FileURI(std::string filename, bool requireExtension = false); + + const std::string& getFilename() const { return m_filename; } + + const std::string& getName() const { return m_name; } + + const std::string& getExtension() const { return m_extension; } + + friend std::ostream& operator<<(std::ostream& out, const FileURI& file) + { + return out << file.getFilename(); + } + +private: + std::string m_filename; + bool m_requireExtension = false; + + std::string m_directory; + std::string m_name; + std::string m_extension; +}; + +} // namespace infomap + +#endif // FILEURI_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.cpp b/src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.cpp new file mode 100644 index 00000000000..723f1674e3a --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.cpp @@ -0,0 +1,898 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "FlowCalculator.h" +#include "../utils/Log.h" +#include "../utils/infomath.h" +#include "../core/StateNetwork.h" +#include +#include +#include +#include +#include +#include + +namespace infomap { + +template +inline void normalize(std::vector& v, const T sum) noexcept +{ + for (auto& numerator : v) { + numerator /= sum; + } +} + +template +inline void normalize(std::vector& v) noexcept +{ + const auto sum = std::accumulate(cbegin(v), cend(v), T {}); + normalize(v, sum); +} + +FlowCalculator::FlowCalculator(StateNetwork& network, const Config& config) + : numNodes(network.numNodes()) +{ + Log() << "Calculating global network flow using flow model '" << config.flowModel << "'... " << std::flush; + + // Prepare data in sequence containers for fast access of individual elements + // Map to zero-based dense indexing + nodeFlow.assign(numNodes, 0.0); + nodeTeleportWeights.assign(numNodes, 0.0); // Fraction of teleportation flow landing on node i + + nodeOutDegree.assign(numNodes, 0); + sumLinkOutWeight.assign(numNodes, 0.0); + + unsigned int nodeIndex = 0; + const auto& nodeLinkMap = network.nodeLinkMap(); + + if (network.isBipartite()) { + // Preserve node order + for (const auto& node : network.nodes()) { + const auto nodeId = node.second.id; + nodeIndexMap[nodeId] = nodeIndex++; + } + + auto bipartiteStartId = network.bipartiteStartId(); + bipartiteStartIndex = nodeIndexMap[bipartiteStartId]; + + } else { + if (config.flowModel != FlowModel::directed) { + // Preserve node order + for (const auto& node : network.nodes()) { + const auto nodeId = node.second.id; + nodeIndexMap[nodeId] = nodeIndex++; + } + } else { + // Store dangling nodes out-of-order, + // with dangling nodes first to optimize calculation of dangling rank + + for (const auto& node : network.nodes()) { + const auto isDangling = nodeLinkMap.find(node.second) == nodeLinkMap.end(); + if (!isDangling) continue; + + const auto& nodeId = node.second.id; + nodeIndexMap[nodeId] = nodeIndex++; + } + + nonDanglingStartIndex = nodeIndex; + + for (const auto& node : network.nodes()) { + const auto isDangling = nodeLinkMap.find(node.second) == nodeLinkMap.end(); + if (isDangling) continue; + + const auto& nodeId = node.second.id; + nodeIndexMap[nodeId] = nodeIndex++; + } + } + } + + flowLinks.resize(network.numLinks(), { 0, 0, 0.0 }); + sumLinkWeight = network.sumLinkWeight(); + sumWeightedDegree = network.sumWeightedDegree(); + + if (network.isBipartite()) { + const auto bipartiteStartId = network.bipartiteStartId(); + + for (const auto& node : nodeLinkMap) { + const auto sourceIsFeature = node.first.id >= bipartiteStartId; + if (sourceIsFeature) continue; + bipartiteLinkStartIndex += node.second.size(); + } + } + + unsigned int linkIndex = 0; + unsigned int featureLinkIndex = bipartiteLinkStartIndex; // bipartite case + + for (const auto& node : nodeLinkMap) { + const auto sourceId = node.first.id; + const auto sourceIndex = nodeIndexMap[sourceId]; + + for (const auto& link : node.second) { + const auto targetId = link.first.id; + const auto targetIndex = nodeIndexMap[targetId]; + const auto linkWeight = link.second.weight; + + ++nodeOutDegree[sourceIndex]; + sumLinkOutWeight[sourceIndex] += linkWeight; + nodeFlow[sourceIndex] += linkWeight / sumWeightedDegree; + + if (network.isBipartite() && sourceId >= network.bipartiteStartId()) { + // Link from feature node to ordinary node + flowLinks[featureLinkIndex].source = sourceIndex; + flowLinks[featureLinkIndex].target = targetIndex; + flowLinks[featureLinkIndex].flow = linkWeight; + ++featureLinkIndex; + } else { + // Ordinary link, or unipartite + flowLinks[linkIndex].source = sourceIndex; + flowLinks[linkIndex].target = targetIndex; + flowLinks[linkIndex].flow = linkWeight; + ++linkIndex; + } + + if (sourceIndex != targetIndex) { + if (config.isUndirectedFlow()) { + ++nodeOutDegree[targetIndex]; + sumLinkOutWeight[targetIndex] += linkWeight; + } + if (config.flowModel != FlowModel::outdirdir) { + nodeFlow[targetIndex] += linkWeight / sumWeightedDegree; + } + } + } + } + + bool normalizeNodeFlow = false; + + switch (config.flowModel) { + case FlowModel::undirected: + if (config.regularized) { + calcUndirectedRegularizedFlow(network, config); + } else { + calcUndirectedFlow(); + } + break; + case FlowModel::directed: + if (network.isBipartite() && config.bipartiteTeleportation) { + calcDirectedBipartiteFlow(network, config); + } else { + if (config.regularized) { + calcDirectedRegularizedFlow(network, config); + } else { + calcDirectedFlow(network, config); + } + } + break; + case FlowModel::undirdir: + case FlowModel::outdirdir: + calcDirdirFlow(config); + normalizeNodeFlow = true; + break; + case FlowModel::rawdir: + calcRawdirFlow(); + normalizeNodeFlow = true; + break; + case FlowModel::precomputed: + usePrecomputedFlow(network, config); + normalizeNodeFlow = true; + break; + } + + finalize(network, config, normalizeNodeFlow); +} + +void FlowCalculator::calcUndirectedFlow() noexcept +{ + Log() << "\n -> Using undirected links."; + + // Flow is outgoing transition probability times source node flow + // = w_ij / s_ij * s_ij / sum(s_ij) = w_ij / sum(s_ij) + // Count twice for non-loops to cover flow in both directions + // Assuming convention to treat self-links as directed + + for (auto& link : flowLinks) { + link.flow /= sumWeightedDegree; + if (link.source != link.target) { + link.flow *= 2; + } + } +} + +void FlowCalculator::calcDirdirFlow(const Config& config) noexcept +{ + if (config.flowModel == FlowModel::outdirdir) + Log() << "\n -> Counting only ingoing links."; + else + Log() << "\n -> Using undirected links, switching to directed after steady state."; + + // Take one last power iteration + const std::vector nodeFlowSteadyState(nodeFlow); + nodeFlow.assign(numNodes, 0.0); + + for (const auto& link : flowLinks) { + nodeFlow[link.target] += nodeFlowSteadyState[link.source] * link.flow / sumLinkOutWeight[link.source]; + } + + double sumNodeFlow = std::accumulate(cbegin(nodeFlow), cend(nodeFlow), 0.0); + + // Update link data to represent flow instead of weight + for (auto& link : flowLinks) { + link.flow *= nodeFlowSteadyState[link.source] / sumLinkOutWeight[link.source] / sumNodeFlow; + } +} + +void FlowCalculator::calcRawdirFlow() noexcept +{ + Log() << "\n -> Using directed links with raw flow."; + Log() << "\n -> Total link weight: " << sumLinkWeight << "."; + + // Treat the link weights as flow (after global normalization) and + // do one power iteration to set the node flow + nodeFlow.assign(numNodes, 0.0); + + for (auto& link : flowLinks) { + link.flow /= sumLinkWeight; + nodeFlow[link.target] += link.flow; + } +} + +void FlowCalculator::usePrecomputedFlow(const StateNetwork& network, const Config& config) +{ + Log() << "\n -> Using directed links with precomputed flow from input data."; + Log() << "\n -> Total link flow: " << sumLinkWeight << "."; + + if (network.haveFileInput()) { + if (network.haveMemoryInput() && !network.haveStateNodeWeights()) { + Log() << std::endl; + throw std::runtime_error("Missing node flow in input data. Should be passed as a third field under a *States section."); + } + if (!network.haveMemoryInput() && !network.haveNodeWeights()) { + Log() << std::endl; + throw std::runtime_error("Missing node flow in input data. Should be passed as a third field under a *Vertices section."); + } + } + + // Treat the link weights as flow + nodeFlow.assign(numNodes, 0.0); + double sumFlow = 0.0; + + for (const auto& nodeIt : network.nodes()) { + auto& node = nodeIt.second; + nodeFlow[nodeIndexMap[node.id]] = node.weight; + sumFlow += node.weight; + } + Log() << "\n -> Total node flow: " << sumFlow << "."; + + if (infomath::isEqual(sumFlow, 0)) { + throw std::runtime_error("Missing node flow. Set it on the node weight property."); + } + if (!infomath::isEqual(sumFlow, 1)) { + if (infomath::isEqual(sumFlow, numNodes) && infomath::isEqual(nodeFlow[0], 1)) { + Log() << "\n Warning: Node flow sums to the number of nodes, is node flow provided or is default node weights used? Normalizing."; + } else { + Log() << "\n Warning: Node flow sums to " << sumFlow << ", normalizing."; + } + for (unsigned int i = 0; i < numNodes; ++i) { + nodeFlow[i] /= sumFlow; + } + } +} + +struct IterationResult { + double alpha; + double beta; +}; + +template +IterationResult powerIterate(double alpha, Iteration&& iter) +{ + unsigned int iterations = 0; + double beta = 1.0 - alpha; + double err = 0.0; + + do { + double oldErr = err; + err = iter(iterations, alpha, beta); + + // Perturb the system if equilibrium + if (std::abs(err - oldErr) < 1e-17) { + alpha += 1.0e-12; + beta = 1.0 - alpha; + } + + ++iterations; + } while (iterations < 200 && (err > 1.0e-15 || iterations < 50)); + + Log() << "\n -> PageRank calculation done in " << iterations << " iterations.\n"; + + return { alpha, beta }; +} + +void FlowCalculator::calcDirectedFlow(const StateNetwork& network, const Config& config) noexcept +{ + Log() << "\n -> Using " << (config.recordedTeleportation ? "recorded" : "unrecorded") << " teleportation to " << (config.teleportToNodes ? "nodes" : "links") << ". " << std::flush; + + // Calculate the teleport rate distribution + if (config.teleportToNodes) { + double sumNodeWeights = 0.0; + + for (const auto& nodeIt : network.nodes()) { + auto& node = nodeIt.second; + nodeTeleportWeights[nodeIndexMap[node.id]] = node.weight; + sumNodeWeights += node.weight; + } + + normalize(nodeTeleportWeights, sumNodeWeights); + } else { + // Teleport to links + + // Teleport proportionally to out-degree, or in-degree if recorded teleportation. + for (const auto& link : flowLinks) { + auto toNode = config.recordedTeleportation ? link.target : link.source; + nodeTeleportWeights[toNode] += link.flow / sumLinkWeight; + } + } + + // Normalize link weights with respect to its source nodes total out-link weight; + for (auto& link : flowLinks) { + if (sumLinkOutWeight[link.source] > 0) { + link.flow /= sumLinkOutWeight[link.source]; + } + } + + std::vector nodeFlowTmp(numNodes, 0.0); + double danglingRank; + + // Calculate PageRank + const auto iteration = [&](const auto iter, const double alpha, const double beta) { + danglingRank = std::accumulate(cbegin(nodeFlow), cbegin(nodeFlow) + nonDanglingStartIndex, 0.0); + + // Flow from teleportation + const auto teleportationFlow = alpha + beta * danglingRank; + for (unsigned int i = 0; i < numNodes; ++i) { + nodeFlowTmp[i] = teleportationFlow * nodeTeleportWeights[i]; + } + + // Flow from links + for (const auto& link : flowLinks) { + nodeFlowTmp[link.target] += beta * link.flow * nodeFlow[link.source]; + } + + // Update node flow from the power iteration above and check if converged + double nodeFlowDiff = -1.0; // Start with -1.0 so we don't have to subtract it later + double error = 0.0; + for (unsigned int i = 0; i < numNodes; ++i) { + nodeFlowDiff += nodeFlowTmp[i]; + error += std::abs(nodeFlowTmp[i] - nodeFlow[i]); + } + + nodeFlow = nodeFlowTmp; + + // Normalize if needed + if (std::abs(nodeFlowDiff) > 1.0e-10) { + Log() << "(Normalizing ranks after " << iter << " power iterations with error " << nodeFlowDiff << ") "; + normalize(nodeFlow, nodeFlowDiff + 1.0); + } + + return error; + }; + + const auto result = powerIterate(config.teleportationProbability, iteration); + + double sumNodeRank = 1.0; + double beta = result.beta; + + if (!config.recordedTeleportation) { + // Take one last power iteration excluding the teleportation + // and normalize node flow + sumNodeRank = 1.0 - danglingRank; + nodeFlow.assign(numNodes, 0.0); + + for (const auto& link : flowLinks) { + nodeFlow[link.target] += link.flow * nodeFlowTmp[link.source] / sumNodeRank; + } + + beta = 1.0; + } + + // Update the links with their global flow from the PageRank values. + // Note: beta is set to 1 if unrecorded teleportation + for (auto& link : flowLinks) { + link.flow *= beta * nodeFlowTmp[link.source] / sumNodeRank; + } +} + +void FlowCalculator::calcDirectedRegularizedFlow(const StateNetwork& network, const Config& config) noexcept +{ + Log() << "\n -> Using recorded teleportation to nodes according to a fully connected Bayesian prior. " << std::flush; + + // Calculate node weights w_i = s_i/k_i, where s_i is the node strength (weighted degree) and k_i the (unweighted) degree + unsigned int N = network.numNodes(); + + std::vector k_out(N, 0); + std::vector k_in(N, 0); + std::vector s_out(N, 0); + std::vector s_in(N, 0); + double sum_s = sumWeightedDegree; + unsigned int sum_k = network.sumDegree(); + double average_weight = sum_s / sum_k; + + for (auto& link : flowLinks) { + k_out[link.source] += 1; + s_out[link.source] += link.flow; + k_in[link.target] += 1; + s_in[link.target] += link.flow; + } + + double min_u_out = std::numeric_limits::max(); + double min_u_in = std::numeric_limits::max(); + for (unsigned int i = 0; i < N; ++i) { + if (k_out[i] > 0) { + min_u_out = std::min(min_u_out, s_out[i] / k_out[i]); + } + if (k_in[i] > 0) { + min_u_in = std::min(min_u_in, s_in[i] / k_in[i]); + } + } + + auto u_out = [s_out, k_out, min_u_out](auto i) { return k_out[i] == 0 ? min_u_out : s_out[i] / k_out[i]; }; + auto u_in = [s_in, k_in, min_u_in](auto i) { return k_in[i] == 0 ? min_u_in : s_in[i] / k_in[i]; }; + + unsigned int numNodesAsTeleportationTargets = config.noSelfLinks ? N - 1 : N; + double lambda = config.regularizationStrength * std::log(N) / numNodesAsTeleportationTargets; + double u_t = average_weight; + + double sum_u_in = 0.0; + for (unsigned int i = 0; i < N; ++i) { + sum_u_in += u_in(i); + } + + for (unsigned int i = 0; i < N; ++i) { + nodeTeleportWeights[i] = u_in(i) / sum_u_in; + } + + std::function t_out_withoutSelfLinks = [lambda, u_t, u_out, u_in, sum_u_in](unsigned int i) { return lambda / u_t * u_out(i) * (sum_u_in - u_in(i)); }; + std::function t_out_withSelfLinks = [lambda, u_t, u_out, sum_u_in](unsigned int i) { return lambda / u_t * u_out(i) * sum_u_in; }; + auto t_out = config.noSelfLinks ? t_out_withoutSelfLinks : t_out_withSelfLinks; + + std::vector alpha(N, 0); + for (unsigned int i = 0; i < N; ++i) { + auto t_i = t_out(i); + alpha[i] = t_i / (s_out[i] + t_i); // = 1 for dangling nodes + if (config.noSelfLinks) { + // Inflate to adjust for no self-teleportation + // TODO: Check possible side-effects + alpha[i] /= 1 - nodeTeleportWeights[i]; + } + } + + // Normalize link weights with respect to its source nodes total out-link weight; + for (auto& link : flowLinks) { + if (sumLinkOutWeight[link.source] > 0) { + link.flow /= sumLinkOutWeight[link.source]; + } + } + + std::vector nodeFlowTmp(numNodes, 0.0); + + // Calculate PageRank + const auto iteration = [&](const auto iter) { + double teleTmp = 0.0; + for (unsigned int i = 0; i < N; ++i) { + teleTmp += alpha[i] * nodeFlow[i]; + } + + for (unsigned int i = 0; i < N; ++i) { + nodeFlowTmp[i] = nodeTeleportWeights[i] * (config.noSelfLinks ? (teleTmp - alpha[i] * nodeFlow[i]) : teleTmp); + } + + // Flow from links + for (const auto& link : flowLinks) { + double beta = 1 - alpha[link.source] * (config.noSelfLinks ? 1 - nodeTeleportWeights[link.source] : 1); + nodeFlowTmp[link.target] += beta * link.flow * nodeFlow[link.source]; + } + + // Update node flow from the power iteration above and check if converged + double nodeFlowDiff = -1.0; // Start with -1.0 so we don't have to subtract it later + double error = 0.0; + for (unsigned int i = 0; i < numNodes; ++i) { + nodeFlowDiff += nodeFlowTmp[i]; + error += std::abs(nodeFlowTmp[i] - nodeFlow[i]); + } + + nodeFlow = nodeFlowTmp; + + // Normalize if needed + if (std::abs(nodeFlowDiff) > 1.0e-10) { + Log() << "(Normalizing ranks after " << iter << " power iterations with error " << nodeFlowDiff << ") "; + normalize(nodeFlow, nodeFlowDiff + 1.0); + } + + return error; + }; + + unsigned int iterations = 0; + double err = 0.0; + + do { + double oldErr = err; + err = iteration(iterations); + + // Perturb the system if equilibrium + if (std::abs(err - oldErr) < 1e-15) { + } + + ++iterations; + } while (iterations < 200 && (err > 1.0e-15 || iterations < 50)); + + Log() << "\n -> PageRank calculation done in " << iterations << " iterations.\n"; + + double sumNodeRank = 1.0; + for (auto& link : flowLinks) { + double beta = 1 - alpha[link.source] * (config.noSelfLinks ? 1 - nodeTeleportWeights[link.source] : 1); + link.flow *= beta * nodeFlow[link.source] / sumNodeRank; + } + + nodeTeleportFlow.assign(numNodes, 0.0); + for (unsigned int i = 0; i < N; ++i) { + nodeTeleportFlow[i] = nodeFlow[i] * alpha[i]; + } +} + +void FlowCalculator::calcUndirectedRegularizedFlow(const StateNetwork& network, const Config& config) noexcept +{ + Log() << "\n -> Using recorded teleportation to nodes according to a fully connected Bayesian prior. " << std::flush; + + // Calculate node weights w_i = s_i/k_i, where s_i is the node strength (weighted degree) and k_i the (unweighted) degree + unsigned int N = network.numNodes(); + std::vector k(N, 0); + std::vector s(N, 0); + double sum_s = sumWeightedDegree; + unsigned int sum_k = network.sumDegree(); + double average_weight = sum_s / sum_k; + + for (auto& link : flowLinks) { + k[link.source] += 1; + s[link.source] += link.flow; + if (link.source != link.target) { + k[link.target] += 1; + s[link.target] += link.flow; + } + } + + double min_u = std::numeric_limits::max(); + for (unsigned int i = 0; i < N; ++i) { + if (k[i] > 0) { + min_u = std::min(min_u, s[i] / k[i]); + } + } + + auto u = [s, k, min_u](auto i) { return k[i] == 0 ? min_u : s[i] / k[i]; }; + + unsigned int numNodesAsTeleportationTargets = config.noSelfLinks ? N - 1 : N; + double lambda = config.regularizationStrength * std::log(N) / numNodesAsTeleportationTargets; + double u_t = average_weight; + + double sum_u = 0.0; + for (unsigned int i = 0; i < N; ++i) { + sum_u += u(i); + } + + // nodeTeleportWeights is the fraction of teleportation flow landing on each node. This is proportional to u_in + for (unsigned int i = 0; i < N; ++i) { + nodeTeleportWeights[i] = u(i) / sum_u; + } + + std::function t_withoutSelfLinks = [lambda, u_t, u, sum_u](unsigned int i) { return lambda / u_t * u(i) * (sum_u - u(i)); }; + std::function t_withSelfLinks = [lambda, u_t, u, sum_u](unsigned int i) { return lambda / u_t * u(i) * sum_u; }; + auto t = config.noSelfLinks ? t_withoutSelfLinks : t_withSelfLinks; + + std::vector alpha(N, 0); + double sum_t = 0.0; + for (unsigned int i = 0; i < N; ++i) { + auto t_i = t(i); + alpha[i] = t_i / (s[i] + t_i); + if (config.noSelfLinks) { + // Inflate to adjust for no self-teleportation + // TODO: No later side effects of cheating here? Need to normalize targets instead? + alpha[i] /= 1 - nodeTeleportWeights[i]; + } + sum_t += t_i; + } + + for (auto& link : flowLinks) { + if (sumLinkOutWeight[link.source] > 0) { + link.flow /= sumLinkOutWeight[link.source]; + } + } + + for (unsigned int i = 0; i < N; ++i) { + nodeFlow[i] = (s[i] + t(i)) / (sum_s + sum_t); + } + + nodeTeleportFlow.assign(numNodes, 0.0); + for (unsigned int i = 0; i < N; ++i) { + nodeTeleportFlow[i] = nodeFlow[i] * alpha[i]; + } + + for (auto& link : flowLinks) { + // TODO: Side effect from inflating alpha, need real alpha here. + double beta = 1 - alpha[link.source] * (config.noSelfLinks ? 1 - nodeTeleportWeights[link.source] : 1); + link.flow *= beta * nodeFlow[link.source] * 2; + } +} + +void FlowCalculator::calcDirectedBipartiteFlow(const StateNetwork& network, const Config& config) noexcept +{ + Log() << "\n -> Using bipartite " << (config.recordedTeleportation ? "recorded" : "unrecorded") << " teleportation to " << (config.teleportToNodes ? "nodes" : "links") << ". " << std::flush; + + const auto bipartiteStartId = network.bipartiteStartId(); + + if (config.teleportToNodes) { + for (const auto& nodeIt : network.nodes()) { + auto& node = nodeIt.second; + if (node.id < bipartiteStartId) { + nodeTeleportWeights[nodeIndexMap[node.id]] = node.weight; + } + } + } else { + // Teleport proportionally to out-degree, or in-degree if recorded teleportation. + // Two-step degree: sum of products between incoming and outgoing links from bipartite nodes + + if (config.recordedTeleportation) { + for (auto link = begin(flowLinks) + bipartiteLinkStartIndex; link != end(flowLinks); ++link) { + // target is an ordinary node + nodeTeleportWeights[link->target] += link->flow; + } + } else { + // Unrecorded teleportation + + for (auto link = begin(flowLinks); link != begin(flowLinks) + bipartiteLinkStartIndex; ++link) { + // source is an ordinary node + nodeTeleportWeights[link->source] += link->flow; + } + } + } + + normalize(nodeTeleportWeights); + + nodeFlow = nodeTeleportWeights; + + // Normalize link weights with respect to its source nodes total out-link weight; + for (auto& link : flowLinks) { + if (sumLinkOutWeight[link.source] > 0) { + link.flow /= sumLinkOutWeight[link.source]; + } + } + + std::vector danglingIndices; + for (size_t i = 0; i < numNodes; ++i) { + if (nodeOutDegree[i] == 0) { + danglingIndices.push_back(i); + } + } + + std::vector nodeFlowTmp(numNodes, 0.0); + double danglingRank; + + // Calculate two-step PageRank + const auto iteration = [&](const auto iter, const double alpha, const double beta) { + danglingRank = 0.0; + for (const auto& i : danglingIndices) { + danglingRank += nodeFlow[i]; + } + + // Flow from teleportation + const auto teleportationFlow = alpha + beta * danglingRank; + for (unsigned int i = 0; i < bipartiteStartIndex; ++i) { + nodeFlowTmp[i] = teleportationFlow * nodeTeleportWeights[i]; + } + + for (unsigned int i = bipartiteStartIndex; i < numNodes; ++i) { + nodeFlowTmp[i] = 0.0; + } + + // Flow from links + // First step + for (auto link = begin(flowLinks); link != begin(flowLinks) + bipartiteLinkStartIndex; ++link) { + nodeFlow[link->target] += beta * link->flow * nodeFlow[link->source]; + } + + // Second step back to primary nodes + for (auto link = begin(flowLinks) + bipartiteLinkStartIndex; link != end(flowLinks); ++link) { + nodeFlowTmp[link->target] += link->flow * nodeFlow[link->source]; + } + + // Update node flow from the power iteration above and check if converged + double nodeFlowDiff = -1.0; + double error = 0.0; + for (unsigned int i = 0; i < bipartiteStartIndex; ++i) { + nodeFlowDiff += nodeFlowTmp[i]; + error += std::abs(nodeFlowTmp[i] - nodeFlow[i]); + } + + nodeFlow = nodeFlowTmp; + + // Normalize if needed + if (std::abs(nodeFlowDiff) > 1.0e-10) { + Log() << "(Normalizing ranks after " << iter << " power iterations with error " << nodeFlowDiff << ") "; + normalize(nodeFlow, nodeFlowDiff + 1.0); + } + + return error; + }; + + const auto result = powerIterate(config.teleportationProbability, iteration); + + double sumNodeRank = 1.0; + double beta = result.beta; + + if (!config.recordedTeleportation) { + // Take one last power iteration excluding the teleportation (and normalize node flow to sum 1.0) + sumNodeRank = 1.0 - danglingRank; + nodeFlow.assign(numNodes, 0.0); + + for (auto link = begin(flowLinks); link != begin(flowLinks) + bipartiteLinkStartIndex; ++link) { + nodeFlowTmp[link->target] += link->flow * nodeFlowTmp[link->source]; + } + // Second step back to primary nodes + for (auto link = begin(flowLinks) + bipartiteLinkStartIndex; link != end(flowLinks); ++link) { + nodeFlow[link->target] += link->flow * nodeFlowTmp[link->source]; + } + + beta = 1.0; + } + + // Update the links with their global flow from the PageRank values. + // Note: beta is set to 1 if unrecorded teleportation + for (auto& link : flowLinks) { + link.flow *= beta * nodeFlowTmp[link.source] / sumNodeRank; + } +} + +void FlowCalculator::finalize(StateNetwork& network, const Config& config, bool normalizeNodeFlow) noexcept +{ + unsigned int N = network.numNodes(); + // TODO: Skip bipartite flow adjustment for directed / rawdir / .. ? + if (network.isBipartite()) { + Log() << "\n -> Using bipartite links."; + + if (!config.skipAdjustBipartiteFlow && !config.bipartiteTeleportation) { + // Only links between ordinary nodes and feature nodes in bipartite network + // Don't code feature nodes -> distribute all flow from those to ordinary nodes + for (auto& link : flowLinks) { + auto sourceIsFeature = link.source >= bipartiteStartIndex; + + if (sourceIsFeature) { + nodeFlow[link.target] += link.flow; + nodeFlow[link.source] = 0.0; // Doesn't matter if done multiple times on each node. + } else { + nodeFlow[link.source] += link.flow; + nodeFlow[link.target] = 0.0; // Doesn't matter if done multiple times on each node. + } + // TODO: Should flow double before moving to nodes, does it cancel out in normalization? + + // Markov time 2 on the full network will correspond to markov time 1 between the real nodes. + link.flow *= 2; + } + // TODO: Should flow double before moving to nodes, does it cancel out in normalization? + + normalizeNodeFlow = true; + + } else if (config.bipartiteTeleportation) { + for (auto& link : flowLinks) { + // Markov time 2 on the full network will correspond to markov time 1 between the real nodes. + link.flow *= 2; + } + } + } + + if (config.useNodeWeightsAsFlow) { + Log() << "\n -> Using node weights as flow."; + + for (auto& nodeIt : network.nodes()) { + auto& node = nodeIt.second; + nodeFlow[nodeIndexMap[node.id]] = node.weight; + } + + normalizeNodeFlow = true; + } + + if (normalizeNodeFlow) { + normalize(nodeFlow); + } + + // Write back flow to network + double sumNodeFlow = 0.0; + double sumLinkFlow = 0.0; + unsigned int linkIndex = 0; + auto featureLinkIndex = bipartiteLinkStartIndex; + + for (auto& node : network.m_nodeLinkMap) { + for (auto& link : node.second) { + auto& linkData = link.second; + if (network.isBipartite() && node.first.id >= network.bipartiteStartId()) { + linkData.flow = flowLinks[featureLinkIndex++].flow; + } else { + linkData.flow = flowLinks[linkIndex++].flow; + } + sumLinkFlow += linkData.flow; + } + } + + for (auto& nodeIt : network.m_nodes) { + auto& node = nodeIt.second; + const auto nodeIndex = nodeIndexMap[node.id]; + node.flow = nodeFlow[nodeIndex]; + node.weight = nodeTeleportWeights[nodeIndex]; + node.teleFlow = !nodeTeleportFlow.empty() ? nodeTeleportFlow[nodeIndex] : nodeFlow[nodeIndex] * (nodeOutDegree[nodeIndex] == 0 ? 1 : config.teleportationProbability); + node.enterFlow = node.flow; + node.exitFlow = node.flow; + + if (!config.noSelfLinks) { + // Remove self-teleportation flow + node.enterFlow -= node.teleFlow * node.weight; + node.exitFlow -= node.teleFlow * node.weight; + + // Remove self-link flow + unsigned int norm = config.isUndirectedFlow() ? 2 : 1; + auto& outLinks = network.m_nodeLinkMap[node.id]; + for (auto& link : outLinks) { + auto& linkData = link.second; + if (node.id == link.first.id) { + node.enterFlow -= linkData.flow / norm; + node.exitFlow -= linkData.flow / norm; + break; + } + } + } + + sumNodeFlow += node.flow; + } + + // Enter/exit flow + if (!config.isUndirectedClustering() && !config.regularized) { + enterFlow.assign(N, 0); + exitFlow.assign(N, 0); + double alpha = config.teleportationProbability; + double sumDanglingFlow = 0.0; + for (unsigned int i = 0; i < N; ++i) { + if (nodeOutDegree[i] == 0) { + sumDanglingFlow += nodeFlow[i]; + } + } + for (auto& nodeIt : network.m_nodes) { + auto& node = nodeIt.second; + const auto sourceIndex = nodeIndexMap[node.id]; + auto& outLinks = network.m_nodeLinkMap[node.id]; + double danglingFlow = outLinks.empty() ? node.flow : 0.0; + if (config.recordedTeleportation) { + // Don't let self-teleportation add to the enter/exit flow (i.e. multiply with (1.0 - node.data.teleportWeight)) + exitFlow[sourceIndex] += alpha * node.flow * (1.0 - node.weight); + enterFlow[sourceIndex] += (alpha * (1.0 - node.flow) + (1 - alpha) * (sumDanglingFlow - danglingFlow)) * node.weight; + } + for (auto& link : outLinks) { + auto& linkData = link.second; + const auto targetIndex = nodeIndexMap[link.first.id]; + exitFlow[sourceIndex] += linkData.flow; + enterFlow[targetIndex] += linkData.flow; + } + } + for (auto& nodeIt : network.m_nodes) { + auto& node = nodeIt.second; + const auto nodeIndex = nodeIndexMap[node.id]; + node.enterFlow = enterFlow[nodeIndex]; + node.exitFlow = exitFlow[nodeIndex]; + } + } + + Log() << "\n => Sum node flow: " << sumNodeFlow << ", sum link flow: " << sumLinkFlow << "\n"; +} + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.h b/src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.h new file mode 100644 index 00000000000..88294b37c4b --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.h @@ -0,0 +1,75 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef FLOW_CALCULATOR_H_ +#define FLOW_CALCULATOR_H_ + +#include +#include + +namespace infomap { + +struct Config; +class StateNetwork; + +namespace detail { + struct FlowLink { + unsigned int source; + unsigned int target; + double flow; + }; +} // namespace detail + +/** + * Calculate flow on network based on different flow models + */ +class FlowCalculator { +public: + FlowCalculator(StateNetwork&, const Config&); + +private: + void calcUndirectedFlow() noexcept; + void calcDirectedFlow(const StateNetwork&, const Config&) noexcept; + void calcUndirectedRegularizedFlow(const StateNetwork&, const Config&) noexcept; + void calcDirectedRegularizedFlow(const StateNetwork&, const Config&) noexcept; + void calcDirectedBipartiteFlow(const StateNetwork&, const Config&) noexcept; + void calcDirdirFlow(const Config&) noexcept; + void calcRawdirFlow() noexcept; + void usePrecomputedFlow(const StateNetwork&, const Config&); + + void finalize(StateNetwork&, const Config&, bool) noexcept; + + unsigned int numNodes; + unsigned int nonDanglingStartIndex = 0; + unsigned int bipartiteStartIndex = 0; + unsigned int bipartiteLinkStartIndex = 0; + + double sumLinkWeight = 0; + double sumWeightedDegree = 0; + + std::map nodeIndexMap; + std::vector nodeFlow; + std::vector nodeTeleportWeights; + std::vector nodeTeleportFlow; + std::vector enterFlow; + std::vector exitFlow; + std::vector sumLinkOutWeight; + std::vector nodeOutDegree; + using FlowLink = detail::FlowLink; + std::vector flowLinks; +}; + +inline void calculateFlow(StateNetwork& network, const Config& config) +{ + FlowCalculator(network, config); +} + +} // namespace infomap + +#endif // FLOW_CALCULATOR_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/Log.cpp b/src/vendor/cigraph/vendor/infomap/src/utils/Log.cpp new file mode 100644 index 00000000000..f16f2b0843b --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/Log.cpp @@ -0,0 +1,17 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#include "Log.h" + +namespace infomap { + +unsigned int Log::s_verboseLevel = 0; +bool Log::s_silent = false; + +} // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/Log.h b/src/vendor/cigraph/vendor/infomap/src/utils/Log.h new file mode 100644 index 00000000000..6a236544635 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/Log.h @@ -0,0 +1,103 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef LOG_H_ +#define LOG_H_ + +#include +#include +#include +#include + +namespace infomap { + +struct hideIf; + +class Log { + using ostreamFuncPtr = std::add_pointer_t; + +public: + /** + * Log when level is below or equal Log::verboseLevel() + * and maxLevel is above or equal Log::verboseLevel() + */ + explicit Log(unsigned int level = 0, unsigned int maxLevel = std::numeric_limits::max()) + : m_level(level), m_maxLevel(maxLevel), m_visible(isVisible(m_level, m_maxLevel)) { } + + bool isVisible() const { return isVisible(m_level, m_maxLevel); } + + void hide(bool value) { m_visible = !value && isVisible(); } + + Log& operator<<(const hideIf&) { return *this; } + + template + Log& operator<<(const T& data) + { + if (m_visible) + m_ostream << data; + return *this; + } + + Log& operator<<(ostreamFuncPtr f) + { + if (m_visible) + m_ostream << f; + return *this; + } + + static void init(unsigned int verboseLevel, bool silent, unsigned int numberPrecision) + { + setVerboseLevel(verboseLevel); + setSilent(silent); + Log() << std::setprecision(static_cast(numberPrecision)); + } + + static bool isVisible(unsigned int level, unsigned int maxLevel) + { + return !s_silent && s_verboseLevel >= level && s_verboseLevel <= maxLevel; + } + + static void setVerboseLevel(unsigned int level) { s_verboseLevel = level; } + + static void setSilent(bool silent) { s_silent = silent; } + + static bool isSilent() { return s_silent; } + + static std::streamsize precision() { return std::cout.precision(); } + + static std::streamsize precision(std::streamsize precision) + { + return std::cout.precision(precision); + } + +private: + unsigned int m_level; + unsigned int m_maxLevel; + bool m_visible; + std::ostream& m_ostream = std::cout; + + static unsigned int s_verboseLevel; + static bool s_silent; +}; + +struct hideIf { + explicit hideIf(bool value) : hide(value) { } + + friend Log& operator<<(Log& out, const hideIf& manip) + { + out.hide(manip.hide); + return out; + } + + bool hide; +}; + +} // namespace infomap + +#endif // LOG_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/MetaCollection.h b/src/vendor/cigraph/vendor/infomap/src/utils/MetaCollection.h new file mode 100644 index 00000000000..67a60d3befe --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/MetaCollection.h @@ -0,0 +1,153 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef META_COLLECTION_H_ +#define META_COLLECTION_H_ + +#include "infomath.h" +#include +#include + +namespace infomap { + +struct FlowCount { + FlowCount() = default; + + explicit FlowCount(double flow) + : flow(flow), count(1) { } + + FlowCount& operator+=(const FlowCount& o) + { + flow += o.flow; + count += o.count; + return *this; + } + + FlowCount& operator+=(double f) + { + flow += f; + ++count; + return *this; + } + + FlowCount& operator-=(const FlowCount& o) + { + flow -= o.flow; + count -= o.count; + return *this; + } + + FlowCount& operator-=(double f) + { + flow -= f; + --count; + return *this; + } + + friend std::ostream& operator<<(std::ostream& out, const FlowCount& o) + { + return out << o.flow << "/" << o.count; + } + + void reset() + { + flow = 0.0; + count = 0; + } + + bool empty() const { return count == 0; } + double flow = 0.0; + unsigned int count = 0; +}; + +using MetaToFlowCount = std::map; // metaId -> (flow,count) + +class MetaCollection { +protected: + FlowCount m_total; + MetaToFlowCount m_metaToFlowCount; + +public: + unsigned int size() const { return m_metaToFlowCount.size(); } + + bool empty() const { return m_metaToFlowCount.empty(); } + + MetaToFlowCount::iterator begin() { return m_metaToFlowCount.begin(); } + MetaToFlowCount::iterator end() { return m_metaToFlowCount.end(); } + MetaToFlowCount::const_iterator begin() const { return m_metaToFlowCount.begin(); } + MetaToFlowCount::const_iterator end() const { return m_metaToFlowCount.end(); } + + void add(unsigned int meta, double flow = 1.0) + { + m_total += flow; + m_metaToFlowCount[meta] += flow; + } + + void add(unsigned int meta, const FlowCount& flow) + { + m_total += flow; + m_metaToFlowCount[meta] += flow; + } + + void add(const MetaCollection& other) + { + for (auto& it : other) { + auto metaId = it.first; + auto& flowCount = it.second; + add(metaId, flowCount); + } + } + + void remove(unsigned int meta, const FlowCount& flow) + { + m_total -= flow; + auto& metaFlowCount = m_metaToFlowCount[meta]; + metaFlowCount -= flow; + if (metaFlowCount.empty()) + m_metaToFlowCount.erase(meta); + } + + void remove(const MetaCollection& other) + { + for (auto& it : other) { + auto metaId = it.first; + auto& flowCount = it.second; + remove(metaId, flowCount); + } + } + + double calculateEntropy() + { + double metaCodelength = 0.0; + for (auto& it : m_metaToFlowCount) { + metaCodelength -= infomath::plogp(it.second.flow / m_total.flow); + } + return m_total.flow * metaCodelength; + } + + void clear() + { + m_total.reset(); + m_metaToFlowCount.clear(); + } + + friend std::ostream& operator<<(std::ostream& out, const MetaCollection& m) + { + out << "<( " << m.m_total << ": "; + for (auto& it : m.m_metaToFlowCount) { + out << "(" << it.first << "," << it.second << ") "; + } + out << ")>"; + return out; + } +}; + +} // namespace infomap + +#endif // META_COLLECTION_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/Random.h b/src/vendor/cigraph/vendor/infomap/src/utils/Random.h new file mode 100644 index 00000000000..6a50069a444 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/Random.h @@ -0,0 +1,45 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef RANDOM_H_ +#define RANDOM_H_ + +#include + +#include +#include + +namespace infomap { + +class Random { + igraph_rng_t* m_randGen; + +public: + Random() : m_randGen(igraph_rng_default()) { } + + unsigned int randInt(unsigned int min, unsigned int max) + { + return igraph_rng_get_integer(m_randGen, min, max); + } + + /** + * Get a random permutation of indices of the size of the input vector + */ + void getRandomizedIndexVector(std::vector& randomOrder) + { + unsigned int size = randomOrder.size(); + for (unsigned int i = 0; i < size; ++i) + randomOrder[i] = i; + for (unsigned int i = 0; i < size; ++i) + std::swap(randomOrder[i], randomOrder[i + randInt(0, size - i - 1)]); + } +}; +} // namespace infomap + +#endif // RANDOM_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/Stopwatch.h b/src/vendor/cigraph/vendor/infomap/src/utils/Stopwatch.h new file mode 100644 index 00000000000..9ee4210e953 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/Stopwatch.h @@ -0,0 +1,103 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef STOPWATCH_H_ +#define STOPWATCH_H_ + +#include +#include +#include +#include + +namespace infomap { + +class Stopwatch { +public: + using Clock = std::chrono::high_resolution_clock; + using TimeType = std::chrono::time_point; + + explicit Stopwatch(bool startImmediately) + : m_start(now()), m_stop(now()), m_running(false) + { + if (startImmediately) { + start(); + } + } + + void start() + { + m_start = Clock::now(); + m_running = true; + } + + void reset() + { + if (m_running) + m_start = Clock::now(); + } + + void stop() + { + if (m_running) { + m_stop = Clock::now(); + m_running = false; + } + } + + TimeType getCurrentTimePoint() const + { + return m_running ? Clock::now() : m_stop; + } + + double getElapsedTimeInSec() const + { + std::chrono::duration diff = getCurrentTimePoint() - m_start; + return diff.count(); + } + + double getElapsedTimeInMilliSec() const + { + std::chrono::duration diff = getCurrentTimePoint() - m_start; + return diff.count(); + } + + static TimeType now() + { + return Clock::now(); + } + + friend std::ostream& operator<<(std::ostream& out, const Stopwatch& stopwatch) + { + auto temp = static_cast(std::floor(stopwatch.getElapsedTimeInMilliSec())); + if (temp > 60'000) { + if (temp > 3600'000) { + if (temp > 86'400'000) { + out << temp / 86'400'000 << "d "; + temp %= 86'400'000; + } + out << temp / 3600'000 << "h "; + temp %= 3600'000; + } + out << temp / 60'000 << "m "; + temp %= 60'000; + out << temp * 1.0 / 1000 << "s"; + } else { + out << stopwatch.getElapsedTimeInSec() << "s"; + } + return out; + } + +private: + TimeType m_start, m_stop; + bool m_running; +}; + +} // namespace infomap + +#endif // STOPWATCH_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/VectorMap.h b/src/vendor/cigraph/vendor/infomap/src/utils/VectorMap.h new file mode 100644 index 00000000000..63994bc92ac --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/VectorMap.h @@ -0,0 +1,82 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef VECTOR_MAP_H_ +#define VECTOR_MAP_H_ + +#include +#include +#include + +namespace infomap { + +template +class VectorMap { +public: + VectorMap(unsigned int capacity = 0) + : m_capacity(capacity), + m_values(capacity), + m_redirect(capacity, 0), + m_maxOffset(std::numeric_limits::max() - 1 - capacity) { } + + void startRound() + { + if (m_size > 0) { + m_offset += m_capacity; + m_size = 0; + } + if (m_offset > m_maxOffset) { + m_redirect.assign(m_capacity, 0); + m_offset = 1; + } + } + + void add(unsigned int index, T value) + { + if (isSet(index)) { + m_values[m_redirect[index] - m_offset] += value; + } else { + m_redirect[index] = m_offset + m_size; + m_values[m_size] = value; + ++m_size; + } + } + + bool isSet(unsigned int index) + { + return m_redirect[index] >= m_offset; + } + + unsigned int size() + { + return m_size; + } + + T& operator[](unsigned int index) + { + return m_values[m_redirect[index] - m_offset]; + } + + std::vector& values() + { + return m_values; + } + +private: + unsigned int m_capacity = 0; + std::vector m_values; + std::vector m_redirect; + unsigned int m_maxOffset = std::numeric_limits::max() - 1; + unsigned int m_offset = 1; + unsigned int m_size = 0; +}; + +} // namespace infomap + +#endif // VECTOR_MAP_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/convert.h b/src/vendor/cigraph/vendor/infomap/src/utils/convert.h new file mode 100644 index 00000000000..f8e5077a268 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/convert.h @@ -0,0 +1,216 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef CONVERT_H_ +#define CONVERT_H_ + +#include +#include +#include +#include +#include // std::locale, std::tolower +#include +#include + +namespace infomap { + +template +struct TypeInfo { + static bool isNumeric() { return false; } +}; +template <> +struct TypeInfo { + static bool isNumeric() { return false; } +}; +template <> +struct TypeInfo { + static bool isNumeric() { return true; } +}; +template <> +struct TypeInfo { + static bool isNumeric() { return true; } +}; +template <> +struct TypeInfo { + static bool isNumeric() { return true; } +}; + +namespace io { + + inline std::string tolower(std::string str) + { + std::locale loc; + for (char& c : str) + c = std::tolower(c, loc); + return str; + } + + template + inline std::string stringify(T& x) + { + std::ostringstream o; + if (!(o << x)) + throw std::runtime_error((o << "stringify(" << x << ")", o.str())); + return o.str(); + } + + template <> + inline std::string stringify(bool& x) + { + return x ? "true" : "false"; + } + + template + inline std::string stringify(const Container& cont, const std::string& delimiter) + { + std::ostringstream o; + if (cont.empty()) + return ""; + unsigned int maxIndex = cont.size() - 1; + for (unsigned int i = 0; i < maxIndex; ++i) { + if (!(o << cont[i])) + throw std::runtime_error((o << "stringify(container[" << i << "])", o.str())); + o << delimiter; + } + if (!(o << cont[maxIndex])) + throw std::runtime_error((o << "stringify(container[" << maxIndex << "])", o.str())); + return o.str(); + } + + struct InsensitiveCompare { + bool operator()(const std::string& a, const std::string& b) const + { + auto lhs = a.begin(); + auto rhs = b.begin(); + + std::locale loc; + for (; lhs != a.end() && rhs != b.end(); ++lhs, ++rhs) { + auto lhs_val = std::tolower(*lhs, loc); + auto rhs_val = std::tolower(*rhs, loc); + + if (lhs_val != rhs_val) + return lhs_val < rhs_val; + } + + return (rhs != b.end()); + } + }; + + inline std::vector& split(const std::string& s, char delim, std::vector& items) + { + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + if (item.length() > 0) { + items.push_back(item); + } + } + return items; + } + + inline std::vector split(const std::string& s, char delim) + { + std::vector items; + split(s, delim, items); + return items; + } + + class Str { + public: + Str() = default; + template + Str& operator<<(const T& t) + { + m_oss << stringify(t); + return *this; + } + Str& operator<<(std::ostream& (*f)(std::ostream&)) + { + m_oss << f; + return *this; + } + operator std::string() const + { + return m_oss.str(); + } + + private: + std::ostringstream m_oss; + }; + + template + inline bool stringToValue(std::string const& str, T& value) + { + std::istringstream istream(str); + return !!(istream >> value); + } + + template <> + inline bool stringToValue(std::string const& str, unsigned int& value) + { + std::istringstream istream(str); + int target = 0; + istream >> target; + if (target < 0) return false; + value = target; + return true; + } + + template <> + inline bool stringToValue(std::string const& str, unsigned long& value) + { + std::istringstream istream(str); + int target = 0; + istream >> target; + if (target < 0) return false; + value = target; + return true; + } + + inline std::string firstWord(const std::string& line) + { + std::istringstream ss; + std::string buf; + ss.str(line); + ss >> buf; + return buf; + } + + template + inline std::string padValue(T value, const std::string::size_type size, bool rightAligned = true, const char paddingChar = ' ') + { + std::string valStr = stringify(value); + if (size == valStr.size()) + return valStr; + if (size < valStr.size()) + return valStr.substr(0, size); + + if (!rightAligned) + return valStr.append(size - valStr.size(), paddingChar); + + return std::string(size - valStr.size(), paddingChar).append(valStr); + } + + inline std::string toPrecision(double value, unsigned int precision = 10, bool fixed = false) + { + std::ostringstream o; + if (fixed) + o << std::fixed << std::setprecision(static_cast(precision)); + else + o << std::setprecision(static_cast(precision)); + if (!(o << value)) + throw std::runtime_error((o << "stringify(" << value << ")", o.str())); + return o.str(); + } + +} // namespace io + +} // namespace infomap + +#endif // CONVERT_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/infomath.h b/src/vendor/cigraph/vendor/infomap/src/utils/infomath.h new file mode 100644 index 00000000000..7c09add1385 --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/utils/infomath.h @@ -0,0 +1,57 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef INFOMATH_H_ +#define INFOMATH_H_ + +#include +#include + +namespace infomap { +namespace infomath { + + using std::log2; + + inline double plogp(double p) + { + return p > 0.0 ? p * log2(p) : 0.0; + } + + inline double isEqual(double a, double b, double tol = 1e-8) + { + return std::abs(a - b) <= tol; + } + + /** + * Tsallis entropy S_q of a uniform probability distribution of length n + */ + inline double tsallisEntropyUniform(double n, double q = 1) + { + if (isEqual(q, 1)) { + return std::log2(n); + } + return 1 / (q - 1) * (1 - pow(n, (1 - q))) / std::log(2); + } + + /** + * Interpolate from linear (q = 0) to log (q = 1) + * linlog(k, 0) = k + * linlog(k, 1) = log2(k) + */ + inline double linlog(double k, double q = 1) + { + double baseCorrection = q <= 1 ? (1 - q) * std::log(2) + q : 1; + double offsetCorrection = q <= 1 ? 1 - q : 0; + return tsallisEntropyUniform(k, q) * baseCorrection + offsetCorrection; + } + +} // namespace infomath +} // namespace infomap + +#endif // INFOMATH_H_ diff --git a/src/vendor/cigraph/vendor/infomap/src/version.h b/src/vendor/cigraph/vendor/infomap/src/version.h new file mode 100644 index 00000000000..0671d20162b --- /dev/null +++ b/src/vendor/cigraph/vendor/infomap/src/version.h @@ -0,0 +1,19 @@ +/******************************************************************************* + Infomap software package for multi-level network clustering + Copyright (c) 2013, 2014 Daniel Edler, Anton Holmgren, Martin Rosvall + + This file is part of the Infomap software package. + See file LICENSE_GPLv3.txt for full license details. + For more information, see + ******************************************************************************/ + +#ifndef VERSION_H_ +#define VERSION_H_ + +namespace infomap { + +const char* const INFOMAP_VERSION = "2.8.0"; + +} + +#endif // VERSION_H_ diff --git a/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c b/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c index e6bb599afc8..418b823481a 100644 --- a/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c +++ b/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c @@ -1,4 +1,3 @@ -/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2011-12 Gabor Csardi diff --git a/src/vendor/cigraph/vendor/nanoflann/nanoflann.hpp b/src/vendor/cigraph/vendor/nanoflann/nanoflann.hpp new file mode 100644 index 00000000000..43fbded03f3 --- /dev/null +++ b/src/vendor/cigraph/vendor/nanoflann/nanoflann.hpp @@ -0,0 +1,2740 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * Copyright 2011-2025 Jose Luis Blanco (joseluisblancoc@gmail.com). + * All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +/** \mainpage nanoflann C++ API documentation + * nanoflann is a C++ header-only library for building KD-Trees, mostly + * optimized for 2D or 3D point clouds. + * + * nanoflann does not require compiling or installing, just an + * #include in your code. + * + * See: + * - [Online README](https://github.com/jlblancoc/nanoflann) + * - [C++ API documentation](https://jlblancoc.github.io/nanoflann/) + */ + +#pragma once + +#include +#include +#include +#include +#include // for abs() +#include +#include // for abs() +#include // std::reference_wrapper +#include +#include +#include // std::numeric_limits +#include +#include +#include +#include + +/** Library version: 0xMmP (M=Major,m=minor,P=patch) */ +#define NANOFLANN_VERSION 0x171 + +// Avoid conflicting declaration of min/max macros in Windows headers +#if !defined(NOMINMAX) && \ + (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64)) +#define NOMINMAX +#ifdef max +#undef max +#undef min +#endif +#endif +// Avoid conflicts with X11 headers +#ifdef None +#undef None +#endif + +namespace nanoflann +{ +/** @addtogroup nanoflann_grp nanoflann C++ library for KD-trees + * @{ */ + +/** the PI constant (required to avoid MSVC missing symbols) */ +template +T pi_const() +{ + return static_cast(3.14159265358979323846); +} + +/** + * Traits if object is resizable and assignable (typically has a resize | assign + * method) + */ +template +struct has_resize : std::false_type +{ +}; + +template +struct has_resize().resize(1), 0)> + : std::true_type +{ +}; + +template +struct has_assign : std::false_type +{ +}; + +template +struct has_assign().assign(1, 0), 0)> + : std::true_type +{ +}; + +/** + * Free function to resize a resizable object + */ +template +inline typename std::enable_if::value, void>::type resize( + Container& c, const size_t nElements) +{ + c.resize(nElements); +} + +/** + * Free function that has no effects on non resizable containers (e.g. + * std::array) It raises an exception if the expected size does not match + */ +template +inline typename std::enable_if::value, void>::type + resize(Container& c, const size_t nElements) +{ + if (nElements != c.size()) + throw std::logic_error("Try to change the size of a std::array."); +} + +/** + * Free function to assign to a container + */ +template +inline typename std::enable_if::value, void>::type assign( + Container& c, const size_t nElements, const T& value) +{ + c.assign(nElements, value); +} + +/** + * Free function to assign to a std::array + */ +template +inline typename std::enable_if::value, void>::type + assign(Container& c, const size_t nElements, const T& value) +{ + for (size_t i = 0; i < nElements; i++) c[i] = value; +} + +/** operator "<" for std::sort() */ +struct IndexDist_Sorter +{ + /** PairType will be typically: ResultItem */ + template + bool operator()(const PairType& p1, const PairType& p2) const + { + return p1.second < p2.second; + } +}; + +/** + * Each result element in RadiusResultSet. Note that distances and indices + * are named `first` and `second` to keep backward-compatibility with the + * `std::pair<>` type used in the past. In contrast, this structure is ensured + * to be `std::is_standard_layout` so it can be used in wrappers to other + * languages. + * See: https://github.com/jlblancoc/nanoflann/issues/166 + */ +template +struct ResultItem +{ + ResultItem() = default; + ResultItem(const IndexType index, const DistanceType distance) + : first(index), second(distance) + { + } + + IndexType first; //!< Index of the sample in the dataset + DistanceType second; //!< Distance from sample to query point +}; + +/** @addtogroup result_sets_grp Result set classes + * @{ */ + +/** Result set for KNN searches (N-closest neighbors) */ +template < + typename _DistanceType, typename _IndexType = size_t, + typename _CountType = size_t> +class KNNResultSet +{ + public: + using DistanceType = _DistanceType; + using IndexType = _IndexType; + using CountType = _CountType; + + private: + IndexType* indices; + DistanceType* dists; + CountType capacity; + CountType count; + + public: + explicit KNNResultSet(CountType capacity_) + : indices(nullptr), dists(nullptr), capacity(capacity_), count(0) + { + } + + void init(IndexType* indices_, DistanceType* dists_) + { + indices = indices_; + dists = dists_; + count = 0; + } + + CountType size() const { return count; } + bool empty() const { return count == 0; } + bool full() const { return count == capacity; } + + /** + * Called during search to add an element matching the criteria. + * @return true if the search should be continued, false if the results are + * sufficient + */ + bool addPoint(DistanceType dist, IndexType index) + { + CountType i; + for (i = count; i > 0; --i) + { + /** If defined and two points have the same distance, the one with + * the lowest-index will be returned first. */ +#ifdef NANOFLANN_FIRST_MATCH + if ((dists[i - 1] > dist) || + ((dist == dists[i - 1]) && (indices[i - 1] > index))) + { +#else + if (dists[i - 1] > dist) + { +#endif + if (i < capacity) + { + dists[i] = dists[i - 1]; + indices[i] = indices[i - 1]; + } + } + else + break; + } + if (i < capacity) + { + dists[i] = dist; + indices[i] = index; + } + if (count < capacity) count++; + + // tell caller that the search shall continue + return true; + } + + //! Returns the worst distance among found solutions if the search result is + //! full, or the maximum possible distance, if not full yet. + DistanceType worstDist() const + { + return (count < capacity || !count) + ? std::numeric_limits::max() + : dists[count - 1]; + } + + void sort() + { + // already sorted + } +}; + +/** Result set for RKNN searches (N-closest neighbors with a maximum radius) */ +template < + typename _DistanceType, typename _IndexType = size_t, + typename _CountType = size_t> +class RKNNResultSet +{ + public: + using DistanceType = _DistanceType; + using IndexType = _IndexType; + using CountType = _CountType; + + private: + IndexType* indices; + DistanceType* dists; + CountType capacity; + CountType count; + DistanceType maximumSearchDistanceSquared; + + public: + explicit RKNNResultSet( + CountType capacity_, DistanceType maximumSearchDistanceSquared_) + : indices(nullptr), + dists(nullptr), + capacity(capacity_), + count(0), + maximumSearchDistanceSquared(maximumSearchDistanceSquared_) + { + } + + void init(IndexType* indices_, DistanceType* dists_) + { + indices = indices_; + dists = dists_; + count = 0; + if (capacity) dists[capacity - 1] = maximumSearchDistanceSquared; + } + + CountType size() const { return count; } + bool empty() const { return count == 0; } + bool full() const { return count == capacity; } + + /** + * Called during search to add an element matching the criteria. + * @return true if the search should be continued, false if the results are + * sufficient + */ + bool addPoint(DistanceType dist, IndexType index) + { + CountType i; + for (i = count; i > 0; --i) + { + /** If defined and two points have the same distance, the one with + * the lowest-index will be returned first. */ +#ifdef NANOFLANN_FIRST_MATCH + if ((dists[i - 1] > dist) || + ((dist == dists[i - 1]) && (indices[i - 1] > index))) + { +#else + if (dists[i - 1] > dist) + { +#endif + if (i < capacity) + { + dists[i] = dists[i - 1]; + indices[i] = indices[i - 1]; + } + } + else + break; + } + if (i < capacity) + { + dists[i] = dist; + indices[i] = index; + } + if (count < capacity) count++; + + // tell caller that the search shall continue + return true; + } + + //! Returns the worst distance among found solutions if the search result is + //! full, or the maximum possible distance, if not full yet. + DistanceType worstDist() const + { + return (count < capacity || !count) ? maximumSearchDistanceSquared + : dists[count - 1]; + } + + void sort() + { + // already sorted + } +}; + +/** + * A result-set class used when performing a radius based search. + */ +template +class RadiusResultSet +{ + public: + using DistanceType = _DistanceType; + using IndexType = _IndexType; + + public: + const DistanceType radius; + + std::vector>& m_indices_dists; + + explicit RadiusResultSet( + DistanceType radius_, + std::vector>& indices_dists) + : radius(radius_), m_indices_dists(indices_dists) + { + init(); + } + + void init() { clear(); } + void clear() { m_indices_dists.clear(); } + + size_t size() const { return m_indices_dists.size(); } + size_t empty() const { return m_indices_dists.empty(); } + + bool full() const { return true; } + + /** + * Called during search to add an element matching the criteria. + * @return true if the search should be continued, false if the results are + * sufficient + */ + bool addPoint(DistanceType dist, IndexType index) + { + if (dist < radius) m_indices_dists.emplace_back(index, dist); + return true; + } + + DistanceType worstDist() const { return radius; } + + /** + * Find the worst result (farthest neighbor) without copying or sorting + * Pre-conditions: size() > 0 + */ + ResultItem worst_item() const + { + if (m_indices_dists.empty()) + throw std::runtime_error( + "Cannot invoke RadiusResultSet::worst_item() on " + "an empty list of results."); + auto it = std::max_element( + m_indices_dists.begin(), m_indices_dists.end(), IndexDist_Sorter()); + return *it; + } + + void sort() + { + std::sort( + m_indices_dists.begin(), m_indices_dists.end(), IndexDist_Sorter()); + } +}; + +/** @} */ + +/** @addtogroup loadsave_grp Load/save auxiliary functions + * @{ */ +template +void save_value(std::ostream& stream, const T& value) +{ + stream.write(reinterpret_cast(&value), sizeof(T)); +} + +template +void save_value(std::ostream& stream, const std::vector& value) +{ + size_t size = value.size(); + stream.write(reinterpret_cast(&size), sizeof(size_t)); + stream.write(reinterpret_cast(value.data()), sizeof(T) * size); +} + +template +void load_value(std::istream& stream, T& value) +{ + stream.read(reinterpret_cast(&value), sizeof(T)); +} + +template +void load_value(std::istream& stream, std::vector& value) +{ + size_t size; + stream.read(reinterpret_cast(&size), sizeof(size_t)); + value.resize(size); + stream.read(reinterpret_cast(value.data()), sizeof(T) * size); +} +/** @} */ + +/** @addtogroup metric_grp Metric (distance) classes + * @{ */ + +struct Metric +{ +}; + +/** Manhattan distance functor (generic version, optimized for + * high-dimensionality data sets). Corresponding distance traits: + * nanoflann::metric_L1 + * + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DataSource Source of the data, i.e. where the vectors are stored + * \tparam _DistanceType Type of distance variables (must be signed) + * \tparam IndexType Type of the arguments with which the data can be + * accessed (e.g. float, double, int64_t, T*) + */ +template < + class T, class DataSource, typename _DistanceType = T, + typename IndexType = size_t> +struct L1_Adaptor +{ + using ElementType = T; + using DistanceType = _DistanceType; + + const DataSource& data_source; + + L1_Adaptor(const DataSource& _data_source) : data_source(_data_source) {} + + DistanceType evalMetric( + const T* a, const IndexType b_idx, size_t size, + DistanceType worst_dist = -1) const + { + DistanceType result = DistanceType(); + const T* last = a + size; + const T* lastgroup = last - 3; + size_t d = 0; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) + { + const DistanceType diff0 = + std::abs(a[0] - data_source.kdtree_get_pt(b_idx, d++)); + const DistanceType diff1 = + std::abs(a[1] - data_source.kdtree_get_pt(b_idx, d++)); + const DistanceType diff2 = + std::abs(a[2] - data_source.kdtree_get_pt(b_idx, d++)); + const DistanceType diff3 = + std::abs(a[3] - data_source.kdtree_get_pt(b_idx, d++)); + result += diff0 + diff1 + diff2 + diff3; + a += 4; + if ((worst_dist > 0) && (result > worst_dist)) { return result; } + } + /* Process last 0-3 components. Not needed for standard vector lengths. + */ + while (a < last) + { + result += std::abs(*a++ - data_source.kdtree_get_pt(b_idx, d++)); + } + return result; + } + + template + DistanceType accum_dist(const U a, const V b, const size_t) const + { + return std::abs(a - b); + } +}; + +/** **Squared** Euclidean distance functor (generic version, optimized for + * high-dimensionality data sets). Corresponding distance traits: + * nanoflann::metric_L2 + * + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DataSource Source of the data, i.e. where the vectors are stored + * \tparam _DistanceType Type of distance variables (must be signed) + * \tparam IndexType Type of the arguments with which the data can be + * accessed (e.g. float, double, int64_t, T*) + */ +template < + class T, class DataSource, typename _DistanceType = T, + typename IndexType = size_t> +struct L2_Adaptor +{ + using ElementType = T; + using DistanceType = _DistanceType; + + const DataSource& data_source; + + L2_Adaptor(const DataSource& _data_source) : data_source(_data_source) {} + + DistanceType evalMetric( + const T* a, const IndexType b_idx, size_t size, + DistanceType worst_dist = -1) const + { + DistanceType result = DistanceType(); + const T* last = a + size; + const T* lastgroup = last - 3; + size_t d = 0; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) + { + const DistanceType diff0 = + a[0] - data_source.kdtree_get_pt(b_idx, d++); + const DistanceType diff1 = + a[1] - data_source.kdtree_get_pt(b_idx, d++); + const DistanceType diff2 = + a[2] - data_source.kdtree_get_pt(b_idx, d++); + const DistanceType diff3 = + a[3] - data_source.kdtree_get_pt(b_idx, d++); + result += + diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; + a += 4; + if ((worst_dist > 0) && (result > worst_dist)) { return result; } + } + /* Process last 0-3 components. Not needed for standard vector lengths. + */ + while (a < last) + { + const DistanceType diff0 = + *a++ - data_source.kdtree_get_pt(b_idx, d++); + result += diff0 * diff0; + } + return result; + } + + template + DistanceType accum_dist(const U a, const V b, const size_t) const + { + return (a - b) * (a - b); + } +}; + +/** **Squared** Euclidean (L2) distance functor (suitable for low-dimensionality + * datasets, like 2D or 3D point clouds) Corresponding distance traits: + * nanoflann::metric_L2_Simple + * + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DataSource Source of the data, i.e. where the vectors are stored + * \tparam _DistanceType Type of distance variables (must be signed) + * \tparam IndexType Type of the arguments with which the data can be + * accessed (e.g. float, double, int64_t, T*) + */ +template < + class T, class DataSource, typename _DistanceType = T, + typename IndexType = size_t> +struct L2_Simple_Adaptor +{ + using ElementType = T; + using DistanceType = _DistanceType; + + const DataSource& data_source; + + L2_Simple_Adaptor(const DataSource& _data_source) + : data_source(_data_source) + { + } + + DistanceType evalMetric( + const T* a, const IndexType b_idx, size_t size) const + { + DistanceType result = DistanceType(); + for (size_t i = 0; i < size; ++i) + { + const DistanceType diff = + a[i] - data_source.kdtree_get_pt(b_idx, i); + result += diff * diff; + } + return result; + } + + template + DistanceType accum_dist(const U a, const V b, const size_t) const + { + return (a - b) * (a - b); + } +}; + +/** SO2 distance functor + * Corresponding distance traits: nanoflann::metric_SO2 + * + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DataSource Source of the data, i.e. where the vectors are stored + * \tparam _DistanceType Type of distance variables (must be signed) (e.g. + * float, double) orientation is constrained to be in [-pi, pi] + * \tparam IndexType Type of the arguments with which the data can be + * accessed (e.g. float, double, int64_t, T*) + */ +template < + class T, class DataSource, typename _DistanceType = T, + typename IndexType = size_t> +struct SO2_Adaptor +{ + using ElementType = T; + using DistanceType = _DistanceType; + + const DataSource& data_source; + + SO2_Adaptor(const DataSource& _data_source) : data_source(_data_source) {} + + DistanceType evalMetric( + const T* a, const IndexType b_idx, size_t size) const + { + return accum_dist( + a[size - 1], data_source.kdtree_get_pt(b_idx, size - 1), size - 1); + } + + /** Note: this assumes that input angles are already in the range [-pi,pi] + */ + template + DistanceType accum_dist(const U a, const V b, const size_t) const + { + DistanceType result = DistanceType(); + DistanceType PI = pi_const(); + result = b - a; + if (result > PI) + result -= 2 * PI; + else if (result < -PI) + result += 2 * PI; + return result; + } +}; + +/** SO3 distance functor (Uses L2_Simple) + * Corresponding distance traits: nanoflann::metric_SO3 + * + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DataSource Source of the data, i.e. where the vectors are stored + * \tparam _DistanceType Type of distance variables (must be signed) (e.g. + * float, double) + * \tparam IndexType Type of the arguments with which the data can be + * accessed (e.g. float, double, int64_t, T*) + */ +template < + class T, class DataSource, typename _DistanceType = T, + typename IndexType = size_t> +struct SO3_Adaptor +{ + using ElementType = T; + using DistanceType = _DistanceType; + + L2_Simple_Adaptor + distance_L2_Simple; + + SO3_Adaptor(const DataSource& _data_source) + : distance_L2_Simple(_data_source) + { + } + + DistanceType evalMetric( + const T* a, const IndexType b_idx, size_t size) const + { + return distance_L2_Simple.evalMetric(a, b_idx, size); + } + + template + DistanceType accum_dist(const U a, const V b, const size_t idx) const + { + return distance_L2_Simple.accum_dist(a, b, idx); + } +}; + +/** Metaprogramming helper traits class for the L1 (Manhattan) metric */ +struct metric_L1 : public Metric +{ + template + struct traits + { + using distance_t = L1_Adaptor; + }; +}; +/** Metaprogramming helper traits class for the L2 (Euclidean) **squared** + * distance metric */ +struct metric_L2 : public Metric +{ + template + struct traits + { + using distance_t = L2_Adaptor; + }; +}; +/** Metaprogramming helper traits class for the L2_simple (Euclidean) + * **squared** distance metric */ +struct metric_L2_Simple : public Metric +{ + template + struct traits + { + using distance_t = L2_Simple_Adaptor; + }; +}; +/** Metaprogramming helper traits class for the SO3_InnerProdQuat metric */ +struct metric_SO2 : public Metric +{ + template + struct traits + { + using distance_t = SO2_Adaptor; + }; +}; +/** Metaprogramming helper traits class for the SO3_InnerProdQuat metric */ +struct metric_SO3 : public Metric +{ + template + struct traits + { + using distance_t = SO3_Adaptor; + }; +}; + +/** @} */ + +/** @addtogroup param_grp Parameter structs + * @{ */ + +enum class KDTreeSingleIndexAdaptorFlags +{ + None = 0, + SkipInitialBuildIndex = 1 +}; + +inline std::underlying_type::type operator&( + KDTreeSingleIndexAdaptorFlags lhs, KDTreeSingleIndexAdaptorFlags rhs) +{ + using underlying = + typename std::underlying_type::type; + return static_cast(lhs) & static_cast(rhs); +} + +/** Parameters (see README.md) */ +struct KDTreeSingleIndexAdaptorParams +{ + KDTreeSingleIndexAdaptorParams( + size_t _leaf_max_size = 10, + KDTreeSingleIndexAdaptorFlags _flags = + KDTreeSingleIndexAdaptorFlags::None, + unsigned int _n_thread_build = 1) + : leaf_max_size(_leaf_max_size), + flags(_flags), + n_thread_build(_n_thread_build) + { + } + + size_t leaf_max_size; + KDTreeSingleIndexAdaptorFlags flags; + unsigned int n_thread_build; +}; + +/** Search options for KDTreeSingleIndexAdaptor::findNeighbors() */ +struct SearchParameters +{ + SearchParameters(float eps_ = 0, bool sorted_ = true) + : eps(eps_), sorted(sorted_) + { + } + + float eps; //!< search for eps-approximate neighbours (default: 0) + bool sorted; //!< only for radius search, require neighbours sorted by + //!< distance (default: true) +}; +/** @} */ + +/** @addtogroup memalloc_grp Memory allocation + * @{ */ + +/** + * Pooled storage allocator + * + * The following routines allow for the efficient allocation of storage in + * small chunks from a specified pool. Rather than allowing each structure + * to be freed individually, an entire pool of storage is freed at once. + * This method has two advantages over just using malloc() and free(). First, + * it is far more efficient for allocating small objects, as there is + * no overhead for remembering all the information needed to free each + * object or consolidating fragmented memory. Second, the decision about + * how long to keep an object is made at the time of allocation, and there + * is no need to track down all the objects to free them. + * + */ +class PooledAllocator +{ + static constexpr size_t WORDSIZE = 16; // WORDSIZE must >= 8 + static constexpr size_t BLOCKSIZE = 8192; + + /* We maintain memory alignment to word boundaries by requiring that all + allocations be in multiples of the machine wordsize. */ + /* Size of machine word in bytes. Must be power of 2. */ + /* Minimum number of bytes requested at a time from the system. Must be + * multiple of WORDSIZE. */ + + using Size = size_t; + + Size remaining_ = 0; //!< Number of bytes left in current block of storage + void* base_ = nullptr; //!< Pointer to base of current block of storage + void* loc_ = nullptr; //!< Current location in block to next allocate + + void internal_init() + { + remaining_ = 0; + base_ = nullptr; + usedMemory = 0; + wastedMemory = 0; + } + + public: + Size usedMemory = 0; + Size wastedMemory = 0; + + /** + Default constructor. Initializes a new pool. + */ + PooledAllocator() { internal_init(); } + + /** + * Destructor. Frees all the memory allocated in this pool. + */ + ~PooledAllocator() { free_all(); } + + /** Frees all allocated memory chunks */ + void free_all() + { + while (base_ != nullptr) + { + // Get pointer to prev block + void* prev = *(static_cast(base_)); + ::free(base_); + base_ = prev; + } + internal_init(); + } + + /** + * Returns a pointer to a piece of new memory of the given size in bytes + * allocated from the pool. + */ + void* malloc(const size_t req_size) + { + /* Round size up to a multiple of wordsize. The following expression + only works for WORDSIZE that is a power of 2, by masking last bits + of incremented size to zero. + */ + const Size size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); + + /* Check whether a new block must be allocated. Note that the first + word of a block is reserved for a pointer to the previous block. + */ + if (size > remaining_) + { + wastedMemory += remaining_; + + /* Allocate new storage. */ + const Size blocksize = + size > BLOCKSIZE ? size + WORDSIZE : BLOCKSIZE + WORDSIZE; + + // use the standard C malloc to allocate memory + void* m = ::malloc(blocksize); + if (!m) + { + throw std::bad_alloc(); + } + + /* Fill first word of new block with pointer to previous block. */ + static_cast(m)[0] = base_; + base_ = m; + + remaining_ = blocksize - WORDSIZE; + loc_ = static_cast(m) + WORDSIZE; + } + void* rloc = loc_; + loc_ = static_cast(loc_) + size; + remaining_ -= size; + + usedMemory += size; + + return rloc; + } + + /** + * Allocates (using this pool) a generic type T. + * + * Params: + * count = number of instances to allocate. + * Returns: pointer (of type T*) to memory buffer + */ + template + T* allocate(const size_t count = 1) + { + T* mem = static_cast(this->malloc(sizeof(T) * count)); + return mem; + } +}; +/** @} */ + +/** @addtogroup nanoflann_metaprog_grp Auxiliary metaprogramming stuff + * @{ */ + +/** Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors + * when DIM=-1. Fixed size version for a generic DIM: + */ +template +struct array_or_vector +{ + using type = std::array; +}; +/** Dynamic size version */ +template +struct array_or_vector<-1, T> +{ + using type = std::vector; +}; + +/** @} */ + +/** kd-tree base-class + * + * Contains the member functions common to the classes KDTreeSingleIndexAdaptor + * and KDTreeSingleIndexDynamicAdaptor_. + * + * \tparam Derived The name of the class which inherits this class. + * \tparam DatasetAdaptor The user-provided adaptor, which must be ensured to + * have a lifetime equal or longer than the instance of this class. + * \tparam Distance The distance metric to use, these are all classes derived + * from nanoflann::Metric + * \tparam DIM Dimensionality of data points (e.g. 3 for 3D points) + * \tparam IndexType Type of the arguments with which the data can be + * accessed (e.g. float, double, int64_t, T*) + */ +template < + class Derived, typename Distance, class DatasetAdaptor, int32_t DIM = -1, + typename index_t = uint32_t> +class KDTreeBaseClass +{ + public: + /** Frees the previously-built index. Automatically called within + * buildIndex(). */ + void freeIndex(Derived& obj) + { + obj.pool_.free_all(); + obj.root_node_ = nullptr; + obj.size_at_index_build_ = 0; + } + + using ElementType = typename Distance::ElementType; + using DistanceType = typename Distance::DistanceType; + using IndexType = index_t; + + /** + * Array of indices to vectors in the dataset_. + */ + std::vector vAcc_; + + using Offset = typename decltype(vAcc_)::size_type; + using Size = typename decltype(vAcc_)::size_type; + using Dimension = int32_t; + + /*--------------------------- + * Internal Data Structures + * --------------------------*/ + struct Node + { + /** Union used because a node can be either a LEAF node or a non-leaf + * node, so both data fields are never used simultaneously */ + union + { + struct leaf + { + Offset left, right; //!< Indices of points in leaf node + } lr; + struct nonleaf + { + Dimension divfeat; //!< Dimension used for subdivision. + /// The values used for subdivision. + DistanceType divlow, divhigh; + } sub; + } node_type; + + /** Child nodes (both=nullptr mean its a leaf node) */ + Node *child1 = nullptr, *child2 = nullptr; + }; + + using NodePtr = Node*; + using NodeConstPtr = const Node*; + + struct Interval + { + ElementType low, high; + }; + + NodePtr root_node_ = nullptr; + + Size leaf_max_size_ = 0; + + /// Number of thread for concurrent tree build + Size n_thread_build_ = 1; + /// Number of current points in the dataset + Size size_ = 0; + /// Number of points in the dataset when the index was built + Size size_at_index_build_ = 0; + Dimension dim_ = 0; //!< Dimensionality of each data point + + /** Define "BoundingBox" as a fixed-size or variable-size container + * depending on "DIM" */ + using BoundingBox = typename array_or_vector::type; + + /** Define "distance_vector_t" as a fixed-size or variable-size container + * depending on "DIM" */ + using distance_vector_t = typename array_or_vector::type; + + /** The KD-tree used to find neighbours */ + BoundingBox root_bbox_; + + /** + * Pooled memory allocator. + * + * Using a pooled memory allocator is more efficient + * than allocating memory directly when there is a large + * number small of memory allocations. + */ + PooledAllocator pool_; + + /** Returns number of points in dataset */ + Size size(const Derived& obj) const { return obj.size_; } + + /** Returns the length of each point in the dataset */ + Size veclen(const Derived& obj) const { return DIM > 0 ? DIM : obj.dim; } + + /// Helper accessor to the dataset points: + ElementType dataset_get( + const Derived& obj, IndexType element, Dimension component) const + { + return obj.dataset_.kdtree_get_pt(element, component); + } + + /** + * Computes the index memory usage + * Returns: memory used by the index + */ + Size usedMemory(const Derived& obj) const + { + return obj.pool_.usedMemory + obj.pool_.wastedMemory + + obj.dataset_.kdtree_get_point_count() * + sizeof(IndexType); // pool memory and vind array memory + } + + /** + * Compute the minimum and maximum element values in the specified dimension + */ + void computeMinMax( + const Derived& obj, Offset ind, Size count, Dimension element, + ElementType& min_elem, ElementType& max_elem) const + { + min_elem = dataset_get(obj, vAcc_[ind], element); + max_elem = min_elem; + for (Offset i = 1; i < count; ++i) + { + ElementType val = dataset_get(obj, vAcc_[ind + i], element); + if (val < min_elem) min_elem = val; + if (val > max_elem) max_elem = val; + } + } + + /** + * Create a tree node that subdivides the list of vecs from vind[first] + * to vind[last]. The routine is called recursively on each sublist. + * + * @param left index of the first vector + * @param right index of the last vector + * @param bbox bounding box used as input for splitting and output for parent node + */ + NodePtr divideTree( + Derived& obj, const Offset left, const Offset right, BoundingBox& bbox) + { + assert(left < obj.dataset_.kdtree_get_point_count()); + + NodePtr node = obj.pool_.template allocate(); // allocate memory + const auto dims = (DIM > 0 ? DIM : obj.dim_); + + /* If too few exemplars remain, then make this a leaf node. */ + if ((right - left) <= static_cast(obj.leaf_max_size_)) + { + node->child1 = node->child2 = nullptr; /* Mark as leaf node. */ + node->node_type.lr.left = left; + node->node_type.lr.right = right; + + // compute bounding-box of leaf points + for (Dimension i = 0; i < dims; ++i) + { + bbox[i].low = dataset_get(obj, obj.vAcc_[left], i); + bbox[i].high = dataset_get(obj, obj.vAcc_[left], i); + } + for (Offset k = left + 1; k < right; ++k) + { + for (Dimension i = 0; i < dims; ++i) + { + const auto val = dataset_get(obj, obj.vAcc_[k], i); + if (bbox[i].low > val) bbox[i].low = val; + if (bbox[i].high < val) bbox[i].high = val; + } + } + } + else + { + /* Determine the index, dimension and value for split plane */ + Offset idx; + Dimension cutfeat; + DistanceType cutval; + middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox); + + node->node_type.sub.divfeat = cutfeat; + + /* Recurse on left */ + BoundingBox left_bbox(bbox); + left_bbox[cutfeat].high = cutval; + node->child1 = this->divideTree(obj, left, left + idx, left_bbox); + + /* Recurse on right */ + BoundingBox right_bbox(bbox); + right_bbox[cutfeat].low = cutval; + node->child2 = this->divideTree(obj, left + idx, right, right_bbox); + + node->node_type.sub.divlow = left_bbox[cutfeat].high; + node->node_type.sub.divhigh = right_bbox[cutfeat].low; + + for (Dimension i = 0; i < dims; ++i) + { + bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low); + bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high); + } + } + + return node; + } + + /** + * Create a tree node that subdivides the list of vecs from vind[first] to + * vind[last] concurrently. The routine is called recursively on each + * sublist. + * + * @param left index of the first vector + * @param right index of the last vector + * @param bbox bounding box used as input for splitting and output for parent node + * @param thread_count count of std::async threads + * @param mutex mutex for mempool allocation + */ + NodePtr divideTreeConcurrent( + Derived& obj, const Offset left, const Offset right, BoundingBox& bbox, + std::atomic& thread_count, std::mutex& mutex) + { + std::unique_lock lock(mutex); + NodePtr node = obj.pool_.template allocate(); // allocate memory + lock.unlock(); + + const auto dims = (DIM > 0 ? DIM : obj.dim_); + + /* If too few exemplars remain, then make this a leaf node. */ + if ((right - left) <= static_cast(obj.leaf_max_size_)) + { + node->child1 = node->child2 = nullptr; /* Mark as leaf node. */ + node->node_type.lr.left = left; + node->node_type.lr.right = right; + + // compute bounding-box of leaf points + for (Dimension i = 0; i < dims; ++i) + { + bbox[i].low = dataset_get(obj, obj.vAcc_[left], i); + bbox[i].high = dataset_get(obj, obj.vAcc_[left], i); + } + for (Offset k = left + 1; k < right; ++k) + { + for (Dimension i = 0; i < dims; ++i) + { + const auto val = dataset_get(obj, obj.vAcc_[k], i); + if (bbox[i].low > val) bbox[i].low = val; + if (bbox[i].high < val) bbox[i].high = val; + } + } + } + else + { + /* Determine the index, dimension and value for split plane */ + Offset idx; + Dimension cutfeat; + DistanceType cutval; + middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox); + + node->node_type.sub.divfeat = cutfeat; + + std::future right_future; + + /* Recurse on right concurrently, if possible */ + + BoundingBox right_bbox(bbox); + right_bbox[cutfeat].low = cutval; + if (++thread_count < n_thread_build_) + { + /* Concurrent thread for right recursion */ + + right_future = std::async( + std::launch::async, &KDTreeBaseClass::divideTreeConcurrent, + this, std::ref(obj), left + idx, right, + std::ref(right_bbox), std::ref(thread_count), + std::ref(mutex)); + } + else { --thread_count; } + + /* Recurse on left in this thread */ + + BoundingBox left_bbox(bbox); + left_bbox[cutfeat].high = cutval; + node->child1 = this->divideTreeConcurrent( + obj, left, left + idx, left_bbox, thread_count, mutex); + + if (right_future.valid()) + { + /* Block and wait for concurrent right from above */ + + node->child2 = right_future.get(); + --thread_count; + } + else + { + /* Otherwise, recurse on right in this thread */ + + node->child2 = this->divideTreeConcurrent( + obj, left + idx, right, right_bbox, thread_count, mutex); + } + + node->node_type.sub.divlow = left_bbox[cutfeat].high; + node->node_type.sub.divhigh = right_bbox[cutfeat].low; + + for (Dimension i = 0; i < dims; ++i) + { + bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low); + bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high); + } + } + + return node; + } + + void middleSplit_( + const Derived& obj, const Offset ind, const Size count, Offset& index, + Dimension& cutfeat, DistanceType& cutval, const BoundingBox& bbox) + { + const auto dims = (DIM > 0 ? DIM : obj.dim_); + const auto EPS = static_cast(0.00001); + ElementType max_span = bbox[0].high - bbox[0].low; + for (Dimension i = 1; i < dims; ++i) + { + ElementType span = bbox[i].high - bbox[i].low; + if (span > max_span) { max_span = span; } + } + ElementType max_spread = -1; + cutfeat = 0; + ElementType min_elem = 0, max_elem = 0; + for (Dimension i = 0; i < dims; ++i) + { + ElementType span = bbox[i].high - bbox[i].low; + if (span >= (1 - EPS) * max_span) + { + ElementType min_elem_, max_elem_; + computeMinMax(obj, ind, count, i, min_elem_, max_elem_); + ElementType spread = max_elem_ - min_elem_; + if (spread > max_spread) + { + cutfeat = i; + max_spread = spread; + min_elem = min_elem_; + max_elem = max_elem_; + } + } + } + // split in the middle + DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2; + + if (split_val < min_elem) + cutval = min_elem; + else if (split_val > max_elem) + cutval = max_elem; + else + cutval = split_val; + + Offset lim1, lim2; + planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2); + + if (lim1 > count / 2) + index = lim1; + else if (lim2 < count / 2) + index = lim2; + else + index = count / 2; + } + + /** + * Subdivide the list of points by a plane perpendicular on the axis + * corresponding to the 'cutfeat' dimension at 'cutval' position. + * + * On return: + * dataset[ind[0..lim1-1]][cutfeat] < cutval + * dataset[ind[lim1..lim2-1]][cutfeat] == cutval + * dataset[ind[lim2..count]][cutfeat] > cutval + */ + void planeSplit( + const Derived& obj, const Offset ind, const Size count, + const Dimension cutfeat, const DistanceType& cutval, Offset& lim1, + Offset& lim2) + { + /* First pass. + * Determine lim1 with all values less than cutval to the left. + */ + Offset left = 0; + Offset right = count - 1; + for (;;) + { + while (left <= right && + dataset_get(obj, vAcc_[ind + left], cutfeat) < cutval) + ++left; + while (right && left <= right && + dataset_get(obj, vAcc_[ind + right], cutfeat) >= cutval) + --right; + if (left > right || !right) + break; // "!right" was added to support unsigned Index types + std::swap(vAcc_[ind + left], vAcc_[ind + right]); + ++left; + --right; + } + /* Second pass + * Determine lim2 with all values greater than cutval to the right + * The middle is used for balancing the tree + */ + lim1 = left; + right = count - 1; + for (;;) + { + while (left <= right && + dataset_get(obj, vAcc_[ind + left], cutfeat) <= cutval) + ++left; + while (right && left <= right && + dataset_get(obj, vAcc_[ind + right], cutfeat) > cutval) + --right; + if (left > right || !right) + break; // "!right" was added to support unsigned Index types + std::swap(vAcc_[ind + left], vAcc_[ind + right]); + ++left; + --right; + } + lim2 = left; + } + + DistanceType computeInitialDistances( + const Derived& obj, const ElementType* vec, + distance_vector_t& dists) const + { + assert(vec); + DistanceType dist = DistanceType(); + + for (Dimension i = 0; i < (DIM > 0 ? DIM : obj.dim_); ++i) + { + if (vec[i] < obj.root_bbox_[i].low) + { + dists[i] = + obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].low, i); + dist += dists[i]; + } + if (vec[i] > obj.root_bbox_[i].high) + { + dists[i] = + obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].high, i); + dist += dists[i]; + } + } + return dist; + } + + static void save_tree( + const Derived& obj, std::ostream& stream, const NodeConstPtr tree) + { + save_value(stream, *tree); + if (tree->child1 != nullptr) { save_tree(obj, stream, tree->child1); } + if (tree->child2 != nullptr) { save_tree(obj, stream, tree->child2); } + } + + static void load_tree(Derived& obj, std::istream& stream, NodePtr& tree) + { + tree = obj.pool_.template allocate(); + load_value(stream, *tree); + if (tree->child1 != nullptr) { load_tree(obj, stream, tree->child1); } + if (tree->child2 != nullptr) { load_tree(obj, stream, tree->child2); } + } + + /** Stores the index in a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so + * when loading the index object it must be constructed associated to the + * same source of data points used while building it. See the example: + * examples/saveload_example.cpp \sa loadIndex */ + void saveIndex(const Derived& obj, std::ostream& stream) const + { + save_value(stream, obj.size_); + save_value(stream, obj.dim_); + save_value(stream, obj.root_bbox_); + save_value(stream, obj.leaf_max_size_); + save_value(stream, obj.vAcc_); + if (obj.root_node_) save_tree(obj, stream, obj.root_node_); + } + + /** Loads a previous index from a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so + * the index object must be constructed associated to the same source of + * data points used while building the index. See the example: + * examples/saveload_example.cpp \sa loadIndex */ + void loadIndex(Derived& obj, std::istream& stream) + { + load_value(stream, obj.size_); + load_value(stream, obj.dim_); + load_value(stream, obj.root_bbox_); + load_value(stream, obj.leaf_max_size_); + load_value(stream, obj.vAcc_); + load_tree(obj, stream, obj.root_node_); + } +}; + +/** @addtogroup kdtrees_grp KD-tree classes and adaptors + * @{ */ + +/** kd-tree static index + * + * Contains the k-d trees and other information for indexing a set of points + * for nearest-neighbor matching. + * + * The class "DatasetAdaptor" must provide the following interface (can be + * non-virtual, inlined methods): + * + * \code + * // Must return the number of data poins + * size_t kdtree_get_point_count() const { ... } + * + * + * // Must return the dim'th component of the idx'th point in the class: + * T kdtree_get_pt(const size_t idx, const size_t dim) const { ... } + * + * // Optional bounding-box computation: return false to default to a standard + * bbox computation loop. + * // Return true if the BBOX was already computed by the class and returned + * in "bb" so it can be avoided to redo it again. + * // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 + * for point clouds) template bool kdtree_get_bbox(BBOX &bb) const + * { + * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits + * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits + * ... + * return true; + * } + * + * \endcode + * + * \tparam DatasetAdaptor The user-provided adaptor, which must be ensured to + * have a lifetime equal or longer than the instance of this class. + * \tparam Distance The distance metric to use: nanoflann::metric_L1, + * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. \tparam DIM + * Dimensionality of data points (e.g. 3 for 3D points) \tparam IndexType Will + * be typically size_t or int + */ +template < + typename Distance, class DatasetAdaptor, int32_t DIM = -1, + typename index_t = uint32_t> +class KDTreeSingleIndexAdaptor + : public KDTreeBaseClass< + KDTreeSingleIndexAdaptor, + Distance, DatasetAdaptor, DIM, index_t> +{ + public: + /** Deleted copy constructor*/ + explicit KDTreeSingleIndexAdaptor( + const KDTreeSingleIndexAdaptor< + Distance, DatasetAdaptor, DIM, index_t>&) = delete; + + /** The data source used by this index */ + const DatasetAdaptor& dataset_; + + const KDTreeSingleIndexAdaptorParams indexParams; + + Distance distance_; + + using Base = typename nanoflann::KDTreeBaseClass< + nanoflann::KDTreeSingleIndexAdaptor< + Distance, DatasetAdaptor, DIM, index_t>, + Distance, DatasetAdaptor, DIM, index_t>; + + using Offset = typename Base::Offset; + using Size = typename Base::Size; + using Dimension = typename Base::Dimension; + + using ElementType = typename Base::ElementType; + using DistanceType = typename Base::DistanceType; + using IndexType = typename Base::IndexType; + + using Node = typename Base::Node; + using NodePtr = Node*; + + using Interval = typename Base::Interval; + + /** Define "BoundingBox" as a fixed-size or variable-size container + * depending on "DIM" */ + using BoundingBox = typename Base::BoundingBox; + + /** Define "distance_vector_t" as a fixed-size or variable-size container + * depending on "DIM" */ + using distance_vector_t = typename Base::distance_vector_t; + + /** + * KDTree constructor + * + * Refer to docs in README.md or online in + * https://github.com/jlblancoc/nanoflann + * + * The KD-Tree point dimension (the length of each point in the datase, e.g. + * 3 for 3D points) is determined by means of: + * - The \a DIM template parameter if >0 (highest priority) + * - Otherwise, the \a dimensionality parameter of this constructor. + * + * @param inputData Dataset with the input features. Its lifetime must be + * equal or longer than that of the instance of this class. + * @param params Basically, the maximum leaf node size + * + * Note that there is a variable number of optional additional parameters + * which will be forwarded to the metric class constructor. Refer to example + * `examples/pointcloud_custom_metric.cpp` for a use case. + * + */ + template + explicit KDTreeSingleIndexAdaptor( + const Dimension dimensionality, const DatasetAdaptor& inputData, + const KDTreeSingleIndexAdaptorParams& params, Args&&... args) + : dataset_(inputData), + indexParams(params), + distance_(inputData, std::forward(args)...) + { + init(dimensionality, params); + } + + explicit KDTreeSingleIndexAdaptor( + const Dimension dimensionality, const DatasetAdaptor& inputData, + const KDTreeSingleIndexAdaptorParams& params = {}) + : dataset_(inputData), indexParams(params), distance_(inputData) + { + init(dimensionality, params); + } + + private: + void init( + const Dimension dimensionality, + const KDTreeSingleIndexAdaptorParams& params) + { + Base::size_ = dataset_.kdtree_get_point_count(); + Base::size_at_index_build_ = Base::size_; + Base::dim_ = dimensionality; + if (DIM > 0) Base::dim_ = DIM; + Base::leaf_max_size_ = params.leaf_max_size; + if (params.n_thread_build > 0) + { + Base::n_thread_build_ = params.n_thread_build; + } + else + { + Base::n_thread_build_ = + std::max(std::thread::hardware_concurrency(), 1u); + } + + if (!(params.flags & + KDTreeSingleIndexAdaptorFlags::SkipInitialBuildIndex)) + { + // Build KD-tree: + buildIndex(); + } + } + + public: + /** + * Builds the index + */ + void buildIndex() + { + Base::size_ = dataset_.kdtree_get_point_count(); + Base::size_at_index_build_ = Base::size_; + init_vind(); + this->freeIndex(*this); + Base::size_at_index_build_ = Base::size_; + if (Base::size_ == 0) return; + computeBoundingBox(Base::root_bbox_); + // construct the tree + if (Base::n_thread_build_ == 1) + { + Base::root_node_ = + this->divideTree(*this, 0, Base::size_, Base::root_bbox_); + } + else + { +#ifndef NANOFLANN_NO_THREADS + std::atomic thread_count(0u); + std::mutex mutex; + Base::root_node_ = this->divideTreeConcurrent( + *this, 0, Base::size_, Base::root_bbox_, thread_count, mutex); +#else /* NANOFLANN_NO_THREADS */ + throw std::runtime_error("Multithreading is disabled"); +#endif /* NANOFLANN_NO_THREADS */ + } + } + + /** \name Query methods + * @{ */ + + /** + * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored + * inside the result object. + * + * Params: + * result = the result object in which the indices of the + * nearest-neighbors are stored vec = the vector for which to search the + * nearest neighbors + * + * \tparam RESULTSET Should be any ResultSet + * \return True if the requested neighbors could be found. + * \sa knnSearch, radiusSearch + * + * \note If L2 norms are used, all returned distances are actually squared + * distances. + */ + template + bool findNeighbors( + RESULTSET& result, const ElementType* vec, + const SearchParameters& searchParams = {}) const + { + assert(vec); + if (this->size(*this) == 0) return false; + if (!Base::root_node_) + throw std::runtime_error( + "[nanoflann] findNeighbors() called before building the " + "index."); + float epsError = 1 + searchParams.eps; + + // fixed or variable-sized container (depending on DIM) + distance_vector_t dists; + // Fill it with zeros. + auto zero = static_cast(0); + assign(dists, (DIM > 0 ? DIM : Base::dim_), zero); + DistanceType dist = this->computeInitialDistances(*this, vec, dists); + searchLevel(result, vec, Base::root_node_, dist, dists, epsError); + + if (searchParams.sorted) result.sort(); + + return result.full(); + } + + /** + * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. + * Their indices and distances are stored in the provided pointers to + * array/vector. + * + * \sa radiusSearch, findNeighbors + * \return Number `N` of valid points in the result set. + * + * \note If L2 norms are used, all returned distances are actually squared + * distances. + * + * \note Only the first `N` entries in `out_indices` and `out_distances` + * will be valid. Return is less than `num_closest` only if the + * number of elements in the tree is less than `num_closest`. + */ + Size knnSearch( + const ElementType* query_point, const Size num_closest, + IndexType* out_indices, DistanceType* out_distances) const + { + nanoflann::KNNResultSet resultSet(num_closest); + resultSet.init(out_indices, out_distances); + findNeighbors(resultSet, query_point); + return resultSet.size(); + } + + /** + * Find all the neighbors to \a query_point[0:dim-1] within a maximum + * radius. The output is given as a vector of pairs, of which the first + * element is a point index and the second the corresponding distance. + * Previous contents of \a IndicesDists are cleared. + * + * If searchParams.sorted==true, the output list is sorted by ascending + * distances. + * + * For a better performance, it is advisable to do a .reserve() on the + * vector if you have any wild guess about the number of expected matches. + * + * \sa knnSearch, findNeighbors, radiusSearchCustomCallback + * \return The number of points within the given radius (i.e. indices.size() + * or dists.size() ) + * + * \note If L2 norms are used, search radius and all returned distances + * are actually squared distances. + */ + Size radiusSearch( + const ElementType* query_point, const DistanceType& radius, + std::vector>& IndicesDists, + const SearchParameters& searchParams = {}) const + { + RadiusResultSet resultSet( + radius, IndicesDists); + const Size nFound = + radiusSearchCustomCallback(query_point, resultSet, searchParams); + return nFound; + } + + /** + * Just like radiusSearch() but with a custom callback class for each point + * found in the radius of the query. See the source of RadiusResultSet<> as + * a start point for your own classes. \sa radiusSearch + */ + template + Size radiusSearchCustomCallback( + const ElementType* query_point, SEARCH_CALLBACK& resultSet, + const SearchParameters& searchParams = {}) const + { + findNeighbors(resultSet, query_point, searchParams); + return resultSet.size(); + } + + /** + * Find the first N neighbors to \a query_point[0:dim-1] within a maximum + * radius. The output is given as a vector of pairs, of which the first + * element is a point index and the second the corresponding distance. + * Previous contents of \a IndicesDists are cleared. + * + * \sa radiusSearch, findNeighbors + * \return Number `N` of valid points in the result set. + * + * \note If L2 norms are used, all returned distances are actually squared + * distances. + * + * \note Only the first `N` entries in `out_indices` and `out_distances` + * will be valid. Return is less than `num_closest` only if the + * number of elements in the tree is less than `num_closest`. + */ + Size rknnSearch( + const ElementType* query_point, const Size num_closest, + IndexType* out_indices, DistanceType* out_distances, + const DistanceType& radius) const + { + nanoflann::RKNNResultSet resultSet( + num_closest, radius); + resultSet.init(out_indices, out_distances); + findNeighbors(resultSet, query_point); + return resultSet.size(); + } + + /** @} */ + + public: + /** Make sure the auxiliary list \a vind has the same size than the current + * dataset, and re-generate if size has changed. */ + void init_vind() + { + // Create a permutable array of indices to the input vectors. + Base::size_ = dataset_.kdtree_get_point_count(); + if (Base::vAcc_.size() != Base::size_) Base::vAcc_.resize(Base::size_); + for (IndexType i = 0; i < static_cast(Base::size_); i++) + Base::vAcc_[i] = i; + } + + void computeBoundingBox(BoundingBox& bbox) + { + const auto dims = (DIM > 0 ? DIM : Base::dim_); + resize(bbox, dims); + if (dataset_.kdtree_get_bbox(bbox)) + { + // Done! It was implemented in derived class + } + else + { + const Size N = dataset_.kdtree_get_point_count(); + if (!N) + throw std::runtime_error( + "[nanoflann] computeBoundingBox() called but " + "no data points found."); + for (Dimension i = 0; i < dims; ++i) + { + bbox[i].low = bbox[i].high = + this->dataset_get(*this, Base::vAcc_[0], i); + } + for (Offset k = 1; k < N; ++k) + { + for (Dimension i = 0; i < dims; ++i) + { + const auto val = + this->dataset_get(*this, Base::vAcc_[k], i); + if (val < bbox[i].low) bbox[i].low = val; + if (val > bbox[i].high) bbox[i].high = val; + } + } + } + } + + /** + * Performs an exact search in the tree starting from a node. + * \tparam RESULTSET Should be any ResultSet + * \return true if the search should be continued, false if the results are + * sufficient + */ + template + bool searchLevel( + RESULTSET& result_set, const ElementType* vec, const NodePtr node, + DistanceType mindist, distance_vector_t& dists, + const float epsError) const + { + /* If this is a leaf node, then do check and return. */ + if ((node->child1 == nullptr) && (node->child2 == nullptr)) + { + DistanceType worst_dist = result_set.worstDist(); + for (Offset i = node->node_type.lr.left; + i < node->node_type.lr.right; ++i) + { + const IndexType accessor = Base::vAcc_[i]; // reorder... : i; + DistanceType dist = distance_.evalMetric( + vec, accessor, (DIM > 0 ? DIM : Base::dim_)); + if (dist < worst_dist) + { + if (!result_set.addPoint(dist, Base::vAcc_[i])) + { + // the resultset doesn't want to receive any more + // points, we're done searching! + return false; + } + } + } + return true; + } + + /* Which child branch should be taken first? */ + Dimension idx = node->node_type.sub.divfeat; + ElementType val = vec[idx]; + DistanceType diff1 = val - node->node_type.sub.divlow; + DistanceType diff2 = val - node->node_type.sub.divhigh; + + NodePtr bestChild; + NodePtr otherChild; + DistanceType cut_dist; + if ((diff1 + diff2) < 0) + { + bestChild = node->child1; + otherChild = node->child2; + cut_dist = + distance_.accum_dist(val, node->node_type.sub.divhigh, idx); + } + else + { + bestChild = node->child2; + otherChild = node->child1; + cut_dist = + distance_.accum_dist(val, node->node_type.sub.divlow, idx); + } + + /* Call recursively to search next level down. */ + if (!searchLevel(result_set, vec, bestChild, mindist, dists, epsError)) + { + // the resultset doesn't want to receive any more points, we're done + // searching! + return false; + } + + DistanceType dst = dists[idx]; + mindist = mindist + cut_dist - dst; + dists[idx] = cut_dist; + if (mindist * epsError <= result_set.worstDist()) + { + if (!searchLevel( + result_set, vec, otherChild, mindist, dists, epsError)) + { + // the resultset doesn't want to receive any more points, we're + // done searching! + return false; + } + } + dists[idx] = dst; + return true; + } + + public: + /** Stores the index in a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so + * when loading the index object it must be constructed associated to the + * same source of data points used while building it. See the example: + * examples/saveload_example.cpp \sa loadIndex */ + void saveIndex(std::ostream& stream) const + { + Base::saveIndex(*this, stream); + } + + /** Loads a previous index from a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so + * the index object must be constructed associated to the same source of + * data points used while building the index. See the example: + * examples/saveload_example.cpp \sa loadIndex */ + void loadIndex(std::istream& stream) { Base::loadIndex(*this, stream); } + +}; // class KDTree + +/** kd-tree dynamic index + * + * Contains the k-d trees and other information for indexing a set of points + * for nearest-neighbor matching. + * + * The class "DatasetAdaptor" must provide the following interface (can be + * non-virtual, inlined methods): + * + * \code + * // Must return the number of data poins + * size_t kdtree_get_point_count() const { ... } + * + * // Must return the dim'th component of the idx'th point in the class: + * T kdtree_get_pt(const size_t idx, const size_t dim) const { ... } + * + * // Optional bounding-box computation: return false to default to a standard + * bbox computation loop. + * // Return true if the BBOX was already computed by the class and returned + * in "bb" so it can be avoided to redo it again. + * // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 + * for point clouds) template bool kdtree_get_bbox(BBOX &bb) const + * { + * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits + * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits + * ... + * return true; + * } + * + * \endcode + * + * \tparam DatasetAdaptor The user-provided adaptor (see comments above). + * \tparam Distance The distance metric to use: nanoflann::metric_L1, + * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. + * \tparam DIM Dimensionality of data points (e.g. 3 for 3D points) + * \tparam IndexType Type of the arguments with which the data can be + * accessed (e.g. float, double, int64_t, T*) + */ +template < + typename Distance, class DatasetAdaptor, int32_t DIM = -1, + typename IndexType = uint32_t> +class KDTreeSingleIndexDynamicAdaptor_ + : public KDTreeBaseClass< + KDTreeSingleIndexDynamicAdaptor_< + Distance, DatasetAdaptor, DIM, IndexType>, + Distance, DatasetAdaptor, DIM, IndexType> +{ + public: + /** + * The dataset used by this index + */ + const DatasetAdaptor& dataset_; //!< The source of our data + + KDTreeSingleIndexAdaptorParams index_params_; + + std::vector& treeIndex_; + + Distance distance_; + + using Base = typename nanoflann::KDTreeBaseClass< + nanoflann::KDTreeSingleIndexDynamicAdaptor_< + Distance, DatasetAdaptor, DIM, IndexType>, + Distance, DatasetAdaptor, DIM, IndexType>; + + using ElementType = typename Base::ElementType; + using DistanceType = typename Base::DistanceType; + + using Offset = typename Base::Offset; + using Size = typename Base::Size; + using Dimension = typename Base::Dimension; + + using Node = typename Base::Node; + using NodePtr = Node*; + + using Interval = typename Base::Interval; + /** Define "BoundingBox" as a fixed-size or variable-size container + * depending on "DIM" */ + using BoundingBox = typename Base::BoundingBox; + + /** Define "distance_vector_t" as a fixed-size or variable-size container + * depending on "DIM" */ + using distance_vector_t = typename Base::distance_vector_t; + + /** + * KDTree constructor + * + * Refer to docs in README.md or online in + * https://github.com/jlblancoc/nanoflann + * + * The KD-Tree point dimension (the length of each point in the datase, e.g. + * 3 for 3D points) is determined by means of: + * - The \a DIM template parameter if >0 (highest priority) + * - Otherwise, the \a dimensionality parameter of this constructor. + * + * @param inputData Dataset with the input features. Its lifetime must be + * equal or longer than that of the instance of this class. + * @param params Basically, the maximum leaf node size + */ + KDTreeSingleIndexDynamicAdaptor_( + const Dimension dimensionality, const DatasetAdaptor& inputData, + std::vector& treeIndex, + const KDTreeSingleIndexAdaptorParams& params = + KDTreeSingleIndexAdaptorParams()) + : dataset_(inputData), + index_params_(params), + treeIndex_(treeIndex), + distance_(inputData) + { + Base::size_ = 0; + Base::size_at_index_build_ = 0; + for (auto& v : Base::root_bbox_) v = {}; + Base::dim_ = dimensionality; + if (DIM > 0) Base::dim_ = DIM; + Base::leaf_max_size_ = params.leaf_max_size; + if (params.n_thread_build > 0) + { + Base::n_thread_build_ = params.n_thread_build; + } + else + { + Base::n_thread_build_ = + std::max(std::thread::hardware_concurrency(), 1u); + } + } + + /** Explicitly default the copy constructor */ + KDTreeSingleIndexDynamicAdaptor_( + const KDTreeSingleIndexDynamicAdaptor_& rhs) = default; + + /** Assignment operator definiton */ + KDTreeSingleIndexDynamicAdaptor_ operator=( + const KDTreeSingleIndexDynamicAdaptor_& rhs) + { + KDTreeSingleIndexDynamicAdaptor_ tmp(rhs); + std::swap(Base::vAcc_, tmp.Base::vAcc_); + std::swap(Base::leaf_max_size_, tmp.Base::leaf_max_size_); + std::swap(index_params_, tmp.index_params_); + std::swap(treeIndex_, tmp.treeIndex_); + std::swap(Base::size_, tmp.Base::size_); + std::swap(Base::size_at_index_build_, tmp.Base::size_at_index_build_); + std::swap(Base::root_node_, tmp.Base::root_node_); + std::swap(Base::root_bbox_, tmp.Base::root_bbox_); + std::swap(Base::pool_, tmp.Base::pool_); + return *this; + } + + /** + * Builds the index + */ + void buildIndex() + { + Base::size_ = Base::vAcc_.size(); + this->freeIndex(*this); + Base::size_at_index_build_ = Base::size_; + if (Base::size_ == 0) return; + computeBoundingBox(Base::root_bbox_); + // construct the tree + if (Base::n_thread_build_ == 1) + { + Base::root_node_ = + this->divideTree(*this, 0, Base::size_, Base::root_bbox_); + } + else + { +#ifndef NANOFLANN_NO_THREADS + std::atomic thread_count(0u); + std::mutex mutex; + Base::root_node_ = this->divideTreeConcurrent( + *this, 0, Base::size_, Base::root_bbox_, thread_count, mutex); +#else /* NANOFLANN_NO_THREADS */ + throw std::runtime_error("Multithreading is disabled"); +#endif /* NANOFLANN_NO_THREADS */ + } + } + + /** \name Query methods + * @{ */ + + /** + * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored + * inside the result object. + * This is the core search function, all others are wrappers around this + * one. + * + * \param result The result object in which the indices of the + * nearest-neighbors are stored. + * \param vec The vector of the query point for which to search the + * nearest neighbors. + * \param searchParams Optional parameters for the search. + * + * \tparam RESULTSET Should be any ResultSet + * \return True if the requested neighbors could be found. + * + * \sa knnSearch(), radiusSearch(), radiusSearchCustomCallback() + * + * \note If L2 norms are used, all returned distances are actually squared + * distances. + */ + template + bool findNeighbors( + RESULTSET& result, const ElementType* vec, + const SearchParameters& searchParams = {}) const + { + assert(vec); + if (this->size(*this) == 0) return false; + if (!Base::root_node_) return false; + float epsError = 1 + searchParams.eps; + + // fixed or variable-sized container (depending on DIM) + distance_vector_t dists; + // Fill it with zeros. + assign( + dists, (DIM > 0 ? DIM : Base::dim_), + static_cast(0)); + DistanceType dist = this->computeInitialDistances(*this, vec, dists); + searchLevel(result, vec, Base::root_node_, dist, dists, epsError); + return result.full(); + } + + /** + * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. + * Their indices are stored inside the result object. \sa radiusSearch, + * findNeighbors + * \return Number `N` of valid points in + * the result set. + * + * \note If L2 norms are used, all returned distances are actually squared + * distances. + * + * \note Only the first `N` entries in `out_indices` and `out_distances` + * will be valid. Return may be less than `num_closest` only if the + * number of elements in the tree is less than `num_closest`. + */ + Size knnSearch( + const ElementType* query_point, const Size num_closest, + IndexType* out_indices, DistanceType* out_distances, + const SearchParameters& searchParams = {}) const + { + nanoflann::KNNResultSet resultSet(num_closest); + resultSet.init(out_indices, out_distances); + findNeighbors(resultSet, query_point, searchParams); + return resultSet.size(); + } + + /** + * Find all the neighbors to \a query_point[0:dim-1] within a maximum + * radius. The output is given as a vector of pairs, of which the first + * element is a point index and the second the corresponding distance. + * Previous contents of \a IndicesDists are cleared. + * + * If searchParams.sorted==true, the output list is sorted by ascending + * distances. + * + * For a better performance, it is advisable to do a .reserve() on the + * vector if you have any wild guess about the number of expected matches. + * + * \sa knnSearch, findNeighbors, radiusSearchCustomCallback + * \return The number of points within the given radius (i.e. indices.size() + * or dists.size() ) + * + * \note If L2 norms are used, search radius and all returned distances + * are actually squared distances. + */ + Size radiusSearch( + const ElementType* query_point, const DistanceType& radius, + std::vector>& IndicesDists, + const SearchParameters& searchParams = {}) const + { + RadiusResultSet resultSet( + radius, IndicesDists); + const size_t nFound = + radiusSearchCustomCallback(query_point, resultSet, searchParams); + return nFound; + } + + /** + * Just like radiusSearch() but with a custom callback class for each point + * found in the radius of the query. See the source of RadiusResultSet<> as + * a start point for your own classes. \sa radiusSearch + */ + template + Size radiusSearchCustomCallback( + const ElementType* query_point, SEARCH_CALLBACK& resultSet, + const SearchParameters& searchParams = {}) const + { + findNeighbors(resultSet, query_point, searchParams); + return resultSet.size(); + } + + /** @} */ + + public: + void computeBoundingBox(BoundingBox& bbox) + { + const auto dims = (DIM > 0 ? DIM : Base::dim_); + resize(bbox, dims); + + if (dataset_.kdtree_get_bbox(bbox)) + { + // Done! It was implemented in derived class + } + else + { + const Size N = Base::size_; + if (!N) + throw std::runtime_error( + "[nanoflann] computeBoundingBox() called but " + "no data points found."); + for (Dimension i = 0; i < dims; ++i) + { + bbox[i].low = bbox[i].high = + this->dataset_get(*this, Base::vAcc_[0], i); + } + for (Offset k = 1; k < N; ++k) + { + for (Dimension i = 0; i < dims; ++i) + { + const auto val = + this->dataset_get(*this, Base::vAcc_[k], i); + if (val < bbox[i].low) bbox[i].low = val; + if (val > bbox[i].high) bbox[i].high = val; + } + } + } + } + + /** + * Performs an exact search in the tree starting from a node. + * \tparam RESULTSET Should be any ResultSet + */ + template + void searchLevel( + RESULTSET& result_set, const ElementType* vec, const NodePtr node, + DistanceType mindist, distance_vector_t& dists, + const float epsError) const + { + /* If this is a leaf node, then do check and return. */ + if ((node->child1 == nullptr) && (node->child2 == nullptr)) + { + DistanceType worst_dist = result_set.worstDist(); + for (Offset i = node->node_type.lr.left; + i < node->node_type.lr.right; ++i) + { + const IndexType index = Base::vAcc_[i]; // reorder... : i; + if (treeIndex_[index] == -1) continue; + DistanceType dist = distance_.evalMetric( + vec, index, (DIM > 0 ? DIM : Base::dim_)); + if (dist < worst_dist) + { + if (!result_set.addPoint( + static_cast(dist), + static_cast( + Base::vAcc_[i]))) + { + // the resultset doesn't want to receive any more + // points, we're done searching! + return; // false; + } + } + } + return; + } + + /* Which child branch should be taken first? */ + Dimension idx = node->node_type.sub.divfeat; + ElementType val = vec[idx]; + DistanceType diff1 = val - node->node_type.sub.divlow; + DistanceType diff2 = val - node->node_type.sub.divhigh; + + NodePtr bestChild; + NodePtr otherChild; + DistanceType cut_dist; + if ((diff1 + diff2) < 0) + { + bestChild = node->child1; + otherChild = node->child2; + cut_dist = + distance_.accum_dist(val, node->node_type.sub.divhigh, idx); + } + else + { + bestChild = node->child2; + otherChild = node->child1; + cut_dist = + distance_.accum_dist(val, node->node_type.sub.divlow, idx); + } + + /* Call recursively to search next level down. */ + searchLevel(result_set, vec, bestChild, mindist, dists, epsError); + + DistanceType dst = dists[idx]; + mindist = mindist + cut_dist - dst; + dists[idx] = cut_dist; + if (mindist * epsError <= result_set.worstDist()) + { + searchLevel(result_set, vec, otherChild, mindist, dists, epsError); + } + dists[idx] = dst; + } + + public: + /** Stores the index in a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so + * when loading the index object it must be constructed associated to the + * same source of data points used while building it. See the example: + * examples/saveload_example.cpp \sa loadIndex */ + void saveIndex(std::ostream& stream) { saveIndex(*this, stream); } + + /** Loads a previous index from a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so + * the index object must be constructed associated to the same source of + * data points used while building the index. See the example: + * examples/saveload_example.cpp \sa loadIndex */ + void loadIndex(std::istream& stream) { loadIndex(*this, stream); } +}; + +/** kd-tree dynaimic index + * + * class to create multiple static index and merge their results to behave as + * single dynamic index as proposed in Logarithmic Approach. + * + * Example of usage: + * examples/dynamic_pointcloud_example.cpp + * + * \tparam DatasetAdaptor The user-provided adaptor (see comments above). + * \tparam Distance The distance metric to use: nanoflann::metric_L1, + * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. \tparam DIM + * Dimensionality of data points (e.g. 3 for 3D points) \tparam IndexType + * Will be typically size_t or int + */ +template < + typename Distance, class DatasetAdaptor, int32_t DIM = -1, + typename IndexType = uint32_t> +class KDTreeSingleIndexDynamicAdaptor +{ + public: + using ElementType = typename Distance::ElementType; + using DistanceType = typename Distance::DistanceType; + + using Offset = typename KDTreeSingleIndexDynamicAdaptor_< + Distance, DatasetAdaptor, DIM>::Offset; + using Size = typename KDTreeSingleIndexDynamicAdaptor_< + Distance, DatasetAdaptor, DIM>::Size; + using Dimension = typename KDTreeSingleIndexDynamicAdaptor_< + Distance, DatasetAdaptor, DIM>::Dimension; + + protected: + Size leaf_max_size_; + Size treeCount_; + Size pointCount_; + + /** + * The dataset used by this index + */ + const DatasetAdaptor& dataset_; //!< The source of our data + + /** treeIndex[idx] is the index of tree in which point at idx is stored. + * treeIndex[idx]=-1 means that point has been removed. */ + std::vector treeIndex_; + std::unordered_set removedPoints_; + + KDTreeSingleIndexAdaptorParams index_params_; + + Dimension dim_; //!< Dimensionality of each data point + + using index_container_t = KDTreeSingleIndexDynamicAdaptor_< + Distance, DatasetAdaptor, DIM, IndexType>; + std::vector index_; + + public: + /** Get a const ref to the internal list of indices; the number of indices + * is adapted dynamically as the dataset grows in size. */ + const std::vector& getAllIndices() const + { + return index_; + } + + private: + /** finds position of least significant unset bit */ + int First0Bit(IndexType num) + { + int pos = 0; + while (num & 1) + { + num = num >> 1; + pos++; + } + return pos; + } + + /** Creates multiple empty trees to handle dynamic support */ + void init() + { + using my_kd_tree_t = KDTreeSingleIndexDynamicAdaptor_< + Distance, DatasetAdaptor, DIM, IndexType>; + std::vector index( + treeCount_, + my_kd_tree_t(dim_ /*dim*/, dataset_, treeIndex_, index_params_)); + index_ = index; + } + + public: + Distance distance_; + + /** + * KDTree constructor + * + * Refer to docs in README.md or online in + * https://github.com/jlblancoc/nanoflann + * + * The KD-Tree point dimension (the length of each point in the datase, e.g. + * 3 for 3D points) is determined by means of: + * - The \a DIM template parameter if >0 (highest priority) + * - Otherwise, the \a dimensionality parameter of this constructor. + * + * @param inputData Dataset with the input features. Its lifetime must be + * equal or longer than that of the instance of this class. + * @param params Basically, the maximum leaf node size + */ + explicit KDTreeSingleIndexDynamicAdaptor( + const int dimensionality, const DatasetAdaptor& inputData, + const KDTreeSingleIndexAdaptorParams& params = + KDTreeSingleIndexAdaptorParams(), + const size_t maximumPointCount = 1000000000U) + : dataset_(inputData), index_params_(params), distance_(inputData) + { + treeCount_ = static_cast(std::log2(maximumPointCount)) + 1; + pointCount_ = 0U; + dim_ = dimensionality; + treeIndex_.clear(); + if (DIM > 0) dim_ = DIM; + leaf_max_size_ = params.leaf_max_size; + init(); + const size_t num_initial_points = dataset_.kdtree_get_point_count(); + if (num_initial_points > 0) { addPoints(0, num_initial_points - 1); } + } + + /** Deleted copy constructor*/ + explicit KDTreeSingleIndexDynamicAdaptor( + const KDTreeSingleIndexDynamicAdaptor< + Distance, DatasetAdaptor, DIM, IndexType>&) = delete; + + /** Add points to the set, Inserts all points from [start, end] */ + void addPoints(IndexType start, IndexType end) + { + const Size count = end - start + 1; + int maxIndex = 0; + treeIndex_.resize(treeIndex_.size() + count); + for (IndexType idx = start; idx <= end; idx++) + { + const int pos = First0Bit(pointCount_); + maxIndex = std::max(pos, maxIndex); + treeIndex_[pointCount_] = pos; + + const auto it = removedPoints_.find(idx); + if (it != removedPoints_.end()) + { + removedPoints_.erase(it); + treeIndex_[idx] = pos; + } + + for (int i = 0; i < pos; i++) + { + for (int j = 0; j < static_cast(index_[i].vAcc_.size()); + j++) + { + index_[pos].vAcc_.push_back(index_[i].vAcc_[j]); + if (treeIndex_[index_[i].vAcc_[j]] != -1) + treeIndex_[index_[i].vAcc_[j]] = pos; + } + index_[i].vAcc_.clear(); + } + index_[pos].vAcc_.push_back(idx); + pointCount_++; + } + + for (int i = 0; i <= maxIndex; ++i) + { + index_[i].freeIndex(index_[i]); + if (!index_[i].vAcc_.empty()) index_[i].buildIndex(); + } + } + + /** Remove a point from the set (Lazy Deletion) */ + void removePoint(size_t idx) + { + if (idx >= pointCount_) return; + removedPoints_.insert(idx); + treeIndex_[idx] = -1; + } + + /** + * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored + * inside the result object. + * + * Params: + * result = the result object in which the indices of the + * nearest-neighbors are stored vec = the vector for which to search the + * nearest neighbors + * + * \tparam RESULTSET Should be any ResultSet + * \return True if the requested neighbors could be found. + * \sa knnSearch, radiusSearch + * + * \note If L2 norms are used, all returned distances are actually squared + * distances. + */ + template + bool findNeighbors( + RESULTSET& result, const ElementType* vec, + const SearchParameters& searchParams = {}) const + { + for (size_t i = 0; i < treeCount_; i++) + { + index_[i].findNeighbors(result, &vec[0], searchParams); + } + return result.full(); + } +}; + +/** An L2-metric KD-tree adaptor for working with data directly stored in an + * Eigen Matrix, without duplicating the data storage. You can select whether a + * row or column in the matrix represents a point in the state space. + * + * Example of usage: + * \code + * Eigen::Matrix mat; + * + * // Fill out "mat"... + * using my_kd_tree_t = nanoflann::KDTreeEigenMatrixAdaptor< + * Eigen::Matrix>; + * + * const int max_leaf = 10; + * my_kd_tree_t mat_index(mat, max_leaf); + * mat_index.index->... + * \endcode + * + * \tparam DIM If set to >0, it specifies a compile-time fixed dimensionality + * for the points in the data set, allowing more compiler optimizations. + * \tparam Distance The distance metric to use: nanoflann::metric_L1, + * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. + * \tparam row_major If set to true the rows of the matrix are used as the + * points, if set to false the columns of the matrix are used as the + * points. + */ +template < + class MatrixType, int32_t DIM = -1, class Distance = nanoflann::metric_L2, + bool row_major = true> +struct KDTreeEigenMatrixAdaptor +{ + using self_t = + KDTreeEigenMatrixAdaptor; + using num_t = typename MatrixType::Scalar; + using IndexType = typename MatrixType::Index; + using metric_t = typename Distance::template traits< + num_t, self_t, IndexType>::distance_t; + + using index_t = KDTreeSingleIndexAdaptor< + metric_t, self_t, + row_major ? MatrixType::ColsAtCompileTime + : MatrixType::RowsAtCompileTime, + IndexType>; + + index_t* index_; //! The kd-tree index for the user to call its methods as + //! usual with any other FLANN index. + + using Offset = typename index_t::Offset; + using Size = typename index_t::Size; + using Dimension = typename index_t::Dimension; + + /// Constructor: takes a const ref to the matrix object with the data points + explicit KDTreeEigenMatrixAdaptor( + const Dimension dimensionality, + const std::reference_wrapper& mat, + const int leaf_max_size = 10, const unsigned int n_thread_build = 1) + : m_data_matrix(mat) + { + const auto dims = row_major ? mat.get().cols() : mat.get().rows(); + if (static_cast(dims) != dimensionality) + throw std::runtime_error( + "Error: 'dimensionality' must match column count in data " + "matrix"); + if (DIM > 0 && static_cast(dims) != DIM) + throw std::runtime_error( + "Data set dimensionality does not match the 'DIM' template " + "argument"); + index_ = new index_t( + dims, *this /* adaptor */, + nanoflann::KDTreeSingleIndexAdaptorParams( + leaf_max_size, nanoflann::KDTreeSingleIndexAdaptorFlags::None, + n_thread_build)); + } + + public: + /** Deleted copy constructor */ + KDTreeEigenMatrixAdaptor(const self_t&) = delete; + + ~KDTreeEigenMatrixAdaptor() { delete index_; } + + const std::reference_wrapper m_data_matrix; + + /** Query for the \a num_closest closest points to a given point (entered as + * query_point[0:dim-1]). Note that this is a short-cut method for + * index->findNeighbors(). The user can also call index->... methods as + * desired. + * + * \note If L2 norms are used, all returned distances are actually squared + * distances. + */ + void query( + const num_t* query_point, const Size num_closest, + IndexType* out_indices, num_t* out_distances) const + { + nanoflann::KNNResultSet resultSet(num_closest); + resultSet.init(out_indices, out_distances); + index_->findNeighbors(resultSet, query_point); + } + + /** @name Interface expected by KDTreeSingleIndexAdaptor + * @{ */ + + const self_t& derived() const { return *this; } + self_t& derived() { return *this; } + + // Must return the number of data points + Size kdtree_get_point_count() const + { + if (row_major) + return m_data_matrix.get().rows(); + else + return m_data_matrix.get().cols(); + } + + // Returns the dim'th component of the idx'th point in the class: + num_t kdtree_get_pt(const IndexType idx, size_t dim) const + { + if (row_major) + return m_data_matrix.get().coeff(idx, IndexType(dim)); + else + return m_data_matrix.get().coeff(IndexType(dim), idx); + } + + // Optional bounding-box computation: return false to default to a standard + // bbox computation loop. + // Return true if the BBOX was already computed by the class and returned + // in "bb" so it can be avoided to redo it again. Look at bb.size() to + // find out the expected dimensionality (e.g. 2 or 3 for point clouds) + template + bool kdtree_get_bbox(BBOX& /*bb*/) const + { + return false; + } + + /** @} */ + +}; // end of KDTreeEigenMatrixAdaptor +/** @} */ + +/** @} */ // end of grouping +} // namespace nanoflann diff --git a/src/vendor/cigraph/vendor/plfit/gss.h b/src/vendor/cigraph/vendor/plfit/gss.h index 45276fda075..afb6aefa459 100644 --- a/src/vendor/cigraph/vendor/plfit/gss.h +++ b/src/vendor/cigraph/vendor/plfit/gss.h @@ -22,7 +22,7 @@ #include "plfit_decls.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS /** * Enum specifying what the search should do when the function is not U-shaped. @@ -133,6 +133,6 @@ unsigned short int gss_get_warning_flag(void); */ void gss_parameter_init(gss_parameter_t *param); -__END_DECLS +PLFIT_END_C_DECLS #endif /* __GSS_H__ */ diff --git a/src/vendor/cigraph/vendor/plfit/hzeta.h b/src/vendor/cigraph/vendor/plfit/hzeta.h index 39a7e01a7cc..598f12d5866 100644 --- a/src/vendor/cigraph/vendor/plfit/hzeta.h +++ b/src/vendor/cigraph/vendor/plfit/hzeta.h @@ -34,7 +34,7 @@ #include "plfit_decls.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS /* Hurwitz Zeta Function @@ -83,6 +83,6 @@ double hsl_sf_lnhzeta_deriv(const double s, const double q); double hsl_sf_lnhzeta_deriv_tuple(const double s, const double q, double * deriv0, double * deriv1); -__END_DECLS +PLFIT_END_C_DECLS #endif // __HZETA_H__ diff --git a/src/vendor/cigraph/vendor/plfit/kolmogorov.h b/src/vendor/cigraph/vendor/plfit/kolmogorov.h index 9615bcb74be..b635baa0db6 100644 --- a/src/vendor/cigraph/vendor/plfit/kolmogorov.h +++ b/src/vendor/cigraph/vendor/plfit/kolmogorov.h @@ -23,12 +23,12 @@ #include #include "plfit_decls.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS double plfit_kolmogorov(double z); double plfit_ks_test_one_sample_p(double d, size_t n); double plfit_ks_test_two_sample_p(double d, size_t n1, size_t n2); -__END_DECLS +PLFIT_END_C_DECLS #endif diff --git a/src/vendor/cigraph/vendor/plfit/lbfgs.h b/src/vendor/cigraph/vendor/plfit/lbfgs.h index 8390ec3c79d..73d99e445a9 100644 --- a/src/vendor/cigraph/vendor/plfit/lbfgs.h +++ b/src/vendor/cigraph/vendor/plfit/lbfgs.h @@ -31,7 +31,7 @@ #include "plfit_decls.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS /* * The default precision of floating point values is 64bit (double). @@ -59,7 +59,7 @@ typedef double lbfgsfloatval_t; #endif -/** +/** * \addtogroup liblbfgs_api libLBFGS API * @{ * @@ -68,7 +68,7 @@ typedef double lbfgsfloatval_t; /** * Return values of lbfgs(). - * + * * Roughly speaking, a negative value indicates an error. */ enum { @@ -365,7 +365,7 @@ typedef struct { * function and its gradients when needed. A client program must implement * this function to evaluate the values of the objective function and its * gradients, given current values of variables. - * + * * @param instance The user data sent for lbfgs() function by the client. * @param x The current values of variables. * @param g The gradient vector. The callback function must compute @@ -502,14 +502,14 @@ void lbfgs_parameter_init(lbfgs_parameter_t *param); * when libLBFGS is built with SSE/SSE2 optimization routines. A user does * not have to use this function for libLBFGS built without SSE/SSE2 * optimization. - * + * * @param n The number of variables. */ lbfgsfloatval_t* lbfgs_malloc(int n); /** * Free an array of variables. - * + * * @param x The array of variables allocated by ::lbfgs_malloc * function. */ @@ -524,7 +524,7 @@ const char* lbfgs_strerror(int err); /** @} */ -__END_DECLS +PLFIT_END_C_DECLS diff --git a/src/vendor/cigraph/vendor/plfit/plfit.c b/src/vendor/cigraph/vendor/plfit/plfit.c index bfc8eeb5ba7..26525da03ce 100644 --- a/src/vendor/cigraph/vendor/plfit/plfit.c +++ b/src/vendor/cigraph/vendor/plfit/plfit.c @@ -1,4 +1,3 @@ -/* vim:set ts=4 sw=4 sts=4 et: */ /* plfit.c * * Copyright (C) 2010-2011 Tamas Nepusz diff --git a/src/vendor/cigraph/vendor/plfit/plfit.h b/src/vendor/cigraph/vendor/plfit/plfit.h index a312790f221..54d57a19c2d 100644 --- a/src/vendor/cigraph/vendor/plfit/plfit.h +++ b/src/vendor/cigraph/vendor/plfit/plfit.h @@ -1,4 +1,3 @@ -/* vim:set ts=4 sw=4 sts=4 et: */ /* plfit.h * * Copyright (C) 2010-2011 Tamas Nepusz @@ -28,7 +27,7 @@ #include "plfit_sampling.h" #include "plfit_version.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS typedef unsigned short int plfit_bool_t; @@ -128,6 +127,6 @@ PLFIT_EXPORT int plfit_calculate_p_value_discrete(const double* xs, size_t n, PLFIT_EXPORT int plfit_moments(const double* data, size_t n, double* mean, double* variance, double* skewness, double* kurtosis); -__END_DECLS +PLFIT_END_C_DECLS #endif /* PLFIT_H */ diff --git a/src/vendor/cigraph/vendor/plfit/plfit_decls.h b/src/vendor/cigraph/vendor/plfit/plfit_decls.h index ee45c3bed3e..de57912386b 100644 --- a/src/vendor/cigraph/vendor/plfit/plfit_decls.h +++ b/src/vendor/cigraph/vendor/plfit/plfit_decls.h @@ -20,14 +20,14 @@ #ifndef PLFIT_DECLS_H #define PLFIT_DECLS_H -#undef __BEGIN_DECLS -#undef __END_DECLS +#undef PLFIT_BEGIN_C_DECLS +#undef PLFIT_END_C_DECLS #ifdef __cplusplus - #define __BEGIN_DECLS extern "C" { - #define __END_DECLS } + #define PLFIT_BEGIN_C_DECLS extern "C" { + #define PLFIT_END_C_DECLS } #else - #define __BEGIN_DECLS /* empty */ - #define __END_DECLS /* empty */ + #define PLFIT_BEGIN_C_DECLS /* empty */ + #define PLFIT_END_C_DECLS /* empty */ #endif #define PLFIT_EXPORT /* empty */ diff --git a/src/vendor/cigraph/vendor/plfit/plfit_error.h b/src/vendor/cigraph/vendor/plfit/plfit_error.h index c6c5dff3251..b94519ee3d3 100644 --- a/src/vendor/cigraph/vendor/plfit/plfit_error.h +++ b/src/vendor/cigraph/vendor/plfit/plfit_error.h @@ -22,7 +22,7 @@ #include "plfit_decls.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS enum { PLFIT_SUCCESS = 0, @@ -67,6 +67,6 @@ PLFIT_EXPORT plfit_error_handler_t* plfit_set_error_handler(plfit_error_handler_ PLFIT_EXPORT void plfit_error(const char *reason, const char *file, int line, int plfit_errno); PLFIT_EXPORT const char* plfit_strerror(const int plfit_errno); -__END_DECLS +PLFIT_END_C_DECLS #endif /* PLFIT_ERROR_H */ diff --git a/src/vendor/cigraph/vendor/plfit/plfit_mt.h b/src/vendor/cigraph/vendor/plfit/plfit_mt.h index 99c5f96b1fd..6905095d1a9 100644 --- a/src/vendor/cigraph/vendor/plfit/plfit_mt.h +++ b/src/vendor/cigraph/vendor/plfit/plfit_mt.h @@ -17,7 +17,7 @@ #include #include "plfit_decls.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS #define PLFIT_MT_LEN 624 @@ -82,6 +82,6 @@ PLFIT_EXPORT uint32_t plfit_mt_random(plfit_mt_rng_t* rng); */ PLFIT_EXPORT double plfit_mt_uniform_01(plfit_mt_rng_t* rng); -__END_DECLS +PLFIT_END_C_DECLS #endif /* PLFIT_MT_H */ diff --git a/src/vendor/cigraph/vendor/plfit/plfit_sampling.h b/src/vendor/cigraph/vendor/plfit/plfit_sampling.h index ed89c2cd05e..edde225132b 100644 --- a/src/vendor/cigraph/vendor/plfit/plfit_sampling.h +++ b/src/vendor/cigraph/vendor/plfit/plfit_sampling.h @@ -24,7 +24,7 @@ #include "plfit_decls.h" #include "plfit_mt.h" -__BEGIN_DECLS +PLFIT_BEGIN_C_DECLS /** * Draws a sample from a binomial distribution with the given count and @@ -163,6 +163,6 @@ PLFIT_EXPORT void plfit_walker_alias_sampler_destroy(plfit_walker_alias_sampler_ PLFIT_EXPORT int plfit_walker_alias_sampler_sample(const plfit_walker_alias_sampler_t* sampler, long int* xs, size_t n, plfit_mt_rng_t* rng); -__END_DECLS +PLFIT_END_C_DECLS #endif /* PLFIT_SAMPLING_H */ diff --git a/src/vendor/igraph_config.h b/src/vendor/igraph_config.h index 5c0f62d9f8a..397d8af7c06 100644 --- a/src/vendor/igraph_config.h +++ b/src/vendor/igraph_config.h @@ -25,7 +25,7 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \define IGRAPH_INTEGER_SIZE @@ -50,6 +50,6 @@ __BEGIN_DECLS */ #define IGRAPH_BOOL_TYPE int -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/igraph_threading.h b/src/vendor/igraph_threading.h index ebbdb1780c0..3a8faa10e7a 100644 --- a/src/vendor/igraph_threading.h +++ b/src/vendor/igraph_threading.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2011-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2011-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_THREADING_H @@ -26,7 +21,7 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS /** * \define IGRAPH_THREAD_SAFE @@ -42,6 +37,6 @@ __BEGIN_DECLS #define IGRAPH_THREAD_SAFE 0 -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h index 2608de3d8a3..5e79535b53d 100644 --- a/src/vendor/igraph_version.h +++ b/src/vendor/igraph_version.h @@ -1,8 +1,6 @@ -/* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Gabor Csardi - 334 Harvard street, Cambridge, MA 02139 USA + Copyright (C) 2010-2025 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 @@ -15,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #ifndef IGRAPH_VERSION_H @@ -26,19 +21,19 @@ #include "igraph_decls.h" -__BEGIN_DECLS +IGRAPH_BEGIN_C_DECLS -#define IGRAPH_VERSION "0.10.16-95-g6a92b9a7a" +#define IGRAPH_VERSION "0.10.16-913-g1db733b23" #define IGRAPH_VERSION_MAJOR 0 #define IGRAPH_VERSION_MINOR 10 #define IGRAPH_VERSION_PATCH 16 -#define IGRAPH_VERSION_PRERELEASE "95-g6a92b9a7a" +#define IGRAPH_VERSION_PRERELEASE "913-g1db733b23" IGRAPH_EXPORT void igraph_version(const char **version_string, int *major, int *minor, int *subminor); -__END_DECLS +IGRAPH_END_C_DECLS #endif diff --git a/src/vendor/io/dl-lexer.c b/src/vendor/io/dl-lexer.c index 4a79fe532f0..4844b12f2e1 100644 --- a/src/vendor/io/dl-lexer.c +++ b/src/vendor/io/dl-lexer.c @@ -881,12 +881,11 @@ static const flex_int32_t yy_rule_can_match_eol[25] = */ -#include -#include - #include "io/dl-header.h" #include "io/parsers/dl-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_dl_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in DL parser: " # msg) @@ -897,10 +896,10 @@ static const flex_int32_t yy_rule_can_match_eol[25] = #endif #define stdout 0 #endif -#line 901 "src/vendor/io/dl-lexer.c" +#line 900 "src/vendor/io/dl-lexer.c" #define YY_NO_INPUT 1 -#line 904 "src/vendor/io/dl-lexer.c" +#line 903 "src/vendor/io/dl-lexer.c" #define INITIAL 0 #define LABELM 1 @@ -1186,10 +1185,10 @@ YY_DECL } { -#line 81 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 80 "src/vendor/cigraph/src/io/dl-lexer.l" -#line 1193 "src/vendor/io/dl-lexer.c" +#line 1192 "src/vendor/io/dl-lexer.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1261,27 +1260,27 @@ YY_DECL case 1: /* rule 1 can match eol */ YY_RULE_SETUP -#line 83 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 82 "src/vendor/cigraph/src/io/dl-lexer.l" { return NEWLINE; } YY_BREAK case 2: YY_RULE_SETUP -#line 85 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 84 "src/vendor/cigraph/src/io/dl-lexer.l" { return DL; } YY_BREAK case 3: YY_RULE_SETUP -#line 86 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 85 "src/vendor/cigraph/src/io/dl-lexer.l" { return NEQ; } YY_BREAK case 4: YY_RULE_SETUP -#line 87 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 86 "src/vendor/cigraph/src/io/dl-lexer.l" { return NUM; } YY_BREAK case 5: YY_RULE_SETUP -#line 89 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 88 "src/vendor/cigraph/src/io/dl-lexer.l" { switch (yyextra->mode) { case 0: BEGIN(FULLMATRIX); @@ -1295,91 +1294,91 @@ YY_RULE_SETUP YY_BREAK case 6: YY_RULE_SETUP -#line 100 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 99 "src/vendor/cigraph/src/io/dl-lexer.l" { BEGIN(LABELM); return LABELS; } YY_BREAK case 7: YY_RULE_SETUP -#line 101 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 100 "src/vendor/cigraph/src/io/dl-lexer.l" { return LABELSEMBEDDED; } YY_BREAK case 8: YY_RULE_SETUP -#line 103 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 102 "src/vendor/cigraph/src/io/dl-lexer.l" { yyextra->mode=0; return FORMATFULLMATRIX; } YY_BREAK case 9: YY_RULE_SETUP -#line 105 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 104 "src/vendor/cigraph/src/io/dl-lexer.l" { yyextra->mode=1; return FORMATEDGELIST1; } YY_BREAK case 10: YY_RULE_SETUP -#line 107 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 106 "src/vendor/cigraph/src/io/dl-lexer.l" { yyextra->mode=2; return FORMATNODELIST1; } YY_BREAK case 11: YY_RULE_SETUP -#line 110 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 109 "src/vendor/cigraph/src/io/dl-lexer.l" { /* eaten up */ } YY_BREAK case 12: YY_RULE_SETUP -#line 111 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 110 "src/vendor/cigraph/src/io/dl-lexer.l" { return LABEL; } YY_BREAK case 13: YY_RULE_SETUP -#line 113 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 112 "src/vendor/cigraph/src/io/dl-lexer.l" { return DIGIT; } YY_BREAK case 14: YY_RULE_SETUP -#line 114 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 113 "src/vendor/cigraph/src/io/dl-lexer.l" { return LABEL; } YY_BREAK case 15: YY_RULE_SETUP -#line 115 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 114 "src/vendor/cigraph/src/io/dl-lexer.l" { } YY_BREAK case 16: YY_RULE_SETUP -#line 117 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 116 "src/vendor/cigraph/src/io/dl-lexer.l" { return NUM; } YY_BREAK case 17: YY_RULE_SETUP -#line 118 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 117 "src/vendor/cigraph/src/io/dl-lexer.l" { return LABEL; } YY_BREAK case 18: YY_RULE_SETUP -#line 119 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 118 "src/vendor/cigraph/src/io/dl-lexer.l" { } YY_BREAK case 19: YY_RULE_SETUP -#line 121 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 120 "src/vendor/cigraph/src/io/dl-lexer.l" { return NUM; } YY_BREAK case 20: YY_RULE_SETUP -#line 122 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 121 "src/vendor/cigraph/src/io/dl-lexer.l" { return LABEL; } YY_BREAK case 21: YY_RULE_SETUP -#line 123 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 122 "src/vendor/cigraph/src/io/dl-lexer.l" { } YY_BREAK case 22: YY_RULE_SETUP -#line 125 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 124 "src/vendor/cigraph/src/io/dl-lexer.l" { /* eaten up */ } YY_BREAK case YY_STATE_EOF(INITIAL): @@ -1387,7 +1386,7 @@ case YY_STATE_EOF(LABELM): case YY_STATE_EOF(FULLMATRIX): case YY_STATE_EOF(EDGELIST): case YY_STATE_EOF(NODELIST): -#line 127 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 126 "src/vendor/cigraph/src/io/dl-lexer.l" { if (yyextra->eof) { yyterminate(); @@ -1400,15 +1399,15 @@ case YY_STATE_EOF(NODELIST): YY_BREAK case 23: YY_RULE_SETUP -#line 137 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 136 "src/vendor/cigraph/src/io/dl-lexer.l" { return 0; } YY_BREAK case 24: YY_RULE_SETUP -#line 138 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 137 "src/vendor/cigraph/src/io/dl-lexer.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 1412 "src/vendor/io/dl-lexer.c" +#line 1411 "src/vendor/io/dl-lexer.c" case YY_END_OF_BUFFER: { @@ -2567,4 +2566,4 @@ void yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 138 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 137 "src/vendor/cigraph/src/io/dl-lexer.l" diff --git a/src/vendor/io/gml-lexer.c b/src/vendor/io/gml-lexer.c index 3a73d7ceab2..1bbf0006e2c 100644 --- a/src/vendor/io/gml-lexer.c +++ b/src/vendor/io/gml-lexer.c @@ -755,11 +755,11 @@ static const flex_int32_t yy_rule_can_match_eol[12] = */ -#include - #include "io/gml-header.h" #include "io/parsers/gml-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_gml_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in GML parser: " # msg) diff --git a/src/vendor/io/lgl-lexer.c b/src/vendor/io/lgl-lexer.c index 9dfdc806383..d202b600b82 100644 --- a/src/vendor/io/lgl-lexer.c +++ b/src/vendor/io/lgl-lexer.c @@ -726,11 +726,11 @@ static const flex_int32_t yy_rule_can_match_eol[7] = */ -#include - #include "io/lgl-header.h" #include "io/parsers/lgl-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_lgl_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in LGL parser: " # msg) 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-lexer.c b/src/vendor/io/ncol-lexer.c index a46f440ef63..393423e5f4d 100644 --- a/src/vendor/io/ncol-lexer.c +++ b/src/vendor/io/ncol-lexer.c @@ -726,11 +726,11 @@ static const flex_int32_t yy_rule_can_match_eol[6] = */ -#include - #include "io/ncol-header.h" #include "io/parsers/ncol-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_ncol_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in NCOL parser: " # msg) 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-lexer.c b/src/vendor/io/pajek-lexer.c index 0c32ca04b9c..781f2e869e1 100644 --- a/src/vendor/io/pajek-lexer.c +++ b/src/vendor/io/pajek-lexer.c @@ -879,11 +879,11 @@ static const flex_int32_t yy_rule_can_match_eol[58] = */ -#include - #include "io/pajek-header.h" #include "io/parsers/pajek-parser.h" +#include + #define YY_EXTRA_TYPE igraph_i_pajek_parsedata_t* #define YY_USER_ACTION yylloc->first_line = yylineno; #define YY_FATAL_ERROR(msg) IGRAPH_FATAL("Error in Pajek parser: " # msg) diff --git a/src/vendor/io/pajek-parser.c b/src/vendor/io/pajek-parser.c index e62631deb5b..466796d5633 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, 216, - 235, 235, 237, 238, 238, 248, 267, 272, 273, 277, - 283, 283, 287, 287, 290, 291, 294, 297, 300, 303, - 306, 309, 312, 315, 318, 323, 326, 329, 332, 335, - 338, 353, 353, 353, 353, 353, 353, 355, 356, 358, - 358, 360, 360, 365, 366, 368, 368, 370, 370, 375, - 375, 379, 379, 382, 383, 386, 389, 392, 395, 398, - 401, 404, 407, 410, 413, 416, 419, 422, 427, 430, - 433, 436, 439, 442, 445, 460, 462, 462, 464, 466, - 466, 468, 470, 475, 477, 477, 479, 481, 481, 483, - 485, 492, 494, 499, 499, 501, 503, 503, 505, 525, - 533, 541, 545, 547, 549, 551 + 0, 194, 194, 205, 205, 207, 207, 209, 211, 222, + 241, 241, 243, 244, 244, 254, 273, 277, 278, 282, + 288, 288, 292, 292, 295, 296, 299, 302, 305, 308, + 311, 314, 317, 320, 323, 328, 331, 334, 337, 340, + 343, 358, 358, 358, 358, 358, 358, 360, 361, 363, + 363, 365, 365, 370, 371, 373, 373, 375, 375, 380, + 380, 384, 384, 387, 388, 391, 394, 397, 400, 403, + 406, 409, 412, 415, 418, 421, 424, 427, 432, 435, + 438, 441, 444, 447, 450, 465, 467, 467, 469, 471, + 471, 473, 475, 480, 482, 482, 484, 486, 486, 488, + 490, 497, 499, 504, 504, 506, 508, 508, 510, 530, + 538, 546, 550, 552, 554, 556 }; #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; @@ -1819,11 +1825,11 @@ YYLTYPE yylloc = yyloc_default; } IGRAPH_YY_CHECK(igraph_bitset_resize(context->seen, context->vcount)); } -#line 1823 "src/vendor/io/pajek-parser.c" +#line 1829 "src/vendor/io/pajek-parser.c" break; case 9: /* verticeshead: "*Vertices line" integer integer */ -#line 216 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 222 "src/vendor/cigraph/src/io/pajek-parser.y" { context->vcount=(yyvsp[-1].intnum); context->vcount2=(yyvsp[0].intnum); @@ -1842,17 +1848,17 @@ YYLTYPE yylloc = yyloc_default; IGRAPH_YY_CHECK(add_bipartite_type(context)); IGRAPH_YY_CHECK(igraph_bitset_resize(context->seen, context->vcount)); } -#line 1846 "src/vendor/io/pajek-parser.c" +#line 1852 "src/vendor/io/pajek-parser.c" break; case 13: /* $@1: %empty */ -#line 238 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 244 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actvertex=(yyvsp[0].intnum); } -#line 1852 "src/vendor/io/pajek-parser.c" +#line 1858 "src/vendor/io/pajek-parser.c" break; case 14: /* vertexline: vertex $@1 vertexid vertexcoords shape vertparams "end of line" */ -#line 238 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 244 "src/vendor/cigraph/src/io/pajek-parser.y" { igraph_integer_t v = (yyvsp[-6].intnum)-1; /* zero-based vertex ID */ if (IGRAPH_BIT_TEST(*context->seen, v)) { @@ -1861,11 +1867,11 @@ YYLTYPE yylloc = yyloc_default; IGRAPH_BIT_SET(*context->seen, v); } } -#line 1865 "src/vendor/io/pajek-parser.c" +#line 1871 "src/vendor/io/pajek-parser.c" break; case 15: /* vertex: integer */ -#line 248 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 254 "src/vendor/cigraph/src/io/pajek-parser.y" { igraph_integer_t v = (yyvsp[0].intnum); /* Per feedback from Pajek's authors, negative signs should be ignored for vertex IDs. @@ -1884,167 +1890,166 @@ YYLTYPE yylloc = yyloc_default; } (yyval.intnum) = v; } -#line 1888 "src/vendor/io/pajek-parser.c" +#line 1894 "src/vendor/io/pajek-parser.c" break; case 16: /* vertexid: word */ -#line 267 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 273 "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 1897 "src/vendor/io/pajek-parser.c" +#line 1902 "src/vendor/io/pajek-parser.c" break; case 18: /* vertexcoords: number number */ -#line 273 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 278 "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 1906 "src/vendor/io/pajek-parser.c" +#line 1911 "src/vendor/io/pajek-parser.c" break; case 19: /* vertexcoords: number number 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("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 1916 "src/vendor/io/pajek-parser.c" +#line 1921 "src/vendor/io/pajek-parser.c" break; case 21: /* shape: word */ -#line 283 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 288 "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 1924 "src/vendor/io/pajek-parser.c" +#line 1929 "src/vendor/io/pajek-parser.c" break; case 25: /* vertparam: VP_X_FACT number */ -#line 291 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 296 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("xfact", (yyvsp[0].realnum), context)); } -#line 1932 "src/vendor/io/pajek-parser.c" +#line 1937 "src/vendor/io/pajek-parser.c" break; case 26: /* vertparam: VP_Y_FACT number */ -#line 294 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 299 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("yfact", (yyvsp[0].realnum), context)); } -#line 1940 "src/vendor/io/pajek-parser.c" +#line 1945 "src/vendor/io/pajek-parser.c" break; case 27: /* vertparam: VP_LR number */ -#line 297 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 302 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("labeldist", (yyvsp[0].realnum), context)); } -#line 1948 "src/vendor/io/pajek-parser.c" +#line 1953 "src/vendor/io/pajek-parser.c" break; case 28: /* vertparam: VP_LPHI number */ -#line 300 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 305 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("labeldegree2", (yyvsp[0].realnum), context)); } -#line 1956 "src/vendor/io/pajek-parser.c" +#line 1961 "src/vendor/io/pajek-parser.c" break; case 29: /* vertparam: VP_BW number */ -#line 303 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 308 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("framewidth", (yyvsp[0].realnum), context)); } -#line 1964 "src/vendor/io/pajek-parser.c" +#line 1969 "src/vendor/io/pajek-parser.c" break; case 30: /* vertparam: VP_FOS number */ -#line 306 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 311 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("fontsize", (yyvsp[0].realnum), context)); } -#line 1972 "src/vendor/io/pajek-parser.c" +#line 1977 "src/vendor/io/pajek-parser.c" break; case 31: /* vertparam: VP_PHI number */ -#line 309 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 314 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("rotation", (yyvsp[0].realnum), context)); } -#line 1980 "src/vendor/io/pajek-parser.c" +#line 1985 "src/vendor/io/pajek-parser.c" break; case 32: /* vertparam: VP_R number */ -#line 312 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 317 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("radius", (yyvsp[0].realnum), context)); } -#line 1988 "src/vendor/io/pajek-parser.c" +#line 1993 "src/vendor/io/pajek-parser.c" break; case 33: /* vertparam: VP_Q number */ -#line 315 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 320 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("diamondratio", (yyvsp[0].realnum), context)); } -#line 1996 "src/vendor/io/pajek-parser.c" +#line 2001 "src/vendor/io/pajek-parser.c" break; case 34: /* vertparam: VP_LA number */ -#line 318 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 323 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("labeldegree", (yyvsp[0].realnum), context)); } -#line 2004 "src/vendor/io/pajek-parser.c" +#line 2009 "src/vendor/io/pajek-parser.c" break; case 35: /* vpword: VP_FONT parstrval */ -#line 323 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 328 "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 2012 "src/vendor/io/pajek-parser.c" +#line 2017 "src/vendor/io/pajek-parser.c" break; case 36: /* vpword: VP_URL parstrval */ -#line 326 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 331 "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 2020 "src/vendor/io/pajek-parser.c" +#line 2025 "src/vendor/io/pajek-parser.c" break; case 37: /* vpword: VP_IC parstrval */ -#line 329 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 334 "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 2028 "src/vendor/io/pajek-parser.c" +#line 2033 "src/vendor/io/pajek-parser.c" break; case 38: /* vpword: VP_BC parstrval */ -#line 332 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 337 "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 2036 "src/vendor/io/pajek-parser.c" +#line 2041 "src/vendor/io/pajek-parser.c" break; case 39: /* vpword: VP_LC parstrval */ -#line 335 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 340 "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 2044 "src/vendor/io/pajek-parser.c" +#line 2049 "src/vendor/io/pajek-parser.c" break; case 40: /* vpword: parname parstrval */ -#line 338 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 343 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_FINALLY(igraph_free, (yyvsp[-1].dynstr)); if (is_standard_vattr((yyvsp[-1].dynstr))) { @@ -2058,231 +2063,231 @@ YYLTYPE yylloc = yyloc_default; IGRAPH_FREE((yyvsp[-1].dynstr)); IGRAPH_FINALLY_CLEAN(1); } -#line 2062 "src/vendor/io/pajek-parser.c" +#line 2067 "src/vendor/io/pajek-parser.c" break; case 47: /* arcs: "*Arcs line" "end of line" arcsdefs */ -#line 355 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 360 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=true; } -#line 2068 "src/vendor/io/pajek-parser.c" +#line 2073 "src/vendor/io/pajek-parser.c" break; case 48: /* arcs: "*Arcs line" number "end of line" arcsdefs */ -#line 356 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 361 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=true; } -#line 2074 "src/vendor/io/pajek-parser.c" +#line 2079 "src/vendor/io/pajek-parser.c" break; case 51: /* $@2: %empty */ -#line 360 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 365 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actedge++; } -#line 2080 "src/vendor/io/pajek-parser.c" +#line 2085 "src/vendor/io/pajek-parser.c" break; case 52: /* arcsline: vertex vertex $@2 weight edgeparams "end of line" */ -#line 360 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 365 "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 2088 "src/vendor/io/pajek-parser.c" +#line 2093 "src/vendor/io/pajek-parser.c" break; case 53: /* edges: "*Edges line" "end of line" edgesdefs */ -#line 365 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 370 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=0; } -#line 2094 "src/vendor/io/pajek-parser.c" +#line 2099 "src/vendor/io/pajek-parser.c" break; case 54: /* edges: "*Edges line" number "end of line" edgesdefs */ -#line 366 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 371 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=0; } -#line 2100 "src/vendor/io/pajek-parser.c" +#line 2105 "src/vendor/io/pajek-parser.c" break; case 57: /* $@3: %empty */ -#line 370 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 375 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actedge++; } -#line 2106 "src/vendor/io/pajek-parser.c" +#line 2111 "src/vendor/io/pajek-parser.c" break; case 58: /* edgesline: vertex vertex $@3 weight edgeparams "end of line" */ -#line 370 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 375 "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 2114 "src/vendor/io/pajek-parser.c" +#line 2119 "src/vendor/io/pajek-parser.c" break; case 60: /* weight: 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("weight", (yyvsp[0].realnum), context)); } -#line 2122 "src/vendor/io/pajek-parser.c" +#line 2127 "src/vendor/io/pajek-parser.c" break; case 64: /* edgeparam: EP_S number */ -#line 383 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 388 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("arrowsize", (yyvsp[0].realnum), context)); } -#line 2130 "src/vendor/io/pajek-parser.c" +#line 2135 "src/vendor/io/pajek-parser.c" break; case 65: /* edgeparam: EP_W number */ -#line 386 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 391 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("edgewidth", (yyvsp[0].realnum), context)); } -#line 2138 "src/vendor/io/pajek-parser.c" +#line 2143 "src/vendor/io/pajek-parser.c" break; case 66: /* edgeparam: EP_H1 number */ -#line 389 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 394 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("hook1", (yyvsp[0].realnum), context)); } -#line 2146 "src/vendor/io/pajek-parser.c" +#line 2151 "src/vendor/io/pajek-parser.c" break; case 67: /* edgeparam: EP_H2 number */ -#line 392 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 397 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("hook2", (yyvsp[0].realnum), context)); } -#line 2154 "src/vendor/io/pajek-parser.c" +#line 2159 "src/vendor/io/pajek-parser.c" break; case 68: /* edgeparam: EP_A1 number */ -#line 395 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 400 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("angle1", (yyvsp[0].realnum), context)); } -#line 2162 "src/vendor/io/pajek-parser.c" +#line 2167 "src/vendor/io/pajek-parser.c" break; case 69: /* edgeparam: EP_A2 number */ -#line 398 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 403 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("angle2", (yyvsp[0].realnum), context)); } -#line 2170 "src/vendor/io/pajek-parser.c" +#line 2175 "src/vendor/io/pajek-parser.c" break; case 70: /* edgeparam: EP_K1 number */ -#line 401 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 406 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("velocity1", (yyvsp[0].realnum), context)); } -#line 2178 "src/vendor/io/pajek-parser.c" +#line 2183 "src/vendor/io/pajek-parser.c" break; case 71: /* edgeparam: EP_K2 number */ -#line 404 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 409 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("velocity2", (yyvsp[0].realnum), context)); } -#line 2186 "src/vendor/io/pajek-parser.c" +#line 2191 "src/vendor/io/pajek-parser.c" break; case 72: /* edgeparam: EP_AP number */ -#line 407 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 412 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("arrowpos", (yyvsp[0].realnum), context)); } -#line 2194 "src/vendor/io/pajek-parser.c" +#line 2199 "src/vendor/io/pajek-parser.c" break; case 73: /* edgeparam: EP_LP number */ -#line 410 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 415 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labelpos", (yyvsp[0].realnum), context)); } -#line 2202 "src/vendor/io/pajek-parser.c" +#line 2207 "src/vendor/io/pajek-parser.c" break; case 74: /* edgeparam: EP_LR number */ -#line 413 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 418 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labelangle", (yyvsp[0].realnum), context)); } -#line 2210 "src/vendor/io/pajek-parser.c" +#line 2215 "src/vendor/io/pajek-parser.c" break; case 75: /* edgeparam: EP_LPHI number */ -#line 416 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 421 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labelangle2", (yyvsp[0].realnum), context)); } -#line 2218 "src/vendor/io/pajek-parser.c" +#line 2223 "src/vendor/io/pajek-parser.c" break; case 76: /* edgeparam: EP_LA number */ -#line 419 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 424 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labeldegree", (yyvsp[0].realnum), context)); } -#line 2226 "src/vendor/io/pajek-parser.c" +#line 2231 "src/vendor/io/pajek-parser.c" break; case 77: /* edgeparam: EP_FOS number */ -#line 422 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 427 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("fontsize", (yyvsp[0].realnum), context)); } -#line 2234 "src/vendor/io/pajek-parser.c" +#line 2239 "src/vendor/io/pajek-parser.c" break; case 78: /* epword: EP_A parstrval */ -#line 427 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 432 "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 2242 "src/vendor/io/pajek-parser.c" +#line 2247 "src/vendor/io/pajek-parser.c" break; case 79: /* epword: EP_P parstrval */ -#line 430 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 435 "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 2250 "src/vendor/io/pajek-parser.c" +#line 2255 "src/vendor/io/pajek-parser.c" break; case 80: /* epword: EP_L parstrval */ -#line 433 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 438 "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 2258 "src/vendor/io/pajek-parser.c" +#line 2263 "src/vendor/io/pajek-parser.c" break; case 81: /* epword: EP_LC parstrval */ -#line 436 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 441 "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 2266 "src/vendor/io/pajek-parser.c" +#line 2271 "src/vendor/io/pajek-parser.c" break; case 82: /* epword: EP_C parstrval */ -#line 439 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 444 "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 2274 "src/vendor/io/pajek-parser.c" +#line 2279 "src/vendor/io/pajek-parser.c" break; case 83: /* epword: EP_FONT parstrval */ -#line 442 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 447 "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 2282 "src/vendor/io/pajek-parser.c" +#line 2287 "src/vendor/io/pajek-parser.c" break; case 84: /* epword: parname parstrval */ -#line 445 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 450 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_FINALLY(igraph_free, (yyvsp[-1].dynstr)); if (is_standard_eattr((yyvsp[-1].dynstr))) { @@ -2296,68 +2301,68 @@ YYLTYPE yylloc = yyloc_default; IGRAPH_FREE((yyvsp[-1].dynstr)); IGRAPH_FINALLY_CLEAN(1); } -#line 2300 "src/vendor/io/pajek-parser.c" +#line 2305 "src/vendor/io/pajek-parser.c" break; case 85: /* arcslist: "*Arcslist line" "end of line" arcslistlines */ -#line 460 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 465 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=true; } -#line 2306 "src/vendor/io/pajek-parser.c" +#line 2311 "src/vendor/io/pajek-parser.c" break; case 91: /* arclistfrom: vertex */ -#line 468 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 473 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom=(yyvsp[0].intnum)-1; } -#line 2312 "src/vendor/io/pajek-parser.c" +#line 2317 "src/vendor/io/pajek-parser.c" break; case 92: /* arclistto: vertex */ -#line 470 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 475 "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, (yyvsp[0].intnum)-1)); } -#line 2321 "src/vendor/io/pajek-parser.c" +#line 2326 "src/vendor/io/pajek-parser.c" break; case 93: /* edgeslist: "*Edgeslist line" "end of line" edgelistlines */ -#line 475 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 480 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=0; } -#line 2327 "src/vendor/io/pajek-parser.c" +#line 2332 "src/vendor/io/pajek-parser.c" break; case 99: /* edgelistfrom: vertex */ -#line 483 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 488 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom=(yyvsp[0].intnum)-1; } -#line 2333 "src/vendor/io/pajek-parser.c" +#line 2338 "src/vendor/io/pajek-parser.c" break; case 100: /* edgelistto: vertex */ -#line 485 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 490 "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, (yyvsp[0].intnum)-1)); } -#line 2342 "src/vendor/io/pajek-parser.c" +#line 2347 "src/vendor/io/pajek-parser.c" break; case 102: /* matrixline: "*Matrix line" */ -#line 494 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 499 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom=0; context->actto=0; context->directed=(context->vcount2==0); } -#line 2351 "src/vendor/io/pajek-parser.c" +#line 2356 "src/vendor/io/pajek-parser.c" break; case 105: /* adjmatrixline: adjmatrixnumbers "end of line" */ -#line 501 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 506 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom++; context->actto=0; } -#line 2357 "src/vendor/io/pajek-parser.c" +#line 2362 "src/vendor/io/pajek-parser.c" break; case 108: /* adjmatrixentry: number */ -#line 505 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 510 "src/vendor/cigraph/src/io/pajek-parser.y" { if ((yyvsp[0].realnum) != 0) { if (context->vcount2==0) { @@ -2375,11 +2380,11 @@ YYLTYPE yylloc = yyloc_default; } context->actto++; } -#line 2379 "src/vendor/io/pajek-parser.c" +#line 2384 "src/vendor/io/pajek-parser.c" break; case 109: /* integer: "number" */ -#line 525 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 530 "src/vendor/cigraph/src/io/pajek-parser.y" { igraph_integer_t val; IGRAPH_YY_CHECK(igraph_i_parse_integer(igraph_pajek_yyget_text(scanner), @@ -2387,11 +2392,11 @@ YYLTYPE yylloc = yyloc_default; &val)); (yyval.intnum)=val; } -#line 2391 "src/vendor/io/pajek-parser.c" +#line 2396 "src/vendor/io/pajek-parser.c" break; case 110: /* number: "number" */ -#line 533 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 538 "src/vendor/cigraph/src/io/pajek-parser.y" { igraph_real_t val; IGRAPH_YY_CHECK(igraph_i_parse_real(igraph_pajek_yyget_text(scanner), @@ -2399,46 +2404,46 @@ YYLTYPE yylloc = yyloc_default; &val)); (yyval.realnum)=val; } -#line 2403 "src/vendor/io/pajek-parser.c" +#line 2408 "src/vendor/io/pajek-parser.c" break; case 111: /* parname: word */ -#line 541 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 546 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(make_dynstr((yyvsp[0].string).str, (yyvsp[0].string).len, &(yyval.dynstr))); } -#line 2411 "src/vendor/io/pajek-parser.c" +#line 2416 "src/vendor/io/pajek-parser.c" break; case 112: /* parstrval: word */ -#line 545 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 550 "src/vendor/cigraph/src/io/pajek-parser.y" { (yyval.string)=(yyvsp[0].string); } -#line 2417 "src/vendor/io/pajek-parser.c" +#line 2422 "src/vendor/io/pajek-parser.c" break; case 113: /* word: "word" */ -#line 547 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 552 "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 2424 "src/vendor/io/pajek-parser.c" +#line 2429 "src/vendor/io/pajek-parser.c" break; case 114: /* word: "number" */ -#line 549 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 554 "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 2431 "src/vendor/io/pajek-parser.c" +#line 2436 "src/vendor/io/pajek-parser.c" break; case 115: /* word: "quoted string" */ -#line 551 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 556 "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 2438 "src/vendor/io/pajek-parser.c" +#line 2443 "src/vendor/io/pajek-parser.c" break; -#line 2442 "src/vendor/io/pajek-parser.c" +#line 2447 "src/vendor/io/pajek-parser.c" default: break; } @@ -2667,7 +2672,7 @@ YYLTYPE yylloc = yyloc_default; return yyresult; } -#line 554 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 559 "src/vendor/cigraph/src/io/pajek-parser.y" int igraph_pajek_yyerror(YYLTYPE* locp, @@ -2682,49 +2687,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_set_default_string(&rec, default_value)); - rec->type = IGRAPH_ATTRIBUTE_STRING; - rec->value = na; - - 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)); } @@ -2809,7 +2792,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); } @@ -2821,7 +2806,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); } @@ -2832,7 +2819,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); } @@ -2843,7 +2832,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); } @@ -2851,10 +2842,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) { @@ -2869,29 +2860,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); + 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->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; } @@ -2931,7 +2906,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; } @@ -2973,3 +2948,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/dl-lexer.h b/src/vendor/io/parsers/dl-lexer.h index 8f86c90948b..e47a4d46e35 100644 --- a/src/vendor/io/parsers/dl-lexer.h +++ b/src/vendor/io/parsers/dl-lexer.h @@ -730,7 +730,7 @@ extern int yylex \ #undef yyTABLES_NAME #endif -#line 138 "src/vendor/cigraph/src/io/dl-lexer.l" +#line 137 "src/vendor/cigraph/src/io/dl-lexer.l" #line 736 "src/vendor/io/parsers/dl-lexer.h" #undef igraph_dl_yyIN_HEADER 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/tools/build-requirements.txt b/tools/build-requirements.txt index 3e71fd9b851..53cf255b4b3 100644 --- a/tools/build-requirements.txt +++ b/tools/build-requirements.txt @@ -3,4 +3,4 @@ # environment to detect when to re-create the virtualenv so the hash # needs to change whenever a package is updated. -git+https://github.com/igraph/stimulus@0.21.5#egg=stimulus +git+https://github.com/krlmlr/stimulus@r#egg=stimulus diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index b7a2c84f432..5e9ae89be49 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -23,6 +23,8 @@ igraph_delete_edges: igraph_delete_vertices: IGNORE: RR, RC +igraph_vcount: + igraph_ecount: IGNORE: RR, RC @@ -103,10 +105,9 @@ igraph_connect_neighborhood: igraph_famous: IGNORE: RR, RC -igraph_lcf_vector: - R: - GATTR: - name: LCF graph +igraph_adjlist: + +igraph_full_multipartite: igraph_realize_degree_sequence: PARAMS: |- @@ -232,6 +233,10 @@ igraph_correlated_game: name: Correlated random graph GATTR-PARAM: corr, p +igraph_correlated_pair_game: + +igraph_dot_product_game: + ####################################### # Basic query functions ####################################### @@ -302,37 +307,6 @@ igraph_get_k_shortest_paths: vertex_paths: vpaths edge_paths: epaths -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 - 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, - NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents, - OPTIONAL OUT VECTOR_INT inbound_edges - DEPS: |- - from ON graph, to ON graph, weights ON graph, vertices ON graph, - edges ON graph - -igraph_widest_path_widths_dijkstra: - PARAMS: |- - GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights=NULL, 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=NULL, NEIMODE mode=OUT - DEPS: from ON graph, to ON graph, weights ON graph - igraph_spanner: DEPS: weights ON graph, spanner ON graph @@ -360,15 +334,17 @@ igraph_personalized_pagerank_vs: igraph_rewire: IGNORE: RR, RC -igraph_average_path_length: - IGNORE: RR, RC, RInit - # No need for it, igraph_average_path_length_dijkstra takes care of the - # unweighted case as well +igraph_subgraph_from_edges: -igraph_average_path_length_dijkstra: - PARAM_NAMES: - unconn_pairs: unconnected - unconn: unconnected +igraph_reverse_edges: + +igraph_path_length_hist: + +igraph_simplify: + +igraph_ecc: + +igraph_reciprocity: igraph_constraint: IGNORE: RR, RC @@ -430,16 +406,6 @@ igraph_hub_score: igraph_authority_score: IGNORE: RR, RC -igraph_hub_and_authority_scores: - # 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: weights ON graph, hub ON graph V(graph), authority ON graph V(graph) - PARAMS: GRAPH graph, OUT VERTEX_QTY hub, OUT VERTEX_QTY authority, - OUT REAL value, BOOLEAN scale=True, OPTIONAL EDGEWEIGHTS weights, - INOUT ARPACKOPT options=ARPACK_DEFAULTS - igraph_is_mutual: PARAM_NAMES: es: eids @@ -447,32 +413,55 @@ igraph_is_mutual: igraph_is_chordal: IGNORE: RR, RC, RInit -# We use igraph_eccentricity_dijkstra instead -igraph_eccentricity: - IGNORE: RR, RC +igraph_avg_nearest_neighbor_degree: -igraph_eccentricity_dijkstra: - PARAM_ORDER: graph, vids, *, weights, ... +igraph_degree_correlation_vector: -# We use igraph_graph_center_dijkstra instead -igraph_graph_center: - IGNORE: RR, RC +igraph_strength: -igraph_graph_center_dijkstra: - FIRST_KW_PARAM: weights +igraph_centralization: + +igraph_centralization_degree: + +igraph_centralization_degree_tmax: + IGNORE: RR + # temporarily coded manually because we need to handle a deprecation + # between igraph 1.3.0 and 1.4.0 + +igraph_centralization_betweenness: + +igraph_centralization_betweenness_tmax: + +igraph_centralization_closeness: + +igraph_centralization_closeness_tmax: + +igraph_centralization_eigenvector_centrality: + +igraph_centralization_eigenvector_centrality_tmax: + +igraph_assortativity_nominal: + +igraph_assortativity: + +igraph_assortativity_degree: + +igraph_joint_degree_matrix: + +igraph_joint_degree_distribution: + +igraph_joint_type_distribution: + +igraph_contract_vertices: # We use igraph_radius_dijkstra instead igraph_radius: IGNORE: RR, RC -igraph_radius_dijkstra: - FIRST_KW_PARAM: weights - igraph_pseudo_diameter: DEPS: start_vid ON graph -igraph_pseudo_diameter_dijkstra: - DEPS: start_vid ON graph, weights ON graph +igraph_diversity: igraph_random_walk: PARAM_ORDER: graph, start, steps, ... @@ -480,6 +469,14 @@ igraph_random_walk: igraph_random_edge_walk: IGNORE: RR, RC +igraph_global_efficiency: + +igraph_local_efficiency: + +igraph_average_local_efficiency: + +igraph_trussness: + ####################################### # Degree sequences ####################################### @@ -521,9 +518,6 @@ igraph_bipartite_projection_size: igraph_bipartite_projection: IGNORE: RR, RC, RInit -igraph_create_bipartite: - IGNORE: RR - igraph_biadjacency: DEPS: types ON graph V(graph) @@ -538,12 +532,6 @@ igraph_bipartite_game_gnp: INTEGER n1, INTEGER n2, REAL p, BOOLEAN directed=False, NEIMODE mode=ALL -igraph_bipartite_game_gnm: - PARAMS: |- - OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES_UNNAMED types, - INTEGER n1, INTEGER n2, INTEGER m, BOOLEAN directed=False, - NEIMODE mode=ALL - igraph_bipartite_game: IGNORE: RR, RC @@ -641,12 +629,6 @@ igraph_layout_kamada_kawai_3d: igraph_layout_graphopt: IGNORE: RR, RC, RInit -igraph_layout_drl: - IGNORE: RR - -igraph_layout_drl_3d: - IGNORE: RR - igraph_layout_merge_dla: IGNORE: RR, RC @@ -905,6 +887,16 @@ igraph_coreness: igraph_get_subisomorphisms_vf2_callback: IGNORE: RR, RC +igraph_count_subisomorphisms_vf2: + +igraph_canonical_permutation: + +igraph_permute_vertices: + +igraph_isomorphic_bliss: + +igraph_count_automorphisms: + igraph_subisomorphic_lad: IGNORE: RR, RC, RInit # R function is hand-rolled @@ -997,6 +989,8 @@ igraph_eulerian_cycle: # Cycle bases ####################################### +igraph_minimum_cycle_basis: + ####################################### # Trees ####################################### @@ -1020,19 +1014,11 @@ igraph_minimum_spanning_tree_unweighted: igraph_minimum_spanning_tree_prim: IGNORE: RR, RC -igraph_random_spanning_tree: - PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid=0 - ####################################### # Coloring ####################################### -####################################### -# Microscopic update -####################################### - -igraph_moran_process: - DEPS: weights ON graph, quantities ON graph V(graph), strategies ON graph +igraph_vertex_coloring_greedy: ####################################### # Other, (yet) undocumented functions @@ -1062,14 +1048,16 @@ igraph_strerror: # Other functions, documented, graph related ####################################### +# A very special case igraph_expand_path_to_pairs: IGNORE: RR igraph_invalidate_cache: PARAMS: INOUT GRAPH graph +# FIXME: Optional IN vertex not easily supported igraph_vertex_path_from_edge_path: - DEPS: start ON graph, vertex_path ON graph, edge_path ON graph + IGNORE: RC, RR ####################################### # Meta info diff --git a/tools/stimulus/types-RC.yaml b/tools/stimulus/types-RC.yaml index e0091a0a788..e61a5c3424f 100644 --- a/tools/stimulus/types-RC.yaml +++ b/tools/stimulus/types-RC.yaml @@ -279,7 +279,7 @@ ADJLIST: OUTCONV: IN: igraph_adjlist_destroy(&%C%); -EDGEWEIGHTS: +EDGE_WEIGHTS: CALL: '&%C%' CTYPE: igraph_vector_t INCONV: @@ -294,7 +294,7 @@ EDGEWEIGHTS: igraph_vector_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -VERTEXWEIGHTS: +VERTEX_WEIGHTS: CALL: '&%C%' CTYPE: igraph_vector_t INCONV: @@ -309,7 +309,7 @@ VERTEXWEIGHTS: igraph_vector_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -EDGE_CAPACITY: +EDGE_CAPACITIES: CALL: '&%C%' CTYPE: igraph_vector_t INCONV: @@ -427,6 +427,12 @@ ALL_VERTEX_QTY: igraph_vector_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); +NEIMODE: + CALL: + IN: '%C%' + INOUT: '&%C%' + OUT: 'NULL' + VERTEX_SELECTOR: CALL: IN: '%C%' @@ -490,6 +496,27 @@ VERTEX_INDICES_PV: igraph_vector_int_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); +VERTEX_INDICES_LIST: + CALL: '&%C%' + CTYPE: igraph_vector_int_list_t + INCONV: + IN: |- + R_igraph_SEXP_to_vector_int_list(%I%, &%C%); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &%C%); + OUT: |- + if (0 != igraph_vector_int_list_init(&%C%, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &%C%); + OUTCONV: + IN: |- + igraph_vector_int_list_destroy(&%C%); + IGRAPH_FINALLY_CLEAN(1); + OUT: |- + PROTECT(%I%=R_igraph_vector_int_list_to_SEXPp1(&%C%)); + igraph_vector_int_list_destroy(&%C%); + IGRAPH_FINALLY_CLEAN(1); + VERTEX_INDEX_PAIRS: CALL: '&%C%' CTYPE: igraph_vector_int_t @@ -528,6 +555,27 @@ EDGE_INDICES: igraph_vector_int_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); +EDGE_INDICES_LIST: + CALL: '&%C%' + CTYPE: igraph_vector_int_list_t + INCONV: + IN: |- + R_igraph_SEXP_to_vector_int_list(%I%, &%C%); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &%C%); + OUT: |- + if (0 != igraph_vector_int_list_init(&%C%, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &%C%); + OUTCONV: + IN: |- + igraph_vector_int_list_destroy(&%C%); + IGRAPH_FINALLY_CLEAN(1); + OUT: |- + PROTECT(%I%=R_igraph_vector_int_list_to_SEXPp1(&%C%)); + igraph_vector_int_list_destroy(&%C%); + IGRAPH_FINALLY_CLEAN(1); + 'NULL': CALL: '0' CTYPE: ~ @@ -558,14 +606,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: {} @@ -647,7 +695,7 @@ BIPARTITE_TYPES_UNNAMED: igraph_vector_bool_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -VERTEX_COLOR: +VERTEX_COLORS: CALL: IN: '&%C%' OUT: '&%C%' @@ -672,7 +720,7 @@ VERTEX_COLOR: igraph_vector_int_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -EDGE_COLOR: +EDGE_COLORS: CALL: IN: '&%C%' OUT: '&%C%' diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index 740193a62f8..d155b639c06 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -43,7 +43,7 @@ ALL_VERTEX_QTY: OUTCONV: OUT: |- if (igraph_opt("add.vertex.names") && is_named(%I1%)) { - names(%I%) <- vertex_attr(%I1%, "name", %I2%) + names(%I%) <- vertex_attr(%I1%, "name") } VECTOR_INT: @@ -181,29 +181,7 @@ EDGE_SELECTOR: %I% <- create_es(%I1%, %I%) } -EDGEWEIGHTS: - INCONV: |- - if (is.null(%I%) && "weight" %in% edge_attr_names(%I1%)) { - %I% <- E(%I1%)$weight - } - if (!is.null(%I%) && any(!is.na(%I%))) { - %I% <- as.numeric(%I%) - } else { - %I% <- NULL - } - -VERTEXWEIGHTS: - INCONV: |- - if (is.null(%I%) && "weight" %in% vertex_attr_names(%I1%)) { - %I% <- V(%I1%)$weight - } - if (!is.null(%I%) && any(!is.na(%I%))) { - %I% <- as.numeric(%I%) - } else { - %I% <- NULL - } - -EDGE_CAPACITY: +EDGE_CAPACITIES: INCONV: |- if (is.null(%I%) && "capacity" %in% edge_attr_names(%I1%)) { %I% <- E(%I1%)$capacity @@ -234,7 +212,7 @@ ALL_BIPARTITE_TYPES: BIPARTITE_TYPES_UNNAMED: -VERTEX_COLOR: +VERTEX_COLORS: INCONV: |- if (missing(%I%)) { if ("color" %in% vertex_attr_names(%I1%)) { @@ -253,7 +231,7 @@ VERTEX_COLOR: names(%I%) <- vertex_attr(%I1%, "name") } -EDGE_COLOR: +EDGE_COLORS: INCONV: |- if (missing(%I%)) { if ("color" %in% edge_attr_names(%I1%)) { @@ -299,7 +277,7 @@ EDGESET_LIST: CALL: {} HEADER: ~ -ARPACKOPT: +ARPACK_OPTIONS: DEFAULT: ARPACK_DEFAULTS: arpack_defaults() INCONV: @@ -413,6 +391,7 @@ LAPLACIAN_NORMALIZATION: LOOPS: DEFAULT: ONCE: c("once", "none", "twice") + TWICE: c("twice", "none", "once") INCONV: '%I% <- switch(igraph.match.arg(%I%), "none"=0L, "twice"=1L, "once"=2L)' SIRLIST: {} @@ -454,6 +433,13 @@ RWSTUCK: RETURN: c("return", "error") INCONV: '%I% <- switch(igraph.match.arg(%I%), "error" = 0L, "return" = 1L)' +LPA_VARIANT: + DEFAULT: + Default: c("dominance", "retention", "fast") + INCONV: |- + %I% <- switch(igraph.match.arg(%I%), + "dominance"=0L, "retention"=1L, "fast"=2L) + EDGE_TYPE_SW: DEFAULT: SIMPLE: c("simple", "loops", "multi", "all") From af144f1477613a933fb2a809d93b6979dbb652ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 17 Aug 2025 11:05:12 +0200 Subject: [PATCH 003/154] chore: Move uuid glue --- src/sources-glue-c.mk | 2 +- src/sources-igraph.mk | 2 +- src/{vendor/uuid/R.c => uuid.c} | 14 +++++++++----- src/uuid.dd | 3 +++ 4 files changed, 14 insertions(+), 7 deletions(-) rename src/{vendor/uuid/R.c => uuid.c} (53%) create mode 100644 src/uuid.dd diff --git a/src/sources-glue-c.mk b/src/sources-glue-c.mk index 289c8bc2e8d..4801852cecf 100644 --- a/src/sources-glue-c.mk +++ b/src/sources-glue-c.mk @@ -1 +1 @@ -GLUE_C_SOURCES=rinterface.o rinterface_extra.o rrandom.o +GLUE_C_SOURCES=rinterface.o rinterface_extra.o rrandom.o uuid.o diff --git a/src/sources-igraph.mk b/src/sources-igraph.mk index 7e03a751e3f..8cf31ee3e5f 100644 --- a/src/sources-igraph.mk +++ b/src/sources-igraph.mk @@ -1 +1 @@ -IGRAPH_SOURCES=vendor/arpack/dgetv0.o vendor/arpack/dlaqrb.o vendor/arpack/dmout.o vendor/arpack/dnaitr.o vendor/arpack/dnapps.o vendor/arpack/dnaup2.o vendor/arpack/dnaupd.o vendor/arpack/dnconv.o vendor/arpack/dneigh.o vendor/arpack/dneupd.o vendor/arpack/dngets.o vendor/arpack/dsaitr.o vendor/arpack/dsapps.o vendor/arpack/dsaup2.o vendor/arpack/dsaupd.o vendor/arpack/dsconv.o vendor/arpack/dseigt.o vendor/arpack/dsesrt.o vendor/arpack/dseupd.o vendor/arpack/dsgets.o vendor/arpack/dsortc.o vendor/arpack/dsortr.o vendor/arpack/dstatn.o vendor/arpack/dstats.o vendor/arpack/dstqrb.o vendor/arpack/dvout.o vendor/arpack/ivout.o vendor/arpack/second.o vendor/arpack/wrap.o vendor/cigraph/src/centrality/betweenness.o vendor/cigraph/src/centrality/centrality_other.o vendor/cigraph/src/centrality/centralization.o vendor/cigraph/src/centrality/closeness.o vendor/cigraph/src/centrality/coreness.o vendor/cigraph/src/centrality/eigenvector.o vendor/cigraph/src/centrality/hub_authority.o vendor/cigraph/src/centrality/pagerank.o vendor/cigraph/src/centrality/prpack.o vendor/cigraph/src/centrality/prpack/prpack_base_graph.o vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_ge_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_gs_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_scc_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_schur_graph.o vendor/cigraph/src/centrality/prpack/prpack_result.o vendor/cigraph/src/centrality/prpack/prpack_solver.o vendor/cigraph/src/centrality/prpack/prpack_utils.o vendor/cigraph/src/centrality/truss.o vendor/cigraph/src/cliques/cliquer/cliquer.o vendor/cigraph/src/cliques/cliquer/cliquer_graph.o vendor/cigraph/src/cliques/cliquer/reorder.o vendor/cigraph/src/cliques/cliquer_wrapper.o vendor/cigraph/src/cliques/cliques.o vendor/cigraph/src/cliques/glet.o vendor/cigraph/src/cliques/maximal_cliques.o vendor/cigraph/src/community/community_misc.o vendor/cigraph/src/community/edge_betweenness.o vendor/cigraph/src/community/fast_modularity.o vendor/cigraph/src/community/fluid.o vendor/cigraph/src/community/infomap.o vendor/cigraph/src/community/label_propagation.o vendor/cigraph/src/community/leading_eigenvector.o vendor/cigraph/src/community/leiden.o vendor/cigraph/src/community/louvain.o vendor/cigraph/src/community/modularity.o vendor/cigraph/src/community/optimal_modularity.o vendor/cigraph/src/community/spinglass/NetDataTypes.o vendor/cigraph/src/community/spinglass/NetRoutines.o vendor/cigraph/src/community/spinglass/clustertool.o vendor/cigraph/src/community/spinglass/pottsmodel_2.o vendor/cigraph/src/community/voronoi.o vendor/cigraph/src/community/walktrap/walktrap.o vendor/cigraph/src/community/walktrap/walktrap_communities.o vendor/cigraph/src/community/walktrap/walktrap_graph.o vendor/cigraph/src/community/walktrap/walktrap_heap.o vendor/cigraph/src/connectivity/cohesive_blocks.o vendor/cigraph/src/connectivity/components.o vendor/cigraph/src/connectivity/percolation.o vendor/cigraph/src/connectivity/reachability.o vendor/cigraph/src/connectivity/separators.o vendor/cigraph/src/constructors/adjacency.o vendor/cigraph/src/constructors/atlas.o vendor/cigraph/src/constructors/basic_constructors.o vendor/cigraph/src/constructors/circulant.o vendor/cigraph/src/constructors/de_bruijn.o vendor/cigraph/src/constructors/famous.o vendor/cigraph/src/constructors/full.o vendor/cigraph/src/constructors/generalized_petersen.o vendor/cigraph/src/constructors/kautz.o vendor/cigraph/src/constructors/lattices.o vendor/cigraph/src/constructors/lcf.o vendor/cigraph/src/constructors/linegraph.o vendor/cigraph/src/constructors/mycielskian.o vendor/cigraph/src/constructors/prufer.o vendor/cigraph/src/constructors/regular.o vendor/cigraph/src/constructors/trees.o vendor/cigraph/src/core/bitset.o vendor/cigraph/src/core/bitset_list.o vendor/cigraph/src/core/buckets.o vendor/cigraph/src/core/cutheap.o vendor/cigraph/src/core/dqueue.o vendor/cigraph/src/core/error.o vendor/cigraph/src/core/estack.o vendor/cigraph/src/core/fixed_vectorlist.o vendor/cigraph/src/core/genheap.o vendor/cigraph/src/core/grid.o vendor/cigraph/src/core/heap.o vendor/cigraph/src/core/indheap.o vendor/cigraph/src/core/interruption.o vendor/cigraph/src/core/marked_queue.o vendor/cigraph/src/core/matrix.o vendor/cigraph/src/core/matrix_list.o vendor/cigraph/src/core/memory.o vendor/cigraph/src/core/printing.o vendor/cigraph/src/core/progress.o vendor/cigraph/src/core/psumtree.o vendor/cigraph/src/core/set.o vendor/cigraph/src/core/setup.o vendor/cigraph/src/core/sparsemat.o vendor/cigraph/src/core/stack.o vendor/cigraph/src/core/statusbar.o vendor/cigraph/src/core/strvector.o vendor/cigraph/src/core/trie.o vendor/cigraph/src/core/vector.o vendor/cigraph/src/core/vector_list.o vendor/cigraph/src/core/vector_ptr.o vendor/cigraph/src/cycles/simple_cycles.o vendor/cigraph/src/flow/flow.o vendor/cigraph/src/flow/flow_conversion.o vendor/cigraph/src/flow/st-cuts.o vendor/cigraph/src/games/barabasi.o vendor/cigraph/src/games/callaway_traits.o vendor/cigraph/src/games/chung_lu.o vendor/cigraph/src/games/citations.o vendor/cigraph/src/games/correlated.o vendor/cigraph/src/games/degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_random.o vendor/cigraph/src/games/dotproduct.o vendor/cigraph/src/games/erdos_renyi.o vendor/cigraph/src/games/establishment.o vendor/cigraph/src/games/forestfire.o vendor/cigraph/src/games/grg.o vendor/cigraph/src/games/growing_random.o vendor/cigraph/src/games/islands.o vendor/cigraph/src/games/k_regular.o vendor/cigraph/src/games/preference.o vendor/cigraph/src/games/recent_degree.o vendor/cigraph/src/games/sbm.o vendor/cigraph/src/games/static_fitness.o vendor/cigraph/src/games/tree.o vendor/cigraph/src/games/watts_strogatz.o vendor/cigraph/src/graph/adjlist.o vendor/cigraph/src/graph/attributes.o vendor/cigraph/src/graph/basic_query.o vendor/cigraph/src/graph/caching.o vendor/cigraph/src/graph/cattributes.o vendor/cigraph/src/graph/graph_list.o vendor/cigraph/src/graph/iterators.o vendor/cigraph/src/graph/type_common.o vendor/cigraph/src/graph/type_indexededgelist.o vendor/cigraph/src/graph/visitors.o vendor/cigraph/src/hrg/hrg.o vendor/cigraph/src/hrg/hrg_types.o vendor/cigraph/src/internal/glpk_support.o vendor/cigraph/src/internal/hacks.o vendor/cigraph/src/internal/lsap.o vendor/cigraph/src/internal/qsort.o vendor/cigraph/src/internal/qsort_r.o vendor/cigraph/src/internal/utils.o vendor/cigraph/src/io/dimacs.o vendor/cigraph/src/io/dl.o vendor/cigraph/src/io/dot.o vendor/cigraph/src/io/edgelist.o vendor/cigraph/src/io/gml-tree.o vendor/cigraph/src/io/gml.o vendor/cigraph/src/io/graphdb.o vendor/cigraph/src/io/graphml.o vendor/cigraph/src/io/leda.o vendor/cigraph/src/io/lgl.o vendor/cigraph/src/io/ncol.o vendor/cigraph/src/io/pajek.o vendor/cigraph/src/io/parse_utils.o vendor/cigraph/src/isomorphism/bliss.o vendor/cigraph/src/isomorphism/bliss/defs.o vendor/cigraph/src/isomorphism/bliss/graph.o vendor/cigraph/src/isomorphism/bliss/heap.o vendor/cigraph/src/isomorphism/bliss/orbit.o vendor/cigraph/src/isomorphism/bliss/partition.o vendor/cigraph/src/isomorphism/bliss/uintseqhash.o vendor/cigraph/src/isomorphism/bliss/utils.o vendor/cigraph/src/isomorphism/isoclasses.o vendor/cigraph/src/isomorphism/isomorphism_misc.o vendor/cigraph/src/isomorphism/lad.o vendor/cigraph/src/isomorphism/queries.o vendor/cigraph/src/isomorphism/vf2.o vendor/cigraph/src/layout/align.o vendor/cigraph/src/layout/circular.o vendor/cigraph/src/layout/davidson_harel.o vendor/cigraph/src/layout/drl/DensityGrid.o vendor/cigraph/src/layout/drl/DensityGrid_3d.o vendor/cigraph/src/layout/drl/drl_graph.o vendor/cigraph/src/layout/drl/drl_graph_3d.o vendor/cigraph/src/layout/drl/drl_layout.o vendor/cigraph/src/layout/drl/drl_layout_3d.o vendor/cigraph/src/layout/drl/drl_parse.o vendor/cigraph/src/layout/fruchterman_reingold.o vendor/cigraph/src/layout/gem.o vendor/cigraph/src/layout/graphopt.o vendor/cigraph/src/layout/kamada_kawai.o vendor/cigraph/src/layout/large_graph.o vendor/cigraph/src/layout/layout_bipartite.o vendor/cigraph/src/layout/layout_grid.o vendor/cigraph/src/layout/layout_random.o vendor/cigraph/src/layout/mds.o vendor/cigraph/src/layout/merge_dla.o vendor/cigraph/src/layout/merge_grid.o vendor/cigraph/src/layout/reingold_tilford.o vendor/cigraph/src/layout/sugiyama.o vendor/cigraph/src/layout/umap.o vendor/cigraph/src/linalg/arpack.o vendor/cigraph/src/linalg/blas.o vendor/cigraph/src/linalg/eigen.o vendor/cigraph/src/linalg/lapack.o vendor/cigraph/src/math/complex.o vendor/cigraph/src/math/safe_intop.o vendor/cigraph/src/math/utils.o vendor/cigraph/src/misc/bipartite.o vendor/cigraph/src/misc/chordality.o vendor/cigraph/src/misc/cocitation.o vendor/cigraph/src/misc/coloring.o vendor/cigraph/src/misc/conversion.o vendor/cigraph/src/misc/cycle_bases.o vendor/cigraph/src/misc/degree_sequence.o vendor/cigraph/src/misc/embedding.o vendor/cigraph/src/misc/feedback_arc_set.o vendor/cigraph/src/misc/graphicality.o vendor/cigraph/src/misc/matching.o vendor/cigraph/src/misc/mixing.o vendor/cigraph/src/misc/motifs.o vendor/cigraph/src/misc/order_cycle.o vendor/cigraph/src/misc/other.o vendor/cigraph/src/misc/power_law_fit.o vendor/cigraph/src/misc/scan.o vendor/cigraph/src/misc/sir.o vendor/cigraph/src/misc/spanning_trees.o vendor/cigraph/src/operators/add_edge.o vendor/cigraph/src/operators/complementer.o vendor/cigraph/src/operators/compose.o vendor/cigraph/src/operators/connect_neighborhood.o vendor/cigraph/src/operators/contract.o vendor/cigraph/src/operators/difference.o vendor/cigraph/src/operators/disjoint_union.o vendor/cigraph/src/operators/intersection.o vendor/cigraph/src/operators/join.o vendor/cigraph/src/operators/misc_internal.o vendor/cigraph/src/operators/permute.o vendor/cigraph/src/operators/products.o vendor/cigraph/src/operators/reverse.o vendor/cigraph/src/operators/rewire.o vendor/cigraph/src/operators/rewire_edges.o vendor/cigraph/src/operators/simplify.o vendor/cigraph/src/operators/subgraph.o vendor/cigraph/src/operators/union.o vendor/cigraph/src/paths/all_shortest_paths.o vendor/cigraph/src/paths/astar.o vendor/cigraph/src/paths/bellman_ford.o vendor/cigraph/src/paths/dijkstra.o vendor/cigraph/src/paths/distances.o vendor/cigraph/src/paths/eulerian.o vendor/cigraph/src/paths/floyd_warshall.o vendor/cigraph/src/paths/histogram.o vendor/cigraph/src/paths/johnson.o vendor/cigraph/src/paths/random_walk.o vendor/cigraph/src/paths/shortest_paths.o vendor/cigraph/src/paths/simple_paths.o vendor/cigraph/src/paths/sparsifier.o vendor/cigraph/src/paths/unweighted.o vendor/cigraph/src/paths/voronoi.o vendor/cigraph/src/paths/widest_paths.o vendor/cigraph/src/properties/basic_properties.o vendor/cigraph/src/properties/complete.o vendor/cigraph/src/properties/constraint.o vendor/cigraph/src/properties/convergence_degree.o vendor/cigraph/src/properties/dag.o vendor/cigraph/src/properties/degrees.o vendor/cigraph/src/properties/ecc.o vendor/cigraph/src/properties/girth.o vendor/cigraph/src/properties/loops.o vendor/cigraph/src/properties/multiplicity.o vendor/cigraph/src/properties/neighborhood.o vendor/cigraph/src/properties/perfect.o vendor/cigraph/src/properties/rich_club.o vendor/cigraph/src/properties/spectral.o vendor/cigraph/src/properties/trees.o vendor/cigraph/src/properties/triangles.o vendor/cigraph/src/random/random.o vendor/cigraph/src/random/random_device.o vendor/cigraph/src/random/rng_glibc2.o vendor/cigraph/src/random/rng_mt19937.o vendor/cigraph/src/random/rng_pcg32.o vendor/cigraph/src/random/rng_pcg64.o vendor/cigraph/src/random/sampling.o vendor/cigraph/src/spatial/nearest_neighbor.o vendor/cigraph/src/version.o vendor/cigraph/vendor/cs/cs_add.o vendor/cigraph/vendor/cs/cs_amd.o vendor/cigraph/vendor/cs/cs_chol.o vendor/cigraph/vendor/cs/cs_cholsol.o vendor/cigraph/vendor/cs/cs_compress.o vendor/cigraph/vendor/cs/cs_counts.o vendor/cigraph/vendor/cs/cs_cumsum.o vendor/cigraph/vendor/cs/cs_dfs.o vendor/cigraph/vendor/cs/cs_dmperm.o vendor/cigraph/vendor/cs/cs_droptol.o vendor/cigraph/vendor/cs/cs_dropzeros.o vendor/cigraph/vendor/cs/cs_dupl.o vendor/cigraph/vendor/cs/cs_entry.o vendor/cigraph/vendor/cs/cs_ereach.o vendor/cigraph/vendor/cs/cs_etree.o vendor/cigraph/vendor/cs/cs_fkeep.o vendor/cigraph/vendor/cs/cs_gaxpy.o vendor/cigraph/vendor/cs/cs_happly.o vendor/cigraph/vendor/cs/cs_house.o vendor/cigraph/vendor/cs/cs_ipvec.o vendor/cigraph/vendor/cs/cs_leaf.o vendor/cigraph/vendor/cs/cs_load.o vendor/cigraph/vendor/cs/cs_lsolve.o vendor/cigraph/vendor/cs/cs_ltsolve.o vendor/cigraph/vendor/cs/cs_lu.o vendor/cigraph/vendor/cs/cs_lusol.o vendor/cigraph/vendor/cs/cs_malloc.o vendor/cigraph/vendor/cs/cs_maxtrans.o vendor/cigraph/vendor/cs/cs_multiply.o vendor/cigraph/vendor/cs/cs_norm.o vendor/cigraph/vendor/cs/cs_permute.o vendor/cigraph/vendor/cs/cs_pinv.o vendor/cigraph/vendor/cs/cs_post.o vendor/cigraph/vendor/cs/cs_print.o vendor/cigraph/vendor/cs/cs_pvec.o vendor/cigraph/vendor/cs/cs_qr.o vendor/cigraph/vendor/cs/cs_qrsol.o vendor/cigraph/vendor/cs/cs_randperm.o vendor/cigraph/vendor/cs/cs_reach.o vendor/cigraph/vendor/cs/cs_scatter.o vendor/cigraph/vendor/cs/cs_scc.o vendor/cigraph/vendor/cs/cs_schol.o vendor/cigraph/vendor/cs/cs_spsolve.o vendor/cigraph/vendor/cs/cs_sqr.o vendor/cigraph/vendor/cs/cs_symperm.o vendor/cigraph/vendor/cs/cs_tdfs.o vendor/cigraph/vendor/cs/cs_transpose.o vendor/cigraph/vendor/cs/cs_updown.o vendor/cigraph/vendor/cs/cs_usolve.o vendor/cigraph/vendor/cs/cs_util.o vendor/cigraph/vendor/cs/cs_utsolve.o vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.o vendor/cigraph/vendor/infomap/src/core/InfoEdge.o vendor/cigraph/vendor/infomap/src/core/InfoNode.o vendor/cigraph/vendor/infomap/src/core/InfomapBase.o vendor/cigraph/vendor/infomap/src/core/MemMapEquation.o vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.o vendor/cigraph/vendor/infomap/src/core/StateNetwork.o vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.o vendor/cigraph/vendor/infomap/src/io/ClusterMap.o vendor/cigraph/vendor/infomap/src/io/Config.o vendor/cigraph/vendor/infomap/src/io/Network.o vendor/cigraph/vendor/infomap/src/io/Output.o vendor/cigraph/vendor/infomap/src/io/ProgramInterface.o vendor/cigraph/vendor/infomap/src/utils/FileURI.o vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.o vendor/cigraph/vendor/infomap/src/utils/Log.o vendor/cigraph/vendor/pcg/pcg-advance-128.o vendor/cigraph/vendor/pcg/pcg-advance-64.o vendor/cigraph/vendor/pcg/pcg-output-128.o vendor/cigraph/vendor/pcg/pcg-output-32.o vendor/cigraph/vendor/pcg/pcg-output-64.o vendor/cigraph/vendor/pcg/pcg-rngs-128.o vendor/cigraph/vendor/pcg/pcg-rngs-64.o vendor/cigraph/vendor/plfit/gss.o vendor/cigraph/vendor/plfit/hzeta.o vendor/cigraph/vendor/plfit/kolmogorov.o vendor/cigraph/vendor/plfit/lbfgs.o vendor/cigraph/vendor/plfit/mt.o vendor/cigraph/vendor/plfit/options.o vendor/cigraph/vendor/plfit/plfit.o vendor/cigraph/vendor/plfit/plfit_error.o vendor/cigraph/vendor/plfit/rbinom.o vendor/cigraph/vendor/plfit/sampling.o vendor/io/dl-lexer.o vendor/io/dl-parser.o vendor/io/gml-lexer.o vendor/io/gml-parser.o vendor/io/lgl-lexer.o vendor/io/lgl-parser.o vendor/io/ncol-lexer.o vendor/io/ncol-parser.o vendor/io/pajek-lexer.o vendor/io/pajek-parser.o vendor/simpleraytracer/Color.o vendor/simpleraytracer/Light.o vendor/simpleraytracer/Point.o vendor/simpleraytracer/Ray.o vendor/simpleraytracer/RayTracer.o vendor/simpleraytracer/RayVector.o vendor/simpleraytracer/Shape.o vendor/simpleraytracer/Sphere.o vendor/simpleraytracer/Triangle.o vendor/simpleraytracer/unit_limiter.o vendor/uuid/R.o vendor/uuid/clear.o vendor/uuid/compare.o vendor/uuid/copy.o vendor/uuid/gen_uuid.o vendor/uuid/isnull.o vendor/uuid/pack.o vendor/uuid/parse.o vendor/uuid/unpack.o vendor/uuid/unparse.o +IGRAPH_SOURCES=vendor/arpack/dgetv0.o vendor/arpack/dlaqrb.o vendor/arpack/dmout.o vendor/arpack/dnaitr.o vendor/arpack/dnapps.o vendor/arpack/dnaup2.o vendor/arpack/dnaupd.o vendor/arpack/dnconv.o vendor/arpack/dneigh.o vendor/arpack/dneupd.o vendor/arpack/dngets.o vendor/arpack/dsaitr.o vendor/arpack/dsapps.o vendor/arpack/dsaup2.o vendor/arpack/dsaupd.o vendor/arpack/dsconv.o vendor/arpack/dseigt.o vendor/arpack/dsesrt.o vendor/arpack/dseupd.o vendor/arpack/dsgets.o vendor/arpack/dsortc.o vendor/arpack/dsortr.o vendor/arpack/dstatn.o vendor/arpack/dstats.o vendor/arpack/dstqrb.o vendor/arpack/dvout.o vendor/arpack/ivout.o vendor/arpack/second.o vendor/arpack/wrap.o vendor/cigraph/src/centrality/betweenness.o vendor/cigraph/src/centrality/centrality_other.o vendor/cigraph/src/centrality/centralization.o vendor/cigraph/src/centrality/closeness.o vendor/cigraph/src/centrality/coreness.o vendor/cigraph/src/centrality/eigenvector.o vendor/cigraph/src/centrality/hub_authority.o vendor/cigraph/src/centrality/pagerank.o vendor/cigraph/src/centrality/prpack.o vendor/cigraph/src/centrality/prpack/prpack_base_graph.o vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_ge_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_gs_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_scc_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_schur_graph.o vendor/cigraph/src/centrality/prpack/prpack_result.o vendor/cigraph/src/centrality/prpack/prpack_solver.o vendor/cigraph/src/centrality/prpack/prpack_utils.o vendor/cigraph/src/centrality/truss.o vendor/cigraph/src/cliques/cliquer/cliquer.o vendor/cigraph/src/cliques/cliquer/cliquer_graph.o vendor/cigraph/src/cliques/cliquer/reorder.o vendor/cigraph/src/cliques/cliquer_wrapper.o vendor/cigraph/src/cliques/cliques.o vendor/cigraph/src/cliques/glet.o vendor/cigraph/src/cliques/maximal_cliques.o vendor/cigraph/src/community/community_misc.o vendor/cigraph/src/community/edge_betweenness.o vendor/cigraph/src/community/fast_modularity.o vendor/cigraph/src/community/fluid.o vendor/cigraph/src/community/infomap.o vendor/cigraph/src/community/label_propagation.o vendor/cigraph/src/community/leading_eigenvector.o vendor/cigraph/src/community/leiden.o vendor/cigraph/src/community/louvain.o vendor/cigraph/src/community/modularity.o vendor/cigraph/src/community/optimal_modularity.o vendor/cigraph/src/community/spinglass/NetDataTypes.o vendor/cigraph/src/community/spinglass/NetRoutines.o vendor/cigraph/src/community/spinglass/clustertool.o vendor/cigraph/src/community/spinglass/pottsmodel_2.o vendor/cigraph/src/community/voronoi.o vendor/cigraph/src/community/walktrap/walktrap.o vendor/cigraph/src/community/walktrap/walktrap_communities.o vendor/cigraph/src/community/walktrap/walktrap_graph.o vendor/cigraph/src/community/walktrap/walktrap_heap.o vendor/cigraph/src/connectivity/cohesive_blocks.o vendor/cigraph/src/connectivity/components.o vendor/cigraph/src/connectivity/percolation.o vendor/cigraph/src/connectivity/reachability.o vendor/cigraph/src/connectivity/separators.o vendor/cigraph/src/constructors/adjacency.o vendor/cigraph/src/constructors/atlas.o vendor/cigraph/src/constructors/basic_constructors.o vendor/cigraph/src/constructors/circulant.o vendor/cigraph/src/constructors/de_bruijn.o vendor/cigraph/src/constructors/famous.o vendor/cigraph/src/constructors/full.o vendor/cigraph/src/constructors/generalized_petersen.o vendor/cigraph/src/constructors/kautz.o vendor/cigraph/src/constructors/lattices.o vendor/cigraph/src/constructors/lcf.o vendor/cigraph/src/constructors/linegraph.o vendor/cigraph/src/constructors/mycielskian.o vendor/cigraph/src/constructors/prufer.o vendor/cigraph/src/constructors/regular.o vendor/cigraph/src/constructors/trees.o vendor/cigraph/src/core/bitset.o vendor/cigraph/src/core/bitset_list.o vendor/cigraph/src/core/buckets.o vendor/cigraph/src/core/cutheap.o vendor/cigraph/src/core/dqueue.o vendor/cigraph/src/core/error.o vendor/cigraph/src/core/estack.o vendor/cigraph/src/core/fixed_vectorlist.o vendor/cigraph/src/core/genheap.o vendor/cigraph/src/core/grid.o vendor/cigraph/src/core/heap.o vendor/cigraph/src/core/indheap.o vendor/cigraph/src/core/interruption.o vendor/cigraph/src/core/marked_queue.o vendor/cigraph/src/core/matrix.o vendor/cigraph/src/core/matrix_list.o vendor/cigraph/src/core/memory.o vendor/cigraph/src/core/printing.o vendor/cigraph/src/core/progress.o vendor/cigraph/src/core/psumtree.o vendor/cigraph/src/core/set.o vendor/cigraph/src/core/setup.o vendor/cigraph/src/core/sparsemat.o vendor/cigraph/src/core/stack.o vendor/cigraph/src/core/statusbar.o vendor/cigraph/src/core/strvector.o vendor/cigraph/src/core/trie.o vendor/cigraph/src/core/vector.o vendor/cigraph/src/core/vector_list.o vendor/cigraph/src/core/vector_ptr.o vendor/cigraph/src/cycles/simple_cycles.o vendor/cigraph/src/flow/flow.o vendor/cigraph/src/flow/flow_conversion.o vendor/cigraph/src/flow/st-cuts.o vendor/cigraph/src/games/barabasi.o vendor/cigraph/src/games/callaway_traits.o vendor/cigraph/src/games/chung_lu.o vendor/cigraph/src/games/citations.o vendor/cigraph/src/games/correlated.o vendor/cigraph/src/games/degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_random.o vendor/cigraph/src/games/dotproduct.o vendor/cigraph/src/games/erdos_renyi.o vendor/cigraph/src/games/establishment.o vendor/cigraph/src/games/forestfire.o vendor/cigraph/src/games/grg.o vendor/cigraph/src/games/growing_random.o vendor/cigraph/src/games/islands.o vendor/cigraph/src/games/k_regular.o vendor/cigraph/src/games/preference.o vendor/cigraph/src/games/recent_degree.o vendor/cigraph/src/games/sbm.o vendor/cigraph/src/games/static_fitness.o vendor/cigraph/src/games/tree.o vendor/cigraph/src/games/watts_strogatz.o vendor/cigraph/src/graph/adjlist.o vendor/cigraph/src/graph/attributes.o vendor/cigraph/src/graph/basic_query.o vendor/cigraph/src/graph/caching.o vendor/cigraph/src/graph/cattributes.o vendor/cigraph/src/graph/graph_list.o vendor/cigraph/src/graph/iterators.o vendor/cigraph/src/graph/type_common.o vendor/cigraph/src/graph/type_indexededgelist.o vendor/cigraph/src/graph/visitors.o vendor/cigraph/src/hrg/hrg.o vendor/cigraph/src/hrg/hrg_types.o vendor/cigraph/src/internal/glpk_support.o vendor/cigraph/src/internal/hacks.o vendor/cigraph/src/internal/lsap.o vendor/cigraph/src/internal/qsort.o vendor/cigraph/src/internal/qsort_r.o vendor/cigraph/src/internal/utils.o vendor/cigraph/src/io/dimacs.o vendor/cigraph/src/io/dl.o vendor/cigraph/src/io/dot.o vendor/cigraph/src/io/edgelist.o vendor/cigraph/src/io/gml-tree.o vendor/cigraph/src/io/gml.o vendor/cigraph/src/io/graphdb.o vendor/cigraph/src/io/graphml.o vendor/cigraph/src/io/leda.o vendor/cigraph/src/io/lgl.o vendor/cigraph/src/io/ncol.o vendor/cigraph/src/io/pajek.o vendor/cigraph/src/io/parse_utils.o vendor/cigraph/src/isomorphism/bliss.o vendor/cigraph/src/isomorphism/bliss/defs.o vendor/cigraph/src/isomorphism/bliss/graph.o vendor/cigraph/src/isomorphism/bliss/heap.o vendor/cigraph/src/isomorphism/bliss/orbit.o vendor/cigraph/src/isomorphism/bliss/partition.o vendor/cigraph/src/isomorphism/bliss/uintseqhash.o vendor/cigraph/src/isomorphism/bliss/utils.o vendor/cigraph/src/isomorphism/isoclasses.o vendor/cigraph/src/isomorphism/isomorphism_misc.o vendor/cigraph/src/isomorphism/lad.o vendor/cigraph/src/isomorphism/queries.o vendor/cigraph/src/isomorphism/vf2.o vendor/cigraph/src/layout/align.o vendor/cigraph/src/layout/circular.o vendor/cigraph/src/layout/davidson_harel.o vendor/cigraph/src/layout/drl/DensityGrid.o vendor/cigraph/src/layout/drl/DensityGrid_3d.o vendor/cigraph/src/layout/drl/drl_graph.o vendor/cigraph/src/layout/drl/drl_graph_3d.o vendor/cigraph/src/layout/drl/drl_layout.o vendor/cigraph/src/layout/drl/drl_layout_3d.o vendor/cigraph/src/layout/drl/drl_parse.o vendor/cigraph/src/layout/fruchterman_reingold.o vendor/cigraph/src/layout/gem.o vendor/cigraph/src/layout/graphopt.o vendor/cigraph/src/layout/kamada_kawai.o vendor/cigraph/src/layout/large_graph.o vendor/cigraph/src/layout/layout_bipartite.o vendor/cigraph/src/layout/layout_grid.o vendor/cigraph/src/layout/layout_random.o vendor/cigraph/src/layout/mds.o vendor/cigraph/src/layout/merge_dla.o vendor/cigraph/src/layout/merge_grid.o vendor/cigraph/src/layout/reingold_tilford.o vendor/cigraph/src/layout/sugiyama.o vendor/cigraph/src/layout/umap.o vendor/cigraph/src/linalg/arpack.o vendor/cigraph/src/linalg/blas.o vendor/cigraph/src/linalg/eigen.o vendor/cigraph/src/linalg/lapack.o vendor/cigraph/src/math/complex.o vendor/cigraph/src/math/safe_intop.o vendor/cigraph/src/math/utils.o vendor/cigraph/src/misc/bipartite.o vendor/cigraph/src/misc/chordality.o vendor/cigraph/src/misc/cocitation.o vendor/cigraph/src/misc/coloring.o vendor/cigraph/src/misc/conversion.o vendor/cigraph/src/misc/cycle_bases.o vendor/cigraph/src/misc/degree_sequence.o vendor/cigraph/src/misc/embedding.o vendor/cigraph/src/misc/feedback_arc_set.o vendor/cigraph/src/misc/graphicality.o vendor/cigraph/src/misc/matching.o vendor/cigraph/src/misc/mixing.o vendor/cigraph/src/misc/motifs.o vendor/cigraph/src/misc/order_cycle.o vendor/cigraph/src/misc/other.o vendor/cigraph/src/misc/power_law_fit.o vendor/cigraph/src/misc/scan.o vendor/cigraph/src/misc/sir.o vendor/cigraph/src/misc/spanning_trees.o vendor/cigraph/src/operators/add_edge.o vendor/cigraph/src/operators/complementer.o vendor/cigraph/src/operators/compose.o vendor/cigraph/src/operators/connect_neighborhood.o vendor/cigraph/src/operators/contract.o vendor/cigraph/src/operators/difference.o vendor/cigraph/src/operators/disjoint_union.o vendor/cigraph/src/operators/intersection.o vendor/cigraph/src/operators/join.o vendor/cigraph/src/operators/misc_internal.o vendor/cigraph/src/operators/permute.o vendor/cigraph/src/operators/products.o vendor/cigraph/src/operators/reverse.o vendor/cigraph/src/operators/rewire.o vendor/cigraph/src/operators/rewire_edges.o vendor/cigraph/src/operators/simplify.o vendor/cigraph/src/operators/subgraph.o vendor/cigraph/src/operators/union.o vendor/cigraph/src/paths/all_shortest_paths.o vendor/cigraph/src/paths/astar.o vendor/cigraph/src/paths/bellman_ford.o vendor/cigraph/src/paths/dijkstra.o vendor/cigraph/src/paths/distances.o vendor/cigraph/src/paths/eulerian.o vendor/cigraph/src/paths/floyd_warshall.o vendor/cigraph/src/paths/histogram.o vendor/cigraph/src/paths/johnson.o vendor/cigraph/src/paths/random_walk.o vendor/cigraph/src/paths/shortest_paths.o vendor/cigraph/src/paths/simple_paths.o vendor/cigraph/src/paths/sparsifier.o vendor/cigraph/src/paths/unweighted.o vendor/cigraph/src/paths/voronoi.o vendor/cigraph/src/paths/widest_paths.o vendor/cigraph/src/properties/basic_properties.o vendor/cigraph/src/properties/complete.o vendor/cigraph/src/properties/constraint.o vendor/cigraph/src/properties/convergence_degree.o vendor/cigraph/src/properties/dag.o vendor/cigraph/src/properties/degrees.o vendor/cigraph/src/properties/ecc.o vendor/cigraph/src/properties/girth.o vendor/cigraph/src/properties/loops.o vendor/cigraph/src/properties/multiplicity.o vendor/cigraph/src/properties/neighborhood.o vendor/cigraph/src/properties/perfect.o vendor/cigraph/src/properties/rich_club.o vendor/cigraph/src/properties/spectral.o vendor/cigraph/src/properties/trees.o vendor/cigraph/src/properties/triangles.o vendor/cigraph/src/random/random.o vendor/cigraph/src/random/random_device.o vendor/cigraph/src/random/rng_glibc2.o vendor/cigraph/src/random/rng_mt19937.o vendor/cigraph/src/random/rng_pcg32.o vendor/cigraph/src/random/rng_pcg64.o vendor/cigraph/src/random/sampling.o vendor/cigraph/src/spatial/nearest_neighbor.o vendor/cigraph/src/version.o vendor/cigraph/vendor/cs/cs_add.o vendor/cigraph/vendor/cs/cs_amd.o vendor/cigraph/vendor/cs/cs_chol.o vendor/cigraph/vendor/cs/cs_cholsol.o vendor/cigraph/vendor/cs/cs_compress.o vendor/cigraph/vendor/cs/cs_counts.o vendor/cigraph/vendor/cs/cs_cumsum.o vendor/cigraph/vendor/cs/cs_dfs.o vendor/cigraph/vendor/cs/cs_dmperm.o vendor/cigraph/vendor/cs/cs_droptol.o vendor/cigraph/vendor/cs/cs_dropzeros.o vendor/cigraph/vendor/cs/cs_dupl.o vendor/cigraph/vendor/cs/cs_entry.o vendor/cigraph/vendor/cs/cs_ereach.o vendor/cigraph/vendor/cs/cs_etree.o vendor/cigraph/vendor/cs/cs_fkeep.o vendor/cigraph/vendor/cs/cs_gaxpy.o vendor/cigraph/vendor/cs/cs_happly.o vendor/cigraph/vendor/cs/cs_house.o vendor/cigraph/vendor/cs/cs_ipvec.o vendor/cigraph/vendor/cs/cs_leaf.o vendor/cigraph/vendor/cs/cs_load.o vendor/cigraph/vendor/cs/cs_lsolve.o vendor/cigraph/vendor/cs/cs_ltsolve.o vendor/cigraph/vendor/cs/cs_lu.o vendor/cigraph/vendor/cs/cs_lusol.o vendor/cigraph/vendor/cs/cs_malloc.o vendor/cigraph/vendor/cs/cs_maxtrans.o vendor/cigraph/vendor/cs/cs_multiply.o vendor/cigraph/vendor/cs/cs_norm.o vendor/cigraph/vendor/cs/cs_permute.o vendor/cigraph/vendor/cs/cs_pinv.o vendor/cigraph/vendor/cs/cs_post.o vendor/cigraph/vendor/cs/cs_print.o vendor/cigraph/vendor/cs/cs_pvec.o vendor/cigraph/vendor/cs/cs_qr.o vendor/cigraph/vendor/cs/cs_qrsol.o vendor/cigraph/vendor/cs/cs_randperm.o vendor/cigraph/vendor/cs/cs_reach.o vendor/cigraph/vendor/cs/cs_scatter.o vendor/cigraph/vendor/cs/cs_scc.o vendor/cigraph/vendor/cs/cs_schol.o vendor/cigraph/vendor/cs/cs_spsolve.o vendor/cigraph/vendor/cs/cs_sqr.o vendor/cigraph/vendor/cs/cs_symperm.o vendor/cigraph/vendor/cs/cs_tdfs.o vendor/cigraph/vendor/cs/cs_transpose.o vendor/cigraph/vendor/cs/cs_updown.o vendor/cigraph/vendor/cs/cs_usolve.o vendor/cigraph/vendor/cs/cs_util.o vendor/cigraph/vendor/cs/cs_utsolve.o vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.o vendor/cigraph/vendor/infomap/src/core/InfoEdge.o vendor/cigraph/vendor/infomap/src/core/InfoNode.o vendor/cigraph/vendor/infomap/src/core/InfomapBase.o vendor/cigraph/vendor/infomap/src/core/MemMapEquation.o vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.o vendor/cigraph/vendor/infomap/src/core/StateNetwork.o vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.o vendor/cigraph/vendor/infomap/src/io/ClusterMap.o vendor/cigraph/vendor/infomap/src/io/Config.o vendor/cigraph/vendor/infomap/src/io/Network.o vendor/cigraph/vendor/infomap/src/io/Output.o vendor/cigraph/vendor/infomap/src/io/ProgramInterface.o vendor/cigraph/vendor/infomap/src/utils/FileURI.o vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.o vendor/cigraph/vendor/infomap/src/utils/Log.o vendor/cigraph/vendor/pcg/pcg-advance-128.o vendor/cigraph/vendor/pcg/pcg-advance-64.o vendor/cigraph/vendor/pcg/pcg-output-128.o vendor/cigraph/vendor/pcg/pcg-output-32.o vendor/cigraph/vendor/pcg/pcg-output-64.o vendor/cigraph/vendor/pcg/pcg-rngs-128.o vendor/cigraph/vendor/pcg/pcg-rngs-64.o vendor/cigraph/vendor/plfit/gss.o vendor/cigraph/vendor/plfit/hzeta.o vendor/cigraph/vendor/plfit/kolmogorov.o vendor/cigraph/vendor/plfit/lbfgs.o vendor/cigraph/vendor/plfit/mt.o vendor/cigraph/vendor/plfit/options.o vendor/cigraph/vendor/plfit/plfit.o vendor/cigraph/vendor/plfit/plfit_error.o vendor/cigraph/vendor/plfit/rbinom.o vendor/cigraph/vendor/plfit/sampling.o vendor/io/dl-lexer.o vendor/io/dl-parser.o vendor/io/gml-lexer.o vendor/io/gml-parser.o vendor/io/lgl-lexer.o vendor/io/lgl-parser.o vendor/io/ncol-lexer.o vendor/io/ncol-parser.o vendor/io/pajek-lexer.o vendor/io/pajek-parser.o vendor/simpleraytracer/Color.o vendor/simpleraytracer/Light.o vendor/simpleraytracer/Point.o vendor/simpleraytracer/Ray.o vendor/simpleraytracer/RayTracer.o vendor/simpleraytracer/RayVector.o vendor/simpleraytracer/Shape.o vendor/simpleraytracer/Sphere.o vendor/simpleraytracer/Triangle.o vendor/simpleraytracer/unit_limiter.o vendor/uuid/clear.o vendor/uuid/compare.o vendor/uuid/copy.o vendor/uuid/gen_uuid.o vendor/uuid/isnull.o vendor/uuid/pack.o vendor/uuid/parse.o vendor/uuid/unpack.o vendor/uuid/unparse.o diff --git a/src/vendor/uuid/R.c b/src/uuid.c similarity index 53% rename from src/vendor/uuid/R.c rename to src/uuid.c index b956b8d40a7..d2078c8db72 100644 --- a/src/vendor/uuid/R.c +++ b/src/uuid.c @@ -1,7 +1,11 @@ -#include "uuid.h" +#include "vendor/uuid/uuid.h" #include -#include "igraph_random.h" + +#define RNG_BEGIN() GetRNGstate() +#define RNG_END() PutRNGstate() +void GetRNGstate(void); +void PutRNGstate(void); SEXP UUID_gen(SEXP sTime) { @@ -11,11 +15,11 @@ SEXP UUID_gen(SEXP sTime) { char c[40]; int use_time = asInteger(sTime); if (use_time == TRUE) - uuid_generate_time(u); + uuid_generate_time(u); else if (use_time == FALSE) - uuid_generate_random(u); + uuid_generate_random(u); else - uuid_generate(u); + uuid_generate(u); uuid_unparse_lower(u, c); RNG_END(); diff --git a/src/uuid.dd b/src/uuid.dd new file mode 100644 index 00000000000..272f3e70166 --- /dev/null +++ b/src/uuid.dd @@ -0,0 +1,3 @@ +# Generated by deps.mk, do not edit by hand and do not add dependencies to system headers +uuid.o: \ + uuid.c \ From e7b367f5429e57d59464a070d00e74c1ab36b57e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 28 Aug 2025 11:23:19 +0200 Subject: [PATCH 004/154] Auto-generate R_igraph_incident --- R/aaa-auto.R | 19 +++++++++++ src/rinterface.c | 33 ++++++++++++++++++++ src/rinterface_extra.c | 27 ++-------------- src/vendor/cigraph/interfaces/functions.yaml | 1 + tools/stimulus/functions-R.yaml | 3 -- 5 files changed, 55 insertions(+), 28 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index 89acea8e617..5665e082215 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -81,6 +81,25 @@ get_all_eids_between_impl <- function(graph, from, to, directed=TRUE) { res } +incident_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once")) { + # Argument checks + ensure_igraph(graph) + vid <- as_igraph_vs(graph, vid) + if (length(vid) == 0) { + stop("No vertex was specified") + } + mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_incident, graph, vid-1, mode, loops) + if (igraph_opt("return.vs.es")) { + res <- create_es(graph, res) + } + res +} + wheel_impl <- function(n, mode=c("out", "in", "undirected", "mutual"), center=0) { # Argument checks n <- as.numeric(n) diff --git a/src/rinterface.c b/src/rinterface.c index 725059b995c..bc174a45ec6 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -222,6 +222,39 @@ SEXP R_igraph_get_all_eids_between(SEXP graph, SEXP from, SEXP to, SEXP directed return(r_result); } +/*-------------------------------------------/ +/ igraph_incident / +/-------------------------------------------*/ +SEXP R_igraph_incident(SEXP graph, SEXP vid, SEXP mode, SEXP loops) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_int_t c_eids; + igraph_integer_t c_vid; + igraph_neimode_t c_mode; + igraph_loops_t c_loops; + SEXP eids; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + IGRAPH_R_CHECK(igraph_vector_int_init(&c_eids, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_eids); + c_vid = (igraph_integer_t) REAL(vid)[0]; + c_mode = (igraph_neimode_t) Rf_asInteger(mode); + c_loops = (igraph_loops_t) Rf_asInteger(loops); + /* Call igraph */ + IGRAPH_R_CHECK(igraph_incident(&c_graph, &c_eids, c_vid, c_mode, c_loops)); + + /* Convert output */ + PROTECT(eids=R_igraph_vector_int_to_SEXPp1(&c_eids)); + igraph_vector_int_destroy(&c_eids); + IGRAPH_FINALLY_CLEAN(1); + r_result = eids; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_adjacency / /-------------------------------------------*/ diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index b54ec08f673..f2c323714d5 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -3908,29 +3908,6 @@ SEXP R_igraph_neighbors(SEXP graph, SEXP pvid, SEXP pmode) { return result; } -SEXP R_igraph_incident(SEXP graph, SEXP pvid, SEXP pmode) { - - igraph_t g; - igraph_vector_int_t neis; - SEXP result; - igraph_real_t vid; - igraph_neimode_t mode; - // FIXME: Expose - igraph_loops_t loops = IGRAPH_NO_LOOPS; - - igraph_vector_int_init(&neis, 0); - vid=REAL(pvid)[0]; - mode = (igraph_neimode_t) Rf_asInteger(pmode); - R_SEXP_to_igraph(graph, &g); - IGRAPH_R_CHECK(igraph_incident(&g, &neis, (igraph_integer_t) vid, mode, loops)); - - PROTECT(result=R_igraph_vector_int_to_SEXP(&neis)); - igraph_vector_int_destroy(&neis); - - UNPROTECT(1); - return result; -} - SEXP R_igraph_delete_edges(SEXP graph, SEXP edges) { igraph_es_t es; @@ -4593,7 +4570,7 @@ SEXP R_igraph_minimum_spanning_tree_unweighted(SEXP graph) { IGRAPH_R_CHECK(igraph_edges(&g, edge_set, &edges, false)); IGRAPH_FINALLY_PV(igraph_es_destroy, &edge_set); igraph_vector_int_destroy(&edges); - + igraph_t mst; IGRAPH_R_CHECK(igraph_subgraph_from_edges(&g, &mst, edge_set, true)); igraph_es_destroy(&edge_set); @@ -4625,7 +4602,7 @@ SEXP R_igraph_minimum_spanning_tree_prim(SEXP graph, SEXP pweights) { IGRAPH_R_CHECK(igraph_edges(&g, edge_set, &edges, false)); IGRAPH_FINALLY_PV(igraph_es_destroy, &edge_set); igraph_vector_int_destroy(&edges); - + igraph_t mst; IGRAPH_R_CHECK(igraph_subgraph_from_edges(&g, &mst, edge_set, true)); igraph_es_destroy(&edge_set); diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml index cee8b524c3e..bbba1f88144 100644 --- a/src/vendor/cigraph/interfaces/functions.yaml +++ b/src/vendor/cigraph/interfaces/functions.yaml @@ -107,6 +107,7 @@ igraph_get_all_eids_between: igraph_incident: PARAMS: GRAPH graph, OUT EDGE_INDICES eids, VERTEX vid, NEIMODE mode=ALL, LOOPS loops=TWICE + DEPS: eids ON graph, vid ON graph FLAGS: no_rng igraph_is_same_graph: diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 5e9ae89be49..33e68787533 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -56,9 +56,6 @@ igraph_get_all_eids_between: # in the argument list. DEPS: from ON graph, to ON graph, eids ON graph -igraph_incident: - IGNORE: RR, RC - igraph_is_same_graph: IGNORE: RR, RC, RInit # Not needed in R; we can simply compare things in the R layer without From e21f1b134fa757af78a255e5f9bbf3ee38f96f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 22 Sep 2025 14:27:29 +0200 Subject: [PATCH 005/154] add missing types cc @krlmlr @szhorvat --- tools/stimulus/types-RR.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index d155b639c06..efe7931026e 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -524,3 +524,25 @@ CHUNG_LU_VARIANT: DEFAULT: ORIGINAL: c("original", "maxent", "nr") INCONV: '%I% <- switch(igraph.match.arg(%I%), "original"=0L, "maxent"=1L, "nr"=2L)' + +EDGE_WEIGHTS: + INCONV: |- + if (is.null(%I%) && "weight" %in% edge_attr_names(%I1%)) { + %I% <- E(%I1%)$weight + } + if (!is.null(%I%) && any(!is.na(%I%))) { + %I% <- as.numeric(%I%) + } else { + %I% <- NULL + } + +VERTEX_WEIGHTS: + INCONV: |- + if (is.null(%I%) && "weight" %in% vertex_attr_names(%I1%)) { + %I% <- V(%I1%)$weight + } + if (!is.null(%I%) && any(!is.na(%I%))) { + %I% <- as.numeric(%I%) + } else { + %I% <- NULL + } From 55b424b031bf85f9df90bd85c709ad8503ed3a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 22 Sep 2025 14:42:38 +0200 Subject: [PATCH 006/154] chore: re-generate code --- R/aaa-auto.R | 632 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 632 insertions(+) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index 5665e082215..e2638b377dd 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -823,6 +823,14 @@ closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "tot ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) @@ -839,6 +847,14 @@ closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } normalized <- as.logical(normalized) cutoff <- as.numeric(cutoff) @@ -854,6 +870,14 @@ closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all get_shortest_path_impl <- function(graph, weights=NULL, from, to, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } from <- as_igraph_vs(graph, from) if (length(from) == 0) { stop("No vertex was specified") @@ -887,6 +911,14 @@ get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, m if (length(to) == 0) { stop("No vertex was specified") } + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -912,6 +944,14 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode= if (length(to) == 0) { stop("No vertex was specified") } + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -929,6 +969,14 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode= get_all_shortest_paths_impl <- function(graph, weights=NULL, from, to, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } from <- as_igraph_vs(graph, from) if (length(from) == 0) { stop("No vertex was specified") @@ -951,6 +999,14 @@ get_all_shortest_paths_dijkstra_impl <- function(graph, from, to=V(graph), weigh stop("No vertex was specified") } to <- as_igraph_vs(graph, to) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -965,6 +1021,14 @@ voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in check_dots_empty() ensure_igraph(graph) generators <- as_igraph_vs(graph, generators) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) tiebreaker <- switch(igraph.match.arg(tiebreaker), "first"=0L, "last"=1L, "random"=2L) @@ -998,6 +1062,14 @@ get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mod # Argument checks check_dots_empty() ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } k <- as.numeric(k) from <- as_igraph_vs(graph, from) if (length(from) == 0) { @@ -1027,6 +1099,14 @@ get_widest_path_impl <- function(graph, from, to, weights, mode=c("out", "in", " if (length(to) == 0) { stop("No vertex was specified") } + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1049,6 +1129,14 @@ get_widest_paths_impl <- function(graph, from, to=V(graph), weights, mode=c("out stop("No vertex was specified") } to <- as_igraph_vs(graph, to) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1063,6 +1151,14 @@ widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph), ensure_igraph(graph) from <- as_igraph_vs(graph, from) to <- as_igraph_vs(graph, to) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1077,6 +1173,14 @@ widest_path_widths_floyd_warshall_impl <- function(graph, from=V(graph), to=V(gr ensure_igraph(graph) from <- as_igraph_vs(graph, from) to <- as_igraph_vs(graph, to) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1090,6 +1194,14 @@ spanner_impl <- function(graph, stretch, weights=NULL) { # Argument checks ensure_igraph(graph) stretch <- as.numeric(stretch) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1105,6 +1217,14 @@ betweenness_cutoff_impl <- function(graph, vids=V(graph), directed=TRUE, weights ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) directed <- as.logical(directed) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } cutoff <- as.numeric(cutoff) on.exit( .Call(R_igraph_finalizer) ) @@ -1123,6 +1243,14 @@ betweenness_subset_impl <- function(graph, vids=V(graph), directed=TRUE, sources directed <- as.logical(directed) sources <- as_igraph_vs(graph, sources) targets <- as_igraph_vs(graph, targets) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1137,6 +1265,14 @@ edge_betweenness_impl <- function(graph, directed=TRUE, weights=NULL) { # Argument checks ensure_igraph(graph) directed <- as.logical(directed) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1149,6 +1285,14 @@ edge_betweenness_cutoff_impl <- function(graph, directed=TRUE, weights=NULL, cut # Argument checks ensure_igraph(graph) directed <- as.logical(directed) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } cutoff <- as.numeric(cutoff) on.exit( .Call(R_igraph_finalizer) ) @@ -1165,6 +1309,14 @@ edge_betweenness_subset_impl <- function(graph, eids=E(graph), directed=TRUE, so directed <- as.logical(directed) sources <- as_igraph_vs(graph, sources) targets <- as_igraph_vs(graph, targets) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1180,6 +1332,14 @@ harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } normalized <- as.logical(normalized) cutoff <- as.numeric(cutoff) @@ -1200,6 +1360,14 @@ personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V directed <- as.logical(directed) damping <- as.numeric(damping) if (!is.null(personalized)) personalized <- as.numeric(personalized) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } if (is.null(options)) { if (algo == 0L) { options <- list(niter=1000, eps=0.001) @@ -1227,6 +1395,14 @@ personalized_pagerank_vs_impl <- function(graph, algo=c("prpack", "arpack"), vid directed <- as.logical(directed) damping <- as.numeric(damping) reset.vids <- as_igraph_vs(graph, reset.vids) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } if (is.null(options)) { if (algo == 0L) { options <- list(niter=1000, eps=0.001) @@ -1290,6 +1466,14 @@ reverse_edges_impl <- function(graph, eids=E(graph)) { average_path_length_impl <- function(graph, weights=NULL, directed=TRUE, unconn=TRUE, details=FALSE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } directed <- as.logical(directed) unconn <- as.logical(unconn) @@ -1369,6 +1553,14 @@ transitivity_barrat_impl <- function(graph, vids=V(graph), weights=NULL, mode=c( # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "nan"=0L, "zero"=1L) on.exit( .Call(R_igraph_finalizer) ) @@ -1448,6 +1640,14 @@ mean_degree_impl <- function(graph, loops=TRUE) { feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "exact_ip")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } algo <- switch(igraph.match.arg(algo), "exact_ip"=0L, "approx_eades"=1L) on.exit( .Call(R_igraph_finalizer) ) @@ -1462,6 +1662,14 @@ feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "e feedback_vertex_set_impl <- function(graph, weights=NULL, algo=c("exact_ip")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% vertex_attr_names(graph)) { + weights <- V(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } algo <- switch(igraph.match.arg(algo), "exact_ip"=0L) on.exit( .Call(R_igraph_finalizer) ) @@ -1591,6 +1799,14 @@ eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total # Argument checks ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } options <- modify_list(arpack_defaults(), options) on.exit( .Call(R_igraph_finalizer) ) @@ -1605,6 +1821,14 @@ eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total hub_and_authority_scores_impl <- function(graph, weights=NULL, options=arpack_defaults()) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } options <- modify_list(arpack_defaults(), options) on.exit( .Call(R_igraph_finalizer) ) @@ -1676,6 +1900,14 @@ avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all", vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) neighbor.degree.mode <- switch(igraph.match.arg(neighbor.degree.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1689,6 +1921,14 @@ avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all", degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } from.mode <- switch(igraph.match.arg(from.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) to.mode <- switch(igraph.match.arg(to.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) directed.neighbors <- as.logical(directed.neighbors) @@ -1703,6 +1943,14 @@ degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out rich_club_sequence_impl <- function(graph, weights=NULL, vertex.order, normalized=TRUE, loops=FALSE, directed=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } vertex.order <- as.numeric(vertex.order)-1 normalized <- as.logical(normalized) loops <- as.logical(loops) @@ -1721,6 +1969,14 @@ strength_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "tota vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1882,6 +2138,14 @@ assortativity_degree_impl <- function(graph, directed=TRUE) { joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=-1, max.in.degree=-1) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } max.out.degree <- as.numeric(max.out.degree) max.in.degree <- as.numeric(max.in.degree) @@ -1895,6 +2159,14 @@ joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=-1, max joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE, normalized=TRUE, max.from.degree=-1, max.to.degree=-1) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } from.mode <- switch(igraph.match.arg(from.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) to.mode <- switch(igraph.match.arg(to.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) directed.neighbors <- as.logical(directed.neighbors) @@ -1912,6 +2184,14 @@ joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out joint_type_distribution_impl <- function(graph, weights=NULL, from.types, to.types=NULL, directed=TRUE, normalized=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } from.types <- as.numeric(from.types)-1 if (!is.null(to.types)) to.types <- as.numeric(to.types)-1 directed <- as.logical(directed) @@ -1940,6 +2220,14 @@ contract_vertices_impl <- function(graph, mapping, vertex.attr.comb=igraph_opt(" eccentricity_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all", "out", "in", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } vids <- as_igraph_vs(graph, vids) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -1955,6 +2243,14 @@ eccentricity_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all", graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -1969,6 +2265,14 @@ graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "t pseudo_diameter_impl <- function(graph, weights=NULL, start.vid, directed=TRUE, unconnected=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(%I1%)) { + weights <- E(%I1%)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } start.vid <- as_igraph_vs(graph, start.vid) if (length(start.vid) == 0) { stop("No vertex was specified") @@ -1986,6 +2290,14 @@ pseudo_diameter_impl <- function(graph, weights=NULL, start.vid, directed=TRUE, diversity_impl <- function(graph, weights=NULL, vids=V(graph)) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } vids <- as_igraph_vs(graph, vids) on.exit( .Call(R_igraph_finalizer) ) @@ -2000,6 +2312,14 @@ diversity_impl <- function(graph, weights=NULL, vids=V(graph)) { random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "in", "all", "total"), stuck=c("return", "error")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } start <- as_igraph_vs(graph, start) if (length(start) == 0) { stop("No vertex was specified") @@ -2023,6 +2343,14 @@ random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "i global_efficiency_impl <- function(graph, weights=NULL, directed=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } directed <- as.logical(directed) on.exit( .Call(R_igraph_finalizer) ) @@ -2035,6 +2363,14 @@ global_efficiency_impl <- function(graph, weights=NULL, directed=TRUE) { local_efficiency_impl <- function(graph, weights=NULL, vids=V(graph), directed=TRUE, mode=c("all", "out", "in", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } vids <- as_igraph_vs(graph, vids) directed <- as.logical(directed) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -2051,6 +2387,14 @@ local_efficiency_impl <- function(graph, weights=NULL, vids=V(graph), directed=T average_local_efficiency_impl <- function(graph, weights=NULL, directed=TRUE, mode=c("all", "out", "in", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } directed <- as.logical(directed) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -2175,6 +2519,14 @@ get_biadjacency_impl <- function(graph, types, weights=NULL) { # Argument checks ensure_igraph(graph) types <- handle_vertex_type_arg(types, graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2251,6 +2603,14 @@ get_laplacian_impl <- function(graph, mode=c("out", "in", "all", "total"), norma ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) normalization <- switch(igraph.match.arg(normalization), "unnormalized"=0L, "symmetric"=1L, "left"=2L, "right"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2264,6 +2624,14 @@ get_laplacian_sparse_impl <- function(graph, mode=c("out", "in", "all", "total") ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) normalization <- switch(igraph.match.arg(normalization), "unnormalized"=0L, "symmetric"=1L, "left"=2L, "right"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2472,6 +2840,14 @@ clique_number_impl <- function(graph) { weighted_cliques_impl <- function(graph, vertex.weights=NULL, min.weight=0, max.weight=0, maximal=FALSE) { # Argument checks ensure_igraph(graph) + if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { + vertex.weights <- V(graph)$weight + } + if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + vertex.weights <- as.numeric(vertex.weights) + } else { + vertex.weights <- NULL + } min.weight <- as.numeric(min.weight) max.weight <- as.numeric(max.weight) maximal <- as.logical(maximal) @@ -2486,6 +2862,14 @@ weighted_cliques_impl <- function(graph, vertex.weights=NULL, min.weight=0, max. largest_weighted_cliques_impl <- function(graph, vertex.weights=NULL) { # Argument checks ensure_igraph(graph) + if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { + vertex.weights <- V(graph)$weight + } + if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + vertex.weights <- as.numeric(vertex.weights) + } else { + vertex.weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2497,6 +2881,14 @@ largest_weighted_cliques_impl <- function(graph, vertex.weights=NULL) { weighted_clique_number_impl <- function(graph, vertex.weights=NULL) { # Argument checks ensure_igraph(graph) + if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { + vertex.weights <- V(graph)$weight + } + if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + vertex.weights <- as.numeric(vertex.weights) + } else { + vertex.weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2623,6 +3015,14 @@ layout_drl_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$def res[] <- as.numeric(res) use.seed <- as.logical(use.seed) options <- modify_list(drl_defaults$default, options) + if (is.null(weights) && "weight" %in% edge_attr_names(%I1%)) { + weights <- E(%I1%)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2637,6 +3037,14 @@ layout_drl_3d_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$ res[] <- as.numeric(res) use.seed <- as.logical(use.seed) options <- modify_list(drl_defaults$default, options) + if (is.null(weights) && "weight" %in% edge_attr_names(%I1%)) { + weights <- E(%I1%)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2652,6 +3060,14 @@ layout_sugiyama_impl <- function(graph, layers=NULL, hgap=1, vgap=1, maxiter=100 hgap <- as.numeric(hgap) vgap <- as.numeric(vgap) maxiter <- as.numeric(maxiter) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2899,6 +3315,14 @@ modularity_impl <- function(graph, membership, weights=NULL, resolution=1.0, dir # Argument checks ensure_igraph(graph) membership <- as.numeric(membership) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } resolution <- as.numeric(resolution) directed <- as.logical(directed) @@ -2912,6 +3336,14 @@ modularity_impl <- function(graph, membership, weights=NULL, resolution=1.0, dir modularity_matrix_impl <- function(graph, weights=NULL, resolution=1.0, directed=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } resolution <- as.numeric(resolution) directed <- as.logical(directed) @@ -2938,6 +3370,14 @@ community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", " # Argument checks ensure_igraph(graph) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } if (!is.null(initial)) initial <- as.numeric(initial)-1 if (!is.null(fixed)) fixed <- as.logical(fixed) lpa.variant <- switch(igraph.match.arg(lpa.variant), @@ -2953,6 +3393,14 @@ community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", " community_multilevel_impl <- function(graph, weights=NULL, resolution=1.0) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } resolution <- as.numeric(resolution) on.exit( .Call(R_igraph_finalizer) ) @@ -2965,6 +3413,14 @@ community_multilevel_impl <- function(graph, weights=NULL, resolution=1.0) { community_optimal_modularity_impl <- function(graph, weights=NULL, resolution=1.0) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } resolution <- as.numeric(resolution) on.exit( .Call(R_igraph_finalizer) ) @@ -2977,6 +3433,30 @@ community_optimal_modularity_impl <- function(graph, weights=NULL, resolution=1. community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, vertex.in.weights=NULL, resolution, beta=0.01, start, n.iterations=2, membership=NULL) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } + if (is.null(vertex.out.weights) && "weight" %in% vertex_attr_names(graph)) { + vertex.out.weights <- V(graph)$weight + } + if (!is.null(vertex.out.weights) && any(!is.na(vertex.out.weights))) { + vertex.out.weights <- as.numeric(vertex.out.weights) + } else { + vertex.out.weights <- NULL + } + if (is.null(vertex.in.weights) && "weight" %in% vertex_attr_names(graph)) { + vertex.in.weights <- V(graph)$weight + } + if (!is.null(vertex.in.weights) && any(!is.na(vertex.in.weights))) { + vertex.in.weights <- as.numeric(vertex.in.weights) + } else { + vertex.in.weights <- NULL + } resolution <- as.numeric(resolution) beta <- as.numeric(beta) start <- as.logical(start) @@ -3005,6 +3485,22 @@ split_join_distance_impl <- function(comm1, comm2) { community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL, nb.trials=10) { # Argument checks ensure_igraph(graph) + if (is.null(edge.weights) && "weight" %in% edge_attr_names(graph)) { + edge.weights <- E(graph)$weight + } + if (!is.null(edge.weights) && any(!is.na(edge.weights))) { + edge.weights <- as.numeric(edge.weights) + } else { + edge.weights <- NULL + } + if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { + vertex.weights <- V(graph)$weight + } + if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + vertex.weights <- as.numeric(vertex.weights) + } else { + vertex.weights <- NULL + } nb.trials <- as.numeric(nb.trials) on.exit( .Call(R_igraph_finalizer) ) @@ -3017,6 +3513,14 @@ community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL graphlets_impl <- function(graph, weights=NULL, niter=1000) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } niter <- as.numeric(niter) on.exit( .Call(R_igraph_finalizer) ) @@ -3188,6 +3692,14 @@ get_adjacency_sparse_impl <- function(graph, type=c("both", "upper", "lower"), w # Argument checks ensure_igraph(graph) type <- switch(igraph.match.arg(type), "upper"=0L, "lower"=1L, "both"=2L) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) on.exit( .Call(R_igraph_finalizer) ) @@ -3201,6 +3713,14 @@ get_stochastic_impl <- function(graph, column.wise=FALSE, weights=NULL) { # Argument checks ensure_igraph(graph) column.wise <- as.logical(column.wise) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3213,6 +3733,14 @@ get_stochastic_sparse_impl <- function(graph, column.wise=FALSE, weights=NULL) { # Argument checks ensure_igraph(graph) column.wise <- as.logical(column.wise) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3335,6 +3863,14 @@ count_triangles_impl <- function(graph) { local_scan_0_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3348,6 +3884,14 @@ local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "i # Argument checks ensure_igraph(us) ensure_igraph(them) + if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { + weights.them <- E(them)$weight + } + if (!is.null(weights.them) && any(!is.na(weights.them))) { + weights.them <- as.numeric(weights.them) + } else { + weights.them <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3360,6 +3904,14 @@ local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "i local_scan_1_ecount_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3373,6 +3925,14 @@ local_scan_1_ecount_them_impl <- function(us, them, weights.them=NULL, mode=c("o # Argument checks ensure_igraph(us) ensure_igraph(them) + if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { + weights.them <- E(them)$weight + } + if (!is.null(weights.them) && any(!is.na(weights.them))) { + weights.them <- as.numeric(weights.them) + } else { + weights.them <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3386,6 +3946,14 @@ local_scan_k_ecount_impl <- function(graph, k, weights=NULL, mode=c("out", "in", # Argument checks ensure_igraph(graph) k <- as.numeric(k) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3400,6 +3968,14 @@ local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c ensure_igraph(us) ensure_igraph(them) k <- as.numeric(k) + if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { + weights.them <- E(them)$weight + } + if (!is.null(weights.them) && any(!is.na(weights.them))) { + weights.them <- as.numeric(weights.them) + } else { + weights.them <- NULL + } mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3412,6 +3988,14 @@ local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c local_scan_neighborhood_ecount_impl <- function(graph, weights=NULL, neighborhoods) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3423,6 +4007,14 @@ local_scan_neighborhood_ecount_impl <- function(graph, weights=NULL, neighborhoo local_scan_subset_ecount_impl <- function(graph, weights=NULL, subsets) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4413,6 +5005,14 @@ maximum_bipartite_matching_impl <- function(graph, types, weights=NULL, eps=.Mac # Argument checks ensure_igraph(graph) types <- handle_vertex_type_arg(types, graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } eps <- as.numeric(eps) on.exit( .Call(R_igraph_finalizer) ) @@ -4426,6 +5026,14 @@ adjacency_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" # Argument checks ensure_igraph(graph) no <- as.numeric(no) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } which <- switch(igraph.match.arg(which), "lm"=0L, "la"=2L, "sa"=3L) scaled <- as.logical(scaled) cvec <- as.numeric(cvec) @@ -4442,6 +5050,14 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" # Argument checks ensure_igraph(graph) no <- as.numeric(no) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } which <- switch(igraph.match.arg(which), "lm"=0L, "la"=2L, "sa"=3L) type <- switch(igraph.match.arg(type), "default"=if (is_directed(graph)) 3L else 0L, @@ -4618,6 +5234,14 @@ fundamental_cycles_impl <- function(graph, start=-1, bfs.cutoff=-1, weights=NULL stop("No vertex was specified") } bfs.cutoff <- as.numeric(bfs.cutoff) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4632,6 +5256,14 @@ minimum_cycle_basis_impl <- function(graph, bfs.cutoff=-1, complete=TRUE, use.cy bfs.cutoff <- as.numeric(bfs.cutoff) complete <- as.logical(complete) use.cycle.order <- as.logical(use.cycle.order) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } on.exit( .Call(R_igraph_finalizer) ) # Function call From 1507a01dc9ded64bbbacc870df5b2f52cc9281b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 21:59:00 +0200 Subject: [PATCH 007/154] Check also on next --- .github/workflows/R-CMD-check.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index d7522af5891..e6f9d69d0c7 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -10,6 +10,7 @@ on: - main - master - release + - next - cran-* pull_request: branches: From 2f8124df853b41523202d89f489499dacedfc6d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 24 Oct 2025 18:42:20 +0200 Subject: [PATCH 008/154] Space --- vignettes/igraph.Rmd | 10 +++++----- vignettes/igraph_ES.rmd | 36 ++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/vignettes/igraph.Rmd b/vignettes/igraph.Rmd index fbb1c38de73..059cb1e94e3 100644 --- a/vignettes/igraph.Rmd +++ b/vignettes/igraph.Rmd @@ -173,12 +173,12 @@ As another example, let's make a chordal graph. Remember that a graph is chordal ```{r} g1 <- graph_from_literal( - A - B:C:I, B - A:C:D, - C - A:B:E:H, + A - B:C:I, B - A:C:D, + C - A:B:E:H, D - B:E:F, - E - C:D:F:H, - F - D:E:G, - G - F:H, + E - C:D:F:H, + F - D:E:G, + G - F:H, H - C:E:G:I, I - A:H ) diff --git a/vignettes/igraph_ES.rmd b/vignettes/igraph_ES.rmd index cc601c37014..bcae51dec50 100644 --- a/vignettes/igraph_ES.rmd +++ b/vignettes/igraph_ES.rmd @@ -143,8 +143,8 @@ g <- add_edges(g, edges = c(38, 37)) Añadamos más vértices y aristas a nuestro grafo. En `igraph` podemos utilizar el paquete `magrittr`, que proporciona un mecanismo para encadenar comandos con el operador `%>%`: ```{r echo = TRUE} -g <- g %>% - add_edges(edges = c(1, 34)) %>% +g <- g %>% + add_edges(edges = c(1, 34)) %>% add_vertices(3) %>% add_edges(edges = c(38, 39, 39, 40, 40, 38, 40, 37)) g @@ -180,13 +180,13 @@ Veamos otro ejemplo, hagamos un grafo cordal. Recuerda que un grafo es cordal (o ```{r} g1 <- graph_from_literal( - A-B:C:I, - B-A:C:D, - C-A:B:E:H, + A-B:C:I, + B-A:C:D, + C-A:B:E:H, D-B:E:F, - E-C:D:F:H, - F-D:E:G, - G-F:H, + E-C:D:F:H, + F-D:E:G, + G-F:H, H-C:E:G:I, I-A:H ) @@ -257,7 +257,7 @@ Para demostrar el uso de los atributos, creemos una red social sencilla: g <- make_graph( ~ Alice-Boris:Himari:Moshe, Himari-Alice:Nang:Moshe:Samira, - Ibrahim-Nang:Moshe, + Ibrahim-Nang:Moshe, Nang-Samira ) ``` @@ -265,7 +265,7 @@ g <- make_graph( Cada vértice representa a una persona, por lo que queremos almacenar sus edades, géneros y el tipo de conexión entre dos personas (`is_formal()` se refiere a si una conexión entre una persona y otra es formal o informal, es decir, colegas o amigos). El operador `$` es un atajo para obtener y establecer atributos de un grafo. Es más corto y tan legible como `graph_attr()` y `set_graph_attr()`. ```{r echo = TRUE} -V(g)$age <- c(25, 31, 18, 23, 47, 22, 50) +V(g)$age <- c(25, 31, 18, 23, 47, 22, 50) V(g)$gender <- c("f", "m", "f", "m", "m", "f", "m") E(g)$is_formal <- c(FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE) summary(g) @@ -275,9 +275,9 @@ summary(g) ```{r echo = TRUE, eval=FALSE} g <- make_graph( - ~ Alice-Boris:Himari:Moshe, + ~ Alice-Boris:Himari:Moshe, Himari-Alice:Nang:Moshe:Samira, - Ibrahim-Nang:Moshe, + Ibrahim-Nang:Moshe, Nang-Samira ) %>% set_vertex_attr("age", value = c(25, 31, 18, 23, 47, 22, 50)) %>% @@ -551,7 +551,7 @@ El argumento `layout` también acepta funciones; en este caso, la función será ```{r} plot( - g, + g, layout = layout_with_fr, main = "Red social con el algoritmo de disposición Fruchterman-Reingold" ) @@ -562,8 +562,8 @@ Para mejorar el aspecto visual, una adición trivial sería colorear los vértic ```{r} V(g)$color <- ifelse(V(g)$gender == "m", "yellow", "red") plot( - g, - layout = layout, + g, + layout = layout, vertex.label.dist = 3.5, main = "Red social - con los géneros como colores" ) @@ -573,9 +573,9 @@ También puedes tratar el atributo `gender` como un factor y proporcionar los co ```{r} plot( - g, - layout = layout, - vertex.label.dist = 3.5, + g, + layout = layout, + vertex.label.dist = 3.5, vertex.color = as.factor(V(g)$gender)) ``` From 2f59f287e830c050a1162f6be8caf2f61aa5c872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 24 Oct 2025 07:49:11 +0200 Subject: [PATCH 009/154] Space --- R/rewire.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/rewire.R b/R/rewire.R index 44354e904b2..86783aafe04 100644 --- a/R/rewire.R +++ b/R/rewire.R @@ -41,7 +41,7 @@ rewire <- function(graph, with) { if (!is(with, "igraph_rewiring_method")) { cli::cli_abort( - "{.arg with} must be an igraph rewiring method, + "{.arg with} must be an igraph rewiring method, not {.obj_type_friendly {with}}." ) } From ce615c8b8373fef2fd44c271160e4ea4e3e458c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 22 Oct 2025 17:47:51 +0200 Subject: [PATCH 010/154] Remove weird warning when running examples --- R/console.R | 32 ++++++++++++++++++++------------ src/rinterface_extra.c | 14 ++++++-------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/R/console.R b/R/console.R index 8a9eabf802d..680ee203ef3 100644 --- a/R/console.R +++ b/R/console.R @@ -94,18 +94,26 @@ console <- function() { #' @inheritParams .igraph.progress #' @dev .igraph.status <- function(message) { - type <- igraph_opt("verbose") - if (is.logical(type) && type) { - message(message, appendLF = FALSE) - } else { - switch( - type, - "tk" = message(message, appendLF = FALSE), - "tkconsole" = .igraph.progress.tkconsole.message(message, start = TRUE), - stop("Cannot interpret 'verbose' option, this should not happen") - ) - } - 0L + # Catch all errors + tryCatch( + { + type <- igraph::igraph_opt("verbose") + if (is.logical(type) && type) { + message(message, appendLF = FALSE) + } else { + switch( + type, + "tk" = message(message, appendLF = FALSE), + "tkconsole" = .igraph.progress.tkconsole.message( + message, + start = TRUE + ), + stop("Cannot interpret 'verbose' option, this should not happen") + ) + } + }, + error = function(e) {} + ) } #' @importFrom utils txtProgressBar setTxtProgressBar diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index f2c323714d5..4dfb8576cd4 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -2406,17 +2406,15 @@ igraph_error_t R_igraph_progress_handler(const char *message, double percent, } igraph_error_t R_igraph_status_handler(const char *message, void *data) { - SEXP l1 = PROTECT(Rf_install("getNamespace")); - SEXP l2 = PROTECT(Rf_ScalarString(PROTECT(Rf_mkChar("igraph")))); - SEXP l3 = PROTECT(Rf_lang2(l1, l2)); - SEXP rho = PROTECT(Rf_eval(l3, R_BaseEnv)); - - SEXP l4 = PROTECT(Rf_install(".igraph.status")); + SEXP l1 = PROTECT(Rf_install(":::")); + SEXP l2 = PROTECT(Rf_install("igraph")); + SEXP l3 = PROTECT(Rf_install(".igraph.status")); + SEXP l4 = PROTECT(Rf_lang3(l1, l2, l3)); SEXP l5 = PROTECT(Rf_ScalarString(PROTECT(Rf_mkChar(message)))); SEXP l6 = PROTECT(Rf_lang2(l4, l5)); - PROTECT(Rf_eval(l6, rho)); + PROTECT(Rf_eval(l6, R_BaseEnv)); - UNPROTECT(10); + UNPROTECT(8); return 0; } From 1b3f3c6c7f382e3aea520c22e08d45bb17281505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 17 Aug 2025 16:21:35 +0200 Subject: [PATCH 011/154] fix: Fix tests for major update --- tests/testthat/_snaps/centrality.md | 2 +- tests/testthat/_snaps/incidence.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/testthat/_snaps/centrality.md b/tests/testthat/_snaps/centrality.md index e33c5262041..574a8cbc8ba 100644 --- a/tests/testthat/_snaps/centrality.md +++ b/tests/testthat/_snaps/centrality.md @@ -117,7 +117,7 @@ arpack(f, options = list(nev = 2, ncv = 4), sym = TRUE) Condition Error in `arpack()`: - ! At vendor/cigraph/src/linalg/arpack.c:1102 : ARPACK error, N must be positive + ! At vendor/cigraph/src/linalg/arpack.c:1025 : N must be positive, ARPACK error --- diff --git a/tests/testthat/_snaps/incidence.md b/tests/testthat/_snaps/incidence.md index dbb1ba9a91e..541b8034a6d 100644 --- a/tests/testthat/_snaps/incidence.md +++ b/tests/testthat/_snaps/incidence.md @@ -6,7 +6,7 @@ IGRAPH UN-B 8 7 -- + attr: type (v/l), name (v/c) + edges (vertex names): - [1] A--c A--d B--b B--c B--e C--b C--d + [1] B--b C--b A--c B--c A--d C--d B--e --- @@ -26,7 +26,7 @@ IGRAPH UN-B 8 10 -- + attr: type (v/l), name (v/c) + edges (vertex names): - [1] A--c A--d A--d A--e B--b B--e C--b C--c C--c C--e + [1] B--b C--b A--c C--c C--c A--d A--d A--e B--e C--e # graph_from_biadjacency_matrix() works -- sparse From 411df7b8108b920c769b1a40337a12d31b5f5b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Wed, 27 Aug 2025 14:31:58 +0200 Subject: [PATCH 012/154] fix: adapt to the new default value thx @szhorvat --- R/games.R | 4 ---- 1 file changed, 4 deletions(-) diff --git a/R/games.R b/R/games.R index 747e7797972..b88eca94a3f 100644 --- a/R/games.R +++ b/R/games.R @@ -938,10 +938,6 @@ sample_pa <- function( )) } - if (is.null(out.seq)) { - out.seq <- numeric() - } - algorithm <- igraph.match.arg(algorithm) algorithm1 <- switch( algorithm, From 68bbbc2f8c2fcc29b2e54e05b04f73a1b10ae9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Wed, 27 Aug 2025 14:40:41 +0200 Subject: [PATCH 013/154] chore: add changelog fragment for Ctrl+F --- inst/CHANGELOG-C-DELETEME.md | 213 +++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 inst/CHANGELOG-C-DELETEME.md diff --git a/inst/CHANGELOG-C-DELETEME.md b/inst/CHANGELOG-C-DELETEME.md new file mode 100644 index 00000000000..1f383ade983 --- /dev/null +++ b/inst/CHANGELOG-C-DELETEME.md @@ -0,0 +1,213 @@ +# igraph C library changelog + +## [develop] + +### Breaking changes + +This section gives detailed on breaking changes you need to consider when updating code written for igraph 0.10.x. + +#### General changes + + - igraph now requires a C++ compiler that supports the C++14 standard. + - `igraph_setup()` is now recommended to be called before using the library. This function may gain essential functions in the future. See below for details. + - `igraph_rng_set_default()` now returns a pointer to the previous RNG. Furthermore, this function now only stores a pointer to the `igraph_rng_t` struct passed to it, instead of copying the struct. Thus the `igraph_rng_t` must continue to exist for as long as it is used as the default RNG. + - Interruption handlers do not take a `void*` argument any more; this is relevant to maintainers of higher-level interfaces only. + - Interruption handlers now return an `igraph_bool_t` instead of an `igraph_error_t`; the returned value must be true if the calculation has to be interrupted and false otherwise. + - `igraph_status()`, `igraph_statusf()` and their macro versions (`IGRAPH_STATUS()` and `IGRAPH_STATUSF()`) do not convert error codes to `IGRAPH_INTERRUPTED` any more. Any error code returned from the status handler function is forwarded intact to the caller. If you want to trigger the interruption of the current calculation from the status handler without reporting an error, report `IGRAPH_INTERRUPTED` explicitly. It is the responsibility of higher-level interfaces to handle this error code appropriately. + - The `RNG_BEGIN()` and `RNG_END()` macros were removed. You are now responsible for seeding the RNG before using any igraph function that may use random numbers by calling `igraph_rng_seed(igraph_rng_default(), ...)`, or by simply ensuring that `igraph_setup()` was called before the first use of the library. + +#### Error codes + + - The `IGRAPH_EINVEVECTOR` error code was removed; `igraph_create()` and `igraph_add_edges()` that used to return this error code for invalid edge vectors will now return `IGRAPH_EINVAL` instead. + - The `IGRAPH_NONSQUARE` error code was removed; functions that used this error code now return `IGRAPH_EINVAL` instead when encountering a non-square matrix. + - The `IGRAPH_EGLP` error code and all other GLP-specific error codes (starting with `IGRAPH_GLP_`) were removed; functions that used this error code now return `IGRAPH_FAILURE` instead, providing more details in the message associated to the error code. + - The `IGRAPH_ELAPACK` error code was removed; functions that used this error code now return `IGRAPH_FAILURE` instead, providing more details in the message associated to the error code. + - The `IGRAPH_CPUTIME` error code was removed in favour of the interruption mechanism built into igraph. + - The unused `IGRAPH_EDIVZERO` and `IGRAPH_EATTRIBUTES` error codes were removed with no replacement. + - The deprecated error code `IGRAPH_ENEGLOOP` was removed. Use `IGRAPH_ENEGCYCLE` instead. The underlying numerical value is the same as it was for `IGRAPH_ENEGLOOP`. + - ARPACK-specific error codes (starting with `IGRAPH_ARPACK_...`) were replaced with a single `IGRAPH_EARPACK` error code. Details about the underlying ARPACK failure are provided in the error message. + - A new error code called `IGRAPH_EINVEID` was added for cases when an invalid edge ID was encountered in an edge ID vector. + +#### Core data structures + + - `igraph_strvector_push_back_len()` now takes a length parameter of `size_t` instead of `igraph_integer_t`. + - `igraph_strvector_print()` no longer takes a file parameter. Use `igraph_strvector_fprint()` to print to a file. + - `igraph_vector_reverse()` no longer returns an error code. + - `igraph_vector_shuffle()` no longer returns an error code. + - `igraph_vector_swap()` and `igraph_matrix_swap()` no longer return an error code. + - `igraph_vector_list_swap()` and `igraph_graph_list_swap()` no longer return an error code. + - `igraph_vector_swap_elements()` no longer returns an error code. + - `igraph_vector_list_swap_elements()` and `igraph_graph_list_swap_elements()` no longer return an error code. + - `igraph_matrix_copy_to()` gained an `igraph_matrix_storage_t storage` parameter that specifies whether the data should be written in column-major or row-major format. + +#### Attribute handling + + - `igraph_attribute_handler_t` members that formerly took an untyped `igraph_vector_ptr_t` argument are now taking a typed `igraph_attribute_record_list_t` argument instead. + - The deprecated `IGRAPH_ATTRIBUTE_DEFAULT` value of the `igraph_attribute_type_t` enum was removed. + - The `gettype` member of `igraph_attribute_table_t` was renamed to `get_type` for sake of consistency with the naming scheme of other struct members. + - Attribute table members that retrieve graph, vertex or edge attributes must not clear the incoming result vector any more; results must be appended to the end of the provided result vector instead. + - The `value` member of `igraph_attribute_record_t` is now a union that can be used to formally treat the associated pointer as an `igraph_vector_t *`, `igraph_strvector_t *` or `igraph_vector_bool_t *`. + +#### Core graph manipulation + + - `igraph_delete_vertices_map()` (formerly called `igraph_delete_vertices_idx()`) and `igraph_induced_subgraph_map()` now use `-1` to represent unmapped vertices in the returned forward mapping vector and they do not offset vertex indices by 1 any more. (Note that the inverse map always behaved this way, this change makes the two mappings consistent). + - `igraph_edges()` gained a new `bycol` argument that determines the order in which the edges are returned. `bycol = false` reproduces the existing behaviour, while `bycol = true` returns the edges suitable for a matrix stored in column-wise order. + - `igraph_neighbors()` and `igraph_vs_adj()` gained two extra arguments to specify what to do with loop and multiple edges. This makes their interfaces consistent with `igraph_adjlist_init()`. + - `igraph_incident()` and `igraph_es_incident()` gained an extra arguments to specify what to do with loop edges. This makes their interfaces consistent with `igraph_inclist_init()`. + - `igraph_multiple_t` was removed from the public API as it is essentially a boolean. The symbolic constants `IGRAPH_MULTIPLE` and `IGRAPH_NO_MULTIPLE` were kept to improve readability of code written directly in C. + +#### Basic graph properties + + - `igraph_density()` now takes an optional `weights` parameter. + - `igraph_is_simple()` gained an extra `igraph_bool_t` argument that decides whether edge directions should be considered. Directed graphs with a mutual edge pair are treated as non-simple if this argument is set to `IGRAPH_UNDIRECTED` (which treats the graph as if it was undirected). + - The type of the `loops` argument of `igraph_adjlist_init_complementer()`, `igraph_centralization_degree()`, `igraph_centralization_degree_tmax()`, `igraph_degree()`, `igraph_maxdegree()`, `igraph_sort_vertex_ids_by_degree()` and `igraph_strength()` was changed to `igraph_loops_t` from `igraph_bool_t`, allowing finer-grained control about how loop edges are treated. + - `igraph_get_biadjacency()` now takes a `weights` parameter, and can optionally create weighted biadjacency matrices. + - `igraph_adjacency()` now treats `IGRAPH_LOOPS_TWICE` as `IGRAPH_LOOPS_ONCE` when the mode is `IGRAPH_ADJ_DIRECTED`, `IGRAPH_ADJ_UPPER` or `IGRAPH_ADJ_LOWER`. For directed graphs, this is for the sake of consistency with the rest of the library where `IGRAPH_LOOPS_TWICE` is considered for undirected graphs only. For the "upper" and "lower" modes, double-counting the diagonal makes no sense because the double-counting artifact appears when you add the _transpose_ of an upper (or lower) diagonal matrix on top of the matrix itself. See Github issue #2501 for more context. + +#### Graph generators + + - `igraph_barabasi_game()`, `igraph_barabasi_aging_game()`, `igraph_recent_degree_game()` and `igraph_recent_degree_aging_game()` no longer interprets an empty `outseq` vector as a missing out-degree sequence. Pass `NULL` if you don't wish to specify an out-degree sequence. + - `igraph_degree_sequence_game()` no longer interprets an empty in-degree vector as a request for generating undirected graphs. To generate undirected graphs, pass `NULL` for in-degrees. + - `igraph_lcf()` was renamed to `igraph_lcf_small()` and `igraph_lcf_vector()` was renamed to `igraph_lcf()`. Now `igraph_lcf()` takes shifts as a vector input, while `igraph_lcf_small()` accepts a shorthand notation where shifts are given as a variable number of function arguments. + - `igraph_sbm_game()` gained a `multiple` parameter and now supports generating multigraph with prescribed expected edge multiplicities. The parameter determining the total number of vertices (`n`) was removed as it was redundant. + +#### Shortest paths + + - `igraph_distances()`, `igraph_distances_cutoff()`, `igraph_get_shortest_path()`, `igraph_get_shortest_paths()` and `igraph_get_all_shortest_paths()` gained a `weights` argument. The functions now automatically select the appropriate implementation (unweighted, Dijkstra, Bellman-Ford or Johnson) algorithm based on whether weights are present and whether there are negative weights or not. You can still call the individual methods by their more specific names. + - `igraph_distances_johnson()` now takes a mode parameter to determine in which direction paths should be followed. + - `igraph_similarity_jaccard()` and `igraph_similarity_dice()` now take two sets of vertices to create vertex pairs of, instead of one. + - The weighted variants of `igraph_diameter()`, `igraph_pseudo_diameter()`, `igraph_radius()`, `igraph_graph_center()`, `igraph_eccentricity()` and `igraph_average_path_length()` were merged into the undirected ones by adding a new argument named `weights` in the second position. + - The `weights` parameter of `igraph_average_path_length()`, `igraph_global_efficiency()`, `igraph_local_efficiency()` and `igraph_average_local_efficiency()` were moved to the second position, after the `graph` itself, for sake of consistency with other functions. + - `igraph_get_all_simple_paths()` returns its results in an integer vector list (`igraph_vector_int_list_t`) instead of a single integer vector. + - `igraph_get_all_simple_paths()` now has an additional parameter that allows restricting paths by minimum length as well. + +#### Community detection + + - `igraph_community_edge_betweenness()` now takes both a `weights` and a `lengths` parameter. Egde weights (interpreted as connection strengths) are used to divide betweenness scores before selecting them for removal as well as for the modularity computation. Edge lengths are used for defining shortest path lengths during the betweenness computation. This fixes issues #2229 and #1040. + - `igraph_community_infomap()` now supports regularization and gained the `is_regularized` and `regularization_strength` parameters. + - `igraph_community_label_propagation()` changed signature to allow specification of label propagation algorithm (LPA) variants. A new fast label propagation variant was added. + - `igraph_community_leiden()` now takes two `vertex_out_weights` and `vertex_in_weights` parameters in order to support directed graphs, instead of the previous single `node_weights` parameter. To obtain the old behavior for undirected graphs, pass the vertex weights as `vertex_out_weights` and set `vertex_in_weights` to `NULL`. + - The `history` parameter of `igraph_community_leading_eigenvector()` is now a pointer to an `igraph_vector_int_t` instead of an `igraph_vector_t`. + - `igraph_community_optimal_modularity()` now takes a `resolution` parameter and its `weight` parameter was moved to the second place. + - `igraph_community_spinglass_single()` now uses `igraph_real_t` for its `inner_links` and `outer_links` output parameters, as these return not simply edge counts, but the sum of the weights of some edges. + +#### Isomorphism functions and permutations + + - `igraph_count_automorphisms()` has been renamed to `igraph_count_automorphisms_bliss()` because it has a BLISS-specific interface. A new `igraph_count_automorphisms()` function was added with a simplified interface that does not depend on BLISS. + - `igraph_automorphism_group()` has been renamed to `igraph_automorphism_group_bliss()` because it has a BLISS-specific interface. A new `igraph_automorphism_group()` function was added with a simplified interface that does not depend on BLISS. + - `igraph_canonical_permutation()` has been renamed to `igraph_canonical_permutation_bliss()` because it has a BLISS-specific interface. A new `igraph_canonical_permutation()` function was added with a simplified interface that does not depend on BLISS. + - `igraph_subisomorphic_lad()` does not have a CPU time limit parameter any more. If you wish to stop the calculation from another thread or a higher level interface, use igraph's interruption mechanism. + - The semantics of the `igraph_permute_vertices()` permutation argument has changed: the i-th element of the vector now contains the index of the _original_ vertex that will be mapped to the i-th vertex in the new graph. This is now consistent with how other igraph functions treat permutations and vertex index vectors; for instance, you can now pass the result of `igraph_topological_sorting()` directly to `igraph_permute_vertices()` to obtain a new graph where the vertices are sorted topologically. + - As a consequence to the change in the semantics of the `igraph_permute_vertices()` permutation argument, the semantics of the permutations returned from `igraph_canonical_permutation()` and `igraph_canonical_permutation_bliss()` have also been inverted to maintain the invariant that the output of these functions can be fed into `igraph_permute_vertices()` directly. + +#### Centralities + + - All betweenness functions got `normalized` parameter to support normalizing the result by the number of vertex pairs in the graph. At the same time, parameter ordering was standardized. The following functions are affected: `igraph_betweenness()`, `igraph_betweenness_cutoff()`, `igraph_edge_betweenness()`, `igraph_edge_betweenness_cutoff()`, `igraph_betweenness_subset()`, `igraph_edge_betweenness_subset()`. + - `igraph_edge_betweenness()` and `igraph_edge_betweenness_cutoff()` now have an `eids` parameter to return only a subset of results. This makes their interface consistent with other betweenness functions. + - `igraph_eigenvector_centrality()`, `igraph_centralization_eigenvector_centrality()` and `igraph_centralization_eigenvector_centrality_tmax()` now use a `mode` parameter with possible values `IGRAPH_OUT`, `IGRAPH_IN` or `IGRAPH_ALL` to control how edge directions are considered. Previously they used a boolean `directed` parameter. + - `igraph_eigenvector_centrality()`, `igraph_centralization_eigenvector_centrality()` and `igraph_centralization_eigenvector_centrality_tmax()` no longer have a `scale` parameter. The result is now always scaled so that the largest centrality value is 1. + - `igraph_hub_and_authority_scores()` no longer has a `scale` parameter. The result is now always scaled so that the largest hub and authority scores are each 1. + - `igraph_pagerank()`, `igraph_personalized_pagerank()` and `igraph_personalized_pagerank_vs()` had their parameter ordering standardized. + +#### Other network analysis + + - `igraph_minimum_spanning_tree()` takes a new `method` parameter that controls the algorithm used for finding the spanning tree. Kruskal's algorithm was added. + - The deprecated `igraph_rng_get_dirichlet()` function was removed. + - `igraph_motifs_randesu_no()` and `igraph_motifs_randesu_estimate()` now take an `igraph_real_t` as their `result` argument to prevent overflows when igraph is compiled with 32-bit integers. + - The experimental functions `igraph_fundamental_cycles()` and `igraph_minimum_cycle_basis()` now use the type `igraph_real_t` for their `bfs_cutoff` parameter, and had their `weights` parameter moved to the 2nd position. + - `igraph_rewire()` now takes an `igraph_edge_type_sw_t` parameter to specify whether to create self-loops. The `igraph_rewiring_t` enum type was removed. Instead of the old `IGRAPH_REWIRING_SIMPLE`, use `IGRAPH_SIMPLE_SW`. Instead of the old `IGRAPH_REWIRING_SIMPLE_LOOPS`, use `IGRAPH_LOOPS_SW`. + +#### Foreign formats + + - `igraph_read_graph_ncol()` and `igraph_read_graph_lgl()` now uses a default edge weight of 1 instead of 0 for files that do not contain edge weights for at least some of the edges. + +### Added + + - `igraph_setup()` performs all initialization tasks that are recommended before using the igraph library. Right now this function only initializes igraph's internal random number generator with a practically random seed, but it may also perform other tasks in the future. It is recommended to call this function before using any other function from the library (although most of the functions will work fine now even if this function is not called). + - `igraph_int_t` may now be used as an alias to `igraph_integer_t`. + - `igraph_erdos_renyi_game_gnm()` gained a `multiple` Boolean argument to uniformly sample G(n,m) graphs with multi-edges. + - `igraph_bipartite_game_gnm()` gained a `multiple` Boolean argument to uniformly sample bipartite G(n,m) graphs with multi-edges. + - `igraph_iea_game()` samples random multigraphs through independent edge assignment. + - `igraph_bipartite_iea_game()` samples random bipartite multigraph through independent edge assignment. + - `igraph_weighted_biadjacency()` creates a weighted graph from a bipartite adjacency matrix. + - `igraph_vector_ptr_capacity()` returns the allocated capacity of a pointer vector. + - `igraph_vector_ptr_resize_min()` deallocates unused capacity of a pointer vector. + - `igraph_strvector_fprint()` prints a string vector to a file. + - `igraph_rng_sample_dirichlet()`, `igraph_rng_sample_sphere_volume()` and `igraph_rng_sample_sphere_surface()` samples vectors from a Dirichlet distribution or from the volume or surface of a sphere while allowing the user to specify the random number generator to use. + - `igraph_nearest_neighbor_graph()` computes a neighborhood graph of spatial points based on a neighbor count, cutoff distance, and chosen metric (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2788! + - `igraph_delaunay_graph()` computes a Delaunay graph of a spatial point set (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2806! + - `igraph_spatial_edge_lengths()` computes edges lengths based on spatial vertex coordinates (experimental function). + - `igraph_community_leiden_simple()` is a simplified interface to `igraph_community_leiden()` that allows selecting the objective function to maximize directly. + - `igraph_vector_difference_and_intersection_sorted()` calculates the intersection and the differences of two vectors simultaneously. + +### Changed + + - The Pajek format reader and writer now map vertex labels to the `name` vertex attribute in igraph. The `id` attribute is no longer used. + - `igraph_minimum_size_separators()` no longer returns any separating vertex sets for complete graphs. Prior to igraph 1.0, it would return all `n - 1` size vertex subsets where `n` is the vertex count. + - `igraph_community_edge_betweenness()` now treats edges with large weights as strong connections. + - `igraph_biadjacency()` now truncates non-integer matrix entries to their integer part instead of rounding them up. This brings consistency with related functions such as `igraph_adjacency()`. + - The order of edges in the graph returned by `igraph_(weighted_)adjacency()` and `igraph_biadjacency()` has changed. Note that these functions do not guarantee any specific edge order. + - `igraph_eigenvector_centrality()` now warns about eigenvector centralities equal to zero, as these indicate a disconnected graph, for which eigenvector centrality is not meaningful. + - `igraph_hub_and_authority_scores()` now warns when a large fraction of centrality scores are zero, as this indicates a non-unique solution, and thus the returned result may not be meaningful. + - `igraph_hub_and_authority_scores()` now warns when providing an undirected graph as input, and falls back to the equivalent eigenvector centrality computation. + - `igraph_get_stochastic_sparse()` no longer throws an error when some row or column sums are zero. This brings its behaviour in line with `igraph_get_stochastic()`. + - `igraph_vector_append()`, `igraph_strvector_append()` and `igraph_vector_ptr_append()` now use a different allocation strategy: if the `to` vector has insufficient capacity, they double its capacity. Previously they reserved precisely as much capacity as needed for appending the `from` vector. + - The implementation of the Infomap algorithm behind `igraph_community_infomap()` has been updated with a more recent version (2.8.0). Isolated vertices are now supported. + - `igraph_vector_difference_sorted()` now handles multisets properly (and documents how the multiplicities are handled). + +### Finalized experimental functions + + - The following functions are not experimental any more: `igraph_count_loops()`, `igraph_count_reachable()`, `igraph_distances_cutoff()`, `igraph_distances_floyd_warshall()`, `igraph_distances_dijkstra_cutoff()`, `igraph_ecc()`, `igraph_enter_safelocale()`, `igraph_exit_safelocale()`, `igraph_feedback_vertex_set()`, `igraph_find_cycle()`, `igraph_get_shortest_path_astar()`, `igraph_graph_power()`, `igraph_hexagonal_lattice()`, `igraph_hypercube()`, `igraph_is_clique()`, `igraph_is_complete()`, `igraph_is_edge_coloring()`, `igraph_is_vertex_coloring()`, `igraph_is_independent_vertex_set()`, `igraph_join()`,`igraph_joint_degree_distribution()`, `igraph_joint_degree_matrix()`, `igraph_joint_type_distribution()`, `igraph_layout_align()`, `igraph_layout_merge_dla()`, `igraph_mean_degree()`, `igraph_radius()`, `igraph_realize_bipartite_degree_sequence()`, `igraph_reachability()`, `igraph_transitive_closure()`, `igraph_tree_from_parent_vector()`, `igraph_triangular_lattice()`, `igraph_vector_intersection_size_sorted()`, `igraph_voronoi()`. + +### Fixed + + - `igraph_community_spinglass_single()` now uses `igraph_real_t` for its `inner_links` and `outer_links` output parameters, as these return not simply edge counts, but the sum of the weights of some edges. Thus these results are no longer incorrectly rounded. + +### Removed + + - Removed `igraph_Calloc()`, `igraph_Realloc()` and `igraph_Free()`. Use `IGRAPH_CALLOC()`, `IGRAPH_REALLOC()` and `IGRAPH_FREE()` instead. + - The deprecated `igraph_adjacent_triangles()` was removed. Use `igraph_count_adjacent_triangles()` instead. + - The deprecated `igraph_are_connected()` was removed. Use `igraph_are_adjacent()` instead. + - The deprecated `igraph_automorphisms()` was removed. Use `igraph_count_automorphisms()` or `igraph_count_automorphisms_bliss()` instead. + - The deprecated `igraph_convex_hull()` was removed. Use `igraph_convex_hull_2d()` instead. + - The deprecated `igraph_decompose_destroy()` was removed. + - The deprecated `igraph_hub_score()` and `igraph_authority_score()` were removed. + - The deprecated `igraph_vs_seq()`, `igraph_vss_seq()`, `igraph_es_seq()`, `igraph_ess_range()`, and `igraph_vector_init_seq()` were removed. Use the `range` alternatives instead of the old `seq` ones. + - The deprecated `igraph_erdos_renyi_game()` and `igraph_bipartite_game()` were removed. Use the corresponding functions with `_gnm()` and `_gnp()` in the name instead. + - The deprecated `igraph_tree()` was removed. Use `igraph_kary_tree()` instead. + - The deprecated `igraph_lattice()` was removed. Use `igraph_square_lattice()` instead. + - The deprecated `igraph_minimum_spanning_tree_prim()` was removed. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. + - The deprecated `igraph_minimum_spanning_tree_unweighted()` was removed. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. + - The deprecated `igraph_get_sparsemat()` was removed. Use `igraph_get_adjacency_sparse()` instead. + - The deprecated `igraph_get_stochastic_sparsemat()` was removed. Use `igraph_get_stochastic_sparse()` instead. + - The deprecated `igraph_laplacian()` was removed. Use `igraph_get_laplacian()` or `igraph_get_laplacian_sparse()` instead. + - The deprecated `igraph_subgraph_edges()` was removed. Use `igraph_subgraph_from_edges()` instead. + - The deprecated `igraph_read_graph_dimacs()` and `igraph_write_graph_dimacs()` were removed. These names may be re-used in the future. Use `igraph_read_graph_dimacs_flow()` and `igraph_write_graph_dimacs_flow()` instead. + - The deprecated `igraph_isomorphic_function_vf2()` was removed. Use `igraph_get_isomorphisms_vf2_callback()` instead. + - The deprecated `igraph_subisomorphic_function_vf2()` was removed. Use `igraph_get_subisomorphisms_vf2_callback()` instead. + - The deprecated `igraph_isomorphic_34()` was removed. Its functionality is accessible through `igraph_isomorphic()`. + - The deprecated `igraph_transitive_closure_dag()` was removed. Use `igraph_transitive_closure()` instead, which works for all graphs, not just DAGs. + - The deprecated `igraph_sparsemat_copy()` was removed. Use `igraph_sparsemat_init_copy()` instead. + - The deprecated `igraph_sparsemat_eye()` was removed. Use `igraph_sparsemat_init_eye()` instead. + - The deprecated `igraph_sparsemat_diag()` was removed. Use `igraph_sparsemat_init_diag()` instead. + - The deprecated `igraph_sparsemat()` and `igraph_weighted_sparsemat()` functions were removed; use `igraph_get_adjacency_sparse()` instead. + - The deprecated `igraph_random_edge_walk()` was removed. Its functionality is incorporated in `igraph_random_walk()`. + - The deprecated `igraph_vector_qsort_ind()` was removed. Use `igraph_vector_sort_ind()` instead. + - The deprecated `igraph_vector_binsearch2()` was removed. Use `igraph_vector_contains_sorted()` instead. + - The deprecated `igraph_vector_copy()` and `igraph_matrix_copy()` were removed. Use `igraph_vector_init_copy()` and `igraph_matrix_init_copy()` instead. + - The deprecated `igraph_vector_e()`, `igraph_vector_e_ptr()`, `igraph_matrix_e()` and `igraph_matrix_e_ptr()` were removed. Use the alternatives ending in `_get()` and `_get_ptr()` instead. + - The deprecated `igraph_vector_move_interval2()` was removed. + - The deprecated `igraph_zeroin()` was removed. + - The deprecated `igraph_deterministic_optimal_imitation()`, `igraph_moran_process()`, `igraph_roulette_wheel_imitation()` and `igraph_stochastic_imitation()` functions were removed. + - `igraph_sample_dirichlet()`, `igraph_sample_sphere_surface()` and `igraph_sample_sphere_volume()` were removed in favour of `igraph_rng_sample_dirichlet()`, `igraph_rng_sample_sphere_surface()` and `igraph_rng_sample_sphere_volume()`, which allow the user to specify the random number generator to use. + - The unused enum type `igraph_fileformat_type_t` was removed. + - The macros `IGRAPH_POSINFINITY` and `IGRAPH_NEGINFINITY` were removed. Use `IGRAPH_INFINITY` and `-IGRAPH_INFINITY` instead. + +### Deprecated + +- `igraph_delete_vertices_idx()` is now deprecated in favour of `igraph_delete_vertices_map()`, which is functionally equivalent but has a name that is consistent with `igraph_induced_subgraph_map()`. + +### Other + + - Documentation improvements. + - Improved performance when creating graphs from dense adjacency matrices (`igraph_adjacency()` and `igraph_weighted_adjacency()`). \ No newline at end of file From 1b733cebf265af1321eaaf6168b751ebcc4a228e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Wed, 27 Aug 2025 16:51:45 +0200 Subject: [PATCH 014/154] fix: scale argument was removed, soft deprecate it on the R side for `hits_scores()` --- R/centrality.R | 16 ++++++++++------ man/hits_scores.Rd | 6 ++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/R/centrality.R b/R/centrality.R index fff80dcb760..26c555244f1 100644 --- a/R/centrality.R +++ b/R/centrality.R @@ -1393,7 +1393,6 @@ eigen_centrality <- function( eigenvector_centrality_impl( graph = graph, directed = directed, - scale = TRUE, weights = weights, options = options ) @@ -1497,9 +1496,7 @@ diversity <- diversity_impl #' scores are the same as authority scores. #' #' @param graph The input graph. -#' @param scale Logical scalar, whether to scale the result to have a maximum -#' score of one. If no scaling is used then the result vector has unit length -#' in the Euclidean norm. +#' @param scale `r lifecycle::badge("deprecated")` Ignored, always scaled. #' @param weights Optional positive weight vector for calculating weighted #' scores. If the graph has a `weight` edge attribute, then this is used #' by default. Pass `NA` to ignore the weight attribute. This function @@ -1545,15 +1542,22 @@ diversity <- diversity_impl hits_scores <- function( graph, ..., - scale = TRUE, + scale = deprecated(), weights = NULL, options = arpack_defaults() ) { rlang::check_dots_empty() + if (lifecycle::is_present(scale)) { + lifecycle::deprecate_soft( + "2.1.5", + "hits_scores(scale = )", + details = "The function always behaves as if `scale = TRUE`. + The argument will be removed in the future." + ) + } hub_and_authority_scores_impl( graph = graph, - scale = scale, weights = weights, options = options ) diff --git a/man/hits_scores.Rd b/man/hits_scores.Rd index ad304438ecd..ca324679740 100644 --- a/man/hits_scores.Rd +++ b/man/hits_scores.Rd @@ -7,7 +7,7 @@ hits_scores( graph, ..., - scale = TRUE, + scale = deprecated(), weights = NULL, options = arpack_defaults() ) @@ -17,9 +17,7 @@ hits_scores( \item{...}{These dots are for future extensions and must be empty.} -\item{scale}{Logical scalar, whether to scale the result to have a maximum -score of one. If no scaling is used then the result vector has unit length -in the Euclidean norm.} +\item{scale}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Ignored, always scaled.} \item{weights}{Optional positive weight vector for calculating weighted scores. If the graph has a \code{weight} edge attribute, then this is used From 43bf7943c15aa2e38d49581e3b77c6fa91bfc288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 1 Sep 2025 16:34:40 +0200 Subject: [PATCH 015/154] chore: directed argument of `is_simple()` --- R/simple.R | 10 ++++++++++ man/simplify.Rd | 13 ++++++++++++- tests/testthat/test-simple.R | 5 +++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/testthat/test-simple.R diff --git a/R/simple.R b/R/simple.R index 0eb9c38e488..c8b41a589a1 100644 --- a/R/simple.R +++ b/R/simple.R @@ -71,6 +71,11 @@ is.simple <- function(graph) { #' `remove.multiple=TRUE`. In this case many edges might be mapped to a #' single one in the new graph, and their attributes are combined. Please see #' [attribute.combination()] for details on this. +#' @param directed Boolean.Whether to consider the directions of edges. +#' The default, `TRUE` means that edge directions will be considered. +#' `FALSE` means that edge directions will be ignored and a directed graph +#' with at least one mutual edge pair will be considered non-simple. +#' Ignored for undirected graphs. #' @return a new graph object with the edges deleted. #' @author Gabor Csardi \email{csardi.gabor@@gmail.com} #' @seealso [which_loop()], [which_multiple()] and @@ -84,6 +89,11 @@ is.simple <- function(graph) { #' is_simple(simplify(g, remove.loops = FALSE)) #' is_simple(simplify(g, remove.multiple = FALSE)) #' is_simple(simplify(g)) +#' +#' # directed argument +#' g <- graph_from_literal(1 +-+ 2 -+ 3) +#' is_simple(g) +#' is_simple(g, directed = FALSE) #' @family simple #' @family functions for manipulating graph structure #' @family isomorphism diff --git a/man/simplify.Rd b/man/simplify.Rd index 9ebaa39c3ca..0e4d05a87f2 100644 --- a/man/simplify.Rd +++ b/man/simplify.Rd @@ -13,7 +13,7 @@ simplify( edge.attr.comb = igraph_opt("edge.attr.comb") ) -is_simple(graph) +is_simple(graph, directed = TRUE) simplify_and_colorize(graph) } @@ -29,6 +29,12 @@ removed.} \code{remove.multiple=TRUE}. In this case many edges might be mapped to a single one in the new graph, and their attributes are combined. Please see \code{\link[=attribute.combination]{attribute.combination()}} for details on this.} + +\item{directed}{Boolean.Whether to consider the directions of edges. +The default, \code{TRUE} means that edge directions will be considered. +\code{FALSE} means that edge directions will be ignored and a directed graph +with at least one mutual edge pair will be considered non-simple. +Ignored for undirected graphs.} } \value{ a new graph object with the edges deleted. @@ -65,6 +71,11 @@ is_simple(g) is_simple(simplify(g, remove.loops = FALSE)) is_simple(simplify(g, remove.multiple = FALSE)) is_simple(simplify(g)) + +# directed argument +g <- graph_from_literal(1 +-+ 2 -+ 3) +is_simple(g) +is_simple(g, directed = FALSE) } \seealso{ \code{\link[=which_loop]{which_loop()}}, \code{\link[=which_multiple]{which_multiple()}} and diff --git a/tests/testthat/test-simple.R b/tests/testthat/test-simple.R new file mode 100644 index 00000000000..aff0bea5c1e --- /dev/null +++ b/tests/testthat/test-simple.R @@ -0,0 +1,5 @@ +test_that("is_simple() works", { + g <- graph_from_literal(1 +-+ 2 -+ 3) + expect_true(is_simple(g)) + expect_false(is_simple(g, directed = FALSE)) +}) From db146efa1facc09f7acdd45ea74c3c4595dde349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 8 Sep 2025 15:58:38 +0200 Subject: [PATCH 016/154] chore: auto-generate `diameter_impl()` --- R/aaa-auto.R | 13 ++++++ R/structural-properties.R | 11 +++-- src/rinterface.c | 73 +++++++++++++++++++++++++++++++++ src/rinterface_extra.c | 23 ----------- tools/stimulus/functions-R.yaml | 4 -- 5 files changed, 91 insertions(+), 33 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index e2638b377dd..0bb271d758d 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -818,6 +818,19 @@ are_adjacent_impl <- function(graph, v1, v2) { res } +diameter_impl <- function(graph, weights=NULL, directed=TRUE, unconnected=TRUE) { + # Argument checks + ensure_igraph(graph) + directed <- as.logical(directed) + unconnected <- as.logical(unconnected) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_diameter, graph, weights, directed, unconnected) + + res +} + closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE) { # Argument checks ensure_igraph(graph) diff --git a/R/structural-properties.R b/R/structural-properties.R index b276cce9c63..ee9e528174e 100644 --- a/R/structural-properties.R +++ b/R/structural-properties.R @@ -767,14 +767,13 @@ diameter <- function( weights <- NULL } - on.exit(.Call(R_igraph_finalizer)) - .Call( - R_igraph_diameter, + res <- diameter_impl( graph, - as.logical(directed), - as.logical(unconnected), - weights + weights = weights, + directed = directed, + unconnected = unconnected ) + res$res } #' @rdname diameter diff --git a/src/rinterface.c b/src/rinterface.c index bc174a45ec6..3bf6e34f399 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -2117,6 +2117,79 @@ SEXP R_igraph_are_adjacent(SEXP graph, SEXP v1, SEXP v2) { return(r_result); } +/*-------------------------------------------/ +/ igraph_diameter / +/-------------------------------------------*/ +SEXP R_igraph_diameter(SEXP graph, SEXP weights, SEXP directed, SEXP unconnected) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_t c_weights; + igraph_real_t c_res; + igraph_integer_t c_from; + igraph_integer_t c_to; + igraph_vector_int_t c_vertex_path; + igraph_vector_int_t c_edge_path; + igraph_bool_t c_directed; + igraph_bool_t c_unconnected; + SEXP res; + SEXP from; + SEXP to; + SEXP vertex_path; + SEXP edge_path; + + SEXP r_result, r_names; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } + c_from=0; + c_to=0; + IGRAPH_R_CHECK(igraph_vector_int_init(&c_vertex_path, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_path); + IGRAPH_R_CHECK(igraph_vector_int_init(&c_edge_path, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edge_path); + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + IGRAPH_R_CHECK_BOOL(unconnected); + c_unconnected = LOGICAL(unconnected)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_diameter(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, &c_from, &c_to, &c_vertex_path, &c_edge_path, c_directed, c_unconnected)); + PutRNGstate(); + + /* Convert output */ + PROTECT(r_result=NEW_LIST(5)); + PROTECT(r_names=NEW_CHARACTER(5)); + PROTECT(res=NEW_NUMERIC(1)); + REAL(res)[0]=c_res; + PROTECT(from=NEW_NUMERIC(1)); + REAL(from)[0]=(double) c_from; + PROTECT(to=NEW_NUMERIC(1)); + REAL(to)[0]=(double) c_to; + PROTECT(vertex_path=R_igraph_vector_int_to_SEXP(&c_vertex_path)); + igraph_vector_int_destroy(&c_vertex_path); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(edge_path=R_igraph_vector_int_to_SEXP(&c_edge_path)); + igraph_vector_int_destroy(&c_edge_path); + IGRAPH_FINALLY_CLEAN(1); + SET_VECTOR_ELT(r_result, 0, res); + SET_VECTOR_ELT(r_result, 1, from); + SET_VECTOR_ELT(r_result, 2, to); + SET_VECTOR_ELT(r_result, 3, vertex_path); + SET_VECTOR_ELT(r_result, 4, edge_path); + SET_STRING_ELT(r_names, 0, Rf_mkChar("res")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("from")); + SET_STRING_ELT(r_names, 2, Rf_mkChar("to")); + SET_STRING_ELT(r_names, 3, Rf_mkChar("vertex_path")); + SET_STRING_ELT(r_names, 4, Rf_mkChar("edge_path")); + SET_NAMES(r_result, r_names); + UNPROTECT(6); + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_closeness / /-------------------------------------------*/ diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 4dfb8576cd4..163f9d14848 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -4005,29 +4005,6 @@ SEXP R_igraph_degree(SEXP graph, SEXP vids, SEXP pmode, SEXP ploops) { return result; } -SEXP R_igraph_diameter(SEXP graph, SEXP pdirected, SEXP punconnected, - SEXP pweights) { - - igraph_t g; - igraph_bool_t directed=LOGICAL(pdirected)[0]; - igraph_bool_t unconnected=LOGICAL(punconnected)[0]; - igraph_vector_t weights; - igraph_real_t res; - SEXP result; - - R_SEXP_to_igraph(graph, &g); - if (!Rf_isNull(pweights)) { - R_SEXP_to_vector(pweights, &weights); - } - IGRAPH_R_CHECK(igraph_diameter(&g, Rf_isNull(pweights) ? 0 : &weights, &res, 0, 0, 0, 0, directed, unconnected)); - - PROTECT(result=NEW_NUMERIC(1)); - REAL(result)[0]=res; - - UNPROTECT(1); - return result; -} - SEXP R_igraph_get_diameter(SEXP graph, SEXP pdirected, SEXP punconnected, SEXP pweights) { diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 33e68787533..75b1b5f4b44 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -247,10 +247,6 @@ igraph_are_connected: ####################################### igraph_diameter: - IGNORE: RR, RC, RInit - -igraph_diameter_dijkstra: - IGNORE: RR, RC, RInit igraph_distances: IGNORE: RR, RC From 0479df870be8071a318fcb853fdd9040080f7f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 22 Sep 2025 10:34:19 +0200 Subject: [PATCH 017/154] fix: renaming of `lcf_vector` to `lcf` --- R/make.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/make.R b/R/make.R index 2abbe4a054c..218486c304c 100644 --- a/R/make.R +++ b/R/make.R @@ -384,7 +384,7 @@ graph.lcf <- function(n, shifts, repeats = 1) { # nocov start lifecycle::deprecate_soft("2.1.0", "graph.lcf()", "graph_from_lcf()") # Use the _impl function - lcf_vector_impl(n = n, shifts = shifts, repeats = repeats) + lcf_impl(n = n, shifts = shifts, repeats = repeats) } # nocov end #' Create a lattice graph @@ -2627,7 +2627,7 @@ graph_from_lcf <- function( ) } - lcf_vector_impl(n = n, shifts = shifts, repeats = repeats) + lcf_impl(n = n, shifts = shifts, repeats = repeats) } ## ----------------------------------------------------------------- From fd1b53c0b850ee3cd51dbf193da78731e2798d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 22 Sep 2025 10:37:00 +0200 Subject: [PATCH 018/154] fix: renaming of `count_automorphisms` to `count_automorphisms_bliss` --- R/topology.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/topology.R b/R/topology.R index caee0c3e80c..125817288ac 100644 --- a/R/topology.R +++ b/R/topology.R @@ -1129,7 +1129,7 @@ graph.isomorphic <- isomorphic_impl #' @family graph automorphism #' @export #' @cdocs igraph_count_automorphisms -count_automorphisms <- count_automorphisms_impl +count_automorphisms <- count_automorphisms_bliss_impl #' Generating set of the automorphism group of a graph From a3e3de4de10cba98fe5554fd441cd7560de0b1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Tue, 30 Sep 2025 10:25:22 +0200 Subject: [PATCH 019/154] feat: new arguments `vids_from` and `vids_to` for `similarity()` --- DESCRIPTION | 2 +- R/similarity.R | 58 +++++++++++++++++++++++++++++++++++++++-------- man/similarity.Rd | 14 +++++++++--- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 0f49cb76a01..af537eff6fd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -83,5 +83,5 @@ Encoding: UTF-8 Roxygen: list(markdown = TRUE, roclets = c("collate", "rd", "namespace", "igraph.r2cdocs::cdocs_roclet", "devtag::dev_roclet"), packages = "igraph.r2cdocs") -RoxygenNote: 7.3.2.9000 +RoxygenNote: 7.3.3.9000 SystemRequirements: libxml2 (optional), glpk (>= 4.57, optional) diff --git a/R/similarity.R b/R/similarity.R index b86fd2f9c3e..0feaa99ee46 100644 --- a/R/similarity.R +++ b/R/similarity.R @@ -26,7 +26,11 @@ #' 25(3):211-230, 2003. #' #' @param graph The input graph. -#' @param vids The vertex ids for which the similarity is calculated. +#' @param vids lifecycle::badge("deprecated") +#' @param vids_from The vertex IDs of the first set of vertices of the pairs +#' for which the calculation will be done. +#' @param vids_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 neighboring vertices to use for the calculation, #' possible values: \sQuote{`out`}, \sQuote{`in`}, #' \sQuote{`all`}. @@ -52,7 +56,7 @@ #' similarity(g, method = "jaccard") similarity <- function( graph, - vids = V(graph), + vids = deprecated(), mode = c( "all", "out", @@ -64,16 +68,47 @@ similarity <- function( "jaccard", "dice", "invlogweighted" - ) + ), + vids_from = V(graph), + vids_to = vids_from ) { - method <- igraph.match.arg(method) - if (method == "jaccard") { - similarity_jaccard_impl(graph, vids, mode, loops) - } else if (method == "dice") { - similarity_dice_impl(graph, vids, mode, loops) - } else if (method == "invlogweighted") { - similarity_inverse_log_weighted_impl(graph, vids, mode) + if (lifecycle::is_present(vids)) { + lifecycle::deprecate_soft( + "similarity(vids =)", + I("similarity(vids_from =, vids_to =)"), + when = "3.0.0" + ) + if (!lifecycle::is_present(vids_from)) { + vids_from <- vids + vids_to <- vids_from + } } + + method <- igraph.match.arg(method) + + switch( + method, + jaccard = similarity_jaccard_impl( + graph, + vit.from = vids_from, + vit.to = vids_to, + mode = mode, + loops = loops + ), + dice = similarity_dice_impl( + graph, + vit.from = vids_from, + vit.to = vids_to, + mode = mode, + loops = loops + ), + invlogweighted = similarity_inverse_log_weighted_impl( + graph, + vit.from = vids_from, + vit.to = vids_to, + mode = mode + ) + ) } #' Similarity measures of two vertices (Jaccard) @@ -83,6 +118,7 @@ similarity <- function( #' #' Please use [similarity()] with `method = "jaccard"` instead. #' @inheritParams similarity +#' @param vids The vertex ids for which the similarity is calculated. #' @keywords internal #' @export similarity.jaccard <- function( @@ -114,6 +150,7 @@ similarity.jaccard <- function( #' #' Please use [similarity()] with `method = "dice"` instead. #' @inheritParams similarity +#' @param vids The vertex ids for which the similarity is calculated. #' @keywords internal #' @export similarity.dice <- function( @@ -145,6 +182,7 @@ similarity.dice <- function( #' #' Please use [similarity()] with `method = "invlogweighted"` instead. #' @inheritParams similarity +#' @param vids The vertex ids for which the similarity is calculated. #' @keywords internal #' @export similarity.invlogweighted <- function( diff --git a/man/similarity.Rd b/man/similarity.Rd index 5f124a707bc..ac9820c3f42 100644 --- a/man/similarity.Rd +++ b/man/similarity.Rd @@ -6,16 +6,18 @@ \usage{ similarity( graph, - vids = V(graph), + vids = deprecated(), mode = c("all", "out", "in", "total"), loops = FALSE, - method = c("jaccard", "dice", "invlogweighted") + method = c("jaccard", "dice", "invlogweighted"), + vids_from = V(graph), + vids_to = vids_from ) } \arguments{ \item{graph}{The input graph.} -\item{vids}{The vertex ids for which the similarity is calculated.} +\item{vids}{lifecycle::badge("deprecated")} \item{mode}{The type of neighboring vertices to use for the calculation, possible values: \sQuote{\code{out}}, \sQuote{\verb{in}}, @@ -25,6 +27,12 @@ possible values: \sQuote{\code{out}}, \sQuote{\verb{in}}, sets.} \item{method}{The method to use.} + +\item{vids_from}{The vertex IDs of the first set of vertices of the pairs +for which the calculation will be done.} + +\item{vids_to}{The vertex IDs of the second set of vertices of the pairs +for which the calculation will be done.} } \value{ A \code{length(vids)} by \code{length(vids)} numeric matrix From 2fc1bde83698681fd3c975b531653245f4152972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Tue, 30 Sep 2025 11:32:42 +0200 Subject: [PATCH 020/154] chore: account for changes in weighted eccentricity+radius (#2153) --- R/aaa-auto.R | 40 +++++++++++++++++--- R/paths.R | 4 +- src/rinterface.c | 32 ++++++++++++++++ src/vendor/cigraph/interfaces/functions.yaml | 2 + tools/stimulus/functions-R.yaml | 7 +--- 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index 0bb271d758d..ae20fdb02ea 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -821,6 +821,14 @@ are_adjacent_impl <- function(graph, v1, v2) { diameter_impl <- function(graph, weights=NULL, directed=TRUE, unconnected=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } directed <- as.logical(directed) unconnected <- as.logical(unconnected) @@ -2275,11 +2283,31 @@ graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "t res } +radius_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")) { + # Argument checks + ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(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_radius, graph, weights, mode) + + res +} + pseudo_diameter_impl <- function(graph, weights=NULL, start.vid, directed=TRUE, unconnected=TRUE) { # Argument checks ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(%I1%)) { - weights <- E(%I1%)$weight + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight } if (!is.null(weights) && any(!is.na(weights))) { weights <- as.numeric(weights) @@ -3028,8 +3056,8 @@ layout_drl_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$def res[] <- as.numeric(res) use.seed <- as.logical(use.seed) options <- modify_list(drl_defaults$default, options) - if (is.null(weights) && "weight" %in% edge_attr_names(%I1%)) { - weights <- E(%I1%)$weight + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight } if (!is.null(weights) && any(!is.na(weights))) { weights <- as.numeric(weights) @@ -3050,8 +3078,8 @@ layout_drl_3d_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$ res[] <- as.numeric(res) use.seed <- as.logical(use.seed) options <- modify_list(drl_defaults$default, options) - if (is.null(weights) && "weight" %in% edge_attr_names(%I1%)) { - weights <- E(%I1%)$weight + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight } if (!is.null(weights) && any(!is.na(weights))) { weights <- as.numeric(weights) diff --git a/R/paths.R b/R/paths.R index ec85f1ac65f..3c60395b2aa 100644 --- a/R/paths.R +++ b/R/paths.R @@ -293,7 +293,7 @@ eccentricity <- function( } } - eccentricity_dijkstra_impl(graph, vids = vids, weights = weights, mode = mode) + eccentricity_impl(graph, vids = vids, weights = weights, mode = mode) } @@ -347,7 +347,7 @@ radius <- function( } } - radius_dijkstra_impl(graph, weights = weights, mode = mode) + radius_impl(graph, weights = weights, mode = mode) } #' Central vertices of a graph diff --git a/src/rinterface.c b/src/rinterface.c index 3bf6e34f399..7ff8f56eb82 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -5530,6 +5530,38 @@ SEXP R_igraph_graph_center(SEXP graph, SEXP weights, SEXP mode) { return(r_result); } +/*-------------------------------------------/ +/ igraph_radius / +/-------------------------------------------*/ +SEXP R_igraph_radius(SEXP graph, SEXP weights, SEXP mode) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_t c_weights; + igraph_real_t c_radius; + igraph_neimode_t c_mode; + SEXP radius; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } + c_mode = (igraph_neimode_t) Rf_asInteger(mode); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_radius(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_radius, c_mode)); + PutRNGstate(); + + /* Convert output */ + PROTECT(radius=NEW_NUMERIC(1)); + REAL(radius)[0]=c_radius; + r_result = radius; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_pseudo_diameter / /-------------------------------------------*/ diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml index bbba1f88144..5ee970b5d8a 100644 --- a/src/vendor/cigraph/interfaces/functions.yaml +++ b/src/vendor/cigraph/interfaces/functions.yaml @@ -1510,11 +1510,13 @@ igraph_layout_drl: PARAMS: |- GRAPH graph, INOUT MATRIX res, BOOLEAN use_seed=False, DRL_OPTIONS options=drl_defaults$default, OPTIONAL EDGE_WEIGHTS weights + DEPS: weights ON graph igraph_layout_drl_3d: PARAMS: |- GRAPH graph, INOUT MATRIX res, BOOLEAN use_seed=False, DRL_OPTIONS options=drl_defaults$default, OPTIONAL EDGE_WEIGHTS weights + DEPS: weights ON graph igraph_layout_merge_dla: PARAMS: GRAPH_PTR_LIST graphs, MATRIX_LIST coords, OUT MATRIX res diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 75b1b5f4b44..47b140f3b83 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -246,8 +246,6 @@ igraph_are_connected: # Structural properties ####################################### -igraph_diameter: - igraph_distances: IGNORE: RR, RC @@ -447,12 +445,9 @@ igraph_joint_type_distribution: igraph_contract_vertices: -# We use igraph_radius_dijkstra instead -igraph_radius: - IGNORE: RR, RC igraph_pseudo_diameter: - DEPS: start_vid ON graph + DEPS: start_vid ON graph, weights ON graph igraph_diversity: From 2d409989ba94742aff80019477a6361627a23ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Thu, 2 Oct 2025 10:46:39 +0200 Subject: [PATCH 021/154] feat: new argument for `incident()` (#2178) --- R/interface.R | 31 ++++++++++++++++++++---------- man/incident.Rd | 15 ++++++++++++++- tests/testthat/_snaps/interface.md | 18 +++++++++++++++++ tests/testthat/test-interface.R | 7 +++++++ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/R/interface.R b/R/interface.R index e5317fd54ed..404b2ea044d 100644 --- a/R/interface.R +++ b/R/interface.R @@ -374,6 +374,13 @@ neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) { #' @param mode Whether to query outgoing (\sQuote{out}), incoming #' (\sQuote{in}) edges, or both types (\sQuote{all}). This is #' ignored for undirected graphs. +#' @param loops Specifies how to treat loop edges. +#' `"none"` removes loop edges from the result. +#' `"once"` makes each loop edge appear only once in the result. +#' `"twice"` makes loop edges appear twice in the result +#' if the graph is undirected or `mode` is set to `"all"` +#' (and once otherwise as returning them twice +#' does not make sense for directed graphs). #' @return An edge sequence containing the incident edges of #' the input vertex. #' @@ -384,26 +391,30 @@ neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) { #' g <- make_graph("Zachary") #' incident(g, 1) #' incident(g, 34) -incident <- function(graph, v, mode = c("all", "out", "in", "total")) { +incident <- function( + graph, + v, + mode = c("all", "out", "in", "total"), + loops = c("twice", "none", "once") +) { ensure_igraph(graph) if (is_directed(graph)) { mode <- igraph.match.arg(mode) - mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3) } else { - mode <- 1 + mode <- "out" } + loops <- igraph.match.arg(loops) v <- as_igraph_vs(graph, v) if (length(v) == 0) { stop("No vertex was specified") } - on.exit(.Call(R_igraph_finalizer)) - res <- .Call(R_igraph_incident, graph, v - 1, as.numeric(mode)) + 1L - - if (igraph_opt("return.vs.es")) { - res <- create_es(graph, res) - } - res + incident_impl( + graph, + vid = v, + mode = mode, + loops = loops + ) } #' Check whether a graph is directed diff --git a/man/incident.Rd b/man/incident.Rd index b69fb6b753c..1a7e809f67d 100644 --- a/man/incident.Rd +++ b/man/incident.Rd @@ -4,7 +4,12 @@ \alias{incident} \title{Incident edges of a vertex in a graph} \usage{ -incident(graph, v, mode = c("all", "out", "in", "total")) +incident( + graph, + v, + mode = c("all", "out", "in", "total"), + loops = c("twice", "none", "once") +) } \arguments{ \item{graph}{The input graph.} @@ -14,6 +19,14 @@ incident(graph, v, mode = c("all", "out", "in", "total")) \item{mode}{Whether to query outgoing (\sQuote{out}), incoming (\sQuote{in}) edges, or both types (\sQuote{all}). This is ignored for undirected graphs.} + +\item{loops}{Specifies how to treat loop edges. +\code{"none"} removes loop edges from the result. +\code{"once"} makes each loop edge appear only once in the result. +\code{"twice"} makes loop edges appear twice in the result +if the graph is undirected or \code{mode} is set to \code{"all"} +(and once otherwise as returning them twice +does not make sense for directed graphs).} } \value{ An edge sequence containing the incident edges of diff --git a/tests/testthat/_snaps/interface.md b/tests/testthat/_snaps/interface.md index d394032f7a6..1c13eac2c5e 100644 --- a/tests/testthat/_snaps/interface.md +++ b/tests/testthat/_snaps/interface.md @@ -33,3 +33,21 @@ Error in `el_to_vec()`: ! The columns of the data.frame are of different type (character and double) +# incident() works + + Code + incident(g, 1) + Output + + 16/78 edges: + [1] 1-- 2 1-- 3 1-- 4 1-- 5 1-- 6 1-- 7 1-- 8 1-- 9 1--11 1--12 1--13 1--14 + [13] 1--18 1--20 1--22 1--32 + +--- + + Code + incident(g, 34) + Output + + 17/78 edges: + [1] 9--34 10--34 14--34 15--34 16--34 19--34 20--34 21--34 23--34 24--34 + [11] 27--34 28--34 29--34 30--34 31--34 32--34 33--34 + diff --git a/tests/testthat/test-interface.R b/tests/testthat/test-interface.R index d1f5b10ecc1..a40b91f2ea4 100644 --- a/tests/testthat/test-interface.R +++ b/tests/testthat/test-interface.R @@ -222,3 +222,10 @@ test_that("get_edge_id() errors correctly for wrong matrices", { mat <- matrix(c(1, 2, 1, 3, 1, 4), nrow = 2, ncol = 3) lifecycle::expect_deprecated(get_edge_ids(g, mat)) }) + +test_that("incident() works", { + local_igraph_options(print.id = FALSE) + g <- make_graph("Zachary") + expect_snapshot(incident(g, 1)) + expect_snapshot(incident(g, 34)) +}) From f58586b5d760423f3723a030c84f415d056d8064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Fri, 3 Oct 2025 14:13:11 +0200 Subject: [PATCH 022/154] fix: `igraph_canonical_permutation()` has been renamed to `igraph_canonical_permutation_bliss()` --- R/topology.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/topology.R b/R/topology.R index 125817288ac..2e470f3c0c7 100644 --- a/R/topology.R +++ b/R/topology.R @@ -997,7 +997,7 @@ graph_from_isomorphism_class <- isoclass_create_impl #' @family graph isomorphism #' @export #' @cdocs igraph_canonical_permutation -canonical_permutation <- canonical_permutation_impl +canonical_permutation <- canonical_permutation_bliss_impl #' Permute the vertices of a graph From fbb9ad457b7725adb8db21e79f91ee4d18ff5e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Fri, 3 Oct 2025 14:22:20 +0200 Subject: [PATCH 023/154] fix: default `vid` for `sample_spanning_tree()` --- R/trees.R | 3 ++- man/sample_spanning_tree.Rd | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/R/trees.R b/R/trees.R index 1ce7be9387c..810770826be 100644 --- a/R/trees.R +++ b/R/trees.R @@ -133,7 +133,7 @@ to_prufer <- to_prufer_impl #' @param graph The input graph to sample from. Edge directions are ignored if #' the graph is directed. #' @param vid When the graph is disconnected, this argument specifies how to -#' handle the situation. When the argument is zero (the default), the sampling +#' handle the situation. When the argument is `NULL` (the default), the sampling #' will be performed component-wise, and the result will be a spanning forest. #' When the argument contains a vertex ID, only the component containing the #' given vertex will be processed, and the result will be a spanning tree of the @@ -153,5 +153,6 @@ to_prufer <- to_prufer_impl #' @export #' @cdocs igraph_random_spanning_tree sample_spanning_tree <- function(graph, vid = NULL) { + vid <- vid %||% 0 random_spanning_tree_impl(graph, vid) } diff --git a/man/sample_spanning_tree.Rd b/man/sample_spanning_tree.Rd index 69efb56e52b..1100e6a41af 100644 --- a/man/sample_spanning_tree.Rd +++ b/man/sample_spanning_tree.Rd @@ -4,14 +4,14 @@ \alias{sample_spanning_tree} \title{Samples from the spanning trees of a graph randomly and uniformly} \usage{ -sample_spanning_tree(graph, vid = 0) +sample_spanning_tree(graph, vid = NULL) } \arguments{ \item{graph}{The input graph to sample from. Edge directions are ignored if the graph is directed.} \item{vid}{When the graph is disconnected, this argument specifies how to -handle the situation. When the argument is zero (the default), the sampling +handle the situation. When the argument is \code{NULL} (the default), the sampling will be performed component-wise, and the result will be a spanning forest. When the argument contains a vertex ID, only the component containing the given vertex will be processed, and the result will be a spanning tree of the From 02174ee543149f99c8d05e9079370d214c24cc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Fri, 3 Oct 2025 14:22:54 +0200 Subject: [PATCH 024/154] docs: run `document()` --- man/automorphism_group.Rd | 7 +------ man/centr_degree.Rd | 2 +- man/degree.Rd | 2 +- man/distances.Rd | 16 ++++++++-------- man/global_efficiency.Rd | 2 +- man/graph_center.Rd | 6 ++---- man/min_st_separators.Rd | 9 +++------ man/strength.Rd | 2 +- 8 files changed, 18 insertions(+), 28 deletions(-) diff --git a/man/automorphism_group.Rd b/man/automorphism_group.Rd index c964ffe1ba4..db65c88d3b0 100644 --- a/man/automorphism_group.Rd +++ b/man/automorphism_group.Rd @@ -4,12 +4,7 @@ \alias{automorphism_group} \title{Generating set of the automorphism group of a graph} \usage{ -automorphism_group( - graph, - colors = NULL, - sh = c("fm", "f", "fs", "fl", "flm", "fsm"), - details = FALSE -) +automorphism_group(graph, colors = NULL) } \arguments{ \item{graph}{The input graph, it is treated as undirected.} diff --git a/man/centr_degree.Rd b/man/centr_degree.Rd index f6ddd711458..9e60b656976 100644 --- a/man/centr_degree.Rd +++ b/man/centr_degree.Rd @@ -7,7 +7,7 @@ centr_degree( graph, mode = c("all", "out", "in", "total"), - loops = TRUE, + loops = c("twice", "none", "once"), normalized = TRUE ) } diff --git a/man/degree.Rd b/man/degree.Rd index 098cf73fea2..e548afcbb3e 100644 --- a/man/degree.Rd +++ b/man/degree.Rd @@ -19,7 +19,7 @@ max_degree( ..., v = V(graph), mode = c("all", "out", "in", "total"), - loops = TRUE + loops = c("twice", "none", "once") ) degree_distribution(graph, cumulative = FALSE, ...) diff --git a/man/distances.Rd b/man/distances.Rd index 96ffa1c2860..216c6319d2e 100644 --- a/man/distances.Rd +++ b/man/distances.Rd @@ -14,7 +14,7 @@ mean_distance( graph, weights = NULL, directed = TRUE, - unconnected = TRUE, + unconn = TRUE, details = FALSE ) @@ -60,12 +60,6 @@ attribute is used. If this is \code{NA} then no weights are used (even if the graph has a \code{weight} attribute). In a weighted graph, the length of a path is the sum of the weights of its constituent edges.} -\item{unconnected}{What to do if the graph is unconnected (not -strongly connected if directed paths are considered). If TRUE, only -the lengths of the existing paths are considered and averaged; if -FALSE, the length of the missing paths are considered as having infinite -length, making the mean distance infinite as well.} - \item{details}{Whether to provide additional details in the result. Functions accepting this argument (like \code{mean_distance()}) return additional information like the number of disconnected vertex pairs in @@ -121,6 +115,12 @@ which vertex \code{i} was reached. The start vertex and vertices that were not reached during the search will have zero in the corresponding entry of the vector. Note that the search terminates if all the vertices in \code{to} are reached.} + +\item{unconnected}{What to do if the graph is unconnected (not +strongly connected if directed paths are considered). If TRUE, only +the lengths of the existing paths are considered and averaged; if +FALSE, the length of the missing paths are considered as having infinite +length, making the mean distance infinite as well.} } \value{ For \code{distances()} a numeric matrix with \code{length(to)} @@ -328,5 +328,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com} \concept{paths} \concept{structural.properties} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_path_length_hist}{\code{path_length_hist()}}, \href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_average_path_length_dijkstra}{\code{average_path_length_dijkstra()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_path_length_hist}{\code{path_length_hist()}}, \href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_average_path_length}{\code{average_path_length()}}.} diff --git a/man/global_efficiency.Rd b/man/global_efficiency.Rd index c2bff5b8b62..2f1684405d7 100644 --- a/man/global_efficiency.Rd +++ b/man/global_efficiency.Rd @@ -10,8 +10,8 @@ global_efficiency(graph, weights = NULL, directed = TRUE) local_efficiency( graph, - vids = V(graph), weights = NULL, + vids = V(graph), directed = TRUE, mode = c("all", "out", "in", "total") ) diff --git a/man/graph_center.Rd b/man/graph_center.Rd index edaa1075a6e..c15fb1e4df6 100644 --- a/man/graph_center.Rd +++ b/man/graph_center.Rd @@ -4,13 +4,11 @@ \alias{graph_center} \title{Central vertices of a graph} \usage{ -graph_center(graph, ..., weights = NULL, mode = c("all", "out", "in", "total")) +graph_center(graph, weights = NULL, mode = c("all", "out", "in", "total")) } \arguments{ \item{graph}{The input graph, it can be directed or undirected.} -\item{...}{These dots are for future extensions and must be empty.} - \item{weights}{Possibly a numeric vector giving edge weights. If this is \code{NULL} and the graph has a \code{weight} edge attribute, then the attribute is used. If this is \code{NA} then no weights are used (even if @@ -57,5 +55,5 @@ Other paths: \code{\link{radius}()} } \concept{paths} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_graph_center_dijkstra}{\code{graph_center_dijkstra()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_graph_center}{\code{graph_center()}}.} diff --git a/man/min_st_separators.Rd b/man/min_st_separators.Rd index 6a1924654d3..cd36e3839dc 100644 --- a/man/min_st_separators.Rd +++ b/man/min_st_separators.Rd @@ -38,16 +38,13 @@ min_st_separators(g) }\if{html}{\out{}} \if{html}{\out{
}}\preformatted{#> [[1]] -#> + 1/5 vertex, named: -#> [1] 1 +#> [1] 2 #> #> [[2]] -#> + 2/5 vertices, named: -#> [1] 2 4 +#> [1] 3 5 #> #> [[3]] -#> + 2/5 vertices, named: -#> [1] 1 3 +#> [1] 2 4 }\if{html}{\out{
}} } diff --git a/man/strength.Rd b/man/strength.Rd index 76a2e34f9b6..cd7c1db3cd5 100644 --- a/man/strength.Rd +++ b/man/strength.Rd @@ -8,7 +8,7 @@ strength( graph, vids = V(graph), mode = c("all", "out", "in", "total"), - loops = TRUE, + loops = c("twice", "none", "once"), weights = NULL ) } From 572083d783c3199b0d7e42b61ab61cd3a748eddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Fri, 3 Oct 2025 15:13:59 +0200 Subject: [PATCH 025/154] fix: don't convert `weights` argument twice in `diameter()` --- R/structural-properties.R | 9 --------- 1 file changed, 9 deletions(-) diff --git a/R/structural-properties.R b/R/structural-properties.R index ee9e528174e..d5433c2214e 100644 --- a/R/structural-properties.R +++ b/R/structural-properties.R @@ -758,15 +758,6 @@ diameter <- function( ) { ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } - res <- diameter_impl( graph, weights = weights, From c1139584e837b93f81fbdcec6e2b52794a61236b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Thu, 9 Oct 2025 09:47:47 +0200 Subject: [PATCH 026/154] fix: handle new names from C in `average_path_length_impl()` (#2189) --- R/structural-properties.R | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/R/structural-properties.R b/R/structural-properties.R index d5433c2214e..97cc05620df 100644 --- a/R/structural-properties.R +++ b/R/structural-properties.R @@ -842,8 +842,28 @@ farthest_vertices <- function( #' @export #' @rdname distances #' @cdocs igraph_average_path_length -mean_distance <- average_path_length_impl +mean_distance <- function( + graph, + weights = NULL, + directed = TRUE, + unconnected = TRUE, + details = FALSE +) { + res <- average_path_length_impl( + graph, + weights = weights, + directed = directed, + unconn = unconnected, + details = details + ) + if (details) { + res$unconnected <- res$unconn_pair + res$unconn_pair <- NULL + } + + res +} #' Degree and degree distribution of the vertices #' From 838e8fa11a6fa19daef5ed2411ab5cd88127cad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Thu, 9 Oct 2025 11:41:37 +0200 Subject: [PATCH 027/154] chore: handle new values of `loops` argument of `degree()` and `max_degree()` (#2188) --- R/aaa-auto.R | 14 +++++ R/structural-properties.R | 65 +++++++++++++++++---- man/degree.Rd | 8 ++- src/rinterface.c | 36 ++++++++++++ src/rinterface_extra.c | 24 -------- tests/testthat/test-structural-properties.R | 6 +- tools/stimulus/functions-R.yaml | 3 - 7 files changed, 113 insertions(+), 43 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index ae20fdb02ea..3773e67904c 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -59,6 +59,20 @@ vcount_impl <- function(graph) { res } +degree_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once")) { + # Argument checks + ensure_igraph(graph) + vids <- as_igraph_vs(graph, vids) + mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_degree, graph, vids-1, mode, loops) + + res +} + get_all_eids_between_impl <- function(graph, from, to, directed=TRUE) { # Argument checks ensure_igraph(graph) diff --git a/R/structural-properties.R b/R/structural-properties.R index 97cc05620df..8339299a3a0 100644 --- a/R/structural-properties.R +++ b/R/structural-properties.R @@ -876,7 +876,11 @@ mean_distance <- function( #' @param mode Character string, \dQuote{out} for out-degree, \dQuote{in} for #' in-degree or \dQuote{total} for the sum of the two. For undirected graphs #' this argument is ignored. \dQuote{all} is a synonym of \dQuote{total}. -#' @param loops Logical; whether the loop edges are also counted. +#' @param loops Character string, +#' `"none"` ignores loop edges; +#' `"once"` counts each loop edge only once; +#' `"twice"` (the default) counts each loop edge twice in undirected graphs +#' and once in directed graphs. #' @param normalized Logical scalar, whether to normalize the degree. If #' `TRUE` then the result is divided by \eqn{n-1}, where \eqn{n} is the #' number of vertices in the graph. @@ -907,22 +911,33 @@ degree <- function( graph, v = V(graph), mode = c("all", "out", "in", "total"), - loops = TRUE, + loops = c("twice", "none", "once"), normalized = FALSE ) { ensure_igraph(graph) - v <- as_igraph_vs(graph, v) mode <- igraph.match.arg(mode) - mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3) - on.exit(.Call(R_igraph_finalizer)) - res <- .Call( - R_igraph_degree, + if (is.logical(loops)) { + lifecycle::deprecate_soft( + "2.2.0", + "degree(loops = 'must be a character string')" + ) + if (loops) { + loops <- "twice" + } else { + loops <- "none" + } + } + + loops <- igraph.match.arg(loops) + + res <- degree_impl( graph, - v - 1, - as.numeric(mode), - as.logical(loops) + vids = v, + mode = mode, + loops = loops ) + if (normalized) { res <- res / (vcount(graph) - 1) } @@ -935,8 +950,36 @@ degree <- function( #' @rdname degree #' @export #' @cdocs igraph_maxdegree -max_degree <- maxdegree_impl +max_degree <- function( + graph, + ..., + v = V(graph), + mode = c("all", "out", "in", "total"), + loops = c("twice", "none", "once") +) { + ensure_igraph(graph) + mode <- igraph.match.arg(mode) + + if (is.logical(loops)) { + lifecycle::deprecate_soft( + "2.2.0", + "max_degree(loops = 'must be a character string')" + ) + if (loops) { + loops <- "twice" + } else { + loops <- "none" + } + } + loops <- igraph.match.arg(loops) + maxdegree_impl( + graph, + v = v, + mode = mode, + loops = loops + ) +} #' @rdname degree #' @param cumulative Logical; whether the cumulative degree distribution is to #' be calculated. diff --git a/man/degree.Rd b/man/degree.Rd index e548afcbb3e..29eede56c18 100644 --- a/man/degree.Rd +++ b/man/degree.Rd @@ -10,7 +10,7 @@ degree( graph, v = V(graph), mode = c("all", "out", "in", "total"), - loops = TRUE, + loops = c("twice", "none", "once"), normalized = FALSE ) @@ -33,7 +33,11 @@ degree_distribution(graph, cumulative = FALSE, ...) in-degree or \dQuote{total} for the sum of the two. For undirected graphs this argument is ignored. \dQuote{all} is a synonym of \dQuote{total}.} -\item{loops}{Logical; whether the loop edges are also counted.} +\item{loops}{Character string, +\code{"none"} ignores loop edges; +\code{"once"} counts each loop edge only once; +\code{"twice"} (the default) counts each loop edge twice in undirected graphs +and once in directed graphs.} \item{normalized}{Logical scalar, whether to normalize the degree. If \code{TRUE} then the result is divided by \eqn{n-1}, where \eqn{n} is the diff --git a/src/rinterface.c b/src/rinterface.c index 7ff8f56eb82..72e2bf616b7 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -188,6 +188,42 @@ SEXP R_igraph_vcount(SEXP graph) { return(r_result); } +/*-------------------------------------------/ +/ igraph_degree / +/-------------------------------------------*/ +SEXP R_igraph_degree(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_int_t c_res; + igraph_vs_t c_vids; + igraph_neimode_t c_mode; + igraph_loops_t c_loops; + SEXP res; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + IGRAPH_R_CHECK(igraph_vector_int_init(&c_res, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_res); + igraph_vector_int_t c_vids_data; + R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); + c_mode = (igraph_neimode_t) Rf_asInteger(mode); + c_loops = (igraph_loops_t) Rf_asInteger(loops); + /* Call igraph */ + IGRAPH_R_CHECK(igraph_degree(&c_graph, &c_res, c_vids, c_mode, c_loops)); + + /* Convert output */ + PROTECT(res=R_igraph_vector_int_to_SEXP(&c_res)); + igraph_vector_int_destroy(&c_res); + IGRAPH_FINALLY_CLEAN(1); + igraph_vector_int_destroy(&c_vids_data); + igraph_vs_destroy(&c_vids); + r_result = res; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_get_all_eids_between / /-------------------------------------------*/ diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 163f9d14848..9f210450491 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -3981,30 +3981,6 @@ SEXP R_igraph_create(SEXP edges, SEXP pn, SEXP pdirected) { return result; } -SEXP R_igraph_degree(SEXP graph, SEXP vids, SEXP pmode, SEXP ploops) { - - igraph_t g; - igraph_vs_t vs; - igraph_vector_int_t vs_data; - igraph_vector_int_t res; - igraph_neimode_t mode = (igraph_neimode_t) Rf_asInteger(pmode); - igraph_bool_t loops=LOGICAL(ploops)[0]; - SEXP result; - - R_SEXP_to_igraph(graph, &g); - R_SEXP_to_igraph_vs(vids, &g, &vs, &vs_data); - igraph_vector_int_init(&res, 0); - IGRAPH_R_CHECK(igraph_degree(&g, &res, vs, mode, loops)); - - PROTECT(result=R_igraph_vector_int_to_SEXP(&res)); - igraph_vector_int_destroy(&res); - igraph_vector_int_destroy(&vs_data); - igraph_vs_destroy(&vs); - - UNPROTECT(1); - return result; -} - SEXP R_igraph_get_diameter(SEXP graph, SEXP pdirected, SEXP punconnected, SEXP pweights) { diff --git a/tests/testthat/test-structural-properties.R b/tests/testthat/test-structural-properties.R index f938d495dd0..7f8a1fcd301 100644 --- a/tests/testthat/test-structural-properties.R +++ b/tests/testthat/test-structural-properties.R @@ -65,9 +65,9 @@ test_that("max_degree() works", { g <- make_graph(c(1, 2, 2, 2, 2, 3), directed = TRUE) expect_equal(max_degree(g), 4) expect_equal(max_degree(g, mode = "out"), 2) - expect_equal(max_degree(g, loops = FALSE), 2) - expect_equal(max_degree(g, mode = "out", loops = FALSE), 1) - expect_equal(max_degree(g, mode = "in", loops = FALSE), 1) + expect_equal(max_degree(g, loops = "none"), 2) + expect_equal(max_degree(g, mode = "out", loops = "none"), 1) + expect_equal(max_degree(g, mode = "in", loops = "none"), 1) expect_equal(max_degree(g, v = c()), 0) expect_equal(max_degree(make_empty_graph()), 0) }) diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 47b140f3b83..4db2ae8fb63 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -34,9 +34,6 @@ igraph_neighbors: igraph_is_directed: IGNORE: RR, RC -igraph_degree: - IGNORE: RR, RC - igraph_edge: IGNORE: RR, RC, RInit From ede7b4bdeb3db1654c3f8a8f8caa1e2ffd5fb6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Thu, 9 Oct 2025 13:15:14 +0200 Subject: [PATCH 028/154] test: split knn tests (#2199) --- tests/testthat/test-structural-properties.R | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/testthat/test-structural-properties.R b/tests/testthat/test-structural-properties.R index 7f8a1fcd301..0c92d2299b9 100644 --- a/tests/testthat/test-structural-properties.R +++ b/tests/testthat/test-structural-properties.R @@ -905,7 +905,7 @@ test_that("edge_density works", { expect_equal(gd, gd2) }) -test_that("knn works", { +test_that("knn works -- trivial examples", { withr::local_seed(42) ## Some trivial ones @@ -917,23 +917,28 @@ test_that("knn works", { knn(g2), list(knn = c(1, rep(9, 9)), knnk = c(9, rep(NaN, 7), 1)) ) +}) - ## A scale-free one, try to plot 'knnk' +test_that("knn works -- scale-free one", { + withr::local_seed(42) g3 <- simplify(sample_pa(1000, m = 5)) r3 <- knn(g3) expect_equal(r3$knn[43], 46) expect_equal(r3$knn[1000], 192.4) expect_equal(r3$knnk[100], 18.78) expect_equal(length(r3$knnk), 359) +}) - ## A random graph +test_that("knn works -- random graph", { + withr::local_seed(42) g4 <- sample_gnp(1000, p = 5 / 1000) r4 <- knn(g4) - expect_equal(r4$knn[1000], 20 / 3) + expect_equal(r4$knn[1000], 5) expect_equal(length(r4$knnk), 15) - expect_equal(r4$knnk[12], 19 / 3) + expect_equal(r4$knnk[12], 5.6389, tolerance = 1e-5) +}) - ## A weighted graph +test_that("knn works -- weighted graph", { g5 <- make_star(10) E(g5)$weight <- seq(ecount(g5)) r5 <- knn(g5) From 8b88bd1d18239832be066906879f302daf2ee91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Thu, 9 Oct 2025 13:55:21 +0200 Subject: [PATCH 029/154] fix `authority_score()`/`hub_score()` --- R/centrality.R | 5 +- tests/testthat/_snaps/centrality.md | 91 ++--------------------------- 2 files changed, 8 insertions(+), 88 deletions(-) diff --git a/R/centrality.R b/R/centrality.R index 26c555244f1..18b28772a39 100644 --- a/R/centrality.R +++ b/R/centrality.R @@ -1593,7 +1593,8 @@ authority_score <- function( weights = weights, options = options ) - scores$hub <- NULL + scores[["hub_vector"]] <- NULL + rlang::set_names(scores, c("vector", "value", "options")) } @@ -1638,7 +1639,7 @@ hub_score <- function( weights = weights, options = options ) - scores$authority <- NULL + scores[["authority_vector"]] <- NULL rlang::set_names(scores, c("vector", "value", "options")) } diff --git a/tests/testthat/_snaps/centrality.md b/tests/testthat/_snaps/centrality.md index 574a8cbc8ba..265cc5c4a65 100644 --- a/tests/testthat/_snaps/centrality.md +++ b/tests/testthat/_snaps/centrality.md @@ -10,6 +10,9 @@ arpack_defaults was deprecated in igraph 1.6.0. i Please use `arpack_defaults()` instead. i So the function arpack_defaults(), not an object called arpack_defaults. + Warning: + The `scale` argument of `hits_scores()` is deprecated as of igraph 2.1.5. + i The function always behaves as if `scale = TRUE`. The argument will be removed in the future. # `hub_score()` works @@ -23,93 +26,9 @@ arpack_defaults was deprecated in igraph 1.6.0. i Please use `arpack_defaults()` instead. i So the function arpack_defaults(), not an object called arpack_defaults. - -# eigen_centrality() deprecated scale argument - - Code - eigen_centrality(g, scale = TRUE) - Condition - Warning: - The `scale` argument of `eigen_centrality()` is deprecated as of igraph 2.1.1. - i eigen_centrality() will always behave as if scale=TRUE were used. - Output - $vector - [1] 1 1 1 1 1 1 1 1 1 1 - - $value - [1] 2 - - $options - $options$bmat - [1] "I" - - $options$n - [1] 10 - - $options$which - [1] "LA" - - $options$nev - [1] 1 - - $options$tol - [1] 0 - - $options$ncv - [1] 0 - - $options$ldv - [1] 0 - - $options$ishift - [1] 1 - - $options$maxiter - [1] 3000 - - $options$nb - [1] 1 - - $options$mode - [1] 1 - - $options$start - [1] 1 - - $options$sigma - [1] 0 - - $options$sigmai - [1] 0 - - $options$info - [1] 0 - - $options$iter - [1] 1 - - $options$nconv - [1] 1 - - $options$numop - [1] 7 - - $options$numopb - [1] 0 - - $options$numreo - [1] 5 - - - ---- - - Code - invisible(eigen_centrality(g, scale = FALSE)) - Condition Warning: - The `scale` argument of `eigen_centrality()` always as if TRUE as of igraph 2.1.1. - i Normalization is always performed + The `scale` argument of `hits_scores()` is deprecated as of igraph 2.1.5. + i The function always behaves as if `scale = TRUE`. The argument will be removed in the future. # arpack() errors well From 05f2158030c54a2abd9a7c3e1d2a01b10bf37cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Tue, 14 Oct 2025 14:26:14 +0200 Subject: [PATCH 030/154] chore: use new `mode` argument of `eigenvector_centrality_impl()` (#2200) --- R/centrality.R | 46 +++++++++++++-- man/distances.Rd | 14 ++--- man/eigen_centrality.Rd | 21 ++++++- tests/testthat/_snaps/centrality.md | 87 +++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 14 deletions(-) diff --git a/R/centrality.R b/R/centrality.R index 18b28772a39..0ec1c9c38a4 100644 --- a/R/centrality.R +++ b/R/centrality.R @@ -184,6 +184,8 @@ graph.diversity <- function(graph, weights = NULL, vids = V(graph)) { #' `evcent()` was renamed to [eigen_centrality()] to create a more #' consistent API. #' @inheritParams eigen_centrality +#' @param directed Logical scalar, whether to consider direction of the edges +#' in directed graphs. It is ignored for undirected graphs. #' @keywords internal #' @export evcent <- function( @@ -1312,7 +1314,7 @@ eigen_defaults <- function() { #' computation, see [arpack()] for more about ARPACK in igraph. #' #' @param graph Graph to be analyzed. -#' @param directed Logical scalar, whether to consider direction of the edges +#' @param directed `r lifecycle::badge("deprecated")` Logical scalar, whether to consider direction of the edges #' in directed graphs. It is ignored for undirected graphs. #' @param scale `r lifecycle::badge("deprecated")` Normalization will always take #' place. @@ -1329,6 +1331,17 @@ eigen_defaults <- function() { #' weights spread the centrality better. #' @param options A named list, to override some ARPACK options. See #' [arpack()] for details. +#' @param mode How to consider edge directions in directed graphs. +#' It is ignored for undirected graphs. +#' Possible values: +#' - `"out"` the left eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices pointing to it. This is the standard eigenvector centrality. +#' - `"in"` the right eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices it points to. +#' - `"all"` edge directions are ignored, +#' and the unweighted eigenvector centrality is calculated. #' @return A named list with components: #' \describe{ #' \item{vector}{ @@ -1358,10 +1371,11 @@ eigen_defaults <- function() { #' @cdocs igraph_eigenvector_centrality eigen_centrality <- function( graph, - directed = FALSE, + directed = deprecated(), scale = deprecated(), weights = NULL, - options = arpack_defaults() + options = arpack_defaults(), + mode = c("out", "in", "all") ) { if (is.function(options)) { lifecycle::deprecate_soft( @@ -1390,9 +1404,33 @@ eigen_centrality <- function( } } + mode <- igraph.match.arg(mode) + + if (lifecycle::is_present(directed)) { + if (directed) { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "out" + } + } else { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "all" + } + } + } + eigenvector_centrality_impl( graph = graph, - directed = directed, + mode = mode, weights = weights, options = options ) diff --git a/man/distances.Rd b/man/distances.Rd index 216c6319d2e..a9ebe93a875 100644 --- a/man/distances.Rd +++ b/man/distances.Rd @@ -14,7 +14,7 @@ mean_distance( graph, weights = NULL, directed = TRUE, - unconn = TRUE, + unconnected = TRUE, details = FALSE ) @@ -60,6 +60,12 @@ attribute is used. If this is \code{NA} then no weights are used (even if the graph has a \code{weight} attribute). In a weighted graph, the length of a path is the sum of the weights of its constituent edges.} +\item{unconnected}{What to do if the graph is unconnected (not +strongly connected if directed paths are considered). If TRUE, only +the lengths of the existing paths are considered and averaged; if +FALSE, the length of the missing paths are considered as having infinite +length, making the mean distance infinite as well.} + \item{details}{Whether to provide additional details in the result. Functions accepting this argument (like \code{mean_distance()}) return additional information like the number of disconnected vertex pairs in @@ -115,12 +121,6 @@ which vertex \code{i} was reached. The start vertex and vertices that were not reached during the search will have zero in the corresponding entry of the vector. Note that the search terminates if all the vertices in \code{to} are reached.} - -\item{unconnected}{What to do if the graph is unconnected (not -strongly connected if directed paths are considered). If TRUE, only -the lengths of the existing paths are considered and averaged; if -FALSE, the length of the missing paths are considered as having infinite -length, making the mean distance infinite as well.} } \value{ For \code{distances()} a numeric matrix with \code{length(to)} diff --git a/man/eigen_centrality.Rd b/man/eigen_centrality.Rd index c0b0975fbcd..f96a9b340dc 100644 --- a/man/eigen_centrality.Rd +++ b/man/eigen_centrality.Rd @@ -6,16 +6,17 @@ \usage{ eigen_centrality( graph, - directed = FALSE, + directed = deprecated(), scale = deprecated(), weights = NULL, - options = arpack_defaults() + options = arpack_defaults(), + mode = c("out", "in", "all") ) } \arguments{ \item{graph}{Graph to be analyzed.} -\item{directed}{Logical scalar, whether to consider direction of the edges +\item{directed}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Logical scalar, whether to consider direction of the edges in directed graphs. It is ignored for undirected graphs.} \item{scale}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Normalization will always take @@ -35,6 +36,20 @@ weights spread the centrality better.} \item{options}{A named list, to override some ARPACK options. See \code{\link[=arpack]{arpack()}} for details.} + +\item{mode}{How to consider edge directions in directed graphs. +It is ignored for undirected graphs. +Possible values: +\itemize{ +\item \code{"out"} the left eigenvector of the adjacency matrix is calculated, +i.e. the centrality of a vertex is proportional to the sum of centralities +of vertices pointing to it. This is the standard eigenvector centrality. +\item \code{"in"} the right eigenvector of the adjacency matrix is calculated, +i.e. the centrality of a vertex is proportional to the sum of centralities +of vertices it points to. +\item \code{"all"} edge directions are ignored, +and the unweighted eigenvector centrality is calculated. +}} } \value{ A named list with components: diff --git a/tests/testthat/_snaps/centrality.md b/tests/testthat/_snaps/centrality.md index 265cc5c4a65..3d3701120bb 100644 --- a/tests/testthat/_snaps/centrality.md +++ b/tests/testthat/_snaps/centrality.md @@ -30,6 +30,93 @@ The `scale` argument of `hits_scores()` is deprecated as of igraph 2.1.5. i The function always behaves as if `scale = TRUE`. The argument will be removed in the future. +# eigen_centrality() deprecated scale argument + + Code + eigen_centrality(g, scale = TRUE) + Condition + Warning: + The `scale` argument of `eigen_centrality()` is deprecated as of igraph 2.1.1. + i eigen_centrality() will always behave as if scale=TRUE were used. + Output + $vector + [1] 1 1 1 1 1 1 1 1 1 1 + + $value + [1] 2 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 10 + + $options$which + [1] "LA" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 7 + + $options$numopb + [1] 0 + + $options$numreo + [1] 4 + + + +--- + + Code + invisible(eigen_centrality(g, scale = FALSE)) + Condition + Warning: + The `scale` argument of `eigen_centrality()` always as if TRUE as of igraph 2.1.1. + i Normalization is always performed + # arpack() errors well Code From 19d0a50de7dfd7c9d9bc0dcb2006fac836712bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Wed, 15 Oct 2025 07:14:34 +0200 Subject: [PATCH 031/154] chore: `mode` argument of centralization functions (#2209) --- R/centralization.R | 79 +++++++++++++++++++++++++++++++++++------ man/centr_eigen.Rd | 22 +++++++++--- man/centr_eigen_tmax.Rd | 5 +-- 3 files changed, 90 insertions(+), 16 deletions(-) diff --git a/R/centralization.R b/R/centralization.R index 4db79aba77e..0925dc67cc4 100644 --- a/R/centralization.R +++ b/R/centralization.R @@ -56,6 +56,8 @@ centralization.evcent.tmax <- function( #' `centralization.evcent()` was renamed to [centr_eigen()] to create a more #' consistent API. #' @inheritParams centr_eigen +#' @param directed logical scalar, whether to use directed shortest paths for +#' calculating eigenvector centrality. #' @keywords internal #' @export centralization.evcent <- function( @@ -569,12 +571,22 @@ centr_clo_tmax <- centralization_closeness_tmax_impl #' See [centralize()] for a summary of graph centralization. #' #' @param graph The input graph. -#' @param directed logical scalar, whether to use directed shortest paths for -#' calculating eigenvector centrality. +#' @param directed `r lifecycle::badge("deprecated")` Use `mode` instead. #' @param scale `r lifecycle::badge("deprecated")` Ignored. Computing #' eigenvector centralization requires normalized eigenvector centrality scores. #' @param options This is passed to [eigen_centrality()], the options #' for the ARPACK eigensolver. +#' @param mode How to consider edge directions in directed graphs. +#' It is ignored for undirected graphs. +#' Possible values: +#' - `"out"` the left eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices pointing to it. This is the standard eigenvector centrality. +#' - `"in"` the right eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices it points to. +#' - `"all"` edge directions are ignored, +#' and the unweighted eigenvector centrality is calculated. #' @param normalized Logical scalar. Whether to normalize the graph level #' centrality score by dividing by the theoretical maximum. #' @return A named list with the following components: @@ -617,10 +629,11 @@ centr_clo_tmax <- centralization_closeness_tmax_impl #' @cdocs igraph_centralization_eigenvector_centrality centr_eigen <- function( graph, - directed = FALSE, + directed = deprecated(), scale = deprecated(), options = arpack_defaults(), - normalized = TRUE + normalized = TRUE, + mode = c("out", "in", "all") ) { if (lifecycle::is_present(scale)) { lifecycle::deprecate_soft( @@ -631,12 +644,35 @@ centr_eigen <- function( ) } + mode <- igraph.match.arg(mode) + + if (lifecycle::is_present(directed)) { + if (directed) { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "out" + } + } else { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "all" + } + } + } + centralization_eigenvector_centrality_impl( graph = graph, - directed = directed, options = options, normalized = normalized, - scale = TRUE + mode = mode ) } @@ -670,8 +706,9 @@ centr_eigen <- function( centr_eigen_tmax <- function( graph = NULL, nodes = 0, - directed = FALSE, - scale = deprecated() + directed = deprecated(), + scale = deprecated(), + mode = c("out", "in", "all") ) { if (lifecycle::is_present(scale)) { lifecycle::deprecate_soft( @@ -681,11 +718,33 @@ centr_eigen_tmax <- function( The argument will be removed in the future." ) } + mode <- igraph.match.arg(mode) + + if (lifecycle::is_present(directed)) { + if (directed) { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "out" + } + } else { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "all" + } + } + } centralization_eigenvector_centrality_tmax_impl( graph = graph, nodes = nodes, - directed = directed, - scale = TRUE + mode = mode ) } diff --git a/man/centr_eigen.Rd b/man/centr_eigen.Rd index e418e792712..6df0134744f 100644 --- a/man/centr_eigen.Rd +++ b/man/centr_eigen.Rd @@ -6,17 +6,17 @@ \usage{ centr_eigen( graph, - directed = FALSE, + directed = deprecated(), scale = deprecated(), options = arpack_defaults(), - normalized = TRUE + normalized = TRUE, + mode = c("out", "in", "all") ) } \arguments{ \item{graph}{The input graph.} -\item{directed}{logical scalar, whether to use directed shortest paths for -calculating eigenvector centrality.} +\item{directed}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Use \code{mode} instead.} \item{scale}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Ignored. Computing eigenvector centralization requires normalized eigenvector centrality scores.} @@ -26,6 +26,20 @@ for the ARPACK eigensolver.} \item{normalized}{Logical scalar. Whether to normalize the graph level centrality score by dividing by the theoretical maximum.} + +\item{mode}{How to consider edge directions in directed graphs. +It is ignored for undirected graphs. +Possible values: +\itemize{ +\item \code{"out"} the left eigenvector of the adjacency matrix is calculated, +i.e. the centrality of a vertex is proportional to the sum of centralities +of vertices pointing to it. This is the standard eigenvector centrality. +\item \code{"in"} the right eigenvector of the adjacency matrix is calculated, +i.e. the centrality of a vertex is proportional to the sum of centralities +of vertices it points to. +\item \code{"all"} edge directions are ignored, +and the unweighted eigenvector centrality is calculated. +}} } \value{ A named list with the following components: diff --git a/man/centr_eigen_tmax.Rd b/man/centr_eigen_tmax.Rd index 143d51252df..8b7718a95d6 100644 --- a/man/centr_eigen_tmax.Rd +++ b/man/centr_eigen_tmax.Rd @@ -7,8 +7,9 @@ centr_eigen_tmax( graph = NULL, nodes = 0, - directed = FALSE, - scale = deprecated() + directed = deprecated(), + scale = deprecated(), + mode = c("out", "in", "all") ) } \arguments{ From 350f218c6e2ec74558f25797e283422d4e1b23e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Sun, 19 Oct 2025 05:14:56 +0200 Subject: [PATCH 032/154] autogenerate mst (#2210) --- R/aaa-auto.R | 22 +++++++ R/minimum.spanning.tree.R | 38 ++++-------- man/minimum.spanning.tree.Rd | 2 +- man/mst.Rd | 9 ++- src/cpp11.cpp | 12 ++-- src/rinterface.c | 35 +++++++++++ src/rinterface_extra.c | 61 ------------------- .../testthat/_snaps/minimum.spanning.tree.md | 3 +- tools/stimulus/functions-R.yaml | 8 --- tools/stimulus/types-RR.yaml | 5 ++ 10 files changed, 91 insertions(+), 104 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index 3773e67904c..d8fbbf256ac 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -5411,6 +5411,28 @@ is_complete_impl <- function(graph) { res } +minimum_spanning_tree_impl <- function(graph, weights=NULL, method=c("automatic", "unweighted", "prim", "kruskal")) { + # Argument checks + ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && any(!is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } + method <- switch(igraph.match.arg(method), "automatic"=0L, "unweighted"=1L, "prim"=2L, "kruskal"=3L) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_minimum_spanning_tree, graph, weights, method) + if (igraph_opt("return.vs.es")) { + res <- create_es(graph, res) + } + res +} + random_spanning_tree_impl <- function(graph, vid=-1) { # Argument checks ensure_igraph(graph) diff --git a/R/minimum.spanning.tree.R b/R/minimum.spanning.tree.R index 4a47836555d..e5edb8eaf63 100644 --- a/R/minimum.spanning.tree.R +++ b/R/minimum.spanning.tree.R @@ -58,7 +58,7 @@ minimum.spanning.tree <- function( #' distances. #' @param algorithm The algorithm to use for calculation. `unweighted` can #' be used for unweighted graphs, and `prim` runs Prim's algorithm for -#' weighted graphs. If this is `NULL` then igraph will select the +#' weighted graphs. By default igraph will select the #' algorithm automatically: if the graph has an edge attribute called #' `weight` or the `weights` argument is not `NULL` then Prim's #' algorithm is chosen, otherwise the unweighted algorithm is used. @@ -79,29 +79,17 @@ minimum.spanning.tree <- function( #' g <- sample_gnp(100, 3 / 100) #' g_mst <- mst(g) #' -mst <- function(graph, weights = NULL, algorithm = NULL, ...) { +mst <- function( + graph, + weights = NULL, + algorithm = c("automatic", "unweighted", "prim", "kruskal"), + ... +) { ensure_igraph(graph) - - if (is.null(algorithm)) { - if (!is.null(weights) || "weight" %in% edge_attr_names(graph)) { - algorithm <- "prim" - } else { - algorithm <- "unweighted" - } - } - - if (algorithm == "unweighted") { - on.exit(.Call(R_igraph_finalizer)) - .Call(R_igraph_minimum_spanning_tree_unweighted, graph) - } else if (algorithm == "prim") { - if (is.null(weights) && !"weight" %in% edge_attr_names(graph)) { - cli::cli_abort("edges weights must be supplied for Prim's algorithm.") - } else if (is.null(weights)) { - weights <- E(graph)$weight - } - on.exit(.Call(R_igraph_finalizer)) - .Call(R_igraph_minimum_spanning_tree_prim, graph, as.numeric(weights)) - } else { - cli::cli_abort("Invalid {.arg algorithm}.") - } + algorithm <- igraph.match.arg(algorithm) + minimum_spanning_tree_impl( + graph, + weights = weights, + method = algorithm + ) } diff --git a/man/minimum.spanning.tree.Rd b/man/minimum.spanning.tree.Rd index 79dc14a82d9..fcef3779db3 100644 --- a/man/minimum.spanning.tree.Rd +++ b/man/minimum.spanning.tree.Rd @@ -16,7 +16,7 @@ distances.} \item{algorithm}{The algorithm to use for calculation. \code{unweighted} can be used for unweighted graphs, and \code{prim} runs Prim's algorithm for -weighted graphs. If this is \code{NULL} then igraph will select the +weighted graphs. By default igraph will select the algorithm automatically: if the graph has an edge attribute called \code{weight} or the \code{weights} argument is not \code{NULL} then Prim's algorithm is chosen, otherwise the unweighted algorithm is used.} diff --git a/man/mst.Rd b/man/mst.Rd index 686678e50e3..7f7335ab1b7 100644 --- a/man/mst.Rd +++ b/man/mst.Rd @@ -4,7 +4,12 @@ \alias{mst} \title{Minimum spanning tree} \usage{ -mst(graph, weights = NULL, algorithm = NULL, ...) +mst( + graph, + weights = NULL, + algorithm = c("automatic", "unweighted", "prim", "kruskal"), + ... +) } \arguments{ \item{graph}{The graph object to analyze.} @@ -16,7 +21,7 @@ distances.} \item{algorithm}{The algorithm to use for calculation. \code{unweighted} can be used for unweighted graphs, and \code{prim} runs Prim's algorithm for -weighted graphs. If this is \code{NULL} then igraph will select the +weighted graphs. By default igraph will select the algorithm automatically: if the graph has an edge attribute called \code{weight} or the \code{weights} argument is not \code{NULL} then Prim's algorithm is chosen, otherwise the unweighted algorithm is used.} diff --git a/src/cpp11.cpp b/src/cpp11.cpp index 40b2c6c1795..cfa33f7d5f7 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -246,7 +246,7 @@ extern SEXP R_igraph_hypercube(SEXP, SEXP); extern SEXP R_igraph_i_levc_arp(SEXP, SEXP, SEXP); extern SEXP R_igraph_identical_graphs(SEXP, SEXP, SEXP); extern SEXP R_igraph_iea_game(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_incident(SEXP, SEXP, SEXP); +extern SEXP R_igraph_incident(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_incident_edges(SEXP, SEXP, SEXP); extern SEXP R_igraph_independence_number(SEXP); extern SEXP R_igraph_independent_vertex_sets(SEXP, SEXP, SEXP); @@ -351,8 +351,7 @@ extern SEXP R_igraph_mincut(SEXP, SEXP); extern SEXP R_igraph_mincut_value(SEXP, SEXP); extern SEXP R_igraph_minimum_cycle_basis(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_minimum_size_separators(SEXP); -extern SEXP R_igraph_minimum_spanning_tree_prim(SEXP, SEXP); -extern SEXP R_igraph_minimum_spanning_tree_unweighted(SEXP); +extern SEXP R_igraph_minimum_spanning_tree(SEXP, SEXP, SEXP); extern SEXP R_igraph_modularity(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_modularity_matrix(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_motifs_randesu(SEXP, SEXP, SEXP); @@ -381,6 +380,7 @@ extern SEXP R_igraph_power_law_fit_new(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_preference_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_product(SEXP, SEXP, SEXP); extern SEXP R_igraph_pseudo_diameter(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_radius(SEXP, SEXP, SEXP); extern SEXP R_igraph_random_sample(SEXP, SEXP, SEXP); extern SEXP R_igraph_random_spanning_tree(SEXP, SEXP); extern SEXP R_igraph_random_walk(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); @@ -719,7 +719,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_i_levc_arp", (DL_FUNC) &R_igraph_i_levc_arp, 3}, {"R_igraph_identical_graphs", (DL_FUNC) &R_igraph_identical_graphs, 3}, {"R_igraph_iea_game", (DL_FUNC) &R_igraph_iea_game, 4}, - {"R_igraph_incident", (DL_FUNC) &R_igraph_incident, 3}, + {"R_igraph_incident", (DL_FUNC) &R_igraph_incident, 4}, {"R_igraph_incident_edges", (DL_FUNC) &R_igraph_incident_edges, 3}, {"R_igraph_independence_number", (DL_FUNC) &R_igraph_independence_number, 1}, {"R_igraph_independent_vertex_sets", (DL_FUNC) &R_igraph_independent_vertex_sets, 3}, @@ -824,8 +824,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_mincut_value", (DL_FUNC) &R_igraph_mincut_value, 2}, {"R_igraph_minimum_cycle_basis", (DL_FUNC) &R_igraph_minimum_cycle_basis, 5}, {"R_igraph_minimum_size_separators", (DL_FUNC) &R_igraph_minimum_size_separators, 1}, - {"R_igraph_minimum_spanning_tree_prim", (DL_FUNC) &R_igraph_minimum_spanning_tree_prim, 2}, - {"R_igraph_minimum_spanning_tree_unweighted", (DL_FUNC) &R_igraph_minimum_spanning_tree_unweighted, 1}, + {"R_igraph_minimum_spanning_tree", (DL_FUNC) &R_igraph_minimum_spanning_tree, 3}, {"R_igraph_modularity", (DL_FUNC) &R_igraph_modularity, 5}, {"R_igraph_modularity_matrix", (DL_FUNC) &R_igraph_modularity_matrix, 4}, {"R_igraph_motifs_randesu", (DL_FUNC) &R_igraph_motifs_randesu, 3}, @@ -854,6 +853,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_preference_game", (DL_FUNC) &R_igraph_preference_game, 7}, {"R_igraph_product", (DL_FUNC) &R_igraph_product, 3}, {"R_igraph_pseudo_diameter", (DL_FUNC) &R_igraph_pseudo_diameter, 5}, + {"R_igraph_radius", (DL_FUNC) &R_igraph_radius, 3}, {"R_igraph_random_sample", (DL_FUNC) &R_igraph_random_sample, 3}, {"R_igraph_random_spanning_tree", (DL_FUNC) &R_igraph_random_spanning_tree, 2}, {"R_igraph_random_walk", (DL_FUNC) &R_igraph_random_walk, 6}, diff --git a/src/rinterface.c b/src/rinterface.c index 72e2bf616b7..7a24a72012b 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -12731,6 +12731,41 @@ SEXP R_igraph_is_complete(SEXP graph) { return(r_result); } +/*-------------------------------------------/ +/ igraph_minimum_spanning_tree / +/-------------------------------------------*/ +SEXP R_igraph_minimum_spanning_tree(SEXP graph, SEXP weights, SEXP method) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_int_t c_res; + igraph_vector_t c_weights; + igraph_mst_algorithm_t c_method; + SEXP res; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + IGRAPH_R_CHECK(igraph_vector_int_init(&c_res, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_res); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } + c_method = (igraph_mst_algorithm_t) Rf_asInteger(method); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_minimum_spanning_tree(&c_graph, &c_res, (Rf_isNull(weights) ? NULL : &c_weights), c_method)); + PutRNGstate(); + + /* Convert output */ + PROTECT(res=R_igraph_vector_int_to_SEXPp1(&c_res)); + igraph_vector_int_destroy(&c_res); + IGRAPH_FINALLY_CLEAN(1); + r_result = res; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_random_spanning_tree / /-------------------------------------------*/ diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 9f210450491..f1f288d1a19 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -4506,67 +4506,6 @@ SEXP R_igraph_layout_lgl(SEXP graph, SEXP pmaxiter, SEXP pmaxdelta, return result; } -SEXP R_igraph_minimum_spanning_tree_unweighted(SEXP graph) { - - igraph_t g; - SEXP result; - - R_SEXP_to_igraph(graph, &g); - - igraph_vector_int_t edges; - IGRAPH_R_CHECK(igraph_minimum_spanning_tree(&g, &edges, NULL, IGRAPH_MST_UNWEIGHTED)); - IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &edges); - - igraph_es_t edge_set; - IGRAPH_R_CHECK(igraph_edges(&g, edge_set, &edges, false)); - IGRAPH_FINALLY_PV(igraph_es_destroy, &edge_set); - igraph_vector_int_destroy(&edges); - - igraph_t mst; - IGRAPH_R_CHECK(igraph_subgraph_from_edges(&g, &mst, edge_set, true)); - igraph_es_destroy(&edge_set); - - PROTECT(result=R_igraph_to_SEXP(&mst)); - IGRAPH_I_DESTROY(&mst); - - IGRAPH_FINALLY_CLEAN(2); - - UNPROTECT(1); - return result; -} - -SEXP R_igraph_minimum_spanning_tree_prim(SEXP graph, SEXP pweights) { - - igraph_t g; - igraph_vector_t weights; - SEXP result; - - R_SEXP_to_vector(pweights, &weights); - - R_SEXP_to_igraph(graph, &g); - - igraph_vector_int_t edges; - IGRAPH_R_CHECK(igraph_minimum_spanning_tree(&g, &edges, &weights, IGRAPH_MST_PRIM)); - IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &edges); - - igraph_es_t edge_set; - IGRAPH_R_CHECK(igraph_edges(&g, edge_set, &edges, false)); - IGRAPH_FINALLY_PV(igraph_es_destroy, &edge_set); - igraph_vector_int_destroy(&edges); - - igraph_t mst; - IGRAPH_R_CHECK(igraph_subgraph_from_edges(&g, &mst, edge_set, true)); - igraph_es_destroy(&edge_set); - - PROTECT(result=R_igraph_to_SEXP(&mst)); - IGRAPH_I_DESTROY(&mst); - - IGRAPH_FINALLY_CLEAN(2); - - UNPROTECT(1); - return result; -} - SEXP R_igraph_get_shortest_paths(SEXP graph, SEXP pfrom, SEXP pto, SEXP pmode, SEXP pno, SEXP weights, SEXP output, SEXP ppred, SEXP pinbound, diff --git a/tests/testthat/_snaps/minimum.spanning.tree.md b/tests/testthat/_snaps/minimum.spanning.tree.md index 9cdfaeb90d6..d14e5554966 100644 --- a/tests/testthat/_snaps/minimum.spanning.tree.md +++ b/tests/testthat/_snaps/minimum.spanning.tree.md @@ -4,5 +4,6 @@ mst(g, algorithm = "undefined") Condition Error in `mst()`: - ! Invalid `algorithm`. + ! `algorithm` must be one of "automatic", "unweighted", "prim", or "kruskal", not "undefined". + i Did you mean "unweighted"? diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 4db2ae8fb63..0522aeeaae5 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -990,14 +990,6 @@ igraph_from_prufer: name: Tree from Prufer sequence GATTR-PARAM: prufer -igraph_minimum_spanning_tree: - IGNORE: RR, RC, RInit - -igraph_minimum_spanning_tree_unweighted: - IGNORE: RR, RC - -igraph_minimum_spanning_tree_prim: - IGNORE: RR, RC ####################################### # Coloring diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index efe7931026e..fd8318553a9 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -546,3 +546,8 @@ VERTEX_WEIGHTS: } else { %I% <- NULL } + +MSTALGORITHM: + DEFAULT: + AUTOMATIC: c("automatic", "unweighted", "prim", "kruskal") + INCONV: '%I% <- switch(igraph.match.arg(%I%), "automatic"=0L, "unweighted"=1L, "prim"=2L, "kruskal"=3L)' From 9676f0c1d31622f32de922eef94d13a72d95eafd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Sun, 19 Oct 2025 05:24:02 +0200 Subject: [PATCH 033/154] lpa_variant (#2203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kirill Müller --- R/community.R | 17 +++++++++++++---- man/cluster_label_prop.Rd | 10 +++++++++- tools/stimulus/types-RR.yaml | 4 +++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/R/community.R b/R/community.R index e8c41be9f92..d70b02ef4e0 100644 --- a/R/community.R +++ b/R/community.R @@ -2343,6 +2343,10 @@ cluster_leading_eigen <- function( #' @param fixed Logical vector denoting which labels are fixed. Of course this #' makes sense only if you provided an initial state, otherwise this element #' will be ignored. Also note that vertices without labels cannot be fixed. +#' @param lpa_variant Which variant of the label propagation algorithm to run. +#' - `"dominance"` (default) check for dominance of all nodes after each iteration. +#' - `"retention"` keep current label if among dominant labels, only check if labels changed. +#' - `"fast"` sample from dominant labels, only check neighbors. #' @return `cluster_label_prop()` returns a #' [communities()] object, please see the [communities()] #' manual page for details. @@ -2371,7 +2375,8 @@ cluster_label_prop <- function( ..., mode = c("out", "in", "all"), initial = NULL, - fixed = NULL + fixed = NULL, + lpa_variant = c("dominance", "retention", "fast") ) { if (...length() > 0) { lifecycle::deprecate_soft( @@ -2393,7 +2398,7 @@ cluster_label_prop <- function( return(inject(cluster_label_prop0(!!!dots))) } - cluster_label_prop0(graph, weights, mode, initial, fixed) + cluster_label_prop0(graph, weights, mode, initial, fixed, lpa_variant) } cluster_label_prop0 <- function( @@ -2401,13 +2406,15 @@ cluster_label_prop0 <- function( weights = NULL, mode = c("out", "in", "all"), initial = NULL, - fixed = NULL + fixed = NULL, + lpa_variant = c("dominance", "retention", "fast") ) { # Argument checks ensure_igraph(graph) # Necessary because evaluated later mode <- igraph.match.arg(mode) + lpa_variant <- igraph.match.arg(lpa_variant) # Function call membership <- community_label_propagation_impl( @@ -2415,8 +2422,10 @@ cluster_label_prop0 <- function( mode = mode, weights = weights, initial = initial, - fixed = fixed + fixed = fixed, + lpa.variant = lpa_variant ) + res <- list() if (igraph_opt("add.vertex.names") && is_named(graph)) { res$names <- V(graph)$name diff --git a/man/cluster_label_prop.Rd b/man/cluster_label_prop.Rd index 86ec14c870f..25c61d2ca0f 100644 --- a/man/cluster_label_prop.Rd +++ b/man/cluster_label_prop.Rd @@ -10,7 +10,8 @@ cluster_label_prop( ..., mode = c("out", "in", "all"), initial = NULL, - fixed = NULL + fixed = NULL, + lta_variant = c("dominance", "retention", "fast") ) } \arguments{ @@ -43,6 +44,13 @@ entries denote vertices without labels.} \item{fixed}{Logical vector denoting which labels are fixed. Of course this makes sense only if you provided an initial state, otherwise this element will be ignored. Also note that vertices without labels cannot be fixed.} + +\item{lpa_variant}{Which variant of the label propagation algorithm to run. +\itemize{ +\item \code{"dominance"} (default) check for dominance of all nodes after each iteration. +\item \code{"retention"} keep current label if among dominant labels, only check if labels changed. +\item \code{"fast"} sample from dominant labels, only check neighbors. +}} } \value{ \code{cluster_label_prop()} returns a diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index fd8318553a9..b8b3388f4e3 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -435,7 +435,9 @@ RWSTUCK: LPA_VARIANT: DEFAULT: - Default: c("dominance", "retention", "fast") + DOMINANCE: c("dominance", "retention", "fast") + RETENTION: c("retention", "dominance", "fast") + FAST: c("fast", "dominance", "retention") INCONV: |- %I% <- switch(igraph.match.arg(%I%), "dominance"=0L, "retention"=1L, "fast"=2L) From 7509b5db8a56f98308b02bc35af1944ce7f5dc01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 7 Sep 2025 21:19:51 +0200 Subject: [PATCH 034/154] chore: Fix seed for test (#2118) --- tests/testthat/test-centrality.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/testthat/test-centrality.R b/tests/testthat/test-centrality.R index 94bfae14cfa..ee7a8c28aea 100644 --- a/tests/testthat/test-centrality.R +++ b/tests/testthat/test-centrality.R @@ -576,6 +576,8 @@ test_that("eigen_centrality() works", { ## Eigenvector-centrality, small stress-test + set.seed(20250907) + is.principal <- function(M, lambda, eps = 1e-12) { abs(eigen(M)$values[1] - lambda) < eps } From 1f93d97e9bbd487bf7b55edee9120433e0053350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 05:01:56 +0200 Subject: [PATCH 035/154] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4ed4b8401634f5cc218682087f1dae5343d3d05a Author: Kirill Müller Date: Sun Oct 19 05:00:13 2025 +0200 Tweak commit f55607b18eb2c003069202a67a0528ba1aad0469 Merge: 6346766cae 0efd1c4376 Author: Kirill Müller Date: Sun Oct 19 04:57:27 2025 +0200 Merge branch 'main' into new-tests commit 6346766cae2a037cb0ab34b445f315268efa5a6c Author: Maëlle Salmon Date: Fri Oct 17 14:44:18 2025 +0200 test: improve centralitystress test --- tests/testthat/test-centrality.R | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/tests/testthat/test-centrality.R b/tests/testthat/test-centrality.R index ee7a8c28aea..cc9f448198a 100644 --- a/tests/testthat/test-centrality.R +++ b/tests/testthat/test-centrality.R @@ -146,31 +146,28 @@ test_that("authority_score survives stress test", { withr::local_seed(42) - is.principal <- function(M, lambda) { + expect_principal <- function(M, lambda) { expect_equal(eigen(M)$values[1], lambda) } - is.ev <- function(M, v, lambda) { + expect_ev <- function(M, v, lambda) { expect_equal(as.vector(M %*% v), lambda * v) } - is.good <- function(M, v, lambda) { - is.principal(M, lambda) - is.ev(M, v, lambda) + expect_good <- function(M, v, lambda) { + expect_principal(M, lambda) + expect_ev(M, v, lambda) } for (i in 1:100) { - G <- sample_gnm(10, sample(1:20, 1)) - as <- hits_scores(G) - M <- as_adjacency_matrix(G, sparse = FALSE) - is.good(t(M) %*% M, as$authority, as$value) - } - - for (i in 1:100) { - G <- sample_gnm(10, sample(1:20, 1)) + repeat { + G <- sample_gnm(10, sample(15:25, 1), directed = FALSE) + if (is_connected(G)) break + } + G <- as_directed(G, mode = "mutual") hs <- hits_scores(G) M <- as_adjacency_matrix(G, sparse = FALSE) - is.good(M %*% t(M), hs$hub, hs$value) + expect_good(M %*% t(M), hs$hub, hs$value) } }) @@ -578,26 +575,27 @@ test_that("eigen_centrality() works", { set.seed(20250907) - is.principal <- function(M, lambda, eps = 1e-12) { - abs(eigen(M)$values[1] - lambda) < eps + expect_principal <- function(M, lambda, eps = 1e-12) { + expect_lt(abs(eigen(M)$values[1] - lambda), eps) } - is.ev <- function(M, v, lambda, eps = 1e-12) { - max(abs(M %*% v - lambda * v)) < eps + expect_ev <- function(M, v, lambda, eps = 1e-12) { + expect_lt(max(abs(M %*% v - lambda * v)), eps) } - is.good <- function(M, v, lambda, eps = 1e-12) { - is.principal(M, lambda, eps) && is.ev(M, v, lambda, eps) + expect_good <- function(M, v, lambda, eps = 1e-12) { + expect_principal(M, lambda, eps) + expect_ev(M, v, lambda, eps) } for (i in 1:1000) { G <- sample_gnm(10, sample(1:20, 1)) ev <- eigen_centrality(G) - expect_true(is.good( + expect_good( as_adjacency_matrix(G, sparse = FALSE), ev$vector, ev$value - )) + ) } }) From 9da2dcc66676d05ecbd96e157248887e32f465ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 05:08:18 +0200 Subject: [PATCH 036/154] Squelch warnings --- tests/testthat/test-centrality.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-centrality.R b/tests/testthat/test-centrality.R index cc9f448198a..392acf64471 100644 --- a/tests/testthat/test-centrality.R +++ b/tests/testthat/test-centrality.R @@ -590,7 +590,8 @@ test_that("eigen_centrality() works", { for (i in 1:1000) { G <- sample_gnm(10, sample(1:20, 1)) - ev <- eigen_centrality(G) + # FIXME: Find a way to avoid warnings + suppressWarnings(ev <- eigen_centrality(G)) expect_good( as_adjacency_matrix(G, sparse = FALSE), ev$vector, From dd30150ad41ed35ff1a0179ba93db31e238ae44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Mon, 18 Aug 2025 08:53:58 +0000 Subject: [PATCH 037/154] chore: add modular product to GRAPH_PRODUCT_TYPE in interfaces --- tools/stimulus/types-RR.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index b8b3388f4e3..f861d57e541 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -454,12 +454,13 @@ EDGE_TYPE_SW: GRAPH_PRODUCT_TYPE: DEFAULT: - CARTESIAN: c("cartesian", "lexicographic", "strong", "tensor") - LEXICOGRAPHIC: c("lexicographic", "cartesian", "strong", "tensor") - STRONG: c("strong", "cartesian", "lexicographic", "tensor") - TENSOR: c("tensor", "cartesian", "lexicographic", "strong") + CARTESIAN: c("cartesian", "lexicographic", "strong", "tensor", "modular") + LEXICOGRAPHIC: c("lexicographic", "cartesian", "strong", "tensor", "modular") + STRONG: c("strong", "cartesian", "lexicographic", "tensor", "modular") + TENSOR: c("tensor", "cartesian", "lexicographic", "strong", "modular") + MODULAR: c("modular", "cartesian", "lexicographic", "strong", "tensor") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "cartesian"=0L, "lexicographic"=1L, "strong"=2L, "tensor"=3L) + %I% <- switch(igraph.match.arg(%I%), "cartesian"=0L, "lexicographic"=1L, "strong"=2L, "tensor"=3L, "modular"=4L) RANDOM_TREE_METHOD: DEFAULT: From 5bdb849905af9639d6bbc8183a3b081f8ea4fbf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 07:28:19 +0200 Subject: [PATCH 038/154] Improve readability of code about not all values being `NA` (#2082) --- R/aaa-auto.R | 168 +++++++++++++++++------------------ tools/stimulus/types-RR.yaml | 4 +- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index d8fbbf256ac..0efaf034194 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -838,7 +838,7 @@ diameter_impl <- function(graph, weights=NULL, directed=TRUE, unconnected=TRUE) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -861,7 +861,7 @@ closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "tot if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -885,7 +885,7 @@ closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -908,7 +908,7 @@ get_shortest_path_impl <- function(graph, weights=NULL, from, to, mode=c("out", if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -949,7 +949,7 @@ get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, m if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -982,7 +982,7 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode= if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1007,7 +1007,7 @@ get_all_shortest_paths_impl <- function(graph, weights=NULL, from, to, mode=c("o if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1037,7 +1037,7 @@ get_all_shortest_paths_dijkstra_impl <- function(graph, from, to=V(graph), weigh if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1059,7 +1059,7 @@ voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1100,7 +1100,7 @@ get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mod if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1137,7 +1137,7 @@ get_widest_path_impl <- function(graph, from, to, weights, mode=c("out", "in", " if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1167,7 +1167,7 @@ get_widest_paths_impl <- function(graph, from, to=V(graph), weights, mode=c("out if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1189,7 +1189,7 @@ widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph), if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1211,7 +1211,7 @@ widest_path_widths_floyd_warshall_impl <- function(graph, from=V(graph), to=V(gr if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1232,7 +1232,7 @@ spanner_impl <- function(graph, stretch, weights=NULL) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1255,7 +1255,7 @@ betweenness_cutoff_impl <- function(graph, vids=V(graph), directed=TRUE, weights if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1281,7 +1281,7 @@ betweenness_subset_impl <- function(graph, vids=V(graph), directed=TRUE, sources if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1303,7 +1303,7 @@ edge_betweenness_impl <- function(graph, directed=TRUE, weights=NULL) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1323,7 +1323,7 @@ edge_betweenness_cutoff_impl <- function(graph, directed=TRUE, weights=NULL, cut if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1347,7 +1347,7 @@ edge_betweenness_subset_impl <- function(graph, eids=E(graph), directed=TRUE, so if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1370,7 +1370,7 @@ harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1398,7 +1398,7 @@ personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1433,7 +1433,7 @@ personalized_pagerank_vs_impl <- function(graph, algo=c("prpack", "arpack"), vid if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1504,7 +1504,7 @@ average_path_length_impl <- function(graph, weights=NULL, directed=TRUE, unconn= if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1591,7 +1591,7 @@ transitivity_barrat_impl <- function(graph, vids=V(graph), weights=NULL, mode=c( if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1678,7 +1678,7 @@ feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "e if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1700,7 +1700,7 @@ feedback_vertex_set_impl <- function(graph, weights=NULL, algo=c("exact_ip")) { if (is.null(weights) && "weight" %in% vertex_attr_names(graph)) { weights <- V(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1837,7 +1837,7 @@ eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1859,7 +1859,7 @@ hub_and_authority_scores_impl <- function(graph, weights=NULL, options=arpack_de if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1938,7 +1938,7 @@ avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all", if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1959,7 +1959,7 @@ degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -1981,7 +1981,7 @@ rich_club_sequence_impl <- function(graph, weights=NULL, vertex.order, normalize if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2007,7 +2007,7 @@ strength_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "tota if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2176,7 +2176,7 @@ joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=-1, max if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2197,7 +2197,7 @@ joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2222,7 +2222,7 @@ joint_type_distribution_impl <- function(graph, weights=NULL, from.types, to.typ if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2258,7 +2258,7 @@ eccentricity_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all", if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2281,7 +2281,7 @@ graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "t if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2303,7 +2303,7 @@ radius_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total") if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2323,7 +2323,7 @@ pseudo_diameter_impl <- function(graph, weights=NULL, start.vid, directed=TRUE, if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2348,7 +2348,7 @@ diversity_impl <- function(graph, weights=NULL, vids=V(graph)) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2370,7 +2370,7 @@ random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "i if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2401,7 +2401,7 @@ global_efficiency_impl <- function(graph, weights=NULL, directed=TRUE) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2421,7 +2421,7 @@ local_efficiency_impl <- function(graph, weights=NULL, vids=V(graph), directed=T if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2445,7 +2445,7 @@ average_local_efficiency_impl <- function(graph, weights=NULL, directed=TRUE, mo if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2577,7 +2577,7 @@ get_biadjacency_impl <- function(graph, types, weights=NULL) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2661,7 +2661,7 @@ get_laplacian_impl <- function(graph, mode=c("out", "in", "all", "total"), norma if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2682,7 +2682,7 @@ get_laplacian_sparse_impl <- function(graph, mode=c("out", "in", "all", "total") if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -2898,7 +2898,7 @@ weighted_cliques_impl <- function(graph, vertex.weights=NULL, min.weight=0, max. if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { vertex.weights <- V(graph)$weight } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + if (!is.null(vertex.weights) && !all(is.na(vertex.weights))) { vertex.weights <- as.numeric(vertex.weights) } else { vertex.weights <- NULL @@ -2920,7 +2920,7 @@ largest_weighted_cliques_impl <- function(graph, vertex.weights=NULL) { if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { vertex.weights <- V(graph)$weight } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + if (!is.null(vertex.weights) && !all(is.na(vertex.weights))) { vertex.weights <- as.numeric(vertex.weights) } else { vertex.weights <- NULL @@ -2939,7 +2939,7 @@ weighted_clique_number_impl <- function(graph, vertex.weights=NULL) { if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { vertex.weights <- V(graph)$weight } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + if (!is.null(vertex.weights) && !all(is.na(vertex.weights))) { vertex.weights <- as.numeric(vertex.weights) } else { vertex.weights <- NULL @@ -3073,7 +3073,7 @@ layout_drl_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$def if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3095,7 +3095,7 @@ layout_drl_3d_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$ if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3118,7 +3118,7 @@ layout_sugiyama_impl <- function(graph, layers=NULL, hgap=1, vgap=1, maxiter=100 if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3373,7 +3373,7 @@ modularity_impl <- function(graph, membership, weights=NULL, resolution=1.0, dir if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3394,7 +3394,7 @@ modularity_matrix_impl <- function(graph, weights=NULL, resolution=1.0, directed if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3428,7 +3428,7 @@ community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", " if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3451,7 +3451,7 @@ community_multilevel_impl <- function(graph, weights=NULL, resolution=1.0) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3471,7 +3471,7 @@ community_optimal_modularity_impl <- function(graph, weights=NULL, resolution=1. if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3491,7 +3491,7 @@ community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3499,7 +3499,7 @@ community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, if (is.null(vertex.out.weights) && "weight" %in% vertex_attr_names(graph)) { vertex.out.weights <- V(graph)$weight } - if (!is.null(vertex.out.weights) && any(!is.na(vertex.out.weights))) { + if (!is.null(vertex.out.weights) && !all(is.na(vertex.out.weights))) { vertex.out.weights <- as.numeric(vertex.out.weights) } else { vertex.out.weights <- NULL @@ -3507,7 +3507,7 @@ community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, if (is.null(vertex.in.weights) && "weight" %in% vertex_attr_names(graph)) { vertex.in.weights <- V(graph)$weight } - if (!is.null(vertex.in.weights) && any(!is.na(vertex.in.weights))) { + if (!is.null(vertex.in.weights) && !all(is.na(vertex.in.weights))) { vertex.in.weights <- as.numeric(vertex.in.weights) } else { vertex.in.weights <- NULL @@ -3543,7 +3543,7 @@ community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL if (is.null(edge.weights) && "weight" %in% edge_attr_names(graph)) { edge.weights <- E(graph)$weight } - if (!is.null(edge.weights) && any(!is.na(edge.weights))) { + if (!is.null(edge.weights) && !all(is.na(edge.weights))) { edge.weights <- as.numeric(edge.weights) } else { edge.weights <- NULL @@ -3551,7 +3551,7 @@ community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { vertex.weights <- V(graph)$weight } - if (!is.null(vertex.weights) && any(!is.na(vertex.weights))) { + if (!is.null(vertex.weights) && !all(is.na(vertex.weights))) { vertex.weights <- as.numeric(vertex.weights) } else { vertex.weights <- NULL @@ -3571,7 +3571,7 @@ graphlets_impl <- function(graph, weights=NULL, niter=1000) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3750,7 +3750,7 @@ get_adjacency_sparse_impl <- function(graph, type=c("both", "upper", "lower"), w if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3771,7 +3771,7 @@ get_stochastic_impl <- function(graph, column.wise=FALSE, weights=NULL) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3791,7 +3791,7 @@ get_stochastic_sparse_impl <- function(graph, column.wise=FALSE, weights=NULL) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3921,7 +3921,7 @@ local_scan_0_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "t if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3942,7 +3942,7 @@ local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "i if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { weights.them <- E(them)$weight } - if (!is.null(weights.them) && any(!is.na(weights.them))) { + if (!is.null(weights.them) && !all(is.na(weights.them))) { weights.them <- as.numeric(weights.them) } else { weights.them <- NULL @@ -3962,7 +3962,7 @@ local_scan_1_ecount_impl <- function(graph, weights=NULL, mode=c("out", "in", "a if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -3983,7 +3983,7 @@ local_scan_1_ecount_them_impl <- function(us, them, weights.them=NULL, mode=c("o if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { weights.them <- E(them)$weight } - if (!is.null(weights.them) && any(!is.na(weights.them))) { + if (!is.null(weights.them) && !all(is.na(weights.them))) { weights.them <- as.numeric(weights.them) } else { weights.them <- NULL @@ -4004,7 +4004,7 @@ local_scan_k_ecount_impl <- function(graph, k, weights=NULL, mode=c("out", "in", if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -4026,7 +4026,7 @@ local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c if (is.null(weights.them) && "weight" %in% edge_attr_names(them)) { weights.them <- E(them)$weight } - if (!is.null(weights.them) && any(!is.na(weights.them))) { + if (!is.null(weights.them) && !all(is.na(weights.them))) { weights.them <- as.numeric(weights.them) } else { weights.them <- NULL @@ -4046,7 +4046,7 @@ local_scan_neighborhood_ecount_impl <- function(graph, weights=NULL, neighborhoo if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -4065,7 +4065,7 @@ local_scan_subset_ecount_impl <- function(graph, weights=NULL, subsets) { if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -4128,11 +4128,11 @@ mycielskian_impl <- function(graph, k=1) { res } -product_impl <- function(g1, g2, type=c("cartesian", "lexicographic", "strong", "tensor")) { +product_impl <- function(g1, g2, type=c("cartesian", "lexicographic", "strong", "tensor", "modular")) { # Argument checks ensure_igraph(g1) ensure_igraph(g2) - type <- switch(igraph.match.arg(type), "cartesian"=0L, "lexicographic"=1L, "strong"=2L, "tensor"=3L) + type <- switch(igraph.match.arg(type), "cartesian"=0L, "lexicographic"=1L, "strong"=2L, "tensor"=3L, "modular"=4L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5063,7 +5063,7 @@ maximum_bipartite_matching_impl <- function(graph, types, weights=NULL, eps=.Mac if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -5084,7 +5084,7 @@ adjacency_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -5108,7 +5108,7 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -5292,7 +5292,7 @@ fundamental_cycles_impl <- function(graph, start=-1, bfs.cutoff=-1, weights=NULL if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -5314,7 +5314,7 @@ minimum_cycle_basis_impl <- function(graph, bfs.cutoff=-1, complete=TRUE, use.cy if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL @@ -5417,7 +5417,7 @@ minimum_spanning_tree_impl <- function(graph, weights=NULL, method=c("automatic" if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } - if (!is.null(weights) && any(!is.na(weights))) { + if (!is.null(weights) && !all(is.na(weights))) { weights <- as.numeric(weights) } else { weights <- NULL diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index f861d57e541..b44fedd204e 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -533,7 +533,7 @@ EDGE_WEIGHTS: if (is.null(%I%) && "weight" %in% edge_attr_names(%I1%)) { %I% <- E(%I1%)$weight } - if (!is.null(%I%) && any(!is.na(%I%))) { + if (!is.null(%I%) && !all(is.na(%I%))) { %I% <- as.numeric(%I%) } else { %I% <- NULL @@ -544,7 +544,7 @@ VERTEX_WEIGHTS: if (is.null(%I%) && "weight" %in% vertex_attr_names(%I1%)) { %I% <- V(%I1%)$weight } - if (!is.null(%I%) && any(!is.na(%I%))) { + if (!is.null(%I%) && !all(is.na(%I%))) { %I% <- as.numeric(%I%) } else { %I% <- NULL From 41cfe499f42f1a447fa0869e1e197d2955049a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 1 Sep 2025 14:23:09 +0200 Subject: [PATCH 039/154] chore: create list of custom tasks for release (#2096) --- R/release.R | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 R/release.R diff --git a/R/release.R b/R/release.R new file mode 100644 index 00000000000..21f7cb82132 --- /dev/null +++ b/R/release.R @@ -0,0 +1,12 @@ +# https://usethis.r-lib.org/reference/use_release_issue.html#customization +# https://github.com/igraph/rigraph/issues/1976 +release_bullets <- function() { + c( + "`allcontributors::add_contributors()` to update allcontributors' data in the README.", + "Update docs based on the C docs.", + "Draft a post for the igraph and cynkra blogs.", + "Submit link to that post to R weekly + cynkra's social media platforms.", + "Add the link to the blog post to the pkgdown's release menu.", + "Announce the release on the igraph forum." + ) +} From a690c663089bb0aeae71c9b0a794cd57ece068c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Mon, 1 Sep 2025 18:25:45 +0000 Subject: [PATCH 040/154] refactor: avoid repeated calls to _size() functions in for loops as this has a non-neglibile performance impact --- src/rinterface_extra.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index f1f288d1a19..171fa183c69 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -3377,11 +3377,11 @@ 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); + const igraph_integer_t length = Rf_xlength(rval); 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; istor_begin[i]=(char*) CHAR(STRING_ELT(rval, i)); } @@ -3389,8 +3389,9 @@ igraph_error_t R_igraph_SEXP_to_strvector(SEXP rval, igraph_strvector_t *sv) { } igraph_error_t R_igraph_SEXP_to_strvector_copy(SEXP rval, igraph_strvector_t *sv) { - IGRAPH_STRVECTOR_INIT_FINALLY(sv, Rf_xlength(rval)); - for (igraph_integer_t i=0; i Date: Sun, 19 Oct 2025 07:32:51 +0200 Subject: [PATCH 041/154] refactor: some cleanup in vs/es functions in rinterface_extra.c --- src/rinterface_extra.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 171fa183c69..1ab62ad8c14 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -3512,7 +3512,7 @@ igraph_error_t R_SEXP_to_igraph_copy(SEXP graph, igraph_t *res) { igraph_error_t R_SEXP_to_igraph_vs(SEXP rit, igraph_t *graph, igraph_vs_t *it, igraph_vector_int_t *data) { IGRAPH_CHECK(R_SEXP_to_vector_int_copy(rit, data)); - igraph_vs_vector(it, data); + IGRAPH_CHECK(igraph_vs_vector(it, data)); return IGRAPH_SUCCESS; } @@ -3524,7 +3524,7 @@ igraph_error_t R_SEXP_to_igraph_vs(SEXP rit, igraph_t *graph, igraph_vs_t *it, i igraph_error_t R_SEXP_to_igraph_es(SEXP rit, igraph_t *graph, igraph_es_t *it, igraph_vector_int_t *data) { IGRAPH_CHECK(R_SEXP_to_vector_int_copy(rit, data)); - igraph_es_vector(it, data); + IGRAPH_CHECK(igraph_es_vector(it, data)); return IGRAPH_SUCCESS; } @@ -5767,18 +5767,23 @@ SEXP R_igraph_vs_nei(SEXP graph, SEXP px, SEXP pv, SEXP pmode) { igraph_vector_int_init(&neis, 0); igraph_vit_create(&g, v, &vv); PROTECT(result=NEW_LOGICAL(igraph_vcount(&g))); - memset(LOGICAL(result), 0, sizeof(LOGICAL(result)[0]) * + memset(LOGICAL(result), FALSE, sizeof(LOGICAL(result)[0]) * (size_t) igraph_vcount(&g)); while (!IGRAPH_VIT_END(vv)) { + igraph_integer_t neis_size; + // FIXME: expose igraph_bool_t loops = false; igraph_bool_t multiple = false; IGRAPH_R_CHECK(igraph_neighbors(&g, &neis, IGRAPH_VIT_GET(vv), mode, loops, multiple)); - for (igraph_integer_t i=0; i Date: Thu, 4 Sep 2025 11:02:11 +0200 Subject: [PATCH 042/154] docs: remove demo (#2008) --- Makefile-cigraph | 2 +- NAMESPACE | 2 - R/demo.R | 211 --------------------------- _pkgdown.yml | 3 - demo/00Index | 6 - demo/centrality.R | 224 ----------------------------- demo/cohesive.R | 59 -------- demo/community.R | 243 ------------------------------- demo/crashR.R | 345 --------------------------------------------- demo/hrg.R | 108 -------------- demo/smallworld.R | 189 ------------------------- man/igraph_demo.Rd | 43 ------ man/igraphdemo.Rd | 19 --- 13 files changed, 1 insertion(+), 1453 deletions(-) delete mode 100644 R/demo.R delete mode 100644 demo/00Index delete mode 100644 demo/centrality.R delete mode 100644 demo/cohesive.R delete mode 100644 demo/community.R delete mode 100644 demo/crashR.R delete mode 100644 demo/hrg.R delete mode 100644 demo/smallworld.R delete mode 100644 man/igraph_demo.Rd delete mode 100644 man/igraphdemo.Rd diff --git a/Makefile-cigraph b/Makefile-cigraph index 49591b85a6e..43b12068723 100644 --- a/Makefile-cigraph +++ b/Makefile-cigraph @@ -72,7 +72,7 @@ src/sources.mk: # R source and doc files -RSRC := $(shell git ls-files R doc inst demo NEWS cleanup.win configure.win) +RSRC := $(shell git ls-files R doc inst NEWS cleanup.win configure.win) # ARPACK Fortran sources diff --git a/NAMESPACE b/NAMESPACE index 3b318d4395e..95be07fb203 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -514,11 +514,9 @@ export(igraph.shape.noclip) export(igraph.shape.noplot) export(igraph.to.graphNEL) export(igraph.version) -export(igraph_demo) export(igraph_opt) export(igraph_options) export(igraph_version) -export(igraphdemo) export(in_circle) export(incident) export(incident_edges) diff --git a/R/demo.R b/R/demo.R deleted file mode 100644 index e4fd3a00125..00000000000 --- a/R/demo.R +++ /dev/null @@ -1,211 +0,0 @@ -#' Run igraph demos, step by step -#' -#' @description -#' `r lifecycle::badge("deprecated")` -#' -#' `igraphdemo()` was renamed to [igraph_demo()] to create a more -#' consistent API. -#' @inheritParams igraph_demo -#' @keywords internal -#' @export -igraphdemo <- function(which) { - # nocov start - lifecycle::deprecate_soft("2.0.0", "igraphdemo()", "igraph_demo()") - igraph_demo(which = which) -} # nocov end -# IGraph R package -# Copyright (C) 2005-2012 Gabor Csardi -# 334 Harvard street, Cambridge, MA 02139 USA -# -# 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA -# -################################################################### - -#' Run igraph demos, step by step -#' -#' Run one of the accompanying igraph demos, somewhat interactively, using a Tk -#' window. -#' -#' This function provides a somewhat nicer interface to igraph demos that come -#' with the package, than the standard [demo()] function. igraph -#' demos are divided into chunks and `igraph_demo()` runs them chunk by -#' chunk, with the possibility of inspecting the workspace between two chunks. -#' -#' The `tcltk` package is needed for `igraph_demo()`. -#' -#' @param which If not given, then the names of the available demos are listed. -#' Otherwise it should be either a filename or the name of an igraph demo. -#' @return Returns `NULL`, invisibly. -#' @author Gabor Csardi \email{csardi.gabor@@gmail.com} -#' @seealso [demo()] -#' @family demo -#' @export -#' @keywords graphs -#' @examples -#' -#' igraph_demo() -#' -#' @examplesIf interactive() && rlang::is_installed("tcltk") -#' igraph_demo("centrality") -#' -igraph_demo <- function(which) { - if (missing(which)) { - demodir <- system.file("demo", package = "igraph") - if (demodir == "") { - stop("Could not find igraph demos, broken igraph installation?") - } - return(sub("\\.R$", "", list.files(demodir))) - } - - if (!grepl("\\.R$", which)) { - which <- paste(which, sep = ".", "R") - } - - if (!file.exists(which) && !grepl("^/", which)) { - which <- system.file(paste("demo", sep = "/", which), package = "igraph") - } - - if (which == "" || !file.exists(which)) { - stop("Could not find demo file") - } - - .igraphdemo.next <- function(top, txt) { - act <- as.character(tcltk::tktag.nextrange(txt, "active", "0.0")) - if (length(act) == 0) { - return() - } - - options(keep.source = TRUE) - - text <- tcltk::tclvalue(tcltk::tkget(txt, act[1], act[2])) - cat("=======================================================\n") - - expr <- parse(text = text) - for (i in seq_along(expr)) { - co <- as.character(attributes(expr)$srcref[[i]]) - co[1] <- paste("> ", sep = "", co[1]) - if (length(co) > 1) { - co[-1] <- paste(" +", sep = "", co[-1]) - } - cat(co, sep = "\n") - res <- withVisible(eval(expr[[i]], envir = .GlobalEnv)) - if (res$visible) { - print(res$value) - } - } - cat("> -------------------------------------------------------\n") - cat(options()$prompt) - - tcltk::tktag.remove(txt, "activechunk", act[1], act[2]) - tcltk::tktag.remove(txt, "active", act[1], act[2]) - - nex <- as.character(tcltk::tktag.nextrange(txt, "activechunk", act[1])) - if (length(nex) != 0) { - tcltk::tktag.add(txt, "active", nex[1], nex[2]) - tcltk::tksee(txt, paste(sep = "", as.numeric(nex[2]), ".0")) - tcltk::tksee(txt, paste(sep = "", as.numeric(nex[1]), ".0")) - } - } - - .igraphdemo.close <- function(top) { - tcltk::tkdestroy(top) - } - - .igraphdemo.reset <- function(top, txt, which) { - demolines <- readLines(which) - demolines <- demolines[!grepl("^pause\\(\\)$", demolines)] - demolines <- paste(" ", sep = "", demolines) - - ch <- grep("^[ ]*###", demolines) - ch <- c(ch, length(demolines) + 1) - if (length(ch) == 1) { - cli::cli_warn("Demo source file does not contain chunks.") - } else { - demolines <- demolines[ch[1]:length(demolines)] - ch <- grep("^[ ]*###", demolines) - ch <- c(ch, length(demolines) + 1) - } - - tcltk::tkconfigure(txt, state = "normal") - tcltk::tkdelete(txt, "0.0", "end") - tcltk::tkinsert(txt, "insert", paste(demolines, collapse = "\n")) - tcltk::tkconfigure(txt, state = "disabled") - - for (i in seq_along(ch[-1])) { - from <- paste(sep = "", ch[i], ".0") - to <- paste(sep = "", ch[i + 1] - 1, ".0") - tcltk::tktag.add(txt, "chunk", from, to) - tcltk::tktag.add(txt, "activechunk", from, to) - } - tcltk::tktag.configure(txt, "chunk", "-borderwidth", "1") - tcltk::tktag.configure(txt, "chunk", "-relief", "sunken") - if (length(ch) >= 2) { - tcltk::tktag.add( - txt, - "active", - paste(sep = "", ch[1], ".0"), - paste(sep = "", ch[2] - 1, ".0") - ) - tcltk::tktag.configure(txt, "active", "-foreground", "red") - tcltk::tktag.configure(txt, "active", "-background", "lightgrey") - } - - comm <- grep("^#", demolines) - for (i in comm) { - tcltk::tktag.add( - txt, - "comment", - paste(sep = "", i, ".0"), - paste(sep = "", i, ".end") - ) - } - tcltk::tktag.configure(txt, "comment", "-font", "bold") - tcltk::tktag.configure(txt, "comment", "-foreground", "darkolivegreen") - } - - top <- tcltk::tktoplevel(background = "lightgrey") - tcltk::tktitle(top) <- paste("igraph demo:", which) - - main.menu <- tcltk::tkmenu(top) - tcltk::tkadd(main.menu, "command", label = "Close", command = function() { - .igraphdemo.close(top) - }) - tcltk::tkadd(main.menu, "command", label = "Reset", command = function() { - .igraphdemo.reset(top, txt, which) - }) - tcltk::tkconfigure(top, "-menu", main.menu) - - scr <- tcltk::tkscrollbar(top, repeatinterval = 5, command = function(...) { - tcltk::tkyview(txt, ...) - }) - txt <- tcltk::tktext( - top, - yscrollcommand = function(...) tcltk::tkset(scr, ...), - width = 80, - height = 40 - ) - but <- tcltk::tkbutton(top, text = "Next", command = function() { - .igraphdemo.next(top, txt) - }) - - tcltk::tkpack(but, side = "bottom", fill = "x", expand = 0) - tcltk::tkpack(scr, side = "right", fill = "y", expand = 0) - tcltk::tkpack(txt, side = "left", fill = "both", expand = 1) - - .igraphdemo.reset(top, txt, which) - - invisible() -} diff --git a/_pkgdown.yml b/_pkgdown.yml index e543b111bf1..633d73b986b 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -214,9 +214,6 @@ reference: - has_concept("processes") - has_concept("random_walk") # ----- -- title: Demo -- contents: - - has_concept("demo") - title: I/O read/write files - contents: - has_concept("foreign") diff --git a/demo/00Index b/demo/00Index deleted file mode 100644 index 5ab11658d53..00000000000 --- a/demo/00Index +++ /dev/null @@ -1,6 +0,0 @@ -crashR A crash-course into R -centrality Classic and other vertex centrality indices -community Community structure detection -smallworld Small-world networks -cohesive Cohesive blocking, the Moody & White method -hrg Hierarchical random graphs diff --git a/demo/centrality.R b/demo/centrality.R deleted file mode 100644 index 83e5a5c09b9..00000000000 --- a/demo/centrality.R +++ /dev/null @@ -1,224 +0,0 @@ -pause <- function() {} - -### Traditional approaches: degree, closeness, betweenness -g <- graph_from_literal( - Andre ---- Beverly:Diane:Fernando:Carol, - Beverly -- Andre:Diane:Garth:Ed, - Carol ---- Andre:Diane:Fernando, - Diane ---- Andre:Carol:Fernando:Garth:Ed:Beverly, - Ed ------- Beverly:Diane:Garth, - Fernando - Carol:Andre:Diane:Garth:Heather, - Garth ---- Ed:Beverly:Diane:Fernando:Heather, - Heather -- Fernando:Garth:Ike, - Ike ------ Heather:Jane, - Jane ----- Ike -) - -pause() - -### Hand-drawn coordinates -coords <- c( - 5, 5, 119, 256, 119, 256, 120, 340, 478, - 622, 116, 330, 231, 116, 5, 330, 451, 231, 231, 231 -) -coords <- matrix(coords, ncol = 2) - -pause() - -### Labels the same as names -V(g)$label <- V(g)$name -g$layout <- coords # $ - -pause() - -### Take a look at it -plotG <- function(g) { - plot( - g, - asp = FALSE, - vertex.label.color = "blue", - vertex.label.cex = 1.5, - vertex.label.font = 2, - vertex.size = 25, - vertex.color = "white", - vertex.frame.color = "white", - edge.color = "black" - ) -} -plotG(g) - -pause() - -### Add degree centrality to labels -V(g)$label <- paste(sep = "\n", V(g)$name, degree(g)) - -pause() - -### And plot again -plotG(g) - -pause() - -### Betweenness -V(g)$label <- paste(sep = "\n", V(g)$name, round(betweenness(g), 2)) -plotG(g) - -pause() - -### Closeness -V(g)$label <- paste(sep = "\n", V(g)$name, round(closeness(g), 2)) -plotG(g) - -pause() - -### Eigenvector centrality -V(g)$label <- paste(sep = "\n", V(g)$name, round(eigen_centrality(g)$vector, 2)) -plotG(g) - -pause() - -### PageRank -V(g)$label <- paste(sep = "\n", V(g)$name, round(page_rank(g)$vector, 2)) -plotG(g) - -pause() - -### Correlation between centrality measures -karate <- make_graph("Zachary") -cent <- list( - `Degree` = degree(g), - `Closeness` = closeness(g), - `Betweenness` = betweenness(g), - `Eigenvector` = eigen_centrality(g)$vector, - `PageRank` = page_rank(g)$vector -) - -pause() - -### Pairs plot -pairs(cent, lower.panel = function(x, y) { - usr <- par("usr") - text( - mean(usr[1:2]), - mean(usr[3:4]), - round(cor(x, y), 3), - cex = 2, - col = "blue" - ) -}) - -pause() - -## ### A real network, US supreme court citations -## ## You will need internet connection for this to work -## vertices <- read.csv("http://jhfowler.ucsd.edu/data/judicial.csv") -## edges <- read.table("http://jhfowler.ucsd.edu/data/allcites.txt") -## jg <- graph.data.frame(edges, vertices=vertices, directed=TRUE) - -## pause() - -## ### Basic data -## summary(jg) - -## pause() - -## ### Is it a simple graph? -## is_simple(jg) - -## pause() - -## ### Is it connected? -## is_connected(jg) - -## pause() - -## ### How many components? -## count_components(jg) - -## pause() - -## ### How big are these? -## table(components(jg)$csize) - -## pause() - -## ### In-degree distribution -## plot(degree_distribution(jg, mode="in"), log="xy") - -## pause() - -## ### Out-degree distribution -## plot(degree_distribution(jg, mode="out"), log="xy") - -## pause() - -## ### Largest in- and out-degree, total degree -## c(max(degree(jg, mode="in")), -## max(degree(jg, mode="out")), -## max(degree(jg, mode="all"))) - -## pause() - -## ### Density -## density(jg) - -## pause() - -## ### Transitivity -## transitivity(jg) - -## pause() - -## ### Transitivity of a random graph of the same size -## g <- sample_gnm(vcount(jg), ecount(jg)) -## transitivity(g) - -## pause() - -## ### Transitivity of a random graph with the same degree distribution -## g <- sample_degseq(degree(jg, mode="out"), degree(jg, mode="in"), -## method="simple") -## transitivity(g) - -## pause() - -## ### Authority and Hub scores -## AS <- authority_score(jg)$vector -## HS <- hub_score(jg)$vector - -## pause() - -## ### Time evolution of authority scores -## AS <- authority_score(jg)$vector -## center <- which.max(AS) -## startyear <- V(jg)[center]$year - -## pause() - -## ### Function to go back in time -## auth.year <- function(y) { -## print(y) -## keep <- which(V(jg)$year <= y) -## g2 <- subgraph(jg, keep) -## as <- abs(authority_score(g2, scale=FALSE)$vector) -## w <- match(V(jg)[center]$usid, V(g2)$usid) -## as[w] -## } - -## pause() - -## ### Go back in time for the top authority, do a plot -## AS2 <- sapply(startyear:2005, auth.year) -## plot(startyear:2005, AS2, type="b", xlab="year", ylab="authority score") - -## pause() - -## ### Check another case -## center <- "22US1" -## startyear <- V(jg)[center]$year - -## pause() - -## ### Calculate past authority scores & plot them -## AS3 <- sapply(startyear:2005, auth.year) -## plot(startyear:2005, AS3, type="b", xlab="year", ylab="authority score") diff --git a/demo/cohesive.R b/demo/cohesive.R deleted file mode 100644 index f38e3e696ee..00000000000 --- a/demo/cohesive.R +++ /dev/null @@ -1,59 +0,0 @@ -pause <- function() {} - -### The Zachary Karate club network - -karate <- make_graph("Zachary") -summary(karate) - -pause() - -### Create a layout that is used from now on - -karate$layout <- layout_nicely(karate) -plot(karate) - -pause() - -### Run cohesive blocking on it - -cbKarate <- cohesive_blocks(karate) -cbKarate - -pause() - -### Plot the results and all the groups - -plot(cbKarate, karate) - -pause() - -### This is a bit messy, plot them step-by-step -### See the hierarchy tree first - -hierarchy(cbKarate) -plot_hierarchy(cbKarate) - -## Plot the first level, blocks 1 & 2 - -plot(cbKarate, karate, mark.groups = blocks(cbKarate)[1:2 + 1], col = "cyan") - -pause() - -### The second group is simple, plot its more cohesive subgroup - -plot( - cbKarate, - karate, - mark.groups = blocks(cbKarate)[c(2, 5) + 1], - col = "cyan" -) - -pause() - -### The first group has more subgroups, plot them - -sub1 <- blocks(cbKarate)[parent(cbKarate) == 1] -sub1 -plot(cbKarate, karate, mark.groups = sub1) - -pause() diff --git a/demo/community.R b/demo/community.R deleted file mode 100644 index 4dbf578a746..00000000000 --- a/demo/community.R +++ /dev/null @@ -1,243 +0,0 @@ -pause <- function() {} - -### A modular graph has dense subgraphs -mod <- make_full_graph(10) %du% make_full_graph(10) %du% make_full_graph(10) -perfect <- c(rep(1, 10), rep(2, 10), rep(3, 10)) -perfect - -pause() - -### Plot it with community (=component) colors -plot(mod, vertex.color = perfect, layout = layout_with_fr) - -pause() - -### Modularity of the perfect division -modularity(mod, perfect) - -pause() - -### Modularity of the trivial partition, quite bad -modularity(mod, rep(1, 30)) - -pause() - -### Modularity of a good partition with two communities -modularity(mod, c(rep(1, 10), rep(2, 20))) - -pause() - -### A real little network, Zachary's karate club data -karate <- make_graph("Zachary") -karate$layout <- layout_with_kk(karate) - -pause() - -### Greedy algorithm -fc <- cluster_fast_greedy(karate) -memb <- membership(fc) -plot(karate, vertex.color = memb) - -pause() - -### Greedy algorithm, easier plotting -plot(fc, karate) - -pause() - -### Spinglass algorithm, create a hierarchical network -pref.mat <- matrix(0, 16, 16) -pref.mat[1:4, 1:4] <- pref.mat[5:8, 5:8] <- - pref.mat[9:12, 9:12] <- pref.mat[13:16, 13:16] <- 7.5 / 127 -pref.mat[pref.mat == 0] <- 5 / (3 * 128) -diag(pref.mat) <- diag(pref.mat) + 10 / 31 - -pause() - -### Create the network with the given vertex preferences -G <- sample_pref(128 * 4, types = 16, pref.matrix = pref.mat) - -pause() - -### Run spinglass community detection with two gamma parameters -sc1 <- cluster_spinglass(G, spins = 4, gamma = 1.0) -sc2.2 <- cluster_spinglass(G, spins = 16, gamma = 2.2) - -pause() - -### Plot the adjacency matrix, use the Matrix package if available -if (require(Matrix)) { - myimage <- function(...) image(Matrix(...)) -} else { - myimage <- image -} -A <- as_adjacency_matrix(G) -myimage(A) - -pause() - -### Ordering according to (big) communities -ord1 <- order(membership(sc1)) -myimage(A[ord1, ord1]) - -pause() - -### Ordering according to (small) communities -ord2.2 <- order(membership(sc2.2)) -myimage(A[ord2.2, ord2.2]) - -pause() - -### Consensus ordering -ord <- order(membership(sc1), membership(sc2.2)) -myimage(A[ord, ord]) - -pause() - -### Comparision of algorithms -communities <- list() - -pause() - -### cluster_edge_betweenness -ebc <- cluster_edge_betweenness(karate) -communities$`Edge betweenness` <- ebc - -pause() - -### cluster_fast_greedy -fc <- cluster_fast_greedy(karate) -communities$`Fast greedy` <- fc - -pause() - -### cluster_leading_eigen -lec <- cluster_leading_eigen(karate) -communities$`Leading eigenvector` <- lec - -pause() - -### cluster_spinglass -sc <- cluster_spinglass(karate, spins = 10) -communities$`Spinglass` <- sc - -pause() - -### cluster_walktrap -wt <- cluster_walktrap(karate) -communities$`Walktrap` <- wt - -pause() - -### cluster_label_prop -labprop <- cluster_label_prop(karate) -communities$`Label propagation` <- labprop - -pause() - -### Plot everything -layout(rbind(1:3, 4:6)) -coords <- layout_with_kk(karate) -lapply(seq_along(communities), function(x) { - m <- modularity(communities[[x]]) - par(mar = c(1, 1, 3, 1)) - plot( - communities[[x]], - karate, - layout = coords, - main = paste( - names(communities)[x], - "\n", - "Modularity:", - round(m, 3) - ) - ) -}) - -pause() - -### Function to calculate clique communities -clique.community <- function(graph, k) { - clq <- cliques(graph, min = k, max = k) - edges <- c() - for (i in seq(along.with = clq)) { - for (j in seq(along.with = clq)) { - if ( - length(unique(c( - clq[[i]], - clq[[j]] - ))) == - k + 1 - ) { - edges <- c(edges, c(i, j)) - } - } - } - clq.graph <- simplify(graph(edges)) - V(clq.graph)$name <- - seq(length.out = vcount(clq.graph)) - comps <- decompose(clq.graph) - - lapply(comps, function(x) { - unique(unlist(clq[V(x)$name])) - }) -} - -pause() - -### Apply it to a graph, this is the example graph from -## the original publication -g <- graph_from_literal( - A - B:F:C:E:D, B - A:D:C:E:F:G, C - A:B:F:E:D, D - A:B:C:F:E, - E - D:A:C:B:F:V:W:U, F - H:B:A:C:D:E, G - B:J:K:L:H, - H - F:G:I:J:K:L, I - J:L:H, J - I:G:H:L, K - G:H:L:M, - L - H:G:I:J:K:M, M - K:L:Q:R:S:P:O:N, N - M:Q:R:P:S:O, - O - N:M:P, P - Q:M:N:O:S, Q - M:N:P:V:U:W:R, R - M:N:V:W:Q, - S - N:P:M:U:W:T, T - S:V:W:U, U - E:V:Q:S:W:T, - V - E:U:W:T:R:Q, W - U:E:V:Q:R:S:T -) - -pause() - -### Hand-made layout to make it look like the original in the paper -lay <- c( - 387.0763, 306.6947, 354.0305, 421.0153, 483.5344, 512.1145, - 148.6107, 392.4351, 524.6183, 541.5878, 240.6031, 20, - 65.54962, 228.0992, 61.9771, 152.1832, 334.3817, 371.8931, - 421.9084, 265.6107, 106.6336, 57.51145, 605, 20, 124.8780, - 273.6585, 160.2439, 241.9512, 132.1951, 123.6585, 343.1707, - 465.1220, 317.561, 216.3415, 226.0976, 343.1707, 306.5854, - 123.6585, 360.2439, 444.3902, 532.1951, 720, 571.2195, - 639.5122, 505.3659, 644.3902 -) -lay <- matrix(lay, ncol = 2) -lay[, 2] <- max(lay[, 2]) - lay[, 2] - -pause() - -### Take a look at it -layout(1) -plot(g, layout = lay, vertex.label = V(g)$name) - -pause() - -### Calculate communities -res <- clique.community(g, k = 4) - -pause() - -### Paint them to different colors -colbar <- rainbow(length(res) + 1) -for (i in seq(along.with = res)) { - V(g)[res[[i]]]$color <- colbar[i + 1] -} - -pause() - -### Paint the vertices in multiple communities to red -V(g)[unlist(res)[duplicated(unlist(res))]]$color <- "red" - -pause() - -### Plot with the new colors -plot(g, layout = lay, vertex.label = V(g)$name) diff --git a/demo/crashR.R b/demo/crashR.R deleted file mode 100644 index 07d4b8390cd..00000000000 --- a/demo/crashR.R +++ /dev/null @@ -1,345 +0,0 @@ -pause <- function() {} - -### R objects, (real) numbers -a <- 3 -a -b <- 4 -b -a + b - -pause() - -### Case sensitive -A <- 16 -a -A - -pause() - -### Vector objects -a <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -a -b <- 1:100 -b -a[1] -b[1:5] -a[1] <- 10 -a -a[1:4] <- 2 -a - -pause() - -### Vector arithmetic -a * 2 + 1 - -pause() - -### Functions -ls() -length(a) -mean(a) -sd(a) -sd -c - -pause() - -### Getting help -# ?sd -# ??"standard deviation" -# RSiteSearch("network betweenness") - -pause() - -### Classes -class(2) -class(1:10) -class(sd) - -pause() - -### Character vectors -char.vec <- c("this", "is", "a", "vector", "of", "characters") -char_vec <- char.vec -char.vec[1] - -pause() - -### Index vectors -age <- c(45, 36, 65, 21, 52, 19) -age[1] -age[1:5] -age[c(2, 5, 6)] - -b[seq(1, 100, by = 2)] - -pause() - -### Named vectors -names(age) <- c("Alice", "Bob", "Cecil", "David", "Eve", "Fiona") -age -age["Bob"] -age[c("Eve", "David", "David")] - -pause() - -### Indexing with logical vectors -age[c(FALSE, TRUE, FALSE, TRUE, FALSE, TRUE)] -names(age)[age > 40] -age > 40 - -pause() - -### Matrices -M <- matrix(1:20, 10, 2) -M -M2 <- matrix(1:20, 10, 2, byrow = TRUE) ## Named argument! -M2 -M[1, 1] -M[1, ] -M[, 1] -M[1:5, 2] - -pause() - -### Generic functions -sd(a) -sd(M) -class(a) -class(M) - -pause() - -### Lists -l <- list(1:10, "Hello!", diag(5)) -l -l[[1]] -l[2:3] -l -l2 <- list(A = 1:10, H = "Hello!", M = diag(5)) -l2 -l2$A -l2$M - -pause() - -### Factors -countries <- c( - "SUI", "USA", "GBR", "GER", "SUI", - "SUI", "GBR", "GER", "FRA", "GER" -) -countries -fcountries <- factor(countries) -fcountries -levels(fcountries) - -pause() - -### Data frames -survey <- data.frame( - row.names = c("Alice", "Bob", "Cecil", "David", "Eve"), - Sex = c("F", "M", "F", "F", "F"), - Age = c(45, 36, 65, 21, 52), - Country = c("SUI", "USA", "SUI", "GBR", "USA"), - Married = c(TRUE, FALSE, FALSE, TRUE, TRUE), - Salary = c(70, 65, 200, 45, 100) -) -survey -survey$Sex -plot(survey$Age, survey$Salary) -AS.model <- lm(Salary ~ Age, data = survey) -AS.model -summary(AS.model) -abline(AS.model) - -tapply(survey$Salary, survey$Country, mean) - -pause() - -### Packages -# install.packages("igraph") -# library(help="igraph") -library(igraph) -sessionInfo() - -pause() - -### Graphs -## Create a small graph, A->B, A->C, B->C, C->E, D -## A=1, B=2, C=3, D=4, E=5 -g <- make_graph(c(1, 2, 1, 3, 2, 3, 3, 5), n = 5) - -pause() - -### Print a graph to the screen -g - -pause() - -### Create an undirected graph as well -## A--B, A--C, B--C, C--E, D -g2 <- make_graph(c(1, 2, 1, 3, 2, 3, 3, 5), n = 5, dir = FALSE) -g2 - -pause() - -### Is this object an igraph graph? -is_igraph(g) -is_igraph(1:10) - -pause() - -### Summary, number of vertices, edges -summary(g) -vcount(g) -ecount(g) - -pause() - -### Is the graph directed? -is_directed(g) -is_directed(g2) - -pause() - -### Convert from directed to undirected -as.undirected(g) - -pause() - -### And back -as.directed(as.undirected(g)) - -pause() - -### Multiple edges -g <- make_graph(c(1, 2, 1, 2, 1, 3, 2, 3, 4, 5), n = 5) -g - -is_simple(g) -which_multiple(g) - -pause() - -### Remove multiple edges -g <- simplify(g) -is_simple(g) - -pause() - -### Loop edges -g <- make_graph(c(1, 1, 1, 2, 1, 3, 2, 3, 4, 5), n = 5) -g - -is_simple(g) -which_loop(g) - -pause() - -### Remove loop edges -g <- simplify(g) -is_simple(g) - -pause() - -### Naming vertices -g <- make_ring(10) -V(g)$name <- letters[1:10] -V(g)$name -g -print(g, v = T) - -pause() - -### Create undirected example graph -g2 <- graph_from_literal( - Alice - Bob:Cecil:Daniel, - Cecil:Daniel - Eugene:Gordon -) -print(g2, v = T) - -pause() - -### Remove Alice -g3 <- delete_vertices(g2, match("Alice", V(g2)$name)) - -pause() - -### Add three new vertices -g4 <- add_vertices(g3, 3) -print(g4, v = T) -igraph_options( - print.vertex.attributes = TRUE, - plot.layout = layout_with_fr -) -g4 -plot(g4) - -pause() - -### Add three new vertices, with names this time -g4 <- add_vertices(g3, 3, attr = list(name = c("Helen", "Ike", "Jane"))) -g4 - -pause() - -### Add some edges as well -g4 <- add_edges(g4, match(c("Helen", "Jane", "Ike", "Jane"), V(g4)$name)) -g4 - -pause() - -### Edge sequences, first create a directed example graph -g2 <- graph_from_literal( - Alice -+ Bob:Cecil:Daniel, - Cecil:Daniel +-+ Eugene:Gordon -) -print(g2, v = T) -plot(g2, layout = layout_with_kk, vertex.label = V(g2)$name) - -pause() - -### Sequence of all edges -E(g2) - -pause() - -### Edge from a vertex to another -E(g2, P = c(1, 2)) - -pause() - -### Delete this edge -g3 <- delete_edges(g2, E(g2, P = c(1, 2))) -g3 - -pause() - -### Get the id of the edge -as.vector(E(g2, P = c(1, 2))) - -pause() - -### All adjacent edges of a vertex -E(g2)[adj(3)] - -pause() - -### Or multiple vertices -E(g2)[adj(c(3, 1))] - -pause() - -### Outgoing edges -E(g2)[from(3)] - -pause() - -### Incoming edges -E(g2)[to(3)] - -pause() - -### Edges along a path -E(g2, path = c(1, 4, 5)) diff --git a/demo/hrg.R b/demo/hrg.R deleted file mode 100644 index 5c5fe4a1b6a..00000000000 --- a/demo/hrg.R +++ /dev/null @@ -1,108 +0,0 @@ -pause <- function() {} - -### Construct the Zachary Karate Club network - -karate <- make_graph("zachary") -karate - -pause() - -### Optimalize modularity - -optcom <- cluster_optimal(karate) -V(karate)$comm <- membership(optcom) -plot(optcom, karate) - -pause() - -### Fit a HRG model to the network - -hrg <- fit_hrg(karate) -hrg - -pause() - -### The fitted model, more details - -print(hrg, level = 5) - -pause() - -### Plot the full hierarchy, as an igraph graph - -ihrg <- as.igraph(hrg) -ihrg$layout <- layout.reingold.tilford -plot(ihrg, vertex.size = 10, edge.arrow.size = 0.2) - -pause() - -### Customize the plot a bit, show probabilities and communities - -vn <- sub("Actor ", "", V(ihrg)$name) -colbar <- rainbow(length(optcom)) -vc <- ifelse(is.na(V(ihrg)$prob), colbar[V(karate)$comm], "darkblue") -V(ihrg)$label <- ifelse(is.na(V(ihrg)$prob), vn, round(V(ihrg)$prob, 2)) -par(mar = c(0, 0, 3, 0)) -plot( - ihrg, - vertex.size = 10, - edge.arrow.size = 0.2, - vertex.shape = "none", - vertex.label.color = vc, - main = "Hierarchical network model of the Karate Club" -) - -pause() - -### Plot it as a dendrogram, looks better if the 'ape' package is installed - -plot_dendrogram(hrg) - -pause() - -### Make a very hierarchical graph - -g1 <- make_full_graph(5) -g2 <- make_ring(5) - -g <- g1 + g2 -g <- g + edge(1, vcount(g1) + 1) - -plot(g) - -pause() - -### Fit HRG - -ghrg <- fit_hrg(g) -plot_dendrogram(ghrg) - -pause() - -### Create a consensus dendrogram from multiple samples, takes longer... - -hcons <- consensus_tree(g) -hcons$consensus - -pause() - -### Predict missing edges - -pred <- predict_edges(g) -pred - -pause() - -### Add some the top 5 predicted edges to the graph, colored red - -E(g)$color <- "grey" -lay <- layout_nicely(g) -g2 <- add_edges(g, t(pred$edges[1:5, ]), color = "red") -plot(g2, layout = lay) - -pause() - -### Add four more predicted edges, colored orange - -g3 <- add_edges(g2, t(pred$edges[6:9, ]), color = "orange") -plot(g3, layout = lay) diff --git a/demo/smallworld.R b/demo/smallworld.R deleted file mode 100644 index 8d66545fb7f..00000000000 --- a/demo/smallworld.R +++ /dev/null @@ -1,189 +0,0 @@ -pause <- function() {} - -### Create a star-like graph -t1 <- graph_from_literal(A - B:C:D:E) -t1 - -pause() - -### Define its plotting properties -t1$layout <- layout_in_circle -V(t1)$color <- "white" -V(t1)[name == "A"]$color <- "orange" -V(t1)$size <- 40 -V(t1)$label.cex <- 3 -V(t1)$label <- V(t1)$name -E(t1)$color <- "black" -E(t1)$width <- 3 - -pause() - -### Plot 't1' and A's transitivity -tr <- transitivity(t1, type = "local")[1] -plot(t1, main = paste("Transitivity of 'A':", tr)) - -pause() - -### Add an edge and recalculate transitivity -t2 <- add_edges(t1, V(t1)[name %in% c("C", "D")], color = "red", width = 3) -tr <- transitivity(t2, type = "local")[1] -plot(t2, main = paste("Transitivity of 'A':", round(tr, 4))) - -pause() - -### Add two more edges -newe <- match(c("B", "C", "B", "E"), V(t2)$name) - 1 -t3 <- add_edges(t2, newe, color = "red", width = 3) -tr <- transitivity(t3, type = "local")[1] -plot(t3, main = paste("Transitivity of 'A':", round(tr, 4))) - -pause() - -### A one dimensional, circular lattice -ring <- make_ring(50) -ring$layout <- layout_in_circle -V(ring)$size <- 3 -plot(ring, vertex.label = NA, main = "Ring graph") - -pause() - -### Watts-Strogatz model -ws1 <- sample_smallworld(1, 50, 3, p = 0) -ws1$layout <- layout_in_circle -V(ws1)$size <- 3 -E(ws1)$curved <- 1 -plot(ws1, vertex.label = NA, main = "regular graph") - -pause() - -### Zoom in to this part -axis(1) -axis(2) -abline(h = c(0.8, 1.1)) -abline(v = c(-0.2, 0.2)) - -pause() - -### Zoom in to this part -plot(ws1, vertex.label = NA, xlim = c(-0.2, 0.2), ylim = c(0.8, 1.1)) - -pause() - -### Transitivity of the ring graph -transitivity(ws1) - -pause() - -### Path lengths, regular graph -mean_distance(ws1) - -pause() - -### Function to test regular graph with given size -try.ring.pl <- function(n) { - g <- sample_smallworld(1, n, 3, p = 0) - mean_distance(g) -} -try.ring.pl(10) -try.ring.pl(100) - -pause() - -### Test a number of regular graphs -ring.size <- seq(100, 1000, by = 100) -ring.pl <- sapply(ring.size, try.ring.pl) -plot(ring.size, ring.pl, type = "b") - -pause() - -### Path lengths, random graph -rg <- sample_gnm(50, 50 * 3) -rg$layout <- layout_in_circle -V(rg)$size <- 3 -plot(rg, vertex.label = NA, main = "Random graph") -mean_distance(rg) - -pause() - -### Path length of random graphs -try.random.pl <- function(n) { - g <- sample_gnm(n, n * 3) - mean_distance(g) -} -try.random.pl(100) - -pause() - -### Plot network size vs. average path length -random.pl <- sapply(ring.size, try.random.pl) -plot(ring.size, random.pl, type = "b") - -pause() - -### Plot again, logarithmic 'x' axis -plot(ring.size, random.pl, type = "b", log = "x") - -pause() - -### Transitivity, random graph, by definition -ecount(rg) / (vcount(rg) * (vcount(rg) - 1) / 2) -transitivity(rg, type = "localaverage") - -pause() - -### Rewiring -ws2 <- sample_smallworld(1, 50, 3, p = 0.1) -ws2$layout <- layout_in_circle -V(ws2)$size <- 3 -plot(ws2, vertex.label = NA) -mean_distance(ws2) - -pause() - -### Path lengths in randomized lattices -try.rr.pl <- function(n, p) { - g <- sample_smallworld(1, n, 3, p = p) - mean_distance(g) -} -rr.pl.0.1 <- sapply(ring.size, try.rr.pl, p = 0.1) -plot(ring.size, rr.pl.0.1, type = "b") - -pause() - -### Logarithmic 'x' axis -plot(ring.size, rr.pl.0.1, type = "b", log = "x") - -pause() - -### Create the graph in the Watts-Strogatz paper -ws.paper <- function(p, n = 1000) { - g <- sample_smallworld(1, n, 10, p = p) - tr <- transitivity(g, type = "localaverage") - pl <- mean_distance(g) - c(tr, pl) -} - -pause() - -### Do the simulation for a number of 'p' values -rewire.prob <- ((1:10)^4) / (10^4) -ws.result <- sapply(rewire.prob, ws.paper) -dim(ws.result) - -pause() - -### Plot it -plot( - rewire.prob, - ws.result[1, ] / ws.result[1, 1], - log = "x", - pch = 22, - xlab = "p", - ylab = "" -) -points(rewire.prob, ws.result[2, ] / ws.result[2, 1], pch = 20) -legend( - "bottomleft", - c(expression(C(p) / C(0)), expression(L(p) / L(0))), - pch = c(22, 20) -) diff --git a/man/igraph_demo.Rd b/man/igraph_demo.Rd deleted file mode 100644 index 765ad6c762a..00000000000 --- a/man/igraph_demo.Rd +++ /dev/null @@ -1,43 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/demo.R -\name{igraph_demo} -\alias{igraph_demo} -\title{Run igraph demos, step by step} -\usage{ -igraph_demo(which) -} -\arguments{ -\item{which}{If not given, then the names of the available demos are listed. -Otherwise it should be either a filename or the name of an igraph demo.} -} -\value{ -Returns \code{NULL}, invisibly. -} -\description{ -Run one of the accompanying igraph demos, somewhat interactively, using a Tk -window. -} -\details{ -This function provides a somewhat nicer interface to igraph demos that come -with the package, than the standard \code{\link[=demo]{demo()}} function. igraph -demos are divided into chunks and \code{igraph_demo()} runs them chunk by -chunk, with the possibility of inspecting the workspace between two chunks. - -The \code{tcltk} package is needed for \code{igraph_demo()}. -} -\examples{ - -igraph_demo() - -\dontshow{if (interactive() && rlang::is_installed("tcltk")) withAutoprint(\{ # examplesIf} -igraph_demo("centrality") -\dontshow{\}) # examplesIf} -} -\seealso{ -\code{\link[=demo]{demo()}} -} -\author{ -Gabor Csardi \email{csardi.gabor@gmail.com} -} -\concept{demo} -\keyword{graphs} diff --git a/man/igraphdemo.Rd b/man/igraphdemo.Rd deleted file mode 100644 index 08141022cdd..00000000000 --- a/man/igraphdemo.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/demo.R -\name{igraphdemo} -\alias{igraphdemo} -\title{Run igraph demos, step by step} -\usage{ -igraphdemo(which) -} -\arguments{ -\item{which}{If not given, then the names of the available demos are listed. -Otherwise it should be either a filename or the name of an igraph demo.} -} -\description{ -\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} - -\code{igraphdemo()} was renamed to \code{\link[=igraph_demo]{igraph_demo()}} to create a more -consistent API. -} -\keyword{internal} From 433a47dfe3fb2243475e66916388829b1ab6d5fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 4 Sep 2025 11:16:04 +0200 Subject: [PATCH 043/154] chore: Build-ignore --- .Rbuildignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.Rbuildignore b/.Rbuildignore index 3e4bd8658db..b1879373672 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -62,6 +62,7 @@ ^covr$ ^src/*\.gcda$ ^src/*\.gcno$ +^R/release\.R$ ^man/dot-igraph.progress\.Rd$ ^man/dot-igraph.status\.Rd$ ^man/dot-extract_constructor_and_modifiers\.Rd$ From dab931dad68305c01f9a6c2ef758f575a4c9481f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 5 Sep 2025 19:10:18 +0200 Subject: [PATCH 044/154] ci: Use reviewdog for external PRs (#2116) --- .github/workflows/commit/action.yml | 99 ++++++++++++------- .github/workflows/update-snapshots/action.yml | 11 ++- 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/.github/workflows/commit/action.yml b/.github/workflows/commit/action.yml index a0a369226ca..8dd0c9e225b 100644 --- a/.github/workflows/commit/action.yml +++ b/.github/workflows/commit/action.yml @@ -11,53 +11,76 @@ outputs: runs: using: "composite" steps: + - name: Check for changes + id: check + run: | + set -x + if [ -n "$(git status --porcelain)" ]; then + echo "has_changes=true" | tee -a $GITHUB_OUTPUT + else + echo "has_changes=false" | tee -a $GITHUB_OUTPUT + fi + shell: bash + - name: Commit if changed, create a PR if protected id: commit + if: steps.check.outputs.has_changes == 'true' env: GITHUB_TOKEN: ${{ inputs.token }} run: | set -x - if [ -n "$(git status --porcelain)" ]; then - echo "Changed" - protected=${{ github.ref_protected }} - foreign=${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} - if [ "${foreign}" = "true" ]; then - # https://github.com/krlmlr/actions-sync/issues/44 - echo "Can't push to foreign branch" - elif [ "${protected}" = "true" ]; then - current_branch=$(git branch --show-current) - new_branch=gha-commit-$(git rev-parse --short HEAD) - git checkout -b ${new_branch} - git add . - git commit -m "chore: Auto-update from GitHub Actions"$'\n'$'\n'"Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" - # Force-push, used in only one place - # Alternative: separate branch names for each usage - git push -u origin HEAD -f - - existing_pr=$(gh pr list --state open --base main --head ${new_branch} --json number --jq '.[] | .number') - if [ -n "${existing_pr}" ]; then - echo "Existing PR: ${existing_pr}" - else - gh pr create --base main --head ${new_branch} --title "chore: Auto-update from GitHub Actions" --body "Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" - fi + protected=${{ github.ref_protected }} + foreign=${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} + is_pr=${{ github.event_name == 'pull_request' }} + if [ "${is_pr}" = "true" ]; then + # Running on a PR - will use reviewdog in next step + echo "Code changes detected on PR, will suggest changes via reviewdog" + echo "use_reviewdog=true" | tee -a $GITHUB_OUTPUT + git reset HEAD + git status + elif [ "${foreign}" = "true" ]; then + # https://github.com/krlmlr/actions-sync/issues/44 + echo "Can't push to foreign branch" + elif [ "${protected}" = "true" ]; then + current_branch=$(git branch --show-current) + new_branch=gha-commit-$(git rev-parse --short HEAD) + git checkout -b ${new_branch} + git add . + git commit -m "chore: Auto-update from GitHub Actions"$'\n'$'\n'"Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + # Force-push, used in only one place + # Alternative: separate branch names for each usage + git push -u origin HEAD -f - gh workflow run rcc -f ref=$(git rev-parse HEAD) - gh pr merge --merge --auto + existing_pr=$(gh pr list --state open --base main --head ${new_branch} --json number --jq '.[] | .number') + if [ -n "${existing_pr}" ]; then + echo "Existing PR: ${existing_pr}" else - git fetch - if [ -n "${GITHUB_HEAD_REF}" ]; then - git add . - git stash save - git switch ${GITHUB_HEAD_REF} - git merge origin/${GITHUB_BASE_REF} --no-edit - git stash pop - fi - git add . - git commit -m "chore: Auto-update from GitHub Actions"$'\n'$'\n'"Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" - git push -u origin HEAD + gh pr create --base main --head ${new_branch} --title "chore: Auto-update from GitHub Actions" --body "Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + fi - # Only set output if changed - echo sha=$(git rev-parse HEAD) >> $GITHUB_OUTPUT + gh workflow run rcc -f ref=$(git rev-parse HEAD) + gh pr merge --merge --auto + else + git fetch + if [ -n "${GITHUB_HEAD_REF}" ]; then + git add . + git stash save + git switch ${GITHUB_HEAD_REF} + git merge origin/${GITHUB_BASE_REF} --no-edit + git stash pop fi + git add . + git commit -m "chore: Auto-update from GitHub Actions"$'\n'$'\n'"Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + git push -u origin HEAD + + # Only set output if changed + echo sha=$(git rev-parse HEAD) >> $GITHUB_OUTPUT fi shell: bash + + - name: Suggest changes via reviewdog + if: steps.commit.outputs.use_reviewdog == 'true' + uses: krlmlr/action-suggester@main + with: + github_token: ${{ inputs.token }} + tool_name: "rcc" diff --git a/.github/workflows/update-snapshots/action.yml b/.github/workflows/update-snapshots/action.yml index 86149ce3b28..03d2173f1b0 100644 --- a/.github/workflows/update-snapshots/action.yml +++ b/.github/workflows/update-snapshots/action.yml @@ -56,19 +56,24 @@ runs: if: ${{ steps.run-tests.outputs.changed }} id: check-changed run: | - echo "changed=$(git status --porcelain -- tests/testthat/_snaps | head -n 1)" >> $GITHUB_OUTPUT + set -x + if [ "${{ github.event_name}}" != "pull_request" ] ; then + echo "changed=$(git status --porcelain -- tests/testthat/_snaps | head -n 1)" | tee -a $GITHUB_OUTPUT + fi shell: bash - name: Derive branch name if: ${{ steps.check-changed.outputs.changed }} id: matrix-desc run: | + set -x config=$(echo '${{ toJSON(matrix) }}' | jq -c .) - echo "text=$(echo ${config})" >> $GITHUB_OUTPUT - echo "branch=$(echo ${config} | sed -r 's/[^0-9a-zA-Z]+/-/g;s/^-//;s/-$//')" >> $GITHUB_OUTPUT + echo "text=$(echo ${config})" | tee -a $GITHUB_OUTPUT + echo "branch=$(echo ${config} | sed -r 's/[^0-9a-zA-Z]+/-/g;s/^-//;s/-$//')" | tee -a $GITHUB_OUTPUT shell: bash - name: Create pull request + # Fall through if PR, will use reviewdog/action-suggester in the commit action if: ${{ steps.check-changed.outputs.changed }} id: cpr uses: peter-evans/create-pull-request@v6 From 3491ff0c494d5af4235c0b9b33a30723e3e4d3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 7 Sep 2025 11:18:08 +0200 Subject: [PATCH 045/154] chore: Results for revdepchecks --- revdep/README.md | 25 +-- revdep/cran.md | 18 +- revdep/failures.md | 505 ++++++++++++++++++++++++++++----------------- revdep/problems.md | 445 +++++---------------------------------- 4 files changed, 376 insertions(+), 617 deletions(-) diff --git a/revdep/README.md b/revdep/README.md index cfb522a5f6a..6abbd372eb1 100644 --- a/revdep/README.md +++ b/revdep/README.md @@ -1,23 +1,24 @@ # Revdeps -## Failed to check (12) +## Failed to check (13) |package |version |error |warning |note | |:---------------|:-------|:-----|:-------|:----| -|bnlearn |5.0.2 |1 | | | +|bnlearn |5.1 |1 | | | |dataone |2.2.2 |1 | | | |datapack |1.4.1 |1 | | | -|FAfA |0.3 |1 | | | +|EGAnet |? | | | | +|FAfA |? | | | | |FAIRmaterials |0.4.2.1 |1 | | | -|lavaan.shiny |1.2 |1 | | | +|lavaan.shiny |? | | | | |multinma |0.8.1 |1 | | | |randomForestSRC |? | | | | -|RSP |0.4 |1 | | | -|sphereML |0.1.1 |1 | | | +|RSP |? | | | | +|sphereML |? | | | | |streamDAG |? | | | | -|TestAnaAPP |1.1.2 |1 | | | +|TestAnaAPP |? | | | | -## New problems (25) +## New problems (21) |package |version |error |warning |note | |:--------------------|:--------|:------|:-------|:----| @@ -26,19 +27,15 @@ |[CITMIC](problems.md#citmic)|0.1.2 |__+1__ | | | |[dosearch](problems.md#dosearch)|1.0.11 |__+1__ | |1 | |[DrDimont](problems.md#drdimont)|0.1.4 |__+2__ | |1 | -|[EGAnet](problems.md#eganet)|2.3.0 |__+1__ | |1 | |[egor](problems.md#egor)|1.24.2 |__+1__ | | | |[FCMapper](problems.md#fcmapper)|1.1 |__+1__ | | | |[GephiForR](problems.md#gephiforr)|0.1.0 |__+1__ | | | -|[gor](problems.md#gor)|1.0 |__+1__ | |1 | -|[handwriterRF](problems.md#handwriterrf)|1.1.1 |__+1__ | | | -|[incidentally](problems.md#incidentally)|1.0.2 |__+1__ | | | +|[incidentally](problems.md#incidentally)|1.0.3 |__+1__ | | | |[IOHanalyzer](problems.md#iohanalyzer)|0.1.8.10 |__+1__ | |2 | |[klassR](problems.md#klassr)|1.0.2 |__+1__ | |1 | -|[manynet](problems.md#manynet)|1.5.1 |__+2__ | |2 | +|[manynet](problems.md#manynet)|1.6.0 |__+2__ | | | |[multinet](problems.md#multinet)|4.2.2 |__+1__ | |1 | |[mwcsr](problems.md#mwcsr)|0.1.9 |__+2__ | |1 | -|[pathfindR](problems.md#pathfindr)|2.5.0 |__+1__ | | | |[PopComm](problems.md#popcomm)|0.1.0.1 |__+1__ | | | |[remify](problems.md#remify)|3.2.8 |__+1__ | |1 | |[rsetse](problems.md#rsetse)|0.5.0 |__+2__ | | | diff --git a/revdep/cran.md b/revdep/cran.md index 8bc41bff961..354e462bc21 100644 --- a/revdep/cran.md +++ b/revdep/cran.md @@ -1,8 +1,8 @@ ## revdepcheck results -We checked 2160 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package. +We checked 37 reverse dependencies (36 from CRAN + 1 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package. - * We saw 25 new problems + * We saw 21 new problems * We failed to check 12 packages Issues with CRAN packages are summarised below. @@ -28,9 +28,6 @@ Issues with CRAN packages are summarised below. checking examples ... ERROR checking re-building of vignette outputs ... ERROR -* EGAnet - checking examples ... ERROR - * egor checking re-building of vignette outputs ... ERROR @@ -40,12 +37,6 @@ Issues with CRAN packages are summarised below. * GephiForR checking examples ... ERROR -* gor - checking examples ... ERROR - -* handwriterRF - checking tests ... ERROR - * incidentally checking re-building of vignette outputs ... ERROR @@ -66,9 +57,6 @@ Issues with CRAN packages are summarised below. checking examples ... ERROR checking tests ... ERROR -* pathfindR - checking tests ... ERROR - * PopComm checking examples ... ERROR @@ -98,12 +86,12 @@ Issues with CRAN packages are summarised below. * bnlearn (NA) * dataone (NA) * datapack (NA) +* EGAnet (NA) * FAfA (NA) * FAIRmaterials (NA) * lavaan.shiny (NA) * multinma (NA) * randomForestSRC (NA) -* RSP (NA) * sphereML (NA) * streamDAG (NA) * TestAnaAPP (NA) diff --git a/revdep/failures.md b/revdep/failures.md index 35fd7e5977f..ea5de2bd14e 100644 --- a/revdep/failures.md +++ b/revdep/failures.md @@ -2,10 +2,10 @@
-* Version: 5.0.2 +* Version: 5.1 * GitHub: NA * Source code: https://github.com/cran/bnlearn -* Date/Publication: 2025-01-07 14:40:05 UTC +* Date/Publication: 2025-08-20 12:50:13 UTC * Number of recursive dependencies: 35 Run `revdepcheck::cloud_details(, "bnlearn")` for more info @@ -63,8 +63,10 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c foreign/parse.c -o foreign/parse.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c globals.c -o globals.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/acyclic.c -o graphs/acyclic.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/is.dag.c -o graphs/is.dag.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/completely.directed.c -o graphs/completely.directed.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/connected.components.c -o graphs/connected.components.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/path.c -o graphs/path.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/path.matrix.c -o graphs/path.matrix.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/pdag2dag.c -o graphs/pdag2dag.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/random/graph.generation.c -o graphs/random/graph.generation.o In file included from graphs/random/../../include/rcore.h:3, @@ -83,12 +85,15 @@ graphs/random/graph.generation.c:719:17: warning: assignment to ‘SEXP’ {aka 371 | #define PROTECT(s) Rf_protect(s) | ^ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/topological.ordering.c -o graphs/topological.ordering.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/rinterface/connected.components.c -o graphs/rinterface/connected.components.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/rinterface/path.matrix.c -o graphs/rinterface/path.matrix.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/rinterface/sid.c -o graphs/rinterface/sid.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/sid.c -o graphs/sid.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/likelihood.weighting.c -o inference/likelihood.weighting.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/common.c -o inference/loglikelihood/common.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/discrete.c -o inference/loglikelihood/discrete.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/gaussian.c -o inference/loglikelihood/gaussian.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/conditional.gaussian.c -o inference/loglikelihood/conditional.gaussian.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loss.c -o inference/loss.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/rbn.c -o inference/rbn.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/rinterface/loglikelihood.c -o inference/rinterface/loglikelihood.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/rinterface/cpdist.c -o inference/rinterface/cpdist.o @@ -109,17 +114,18 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c minimal/table.c -o minimal/table.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c minimal/tiers.c -o minimal/tiers.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c minimal/unique.c -o minimal/unique.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/classic_discrete.c -o parameters/discrete/classic_discrete.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/hierarchical_dirichlet.c -o parameters/discrete/hierarchical_dirichlet.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/classic_discrete.c -o parameters/rinterface/classic_discrete.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/hierarchical_dirichlet.c -o parameters/rinterface/hierarchical_dirichlet.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/mixture_ordinary_least_squares.c -o parameters/rinterface/mixture_ordinary_least_squares.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/ordinary_least_squares.c -o parameters/rinterface/ordinary_least_squares.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/classic.discrete.c -o parameters/discrete/classic.discrete.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/hierarchical.dirichlet.c -o parameters/discrete/hierarchical.dirichlet.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/classic.discrete.c -o parameters/rinterface/classic.discrete.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/hierarchical.dirichlet.c -o parameters/rinterface/hierarchical.dirichlet.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/mixture.ordinary.least.squares.c -o parameters/rinterface/mixture.ordinary.least.squares.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/ordinary.least.squares.c -o parameters/rinterface/ordinary.least.squares.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c predict/map.lw.c -o predict/map.lw.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c predict/predict.c -o predict/predict.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/dedup.c -o preprocessing/dedup.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/discretize.c -o preprocessing/discretize.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/enums.c -o preprocessing/enums.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/rinterface/discretize.c -o preprocessing/rinterface/discretize.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c sanitization/cg.assumptions.c -o sanitization/cg.assumptions.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c sanitization/covariance.c -o sanitization/covariance.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c sanitization/data.c -o sanitization/data.o @@ -153,8 +159,8 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/gaussian.nal.c -o scores/gaussian.nal.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/gaussian.predictive.loglikelihood.c -o scores/gaussian.predictive.loglikelihood.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/graph.priors.c -o scores/graph.priors.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml_regret.c -o scores/nml_regret.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml_regret_table.c -o scores/nml_regret_table.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml.regret.c -o scores/nml.regret.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml.regret.table.c -o scores/nml.regret.table.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/normalized.maximum.likelihood.c -o scores/normalized.maximum.likelihood.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/per.node.score.c -o scores/per.node.score.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/wishart.posterior.c -o scores/wishart.posterior.o @@ -196,7 +202,7 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c tests/rinterface/indep.test.c -o tests/rinterface/indep.test.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c tests/rinterface/roundrobin.test.c -o tests/rinterface/roundrobin.test.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c tests/rinterface/utest.c -o tests/rinterface/utest.o -gcc -std=gnu17 -shared -L/opt/R/4.4.0/lib/R/lib -L/usr/local/lib -o bnlearn.so arcs/arcs2amat.o arcs/arcs2elist.o arcs/bind.o arcs/filter.arcs.o arcs/hash.o arcs/is.row.equal.o bnlearn/bayesian.network.o bnlearn/bn.recovery.o bnlearn/cache.structure.o bnlearn/cextend.o bnlearn/colliders.o bnlearn/cpdag.o bnlearn/fitted.o bnlearn/nparams.o bnlearn/shd.o core/allocations.o core/contingency.tables.o core/correlation.o core/covariance.matrix.o core/data.table.o core/math.functions.o core/moments.o core/sampling.o core/sets.o core/sort.o core/uppertriangular.o fitted/enums.o fitted/fitted.o fitted/nparams.o fitted/rinterface/nparams.o foreign/parse.o globals.o graphs/acyclic.o graphs/is.dag.o graphs/path.o graphs/pdag2dag.o graphs/random/graph.generation.o graphs/topological.ordering.o inference/likelihood.weighting.o inference/loglikelihood/common.o inference/loglikelihood/discrete.o inference/loglikelihood/gaussian.o inference/loglikelihood/conditional.gaussian.o inference/loss.o inference/rbn.o inference/rinterface/loglikelihood.o inference/rinterface/cpdist.o inference/rinterface/rbn.o inference/rinterface/likelihood.weighting.o learning/averaging/averaging.o learning/averaging/bootstrap.o learning/local/mi.matrix.o learning/score/hc.cache.lookup.o learning/score/score.delta.o learning/score/tabu.o math/conditional.least.squares.o math/least.squares.o math/linear.algebra.o minimal/common.o minimal/data.frame.o minimal/strings.o minimal/table.o minimal/tiers.o minimal/unique.o parameters/discrete/classic_discrete.o parameters/discrete/hierarchical_dirichlet.o parameters/rinterface/classic_discrete.o parameters/rinterface/hierarchical_dirichlet.o parameters/rinterface/mixture_ordinary_least_squares.o parameters/rinterface/ordinary_least_squares.o predict/map.lw.o predict/predict.o preprocessing/dedup.o preprocessing/discretize.o preprocessing/enums.o sanitization/cg.assumptions.o sanitization/covariance.o sanitization/data.o scores/alpha.star.o scores/cg.loglikelihood.o scores/cg.predictive.loglikelihood.o scores/cg.nal.o scores/custom.score.o scores/dirichlet.averaged.posterior.o scores/dirichlet.posterior.o scores/discrete.loglikelihood.o scores/discrete.nal.o scores/discrete.predictive.loglikelihood.o scores/enum.o scores/gaussian.loglikelihood.o scores/gaussian.nal.o scores/gaussian.predictive.loglikelihood.o scores/graph.priors.o scores/nml_regret.o scores/nml_regret_table.o scores/normalized.maximum.likelihood.o scores/per.node.score.o scores/wishart.posterior.o test.counter.o tests/conditional.gaussian/cg.mutual.information.o tests/discrete/df.adjust.o tests/discrete/discrete.tests.o tests/discrete/jonckheere.o tests/discrete/shrinkage.o tests/enums.o tests/gaussian/df.adjust.o tests/gaussian/gaussian.tests.o tests/gaussian/shrinkage.o tests/omnibus/custom.test.o tests/patterns/allsubs.test.o tests/patterns/ctest.o tests/patterns/roundrobin.test.o tests/patterns/utest.o tests/permutation/discrete.monte.carlo.o tests/permutation/gaussian.monte.carlo.o tests/rinterface/allsubs.test.o tests/rinterface/ctest.o tests/rinterface/htest.o tests/rinterface/indep.test.o tests/rinterface/roundrobin.test.o tests/rinterface/utest.o -llapack -lblas -lgfortran -lm -lquadmath -L/opt/R/4.4.0/lib/R/lib -lR +gcc -std=gnu17 -shared -L/opt/R/4.4.0/lib/R/lib -L/usr/local/lib -o bnlearn.so arcs/arcs2amat.o arcs/arcs2elist.o arcs/bind.o arcs/filter.arcs.o arcs/hash.o arcs/is.row.equal.o bnlearn/bayesian.network.o bnlearn/bn.recovery.o bnlearn/cache.structure.o bnlearn/cextend.o bnlearn/colliders.o bnlearn/cpdag.o bnlearn/fitted.o bnlearn/nparams.o bnlearn/shd.o core/allocations.o core/contingency.tables.o core/correlation.o core/covariance.matrix.o core/data.table.o core/math.functions.o core/moments.o core/sampling.o core/sets.o core/sort.o core/uppertriangular.o fitted/enums.o fitted/fitted.o fitted/nparams.o fitted/rinterface/nparams.o foreign/parse.o globals.o graphs/acyclic.o graphs/completely.directed.o graphs/connected.components.o graphs/path.o graphs/path.matrix.o graphs/pdag2dag.o graphs/random/graph.generation.o graphs/topological.ordering.o graphs/rinterface/connected.components.o graphs/rinterface/path.matrix.o graphs/rinterface/sid.o graphs/sid.o inference/likelihood.weighting.o inference/loglikelihood/common.o inference/loglikelihood/discrete.o inference/loglikelihood/gaussian.o inference/loglikelihood/conditional.gaussian.o inference/rbn.o inference/rinterface/loglikelihood.o inference/rinterface/cpdist.o inference/rinterface/rbn.o inference/rinterface/likelihood.weighting.o learning/averaging/averaging.o learning/averaging/bootstrap.o learning/local/mi.matrix.o learning/score/hc.cache.lookup.o learning/score/score.delta.o learning/score/tabu.o math/conditional.least.squares.o math/least.squares.o math/linear.algebra.o minimal/common.o minimal/data.frame.o minimal/strings.o minimal/table.o minimal/tiers.o minimal/unique.o parameters/discrete/classic.discrete.o parameters/discrete/hierarchical.dirichlet.o parameters/rinterface/classic.discrete.o parameters/rinterface/hierarchical.dirichlet.o parameters/rinterface/mixture.ordinary.least.squares.o parameters/rinterface/ordinary.least.squares.o predict/map.lw.o predict/predict.o preprocessing/dedup.o preprocessing/discretize.o preprocessing/enums.o preprocessing/rinterface/discretize.o sanitization/cg.assumptions.o sanitization/covariance.o sanitization/data.o scores/alpha.star.o scores/cg.loglikelihood.o scores/cg.predictive.loglikelihood.o scores/cg.nal.o scores/custom.score.o scores/dirichlet.averaged.posterior.o scores/dirichlet.posterior.o scores/discrete.loglikelihood.o scores/discrete.nal.o scores/discrete.predictive.loglikelihood.o scores/enum.o scores/gaussian.loglikelihood.o scores/gaussian.nal.o scores/gaussian.predictive.loglikelihood.o scores/graph.priors.o scores/nml.regret.o scores/nml.regret.table.o scores/normalized.maximum.likelihood.o scores/per.node.score.o scores/wishart.posterior.o test.counter.o tests/conditional.gaussian/cg.mutual.information.o tests/discrete/df.adjust.o tests/discrete/discrete.tests.o tests/discrete/jonckheere.o tests/discrete/shrinkage.o tests/enums.o tests/gaussian/df.adjust.o tests/gaussian/gaussian.tests.o tests/gaussian/shrinkage.o tests/omnibus/custom.test.o tests/patterns/allsubs.test.o tests/patterns/ctest.o tests/patterns/roundrobin.test.o tests/patterns/utest.o tests/permutation/discrete.monte.carlo.o tests/permutation/gaussian.monte.carlo.o tests/rinterface/allsubs.test.o tests/rinterface/ctest.o tests/rinterface/htest.o tests/rinterface/indep.test.o tests/rinterface/roundrobin.test.o tests/rinterface/utest.o -llapack -lblas -lgfortran -lm -lquadmath -L/opt/R/4.4.0/lib/R/lib -lR installing to /tmp/workdir/bnlearn/new/bnlearn.Rcheck/00LOCK-bnlearn/00new/bnlearn/libs ** R ** data @@ -258,8 +264,10 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c foreign/parse.c -o foreign/parse.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c globals.c -o globals.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/acyclic.c -o graphs/acyclic.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/is.dag.c -o graphs/is.dag.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/completely.directed.c -o graphs/completely.directed.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/connected.components.c -o graphs/connected.components.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/path.c -o graphs/path.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/path.matrix.c -o graphs/path.matrix.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/pdag2dag.c -o graphs/pdag2dag.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/random/graph.generation.c -o graphs/random/graph.generation.o In file included from graphs/random/../../include/rcore.h:3, @@ -278,12 +286,15 @@ graphs/random/graph.generation.c:719:17: warning: assignment to ‘SEXP’ {aka 371 | #define PROTECT(s) Rf_protect(s) | ^ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/topological.ordering.c -o graphs/topological.ordering.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/rinterface/connected.components.c -o graphs/rinterface/connected.components.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/rinterface/path.matrix.c -o graphs/rinterface/path.matrix.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/rinterface/sid.c -o graphs/rinterface/sid.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c graphs/sid.c -o graphs/sid.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/likelihood.weighting.c -o inference/likelihood.weighting.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/common.c -o inference/loglikelihood/common.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/discrete.c -o inference/loglikelihood/discrete.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/gaussian.c -o inference/loglikelihood/gaussian.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loglikelihood/conditional.gaussian.c -o inference/loglikelihood/conditional.gaussian.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/loss.c -o inference/loss.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/rbn.c -o inference/rbn.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/rinterface/loglikelihood.c -o inference/rinterface/loglikelihood.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c inference/rinterface/cpdist.c -o inference/rinterface/cpdist.o @@ -304,17 +315,18 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c minimal/table.c -o minimal/table.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c minimal/tiers.c -o minimal/tiers.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c minimal/unique.c -o minimal/unique.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/classic_discrete.c -o parameters/discrete/classic_discrete.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/hierarchical_dirichlet.c -o parameters/discrete/hierarchical_dirichlet.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/classic_discrete.c -o parameters/rinterface/classic_discrete.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/hierarchical_dirichlet.c -o parameters/rinterface/hierarchical_dirichlet.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/mixture_ordinary_least_squares.c -o parameters/rinterface/mixture_ordinary_least_squares.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/ordinary_least_squares.c -o parameters/rinterface/ordinary_least_squares.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/classic.discrete.c -o parameters/discrete/classic.discrete.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/discrete/hierarchical.dirichlet.c -o parameters/discrete/hierarchical.dirichlet.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/classic.discrete.c -o parameters/rinterface/classic.discrete.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/hierarchical.dirichlet.c -o parameters/rinterface/hierarchical.dirichlet.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/mixture.ordinary.least.squares.c -o parameters/rinterface/mixture.ordinary.least.squares.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c parameters/rinterface/ordinary.least.squares.c -o parameters/rinterface/ordinary.least.squares.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c predict/map.lw.c -o predict/map.lw.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c predict/predict.c -o predict/predict.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/dedup.c -o preprocessing/dedup.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/discretize.c -o preprocessing/discretize.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/enums.c -o preprocessing/enums.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c preprocessing/rinterface/discretize.c -o preprocessing/rinterface/discretize.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c sanitization/cg.assumptions.c -o sanitization/cg.assumptions.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c sanitization/covariance.c -o sanitization/covariance.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c sanitization/data.c -o sanitization/data.o @@ -348,8 +360,8 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/gaussian.nal.c -o scores/gaussian.nal.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/gaussian.predictive.loglikelihood.c -o scores/gaussian.predictive.loglikelihood.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/graph.priors.c -o scores/graph.priors.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml_regret.c -o scores/nml_regret.o -gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml_regret_table.c -o scores/nml_regret_table.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml.regret.c -o scores/nml.regret.o +gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/nml.regret.table.c -o scores/nml.regret.table.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/normalized.maximum.likelihood.c -o scores/normalized.maximum.likelihood.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/per.node.score.c -o scores/per.node.score.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c scores/wishart.posterior.c -o scores/wishart.posterior.o @@ -391,7 +403,7 @@ gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c tests/rinterface/indep.test.c -o tests/rinterface/indep.test.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c tests/rinterface/roundrobin.test.c -o tests/rinterface/roundrobin.test.o gcc -std=gnu17 -I"/opt/R/4.4.0/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c tests/rinterface/utest.c -o tests/rinterface/utest.o -gcc -std=gnu17 -shared -L/opt/R/4.4.0/lib/R/lib -L/usr/local/lib -o bnlearn.so arcs/arcs2amat.o arcs/arcs2elist.o arcs/bind.o arcs/filter.arcs.o arcs/hash.o arcs/is.row.equal.o bnlearn/bayesian.network.o bnlearn/bn.recovery.o bnlearn/cache.structure.o bnlearn/cextend.o bnlearn/colliders.o bnlearn/cpdag.o bnlearn/fitted.o bnlearn/nparams.o bnlearn/shd.o core/allocations.o core/contingency.tables.o core/correlation.o core/covariance.matrix.o core/data.table.o core/math.functions.o core/moments.o core/sampling.o core/sets.o core/sort.o core/uppertriangular.o fitted/enums.o fitted/fitted.o fitted/nparams.o fitted/rinterface/nparams.o foreign/parse.o globals.o graphs/acyclic.o graphs/is.dag.o graphs/path.o graphs/pdag2dag.o graphs/random/graph.generation.o graphs/topological.ordering.o inference/likelihood.weighting.o inference/loglikelihood/common.o inference/loglikelihood/discrete.o inference/loglikelihood/gaussian.o inference/loglikelihood/conditional.gaussian.o inference/loss.o inference/rbn.o inference/rinterface/loglikelihood.o inference/rinterface/cpdist.o inference/rinterface/rbn.o inference/rinterface/likelihood.weighting.o learning/averaging/averaging.o learning/averaging/bootstrap.o learning/local/mi.matrix.o learning/score/hc.cache.lookup.o learning/score/score.delta.o learning/score/tabu.o math/conditional.least.squares.o math/least.squares.o math/linear.algebra.o minimal/common.o minimal/data.frame.o minimal/strings.o minimal/table.o minimal/tiers.o minimal/unique.o parameters/discrete/classic_discrete.o parameters/discrete/hierarchical_dirichlet.o parameters/rinterface/classic_discrete.o parameters/rinterface/hierarchical_dirichlet.o parameters/rinterface/mixture_ordinary_least_squares.o parameters/rinterface/ordinary_least_squares.o predict/map.lw.o predict/predict.o preprocessing/dedup.o preprocessing/discretize.o preprocessing/enums.o sanitization/cg.assumptions.o sanitization/covariance.o sanitization/data.o scores/alpha.star.o scores/cg.loglikelihood.o scores/cg.predictive.loglikelihood.o scores/cg.nal.o scores/custom.score.o scores/dirichlet.averaged.posterior.o scores/dirichlet.posterior.o scores/discrete.loglikelihood.o scores/discrete.nal.o scores/discrete.predictive.loglikelihood.o scores/enum.o scores/gaussian.loglikelihood.o scores/gaussian.nal.o scores/gaussian.predictive.loglikelihood.o scores/graph.priors.o scores/nml_regret.o scores/nml_regret_table.o scores/normalized.maximum.likelihood.o scores/per.node.score.o scores/wishart.posterior.o test.counter.o tests/conditional.gaussian/cg.mutual.information.o tests/discrete/df.adjust.o tests/discrete/discrete.tests.o tests/discrete/jonckheere.o tests/discrete/shrinkage.o tests/enums.o tests/gaussian/df.adjust.o tests/gaussian/gaussian.tests.o tests/gaussian/shrinkage.o tests/omnibus/custom.test.o tests/patterns/allsubs.test.o tests/patterns/ctest.o tests/patterns/roundrobin.test.o tests/patterns/utest.o tests/permutation/discrete.monte.carlo.o tests/permutation/gaussian.monte.carlo.o tests/rinterface/allsubs.test.o tests/rinterface/ctest.o tests/rinterface/htest.o tests/rinterface/indep.test.o tests/rinterface/roundrobin.test.o tests/rinterface/utest.o -llapack -lblas -lgfortran -lm -lquadmath -L/opt/R/4.4.0/lib/R/lib -lR +gcc -std=gnu17 -shared -L/opt/R/4.4.0/lib/R/lib -L/usr/local/lib -o bnlearn.so arcs/arcs2amat.o arcs/arcs2elist.o arcs/bind.o arcs/filter.arcs.o arcs/hash.o arcs/is.row.equal.o bnlearn/bayesian.network.o bnlearn/bn.recovery.o bnlearn/cache.structure.o bnlearn/cextend.o bnlearn/colliders.o bnlearn/cpdag.o bnlearn/fitted.o bnlearn/nparams.o bnlearn/shd.o core/allocations.o core/contingency.tables.o core/correlation.o core/covariance.matrix.o core/data.table.o core/math.functions.o core/moments.o core/sampling.o core/sets.o core/sort.o core/uppertriangular.o fitted/enums.o fitted/fitted.o fitted/nparams.o fitted/rinterface/nparams.o foreign/parse.o globals.o graphs/acyclic.o graphs/completely.directed.o graphs/connected.components.o graphs/path.o graphs/path.matrix.o graphs/pdag2dag.o graphs/random/graph.generation.o graphs/topological.ordering.o graphs/rinterface/connected.components.o graphs/rinterface/path.matrix.o graphs/rinterface/sid.o graphs/sid.o inference/likelihood.weighting.o inference/loglikelihood/common.o inference/loglikelihood/discrete.o inference/loglikelihood/gaussian.o inference/loglikelihood/conditional.gaussian.o inference/rbn.o inference/rinterface/loglikelihood.o inference/rinterface/cpdist.o inference/rinterface/rbn.o inference/rinterface/likelihood.weighting.o learning/averaging/averaging.o learning/averaging/bootstrap.o learning/local/mi.matrix.o learning/score/hc.cache.lookup.o learning/score/score.delta.o learning/score/tabu.o math/conditional.least.squares.o math/least.squares.o math/linear.algebra.o minimal/common.o minimal/data.frame.o minimal/strings.o minimal/table.o minimal/tiers.o minimal/unique.o parameters/discrete/classic.discrete.o parameters/discrete/hierarchical.dirichlet.o parameters/rinterface/classic.discrete.o parameters/rinterface/hierarchical.dirichlet.o parameters/rinterface/mixture.ordinary.least.squares.o parameters/rinterface/ordinary.least.squares.o predict/map.lw.o predict/predict.o preprocessing/dedup.o preprocessing/discretize.o preprocessing/enums.o preprocessing/rinterface/discretize.o sanitization/cg.assumptions.o sanitization/covariance.o sanitization/data.o scores/alpha.star.o scores/cg.loglikelihood.o scores/cg.predictive.loglikelihood.o scores/cg.nal.o scores/custom.score.o scores/dirichlet.averaged.posterior.o scores/dirichlet.posterior.o scores/discrete.loglikelihood.o scores/discrete.nal.o scores/discrete.predictive.loglikelihood.o scores/enum.o scores/gaussian.loglikelihood.o scores/gaussian.nal.o scores/gaussian.predictive.loglikelihood.o scores/graph.priors.o scores/nml.regret.o scores/nml.regret.table.o scores/normalized.maximum.likelihood.o scores/per.node.score.o scores/wishart.posterior.o test.counter.o tests/conditional.gaussian/cg.mutual.information.o tests/discrete/df.adjust.o tests/discrete/discrete.tests.o tests/discrete/jonckheere.o tests/discrete/shrinkage.o tests/enums.o tests/gaussian/df.adjust.o tests/gaussian/gaussian.tests.o tests/gaussian/shrinkage.o tests/omnibus/custom.test.o tests/patterns/allsubs.test.o tests/patterns/ctest.o tests/patterns/roundrobin.test.o tests/patterns/utest.o tests/permutation/discrete.monte.carlo.o tests/permutation/gaussian.monte.carlo.o tests/rinterface/allsubs.test.o tests/rinterface/ctest.o tests/rinterface/htest.o tests/rinterface/indep.test.o tests/rinterface/roundrobin.test.o tests/rinterface/utest.o -llapack -lblas -lgfortran -lm -lquadmath -L/opt/R/4.4.0/lib/R/lib -lR installing to /tmp/workdir/bnlearn/old/bnlearn.Rcheck/00LOCK-bnlearn/00new/bnlearn/libs ** R ** data @@ -535,6 +547,80 @@ ERROR: lazy loading failed for package ‘datapack’ * removing ‘/tmp/workdir/datapack/old/datapack.Rcheck/datapack’ +``` +# EGAnet + +
+ +* Version: 2.3.0 +* GitHub: https://github.com/hfgolino/EGAnet +* Source code: https://github.com/cran/EGAnet +* Date/Publication: 2025-04-09 23:10:15 UTC +* Number of recursive dependencies: 181 + +Run `revdepcheck::cloud_details(, "EGAnet")` for more info + +
+ +## Error before installation + +### Devel + +``` +* using log directory ‘/tmp/workdir/EGAnet/new/EGAnet.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘EGAnet/DESCRIPTION’ ... OK +* this is package ‘EGAnet’ version ‘2.3.0’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + + + +``` +### CRAN + +``` +* using log directory ‘/tmp/workdir/EGAnet/old/EGAnet.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘EGAnet/DESCRIPTION’ ... OK +* this is package ‘EGAnet’ version ‘2.3.0’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + + + ``` # FAfA @@ -544,55 +630,69 @@ ERROR: lazy loading failed for package ‘datapack’ * GitHub: NA * Source code: https://github.com/cran/FAfA * Date/Publication: 2025-05-23 19:42:09 UTC -* Number of recursive dependencies: 248 +* Number of recursive dependencies: 249 Run `revdepcheck::cloud_details(, "FAfA")` for more info
-## In both - -* checking whether package ‘FAfA’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/FAfA/new/FAfA.Rcheck/00install.out’ for details. - ``` - -## Installation +## Error before installation ### Devel ``` -* installing *source* package ‘FAfA’ ... -** package ‘FAfA’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘FAfA’ -* removing ‘/tmp/workdir/FAfA/new/FAfA.Rcheck/FAfA’ +* using log directory ‘/tmp/workdir/FAfA/new/FAfA.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘FAfA/DESCRIPTION’ ... OK +* this is package ‘FAfA’ version ‘0.3’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Packages required but not available: 'MBESS', 'semPlot' + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` ### CRAN ``` -* installing *source* package ‘FAfA’ ... -** package ‘FAfA’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘FAfA’ -* removing ‘/tmp/workdir/FAfA/old/FAfA.Rcheck/FAfA’ +* using log directory ‘/tmp/workdir/FAfA/old/FAfA.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘FAfA/DESCRIPTION’ ... OK +* this is package ‘FAfA’ version ‘0.3’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Packages required but not available: 'MBESS', 'semPlot' + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` @@ -672,49 +772,63 @@ Run `revdepcheck::cloud_details(, "lavaan.shiny")` for more info -## In both - -* checking whether package ‘lavaan.shiny’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/lavaan.shiny/new/lavaan.shiny.Rcheck/00install.out’ for details. - ``` - -## Installation +## Error before installation ### Devel ``` -* installing *source* package ‘lavaan.shiny’ ... -** package ‘lavaan.shiny’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘lavaan.shiny’ -* removing ‘/tmp/workdir/lavaan.shiny/new/lavaan.shiny.Rcheck/lavaan.shiny’ +* using log directory ‘/tmp/workdir/lavaan.shiny/new/lavaan.shiny.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘lavaan.shiny/DESCRIPTION’ ... OK +* checking extension type ... Package +* this is package ‘lavaan.shiny’ version ‘1.2’ +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` ### CRAN ``` -* installing *source* package ‘lavaan.shiny’ ... -** package ‘lavaan.shiny’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘lavaan.shiny’ -* removing ‘/tmp/workdir/lavaan.shiny/old/lavaan.shiny.Rcheck/lavaan.shiny’ +* using log directory ‘/tmp/workdir/lavaan.shiny/old/lavaan.shiny.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘lavaan.shiny/DESCRIPTION’ ... OK +* checking extension type ... Package +* this is package ‘lavaan.shiny’ version ‘1.2’ +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` @@ -2924,59 +3038,34 @@ Status: 1 NOTE
-* Version: 0.4 +* Version: NA * GitHub: NA * Source code: https://github.com/cran/RSP -* Date/Publication: 2023-09-24 21:00:02 UTC -* Number of recursive dependencies: 239 +* Number of recursive dependencies: 0 Run `revdepcheck::cloud_details(, "RSP")` for more info
-## In both - -* checking whether package ‘RSP’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/RSP/new/RSP.Rcheck/00install.out’ for details. - ``` - -## Installation +## Error before installation ### Devel ``` -* installing *source* package ‘RSP’ ... -** package ‘RSP’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘RSP’ -* removing ‘/tmp/workdir/RSP/new/RSP.Rcheck/RSP’ + + + + ``` ### CRAN ``` -* installing *source* package ‘RSP’ ... -** package ‘RSP’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘RSP’ -* removing ‘/tmp/workdir/RSP/old/RSP.Rcheck/RSP’ + + + + ``` @@ -2994,49 +3083,65 @@ Run `revdepcheck::cloud_details(, "sphereML")` for more info -## In both - -* checking whether package ‘sphereML’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/sphereML/new/sphereML.Rcheck/00install.out’ for details. - ``` - -## Installation +## Error before installation ### Devel ``` -* installing *source* package ‘sphereML’ ... -** package ‘sphereML’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘sphereML’ -* removing ‘/tmp/workdir/sphereML/new/sphereML.Rcheck/sphereML’ +* using log directory ‘/tmp/workdir/sphereML/new/sphereML.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘sphereML/DESCRIPTION’ ... OK +* checking extension type ... Package +* this is package ‘sphereML’ version ‘0.1.1’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` ### CRAN ``` -* installing *source* package ‘sphereML’ ... -** package ‘sphereML’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘sphereML’ -* removing ‘/tmp/workdir/sphereML/old/sphereML.Rcheck/sphereML’ +* using log directory ‘/tmp/workdir/sphereML/old/sphereML.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘sphereML/DESCRIPTION’ ... OK +* checking extension type ... Package +* this is package ‘sphereML’ version ‘0.1.1’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` @@ -3126,49 +3231,63 @@ Run `revdepcheck::cloud_details(, "TestAnaAPP")` for more info -## In both - -* checking whether package ‘TestAnaAPP’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/TestAnaAPP/new/TestAnaAPP.Rcheck/00install.out’ for details. - ``` - -## Installation +## Error before installation ### Devel ``` -* installing *source* package ‘TestAnaAPP’ ... -** package ‘TestAnaAPP’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘TestAnaAPP’ -* removing ‘/tmp/workdir/TestAnaAPP/new/TestAnaAPP.Rcheck/TestAnaAPP’ +* using log directory ‘/tmp/workdir/TestAnaAPP/new/TestAnaAPP.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘TestAnaAPP/DESCRIPTION’ ... OK +* this is package ‘TestAnaAPP’ version ‘1.1.2’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` ### CRAN ``` -* installing *source* package ‘TestAnaAPP’ ... -** package ‘TestAnaAPP’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in loadNamespace(i, c(lib.loc, .libPaths()), versionCheck = vI[[i]]) : - there is no package called ‘OpenMx’ -Calls: ... loadNamespace -> withRestarts -> withOneRestart -> doWithOneRestart -Execution halted -ERROR: lazy loading failed for package ‘TestAnaAPP’ -* removing ‘/tmp/workdir/TestAnaAPP/old/TestAnaAPP.Rcheck/TestAnaAPP’ +* using log directory ‘/tmp/workdir/TestAnaAPP/old/TestAnaAPP.Rcheck’ +* using R version 4.4.0 (2024-04-24) +* using platform: x86_64-pc-linux-gnu +* R was compiled by + gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 + GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 +* running under: Ubuntu 24.04.2 LTS +* using session charset: UTF-8 +* using option ‘--no-manual’ +* checking for file ‘TestAnaAPP/DESCRIPTION’ ... OK +* this is package ‘TestAnaAPP’ version ‘1.1.2’ +* package encoding: UTF-8 +* checking package namespace information ... OK +* checking package dependencies ... ERROR +Package required but not available: ‘semPlot’ + +See section ‘The DESCRIPTION file’ in the ‘Writing R Extensions’ +manual. +* DONE +Status: 1 ERROR + + + ``` diff --git a/revdep/problems.md b/revdep/problems.md index 96808f9b44b..d940d1529c7 100644 --- a/revdep/problems.md +++ b/revdep/problems.md @@ -435,16 +435,16 @@ Run `revdepcheck::cloud_details(, "DrDimont")` for more info + reduction_method="pickHardThreshold", + r_squared=list(default=0.65, metabolite=0.1), + cut_vector=list(default=seq(0.2, 0.5, 0.01))) - [25-07-10 09:23:08] WARNING: Python executable in virtual environment 'r-DrDimont' not found. Either run `install_python_dependencies(package_manager='pip') or set `conda=TRUE` in `drdimont_settings()` if conda installation was used. + [25-09-05 04:12:21] WARNING: Python executable in virtual environment 'r-DrDimont' not found. Either run `install_python_dependencies(package_manager='pip') or set `conda=TRUE` in `drdimont_settings()` if conda installation was used. > > example_individual_graphs <- generate_individual_graphs( + correlation_matrices=correlation_matrices_example, + layers=layers_example, + settings=example_settings) - [25-07-10 09:23:08] Generating graph of layer mrna for groupA... - [25-07-10 09:23:08] Reducing network by WGCNA::pickHardThreshold... - [25-07-10 09:23:08] R2 cutoff: 0.65 - [25-07-10 09:23:08] Cut Threshold: 0.26 + [25-09-05 04:12:21] Generating graph of layer mrna for groupA... + [25-09-05 04:12:21] Reducing network by WGCNA::pickHardThreshold... + [25-09-05 04:12:21] R2 cutoff: 0.65 + [25-09-05 04:12:22] Cut Threshold: 0.26 Error in `graph_from_adjacency_matrix()`: ! Cannot create a graph object because the adjacency matrix contains NAs. @@ -491,75 +491,6 @@ Run `revdepcheck::cloud_details(, "DrDimont")` for more info | ^ ``` -# EGAnet - -
- -* Version: 2.3.0 -* GitHub: https://github.com/hfgolino/EGAnet -* Source code: https://github.com/cran/EGAnet -* Date/Publication: 2025-04-09 23:10:15 UTC -* Number of recursive dependencies: 180 - -Run `revdepcheck::cloud_details(, "EGAnet")` for more info - -
- -## Newly broken - -* checking examples ... ERROR - ``` - Running examples in ‘EGAnet-Ex.R’ failed - The error most likely occurred in: - - > ### Name: EGA - > ### Title: Exploratory Graph Analysis - > ### Aliases: EGA - > - > ### ** Examples - > - > # Obtain data - > wmt <- wmt2[,7:24] - > - > # Estimate EGA - > ega.wmt <- EGA( - + data = wmt, - + plot.EGA = FALSE # No plot for CRAN checks - + ) - Error in `set_vertex_attr()`: - ! `name` must be a single string, not `FALSE`. - Backtrace: - ▆ - 1. └─EGAnet::EGA(data = wmt, plot.EGA = FALSE) - 2. └─EGAnet::EGA.estimate(...) - 3. ├─base::do.call(...) - 4. └─EGAnet (local) ``(...) - 5. └─EGAnet::convert2igraph(network) - 6. ├─EGAnet:::silent_call(...) - 7. │ ├─utils::capture.output(result <- suppressWarnings(suppressMessages(...))) - 8. │ │ └─base::withVisible(...elt(i)) - 9. │ ├─base::suppressWarnings(suppressMessages(...)) - 10. │ │ └─base::withCallingHandlers(...) - 11. │ └─base::suppressMessages(...) - 12. │ └─base::withCallingHandlers(...) - 13. └─igraph::graph_from_adjacency_matrix(...) - 14. └─igraph::set_vertex_attr(name = add.colnames) - 15. └─igraph:::check_string(name) - 16. └─igraph:::stop_input_type(...) - 17. └─rlang::abort(message, ..., call = call, arg = arg) - Execution halted - ``` - -## In both - -* checking installed package size ... NOTE - ``` - installed size is 6.2Mb - sub-directories of 1Mb or more: - R 1.5Mb - data 4.0Mb - ``` - # egor
@@ -691,176 +622,14 @@ Run `revdepcheck::cloud_details(, "GephiForR")` for more info Execution halted ``` -# gor - -
- -* Version: 1.0 -* GitHub: NA -* Source code: https://github.com/cran/gor -* Date/Publication: 2023-05-03 18:40:02 UTC -* Number of recursive dependencies: 11 - -Run `revdepcheck::cloud_details(, "gor")` for more info - -
- -## Newly broken - -* checking examples ... ERROR - ``` - Running examples in ‘gor-Ex.R’ failed - The error most likely occurred in: - - > ### Name: generate_fundamental_cycles - > ### Title: Generate fundamental cycles in a connected graph - > ### Aliases: generate_fundamental_cycles - > - > ### ** Examples - > - > g <- make_graph("Dodecahedron") - > n <- gorder(g) - > b <- bfs(g, 1, father = TRUE) # BFS tree - Warning: The `father` argument of `bfs()` is deprecated as of igraph 2.2.0. - ℹ Please use the `parent` argument instead. - > T <- make_graph(rbind(b$father[2:n], 2:n), n) # Tree as igraph graph - > eT <- as_edgelist(T) - > eG <- as_edgelist(g) - > C <- generate_fundamental_cycles(eT, eG) # Fundamental cycles - > mu <- gsize(g) - gorder(g) + 1 # Cyclomatic number - > z <- layout_with_gem(g) - > for (i in 1:mu) { # Cycle drawing - + c1 <- make_graph(t(eG[which(C[i,] == 1),]) , dir = FALSE) - + plot(g, layout = z) - + plot(c1, layout = z, add = TRUE, edge.color = "cyan4", - + edge.lty = "dashed", edge.width = 3) - + title(paste0("Cycle ", i, " of ", mu)) - + #Sys.sleep(1) # Adjust time to see the cycles - + } - Error in `plot()`: - ! The layout has 20 rows, but the graph has 5 vertices. - ℹ It is recommended to store the layout as x and y vertex attributes and not as - a matrix graph attribute. - Backtrace: - ▆ - 1. ├─base::plot(...) - 2. └─igraph::plot.igraph(...) - 3. └─cli::cli_abort(...) - 4. └─rlang::abort(...) - Execution halted - ``` - -## In both - -* checking Rd files ... NOTE - ``` - checkRd: (-1) compute_lower_bound_1tree.Rd:31: Lost braces; missing escapes or markup? - 31 | instance from vertex 1. Internally, it creates the graph Kn-{v1} - | ^ - ``` - -# handwriterRF - -
- -* Version: 1.1.1 -* GitHub: https://github.com/CSAFE-ISU/handwriterRF -* Source code: https://github.com/cran/handwriterRF -* Date/Publication: 2025-01-29 00:20:01 UTC -* Number of recursive dependencies: 123 - -Run `revdepcheck::cloud_details(, "handwriterRF")` for more info - -
- -## Newly broken - -* checking tests ... ERROR - ``` - Running ‘testthat.R’ - Running the tests in ‘tests/testthat.R’ failed. - Complete output: - > # This file is part of the standard setup for testthat. - > # It is recommended that you do not modify it. - > # - > # Where should you do additional test configuration? - > # Learn more about the roles of various files in: - > # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview - > # * https://testthat.r-lib.org/articles/special-files.html - > - > library(testthat) - > library(handwriterRF) - > - > test_check("handwriterRF") - Copying samples to project directory > docs... - - Estimating writer profiles... - Listing documents to be processed... - Creating output directory... - Directory already exists. - Processing document w0030_s01_pWOZ_r01.png... - path in readPNGBinary: /tmp/RtmpSZltDI/comparison/docs/w0030_s01_pWOZ_r01.png - Starting Processing... - Getting Nodes... - Skeletonizing writing... - Splitting document into components... - Merging nodes... - Finding paths... - Split paths into graphs... - Organizing graphs... - Creating graph lists... - Adding character features... - Document processing complete - Saving processed document w0030_s01_pWOZ_r01.png... - - Processing document w0030_s01_pWOZ_r02.png... - path in readPNGBinary: /tmp/RtmpSZltDI/comparison/docs/w0030_s01_pWOZ_r02.png - Starting Processing... - Getting Nodes... - Skeletonizing writing... - Splitting document into components... - Merging nodes... - Finding paths... - Split paths into graphs... - Organizing graphs... - Creating graph lists... - Adding character features... - Document processing complete - Saving processed document w0030_s01_pWOZ_r02.png... - - All documents were successfully processed... - - Loading graphs for w0030_s01_pWOZ_r01_proclist.rds - Getting cluster assignments for w0030_s01_pWOZ_r01 - Saving cluster assignments for w0030_s01_pWOZ_r01 - - Loading graphs for w0030_s01_pWOZ_r02_proclist.rds - Getting cluster assignments for w0030_s01_pWOZ_r02 - Saving cluster assignments for w0030_s01_pWOZ_r02 - - Calculating distance between samples... - Calculating similarity score... - Calculating distance between samples... - Calculating similarity score... - Calculating distance between samples... - Calculating similarity score... - Calculating distance between samples... - Calculating similarity score... - Calculating SLR... - Calculating distance between samples... - Calculating similarity score... - Calculating SLR... - Killed - ``` - # incidentally
-* Version: 1.0.2 +* Version: 1.0.3 * GitHub: https://github.com/zpneal/incidentally * Source code: https://github.com/cran/incidentally -* Date/Publication: 2023-02-15 21:00:02 UTC +* Date/Publication: 2025-07-28 22:10:02 UTC * Number of recursive dependencies: 36 Run `revdepcheck::cloud_details(, "incidentally")` for more info @@ -1004,11 +773,11 @@ Run `revdepcheck::cloud_details(, "klassR")` for more info
-* Version: 1.5.1 +* Version: 1.6.0 * GitHub: https://github.com/stocnet/manynet * Source code: https://github.com/cran/manynet -* Date/Publication: 2025-06-23 08:30:02 UTC -* Number of recursive dependencies: 135 +* Date/Publication: 2025-08-22 23:40:02 UTC +* Number of recursive dependencies: 117 Run `revdepcheck::cloud_details(, "manynet")` for more info @@ -1021,31 +790,23 @@ Run `revdepcheck::cloud_details(, "manynet")` for more info Running examples in ‘manynet-Ex.R’ failed The error most likely occurred in: - > ### Name: manip_paths - > ### Title: Modifying networks paths - > ### Aliases: manip_paths to_matching to_mentoring to_eulerian to_tree - > ### to_dominating + > ### Name: mark_features + > ### Title: Marking networks features + > ### Aliases: mark_features is_connected is_perfect_matching is_eulerian + > ### is_acyclic is_aperiodic > > ### ** Examples > - > to_matching(ison_southern_women) - Error in `igraph::graph_from_data_frame()`: - ! Cannot create a graph object because the edge data frame contains NAs. - Backtrace: - ▆ - 1. ├─manynet::to_matching(ison_southern_women) - 2. └─manynet:::to_matching.tbl_graph(ison_southern_women) - 3. ├─manynet::as_tidygraph(to_matching.igraph(.data, mark, capacities = capacities)) - 4. └─manynet:::to_matching.igraph(.data, mark, capacities = capacities) - 5. ├─base::suppressWarnings(as_igraph(el, twomode = TRUE)) - 6. │ └─base::withCallingHandlers(...) - 7. ├─manynet::as_igraph(el, twomode = TRUE) - 8. └─manynet:::as_igraph.data.frame(el, twomode = TRUE) - 9. └─igraph::graph_from_data_frame(.data) - 10. └─igraph:::ensure_no_na(d[, 1:2], "edge data frame") - 11. └─cli::cli_abort(...) - 12. └─rlang::abort(...) - Execution halted + > is_connected(ison_southern_women) + [1] TRUE + > is_perfect_matching(ison_southern_women) + [1] FALSE + > is_eulerian(ison_brandes) + [1] FALSE + > is_acyclic(ison_algebra) + [1] FALSE + > is_aperiodic(ison_algebra) + Killed ``` * checking tests ... ERROR @@ -1058,77 +819,34 @@ Run `revdepcheck::cloud_details(, "manynet")` for more info > > test_check("manynet") Starting 2 test processes - [ FAIL 2 | WARN 404 | SKIP 20 | PASS 570 ] - ══ Skipped tests (20) ══════════════════════════════════════════════════════════ - • On CRAN (20): 'test-manip_as.R:86:3', 'test-manip_split.R:49:3', - 'test-map_autograph.R:2:3', 'test-map_autograph.R:17:3', - 'test-map_autograph.R:31:3', 'test-map_autograph.R:47:3', - 'test-map_autograph.R:65:3', 'test-map_autograph.R:91:3', - 'test-map_autograph.R:103:3', 'test-map_autograph.R:113:3', - 'test-map_autograph.R:120:3', 'test-map_autograph.R:127:3', - 'test-map_autograph.R:140:3', 'test-map_autograph.R:171:3', - 'test-map_autograph.R:180:3', 'test-mark_nodes.R:36:3', - 'test-mark_nodes.R:45:3', 'test-mark_nodes.R:81:3', 'test-mark_ties.R:24:3', - 'test-mark_ties.R:33:3' - ══ Failed tests ════════════════════════════════════════════════════════════════ - ── Error ('test-mark_is.R:12:3'): is_ tests return correct values ────────────── - Error in `igraph::graph_from_data_frame(.data)`: Cannot create a graph object because the edge data frame contains NAs. + Error in `private$handle_error()`: + ! testthat subprocess exited in file `test-measure_closure.R` + Caused by error: + ! R session crashed with exit code -9 Backtrace: ▆ - 1. ├─testthat::expect_false(is_perfect_matching(ison_southern_women)) at test-mark_is.R:12:3 - 2. │ └─testthat::quasi_label(enquo(object), label, arg = "object") - 3. │ └─rlang::eval_bare(expr, quo_get_env(quo)) - 4. └─manynet::is_perfect_matching(ison_southern_women) - 5. ├─manynet::to_matching(.data, mark = mark) - 6. └─manynet:::to_matching.igraph(.data, mark = mark) - 7. ├─base::suppressWarnings(as_igraph(el, twomode = TRUE)) - 8. │ └─base::withCallingHandlers(...) - 9. ├─manynet::as_igraph(el, twomode = TRUE) - 10. └─manynet:::as_igraph.data.frame(el, twomode = TRUE) - 11. └─igraph::graph_from_data_frame(.data) - 12. └─igraph:::ensure_no_na(d[, 1:2], "edge data frame") - 13. └─cli::cli_abort(...) - 14. └─rlang::abort(...) - ── Error ('test-manip_transform.R:43:3'): to matching works ──────────────────── - Error in `igraph::graph_from_data_frame(.data)`: Cannot create a graph object because the edge data frame contains NAs. - Backtrace: - ▆ - 1. ├─manynet::as_edgelist(to_matching(ison_southern_women)) at test-manip_transform.R:43:3 - 2. ├─manynet::to_matching(ison_southern_women) - 3. └─manynet:::to_matching.tbl_graph(ison_southern_women) - 4. ├─manynet::as_tidygraph(to_matching.igraph(.data, mark, capacities = capacities)) - 5. └─manynet:::to_matching.igraph(.data, mark, capacities = capacities) - 6. ├─base::suppressWarnings(as_igraph(el, twomode = TRUE)) - 7. │ └─base::withCallingHandlers(...) - 8. ├─manynet::as_igraph(el, twomode = TRUE) - 9. └─manynet:::as_igraph.data.frame(el, twomode = TRUE) - 10. └─igraph::graph_from_data_frame(.data) - 11. └─igraph:::ensure_no_na(d[, 1:2], "edge data frame") - 12. └─cli::cli_abort(...) - 13. └─rlang::abort(...) - - [ FAIL 2 | WARN 404 | SKIP 20 | PASS 570 ] - Error: Test failures + 1. └─testthat::test_check("manynet") + 2. └─testthat::test_dir(...) + 3. └─testthat:::test_files(...) + 4. └─testthat:::test_files_parallel(...) + 5. ├─withr::with_dir(...) + 6. │ └─base::force(code) + 7. ├─testthat::with_reporter(...) + 8. │ └─base::tryCatch(...) + 9. │ └─base (local) tryCatchList(expr, classes, parentenv, handlers) + 10. │ └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]]) + 11. │ └─base (local) doTryCatch(return(expr), name, parentenv, handler) + 12. └─testthat:::parallel_event_loop_chunky(queue, reporters, ".") + 13. └─queue$poll(Inf) + 14. └─base::lapply(...) + 15. └─testthat (local) FUN(X[[i]], ...) + 16. └─private$handle_error(msg, i) + 17. └─rlang::abort(...) Execution halted ``` -## In both - -* checking package dependencies ... NOTE - ``` - Package which this enhances but not available for checking: ‘Rgraphviz’ - ``` - -* checking installed package size ... NOTE - ``` - installed size is 5.1Mb - sub-directories of 1Mb or more: - R 1.5Mb - tutorials 1.6Mb - ``` - # multinet
@@ -1284,69 +1002,6 @@ Run `revdepcheck::cloud_details(, "mwcsr")` for more info libs 10.5Mb ``` -# pathfindR - -
- -* Version: 2.5.0 -* GitHub: https://github.com/egeulgen/pathfindR -* Source code: https://github.com/cran/pathfindR -* Date/Publication: 2025-06-15 00:00:02 UTC -* Number of recursive dependencies: 147 - -Run `revdepcheck::cloud_details(, "pathfindR")` for more info - -
- -## Newly broken - -* checking tests ... ERROR - ``` - Running ‘testthat-active_snw.R’ - Running ‘testthat-clustering.R’ - Running the tests in ‘tests/testthat-clustering.R’ failed. - Complete output: - > library(testthat) - > library(pathfindR) - Loading required package: pathfindR.data - ############################################################################## - Welcome to pathfindR! - - Please cite the article below if you use pathfindR in published reseach: - - Ulgen E, Ozisik O, Sezerman OU. 2019. pathfindR: An R Package for Comprehensive - Identification of Enriched Pathways in Omics Data Through Active Subnetworks. - Front. Genet. doi:10.3389/fgene.2019.00858 - - ############################################################################## - > - > test_check("pathfindR", filter = "clustering") - [ FAIL 1 | WARN 0 | SKIP 0 | PASS 77 ] - - ══ Failed tests ════════════════════════════════════════════════════════════════ - ── Error ('test-clustering.R:198:5'): `cluster_graph_vis()` -- coloring of 'extra' clusters work ── - Error in `igraph::graph_from_adjacency_matrix(kappa_mat2, weighted = TRUE)`: Cannot create a graph object because the adjacency matrix contains NAs. - Backtrace: - ▆ - 1. ├─testthat::expect_silent(...) at test-clustering.R:198:5 - 2. │ └─testthat:::quasi_capture(enquo(object), NULL, evaluate_promise) - 3. │ ├─testthat (local) .capture(...) - 4. │ │ ├─withr::with_output_sink(...) - 5. │ │ │ └─base::force(code) - 6. │ │ ├─base::withCallingHandlers(...) - 7. │ │ └─base::withVisible(code) - 8. │ └─rlang::eval_bare(quo_get_expr(.quo), quo_get_env(.quo)) - 9. └─pathfindR::cluster_graph_vis(...) - 10. └─igraph::graph_from_adjacency_matrix(kappa_mat2, weighted = TRUE) - 11. └─igraph:::ensure_no_na(adjmatrix, "adjacency matrix") - 12. └─cli::cli_abort(...) - 13. └─rlang::abort(...) - - [ FAIL 1 | WARN 0 | SKIP 0 | PASS 77 ] - Error: Test failures - Execution halted - ``` - # PopComm
@@ -1443,7 +1098,7 @@ Run `revdepcheck::cloud_details(, "remify")` for more info test-rehshape.R............... 24 tests OK test-rehshape.R............... 24 tests OK test-rehshape.R............... 25 tests OK - test-rehshape.R............... 26 tests OK 2.9s + test-rehshape.R............... 26 tests OK 2.3s test-remify-error-messages.R.. 1 tests OK test-remify-error-messages.R.. 1 tests OK @@ -1496,7 +1151,7 @@ Run `revdepcheck::cloud_details(, "remify")` for more info test-remify-error-messages.R.. 19 tests OK test-remify-error-messages.R.. 20 tests OK test-remify-error-messages.R.. 20 tests OK - test-remify-error-messages.R.. 21 tests OK 0.2s + test-remify-error-messages.R.. 21 tests OK 0.1s test-remify-methods.R......... 0 tests test-remify-methods.R......... 0 tests @@ -1658,7 +1313,7 @@ Run `revdepcheck::cloud_details(, "remify")` for more info test-remify-methods.R......... 112 tests 10 fails test-remify-methods.R......... 112 tests 10 fails test-remify-methods.R......... 112 tests 10 fails - test-remify-methods.R......... 113 tests 10 fails 11.4s + test-remify-methods.R......... 113 tests 10 fails 7.6s test-remify-warning-messages.R 0 tests test-remify-warning-messages.R 0 tests @@ -1728,7 +1383,7 @@ Run `revdepcheck::cloud_details(, "remify")` for more info test-remify-warning-messages.R 29 tests OK test-remify-warning-messages.R 29 tests OK test-remify-warning-messages.R 30 tests OK - test-remify-warning-messages.R 31 tests OK 0.6s + test-remify-warning-messages.R 31 tests OK 0.5s test-remify.R................. 0 tests test-remify.R................. 1 tests OK @@ -1860,7 +1515,7 @@ Run `revdepcheck::cloud_details(, "remify")` for more info test-remify.R................. 61 tests OK test-remify.R................. 62 tests OK test-remify.R................. 62 tests OK - test-remify.R................. 63 tests OK 0.7s + test-remify.R................. 63 tests OK 0.5s ----- FAILED[xcpt]: test-remify-methods.R<349--349> call| expect_silent(plot(x = out)) diff| Execution was not silent. A warning was thrown with message From 6b3b01d46f2c077f680b6af78f869d4dac934ecf Mon Sep 17 00:00:00 2001 From: David Schoch Date: Thu, 11 Sep 2025 21:45:02 +0200 Subject: [PATCH 046/154] tests: add tests for aaa-auto.R (#2129) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kirill Müller --- .github/workflows/update-snapshots/action.yml | 3 +- R/aaa-auto.R | 8 +- patch/0005-induced_subgraph_map.patch | 25 + patch/0006-count_reachable.patch | 25 + tests/testthat/_snaps/aaa-auto.md | 10092 ++++++++++++++++ tests/testthat/helper.R | 11 + tests/testthat/test-aaa-auto.R | 5539 +++++++++ tools/stimulus/functions-R.yaml | 5 +- tools/stimulus/types-RR.yaml | 2 + 9 files changed, 15704 insertions(+), 6 deletions(-) create mode 100644 patch/0005-induced_subgraph_map.patch create mode 100644 patch/0006-count_reachable.patch create mode 100644 tests/testthat/_snaps/aaa-auto.md create mode 100644 tests/testthat/test-aaa-auto.R diff --git a/.github/workflows/update-snapshots/action.yml b/.github/workflows/update-snapshots/action.yml index 03d2173f1b0..f283171b778 100644 --- a/.github/workflows/update-snapshots/action.yml +++ b/.github/workflows/update-snapshots/action.yml @@ -24,7 +24,8 @@ runs: pattern <- paste0(patterns, collapse = "|") tryCatch( { - result <- as.data.frame(testthat::test_local(pattern = pattern, reporter = "silent", stop_on_failure = FALSE)) + Sys.setenv(TESTTHAT_PARALLEL = FALSE) + result <- as.data.frame(testthat::test_local(pattern = pattern, reporter = "location", stop_on_failure = FALSE)) print(result) failures <- result[result$failed + result$warning > 0, ] if (nrow(failures) > 0) { diff --git a/R/aaa-auto.R b/R/aaa-auto.R index 0efaf034194..26e49b83a33 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -348,8 +348,8 @@ full_bipartite_impl <- function(n1, n2, directed=FALSE, mode=c("all", "out", "in on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_full_bipartite, n1, n2, directed, mode) - if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$types) <- vertex_attr(graph, "name") + if (igraph_opt("add.vertex.names") && is_named(res$graph)) { + names(res$types) <- vertex_attr(res$graph, "name") } res } @@ -2549,8 +2549,8 @@ biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", "out", " on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_biadjacency, biadjmatrix, directed, mode, multiple) - if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$types) <- vertex_attr(graph, "name", V(graph)) + if (igraph_opt("add.vertex.names") && is_named(res$graph)) { + names(res$types) <- vertex_attr(res$graph, "name", V(res$graph)) } res } diff --git a/patch/0005-induced_subgraph_map.patch b/patch/0005-induced_subgraph_map.patch new file mode 100644 index 00000000000..e541ec5824f --- /dev/null +++ b/patch/0005-induced_subgraph_map.patch @@ -0,0 +1,25 @@ +From e8e2fedaa1eaf6a47d388e7a264d55c8b0d49c17 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Kirill=20M=C3=BCller?= +Date: Thu, 11 Sep 2025 11:13:47 +0200 +Subject: [PATCH] induced_subgraph_map + +--- + src/vendor/cigraph/interfaces/functions.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml +index c7e2319550..da6f8b3c16 100644 +--- a/src/vendor/cigraph/interfaces/functions.yaml ++++ b/src/vendor/cigraph/interfaces/functions.yaml +@@ -2126,7 +2126,7 @@ igraph_compose: + + igraph_induced_subgraph_map: + PARAMS: |- +- GRAPH graph, OUT GRAPH res, VERTEX_SELECTOR vids, SUBGRAPH_IMPL impl, ++ GRAPH graph, OUT GRAPH res, VERTEX_SELECTOR vids, SUBGRAPH_IMPL impl=AUTO, + OPTIONAL OUT INDEX_VECTOR map, OPTIONAL OUT INDEX_VECTOR invmap + DEPS: vids ON graph + +-- +2.50.1 + diff --git a/patch/0006-count_reachable.patch b/patch/0006-count_reachable.patch new file mode 100644 index 00000000000..919de16539d --- /dev/null +++ b/patch/0006-count_reachable.patch @@ -0,0 +1,25 @@ +From 6eb407bbd348403507efaa4dd562031880cf3c88 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Kirill=20M=C3=BCller?= +Date: Thu, 11 Sep 2025 11:17:49 +0200 +Subject: [PATCH] count_reachable + +--- + src/vendor/cigraph/interfaces/functions.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml +index da6f8b3c16..6b46816f1d 100644 +--- a/src/vendor/cigraph/interfaces/functions.yaml ++++ b/src/vendor/cigraph/interfaces/functions.yaml +@@ -1332,7 +1332,7 @@ igraph_is_biconnected: + PARAMS: GRAPH graph, OUT BOOLEAN res + + igraph_count_reachable: +- PARAMS: GRAPH graph, OUT VECTOR_INT counts, NEIMODE mode ++ PARAMS: GRAPH graph, OUT VECTOR_INT counts, NEIMODE mode=OUT + + ####################################### + # Percolation +-- +2.50.1 + diff --git a/tests/testthat/_snaps/aaa-auto.md b/tests/testthat/_snaps/aaa-auto.md new file mode 100644 index 00000000000..6866c3430cf --- /dev/null +++ b/tests/testthat/_snaps/aaa-auto.md @@ -0,0 +1,10092 @@ +# empty_impl basic + + Code + empty_impl() + Output + IGRAPH D--- 0 0 -- + + edges: + +--- + + Code + empty_impl(5, directed = FALSE) + Output + IGRAPH U--- 5 0 -- + + edges: + +# empty_impl errors + + Code + x + Condition + Error in `empty_impl()`: + ! At vendor/cigraph/src/graph/type_indexededgelist.c:xx : Number of vertices must not be negative. Invalid value + +# add_edges_impl basic + + Code + add_edges_impl(g, c(0, 1, 1, 2)) + Output + IGRAPH D--- 3 2 -- + + edges: + [1] 1->2 2->3 + +# add_edges_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# copy_impl basic + + Code + copy_impl(g) + Output + IGRAPH D--- 2 0 -- + + edges: + +# copy_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# delete_vertices_idx_impl basic + + Code + delete_vertices_idx_impl(g, 1) + Output + $graph + IGRAPH D--- 2 0 -- + + edges: + + $idx + [1] 0 1 2 + + $invidx + [1] 1 2 + + +# delete_vertices_idx_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# vcount_impl basic + + Code + vcount_impl(g) + Output + [1] 4 + +# vcount_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# degree_impl basic + + Code + degree_impl(g) + Output + [1] 0 0 0 + +--- + + Code + degree_impl(g, mode = "in") + Output + [1] 0 0 0 + +# degree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_all_eids_between_impl basic + + Code + get_all_eids_between_impl(g, 1, 2) + Output + + 0/0 edges: + +# get_all_eids_between_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# wheel_impl basic + + Code + wheel_impl(5) + Output + IGRAPH D--- 5 8 -- + + edges: + [1] 1->2 1->3 1->4 1->5 2->3 3->4 4->5 5->2 + +--- + + Code + wheel_impl(5, mode = "in", center = 2) + Output + IGRAPH D--- 5 8 -- + + edges: + [1] 1->3 2->3 4->3 5->3 1->2 2->4 4->5 5->1 + +# wheel_impl errors + + Code + x + Condition + Error in `wheel_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : Invalid number of vertices. Invalid vertex ID + +# hypercube_impl basic + + Code + hypercube_impl(3) + Output + IGRAPH U--- 8 12 -- + + edges: + [1] 1--2 1--3 1--5 2--4 2--6 3--4 3--7 4--8 5--6 5--7 6--8 7--8 + +--- + + Code + hypercube_impl(3, directed = TRUE) + Output + IGRAPH D--- 8 12 -- + + edges: + [1] 1->2 1->3 1->5 2->4 2->6 3->4 3->7 4->8 5->6 5->7 6->8 7->8 + +# hypercube_impl errors + + Code + x + Condition + Error in `hypercube_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : The requested hypercube graph dimension (10000) is too high. It must be no greater than 57. Invalid value + +# square_lattice_impl basic + + Code + square_lattice_impl(c(2, 2)) + Output + IGRAPH U--- 4 4 -- + + edges: + [1] 1--2 1--3 2--4 3--4 + +--- + + Code + square_lattice_impl(c(2, 2), nei = 2, directed = TRUE, mutual = TRUE, periodic = c( + TRUE, TRUE)) + Output + IGRAPH D--- 4 10 -- + + edges: + [1] 1->2 1->3 2->1 2->4 3->4 3->1 4->3 4->2 1->4 2->3 + +# square_lattice_impl errors + + Code + x + Condition + Error in `square_lattice_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : Invalid dimension vector. Invalid value + +# triangular_lattice_impl basic + + Code + triangular_lattice_impl(c(2, 2)) + Output + IGRAPH U--- 4 5 -- + + edges: + [1] 1--2 1--4 1--3 2--4 3--4 + +--- + + Code + triangular_lattice_impl(c(2, 2), directed = TRUE, mutual = TRUE) + Output + IGRAPH D--- 4 10 -- + + edges: + [1] 1->2 2->1 1->4 4->1 1->3 3->1 2->4 4->2 3->4 4->3 + +# triangular_lattice_impl errors + + Code + x + Condition + Error in `triangular_lattice_impl()`: + ! At vendor/cigraph/src/constructors/lattices.c:xx : Invalid dimension vector. Invalid value + +# path_graph_impl basic + + Code + path_graph_impl(5) + Output + IGRAPH U--- 5 4 -- + + edges: + [1] 1--2 2--3 3--4 4--5 + +--- + + Code + path_graph_impl(5, directed = TRUE, mutual = TRUE) + Output + IGRAPH D--- 5 8 -- + + edges: + [1] 1->2 2->1 2->3 3->2 3->4 4->3 4->5 5->4 + +# path_graph_impl errors + + Code + x + Condition + Error in `path_graph_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : The number of vertices must be non-negative, got -1. Invalid value + +# cycle_graph_impl basic + + Code + cycle_graph_impl(5) + Output + IGRAPH U--- 5 5 -- + + edges: + [1] 1--2 2--3 3--4 4--5 1--5 + +--- + + Code + cycle_graph_impl(5, directed = TRUE, mutual = TRUE) + Output + IGRAPH D--- 5 10 -- + + edges: + [1] 1->2 2->1 2->3 3->2 3->4 4->3 4->5 5->4 5->1 1->5 + +# cycle_graph_impl errors + + Code + x + Condition + Error in `cycle_graph_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : The number of vertices must be non-negative, got -1. Invalid value + +# symmetric_tree_impl basic + + Code + symmetric_tree_impl(3) + Output + IGRAPH D--- 4 3 -- + + edges: + [1] 1->2 1->3 1->4 + +--- + + Code + symmetric_tree_impl(3, type = "in") + Output + IGRAPH D--- 4 3 -- + + edges: + [1] 2->1 3->1 4->1 + +# symmetric_tree_impl errors + + Code + x + Condition + Error in `symmetric_tree_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : The number of branches must be positive at each level. Invalid value + +# regular_tree_impl basic + + Code + regular_tree_impl(2) + Output + IGRAPH U--- 10 9 -- + + edges: + [1] 1-- 2 1-- 3 1-- 4 2-- 5 2-- 6 3-- 7 3-- 8 4-- 9 4--10 + +--- + + Code + regular_tree_impl(2, k = 4, type = "in") + Output + IGRAPH D--- 17 16 -- + + edges: + [1] 2->1 3->1 4->1 5->1 6->2 7->2 8->2 9->3 10->3 11->3 12->4 13->4 + [13] 14->4 15->5 16->5 17->5 + +# regular_tree_impl errors + + Code + x + Condition + Error in `regular_tree_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : Height of regular tree must be positive, got -1. Invalid value + +# full_citation_impl basic + + Code + full_citation_impl(5) + Output + IGRAPH D--- 5 10 -- + + edges: + [1] 2->1 3->1 3->2 4->1 4->2 4->3 5->1 5->2 5->3 5->4 + +--- + + Code + full_citation_impl(5, directed = FALSE) + Output + IGRAPH U--- 5 10 -- + + edges: + [1] 1--2 1--3 2--3 1--4 2--4 3--4 1--5 2--5 3--5 4--5 + +# full_citation_impl errors + + Code + x + Condition + Error in `full_citation_impl()`: + ! At vendor/cigraph/src/constructors/full.c:xx : Invalid number of vertices. Invalid value + +# atlas_impl basic + + Code + atlas_impl(0) + Output + IGRAPH U--- 0 0 -- + + edges: + +--- + + Code + atlas_impl(5) + Output + IGRAPH U--- 3 1 -- + + edge: + [1] 2--3 + +# atlas_impl errors + + Code + x + Condition + Error in `atlas_impl()`: + ! At vendor/cigraph/src/constructors/atlas.c:xx : No such graph in atlas. The graph index must be less than 1253. Invalid value + +# extended_chordal_ring_impl basic + + Code + extended_chordal_ring_impl(5, matrix(c(1, 2))) + Output + IGRAPH U--- 5 15 -- + + edges: + [1] 1--2 2--3 3--4 4--5 1--5 1--2 1--3 2--3 2--4 3--4 3--5 4--5 1--4 1--5 2--5 + +--- + + Code + extended_chordal_ring_impl(5, matrix(c(1, 2)), directed = TRUE) + Output + IGRAPH D--- 5 15 -- + + edges: + [1] 1->2 2->3 3->4 4->5 5->1 1->2 1->3 2->3 2->4 3->4 3->5 4->5 4->1 5->1 5->2 + +# extended_chordal_ring_impl errors + + Code + x + Condition + Error in `extended_chordal_ring_impl()`: + ! At vendor/cigraph/src/constructors/regular.c:xx : An extended chordal ring has at least 3 nodes. Invalid value + +# graph_power_impl basic + + Code + graph_power_impl(g, 2) + Output + IGRAPH U--- 5 7 -- + + edges: + [1] 1--2 2--3 3--4 4--5 1--3 2--4 3--5 + +--- + + Code + graph_power_impl(g, 2, directed = TRUE) + Output + IGRAPH U--- 5 7 -- + + edges: + [1] 1--2 2--3 3--4 4--5 1--3 2--4 3--5 + +# graph_power_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# linegraph_impl basic + + Code + linegraph_impl(g) + Output + IGRAPH U--- 4 3 -- + + edges: + [1] 1--2 2--3 3--4 + +# linegraph_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# de_bruijn_impl basic + + Code + de_bruijn_impl(2, 3) + Output + IGRAPH D--- 8 16 -- + + edges: + [1] 1->1 1->2 2->3 2->4 3->5 3->6 4->7 4->8 5->1 5->2 6->3 6->4 7->5 7->6 8->7 + [16] 8->8 + +# de_bruijn_impl errors + + Code + x + Condition + Error in `de_bruijn_impl()`: + ! At vendor/cigraph/src/constructors/de_bruijn.c:xx : `m' and `n' should be non-negative in a de Bruijn graph, Invalid value + +# kautz_impl basic + + Code + kautz_impl(2, 3) + Output + IGRAPH D--- 24 48 -- + + edges: + [1] 1-> 9 1->10 2->11 2->12 3->13 3->14 4->15 4->16 5->17 5->18 + [11] 6->19 6->20 7->21 7->22 8->23 8->24 9-> 1 9-> 2 10-> 3 10-> 4 + [21] 11-> 5 11-> 6 12-> 7 12-> 8 13->17 13->18 14->19 14->20 15->21 15->22 + [31] 16->23 16->24 17-> 1 17-> 2 18-> 3 18-> 4 19-> 5 19-> 6 20-> 7 20-> 8 + [41] 21-> 9 21->10 22->11 22->12 23->13 23->14 24->15 24->16 + +# kautz_impl errors + + Code + x + Condition + Error in `kautz_impl()`: + ! At vendor/cigraph/src/constructors/kautz.c:xx : `m' and `n' should be non-negative in a Kautz graph, Invalid value + +# lcf_vector_impl basic + + Code + lcf_vector_impl(10, c(3, -3, 4), 2) + Output + IGRAPH U--- 10 16 -- LCF graph + + attr: name (g/c) + + edges: + [1] 1-- 2 1-- 4 1--10 2-- 3 2-- 5 2-- 9 3-- 4 3-- 7 4-- 5 4-- 7 5-- 6 6-- 7 + [13] 6--10 7-- 8 8-- 9 9--10 + +# lcf_vector_impl errors + + Code + x + Condition + Error in `lcf_vector_impl()`: + ! At vendor/cigraph/src/graph/type_indexededgelist.c:xx : Number of vertices must not be negative. Invalid value + +# mycielski_graph_impl basic + + Code + mycielski_graph_impl(3) + Output + IGRAPH U--- 5 5 -- + + edges: + [1] 1--2 1--4 2--3 3--5 4--5 + +# mycielski_graph_impl errors + + Code + x + Condition + Error in `mycielski_graph_impl()`: + ! At vendor/cigraph/src/constructors/mycielskian.c:xx : The Mycielski graph order must not be negative. Invalid value + +# adjlist_impl basic + + Code + adjlist_impl(list(c(2, 3), c(1), c(1)), mode = "out") + Output + IGRAPH D--- 3 4 -- + + edges: + [1] 1->2 1->3 2->1 3->1 + +# adjlist_impl errors + + Code + x + Condition + Error in `adjlist_impl()`: + ! At vendor/cigraph/src/constructors/basic_constructors.c:xx : Invalid (negative or too large) vertex ID. Invalid vertex ID + +# full_bipartite_impl basic + + Code + full_bipartite_impl(2, 3) + Output + $graph + IGRAPH U--- 5 6 -- + + edges: + [1] 1--3 1--4 1--5 2--3 2--4 2--5 + + $types + [1] FALSE FALSE TRUE TRUE TRUE + + +--- + + Code + full_bipartite_impl(2, 3, directed = TRUE, mode = "in") + Output + $graph + IGRAPH D--- 5 6 -- + + edges: + [1] 3->1 4->1 5->1 3->2 4->2 5->2 + + $types + [1] FALSE FALSE TRUE TRUE TRUE + + +# full_bipartite_impl errors + + Code + x + Condition + Error in `full_bipartite_impl()`: + ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite graph. Invalid value + +# full_multipartite_impl basic + + Code + full_multipartite_impl(c(2, 3, 4)) + Output + $graph + IGRAPH U--- 9 26 -- + + edges: + [1] 1--3 1--4 1--5 1--6 1--7 1--8 1--9 2--3 2--4 2--5 2--6 2--7 2--8 2--9 3--6 + [16] 3--7 3--8 3--9 4--6 4--7 4--8 4--9 5--6 5--7 5--8 5--9 + + $types + [1] 1 1 2 2 2 3 3 3 3 + + +--- + + Code + full_multipartite_impl(c(2, 3, 4), directed = TRUE, mode = "in") + Output + $graph + IGRAPH D--- 9 26 -- + + edges: + [1] 3->1 4->1 5->1 6->1 7->1 8->1 9->1 3->2 4->2 5->2 6->2 7->2 8->2 9->2 6->3 + [16] 7->3 8->3 9->3 6->4 7->4 8->4 9->4 6->5 7->5 8->5 9->5 + + $types + [1] 1 1 2 2 2 3 3 3 3 + + +# full_multipartite_impl errors + + Code + x + Condition + Error in `full_multipartite_impl()`: + ! At vendor/cigraph/src/constructors/full.c:xx : Number of vertices must not be negative in any partition. Invalid value + +# realize_degree_sequence_impl basic + + Code + realize_degree_sequence_impl(c(2, 2, 2)) + Output + IGRAPH U--- 3 3 -- Graph from degree sequence + + attr: name (g/c), out.deg (g/n), in.deg (g/x), allowed.edge.types + | (g/n), method (g/n) + + edges: + [1] 1--3 2--3 1--2 + +--- + + Code + realize_degree_sequence_impl(c(2, 2, 2), c(2, 2, 2), allowed.edge.types = "simple", + method = "largest") + Output + IGRAPH D--- 3 6 -- Graph from degree sequence + + attr: name (g/c), out.deg (g/n), in.deg (g/n), allowed.edge.types + | (g/n), method (g/n) + + edges: + [1] 1->2 1->3 2->1 2->3 3->1 3->2 + +# realize_degree_sequence_impl errors + + Code + x + Condition + Error in `realize_degree_sequence_impl()`: + ! At vendor/cigraph/src/misc/degree_sequence.cpp:xx : The sum of degrees must be even for an undirected graph. Invalid value + +# realize_bipartite_degree_sequence_impl basic + + Code + realize_bipartite_degree_sequence_impl(c(2, 2), c(2, 2)) + Output + IGRAPH U--- 4 4 -- Bipartite graph from degree sequence + + attr: name (g/c), degrees1 (g/n), degrees2 (g/n), allowed.edge.types + | (g/n), method (g/n) + + edges: + [1] 2--3 2--4 1--4 1--3 + +--- + + Code + realize_bipartite_degree_sequence_impl(c(2, 2), c(2, 2), allowed.edge.types = "loops", + method = "largest") + Output + IGRAPH U--- 4 4 -- Bipartite graph from degree sequence + + attr: name (g/c), degrees1 (g/n), degrees2 (g/n), allowed.edge.types + | (g/n), method (g/n) + + edges: + [1] 1--3 1--4 2--3 2--4 + +# realize_bipartite_degree_sequence_impl errors + + Code + x + Condition + Error in `realize_bipartite_degree_sequence_impl()`: + ! At vendor/cigraph/src/misc/degree_sequence.cpp:xx : The given bidegree sequence cannot be realized as a bipartite simple graph. Invalid value + +# circulant_impl basic + + Code + circulant_impl(5, c(1, 2)) + Output + IGRAPH U--- 5 10 -- + + edges: + [1] 1--2 2--3 3--4 4--5 1--5 1--3 2--4 3--5 1--4 2--5 + +--- + + Code + circulant_impl(5, c(1, 2), directed = TRUE) + Output + IGRAPH D--- 5 10 -- + + edges: + [1] 1->2 2->3 3->4 4->5 5->1 1->3 2->4 3->5 4->1 5->2 + +# circulant_impl errors + + Code + x + Condition + Error in `circulant_impl()`: + ! At vendor/cigraph/src/constructors/circulant.c:xx : Number of nodes = -1 must be non-negative. Invalid value + +# generalized_petersen_impl basic + + Code + generalized_petersen_impl(5, 2) + Output + IGRAPH U--- 10 15 -- + + edges: + [1] 1-- 2 1-- 6 6-- 8 2-- 3 2-- 7 7-- 9 3-- 4 3-- 8 8--10 4-- 5 4-- 9 6-- 9 + [13] 1-- 5 5--10 7--10 + +# generalized_petersen_impl errors + + Code + x + Condition + Error in `generalized_petersen_impl()`: + ! At vendor/cigraph/src/constructors/generalized_petersen.c:xx : n = -1 must be at least 3. Invalid value + +# turan_impl basic + + Code + turan_impl(5, 2) + Output + $graph + IGRAPH U--- 5 6 -- + + edges: + [1] 1--4 1--5 2--4 2--5 3--4 3--5 + + $types + [1] 1 1 1 2 2 + + +# turan_impl errors + + Code + x + Condition + Error in `turan_impl()`: + ! At vendor/cigraph/src/constructors/full.c:xx : Number of vertices must not be negative, got -1. Invalid value + +# erdos_renyi_game_gnp_impl basic + + Code + erdos_renyi_game_gnp_impl(5, 0.5) + Output + IGRAPH U--- 5 7 -- + + edges: + [1] 1--2 1--3 2--3 1--4 2--4 1--5 4--5 + +--- + + Code + erdos_renyi_game_gnp_impl(5, 0.5, directed = TRUE, loops = TRUE) + Output + IGRAPH D--- 5 12 -- + + edges: + [1] 2->1 3->1 4->1 2->2 1->3 2->3 4->3 1->4 2->4 5->4 3->5 4->5 + +# erdos_renyi_game_gnp_impl errors + + Code + x + Condition + Error in `erdos_renyi_game_gnp_impl()`: + ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices. Invalid value + +# erdos_renyi_game_gnm_impl basic + + Code + erdos_renyi_game_gnm_impl(5, 3) + Output + IGRAPH U--- 5 3 -- + + edges: + [1] 3--4 2--5 4--5 + +--- + + Code + erdos_renyi_game_gnm_impl(5, 3, directed = TRUE, loops = TRUE) + Output + IGRAPH D--- 5 3 -- + + edges: + [1] 4->3 5->3 3->5 + +# erdos_renyi_game_gnm_impl errors + + Code + x + Condition + Error in `erdos_renyi_game_gnm_impl()`: + ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices. Invalid value + +# growing_random_game_impl basic + + Code + growing_random_game_impl(5, 2) + Output + IGRAPH D--- 5 8 -- Growing random graph + + attr: name (g/c), m (g/n), citation (g/l) + + edges: + [1] 2->2 1->2 3->3 3->3 3->3 1->2 2->2 5->4 + +--- + + Code + growing_random_game_impl(5, 2, directed = FALSE, citation = TRUE) + Output + IGRAPH U--- 5 8 -- Growing random graph + + attr: name (g/c), m (g/n), citation (g/l) + + edges: + [1] 1--2 1--2 2--3 1--3 1--4 2--4 1--5 4--5 + +# growing_random_game_impl errors + + Code + x + Condition + Error in `growing_random_game_impl()`: + ! At vendor/cigraph/src/games/growing_random.c:xx : Invalid number of vertices. Invalid value + +# preference_game_impl basic + + Code + preference_game_impl(5, 2, c(0.5, 0.5), FALSE, matrix(c(0.5, 0.5, 0.5, 0.5), 2, + 2)) + Output + $graph + IGRAPH U--- 5 4 -- + + edges: + [1] 1--3 3--4 1--4 1--5 + + $node_type_vec + [1] 1 0 0 1 1 + + +# preference_game_impl errors + + Code + x + Condition + Error in `preference_game_impl()`: + ! At vendor/cigraph/src/games/preference.c:xx : The number of vertices must be non-negative. Invalid value + +# asymmetric_preference_game_impl basic + + Code + asymmetric_preference_game_impl(5, 2, 2, matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2), + matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2)) + Output + $graph + IGRAPH D--- 5 9 -- + + edges: + [1] 2->4 4->2 5->2 1->3 4->3 4->5 3->1 1->4 1->5 + + $node_type_out_vec + [1] 1 0 1 1 1 + + $node_type_in_vec + [1] 1 0 0 1 1 + + +# asymmetric_preference_game_impl errors + + Code + x + Condition + Error in `asymmetric_preference_game_impl()`: + ! At vendor/cigraph/src/games/preference.c:xx : The number of vertices must not be negative. Invalid value + +# rewire_edges_impl basic + + Code + rewire_edges_impl(g, 0.5) + Output + IGRAPH U--- 5 4 -- + + edges: + [1] 2--4 3--4 1--3 2--5 + +# rewire_edges_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# rewire_directed_edges_impl basic + + Code + rewire_directed_edges_impl(g, 0.5) + Output + IGRAPH D--- 5 4 -- + + edges: + [1] 1->4 2->3 3->2 4->5 + +# rewire_directed_edges_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# forest_fire_game_impl basic + + Code + forest_fire_game_impl(5, 0.5) + Output + IGRAPH D--- 5 9 -- Forest fire model + + attr: name (g/c), fw.prob (g/n), bw.factor (g/n), ambs (g/n) + + edges: + [1] 2->1 3->2 4->2 4->1 4->3 5->1 5->2 5->4 5->3 + +--- + + Code + forest_fire_game_impl(5, 0.5, bw.factor = 0.2, ambs = 2, directed = FALSE) + Output + IGRAPH U--- 5 4 -- Forest fire model + + attr: name (g/c), fw.prob (g/n), bw.factor (g/n), ambs (g/n) + + edges: + [1] 1--2 1--3 1--4 4--5 + +# forest_fire_game_impl errors + + Code + x + Condition + Error in `forest_fire_game_impl()`: + ! At vendor/cigraph/src/games/forestfire.c:xx : Insufficient memory for forest fire model. Out of memory + +# simple_interconnected_islands_game_impl basic + + Code + simple_interconnected_islands_game_impl(2, 3, 0.5, 1) + Output + IGRAPH U--- 6 5 -- Interconnected islands model + + attr: name (g/c), islands.n (g/n), islands.size (g/n), islands.pin + | (g/n), n.inter (g/n) + + edges: + [1] 1--2 1--3 2--3 3--6 5--6 + +# simple_interconnected_islands_game_impl errors + + Code + x + Condition + Error in `simple_interconnected_islands_game_impl()`: + ! At vendor/cigraph/src/games/islands.c:xx : Number of islands cannot be negative, got -1. Invalid value + +# chung_lu_game_impl basic + + Code + chung_lu_game_impl(c(2, 2, 2)) + Output + IGRAPH U--- 3 5 -- Chung-Lu model + + attr: name (g/c), variant (g/n) + + edges: + [1] 1--2 1--3 2--2 2--3 3--3 + +--- + + Code + chung_lu_game_impl(c(1, 2, 3), c(1, 2, 3), loops = FALSE, variant = "maxent") + Output + IGRAPH D--- 3 1 -- Chung-Lu model + + attr: name (g/c), variant (g/n) + + edge: + [1] 3->1 + +# chung_lu_game_impl errors + + Code + x + Condition + Error in `chung_lu_game_impl()`: + ! At vendor/cigraph/src/games/chung_lu.c:xx : Vertex weights must not be negative in Chung-Lu model, got -1. Invalid value + +# static_fitness_game_impl basic + + Code + static_fitness_game_impl(3, c(1, 2, 3)) + Output + IGRAPH U--- 3 3 -- Static fitness model + + attr: name (g/c), loops (g/l), multiple (g/l) + + edges: + [1] 1--2 1--3 2--3 + +--- + + Code + static_fitness_game_impl(3, c(1, 2, 3), c(1, 2, 3), loops = TRUE, multiple = TRUE) + Output + IGRAPH D--- 3 3 -- Static fitness model + + attr: name (g/c), loops (g/l), multiple (g/l) + + edges: + [1] 1->2 2->3 1->3 + +# static_fitness_game_impl errors + + Code + x + Condition + Error in `static_fitness_game_impl()`: + ! At vendor/cigraph/src/games/static_fitness.c:xx : Number of edges cannot be negative, got -1. Invalid value + +# static_power_law_game_impl basic + + Code + static_power_law_game_impl(5, 4, 2.5) + Output + IGRAPH U--- 5 4 -- Static power law model + + attr: name (g/c), exponent.out (g/n), exponent.in (g/n), loops (g/l), + | multiple (g/l), finite.size.correction (g/l) + + edges: + [1] 1--5 2--4 3--5 4--5 + +--- + + Code + static_power_law_game_impl(5, 4, 2.5, exponent.in = 2, loops = TRUE, multiple = TRUE, + finite.size.correction = FALSE) + Output + IGRAPH D--- 5 4 -- Static power law model + + attr: name (g/c), exponent.out (g/n), exponent.in (g/n), loops (g/l), + | multiple (g/l), finite.size.correction (g/l) + + edges: + [1] 1->1 3->5 1->4 5->1 + +# static_power_law_game_impl errors + + Code + x + Condition + Error in `static_power_law_game_impl()`: + ! At vendor/cigraph/src/games/static_fitness.c:xx : Number of nodes cannot be negative, got -1. Invalid value + +# k_regular_game_impl basic + + Code + k_regular_game_impl(5, 2) + Output + IGRAPH U--- 5 5 -- k-regular graph + + attr: name (g/c), k (g/n) + + edges: + [1] 1--3 1--5 2--3 2--4 4--5 + +--- + + Code + k_regular_game_impl(5, 2, directed = TRUE, multiple = TRUE) + Output + IGRAPH D--- 5 10 -- k-regular graph + + attr: name (g/c), k (g/n) + + edges: + [1] 3->4 3->3 2->1 5->5 1->5 4->3 5->2 4->1 1->2 2->4 + +# k_regular_game_impl errors + + Code + x + Condition + Error in `k_regular_game_impl()`: + ! At vendor/cigraph/src/games/k_regular.c:xx : Number of nodes must be non-negative. Invalid value + +# sbm_game_impl basic + + Code + sbm_game_impl(5, matrix(0.5, 2, 2), c(2, 3)) + Output + IGRAPH U--- 5 6 -- Stochastic block model + + attr: name (g/c), loops (g/l) + + edges: + [1] 1--2 1--3 2--3 1--4 1--5 3--5 + +--- + + Code + sbm_game_impl(5, matrix(0.5, 2, 2), c(2, 3), directed = TRUE, loops = TRUE) + Output + IGRAPH D--- 5 14 -- Stochastic block model + + attr: name (g/c), loops (g/l) + + edges: + [1] 1->1 2->1 2->4 1->5 4->1 5->1 5->2 3->3 5->3 3->4 4->4 5->4 3->5 5->5 + +# sbm_game_impl errors + + Code + x + Condition + Error in `sbm_game_impl()`: + ! At vendor/cigraph/src/games/sbm.c:xx : Sum of the block sizes (5) must equal the number of vertices (-1). Invalid value + +# hsbm_game_impl basic + + Code + hsbm_game_impl(6, 2, c(0.5, 0.5), matrix(1, 2, 2), 0.5) + Output + IGRAPH U--- 6 9 -- Hierarchical stochastic block model + + attr: name (g/c), m (g/n), rho (g/n), C (g/n), p (g/n) + + edges: + [1] 1--2 3--4 5--6 1--4 1--5 2--5 1--6 4--5 3--6 + +# hsbm_game_impl errors + + Code + x + Condition + Error in `hsbm_game_impl()`: + ! At vendor/cigraph/src/games/sbm.c:xx : `n' must be positive for HSBM, Invalid value + +# hsbm_list_game_impl basic + + Code + hsbm_list_game_impl(100, list(50, 50), rho = list(c(3, 3, 4) / 10), C = list(C), + p = 1 / 20) + Output + IGRAPH U--- 100 783 -- Hierarchical stochastic block model + + attr: name (g/c), p (g/n) + + edges: + [1] 1-- 2 1-- 3 2-- 3 1-- 4 2-- 4 3-- 4 1-- 5 2-- 5 3-- 5 4-- 5 + [11] 1-- 6 2-- 6 3-- 6 4-- 6 5-- 6 1-- 7 2-- 7 3-- 7 4-- 7 5-- 7 + [21] 6-- 7 1-- 8 2-- 8 3-- 8 4-- 8 5-- 8 6-- 8 7-- 8 1-- 9 2-- 9 + [31] 3-- 9 4-- 9 5-- 9 6-- 9 7-- 9 8-- 9 1--10 2--10 3--10 4--10 + [41] 5--10 6--10 7--10 8--10 9--10 1--11 2--11 3--11 4--11 5--11 + [51] 6--11 7--11 8--11 9--11 10--11 1--12 2--12 3--12 4--12 5--12 + [61] 6--12 7--12 8--12 9--12 10--12 11--12 1--13 2--13 3--13 4--13 + [71] 5--13 6--13 7--13 8--13 9--13 10--13 11--13 12--13 1--14 2--14 + + ... omitted several edges + +# hsbm_list_game_impl errors + + Code + x + Condition + Error in `hsbm_list_game_impl()`: + ! At vendor/cigraph/src/games/sbm.c:xx : `n' must be positive for HSBM. Invalid value + +# correlated_game_impl basic + + Code + correlated_game_impl(g, 0.5) + Output + IGRAPH U--- 5 3 -- Correlated random graph + + attr: name (g/c), corr (g/n), p (g/n) + + edges: + [1] 1--3 3--4 2--5 + +# correlated_game_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# correlated_pair_game_impl basic + + Code + correlated_pair_game_impl(5, 0.5, 0.5) + Output + $graph1 + IGRAPH U--- 5 7 -- + + edges: + [1] 1--2 1--3 2--3 1--4 2--4 1--5 4--5 + + $graph2 + IGRAPH U--- 5 7 -- + + edges: + [1] 1--2 1--3 2--3 1--4 2--4 1--5 3--5 + + +--- + + Code + correlated_pair_game_impl(5, 0.5, 0.5, directed = TRUE) + Output + $graph1 + IGRAPH D--- 5 10 -- + + edges: + [1] 4->1 5->1 2->5 4->2 5->2 3->5 1->4 2->4 4->5 5->4 + + $graph2 + IGRAPH D--- 5 9 -- + + edges: + [1] 1->5 2->1 2->5 4->2 4->3 1->4 2->4 4->5 5->4 + + +# correlated_pair_game_impl errors + + Code + x + Condition + Error in `correlated_pair_game_impl()`: + ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices. Invalid value + +# dot_product_game_impl basic + + Code + dot_product_game_impl(matrix(0.5, 5, 2)) + Condition + Warning in `dot_product_game_impl()`: + At vendor/cigraph/src/games/dotproduct.c:90 : Greater than 1 connection probability in dot-product graph. + Output + IGRAPH U--- 2 1 -- + + edge: + [1] 1--2 + +--- + + Code + dot_product_game_impl(matrix(0.5, 5, 2), directed = TRUE) + Condition + Warning in `dot_product_game_impl()`: + At vendor/cigraph/src/games/dotproduct.c:90 : Greater than 1 connection probability in dot-product graph. + Output + IGRAPH D--- 2 2 -- + + edges: + [1] 1->2 2->1 + +# dot_product_game_impl errors + + Code + x + Condition + Error in `dot_product_game_impl()`: + ! REAL() can only be applied to a 'numeric', not a 'NULL' + +# sample_sphere_surface_impl basic + + Code + sample_sphere_surface_impl(3, 5) + Output + [,1] [,2] [,3] [,4] [,5] + [1,] 0.87877523 0.8206548 0.1430028 0.6349227 0.99933629 + [2,] 0.05165973 0.5261159 0.1145481 0.2979741 0.02649327 + [3,] 0.47443162 0.2229974 0.9830712 0.7128005 0.02500179 + +--- + + Code + sample_sphere_surface_impl(3, 5, radius = 2, positive = FALSE) + Output + [,1] [,2] [,3] [,4] [,5] + [1,] -0.4904253 -1.4825368 -0.5141332 1.95644246 0.369407 + [2,] -1.6787252 1.1329528 -0.7872709 -0.41498660 1.953509 + [3,] -0.9702395 0.7200713 1.7651832 -0.01090904 0.217584 + +# sample_sphere_surface_impl errors + + Code + x + Condition + Error in `sample_sphere_surface_impl()`: + ! At vendor/cigraph/src/games/dotproduct.c:xx : Sphere must be at least two dimensional to sample from surface. Invalid value + +# sample_sphere_volume_impl basic + + Code + sample_sphere_volume_impl(3, 5) + Output + [,1] [,2] [,3] [,4] [,5] + [1,] 0.67165090 0.6105364 0.09806950 0.4132698 0.73325518 + [2,] 0.03948371 0.3914105 0.07855561 0.1939507 0.01943923 + [3,] 0.36260970 0.1659017 0.67417787 0.4639603 0.01834487 + +--- + + Code + sample_sphere_volume_impl(3, 5, radius = 2, positive = FALSE) + Output + [,1] [,2] [,3] [,4] [,5] + [1,] 1.903629152 -1.3795904 -1.2061886 0.9035986 -1.1692436 + [2,] -0.159619927 0.2402815 -0.1258477 0.1842403 -1.4940836 + [3,] 0.003829883 1.2440192 0.6204597 1.5776103 0.4096058 + +# sample_sphere_volume_impl errors + + Code + x + Condition + Error in `sample_sphere_volume_impl()`: + ! At vendor/cigraph/src/games/dotproduct.c:xx : Sphere must be at least two dimensional to sample from surface. Invalid value + +# sample_dirichlet_impl basic + + Code + sample_dirichlet_impl(5, c(1, 1, 1)) + Output + [,1] [,2] [,3] [,4] [,5] + [1,] 0.6298008 0.4168413 0.29594281 0.2432340 0.1516815 + [2,] 0.1093984 0.3461600 0.08924333 0.4251328 0.3561426 + [3,] 0.2608008 0.2369988 0.61481386 0.3316331 0.4921759 + +# sample_dirichlet_impl errors + + Code + x + Condition + Error in `sample_dirichlet_impl()`: + ! At vendor/cigraph/src/games/dotproduct.c:xx : Number of samples should be non-negative, got -1. Invalid value + +# are_adjacent_impl basic + + Code + are_adjacent_impl(g, 1, 2) + Output + [1] TRUE + +# are_adjacent_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# closeness_impl basic + + Code + closeness_impl(g) + Output + $res + [1] 0.3333333 0.5000000 0.3333333 + + $reachable_count + [1] 2 2 2 + + $all_reachable + [1] TRUE + + +--- + + Code + closeness_impl(g, mode = "in", normalized = TRUE) + Output + $res + [1] 0.6666667 1.0000000 0.6666667 + + $reachable_count + [1] 2 2 2 + + $all_reachable + [1] TRUE + + +# closeness_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# closeness_cutoff_impl basic + + Code + closeness_cutoff_impl(g, cutoff = 2) + Output + $res + [1] 0.3333333 0.5000000 0.3333333 + + $reachable_count + [1] 2 2 2 + + $all_reachable + [1] TRUE + + +--- + + Code + closeness_cutoff_impl(g, mode = "in", normalized = TRUE, cutoff = 1) + Output + $res + [1] 1 1 1 + + $reachable_count + [1] 1 2 1 + + $all_reachable + [1] FALSE + + +# closeness_cutoff_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_shortest_path_impl basic + + Code + get_shortest_path_impl(g, 1, 3) + Output + $vertices + + 3/3 vertices: + [1] 1 2 3 + + $edges + + 2/2 edges: + [1] 1--2 2--3 + + +# get_shortest_path_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_shortest_path_bellman_ford_impl basic + + Code + get_shortest_path_bellman_ford_impl(g, 1, 3) + Output + $vertices + + 3/3 vertices: + [1] 1 2 3 + + $edges + + 2/2 edges: + [1] 1--2 2--3 + + +# get_shortest_path_bellman_ford_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_shortest_path_dijkstra_impl basic + + Code + get_shortest_path_dijkstra_impl(g, 1, 3) + Output + $vertices + + 3/3 vertices: + [1] 1 2 3 + + $edges + + 2/2 edges: + [1] 1--2 2--3 + + +# get_shortest_path_dijkstra_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_all_shortest_paths_impl basic + + Code + get_all_shortest_paths_impl(g, 1, 3) + Output + $vpaths + $vpaths[[1]] + + 3/3 vertices: + [1] 1 2 3 + + + $epaths + $epaths[[1]] + + 2/2 edges: + [1] 1--2 2--3 + + + $nrgeo + [1] 1 1 1 + + +# get_all_shortest_paths_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_all_shortest_paths_dijkstra_impl basic + + Code + get_all_shortest_paths_dijkstra_impl(g, 1, 3) + Output + $vpaths + $vpaths[[1]] + + 3/3 vertices: + [1] 1 2 3 + + + $epaths + $epaths[[1]] + + 2/2 edges: + [1] 1--2 2--3 + + + $nrgeo + [1] 1 1 1 + + +# get_all_shortest_paths_dijkstra_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# voronoi_impl basic + + Code + voronoi_impl(g, 1) + Output + $membership + [1] 0 0 0 + + $distances + [1] 0 1 2 + + +--- + + Code + voronoi_impl(g, 1, mode = "in", tiebreaker = "first") + Output + $membership + [1] 0 0 0 + + $distances + [1] 0 1 2 + + +# voronoi_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_all_simple_paths_impl basic + + Code + get_all_simple_paths_impl(g, 1, 3) + Output + + 3/3 vertices: + [1] 1 2 3 + +# get_all_simple_paths_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_k_shortest_paths_impl basic + + Code + get_k_shortest_paths_impl(g, 1, 3, k = 2) + Output + $vpaths + $vpaths[[1]] + + 3/3 vertices: + [1] 1 2 3 + + + $epaths + $epaths[[1]] + + 2/2 edges: + [1] 1--2 2--3 + + + +# get_k_shortest_paths_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_widest_path_impl basic + + Code + get_widest_path_impl(g, 1, 3, weights = c(1, 2)) + Output + $vertices + + 3/3 vertices: + [1] 1 2 3 + + $edges + + 2/2 edges: + [1] 1--2 2--3 + + +# get_widest_path_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_widest_paths_impl basic + + Code + get_widest_paths_impl(g, 1, 3, weights = c(1, 2)) + Output + $vertices + $vertices[[1]] + + 3/3 vertices: + [1] 1 2 3 + + + $edges + $edges[[1]] + + 2/2 edges: + [1] 1--2 2--3 + + + $parents + [1] -1 0 1 + + $inbound_edges + [1] -1 0 1 + + +# get_widest_paths_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# spanner_impl basic + + Code + spanner_impl(g, 2) + Output + + 2/2 edges: + [1] 1--2 2--3 + +# spanner_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# betweenness_cutoff_impl basic + + Code + betweenness_cutoff_impl(g, cutoff = 2) + Output + [1] 0 1 0 + +# betweenness_cutoff_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# betweenness_subset_impl basic + + Code + betweenness_subset_impl(g) + Output + [1] 0 1 0 + +# betweenness_subset_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# edge_betweenness_impl basic + + Code + edge_betweenness_impl(g) + Output + [1] 2 2 + +# edge_betweenness_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# edge_betweenness_cutoff_impl basic + + Code + edge_betweenness_cutoff_impl(g, cutoff = 2) + Output + [1] 2 2 + +# edge_betweenness_cutoff_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# edge_betweenness_subset_impl basic + + Code + edge_betweenness_subset_impl(g) + Output + [1] 2 2 + +# edge_betweenness_subset_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# harmonic_centrality_cutoff_impl basic + + Code + harmonic_centrality_cutoff_impl(g, cutoff = 2) + Output + [1] 1.5 2.0 1.5 + +# harmonic_centrality_cutoff_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# personalized_pagerank_impl basic + + Code + personalized_pagerank_impl(g) + Output + $vector + [1] 0.2567568 0.4864865 0.2567568 + + $value + [1] 1 + + $options + NULL + + +--- + + Code + personalized_pagerank_impl(g, algo = "arpack", damping = 0.9) + Output + $vector + [1] 0.2543860 0.4912281 0.2543860 + + $value + [1] 1 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LR" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 3 + + + +# personalized_pagerank_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# personalized_pagerank_vs_impl basic + + Code + personalized_pagerank_vs_impl(g, reset.vids = 1) + Output + [1] 0.3452703 0.4594595 0.1952703 + +--- + + Code + personalized_pagerank_vs_impl(g, algo = "arpack", reset.vids = 1, details = TRUE) + Output + $vector + [1] 0.3452703 0.4594595 0.1952703 + + $value + [1] 1 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LR" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 3 + + + +# personalized_pagerank_vs_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# induced_subgraph_impl basic + + Code + induced_subgraph_impl(g, 1:2) + Output + IGRAPH U--- 2 1 -- + + edge: + [1] 1--2 + +# induced_subgraph_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# subgraph_from_edges_impl basic + + Code + subgraph_from_edges_impl(g, 1) + Output + IGRAPH U--- 2 1 -- + + edge: + [1] 1--2 + +# subgraph_from_edges_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# reverse_edges_impl basic + + Code + reverse_edges_impl(g) + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + +# reverse_edges_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# path_length_hist_impl basic + + Code + path_length_hist_impl(g) + Output + $res + [1] 2 1 + + $unconnected + [1] 0 + + +--- + + Code + path_length_hist_impl(g, directed = FALSE) + Output + $res + [1] 2 1 + + $unconnected + [1] 0 + + +# path_length_hist_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# simplify_impl basic + + Code + simplify_impl(g) + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + +--- + + Code + simplify_impl(g, remove.multiple = FALSE, remove.loops = FALSE) + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + +# simplify_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# transitivity_undirected_impl basic + + Code + transitivity_undirected_impl(g) + Output + [1] 0 + +--- + + Code + transitivity_undirected_impl(g, mode = "zero") + Output + [1] 0 + +# transitivity_undirected_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# transitivity_local_undirected_impl basic + + Code + transitivity_local_undirected_impl(g) + Output + [1] NaN 0 NaN + +--- + + Code + transitivity_local_undirected_impl(g, mode = "zero") + Output + [1] 0 0 0 + +# transitivity_local_undirected_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# transitivity_avglocal_undirected_impl basic + + Code + transitivity_avglocal_undirected_impl(g) + Output + [1] 0 + +--- + + Code + transitivity_avglocal_undirected_impl(g, mode = "zero") + Output + [1] 0 + +# transitivity_avglocal_undirected_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# transitivity_barrat_impl basic + + Code + transitivity_barrat_impl(g) + Condition + Warning in `transitivity_barrat_impl()`: + At vendor/cigraph/src/properties/triangles.c:913 : No weights given for Barrat's transitivity, unweighted version is used. + Output + [1] NaN 0 NaN + +--- + + Code + transitivity_barrat_impl(g, mode = "zero") + Condition + Warning in `transitivity_barrat_impl()`: + At vendor/cigraph/src/properties/triangles.c:913 : No weights given for Barrat's transitivity, unweighted version is used. + Output + [1] 0 0 0 + +# transitivity_barrat_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# ecc_impl basic + + Code + ecc_impl(g) + Output + [1] NaN 0 NaN + +--- + + Code + ecc_impl(g, k = 3, offset = TRUE, normalize = FALSE) + Output + [1] 1 1 1 + +# ecc_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# reciprocity_impl basic + + Code + reciprocity_impl(g) + Output + [1] 1 + +--- + + Code + reciprocity_impl(g, ignore.loops = FALSE, mode = "ratio") + Output + [1] 1 + +# reciprocity_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# maxdegree_impl basic + + Code + maxdegree_impl(g) + Output + [1] 2 + +--- + + Code + maxdegree_impl(g, mode = "in", loops = FALSE) + Output + [1] 2 + +# maxdegree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# density_impl basic + + Code + density_impl(g) + Output + [1] 0.6666667 + +--- + + Code + density_impl(g, loops = TRUE) + Output + [1] 0.3333333 + +# density_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# mean_degree_impl basic + + Code + mean_degree_impl(g) + Output + [1] 1.333333 + +--- + + Code + mean_degree_impl(g, loops = FALSE) + Output + [1] 1.333333 + +# mean_degree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# feedback_arc_set_impl basic + + Code + feedback_arc_set_impl(g) + Output + + 0/2 edges: + +--- + + Code + feedback_arc_set_impl(g, algo = "exact_ip") + Output + + 0/2 edges: + +# feedback_arc_set_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# feedback_vertex_set_impl basic + + Code + feedback_vertex_set_impl(g) + Output + + 0/3 vertices: + +# feedback_vertex_set_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_loop_impl basic + + Code + is_loop_impl(g) + Output + [1] FALSE FALSE + +# is_loop_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_dag_impl basic + + Code + is_dag_impl(g) + Output + [1] FALSE + +# is_dag_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_acyclic_impl basic + + Code + is_acyclic_impl(g) + Output + [1] TRUE + +# is_acyclic_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_simple_impl basic + + Code + is_simple_impl(g) + Output + [1] TRUE + +# is_simple_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_multiple_impl basic + + Code + is_multiple_impl(g) + Output + [1] FALSE FALSE + +# is_multiple_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# has_loop_impl basic + + Code + has_loop_impl(g) + Output + [1] FALSE + +# has_loop_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# has_multiple_impl basic + + Code + has_multiple_impl(g) + Output + [1] FALSE + +# has_multiple_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_loops_impl basic + + Code + count_loops_impl(g) + Output + [1] 0 + +# count_loops_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_multiple_impl basic + + Code + count_multiple_impl(g) + Output + [1] 1 1 + +# count_multiple_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_perfect_impl basic + + Code + is_perfect_impl(g) + Output + [1] TRUE + +# is_perfect_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# eigenvector_centrality_impl basic + + Code + eigenvector_centrality_impl(g) + Output + $vector + [1] 0.7071068 1.0000000 0.7071068 + + $value + [1] 1.414214 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LA" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 3 + + + +--- + + Code + eigenvector_centrality_impl(g, directed = TRUE, scale = FALSE) + Output + $vector + [1] 0.5000000 0.7071068 0.5000000 + + $value + [1] 1.414214 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LA" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 3 + + + +# eigenvector_centrality_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# hub_and_authority_scores_impl basic + + Code + hub_and_authority_scores_impl(g) + Output + $hub + [1] 1 1 1 1 1 + + $authority + [1] 1 1 1 1 1 + + $value + [1] 16 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 5 + + $options$which + [1] "LA" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 4 + + $options$numopb + [1] 0 + + $options$numreo + [1] 4 + + + +--- + + Code + hub_and_authority_scores_impl(g, scale = FALSE) + Output + $hub + [1] 0.4472136 0.4472136 0.4472136 0.4472136 0.4472136 + + $authority + [1] 0.4472136 0.4472136 0.4472136 0.4472136 0.4472136 + + $value + [1] 16 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 5 + + $options$which + [1] "LA" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 4 + + $options$numopb + [1] 0 + + $options$numreo + [1] 4 + + + +# hub_and_authority_scores_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# unfold_tree_impl basic + + Code + unfold_tree_impl(g, roots = 1) + Output + $tree + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + + $vertex_index + [1] 1 2 3 + + +--- + + Code + unfold_tree_impl(g, mode = "in", roots = 1) + Output + $tree + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + + $vertex_index + [1] 1 2 3 + + +# unfold_tree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_mutual_impl basic + + Code + is_mutual_impl(g) + Output + [1] TRUE TRUE + +--- + + Code + is_mutual_impl(g, loops = FALSE) + Output + [1] TRUE TRUE + +# is_mutual_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# has_mutual_impl basic + + Code + has_mutual_impl(g) + Output + [1] TRUE + +--- + + Code + has_mutual_impl(g, loops = FALSE) + Output + [1] TRUE + +# has_mutual_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# maximum_cardinality_search_impl basic + + Code + maximum_cardinality_search_impl(g) + Output + $alpha + [1] 3 2 1 + + $alpham1 + + 3/3 vertices: + [1] 3 2 1 + + +# maximum_cardinality_search_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# avg_nearest_neighbor_degree_impl basic + + Code + avg_nearest_neighbor_degree_impl(g) + Output + $knn + [1] 2 1 2 + + $knnk + [1] 2 1 + + +--- + + Code + avg_nearest_neighbor_degree_impl(g, mode = "in", neighbor.degree.mode = "out") + Output + $knn + [1] 2 1 2 + + $knnk + [1] 2 1 + + +# avg_nearest_neighbor_degree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# degree_correlation_vector_impl basic + + Code + degree_correlation_vector_impl(g) + Output + [1] NaN 2 1 + +--- + + Code + degree_correlation_vector_impl(g, from.mode = "in", to.mode = "out", + directed.neighbors = FALSE) + Output + [1] NaN 2 1 + +# degree_correlation_vector_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# rich_club_sequence_impl basic + + Code + rich_club_sequence_impl(g, vertex.order = 1:3) + Output + [1] 0.6666667 1.0000000 NaN + +--- + + Code + rich_club_sequence_impl(g, vertex.order = 1:3, normalized = FALSE, loops = TRUE, + directed = FALSE) + Output + [1] 2 1 0 + +# rich_club_sequence_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# strength_impl basic + + Code + strength_impl(g) + Output + [1] 1 2 1 + +--- + + Code + strength_impl(g, mode = "in", loops = FALSE) + Output + [1] 1 2 1 + +# strength_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# centralization_impl basic + + Code + centralization_impl(c(1, 2, 3)) + Output + [1] Inf + +--- + + Code + centralization_impl(c(1, 2, 3), theoretical.max = 2, normalized = FALSE) + Output + [1] 3 + +# centralization_impl errors + + Code + x + Condition + Error in `centralization_impl()`: + ! 'list' object cannot be coerced to type 'double' + +# centralization_degree_impl basic + + Code + centralization_degree_impl(g) + Output + $res + [1] 1 2 1 + + $centralization + [1] 0.3333333 + + $theoretical_max + [1] 6 + + +--- + + Code + centralization_degree_impl(g, mode = "in", loops = FALSE, normalized = FALSE) + Output + $res + [1] 1 2 1 + + $centralization + [1] 2 + + $theoretical_max + [1] 2 + + +# centralization_degree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# centralization_degree_tmax_impl basic + + Code + centralization_degree_tmax_impl(nodes = 3, loops = TRUE) + Output + [1] 6 + +--- + + Code + centralization_degree_tmax_impl(nodes = 3, mode = "in", loops = FALSE) + Output + [1] 4 + +# centralization_degree_tmax_impl errors + + Code + x + Condition + Error in `centralization_degree_tmax_impl()`: + ! At vendor/cigraph/src/centrality/centralization.c:xx : Number of vertices must not be negative. Invalid value + +# centralization_betweenness_impl basic + + Code + centralization_betweenness_impl(g) + Output + $res + [1] 0 1 0 + + $centralization + [1] 1 + + $theoretical_max + [1] 2 + + +--- + + Code + centralization_betweenness_impl(g, directed = FALSE, normalized = FALSE) + Output + $res + [1] 0 1 0 + + $centralization + [1] 2 + + $theoretical_max + [1] 2 + + +# centralization_betweenness_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# centralization_betweenness_tmax_impl basic + + Code + centralization_betweenness_tmax_impl(nodes = 3, directed = TRUE) + Output + [1] 4 + +--- + + Code + centralization_betweenness_tmax_impl(nodes = 3, directed = FALSE) + Output + [1] 2 + +# centralization_betweenness_tmax_impl errors + + Code + x + Condition + Error in `centralization_betweenness_tmax_impl()`: + ! At vendor/cigraph/src/centrality/centralization.c:xx : Number of vertices must not be negative. Invalid value + +# centralization_closeness_impl basic + + Code + centralization_closeness_impl(g) + Output + $res + [1] 0.6666667 1.0000000 0.6666667 + + $centralization + [1] 1 + + $theoretical_max + [1] 0.6666667 + + +--- + + Code + centralization_closeness_impl(g, mode = "in", normalized = FALSE) + Output + $res + [1] 0.6666667 1.0000000 0.6666667 + + $centralization + [1] 0.6666667 + + $theoretical_max + [1] 0.6666667 + + +# centralization_closeness_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# centralization_closeness_tmax_impl basic + + Code + centralization_closeness_tmax_impl(nodes = 3) + Output + [1] 1.333333 + +--- + + Code + centralization_closeness_tmax_impl(nodes = 3, mode = "in") + Output + [1] 1.333333 + +# centralization_closeness_tmax_impl errors + + Code + x + Condition + Error in `centralization_closeness_tmax_impl()`: + ! At vendor/cigraph/src/centrality/centralization.c:xx : Number of vertices must not be negative. Invalid value + +# centralization_eigenvector_centrality_impl basic + + Code + centralization_eigenvector_centrality_impl(g) + Output + $vector + [1] 0.7071068 1.0000000 0.7071068 + + $value + [1] 1.414214 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LA" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 3 + + + $centralization + [1] 0.5857864 + + $theoretical_max + [1] 1 + + +--- + + Code + centralization_eigenvector_centrality_impl(g, directed = TRUE, normalized = FALSE) + Output + $vector + [1] 0.7071068 1.0000000 0.7071068 + + $value + [1] 1.414214 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LA" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 0 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 1 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 3 + + + $centralization + [1] 0.5857864 + + $theoretical_max + [1] 1 + + +# centralization_eigenvector_centrality_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# centralization_eigenvector_centrality_tmax_impl basic + + Code + centralization_eigenvector_centrality_tmax_impl(nodes = 3) + Output + [1] 1 + +--- + + Code + centralization_eigenvector_centrality_tmax_impl(nodes = 3, directed = TRUE) + Output + [1] 2 + +# centralization_eigenvector_centrality_tmax_impl errors + + Code + x + Condition + Error in `centralization_eigenvector_centrality_tmax_impl()`: + ! At vendor/cigraph/src/centrality/centralization.c:xx : Number of vertices must not be negative. Invalid value + +# assortativity_nominal_impl basic + + Code + assortativity_nominal_impl(g, c(1, 2, 1)) + Output + [1] -1 + +--- + + Code + assortativity_nominal_impl(g, c(1, 2, 1), directed = FALSE, normalized = FALSE) + Output + [1] -0.5 + +# assortativity_nominal_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# assortativity_impl basic + + Code + assortativity_impl(g, c(1, 2, 1)) + Output + [1] -1 + +--- + + Code + assortativity_impl(g, c(1, 2, 1), directed = FALSE, normalized = FALSE) + Output + [1] -0.25 + +# assortativity_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# assortativity_degree_impl basic + + Code + assortativity_degree_impl(g) + Output + [1] -1 + +--- + + Code + assortativity_degree_impl(g, directed = FALSE) + Output + [1] -1 + +# assortativity_degree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# joint_degree_matrix_impl basic + + Code + joint_degree_matrix_impl(g) + Output + [,1] [,2] + [1,] 0 2 + [2,] 2 0 + +--- + + Code + joint_degree_matrix_impl(g, max.out.degree = 2, max.in.degree = 2) + Output + [,1] [,2] + [1,] 0 2 + [2,] 2 0 + +# joint_degree_matrix_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# joint_degree_distribution_impl basic + + Code + joint_degree_distribution_impl(g) + Output + [,1] [,2] [,3] + [1,] 0 0.0 0.0 + [2,] 0 0.0 0.5 + [3,] 0 0.5 0.0 + +--- + + Code + joint_degree_distribution_impl(g, from.mode = "in", to.mode = "out", + directed.neighbors = FALSE, normalized = FALSE, max.from.degree = 2, + max.to.degree = 2) + Output + [,1] [,2] [,3] + [1,] 0 0 0 + [2,] 0 0 2 + [3,] 0 2 0 + +# joint_degree_distribution_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# joint_type_distribution_impl basic + + Code + joint_type_distribution_impl(g, from.types = c(1, 2, 1)) + Output + [,1] [,2] + [1,] 0.0 0.5 + [2,] 0.5 0.0 + +--- + + Code + joint_type_distribution_impl(g, from.types = c(1, 2, 1), to.types = c(1, 2, 1), + directed = FALSE, normalized = FALSE) + Output + [,1] [,2] + [1,] 0 2 + [2,] 2 0 + +# joint_type_distribution_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# contract_vertices_impl basic + + Code + contract_vertices_impl(g, c(1, 1, 2)) + Output + IGRAPH U--- 2 2 -- + + edges: + [1] 1--1 1--2 + +# contract_vertices_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# eccentricity_dijkstra_impl basic + + Code + eccentricity_dijkstra_impl(g) + Output + [1] 2 1 2 + +--- + + Code + eccentricity_dijkstra_impl(g, mode = "in") + Output + [1] 2 1 2 + +# eccentricity_dijkstra_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# graph_center_dijkstra_impl basic + + Code + graph_center_dijkstra_impl(g) + Output + + 1/3 vertex: + [1] 2 + +--- + + Code + graph_center_dijkstra_impl(g, mode = "in") + Output + + 1/3 vertex: + [1] 2 + +# graph_center_dijkstra_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# radius_dijkstra_impl basic + + Code + radius_dijkstra_impl(g) + Output + [1] 1 + +--- + + Code + radius_dijkstra_impl(g, mode = "in") + Output + [1] 1 + +# radius_dijkstra_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# pseudo_diameter_impl basic + + Code + pseudo_diameter_impl(g, 1) + Output + $diameter + [1] 2 + + $from + [1] 0 + + $to + [1] 2 + + +--- + + Code + pseudo_diameter_impl(g, 1, directed = FALSE, unconnected = FALSE) + Output + $diameter + [1] 2 + + $from + [1] 0 + + $to + [1] 2 + + +# pseudo_diameter_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# pseudo_diameter_dijkstra_impl basic + + Code + pseudo_diameter_dijkstra_impl(g, start.vid = 1) + Output + $diameter + [1] 2 + + $from + [1] 0 + + $to + [1] 2 + + +--- + + Code + pseudo_diameter_dijkstra_impl(g, start.vid = 1, directed = FALSE, unconnected = FALSE) + Output + $diameter + [1] 2 + + $from + [1] 0 + + $to + [1] 2 + + +# pseudo_diameter_dijkstra_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# diversity_impl basic + + Code + diversity_impl(g) + Output + [1] 0.0000000 0.9182958 0.0000000 + +# diversity_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# random_walk_impl basic + + Code + random_walk_impl(g, 1, 2) + Output + $vertices + + 3/3 vertices: + [1] 1 2 3 + + $edges + + 2/2 edges: + [1] 1--2 2--3 + + +--- + + Code + random_walk_impl(g, 1, 2, mode = "in", stuck = "error") + Output + $vertices + + 3/3 vertices: + [1] 1 2 1 + + $edges + + 2/2 edges: + [1] 1--2 1--2 + + +# random_walk_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# global_efficiency_impl basic + + Code + global_efficiency_impl(g) + Output + [1] 0.8333333 + +--- + + Code + global_efficiency_impl(g, directed = FALSE) + Output + [1] 0.8333333 + +# global_efficiency_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_efficiency_impl basic + + Code + local_efficiency_impl(g) + Output + [1] 0 0 0 + +--- + + Code + local_efficiency_impl(g, directed = FALSE, mode = "in") + Output + [1] 0 0 0 + +# local_efficiency_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# average_local_efficiency_impl basic + + Code + average_local_efficiency_impl(g) + Output + [1] 0 + +--- + + Code + average_local_efficiency_impl(g, directed = FALSE, mode = "in") + Output + [1] 0 + +# average_local_efficiency_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# transitive_closure_dag_impl basic + + Code + transitive_closure_dag_impl(g) + Output + IGRAPH D--- 3 3 -- + + edges: + [1] 1->3 1->2 2->3 + +# transitive_closure_dag_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# transitive_closure_impl basic + + Code + transitive_closure_impl(g) + Output + IGRAPH U--- 3 3 -- + + edges: + [1] 1--2 1--3 2--3 + +# transitive_closure_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# trussness_impl basic + + Code + trussness_impl(g) + Output + [1] 2 2 + +# trussness_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_graphical_impl basic + + Code + is_graphical_impl(c(2, 2, 2)) + Output + [1] TRUE + +--- + + Code + is_graphical_impl(c(2, 2, 2), c(1, 1, 1), allowed.edge.types = "all") + Output + [1] FALSE + +# is_graphical_impl errors + + Code + x + Condition + Warning in `is_graphical_impl()`: + NAs introduced by coercion + Error in `is_graphical_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# bfs_simple_impl basic + + Code + bfs_simple_impl(g, 1) + Output + $order + + 3/3 vertices: + [1] 1 2 3 + + $layers + [1] 0 1 2 3 + + $parents + [1] -1 0 1 + + +--- + + Code + bfs_simple_impl(g, 1, mode = "in") + Output + $order + + 3/3 vertices: + [1] 1 2 3 + + $layers + [1] 0 1 2 3 + + $parents + [1] -1 0 1 + + +# bfs_simple_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# bipartite_projection_size_impl basic + + Code + bipartite_projection_size_impl(g) + Output + $vcount1 + [1] 2 + + $ecount1 + [1] 1 + + $vcount2 + [1] 2 + + $ecount2 + [1] 1 + + +# bipartite_projection_size_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# biadjacency_impl basic + + Code + biadjacency_impl(m) + Output + $graph + IGRAPH U--- 5 4 -- + + edges: + [1] 1--3 1--4 1--5 2--5 + + $types + [1] FALSE FALSE TRUE TRUE TRUE + + +--- + + Code + biadjacency_impl(m, directed = TRUE, mode = "in", multiple = TRUE) + Output + $graph + IGRAPH D--- 5 4 -- + + edges: + [1] 3->1 4->1 5->1 5->2 + + $types + [1] FALSE FALSE TRUE TRUE TRUE + + +# biadjacency_impl errors + + Code + x + Condition + Warning in `biadjacency_impl()`: + NAs introduced by coercion + Error in `biadjacency_impl()`: + ! REAL() can only be applied to a 'numeric', not a 'character' + +# get_biadjacency_impl basic + + Code + get_biadjacency_impl(g, c(TRUE, FALSE, TRUE)) + Output + $res + [,1] [,2] + [1,] 1 1 + + $row_ids + [1] 2 + + $col_ids + [1] 1 3 + + +# get_biadjacency_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_bipartite_impl basic + + Code + is_bipartite_impl(g) + Output + $res + [1] TRUE + + $type + [1] FALSE TRUE FALSE + + +# is_bipartite_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# bipartite_game_gnp_impl basic + + Code + bipartite_game_gnp_impl(2, 2, 0.5) + Output + $graph + IGRAPH U--- 4 4 -- + + edges: + [1] 1--3 2--3 1--4 2--4 + + $types + [1] FALSE FALSE TRUE TRUE + + +--- + + Code + bipartite_game_gnp_impl(2, 2, 0.5, directed = TRUE, mode = "in") + Output + $graph + IGRAPH D--- 4 1 -- + + edge: + [1] 3->2 + + $types + [1] FALSE FALSE TRUE TRUE + + +# bipartite_game_gnp_impl errors + + Code + x + Condition + Error in `bipartite_game_gnp_impl()`: + ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite graph. Invalid value + +# bipartite_game_gnm_impl basic + + Code + bipartite_game_gnm_impl(2, 2, 1) + Output + $graph + IGRAPH U--- 4 1 -- + + edge: + [1] 2--4 + + $types + [1] FALSE FALSE TRUE TRUE + + +--- + + Code + bipartite_game_gnm_impl(2, 2, 1, directed = TRUE, mode = "in") + Output + $graph + IGRAPH D--- 4 1 -- + + edge: + [1] 3->1 + + $types + [1] FALSE FALSE TRUE TRUE + + +# bipartite_game_gnm_impl errors + + Code + x + Condition + Error in `bipartite_game_gnm_impl()`: + ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite graph. Invalid value + +# get_laplacian_impl basic + + Code + get_laplacian_impl(g) + Output + [,1] [,2] [,3] + [1,] 1 -1 0 + [2,] -1 2 -1 + [3,] 0 -1 1 + +--- + + Code + get_laplacian_impl(g, mode = "in", normalization = "symmetric", weights = c(1, + 2)) + Output + [,1] [,2] [,3] + [1,] 1.0000000 -0.5773503 0.0000000 + [2,] -0.5773503 1.0000000 -0.8164966 + [3,] 0.0000000 -0.8164966 1.0000000 + +# get_laplacian_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_laplacian_sparse_impl basic + + Code + get_laplacian_sparse_impl(g) + Output + $type + [1] "triplet" + + $dim + [1] 3 3 + + $p + [1] 0 1 2 0 1 1 2 + + $i + [1] 0 1 2 1 0 2 1 + + $x + [1] 1 2 1 -1 -1 -1 -1 + + attr(,"class") + [1] "igraph.tmp.sparse" + +--- + + Code + get_laplacian_sparse_impl(g, mode = "in", normalization = "symmetric", weights = c( + 1, 2)) + Output + $type + [1] "triplet" + + $dim + [1] 3 3 + + $p + [1] 0 1 2 0 1 1 2 + + $i + [1] 0 1 2 1 0 2 1 + + $x + [1] 1.0000000 1.0000000 1.0000000 -0.5773503 -0.5773503 -0.8164966 -0.8164966 + + attr(,"class") + [1] "igraph.tmp.sparse" + +# get_laplacian_sparse_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# connected_components_impl basic + + Code + connected_components_impl(g) + Output + [1] 0 0 0 + +--- + + Code + connected_components_impl(g, mode = "strong", details = TRUE) + Output + $membership + [1] 0 0 0 + + $csize + [1] 3 + + $no + [1] 1 + + +# connected_components_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_connected_impl basic + + Code + is_connected_impl(g) + Output + [1] TRUE + +--- + + Code + is_connected_impl(g, mode = "strong") + Output + [1] TRUE + +# is_connected_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# articulation_points_impl basic + + Code + articulation_points_impl(g) + Output + + 1/3 vertex: + [1] 2 + +# articulation_points_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# biconnected_components_impl basic + + Code + biconnected_components_impl(g) + Output + $no + [1] 2 + + $tree_edges + $tree_edges[[1]] + [1] 2 + + $tree_edges[[2]] + [1] 1 + + + $component_edges + $component_edges[[1]] + [1] 2 + + $component_edges[[2]] + [1] 1 + + + $components + $components[[1]] + + 2/3 vertices: + [1] 3 2 + + $components[[2]] + + 2/3 vertices: + [1] 2 1 + + + $articulation_points + [1] 2 + + $tree.edges + list() + + $component.edges + list() + + $articulation.points + + 0/3 vertices: + + +# biconnected_components_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# bridges_impl basic + + Code + bridges_impl(g) + Output + + 2/2 edges: + [1] 2--3 1--2 + +# bridges_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_biconnected_impl basic + + Code + is_biconnected_impl(g) + Output + [1] FALSE + +# is_biconnected_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_reachable_impl basic + + Code + count_reachable_impl(g, mode = "out") + Output + [1] 5 5 5 5 5 + +--- + + Code + count_reachable_impl(g, mode = "in") + Output + [1] 5 5 5 5 5 + +# count_reachable_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# bond_percolation_impl basic + + Code + bond_percolation_impl(g) + Output + $giant_size + numeric(0) + + $vetex_count + numeric(0) + + +# bond_percolation_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# site_percolation_impl basic + + Code + site_percolation_impl(g) + Output + $giant_size + numeric(0) + + $edge_count + numeric(0) + + +# site_percolation_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# edgelist_percolation_impl basic + + Code + edgelist_percolation_impl(matrix(c(1, 2, 2, 3), ncol = 2)) + Output + $giant_size + [1] 2 3 + + $vertex_count + [1] 2 3 + + +# edgelist_percolation_impl errors + + Code + x + Condition + Error in `edgelist_percolation_impl()`: + ! REAL() can only be applied to a 'numeric', not a 'character' + +# is_clique_impl basic + + Code + is_clique_impl(g, 1:2) + Output + [1] TRUE + +--- + + Code + is_clique_impl(g, 1:2, directed = TRUE) + Output + [1] TRUE + +# is_clique_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# cliques_impl basic + + Code + cliques_impl(g) + Output + [[1]] + + 1/3 vertex: + [1] 2 + + [[2]] + + 1/3 vertex: + [1] 3 + + [[3]] + + 2/3 vertices: + [1] 2 3 + + [[4]] + + 1/3 vertex: + [1] 1 + + [[5]] + + 2/3 vertices: + [1] 1 2 + + +--- + + Code + cliques_impl(g, min = 2, max = 2) + Output + [[1]] + + 2/3 vertices: + [1] 2 3 + + [[2]] + + 2/3 vertices: + [1] 1 2 + + +# cliques_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# clique_size_hist_impl basic + + Code + clique_size_hist_impl(g) + Output + [1] 3 2 + +--- + + Code + clique_size_hist_impl(g, min.size = 2, max.size = 2) + Output + [1] 0 2 + +# clique_size_hist_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# largest_cliques_impl basic + + Code + largest_cliques_impl(g) + Output + [[1]] + + 2/3 vertices: + [1] 1 2 + + [[2]] + + 2/3 vertices: + [1] 2 3 + + +# largest_cliques_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# maximal_cliques_hist_impl basic + + Code + maximal_cliques_hist_impl(g) + Output + [1] 0 2 + +--- + + Code + maximal_cliques_hist_impl(g, min.size = 2, max.size = 2) + Output + [1] 0 2 + +# maximal_cliques_hist_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# clique_number_impl basic + + Code + clique_number_impl(g) + Output + [1] 2 + +# clique_number_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# weighted_cliques_impl basic + + Code + weighted_cliques_impl(g) + Output + [[1]] + + 1/3 vertex: + [1] 2 + + [[2]] + + 1/3 vertex: + [1] 3 + + [[3]] + + 2/3 vertices: + [1] 2 3 + + [[4]] + + 1/3 vertex: + [1] 1 + + [[5]] + + 2/3 vertices: + [1] 1 2 + + +--- + + Code + weighted_cliques_impl(g, vertex.weights = c(1, 2, 3), min.weight = 1, + max.weight = 3, maximal = TRUE) + Output + [[1]] + + 2/3 vertices: + [1] 1 2 + + +# weighted_cliques_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# largest_weighted_cliques_impl basic + + Code + largest_weighted_cliques_impl(g) + Output + [[1]] + + 2/3 vertices: + [1] 1 2 + + [[2]] + + 2/3 vertices: + [1] 2 3 + + +--- + + Code + largest_weighted_cliques_impl(g, vertex.weights = c(1, 2, 3)) + Output + [[1]] + + 2/3 vertices: + [1] 2 3 + + +# largest_weighted_cliques_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# weighted_clique_number_impl basic + + Code + weighted_clique_number_impl(g) + Output + [1] 2 + +--- + + Code + weighted_clique_number_impl(g, vertex.weights = c(1, 2, 3)) + Output + [1] 5 + +# weighted_clique_number_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_independent_vertex_set_impl basic + + Code + is_independent_vertex_set_impl(g, 1:2) + Output + [1] FALSE + +# is_independent_vertex_set_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_random_impl basic + + Code + layout_random_impl(g) + Output + [,1] [,2] + [1,] 0.91714717 0.7003783 + [2,] -0.84358557 0.6509057 + [3,] -0.08120892 -0.8259847 + +# layout_random_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_circle_impl basic + + Code + layout_circle_impl(g) + Output + [,1] [,2] + [1,] 1.0 0.0000000 + [2,] -0.5 0.8660254 + [3,] -0.5 -0.8660254 + +--- + + Code + layout_circle_impl(g, order = 1:3) + Output + [,1] [,2] + [1,] 1.0 0.0000000 + [2,] -0.5 0.8660254 + [3,] -0.5 -0.8660254 + +# layout_circle_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_star_impl basic + + Code + layout_star_impl(g) + Output + [,1] [,2] + [1,] 0 0.000000e+00 + [2,] 1 0.000000e+00 + [3,] -1 1.224647e-16 + +--- + + Code + layout_star_impl(g, center = 1, order = 1:3) + Output + [,1] [,2] + [1,] 0 0.000000e+00 + [2,] 1 0.000000e+00 + [3,] -1 1.224647e-16 + +# layout_star_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_grid_impl basic + + Code + layout_grid_impl(g) + Output + [,1] [,2] + [1,] 0 0 + [2,] 1 0 + [3,] 0 1 + +--- + + Code + layout_grid_impl(g, width = 2) + Output + [,1] [,2] + [1,] 0 0 + [2,] 1 0 + [3,] 0 1 + +# layout_grid_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_grid_3d_impl basic + + Code + layout_grid_3d_impl(g) + Output + [,1] [,2] [,3] + [1,] 0 0 0 + [2,] 1 0 0 + [3,] 0 1 0 + +--- + + Code + layout_grid_3d_impl(g, width = 2, height = 2) + Output + [,1] [,2] [,3] + [1,] 0 0 0 + [2,] 1 0 0 + [3,] 0 1 0 + +# layout_grid_3d_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# roots_for_tree_layout_impl basic + + Code + roots_for_tree_layout_impl(g, mode = "out", heuristic = 1) + Output + + 1/3 vertex: + [1] 2 + +# roots_for_tree_layout_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_random_3d_impl basic + + Code + layout_random_3d_impl(g) + Output + [,1] [,2] [,3] + [1,] 0.91714717 0.7003783 0.7338074 + [2,] -0.84358557 0.6509057 0.4644714 + [3,] -0.08120892 -0.8259847 0.5240391 + +# layout_random_3d_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_sphere_impl basic + + Code + layout_sphere_impl(g) + Output + [,1] [,2] [,3] + [1,] 0.0000000 0.0000000 -1 + [2,] -0.4861377 0.8738822 0 + [3,] 0.0000000 0.0000000 1 + +# layout_sphere_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_sugiyama_impl basic + + Code + layout_sugiyama_impl(g) + Output + $res + [,1] [,2] + [1,] 0.0 1 + [2,] 0.5 0 + [3,] 1.0 1 + + $extd_graph + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + + $extd_to_orig_eids + [1] 1 2 + + +--- + + Code + layout_sugiyama_impl(g, layers = 1:3, hgap = 2, vgap = 2, maxiter = 10, + weights = c(1, 2)) + Output + $res + [,1] [,2] + [1,] 0 0 + [2,] 0 2 + [3,] 0 4 + + $extd_graph + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + + $extd_to_orig_eids + [1] 1 2 + + +# layout_sugiyama_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_mds_impl basic + + Code + layout_mds_impl(g) + Output + [,1] [,2] + [1,] 1 2.807594e-08 + [2,] 0 0.000000e+00 + [3,] -1 2.807594e-08 + +--- + + Code + layout_mds_impl(g, dist = matrix(1:9, nrow = 3), dim = 3) + Output + [,1] [,2] [,3] + [1,] -2.907521 2.32638426 1.444979 + [2,] -3.900013 -1.63291106 2.258035 + [3,] 3.975674 0.09951448 3.271816 + +# layout_mds_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_bipartite_impl basic + + Code + layout_bipartite_impl(g, types = c(TRUE, FALSE, TRUE)) + Output + [,1] [,2] + [1,] 0.0 0 + [2,] 0.5 1 + [3,] 1.0 0 + +--- + + Code + layout_bipartite_impl(g, types = c(TRUE, FALSE, TRUE), hgap = 2, vgap = 2, + maxiter = 10) + Output + [,1] [,2] + [1,] 0 0 + [2,] 1 2 + [3,] 2 0 + +# layout_bipartite_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_gem_impl basic + + Code + layout_gem_impl(g, res = matrix(0, nrow = 3, ncol = 2)) + Output + [,1] [,2] + [1,] 200.18284 -69.23950 + [2,] 86.00346 64.12806 + [3,] 66.22930 -92.94294 + +--- + + Code + layout_gem_impl(g, res = matrix(0, nrow = 3, ncol = 2), use.seed = TRUE, + maxiter = 10, temp.max = 2, temp.min = 0.1, temp.init = 1) + Output + [,1] [,2] + [1,] 1.0114521 -0.1206363 + [2,] -0.2178589 2.9621162 + [3,] -0.7089555 -3.8896500 + +# layout_gem_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_davidson_harel_impl basic + + Code + layout_davidson_harel_impl(g, res = matrix(0, nrow = 3, ncol = 2)) + Output + [,1] [,2] + [1,] 1.152116 0.9424808 + [2,] 2.474361 2.5195497 + [3,] 3.849187 4.0402661 + +--- + + Code + layout_davidson_harel_impl(g, res = matrix(0, nrow = 3, ncol = 2), use.seed = TRUE, + maxiter = 10, fineiter = 5, cool.fact = 0.5, weight.node.dist = 2, + weight.border = 1, weight.edge.lengths = 0.1, weight.edge.crossings = 0.2, + weight.node.edge.dist = 0.3) + Output + [,1] [,2] + [1,] -6.609493 -2.155221 + [2,] -8.660255 -3.797365 + [3,] -6.485087 -5.224752 + +# layout_davidson_harel_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_umap_impl basic + + Code + layout_umap_impl(g, res = matrix(0, nrow = 3, ncol = 2), use.seed = TRUE) + Output + [,1] [,2] + [1,] 0 0 + [2,] 0 0 + [3,] 0 0 + +--- + + Code + layout_umap_impl(g, res = matrix(0, nrow = 3, ncol = 2), use.seed = TRUE, + distances = 1:3, min.dist = 0.1, epochs = 10, distances.are.weights = TRUE) + Output + [,1] [,2] + [1,] 0 0 + [2,] 0 0 + [3,] 0 0 + +# layout_umap_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_umap_3d_impl basic + + Code + layout_umap_3d_impl(g, res = matrix(0, nrow = 3, ncol = 3), use.see = TRUE) + Output + [,1] [,2] [,3] + [1,] 0 0 0 + [2,] 0 0 0 + [3,] 0 0 0 + +--- + + Code + layout_umap_3d_impl(g, res = matrix(0, nrow = 3, ncol = 3), use.seed = TRUE, + distances = 1:3, min.dist = 0.1, epochs = 10, distances.are.weights = TRUE) + Output + [,1] [,2] [,3] + [1,] 0 0 0 + [2,] 0 0 0 + [3,] 0 0 0 + +# layout_umap_3d_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_umap_compute_weights_impl basic + + Code + layout_umap_compute_weights_impl(g, distances = 1:2, weights = 1:3) + Output + [1] 1 1 + +# layout_umap_compute_weights_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# layout_align_impl basic + + Code + layout_align_impl(g, layout = matrix(0, nrow = 3, ncol = 2)) + Output + [,1] [,2] + [1,] 0 0 + [2,] 0 0 + [3,] 0 0 + +# layout_align_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# similarity_dice_impl basic + + Code + similarity_dice_impl(g) + Output + [,1] [,2] [,3] + [1,] 1 0 1 + [2,] 0 1 0 + [3,] 1 0 1 + +--- + + Code + similarity_dice_impl(g, vids = 1:2, mode = "in", loops = TRUE) + Output + [,1] [,2] + [1,] 1.0 0.8 + [2,] 0.8 1.0 + +# similarity_dice_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# similarity_dice_es_impl basic + + Code + similarity_dice_es_impl(g) + Output + [1] 0 0 + +--- + + Code + similarity_dice_es_impl(g, es = 1:2, mode = "in", loops = TRUE) + Output + [1] 0.8 0.8 + +# similarity_dice_es_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# similarity_dice_pairs_impl basic + + Code + similarity_dice_pairs_impl(g, pairs = matrix(c(1, 2, 2, 3), ncol = 2)) + Output + [1] 0 0 + +--- + + Code + similarity_dice_pairs_impl(g, pairs = matrix(c(1, 2, 2, 3), ncol = 2), mode = "in", + loops = TRUE) + Output + [1] 0.6666667 0.8000000 + +# similarity_dice_pairs_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# similarity_inverse_log_weighted_impl basic + + Code + similarity_inverse_log_weighted_impl(g) + Output + [,1] [,2] [,3] + [1,] 0.000000 0 1.442695 + [2,] 0.000000 0 0.000000 + [3,] 1.442695 0 0.000000 + +--- + + Code + similarity_inverse_log_weighted_impl(g, vids = 1:2, mode = "in") + Output + [,1] [,2] [,3] + [1,] 0 0 1.442695 + [2,] 0 0 0.000000 + +# similarity_inverse_log_weighted_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# similarity_jaccard_impl basic + + Code + similarity_jaccard_impl(g) + Output + [,1] [,2] [,3] + [1,] 1 0 1 + [2,] 0 1 0 + [3,] 1 0 1 + +--- + + Code + similarity_jaccard_impl(g, vids = 1:2, mode = "in", loops = TRUE) + Output + [,1] [,2] + [1,] 1.0000000 0.6666667 + [2,] 0.6666667 1.0000000 + +# similarity_jaccard_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# similarity_jaccard_es_impl basic + + Code + similarity_jaccard_es_impl(g) + Output + [1] 0 0 + +--- + + Code + similarity_jaccard_es_impl(g, es = 1:2, mode = "in", loops = TRUE) + Output + [1] 0.6666667 0.6666667 + +# similarity_jaccard_es_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# similarity_jaccard_pairs_impl basic + + Code + similarity_jaccard_pairs_impl(g, pairs = matrix(c(1, 2, 2, 3), ncol = 2)) + Output + [1] 0 0 + +--- + + Code + similarity_jaccard_pairs_impl(g, pairs = matrix(c(1, 2, 2, 3), ncol = 2), mode = "in", + loops = TRUE) + Output + [1] 0.5000000 0.6666667 + +# similarity_jaccard_pairs_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# compare_communities_impl basic + + Code + compare_communities_impl(c(1, 2, 1), c(2, 1, 2)) + Output + [1] 0 + +--- + + Code + compare_communities_impl(c(1, 2, 1), c(2, 1, 2), method = "nmi") + Output + [1] 1 + +# compare_communities_impl errors + + Code + x + Condition + Warning in `compare_communities_impl()`: + NAs introduced by coercion + Error in `compare_communities_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# modularity_impl basic + + Code + modularity_impl(g, membership = c(1, 2, 1)) + Output + [1] -0.5 + +--- + + Code + modularity_impl(g, membership = c(1, 2, 1), weights = c(1, 2), resolution = 0.5, + directed = FALSE) + Output + [1] -0.25 + +# modularity_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# modularity_matrix_impl basic + + Code + modularity_matrix_impl(g) + Output + [,1] [,2] [,3] + [1,] -0.25 0.5 -0.25 + [2,] 0.50 -1.0 0.50 + [3,] -0.25 0.5 -0.25 + +--- + + Code + modularity_matrix_impl(g, weights = c(1, 2), resolution = 0.5, directed = FALSE) + Output + [,1] [,2] [,3] + [1,] -0.08333333 0.75 -0.1666667 + [2,] 0.75000000 -0.75 1.5000000 + [3,] -0.16666667 1.50 -0.3333333 + +# modularity_matrix_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# community_fluid_communities_impl basic + + Code + community_fluid_communities_impl(g, no.of.communities = 2) + Output + [1] 1 0 0 + +# community_fluid_communities_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# community_label_propagation_impl basic + + Code + community_label_propagation_impl(g) + Output + [1] 0 0 0 + +--- + + Code + community_label_propagation_impl(g, mode = "in", weights = c(1, 2), initial = 1: + 3, fixed = c(TRUE, FALSE, TRUE)) + Output + [1] 0 1 1 + +# community_label_propagation_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# community_multilevel_impl basic + + Code + community_multilevel_impl(g) + Output + $membership + [1] 0 0 0 + + $memberships + [,1] [,2] [,3] + [1,] 0 0 0 + + $modularity + [1] 0 + + +--- + + Code + community_multilevel_impl(g, weights = c(1, 2), resolution = 0.5) + Output + $membership + [1] 0 0 0 + + $memberships + [,1] [,2] [,3] + [1,] 0 0 0 + + $modularity + [1] 0.5 + + +# community_multilevel_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# community_optimal_modularity_impl basic + + Code + community_optimal_modularity_impl(g) + Output + $modularity + [1] 0 + + $membership + [1] 0 0 0 + + +--- + + Code + community_optimal_modularity_impl(g, weights = c(1, 2)) + Output + $modularity + [1] 1.850372e-17 + + $membership + [1] 0 0 0 + + +# community_optimal_modularity_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# community_leiden_impl basic + + Code + community_leiden_impl(g, weights = c(1, 2), vertex.weights = c(1, 2, 3), + resolution = 0.5, beta = 0.1, start = TRUE, n.iterations = 1, membership = 1:3) + Output + $membership + [1] 0 1 2 + + $nb_clusters + [1] 3 + + $quality + [1] -1.166667 + + +# community_leiden_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# split_join_distance_impl basic + + Code + split_join_distance_impl(c(1, 2, 1), c(2, 1, 2)) + Output + $distance12 + [1] 0 + + $distance21 + [1] 0 + + +# split_join_distance_impl errors + + Code + x + Condition + Warning in `split_join_distance_impl()`: + NAs introduced by coercion + Error in `split_join_distance_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# community_infomap_impl basic + + Code + community_infomap_impl(g) + Output + $membership + [1] 0 0 0 + + $codelength + [1] 1.512987 + + +--- + + Code + community_infomap_impl(g, e.weights = c(1, 2), v.weights = c(1, 2, 3), + nb.trials = 2) + Output + $membership + [1] 0 0 0 + + $codelength + [1] 1.462254 + + +# community_infomap_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# graphlets_impl basic + + Code + graphlets_impl(g) + Output + $cliques + $cliques[[1]] + + 2/3 vertices: + [1] 2 3 + + $cliques[[2]] + + 2/3 vertices: + [1] 1 2 + + + $Mu + [1] 0.6665667 0.3332333 + + +--- + + Code + graphlets_impl(g, weights = c(3, 4), niter = 10) + Output + $cliques + $cliques[[1]] + + 2/3 vertices: + [1] 2 3 + + $cliques[[2]] + + 2/3 vertices: + [1] 1 2 + + + $Mu + [1] 1.333233 0.999900 + + +# graphlets_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# hrg_fit_impl basic + + Code + hrg_fit_impl(g1) + Output + $left + [1] -2 0 + + $right + [1] 1 2 + + $prob + [1] 1 0 + + $edges + [1] 2 0 + + $vertices + [1] 3 2 + + +# hrg_fit_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# hrg_sample_impl basic + + Code + hrg_sample_impl(hrg_model) + Output + IGRAPH U--- 10 45 -- + + edges: + [1] 1-- 2 1-- 3 1-- 4 1-- 5 1-- 6 1-- 7 1-- 8 1-- 9 1--10 2-- 3 2-- 4 2-- 5 + [13] 2-- 6 2-- 7 2-- 8 2-- 9 2--10 3-- 4 3-- 5 3-- 6 3-- 7 3-- 8 3-- 9 3--10 + [25] 4-- 5 4-- 6 4-- 7 4-- 8 4-- 9 4--10 5-- 6 5-- 7 5-- 8 5-- 9 5--10 6-- 7 + [37] 6-- 8 6-- 9 6--10 7-- 8 7-- 9 7--10 8-- 9 8--10 9--10 + +# hrg_sample_impl errors + + Code + x + Condition + Error in `hrg_sample_impl()`: + ! At vendor/cigraph/src/hrg/hrg_types.cc:xx : Assertion failed: n >= 0. This is an unexpected igraph error; please report this as a bug, along with the steps to reproduce it. + Please restart your R session to avoid crashes or other surprising behavior. + +# hrg_sample_many_impl basic + + Code + hrg_sample_many_impl(hrg_model, num.samples = 2) + Output + [[1]] + IGRAPH U--- 10 45 -- + + edges: + [1] 1-- 2 1-- 3 1-- 4 1-- 5 1-- 6 1-- 7 1-- 8 1-- 9 1--10 2-- 3 2-- 4 2-- 5 + [13] 2-- 6 2-- 7 2-- 8 2-- 9 2--10 3-- 4 3-- 5 3-- 6 3-- 7 3-- 8 3-- 9 3--10 + [25] 4-- 5 4-- 6 4-- 7 4-- 8 4-- 9 4--10 5-- 6 5-- 7 5-- 8 5-- 9 5--10 6-- 7 + [37] 6-- 8 6-- 9 6--10 7-- 8 7-- 9 7--10 8-- 9 8--10 9--10 + + [[2]] + IGRAPH U--- 10 45 -- + + edges: + [1] 1-- 2 1-- 3 1-- 4 1-- 5 1-- 6 1-- 7 1-- 8 1-- 9 1--10 2-- 3 2-- 4 2-- 5 + [13] 2-- 6 2-- 7 2-- 8 2-- 9 2--10 3-- 4 3-- 5 3-- 6 3-- 7 3-- 8 3-- 9 3--10 + [25] 4-- 5 4-- 6 4-- 7 4-- 8 4-- 9 4--10 5-- 6 5-- 7 5-- 8 5-- 9 5--10 6-- 7 + [37] 6-- 8 6-- 9 6--10 7-- 8 7-- 9 7--10 8-- 9 8--10 9--10 + + +# hrg_sample_many_impl errors + + Code + x + Condition + Error in `hrg_sample_many_impl()`: + ! At vendor/cigraph/src/hrg/hrg_types.cc:xx : Assertion failed: n >= 0. This is an unexpected igraph error; please report this as a bug, along with the steps to reproduce it. + Please restart your R session to avoid crashes or other surprising behavior. + +# hrg_game_impl basic + + Code + hrg_game_impl(hrg_model) + Output + IGRAPH U--- 10 45 -- Hierarchical random graph model + + attr: name (g/c) + + edges: + [1] 1-- 2 1-- 3 1-- 4 1-- 5 1-- 6 1-- 7 1-- 8 1-- 9 1--10 2-- 3 2-- 4 2-- 5 + [13] 2-- 6 2-- 7 2-- 8 2-- 9 2--10 3-- 4 3-- 5 3-- 6 3-- 7 3-- 8 3-- 9 3--10 + [25] 4-- 5 4-- 6 4-- 7 4-- 8 4-- 9 4--10 5-- 6 5-- 7 5-- 8 5-- 9 5--10 6-- 7 + [37] 6-- 8 6-- 9 6--10 7-- 8 7-- 9 7--10 8-- 9 8--10 9--10 + +# hrg_game_impl errors + + Code + x + Condition + Error in `hrg_game_impl()`: + ! At vendor/cigraph/src/hrg/hrg_types.cc:xx : Assertion failed: n >= 0. This is an unexpected igraph error; please report this as a bug, along with the steps to reproduce it. + Please restart your R session to avoid crashes or other surprising behavior. + +# hrg_consensus_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# hrg_predict_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# hrg_create_impl basic + + Code + hrg_create_impl(g, prob = rep(0.5, 2)) + Output + Hierarchical random graph, at level 3: + g1 p=0.5 1 + '- g2 p=0.5 2 3 + +# hrg_create_impl errors + + Code + x + Condition + Error in `hrg_create_impl()`: + ! At vendor/cigraph/src/hrg/hrg.cc:xx : HRG probability vector size (1) should be equal to the number of internal nodes (2). Invalid value + +# hrg_resize_impl basic + + Code + hrg_resize_impl(hrg_model, newsize = 5) + Output + $left + [1] 0 -9 -6 -2 + + $right + [1] -4 4 7 -8 + + $prob + [1] 1 1 1 1 + + $edges + [1] 9 6 3 14 + + $vertices + [1] 10 7 4 9 + + +# hrg_resize_impl errors + + Code + x + Condition + Error in `hrg_resize_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# hrg_size_impl basic + + Code + hrg_size_impl(hrg_model) + Output + [1] 10 + +# hrg_size_impl errors + + Code + x + Condition + Error in `hrg_size_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# from_hrg_dendrogram_impl basic + + Code + from_hrg_dendrogram_impl(hrg_model) + Output + $graph + IGRAPH D--- 19 18 -- + + edges: + [1] 11-> 1 11->14 12->19 12-> 5 13->16 13-> 8 14->12 14->18 15-> 3 15-> 6 + [11] 16->15 16->10 17->13 17-> 4 18-> 7 18-> 9 19-> 2 19->17 + + $prob + [1] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 1 1 1 1 1 1 1 1 1 + + +# from_hrg_dendrogram_impl errors + + Code + x + Condition + Error in `from_hrg_dendrogram_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# get_adjacency_sparse_impl basic + + Code + get_adjacency_sparse_impl(g) + Output + $type + [1] "triplet" + + $dim + [1] 3 3 + + $p + [1] 0 1 1 2 + + $i + [1] 1 0 2 1 + + $x + [1] 1 1 1 1 + + attr(,"class") + [1] "igraph.tmp.sparse" + +--- + + Code + get_adjacency_sparse_impl(g, type = "upper", weights = c(1, 2), loops = "none") + Output + $type + [1] "triplet" + + $dim + [1] 3 3 + + $p + [1] 1 2 + + $i + [1] 0 1 + + $x + [1] 1 2 + + attr(,"class") + [1] "igraph.tmp.sparse" + +# get_adjacency_sparse_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_stochastic_impl basic + + Code + get_stochastic_impl(g) + Output + [,1] [,2] [,3] + [1,] 0.0 1 0.0 + [2,] 0.5 0 0.5 + [3,] 0.0 1 0.0 + +--- + + Code + get_stochastic_impl(g, column.wise = TRUE, weights = c(1, 2)) + Output + [,1] [,2] [,3] + [1,] 0 0.3333333 0 + [2,] 1 0.0000000 1 + [3,] 0 0.6666667 0 + +# get_stochastic_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_stochastic_sparse_impl basic + + Code + get_stochastic_sparse_impl(g) + Output + $type + [1] "triplet" + + $dim + [1] 3 3 + + $p + [1] 0 1 1 2 + + $i + [1] 1 0 2 1 + + $x + [1] 0.5 1.0 1.0 0.5 + + attr(,"class") + [1] "igraph.tmp.sparse" + +--- + + Code + get_stochastic_sparse_impl(g, column.wise = TRUE, weights = c(1, 2)) + Output + $type + [1] "triplet" + + $dim + [1] 3 3 + + $p + [1] 0 1 1 2 + + $i + [1] 1 0 2 1 + + $x + [1] 1.0000000 0.3333333 0.6666667 1.0000000 + + attr(,"class") + [1] "igraph.tmp.sparse" + +# get_stochastic_sparse_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# to_directed_impl basic + + Code + to_directed_impl(g) + Output + IGRAPH D--- 3 4 -- + + edges: + [1] 1->2 2->3 2->1 3->2 + +--- + + Code + to_directed_impl(g, mode = "acyclic") + Output + IGRAPH D--- 3 2 -- + + edges: + [1] 1->2 2->3 + +# to_directed_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# to_undirected_impl basic + + Code + to_undirected_impl(g) + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + +--- + + Code + to_undirected_impl(g, mode = "mutual", edge.attr.comb = "sum") + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + +# to_undirected_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# motifs_randesu_impl basic + + Code + motifs_randesu_impl(g) + Output + [1] NaN NaN 1 0 + +--- + + Code + motifs_randesu_impl(g, size = 4, cut.prob = rep(0.1, 4)) + Output + [1] NaN NaN NaN NaN 0 NaN 0 0 0 0 0 + +# motifs_randesu_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# motifs_randesu_estimate_impl basic + + Code + motifs_randesu_estimate_impl(g, size = 3, sample.size = 2) + Output + [1] 3 + +--- + + Code + motifs_randesu_estimate_impl(g, size = 4, cut.prob = rep(0.1, 4), sample.size = 2, + sample = 1:2) + Output + [1] 3 + +# motifs_randesu_estimate_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# motifs_randesu_no_impl basic + + Code + motifs_randesu_no_impl(g) + Output + [1] 1 + +--- + + Code + motifs_randesu_no_impl(g, size = 4, cut.prob = c(0.1, 0.1, 0.1, 0.1)) + Output + [1] 0 + +# motifs_randesu_no_impl errors + + Code + x + Condition + Error in `motifs_randesu_no_impl()`: + ! At vendor/cigraph/src/misc/motifs.c:xx : Cut probability vector size (1) must agree with motif size (3). Invalid value + +# dyad_census_impl basic + + Code + dyad_census_impl(g) + Output + $mut + [1] 2 + + $asym + [1] 0 + + $null + [1] 1 + + +# dyad_census_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# triad_census_impl basic + + Code + triad_census_impl(g) + Condition + Warning in `triad_census_impl()`: + At vendor/cigraph/src/misc/motifs.c:1157 : Triad census called on an undirected graph. All connections will be treated as mutual. + Output + [1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 + +# triad_census_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_adjacent_triangles_impl basic + + Code + count_adjacent_triangles_impl(g) + Output + [1] 0 0 0 + +--- + + Code + count_adjacent_triangles_impl(g, vids = 1:2) + Output + [1] 0 0 + +# count_adjacent_triangles_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_triangles_impl basic + + Code + count_triangles_impl(g) + Output + [1] 0 + +# count_triangles_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_0_impl basic + + Code + local_scan_0_impl(g) + Output + [1] 1 2 1 + +--- + + Code + local_scan_0_impl(g, weights = c(1, 2), mode = "in") + Output + [1] 1 3 2 + +# local_scan_0_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_0_them_impl basic + + Code + local_scan_0_them_impl(g1, g2) + Output + [1] 1 2 1 + +--- + + Code + local_scan_0_them_impl(g1, g2, weights.them = c(1, 2), mode = "in") + Output + [1] 1 3 2 + +# local_scan_0_them_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_1_ecount_impl basic + + Code + local_scan_1_ecount_impl(g) + Output + [1] 1 2 1 + +--- + + Code + local_scan_1_ecount_impl(g, weights = c(1, 2), mode = "in") + Output + [1] 1 3 2 + +# local_scan_1_ecount_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_1_ecount_them_impl basic + + Code + local_scan_1_ecount_them_impl(g1, g2) + Output + [1] 1 2 1 + +--- + + Code + local_scan_1_ecount_them_impl(g1, g2, weights.them = c(1, 2), mode = "in") + Output + [1] 1 3 2 + +# local_scan_1_ecount_them_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_k_ecount_impl basic + + Code + local_scan_k_ecount_impl(g, k = 1) + Output + [1] 1 2 1 + +--- + + Code + local_scan_k_ecount_impl(g, k = 1, weights = c(1, 2), mode = "in") + Output + [1] 1 3 2 + +# local_scan_k_ecount_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_k_ecount_them_impl basic + + Code + local_scan_k_ecount_them_impl(g1, g2, k = 1) + Output + [1] 1 2 1 + +--- + + Code + local_scan_k_ecount_them_impl(g1, g2, k = 1, weights.them = c(1, 2), mode = "in") + Output + [1] 1 3 2 + +# local_scan_k_ecount_them_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_neighborhood_ecount_impl basic + + Code + local_scan_neighborhood_ecount_impl(g, neighborhoods = list(1:2, 2:3, 2:4, 2)) + Output + [1] 1 1 2 0 + +--- + + Code + local_scan_neighborhood_ecount_impl(g, weights = c(1, 2, 3), neighborhoods = list( + 1:2, 1:3, 2:4, 1)) + Output + [1] 1 3 5 0 + +# local_scan_neighborhood_ecount_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# local_scan_subset_ecount_impl basic + + Code + local_scan_subset_ecount_impl(g, subsets = list(c(1, 2), c(2, 3))) + Output + [1] 1 1 + +--- + + Code + local_scan_subset_ecount_impl(g, weights = c(1, 2, 3), subsets = list(c(1, 2), + c(2, 3))) + Output + [1] 1 2 + +# local_scan_subset_ecount_impl errors + + Code + x + Condition + Error in `.x - 1`: + ! non-numeric argument to binary operator + +# list_triangles_impl basic + + Code + list_triangles_impl(g) + Output + + 0/3 vertices: + +# list_triangles_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# join_impl basic + + Code + join_impl(g1, g2) + Output + IGRAPH U--- 6 13 -- + + edges: + [1] 1--2 2--3 4--5 5--6 1--4 1--5 1--6 2--4 2--5 2--6 3--4 3--5 3--6 + +# join_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# induced_subgraph_map_impl basic + + Code + induced_subgraph_map_impl(g, 1:2, impl = "auto") + Output + $res + IGRAPH U--- 2 1 -- + + edge: + [1] 1--2 + + $map + [1] 2 3 1 + + $invmap + [1] 1 2 + + +--- + + Code + induced_subgraph_map_impl(g, 1:2, impl = "copy_and_delete") + Output + $res + IGRAPH U--- 2 1 -- + + edge: + [1] 1--2 + + $map + [1] 2 3 1 + + $invmap + [1] 1 2 + + +# induced_subgraph_map_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# mycielskian_impl basic + + Code + mycielskian_impl(g) + Output + IGRAPH U--- 7 9 -- + + edges: + [1] 1--2 2--3 1--5 2--4 2--6 3--5 4--7 5--7 6--7 + +--- + + Code + mycielskian_impl(g, k = 2) + Output + IGRAPH U--- 15 34 -- + + edges: + [1] 1-- 2 2-- 3 1-- 5 2-- 4 2-- 6 3-- 5 4-- 7 5-- 7 6-- 7 1-- 9 + [11] 2-- 8 2--10 3-- 9 1--12 5-- 8 2--11 4-- 9 2--13 6-- 9 3--12 + [21] 5--10 4--14 7--11 5--14 7--12 6--14 7--13 8--15 9--15 10--15 + [31] 11--15 12--15 13--15 14--15 + +# mycielskian_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# product_impl basic + + Code + product_impl(g1, g2) + Output + IGRAPH U--- 9 12 -- + + edges: + [1] 1--4 2--5 3--6 4--7 5--8 6--9 1--2 4--5 7--8 2--3 5--6 8--9 + +--- + + Code + product_impl(g1, g2, type = "tensor") + Output + IGRAPH U--- 9 8 -- + + edges: + [1] 1--5 2--4 2--6 3--5 4--8 5--7 5--9 6--8 + +# product_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# rooted_product_impl basic + + Code + rooted_product_impl(g1, g2, root = 1) + Output + IGRAPH U--- 9 8 -- + + edges: + [1] 1--4 4--7 1--2 4--5 7--8 2--3 5--6 8--9 + +# rooted_product_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# gomory_hu_tree_impl basic + + Code + gomory_hu_tree_impl(g) + Output + $tree + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + + $flows + [1] 1 1 + + +--- + + Code + gomory_hu_tree_impl(g, capacity = c(1, 2)) + Output + $tree + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + + $flows + [1] 1 2 + + +# gomory_hu_tree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# maxflow_impl basic + + Code + maxflow_impl(g, source = 1, target = 3) + Output + $value + [1] 1 + + $flow + [1] 1 1 + + $cut + + 1/2 edge: + [1] 2--3 + + $partition1 + + 2/3 vertices: + [1] 1 2 + + $partition2 + + 1/3 vertex: + [1] 3 + + $stats + $stats$nopush + [1] 1 + + $stats$norelabel + [1] 0 + + $stats$nogap + [1] 0 + + $stats$nogapnodes + [1] 0 + + $stats$nobfs + [1] 1 + + + +--- + + Code + maxflow_impl(g, source = 1, target = 3, capacity = c(1, 2)) + Output + $value + [1] 1 + + $flow + [1] 1 1 + + $cut + + 1/2 edge: + [1] 1--2 + + $partition1 + + 1/3 vertex: + [1] 1 + + $partition2 + + 2/3 vertices: + [1] 2 3 + + $stats + $stats$nopush + [1] 1 + + $stats$norelabel + [1] 0 + + $stats$nogap + [1] 0 + + $stats$nogapnodes + [1] 0 + + $stats$nobfs + [1] 1 + + + +# maxflow_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# residual_graph_impl basic + + Code + residual_graph_impl(g, capacity = c(1, 2), flow = c(1, 2)) + Output + $residual + IGRAPH D--- 3 0 -- + + edges: + + $residual_capacity + numeric(0) + + +# residual_graph_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# reverse_residual_graph_impl basic + + Code + reverse_residual_graph_impl(g, capacity = c(1, 2), flow = c(1, 2)) + Output + IGRAPH D--- 3 2 -- + + edges: + [1] 2->1 3->2 + +# reverse_residual_graph_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# st_mincut_impl basic + + Code + st_mincut_impl(g, source = 1, target = 3) + Output + $value + [1] 1 + + $cut + + 1/2 edge: + [1] 2--3 + + $partition1 + + 2/3 vertices: + [1] 1 2 + + $partition2 + + 1/3 vertex: + [1] 3 + + +--- + + Code + st_mincut_impl(g, source = 1, target = 3, capacity = c(1, 2)) + Output + $value + [1] 1 + + $cut + + 1/2 edge: + [1] 1--2 + + $partition1 + + 1/3 vertex: + [1] 1 + + $partition2 + + 2/3 vertices: + [1] 2 3 + + +# st_mincut_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# dominator_tree_impl basic + + Code + dominator_tree_impl(g, root = 1) + Output + $dom + [1] 0 1 2 + + $domtree + IGRAPH D--- 3 2 -- + + edges: + [1] 1->2 2->3 + + $leftout + + 0/3 vertices: + + +--- + + Code + dominator_tree_impl(g, root = 1, mode = "in") + Output + $dom + [1] 0 -1 -1 + + $domtree + IGRAPH D--- 3 0 -- + + edges: + + $leftout + + 2/3 vertices: + [1] 2 3 + + +# dominator_tree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# all_st_cuts_impl basic + + Code + all_st_cuts_impl(g, source = 1, target = 3) + Output + $cuts + $cuts[[1]] + + 1/2 edge: + [1] 1->2 + + $cuts[[2]] + + 1/2 edge: + [1] 2->3 + + + $partition1s + $partition1s[[1]] + + 1/3 vertex: + [1] 1 + + $partition1s[[2]] + + 2/3 vertices: + [1] 1 2 + + + +# all_st_cuts_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# all_st_mincuts_impl basic + + Code + all_st_mincuts_impl(g, source = 1, target = 3) + Output + $value + [1] 1 + + $cuts + $cuts[[1]] + + 1/2 edge: + [1] 1->2 + + $cuts[[2]] + + 1/2 edge: + [1] 2->3 + + + $partition1s + $partition1s[[1]] + + 1/3 vertex: + [1] 1 + + $partition1s[[2]] + + 2/3 vertices: + [1] 1 2 + + + +--- + + Code + all_st_mincuts_impl(g, source = 1, target = 3, capacity = c(1, 2)) + Output + $value + [1] 1 + + $cuts + $cuts[[1]] + + 1/2 edge: + [1] 1->2 + + + $partition1s + $partition1s[[1]] + + 1/3 vertex: + [1] 1 + + + +# all_st_mincuts_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# even_tarjan_reduction_impl basic + + Code + even_tarjan_reduction_impl(g) + Output + $graphbar + IGRAPH D--- 6 7 -- + + edges: + [1] 1->4 2->5 3->6 5->1 4->2 6->2 5->3 + + $capacity + [1] 1 1 1 3 3 3 3 + + +# even_tarjan_reduction_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_separator_impl basic + + Code + is_separator_impl(g, 1:2) + Output + [1] FALSE + +# is_separator_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_minimal_separator_impl basic + + Code + is_minimal_separator_impl(g, 1:2) + Output + [1] FALSE + +# is_minimal_separator_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# all_minimal_st_separators_impl basic + + Code + all_minimal_st_separators_impl(g) + Output + [[1]] + + 1/3 vertex: + [1] 2 + + +# all_minimal_st_separators_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# minimum_size_separators_impl basic + + Code + minimum_size_separators_impl(g) + Output + [[1]] + + 1/3 vertex: + [1] 2 + + +# minimum_size_separators_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# isoclass_impl basic + + Code + isoclass_impl(g) + Output + [1] 2 + +# isoclass_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# isomorphic_impl basic + + Code + isomorphic_impl(g1, g2) + Output + [1] TRUE + +# isomorphic_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# isoclass_subgraph_impl basic + + Code + isoclass_subgraph_impl(g, c(1, 2, 3)) + Output + [1] 2 + +# isoclass_subgraph_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# isoclass_create_impl basic + + Code + isoclass_create_impl(size = 3, number = 1) + Output + IGRAPH D--- 3 1 -- + + edge: + [1] 2->1 + +--- + + Code + isoclass_create_impl(size = 3, number = 1, directed = FALSE) + Output + IGRAPH U--- 3 1 -- + + edge: + [1] 1--2 + +# isoclass_create_impl errors + + Code + x + Condition + Warning in `isoclass_create_impl()`: + NAs introduced by coercion + Error in `isoclass_create_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# isomorphic_vf2_impl basic + + Code + isomorphic_vf2_impl(g1, g2) + Output + $iso + [1] TRUE + + $map12 + [1] 1 2 3 + + $map21 + [1] 1 2 3 + + +--- + + Code + isomorphic_vf2_impl(g1, g2, vertex.color1 = c(1, 2, 3), vertex.color2 = c(1, 2, + 3), edge.color1 = c(1, 2), edge.color2 = c(1, 2)) + Output + $iso + [1] TRUE + + $map12 + [1] 1 2 3 + + $map21 + [1] 1 2 3 + + +# isomorphic_vf2_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_isomorphisms_vf2_impl basic + + Code + count_isomorphisms_vf2_impl(g1, g2) + Output + [1] 2 + +--- + + Code + count_isomorphisms_vf2_impl(g1, g2, vertex.color1 = c(1, 2, 3), vertex.color2 = c( + 1, 2, 3), edge.color1 = c(1, 2), edge.color2 = c(1, 2)) + Output + [1] 1 + +# count_isomorphisms_vf2_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_isomorphisms_vf2_impl basic + + Code + get_isomorphisms_vf2_impl(g1, g2) + Output + [[1]] + [1] 0 1 2 + + [[2]] + [1] 2 1 0 + + +--- + + Code + get_isomorphisms_vf2_impl(g1, g2, vertex.color1 = c(1, 2, 3), vertex.color2 = c( + 1, 2, 3), edge.color1 = c(1, 2), edge.color2 = c(1, 2)) + Output + [[1]] + [1] 0 1 2 + + +# get_isomorphisms_vf2_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# subisomorphic_impl basic + + Code + subisomorphic_impl(g1, g2) + Output + [1] TRUE + +# subisomorphic_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# subisomorphic_vf2_impl basic + + Code + subisomorphic_vf2_impl(g1, g2) + Output + $iso + [1] TRUE + + $map12 + [1] 1 2 3 + + $map21 + [1] 1 2 3 + + +--- + + Code + subisomorphic_vf2_impl(g1, g2, vertex.color1 = c(1, 2, 3), vertex.color2 = c(1, + 2, 3), edge.color1 = c(1, 2), edge.color2 = c(1, 2)) + Output + $iso + [1] TRUE + + $map12 + [1] 1 2 3 + + $map21 + [1] 1 2 3 + + +# subisomorphic_vf2_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_subisomorphisms_vf2_impl basic + + Code + count_subisomorphisms_vf2_impl(g1, g2) + Output + [1] 2 + +--- + + Code + count_subisomorphisms_vf2_impl(g1, g2, vertex.color1 = c(1, 2, 3), + vertex.color2 = c(1, 2, 3), edge.color1 = c(1, 2), edge.color2 = c(1, 2)) + Output + [1] 1 + +# count_subisomorphisms_vf2_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# get_subisomorphisms_vf2_impl basic + + Code + get_subisomorphisms_vf2_impl(g1, g2) + Output + [[1]] + [1] 0 1 2 + + [[2]] + [1] 2 1 0 + + +--- + + Code + get_subisomorphisms_vf2_impl(g1, g2, vertex.color1 = c(1, 2, 3), vertex.color2 = c( + 1, 2, 3), edge.color1 = c(1, 2), edge.color2 = c(1, 2)) + Output + [[1]] + [1] 0 1 2 + + +# get_subisomorphisms_vf2_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# canonical_permutation_impl basic + + Code + canonical_permutation_impl(g) + Output + $labeling + [1] 2 3 1 + + $info + $info$nof_nodes + [1] 3 + + $info$nof_leaf_nodes + [1] 3 + + $info$nof_bad_nodes + [1] 0 + + $info$nof_canupdates + [1] 1 + + $info$max_level + [1] 1 + + $info$group_size + [1] "2" + + + +--- + + Code + canonical_permutation_impl(g, colors = c(1, 2, 3), sh = "fl") + Output + $labeling + [1] 1 2 3 + + $info + $info$nof_nodes + [1] 1 + + $info$nof_leaf_nodes + [1] 1 + + $info$nof_bad_nodes + [1] 0 + + $info$nof_canupdates + [1] 0 + + $info$max_level + [1] 0 + + $info$group_size + [1] "1" + + + +# canonical_permutation_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# permute_vertices_impl basic + + Code + permute_vertices_impl(g, permutation = 3:1) + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 2--3 1--2 + +# permute_vertices_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# isomorphic_bliss_impl basic + + Code + isomorphic_bliss_impl(g1, g2) + Output + $iso + [1] TRUE + + $map12 + [1] 1 2 3 + + $map21 + [1] 1 2 3 + + $info1 + $info1$nof_nodes + [1] 3 + + $info1$nof_leaf_nodes + [1] 3 + + $info1$nof_bad_nodes + [1] 0 + + $info1$nof_canupdates + [1] 1 + + $info1$max_level + [1] 1 + + $info1$group_size + [1] "2" + + + $info2 + $info2$nof_nodes + [1] 3 + + $info2$nof_leaf_nodes + [1] 3 + + $info2$nof_bad_nodes + [1] 0 + + $info2$nof_canupdates + [1] 1 + + $info2$max_level + [1] 1 + + $info2$group_size + [1] "2" + + + +--- + + Code + isomorphic_bliss_impl(g1, g2, colors1 = c(1, 2, 3), colors2 = c(1, 2, 3), sh = "fl") + Output + $iso + [1] TRUE + + $map12 + [1] 1 2 3 + + $map21 + [1] 1 2 3 + + $info1 + $info1$nof_nodes + [1] 1 + + $info1$nof_leaf_nodes + [1] 1 + + $info1$nof_bad_nodes + [1] 0 + + $info1$nof_canupdates + [1] 0 + + $info1$max_level + [1] 0 + + $info1$group_size + [1] "1" + + + $info2 + $info2$nof_nodes + [1] 1 + + $info2$nof_leaf_nodes + [1] 1 + + $info2$nof_bad_nodes + [1] 0 + + $info2$nof_canupdates + [1] 0 + + $info2$max_level + [1] 0 + + $info2$group_size + [1] "1" + + + +# isomorphic_bliss_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# count_automorphisms_impl basic + + Code + count_automorphisms_impl(g) + Output + $nof_nodes + [1] 3 + + $nof_leaf_nodes + [1] 3 + + $nof_bad_nodes + [1] 0 + + $nof_canupdates + [1] 1 + + $max_level + [1] 1 + + $group_size + [1] "2" + + +--- + + Code + count_automorphisms_impl(g, colors = c(1, 2, 3), sh = "fl") + Output + $nof_nodes + [1] 1 + + $nof_leaf_nodes + [1] 1 + + $nof_bad_nodes + [1] 0 + + $nof_canupdates + [1] 0 + + $max_level + [1] 0 + + $group_size + [1] "1" + + +# count_automorphisms_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# automorphism_group_impl basic + + Code + automorphism_group_impl(g) + Output + [[1]] + + 3/3 vertices: + [1] 3 2 1 + + +--- + + Code + automorphism_group_impl(g, colors = c(1, 2, 3), sh = "fl", details = TRUE) + Output + $generators + list() + + $info + $info$nof_nodes + [1] 1 + + $info$nof_leaf_nodes + [1] 1 + + $info$nof_bad_nodes + [1] 0 + + $info$nof_canupdates + [1] 0 + + $info$max_level + [1] 0 + + $info$group_size + [1] "1" + + + +# automorphism_group_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# simplify_and_colorize_impl basic + + Code + simplify_and_colorize_impl(g) + Output + $res + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + + $vertex_color + [1] 0 0 0 + + $edge_color + [1] 1 1 + + +# simplify_and_colorize_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# graph_count_impl basic + + Code + graph_count_impl(3) + Output + [1] 4 + +--- + + Code + graph_count_impl(3, directed = TRUE) + Output + [1] 16 + +# graph_count_impl errors + + Code + x + Condition + Warning in `graph_count_impl()`: + NAs introduced by coercion + Error in `graph_count_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# is_matching_impl basic + + Code + is_matching_impl(g, matching = 1:2) + Output + [1] FALSE + +--- + + Code + is_matching_impl(g, types = c(TRUE, FALSE, TRUE), matching = 1:2) + Output + [1] FALSE + +# is_matching_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_maximal_matching_impl basic + + Code + is_maximal_matching_impl(g, matching = 1:2) + Output + [1] FALSE + +--- + + Code + is_maximal_matching_impl(g, types = c(TRUE, FALSE, TRUE), matching = 1:2) + Output + [1] FALSE + +# is_maximal_matching_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# maximum_bipartite_matching_impl basic + + Code + maximum_bipartite_matching_impl(g, types = c(TRUE, FALSE, TRUE)) + Output + $matching_size + [1] 1 + + $matching_weight + [1] 1 + + $matching + [1] 2 1 0 + + +--- + + Code + maximum_bipartite_matching_impl(g, types = c(TRUE, FALSE, TRUE), weights = c(1, + 2), eps = 1e-05) + Output + $matching_size + [1] 1 + + $matching_weight + [1] 2 + + $matching + [1] 0 3 2 + + +# maximum_bipartite_matching_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# adjacency_spectral_embedding_impl basic + + Code + adjacency_spectral_embedding_impl(g, no = 2) + Output + $X + [,1] [,2] + [1,] 0.6718598 -0.4487712 + [2,] 1.1328501 0.5323058 + [3,] 0.6718598 -0.4487712 + + $Y + NULL + + $D + [1] 2.1861407 -0.6861407 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LM" + + $options$nev + [1] 2 + + $options$tol + [1] 0 + + $options$ncv + [1] 3 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 2 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 2 + + + +--- + + Code + adjacency_spectral_embedding_impl(g, no = 2, weights = c(1, 2), which = "la", + scaled = FALSE, cvec = c(1, 2, 3), options = list(maxiter = 10)) + Output + $X + [,1] [,2] + [1,] 0.1720265 -0.7864357 + [2,] 0.6311790 -0.3743620 + [3,] 0.7563200 0.4912963 + + $Y + NULL + + $D + [1] 4.669079 1.476024 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LA" + + $options$nev + [1] 2 + + $options$tol + [1] 0 + + $options$ncv + [1] 3 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 10 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 2 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 2 + + + +# adjacency_spectral_embedding_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# laplacian_spectral_embedding_impl basic + + Code + laplacian_spectral_embedding_impl(g, no = 2) + Output + $X + [,1] [,2] + [1,] -0.7071068 -0.7071068 + [2,] 1.4142136 0.0000000 + [3,] -0.7071068 0.7071068 + + $Y + NULL + + $D + [1] 3 1 + + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LM" + + $options$nev + [1] 2 + + $options$tol + [1] 0 + + $options$ncv + [1] 3 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 1 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 1 + + $options$nconv + [1] 2 + + $options$numop + [1] 3 + + $options$numopb + [1] 0 + + $options$numreo + [1] 3 + + + +# laplacian_spectral_embedding_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# eigen_adjacency_impl basic + + Code + eigen_adjacency_impl(g) + Output + $options + $options$bmat + [1] "I" + + $options$n + [1] 3 + + $options$which + [1] "LM" + + $options$nev + [1] 1 + + $options$tol + [1] 0 + + $options$ncv + [1] 2 + + $options$ldv + [1] 0 + + $options$ishift + [1] 1 + + $options$maxiter + [1] 3000 + + $options$nb + [1] 1 + + $options$mode + [1] 1 + + $options$start + [1] 0 + + $options$sigma + [1] 0 + + $options$sigmai + [1] 0 + + $options$info + [1] 0 + + $options$iter + [1] 29 + + $options$nconv + [1] 1 + + $options$numop + [1] 30 + + $options$numopb + [1] 0 + + $options$numreo + [1] 16 + + + $values + [1] -1.414214 + + $vectors + [,1] + [1,] -0.5000000 + [2,] 0.7071068 + [3,] -0.5000000 + + $cmplxvalues + complex(0) + + $cmplxvectors + <0 x 0 matrix> + + +--- + + Code + x + Condition + Error in `eigen_adjacency_impl()`: + ! At vendor/cigraph/src/linalg/eigen.c:xx : 'LAPACK' algorithm not implemented yet, Unimplemented function call + +# eigen_adjacency_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# power_law_fit_impl basic + + Code + power_law_fit_impl(c(1, 2, 3)) + Output + $continuous + [1] FALSE + + $alpha + [1] 1.646771 + + $xmin + [1] 1 + + $logLik + [1] -5.272517 + + $KS.stat + [1] 0.2640998 + + +--- + + Code + power_law_fit_impl(c(1, 2, 3), xmin = 1, force.continuous = TRUE) + Output + $continuous + [1] TRUE + + $alpha + [1] 2.116221 + + $xmin + [1] 1 + + $logLik + [1] -3.461912 + + $KS.stat + [1] 0.3533555 + + +# power_law_fit_impl errors + + Code + x + Condition + Warning in `power_law_fit_impl()`: + NAs introduced by coercion + Error in `power_law_fit_impl()`: + ! At vendor/cigraph/src/misc/power_law_fit.c:xx : xmin must be greater than zero, Invalid value + +# sir_impl basic + + Code + sir_impl(g, beta = 0.1, gamma = 0.1) + Output + [[1]] + [[1]]$times + [1] 0.000000 6.326537 8.018361 8.809852 9.405480 17.386752 + + [[1]]$NS + [1] 2 1 0 0 0 0 + + [[1]]$NI + [1] 1 2 3 2 1 0 + + [[1]]$NR + [1] 0 0 0 1 2 3 + + + [[2]] + [[2]]$times + [1] 0.000000 3.674354 13.783038 13.921168 + + [[2]]$NS + [1] 2 1 1 1 + + [[2]]$NI + [1] 1 2 1 0 + + [[2]]$NR + [1] 0 0 1 2 + + + [[3]] + [[3]]$times + [1] 0.000000 3.277542 7.521770 16.781182 18.515742 29.375613 + + [[3]]$NS + [1] 2 1 0 0 0 0 + + [[3]]$NI + [1] 1 2 3 2 1 0 + + [[3]]$NR + [1] 0 0 0 1 2 3 + + + [[4]] + [[4]]$times + [1] 0.0000000 0.3027921 + + [[4]]$NS + [1] 2 2 + + [[4]]$NI + [1] 1 0 + + [[4]]$NR + [1] 0 1 + + + [[5]] + [[5]]$times + [1] 0.000000 3.559451 5.615586 20.582742 + + [[5]]$NS + [1] 2 1 1 1 + + [[5]]$NI + [1] 1 2 1 0 + + [[5]]$NR + [1] 0 0 1 2 + + + [[6]] + [[6]]$times + [1] 0.0000000 0.7300885 0.7328203 1.2536518 1.9258569 5.1406208 + + [[6]]$NS + [1] 2 1 0 0 0 0 + + [[6]]$NI + [1] 1 2 3 2 1 0 + + [[6]]$NR + [1] 0 0 0 1 2 3 + + + [[7]] + [[7]]$times + [1] 0.000000 0.865533 + + [[7]]$NS + [1] 2 2 + + [[7]]$NI + [1] 1 0 + + [[7]]$NR + [1] 0 1 + + + [[8]] + [[8]]$times + [1] 0.00000 10.68605 + + [[8]]$NS + [1] 2 2 + + [[8]]$NI + [1] 1 0 + + [[8]]$NR + [1] 0 1 + + + [[9]] + [[9]]$times + [1] 0.000000 2.185910 7.669126 16.635095 21.440723 23.497554 + + [[9]]$NS + [1] 2 1 0 0 0 0 + + [[9]]$NI + [1] 1 2 3 2 1 0 + + [[9]]$NR + [1] 0 0 0 1 2 3 + + + [[10]] + [[10]]$times + [1] 0.000000 4.105424 4.424244 22.891743 24.099505 32.514828 + + [[10]]$NS + [1] 2 1 1 0 0 0 + + [[10]]$NI + [1] 1 2 1 2 1 0 + + [[10]]$NR + [1] 0 0 1 1 2 3 + + + [[11]] + [[11]]$times + [1] 0.00000 4.93042 21.00935 21.07441 23.37619 41.26694 + + [[11]]$NS + [1] 2 1 0 0 0 0 + + [[11]]$NI + [1] 1 2 3 2 1 0 + + [[11]]$NR + [1] 0 0 0 1 2 3 + + + [[12]] + [[12]]$times + [1] 0.00000 15.47343 26.09187 38.01744 43.76847 50.41068 + + [[12]]$NS + [1] 2 1 0 0 0 0 + + [[12]]$NI + [1] 1 2 3 2 1 0 + + [[12]]$NR + [1] 0 0 0 1 2 3 + + + [[13]] + [[13]]$times + [1] 0.000000 3.540437 + + [[13]]$NS + [1] 2 2 + + [[13]]$NI + [1] 1 0 + + [[13]]$NR + [1] 0 1 + + + [[14]] + [[14]]$times + [1] 0.000000 7.081426 7.638086 11.569527 + + [[14]]$NS + [1] 2 1 1 1 + + [[14]]$NI + [1] 1 2 1 0 + + [[14]]$NR + [1] 0 0 1 2 + + + [[15]] + [[15]]$times + [1] 0.00000 15.60443 15.66654 20.19745 22.11224 42.62196 + + [[15]]$NS + [1] 2 1 0 0 0 0 + + [[15]]$NI + [1] 1 2 3 2 1 0 + + [[15]]$NR + [1] 0 0 0 1 2 3 + + + [[16]] + [[16]]$times + [1] 0.000000 3.239708 17.193626 18.833130 19.040959 35.199892 + + [[16]]$NS + [1] 2 1 1 0 0 0 + + [[16]]$NI + [1] 1 2 1 2 1 0 + + [[16]]$NR + [1] 0 0 1 1 2 3 + + + [[17]] + [[17]]$times + [1] 0.0000000 0.2300489 1.8970602 6.9851496 16.0587095 28.8528567 + + [[17]]$NS + [1] 2 1 0 0 0 0 + + [[17]]$NI + [1] 1 2 3 2 1 0 + + [[17]]$NR + [1] 0 0 0 1 2 3 + + + [[18]] + [[18]]$times + [1] 0.000000 4.674879 5.319832 17.366640 63.357258 86.262883 + + [[18]]$NS + [1] 2 1 1 0 0 0 + + [[18]]$NI + [1] 1 2 1 2 1 0 + + [[18]]$NR + [1] 0 0 1 1 2 3 + + + [[19]] + [[19]]$times + [1] 0.000000 1.972293 + + [[19]]$NS + [1] 2 2 + + [[19]]$NI + [1] 1 0 + + [[19]]$NR + [1] 0 1 + + + [[20]] + [[20]]$times + [1] 0.000000 3.177922 + + [[20]]$NS + [1] 2 2 + + [[20]]$NI + [1] 1 0 + + [[20]]$NR + [1] 0 1 + + + [[21]] + [[21]]$times + [1] 0.000000 1.994279 2.508129 8.208209 28.478526 36.256169 + + [[21]]$NS + [1] 2 1 0 0 0 0 + + [[21]]$NI + [1] 1 2 3 2 1 0 + + [[21]]$NR + [1] 0 0 0 1 2 3 + + + [[22]] + [[22]]$times + [1] 0.000000 5.226609 14.744785 16.304309 + + [[22]]$NS + [1] 2 1 1 1 + + [[22]]$NI + [1] 1 2 1 0 + + [[22]]$NR + [1] 0 0 1 2 + + + [[23]] + [[23]]$times + [1] 0.000000 3.254634 13.673154 21.069828 + + [[23]]$NS + [1] 2 1 1 1 + + [[23]]$NI + [1] 1 2 1 0 + + [[23]]$NR + [1] 0 0 1 2 + + + [[24]] + [[24]]$times + [1] 0.00000 18.01982 18.36106 44.55144 + + [[24]]$NS + [1] 2 1 1 1 + + [[24]]$NI + [1] 1 2 1 0 + + [[24]]$NR + [1] 0 0 1 2 + + + [[25]] + [[25]]$times + [1] 0.00000 18.09036 30.47469 36.51570 + + [[25]]$NS + [1] 2 1 1 1 + + [[25]]$NI + [1] 1 2 1 0 + + [[25]]$NR + [1] 0 0 1 2 + + + [[26]] + [[26]]$times + [1] 0.00000 11.21296 + + [[26]]$NS + [1] 2 2 + + [[26]]$NI + [1] 1 0 + + [[26]]$NR + [1] 0 1 + + + [[27]] + [[27]]$times + [1] 0.000000 1.605373 + + [[27]]$NS + [1] 2 2 + + [[27]]$NI + [1] 1 0 + + [[27]]$NR + [1] 0 1 + + + [[28]] + [[28]]$times + [1] 0.000000 3.448751 12.086502 17.941228 + + [[28]]$NS + [1] 2 1 1 1 + + [[28]]$NI + [1] 1 2 1 0 + + [[28]]$NR + [1] 0 0 1 2 + + + [[29]] + [[29]]$times + [1] 0.000000 8.277924 + + [[29]]$NS + [1] 2 2 + + [[29]]$NI + [1] 1 0 + + [[29]]$NR + [1] 0 1 + + + [[30]] + [[30]]$times + [1] 0.000000 9.146159 + + [[30]]$NS + [1] 2 2 + + [[30]]$NI + [1] 1 0 + + [[30]]$NR + [1] 0 1 + + + [[31]] + [[31]]$times + [1] 0.00000000 0.07833588 + + [[31]]$NS + [1] 2 2 + + [[31]]$NI + [1] 1 0 + + [[31]]$NR + [1] 0 1 + + + [[32]] + [[32]]$times + [1] 0.000000 7.825191 + + [[32]]$NS + [1] 2 2 + + [[32]]$NI + [1] 1 0 + + [[32]]$NR + [1] 0 1 + + + [[33]] + [[33]]$times + [1] 0.0000000 0.4018017 + + [[33]]$NS + [1] 2 2 + + [[33]]$NI + [1] 1 0 + + [[33]]$NR + [1] 0 1 + + + [[34]] + [[34]]$times + [1] 0.000000 1.433794 + + [[34]]$NS + [1] 2 2 + + [[34]]$NI + [1] 1 0 + + [[34]]$NR + [1] 0 1 + + + [[35]] + [[35]]$times + [1] 0.00000000 0.06959151 2.61176819 2.76819228 + + [[35]]$NS + [1] 2 1 1 1 + + [[35]]$NI + [1] 1 2 1 0 + + [[35]]$NR + [1] 0 0 1 2 + + + [[36]] + [[36]]$times + [1] 0.000000 1.539839 17.502742 21.550799 31.779748 59.056912 + + [[36]]$NS + [1] 2 1 0 0 0 0 + + [[36]]$NI + [1] 1 2 3 2 1 0 + + [[36]]$NR + [1] 0 0 0 1 2 3 + + + [[37]] + [[37]]$times + [1] 0.000000 8.878624 + + [[37]]$NS + [1] 2 2 + + [[37]]$NI + [1] 1 0 + + [[37]]$NR + [1] 0 1 + + + [[38]] + [[38]]$times + [1] 0.000000 6.855525 + + [[38]]$NS + [1] 2 2 + + [[38]]$NI + [1] 1 0 + + [[38]]$NR + [1] 0 1 + + + [[39]] + [[39]]$times + [1] 0.000000 2.628739 3.809460 7.051204 + + [[39]]$NS + [1] 2 1 1 1 + + [[39]]$NI + [1] 1 2 1 0 + + [[39]]$NR + [1] 0 0 1 2 + + + [[40]] + [[40]]$times + [1] 0.000000 2.484282 + + [[40]]$NS + [1] 2 2 + + [[40]]$NI + [1] 1 0 + + [[40]]$NR + [1] 0 1 + + + [[41]] + [[41]]$times + [1] 0.0000000 0.8248393 + + [[41]]$NS + [1] 2 2 + + [[41]]$NI + [1] 1 0 + + [[41]]$NR + [1] 0 1 + + + [[42]] + [[42]]$times + [1] 0.000000 2.300359 3.886947 6.810196 7.223496 28.297207 + + [[42]]$NS + [1] 2 1 0 0 0 0 + + [[42]]$NI + [1] 1 2 3 2 1 0 + + [[42]]$NR + [1] 0 0 0 1 2 3 + + + [[43]] + [[43]]$times + [1] 0.00000 5.52241 10.93993 29.15486 + + [[43]]$NS + [1] 2 1 1 1 + + [[43]]$NI + [1] 1 2 1 0 + + [[43]]$NR + [1] 0 0 1 2 + + + [[44]] + [[44]]$times + [1] 0.000000 9.526317 12.154710 21.171748 + + [[44]]$NS + [1] 2 1 1 1 + + [[44]]$NI + [1] 1 2 1 0 + + [[44]]$NR + [1] 0 0 1 2 + + + [[45]] + [[45]]$times + [1] 0.000000 4.448428 + + [[45]]$NS + [1] 2 2 + + [[45]]$NI + [1] 1 0 + + [[45]]$NR + [1] 0 1 + + + [[46]] + [[46]]$times + [1] 0.0000000 0.0560511 + + [[46]]$NS + [1] 2 2 + + [[46]]$NI + [1] 1 0 + + [[46]]$NR + [1] 0 1 + + + [[47]] + [[47]]$times + [1] 0.00000 11.57560 12.20970 12.58732 26.47299 36.19628 + + [[47]]$NS + [1] 2 1 0 0 0 0 + + [[47]]$NI + [1] 1 2 3 2 1 0 + + [[47]]$NR + [1] 0 0 0 1 2 3 + + + [[48]] + [[48]]$times + [1] 0.000000 3.687231 + + [[48]]$NS + [1] 2 2 + + [[48]]$NI + [1] 1 0 + + [[48]]$NR + [1] 0 1 + + + [[49]] + [[49]]$times + [1] 0.0000000 0.3436458 1.0908931 1.4640857 + + [[49]]$NS + [1] 2 1 1 1 + + [[49]]$NI + [1] 1 2 1 0 + + [[49]]$NR + [1] 0 0 1 2 + + + [[50]] + [[50]]$times + [1] 0.000000 1.536136 + + [[50]]$NS + [1] 2 2 + + [[50]]$NI + [1] 1 0 + + [[50]]$NR + [1] 0 1 + + + [[51]] + [[51]]$times + [1] 0.000000 2.021208 + + [[51]]$NS + [1] 2 2 + + [[51]]$NI + [1] 1 0 + + [[51]]$NR + [1] 0 1 + + + [[52]] + [[52]]$times + [1] 0.00000 4.29424 + + [[52]]$NS + [1] 2 2 + + [[52]]$NI + [1] 1 0 + + [[52]]$NR + [1] 0 1 + + + [[53]] + [[53]]$times + [1] 0.000000 1.884908 5.139700 8.417338 12.272436 15.154107 + + [[53]]$NS + [1] 2 1 0 0 0 0 + + [[53]]$NI + [1] 1 2 3 2 1 0 + + [[53]]$NR + [1] 0 0 0 1 2 3 + + + [[54]] + [[54]]$times + [1] 0.0000000 0.1997796 + + [[54]]$NS + [1] 2 2 + + [[54]]$NI + [1] 1 0 + + [[54]]$NR + [1] 0 1 + + + [[55]] + [[55]]$times + [1] 0.0000000 0.1825065 + + [[55]]$NS + [1] 2 2 + + [[55]]$NI + [1] 1 0 + + [[55]]$NR + [1] 0 1 + + + [[56]] + [[56]]$times + [1] 0.000000 1.913698 2.656593 7.598135 + + [[56]]$NS + [1] 2 1 1 1 + + [[56]]$NI + [1] 1 2 1 0 + + [[56]]$NR + [1] 0 0 1 2 + + + [[57]] + [[57]]$times + [1] 0.000000 3.435708 + + [[57]]$NS + [1] 2 2 + + [[57]]$NI + [1] 1 0 + + [[57]]$NR + [1] 0 1 + + + [[58]] + [[58]]$times + [1] 0.000000 0.583133 5.284710 10.065112 18.657681 21.137430 + + [[58]]$NS + [1] 2 1 1 0 0 0 + + [[58]]$NI + [1] 1 2 1 2 1 0 + + [[58]]$NR + [1] 0 0 1 1 2 3 + + + [[59]] + [[59]]$times + [1] 0.000000 8.526031 + + [[59]]$NS + [1] 2 2 + + [[59]]$NI + [1] 1 0 + + [[59]]$NR + [1] 0 1 + + + [[60]] + [[60]]$times + [1] 0.000000 3.470768 + + [[60]]$NS + [1] 2 2 + + [[60]]$NI + [1] 1 0 + + [[60]]$NR + [1] 0 1 + + + [[61]] + [[61]]$times + [1] 0.000000 2.311806 + + [[61]]$NS + [1] 2 2 + + [[61]]$NI + [1] 1 0 + + [[61]]$NR + [1] 0 1 + + + [[62]] + [[62]]$times + [1] 0.000000 5.603495 + + [[62]]$NS + [1] 2 2 + + [[62]]$NI + [1] 1 0 + + [[62]]$NR + [1] 0 1 + + + [[63]] + [[63]]$times + [1] 0.0000000 0.2376974 + + [[63]]$NS + [1] 2 2 + + [[63]]$NI + [1] 1 0 + + [[63]]$NR + [1] 0 1 + + + [[64]] + [[64]]$times + [1] 0.000000 1.164209 4.169140 7.017509 + + [[64]]$NS + [1] 2 1 1 1 + + [[64]]$NI + [1] 1 2 1 0 + + [[64]]$NR + [1] 0 0 1 2 + + + [[65]] + [[65]]$times + [1] 0.000000 6.415227 6.561435 14.007083 + + [[65]]$NS + [1] 2 1 1 1 + + [[65]]$NI + [1] 1 2 1 0 + + [[65]]$NR + [1] 0 0 1 2 + + + [[66]] + [[66]]$times + [1] 0.00000 14.28491 31.69273 39.51170 + + [[66]]$NS + [1] 2 1 1 1 + + [[66]]$NI + [1] 1 2 1 0 + + [[66]]$NR + [1] 0 0 1 2 + + + [[67]] + [[67]]$times + [1] 0.000000 3.592755 4.363836 11.200455 + + [[67]]$NS + [1] 2 1 1 1 + + [[67]]$NI + [1] 1 2 1 0 + + [[67]]$NR + [1] 0 0 1 2 + + + [[68]] + [[68]]$times + [1] 0.000000 8.044133 10.227368 12.702160 16.225120 23.696870 + + [[68]]$NS + [1] 2 1 1 0 0 0 + + [[68]]$NI + [1] 1 2 1 2 1 0 + + [[68]]$NR + [1] 0 0 1 1 2 3 + + + [[69]] + [[69]]$times + [1] 0.000000 3.324148 + + [[69]]$NS + [1] 2 2 + + [[69]]$NI + [1] 1 0 + + [[69]]$NR + [1] 0 1 + + + [[70]] + [[70]]$times + [1] 0.000000 6.316816 + + [[70]]$NS + [1] 2 2 + + [[70]]$NI + [1] 1 0 + + [[70]]$NR + [1] 0 1 + + + [[71]] + [[71]]$times + [1] 0.000000 7.473339 7.757794 15.139281 + + [[71]]$NS + [1] 2 1 1 1 + + [[71]]$NI + [1] 1 2 1 0 + + [[71]]$NR + [1] 0 0 1 2 + + + [[72]] + [[72]]$times + [1] 0.000000 4.073649 6.034897 8.135670 + + [[72]]$NS + [1] 2 1 1 1 + + [[72]]$NI + [1] 1 2 1 0 + + [[72]]$NR + [1] 0 0 1 2 + + + [[73]] + [[73]]$times + [1] 0.00000 1.60059 + + [[73]]$NS + [1] 2 2 + + [[73]]$NI + [1] 1 0 + + [[73]]$NR + [1] 0 1 + + + [[74]] + [[74]]$times + [1] 0.000000 1.497596 + + [[74]]$NS + [1] 2 2 + + [[74]]$NI + [1] 1 0 + + [[74]]$NR + [1] 0 1 + + + [[75]] + [[75]]$times + [1] 0.000000 1.916758 + + [[75]]$NS + [1] 2 2 + + [[75]]$NI + [1] 1 0 + + [[75]]$NR + [1] 0 1 + + + [[76]] + [[76]]$times + [1] 0.0000000 0.8368377 4.1462512 14.4447646 + + [[76]]$NS + [1] 2 1 1 1 + + [[76]]$NI + [1] 1 2 1 0 + + [[76]]$NR + [1] 0 0 1 2 + + + [[77]] + [[77]]$times + [1] 0.000000 8.546053 9.275575 11.920068 14.117820 14.371987 + + [[77]]$NS + [1] 2 1 0 0 0 0 + + [[77]]$NI + [1] 1 2 3 2 1 0 + + [[77]]$NR + [1] 0 0 0 1 2 3 + + + [[78]] + [[78]]$times + [1] 0.000000 2.730273 6.669293 7.301694 14.402306 22.580301 + + [[78]]$NS + [1] 2 1 0 0 0 0 + + [[78]]$NI + [1] 1 2 3 2 1 0 + + [[78]]$NR + [1] 0 0 0 1 2 3 + + + [[79]] + [[79]]$times + [1] 0.00000 13.02458 + + [[79]]$NS + [1] 2 2 + + [[79]]$NI + [1] 1 0 + + [[79]]$NR + [1] 0 1 + + + [[80]] + [[80]]$times + [1] 0.000000 4.655717 10.847343 15.188912 38.570735 51.548959 + + [[80]]$NS + [1] 2 1 0 0 0 0 + + [[80]]$NI + [1] 1 2 3 2 1 0 + + [[80]]$NR + [1] 0 0 0 1 2 3 + + + [[81]] + [[81]]$times + [1] 0.000000 7.919139 12.774389 13.210280 20.037088 27.652380 + + [[81]]$NS + [1] 2 1 0 0 0 0 + + [[81]]$NI + [1] 1 2 3 2 1 0 + + [[81]]$NR + [1] 0 0 0 1 2 3 + + + [[82]] + [[82]]$times + [1] 0.000000 4.565727 4.640174 5.827227 8.181199 13.514984 + + [[82]]$NS + [1] 2 1 0 0 0 0 + + [[82]]$NI + [1] 1 2 3 2 1 0 + + [[82]]$NR + [1] 0 0 0 1 2 3 + + + [[83]] + [[83]]$times + [1] 0.0000000 0.4331829 + + [[83]]$NS + [1] 2 2 + + [[83]]$NI + [1] 1 0 + + [[83]]$NR + [1] 0 1 + + + [[84]] + [[84]]$times + [1] 0.0000000 0.5663187 + + [[84]]$NS + [1] 2 2 + + [[84]]$NI + [1] 1 0 + + [[84]]$NR + [1] 0 1 + + + [[85]] + [[85]]$times + [1] 0.000000 4.717821 7.368033 15.405952 20.251957 28.844191 + + [[85]]$NS + [1] 2 1 0 0 0 0 + + [[85]]$NI + [1] 1 2 3 2 1 0 + + [[85]]$NR + [1] 0 0 0 1 2 3 + + + [[86]] + [[86]]$times + [1] 0.00000 10.41346 13.17259 31.58865 35.49247 39.20284 + + [[86]]$NS + [1] 2 1 1 0 0 0 + + [[86]]$NI + [1] 1 2 1 2 1 0 + + [[86]]$NR + [1] 0 0 1 1 2 3 + + + [[87]] + [[87]]$times + [1] 0.000000 7.800903 + + [[87]]$NS + [1] 2 2 + + [[87]]$NI + [1] 1 0 + + [[87]]$NR + [1] 0 1 + + + [[88]] + [[88]]$times + [1] 0.000000 1.164975 2.214760 3.395779 4.269503 6.277390 + + [[88]]$NS + [1] 2 1 0 0 0 0 + + [[88]]$NI + [1] 1 2 3 2 1 0 + + [[88]]$NR + [1] 0 0 0 1 2 3 + + + [[89]] + [[89]]$times + [1] 0.000000 1.419246 5.241578 10.249121 + + [[89]]$NS + [1] 2 1 1 1 + + [[89]]$NI + [1] 1 2 1 0 + + [[89]]$NR + [1] 0 0 1 2 + + + [[90]] + [[90]]$times + [1] 0.000000 4.015171 + + [[90]]$NS + [1] 2 2 + + [[90]]$NI + [1] 1 0 + + [[90]]$NR + [1] 0 1 + + + [[91]] + [[91]]$times + [1] 0.00000 10.95119 10.95895 13.37237 15.94527 20.47069 + + [[91]]$NS + [1] 2 1 0 0 0 0 + + [[91]]$NI + [1] 1 2 3 2 1 0 + + [[91]]$NR + [1] 0 0 0 1 2 3 + + + [[92]] + [[92]]$times + [1] 0.000000 1.719506 + + [[92]]$NS + [1] 2 2 + + [[92]]$NI + [1] 1 0 + + [[92]]$NR + [1] 0 1 + + + [[93]] + [[93]]$times + [1] 0.00000 20.34997 23.10320 33.53507 37.61908 42.59392 + + [[93]]$NS + [1] 2 1 0 0 0 0 + + [[93]]$NI + [1] 1 2 3 2 1 0 + + [[93]]$NR + [1] 0 0 0 1 2 3 + + + [[94]] + [[94]]$times + [1] 0.000000 2.981562 4.220980 4.501876 5.930935 17.597979 + + [[94]]$NS + [1] 2 1 0 0 0 0 + + [[94]]$NI + [1] 1 2 3 2 1 0 + + [[94]]$NR + [1] 0 0 0 1 2 3 + + + [[95]] + [[95]]$times + [1] 0.0000000 0.8570038 6.2225289 7.4542303 + + [[95]]$NS + [1] 2 1 1 1 + + [[95]]$NI + [1] 1 2 1 0 + + [[95]]$NR + [1] 0 0 1 2 + + + [[96]] + [[96]]$times + [1] 0.00000 10.99346 + + [[96]]$NS + [1] 2 2 + + [[96]]$NI + [1] 1 0 + + [[96]]$NR + [1] 0 1 + + + [[97]] + [[97]]$times + [1] 0.000000 6.324172 10.943694 11.370294 + + [[97]]$NS + [1] 2 1 1 1 + + [[97]]$NI + [1] 1 2 1 0 + + [[97]]$NR + [1] 0 0 1 2 + + + [[98]] + [[98]]$times + [1] 0.00000000 0.07582625 1.04605163 3.19140611 3.57055288 9.94371399 + + [[98]]$NS + [1] 2 1 1 0 0 0 + + [[98]]$NI + [1] 1 2 1 2 1 0 + + [[98]]$NR + [1] 0 0 1 1 2 3 + + + [[99]] + [[99]]$times + [1] 0.000000 1.910419 + + [[99]]$NS + [1] 2 2 + + [[99]]$NI + [1] 1 0 + + [[99]]$NR + [1] 0 1 + + + [[100]] + [[100]]$times + [1] 0.000000 2.446835 + + [[100]]$NS + [1] 2 2 + + [[100]]$NI + [1] 1 0 + + [[100]]$NR + [1] 0 1 + + + attr(,"class") + [1] "sir" + +--- + + Code + sir_impl(g, beta = 0.1, gamma = 0.1, no.sim = 2) + Output + [[1]] + [[1]]$times + [1] 0.0000000 0.5059133 5.9903814 8.4444363 + + [[1]]$NS + [1] 2 1 1 1 + + [[1]]$NI + [1] 1 2 1 0 + + [[1]]$NR + [1] 0 0 1 2 + + + [[2]] + [[2]]$times + [1] 0.000000 4.481524 + + [[2]]$NS + [1] 2 2 + + [[2]]$NI + [1] 1 0 + + [[2]]$NR + [1] 0 1 + + + attr(,"class") + [1] "sir" + +# sir_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# convex_hull_2d_impl basic + + Code + convex_hull_2d_impl(matrix(1:6, ncol = 2)) + Output + $resverts + [1] 1 3 + + $rescoords + [,1] [,2] + [1,] 1 4 + [2,] 3 6 + + +# convex_hull_2d_impl errors + + Code + x + Condition + Warning in `convex_hull_2d_impl()`: + NAs introduced by coercion + Error in `convex_hull_2d_impl()`: + ! REAL() can only be applied to a 'numeric', not a 'character' + +# dim_select_impl basic + + Code + dim_select_impl(c(1, 2, 3)) + Output + [1] 1 + +# dim_select_impl errors + + Code + x + Condition + Error in `dim_select_impl()`: + ! At vendor/cigraph/src/misc/embedding.c:xx : Need at least one singular value for dimensionality selection, Invalid value + +# solve_lsap_impl basic + + Code + solve_lsap_impl(matrix(1:4, ncol = 2), n = 2) + Output + [1] 0 1 + +# solve_lsap_impl errors + + Code + x + Condition + Warning in `solve_lsap_impl()`: + NAs introduced by coercion + Error in `solve_lsap_impl()`: + ! REAL() can only be applied to a 'numeric', not a 'character' + +# find_cycle_impl basic + + Code + find_cycle_impl(g) + Output + $vertices + + 0/3 vertices: + + $edges + + 0/2 edges: + + +--- + + Code + find_cycle_impl(g, mode = "in") + Output + $vertices + + 0/3 vertices: + + $edges + + 0/2 edges: + + +# find_cycle_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# simple_cycles_impl basic + + Code + simple_cycles_impl(g) + Output + $vertices + list() + + $edges + list() + + +--- + + Code + simple_cycles_impl(g, mode = "in", min.cycle.length = 2, max.cycle.length = 3) + Output + $vertices + list() + + $edges + list() + + +# simple_cycles_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_eulerian_impl basic + + Code + is_eulerian_impl(g) + Output + $has_path + [1] TRUE + + $has_cycle + [1] FALSE + + +# is_eulerian_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# eulerian_path_impl basic + + Code + eulerian_path_impl(g) + Output + $epath + + 2/2 edges: + [1] 1--2 2--3 + + $vpath + + 3/3 vertices: + [1] 1 2 3 + + +# eulerian_path_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# eulerian_cycle_impl basic + + Code + x + Condition + Error in `eulerian_cycle_impl()`: + ! At vendor/cigraph/src/paths/eulerian.c:xx : The graph does not have an Eulerian cycle. Input problem has no solution + +--- + + Code + eulerian_cycle_impl(g2) + Output + $epath + + 4/4 edges: + [1] 1--2 2--3 3--4 1--4 + + $vpath + + 5/4 vertices: + [1] 1 2 3 4 1 + + +# eulerian_cycle_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# fundamental_cycles_impl basic + + Code + fundamental_cycles_impl(g, start = 1) + Output + list() + +--- + + Code + fundamental_cycles_impl(g, start = 1, bfs.cutoff = 2, weights = c(1, 2)) + Output + list() + +# fundamental_cycles_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# minimum_cycle_basis_impl basic + + Code + minimum_cycle_basis_impl(g) + Output + list() + +--- + + Code + minimum_cycle_basis_impl(g, bfs.cutoff = 2, complete = FALSE, use.cycle.order = FALSE, + weights = c(1, 2)) + Output + list() + +# minimum_cycle_basis_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_tree_impl basic + + Code + is_tree_impl(g) + Output + [1] TRUE + +--- + + Code + is_tree_impl(g, mode = "in", details = TRUE) + Output + $res + [1] TRUE + + $root + + 1/3 vertex: + [1] 1 + + +# is_tree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_forest_impl basic + + Code + is_forest_impl(g) + Output + [1] TRUE + +--- + + Code + is_forest_impl(g, mode = "in", details = TRUE) + Output + $res + [1] TRUE + + $roots + + 1/3 vertex: + [1] 1 + + +# is_forest_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# from_prufer_impl basic + + Code + from_prufer_impl(1:2) + Output + IGRAPH U--- 4 3 -- Tree from Prufer sequence + + attr: name (g/c), prufer (g/n) + + edges: + [1] 1--3 1--2 2--4 + +# from_prufer_impl errors + + Code + x + Condition + Warning in `from_prufer_impl()`: + NAs introduced by coercion + Error in `from_prufer_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# to_prufer_impl basic + + Code + to_prufer_impl(g) + Output + [1] 2 + +# to_prufer_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# tree_from_parent_vector_impl basic + + Code + tree_from_parent_vector_impl(c(-1, 1, 2, 3)) + Output + IGRAPH D--- 4 3 -- + + edges: + [1] 1->2 2->3 3->4 + +--- + + Code + tree_from_parent_vector_impl(c(-1, 1, 2, 3), type = "in") + Output + IGRAPH D--- 4 3 -- + + edges: + [1] 2->1 3->2 4->3 + +# tree_from_parent_vector_impl errors + + Code + x + Condition + Warning in `tree_from_parent_vector_impl()`: + NAs introduced by coercion + Error in `tree_from_parent_vector_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# is_complete_impl basic + + Code + is_complete_impl(g) + Output + [1] FALSE + +# is_complete_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# random_spanning_tree_impl basic + + Code + random_spanning_tree_impl(g, vid = 1) + Output + + 2/2 edges: + [1] 1--2 2--3 + +# random_spanning_tree_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# tree_game_impl basic + + Code + tree_game_impl(3) + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 2--3 1--2 + +--- + + Code + tree_game_impl(3, directed = TRUE, method = "lerw") + Output + IGRAPH D--- 3 2 -- + + edges: + [1] 3->1 1->2 + +# tree_game_impl errors + + Code + x + Condition + Warning in `tree_game_impl()`: + NAs introduced by coercion + Error in `tree_game_impl()`: + ! At rinterface_extra.c:xx : The value nan is not representable as an integer. Invalid value + +# vertex_coloring_greedy_impl basic + + Code + vertex_coloring_greedy_impl(g) + Output + [1] 2 1 2 + +--- + + Code + vertex_coloring_greedy_impl(g, heuristic = "dsatur") + Output + [1] 2 1 2 + +# vertex_coloring_greedy_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_vertex_coloring_impl basic + + Code + is_vertex_coloring_impl(g, types = c(1, 2, 3)) + Output + [1] TRUE + +# is_vertex_coloring_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_bipartite_coloring_impl basic + + Code + is_bipartite_coloring_impl(g, types = c(TRUE, FALSE, TRUE)) + Output + [1] TRUE + +# is_bipartite_coloring_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# is_edge_coloring_impl basic + + Code + is_edge_coloring_impl(g, types = c(1, 2)) + Output + [1] TRUE + +--- + + Code + is_edge_coloring_impl(g) + Output + [1] TRUE + +# is_edge_coloring_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# deterministic_optimal_imitation_impl basic + + Code + deterministic_optimal_imitation_impl(g, 1, quantities = c(1, 2, 3), strategies = c( + 1, 2, 3)) + Output + [1] 2 2 3 + +--- + + Code + deterministic_optimal_imitation_impl(g, 1, optimality = "minimum", quantities = c( + 1, 2, 3), strategies = c(1, 2, 3), mode = "in") + Output + [1] 1 2 3 + +# deterministic_optimal_imitation_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# moran_process_impl basic + + Code + moran_process_impl(g, weights = c(1, 1), quantities = c(1, 2, 3), strategies = c( + 1, 2, 3), mode = "in") + Output + $quantities + [1] 1 3 3 + + $strategies + [1] 1 3 3 + + +# moran_process_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# roulette_wheel_imitation_impl basic + + Code + roulette_wheel_imitation_impl(g, 1, TRUE, quantities = c(1, 2, 3), strategies = c( + 1, 2, 3)) + Output + [1] 1 2 3 + +--- + + Code + roulette_wheel_imitation_impl(g, 1, FALSE, quantities = c(1, 2, 3), strategies = c( + 1, 2, 3), mode = "in") + Output + [1] 3 2 3 + +# roulette_wheel_imitation_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# stochastic_imitation_impl basic + + Code + stochastic_imitation_impl(g, 1, algo = 1, quantities = c(1, 2, 3), strategies = c( + 1, 2, 3)) + Output + [1] 1 2 3 + +--- + + Code + stochastic_imitation_impl(g, 1, algo = 2, quantities = c(1, 2, 3), strategies = c( + 1, 2, 3), mode = "in") + Output + [1] 1 2 3 + +# stochastic_imitation_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# invalidate_cache_impl basic + + Code + invalidate_cache_impl(g) + Output + IGRAPH U--- 3 2 -- + + edges: + [1] 1--2 2--3 + +# invalidate_cache_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# vertex_path_from_edge_path_impl basic + + Code + vertex_path_from_edge_path_impl(g, start = 1, edge.path = c(1, 2)) + Output + + 3/3 vertices: + [1] 1 2 3 + +--- + + Code + vertex_path_from_edge_path_impl(g, start = 1, edge.path = c(1), mode = "in") + Output + + 2/3 vertices: + [1] 1 2 + +# vertex_path_from_edge_path_impl errors + + Code + x + Condition + Error in `ensure_igraph()`: + ! Must provide a graph object (provided `NULL`). + +# version_impl basic + + Code + version_impl_clean() + Output + [1] "0.10.16" + +# version_impl errors + + Code + x + Condition + Error in `version_impl()`: + ! unused argument ("invalid") + diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 03a7eabe582..6a97d3dbd17 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -43,3 +43,14 @@ expect_identical_graphs <- function(g1, g2, ...) { expect_not_identical_graphs <- function(g1, g2, ...) { expect_false(identical_graphs(g1, g2, ...)) } + +expect_snapshot_igraph_error <- function(x, ...) { + expect_snapshot( + x, + error = TRUE, + transform = function(y) { + gsub(":(\\d+)", ":xx", y) + }, + ... + ) +} diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R new file mode 100644 index 00000000000..9a27692368e --- /dev/null +++ b/tests/testthat/test-aaa-auto.R @@ -0,0 +1,5539 @@ +# 1. empty_impl +test_that("empty_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + + expect_snapshot(empty_impl()) + expect_snapshot(empty_impl(5, directed = FALSE)) +}) + +test_that("empty_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(empty_impl(-1)) +}) + +# 2. add_edges_impl + +test_that("add_edges_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- empty_impl(3) + expect_snapshot(add_edges_impl(g, c(0, 1, 1, 2))) +}) + +test_that("add_edges_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(add_edges_impl(NULL, c(1, 2))) +}) + +# 3. copy_impl + +test_that("copy_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- empty_impl(2) + expect_snapshot(copy_impl(g)) +}) + +test_that("copy_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(copy_impl(NULL)) +}) + +# 4. delete_vertices_idx_impl + +test_that("delete_vertices_idx_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- empty_impl(3) + expect_snapshot(delete_vertices_idx_impl(g, 1)) +}) + +test_that("delete_vertices_idx_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(delete_vertices_idx_impl(NULL, 1)) +}) + +# 5. vcount_impl + +test_that("vcount_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- empty_impl(4) + expect_snapshot(vcount_impl(g)) +}) + +test_that("vcount_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(vcount_impl(NULL)) +}) + +# 6. degree_impl + +test_that("degree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- empty_impl(3) + expect_snapshot(degree_impl(g)) + expect_snapshot(degree_impl(g, mode = "in")) +}) + +test_that("degree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(degree_impl(NULL)) +}) + +# 7. get_all_eids_between_impl + +test_that("get_all_eids_between_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- empty_impl(2) + expect_snapshot(get_all_eids_between_impl(g, 1, 2)) +}) + +test_that("get_all_eids_between_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_all_eids_between_impl(NULL, 1, 2)) +}) + +# 8. wheel_impl + +test_that("wheel_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(wheel_impl(5)) + expect_snapshot(wheel_impl(5, mode = "in", center = 2)) +}) + +test_that("wheel_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(wheel_impl(-1)) +}) + +# 9. hypercube_impl + +test_that("hypercube_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(hypercube_impl(3)) + expect_snapshot(hypercube_impl(3, directed = TRUE)) +}) + +test_that("hypercube_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hypercube_impl(10000)) +}) + +# 10. square_lattice_impl + +test_that("square_lattice_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(square_lattice_impl(c(2, 2))) + expect_snapshot(square_lattice_impl( + c(2, 2), + nei = 2, + directed = TRUE, + mutual = TRUE, + periodic = c(TRUE, TRUE) + )) +}) + +test_that("square_lattice_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(square_lattice_impl(-1)) +}) + +# 11. triangular_lattice_impl + +test_that("triangular_lattice_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(triangular_lattice_impl(c(2, 2))) + expect_snapshot(triangular_lattice_impl( + c(2, 2), + directed = TRUE, + mutual = TRUE + )) +}) + +test_that("triangular_lattice_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(triangular_lattice_impl(-1)) +}) + +# 12. path_graph_impl + +test_that("path_graph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(path_graph_impl(5)) + expect_snapshot(path_graph_impl(5, directed = TRUE, mutual = TRUE)) +}) + +test_that("path_graph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(path_graph_impl(-1)) +}) + +# 13. cycle_graph_impl + +test_that("cycle_graph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(cycle_graph_impl(5)) + expect_snapshot(cycle_graph_impl(5, directed = TRUE, mutual = TRUE)) +}) + +test_that("cycle_graph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(cycle_graph_impl(-1)) +}) + +# 14. symmetric_tree_impl + +test_that("symmetric_tree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(symmetric_tree_impl(3)) + expect_snapshot(symmetric_tree_impl(3, type = "in")) +}) + +test_that("symmetric_tree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(symmetric_tree_impl(-1)) +}) + +# 15. regular_tree_impl + +test_that("regular_tree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(regular_tree_impl(2)) + expect_snapshot(regular_tree_impl(2, k = 4, type = "in")) +}) + +test_that("regular_tree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(regular_tree_impl(-1)) +}) + +# 16. full_citation_impl + +test_that("full_citation_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(full_citation_impl(5)) + expect_snapshot(full_citation_impl(5, directed = FALSE)) +}) + +test_that("full_citation_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(full_citation_impl(-1)) +}) + +# 17. atlas_impl + +test_that("atlas_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(atlas_impl(0)) + expect_snapshot(atlas_impl(5)) +}) + +test_that("atlas_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(atlas_impl(-1)) +}) + +# 18. extended_chordal_ring_impl + +test_that("extended_chordal_ring_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(extended_chordal_ring_impl(5, matrix(c(1, 2)))) + expect_snapshot(extended_chordal_ring_impl( + 5, + matrix(c(1, 2)), + directed = TRUE + )) +}) + +test_that("extended_chordal_ring_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(extended_chordal_ring_impl(-1, matrix(c(1, 2)))) +}) + +# 19. graph_power_impl + +test_that("graph_power_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(5) + expect_snapshot(graph_power_impl(g, 2)) + expect_snapshot(graph_power_impl(g, 2, directed = TRUE)) +}) + +test_that("graph_power_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(graph_power_impl(NULL, 2)) +}) + +# 20. linegraph_impl + +test_that("linegraph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(5) + expect_snapshot(linegraph_impl(g)) +}) + +test_that("linegraph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(linegraph_impl(NULL)) +}) + +# 21. de_bruijn_impl +test_that("de_bruijn_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(de_bruijn_impl(2, 3)) +}) +test_that("de_bruijn_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(de_bruijn_impl(-1, 3)) +}) + +# 22. kautz_impl +test_that("kautz_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(kautz_impl(2, 3)) +}) +test_that("kautz_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(kautz_impl(-1, 3)) +}) + +# 23. lcf_vector_impl +test_that("lcf_vector_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(lcf_vector_impl(10, c(3, -3, 4), 2)) +}) +test_that("lcf_vector_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(lcf_vector_impl(-1, c(3, -3, 4), 2)) +}) + +# 24. mycielski_graph_impl +test_that("mycielski_graph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(mycielski_graph_impl(3)) +}) +test_that("mycielski_graph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(mycielski_graph_impl(-1)) +}) + +# 25. adjlist_impl +test_that("adjlist_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(adjlist_impl(list(c(2, 3), c(1), c(1)), mode = "out")) +}) +test_that("adjlist_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(adjlist_impl(-1, mode = "out")) +}) + +# 26. full_bipartite_impl +test_that("full_bipartite_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(full_bipartite_impl(2, 3)) + expect_snapshot(full_bipartite_impl(2, 3, directed = TRUE, mode = "in")) +}) +test_that("full_bipartite_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(full_bipartite_impl(-1, 3)) +}) + +# 27. full_multipartite_impl +test_that("full_multipartite_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(full_multipartite_impl(c(2, 3, 4))) + expect_snapshot(full_multipartite_impl( + c(2, 3, 4), + directed = TRUE, + mode = "in" + )) +}) +test_that("full_multipartite_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(full_multipartite_impl(-1)) +}) + +# 28. realize_degree_sequence_impl +test_that("realize_degree_sequence_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(realize_degree_sequence_impl(c(2, 2, 2))) + expect_snapshot(realize_degree_sequence_impl( + c(2, 2, 2), + c(2, 2, 2), + allowed.edge.types = "simple", + method = "largest" + )) +}) +test_that("realize_degree_sequence_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(realize_degree_sequence_impl(-1)) +}) + +# 29. realize_bipartite_degree_sequence_impl +test_that("realize_bipartite_degree_sequence_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(realize_bipartite_degree_sequence_impl(c(2, 2), c(2, 2))) + expect_snapshot(realize_bipartite_degree_sequence_impl( + c(2, 2), + c(2, 2), + allowed.edge.types = "loops", + method = "largest" + )) +}) +test_that("realize_bipartite_degree_sequence_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + realize_bipartite_degree_sequence_impl(-1, c(2, 2)) + ) +}) + +# 30. circulant_impl +test_that("circulant_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(circulant_impl(5, c(1, 2))) + expect_snapshot(circulant_impl(5, c(1, 2), directed = TRUE)) +}) +test_that("circulant_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(circulant_impl(-1, c(1, 2))) +}) + +# 31. generalized_petersen_impl +test_that("generalized_petersen_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(generalized_petersen_impl(5, 2)) +}) +test_that("generalized_petersen_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(generalized_petersen_impl(-1, 2)) +}) + +# 32. turan_impl +test_that("turan_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(turan_impl(5, 2)) +}) +test_that("turan_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(turan_impl(-1, 2)) +}) + +# 33. erdos_renyi_game_gnp_impl +test_that("erdos_renyi_game_gnp_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(erdos_renyi_game_gnp_impl(5, 0.5)) + expect_snapshot(erdos_renyi_game_gnp_impl( + 5, + 0.5, + directed = TRUE, + loops = TRUE + )) +}) +test_that("erdos_renyi_game_gnp_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(erdos_renyi_game_gnp_impl(-1, 0.5)) +}) + +# 34. erdos_renyi_game_gnm_impl +test_that("erdos_renyi_game_gnm_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(erdos_renyi_game_gnm_impl(5, 3)) + expect_snapshot(erdos_renyi_game_gnm_impl( + 5, + 3, + directed = TRUE, + loops = TRUE + )) +}) +test_that("erdos_renyi_game_gnm_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(erdos_renyi_game_gnm_impl(-1, 3)) +}) + +# 35. growing_random_game_impl +test_that("growing_random_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(growing_random_game_impl(5, 2)) + expect_snapshot(growing_random_game_impl( + 5, + 2, + directed = FALSE, + citation = TRUE + )) +}) +test_that("growing_random_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(growing_random_game_impl(-1, 2)) +}) + +# 36. preference_game_impl +test_that("preference_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(preference_game_impl( + 5, + 2, + c(0.5, 0.5), + FALSE, + matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2) + )) +}) +test_that("preference_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + preference_game_impl( + -1, + 2, + c(0.5, 0.5), + FALSE, + matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2) + ) + ) +}) + +# 37. asymmetric_preference_game_impl +test_that("asymmetric_preference_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(asymmetric_preference_game_impl( + 5, + 2, + 2, + matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2), + matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2) + )) +}) +test_that("asymmetric_preference_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + asymmetric_preference_game_impl( + -1, + 2, + 2, + matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2), + matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2) + ) + ) +}) + +# 38. rewire_edges_impl +test_that("rewire_edges_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(5) + expect_snapshot(rewire_edges_impl(g, 0.5)) +}) +test_that("rewire_edges_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(rewire_edges_impl(NULL, 0.5)) +}) + +# 39. rewire_directed_edges_impl +test_that("rewire_directed_edges_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(5, directed = TRUE) + expect_snapshot(rewire_directed_edges_impl(g, 0.5)) +}) +test_that("rewire_directed_edges_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(rewire_directed_edges_impl(NULL, 0.5)) +}) + +# 40. forest_fire_game_impl +test_that("forest_fire_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(forest_fire_game_impl(5, 0.5)) + expect_snapshot(forest_fire_game_impl( + 5, + 0.5, + bw.factor = 0.2, + ambs = 2, + directed = FALSE + )) +}) +test_that("forest_fire_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(forest_fire_game_impl(-1, 0.5)) +}) + +# 41. simple_interconnected_islands_game_impl +test_that("simple_interconnected_islands_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(simple_interconnected_islands_game_impl(2, 3, 0.5, 1)) +}) +test_that("simple_interconnected_islands_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + simple_interconnected_islands_game_impl(-1, 3, 0.5, 1) + ) +}) + +# 42. chung_lu_game_impl +test_that("chung_lu_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(chung_lu_game_impl(c(2, 2, 2))) + expect_snapshot(chung_lu_game_impl( + c(1, 2, 3), + c(1, 2, 3), + loops = FALSE, + variant = "maxent" + )) +}) +test_that("chung_lu_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(chung_lu_game_impl(-1)) +}) + +# 43. static_fitness_game_impl +test_that("static_fitness_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(static_fitness_game_impl(3, c(1, 2, 3))) + expect_snapshot(static_fitness_game_impl( + 3, + c(1, 2, 3), + c(1, 2, 3), + loops = TRUE, + multiple = TRUE + )) +}) +test_that("static_fitness_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(static_fitness_game_impl(-1, c(1, 2, 3))) +}) + +# 44. static_power_law_game_impl +test_that("static_power_law_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(static_power_law_game_impl(5, 4, 2.5)) + expect_snapshot(static_power_law_game_impl( + 5, + 4, + 2.5, + exponent.in = 2, + loops = TRUE, + multiple = TRUE, + finite.size.correction = FALSE + )) +}) +test_that("static_power_law_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(static_power_law_game_impl(-1, 4, 2.5)) +}) + +# 45. k_regular_game_impl + +test_that("k_regular_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(k_regular_game_impl(5, 2)) + expect_snapshot(k_regular_game_impl(5, 2, directed = TRUE, multiple = TRUE)) +}) + +test_that("k_regular_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(k_regular_game_impl(-1, 2)) +}) + +# 46. sbm_game_impl + +test_that("sbm_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(sbm_game_impl(5, matrix(0.5, 2, 2), c(2, 3))) + expect_snapshot(sbm_game_impl( + 5, + matrix(0.5, 2, 2), + c(2, 3), + directed = TRUE, + loops = TRUE + )) +}) + +test_that("sbm_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(sbm_game_impl(-1, matrix(0.5, 2, 2), c(2, 3))) +}) + +# 47. hsbm_game_impl + +test_that("hsbm_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(hsbm_game_impl(6, 2, c(0.5, 0.5), matrix(1, 2, 2), 0.5)) +}) + +test_that("hsbm_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + hsbm_game_impl(-1, 2, 0.5, matrix(1, 2, 2), 0.5) + ) +}) + +# 48. hsbm_list_game_impl + +test_that("hsbm_list_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + C <- matrix( + c( + 1, + 3 / 4, + 0, + 3 / 4, + 0, + 3 / 4, + 0, + 3 / 4, + 3 / 4 + ), + nrow = 3 + ) + expect_snapshot(hsbm_list_game_impl( + 100, + list(50, 50), + rho = list(c(3, 3, 4) / 10), + C = list(C), + p = 1 / 20 + )) +}) + +test_that("hsbm_list_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + hsbm_list_game_impl( + -1, + c(2, 3), + list(0.5, 0.5), + list(matrix(1, 2, 2), matrix(1, 2, 2)), + 0.5 + ) + ) +}) + +# 49. correlated_game_impl + +test_that("correlated_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(5) + expect_snapshot(correlated_game_impl(g, 0.5)) +}) + +test_that("correlated_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(correlated_game_impl(NULL, 0.5)) +}) + +# 50. correlated_pair_game_impl + +test_that("correlated_pair_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(correlated_pair_game_impl(5, 0.5, 0.5)) + expect_snapshot(correlated_pair_game_impl(5, 0.5, 0.5, directed = TRUE)) +}) + +test_that("correlated_pair_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(correlated_pair_game_impl(-1, 0.5, 0.5)) +}) + +# 51. dot_product_game_impl + +test_that("dot_product_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(dot_product_game_impl(matrix(0.5, 5, 2))) + expect_snapshot(dot_product_game_impl(matrix(0.5, 5, 2), directed = TRUE)) +}) + +test_that("dot_product_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(dot_product_game_impl(NULL)) +}) + +# 52. sample_sphere_surface_impl + +test_that("sample_sphere_surface_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(sample_sphere_surface_impl(3, 5)) + expect_snapshot(sample_sphere_surface_impl( + 3, + 5, + radius = 2, + positive = FALSE + )) +}) + +test_that("sample_sphere_surface_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(sample_sphere_surface_impl(-1, 5)) +}) + +# 53. sample_sphere_volume_impl + +test_that("sample_sphere_volume_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(sample_sphere_volume_impl(3, 5)) + expect_snapshot(sample_sphere_volume_impl(3, 5, radius = 2, positive = FALSE)) +}) + +test_that("sample_sphere_volume_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(sample_sphere_volume_impl(-1, 5)) +}) + +# 54. sample_dirichlet_impl + +test_that("sample_dirichlet_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(sample_dirichlet_impl(5, c(1, 1, 1))) +}) + +test_that("sample_dirichlet_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(sample_dirichlet_impl(-1, c(1, 1, 1))) +}) + +# 55. are_adjacent_impl + +test_that("are_adjacent_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(are_adjacent_impl(g, 1, 2)) +}) + +test_that("are_adjacent_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(are_adjacent_impl(NULL, 1, 2)) +}) + +# 56. closeness_impl + +test_that("closeness_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(closeness_impl(g)) + expect_snapshot(closeness_impl(g, mode = "in", normalized = TRUE)) +}) + +test_that("closeness_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(closeness_impl(NULL)) +}) + +# 57. closeness_cutoff_impl + +test_that("closeness_cutoff_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(closeness_cutoff_impl(g, cutoff = 2)) + expect_snapshot(closeness_cutoff_impl( + g, + mode = "in", + normalized = TRUE, + cutoff = 1 + )) +}) + +test_that("closeness_cutoff_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(closeness_cutoff_impl(NULL)) +}) + +# 58. get_shortest_path_impl + +test_that("get_shortest_path_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_shortest_path_impl(g, 1, 3)) +}) + +test_that("get_shortest_path_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_shortest_path_impl(NULL, 1, 3)) +}) + +# 59. get_shortest_path_bellman_ford_impl + +test_that("get_shortest_path_bellman_ford_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_shortest_path_bellman_ford_impl(g, 1, 3)) +}) + +test_that("get_shortest_path_bellman_ford_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_shortest_path_bellman_ford_impl(NULL, 1, 3)) +}) + +# 60. get_shortest_path_dijkstra_impl + +test_that("get_shortest_path_dijkstra_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_shortest_path_dijkstra_impl(g, 1, 3)) +}) + +test_that("get_shortest_path_dijkstra_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_shortest_path_dijkstra_impl(NULL, 1, 3)) +}) + +# 61. get_all_shortest_paths_impl + +test_that("get_all_shortest_paths_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_all_shortest_paths_impl(g, 1, 3)) +}) + +test_that("get_all_shortest_paths_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_all_shortest_paths_impl(NULL, 1, 3)) +}) + +# 62. get_all_shortest_paths_dijkstra_impl + +test_that("get_all_shortest_paths_dijkstra_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_all_shortest_paths_dijkstra_impl(g, 1, 3)) +}) + +test_that("get_all_shortest_paths_dijkstra_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + get_all_shortest_paths_dijkstra_impl(NULL, 1, 3) + ) +}) + +# 63. voronoi_impl + +test_that("voronoi_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(voronoi_impl(g, 1)) + expect_snapshot(voronoi_impl(g, 1, mode = "in", tiebreaker = "first")) +}) + +test_that("voronoi_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(voronoi_impl(NULL, 1)) +}) + +# 64. get_all_simple_paths_impl + +test_that("get_all_simple_paths_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_all_simple_paths_impl(g, 1, 3)) +}) + +test_that("get_all_simple_paths_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_all_simple_paths_impl(NULL, 1, 3)) +}) + +# 65. get_k_shortest_paths_impl + +test_that("get_k_shortest_paths_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_k_shortest_paths_impl(g, 1, 3, k = 2)) +}) + +test_that("get_k_shortest_paths_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_k_shortest_paths_impl(NULL, 1, 3, k = 2)) +}) + +# 66. get_widest_path_impl + +test_that("get_widest_path_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_widest_path_impl(g, 1, 3, weights = c(1, 2))) +}) + +test_that("get_widest_path_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_widest_path_impl(NULL, 1, 3)) +}) + +# 67. get_widest_paths_impl + +test_that("get_widest_paths_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_widest_paths_impl(g, 1, 3, weights = c(1, 2))) +}) + +test_that("get_widest_paths_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_widest_paths_impl(NULL, 1, 3)) +}) + +# 70. spanner_impl + +test_that("spanner_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(spanner_impl(g, 2)) +}) + +test_that("spanner_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(spanner_impl(NULL, 2)) +}) + +# 71. betweenness_cutoff_impl + +test_that("betweenness_cutoff_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(betweenness_cutoff_impl(g, cutoff = 2)) +}) + +test_that("betweenness_cutoff_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(betweenness_cutoff_impl(NULL, cutoff = 2)) +}) + +# 72. betweenness_subset_impl + +test_that("betweenness_subset_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(betweenness_subset_impl(g)) +}) + +test_that("betweenness_subset_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(betweenness_subset_impl(NULL)) +}) + +# 73. edge_betweenness_impl + +test_that("edge_betweenness_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(edge_betweenness_impl(g)) +}) + +test_that("edge_betweenness_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(edge_betweenness_impl(NULL)) +}) + +# 74. edge_betweenness_cutoff_impl + +test_that("edge_betweenness_cutoff_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(edge_betweenness_cutoff_impl(g, cutoff = 2)) +}) + +test_that("edge_betweenness_cutoff_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(edge_betweenness_cutoff_impl(NULL, cutoff = 2)) +}) + +# 75. edge_betweenness_subset_impl + +test_that("edge_betweenness_subset_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(edge_betweenness_subset_impl(g)) +}) + +test_that("edge_betweenness_subset_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(edge_betweenness_subset_impl(NULL)) +}) + +# 76. harmonic_centrality_cutoff_impl + +test_that("harmonic_centrality_cutoff_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(harmonic_centrality_cutoff_impl(g, cutoff = 2)) +}) + +test_that("harmonic_centrality_cutoff_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + harmonic_centrality_cutoff_impl(NULL, cutoff = 2) + ) +}) + +# 77. personalized_pagerank_impl + +test_that("personalized_pagerank_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(personalized_pagerank_impl(g)) + expect_snapshot(personalized_pagerank_impl(g, algo = "arpack", damping = 0.9)) +}) + +test_that("personalized_pagerank_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(personalized_pagerank_impl(NULL)) +}) + +# 78. personalized_pagerank_vs_impl + +test_that("personalized_pagerank_vs_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(personalized_pagerank_vs_impl(g, reset.vids = 1)) + expect_snapshot(personalized_pagerank_vs_impl( + g, + algo = "arpack", + reset.vids = 1, + details = TRUE + )) +}) + +test_that("personalized_pagerank_vs_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + personalized_pagerank_vs_impl(NULL, reset.vids = 1) + ) +}) + +# 79. induced_subgraph_impl + +test_that("induced_subgraph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(induced_subgraph_impl(g, 1:2)) +}) + +test_that("induced_subgraph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(induced_subgraph_impl(NULL, 1:2)) +}) + +# 80. subgraph_from_edges_impl + +test_that("subgraph_from_edges_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(subgraph_from_edges_impl(g, 1)) +}) + +test_that("subgraph_from_edges_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(subgraph_from_edges_impl(NULL, 1)) +}) + +# 81. reverse_edges_impl + +test_that("reverse_edges_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(reverse_edges_impl(g)) +}) + +test_that("reverse_edges_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(reverse_edges_impl(NULL)) +}) + +# and much more halucination before... +# 91-96: halucination of get_shortest_path_* +# 97-100: halucination of get_widest_path_cutoff_impl,get_widest_paths_cutoff_impl, widest_path_widths_dijkstra_cutoff_impl, widest_path_widths_floyd_warshall_cutoff_impl + +# 101. path_length_hist_impl + +test_that("path_length_hist_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(path_length_hist_impl(g)) + expect_snapshot(path_length_hist_impl(g, directed = FALSE)) +}) + +test_that("path_length_hist_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(path_length_hist_impl(NULL)) +}) + +# 102. simplify_impl + +test_that("simplify_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(simplify_impl(g)) + expect_snapshot(simplify_impl( + g, + remove.multiple = FALSE, + remove.loops = FALSE + )) +}) + +test_that("simplify_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(simplify_impl(NULL)) +}) + +# 103. transitivity_undirected_impl + +test_that("transitivity_undirected_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(transitivity_undirected_impl(g)) + expect_snapshot(transitivity_undirected_impl(g, mode = "zero")) +}) + +test_that("transitivity_undirected_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(transitivity_undirected_impl(NULL)) +}) + +# 104. transitivity_local_undirected_impl + +test_that("transitivity_local_undirected_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(transitivity_local_undirected_impl(g)) + expect_snapshot(transitivity_local_undirected_impl(g, mode = "zero")) +}) + +test_that("transitivity_local_undirected_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(transitivity_local_undirected_impl(NULL)) +}) + +# 105. transitivity_avglocal_undirected_impl + +test_that("transitivity_avglocal_undirected_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(transitivity_avglocal_undirected_impl(g)) + expect_snapshot(transitivity_avglocal_undirected_impl(g, mode = "zero")) +}) + +test_that("transitivity_avglocal_undirected_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(transitivity_avglocal_undirected_impl(NULL)) +}) + +# 106. transitivity_barrat_impl + +test_that("transitivity_barrat_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(transitivity_barrat_impl(g)) + expect_snapshot(transitivity_barrat_impl(g, mode = "zero")) +}) + +test_that("transitivity_barrat_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(transitivity_barrat_impl(NULL)) +}) + +# 107. ecc_impl + +test_that("ecc_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(4) + expect_snapshot(ecc_impl(g)) + expect_snapshot(ecc_impl(g, k = 3, offset = TRUE, normalize = FALSE)) +}) + +test_that("ecc_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(ecc_impl(NULL)) +}) + +# 108. reciprocity_impl + +test_that("reciprocity_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(reciprocity_impl(g)) + expect_snapshot(reciprocity_impl(g, ignore.loops = FALSE, mode = "ratio")) +}) + +test_that("reciprocity_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(reciprocity_impl(NULL)) +}) + +# 109. maxdegree_impl + +test_that("maxdegree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(maxdegree_impl(g)) + expect_snapshot(maxdegree_impl(g, mode = "in", loops = FALSE)) +}) + +test_that("maxdegree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(maxdegree_impl(NULL)) +}) + +# 110. density_impl + +test_that("density_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(density_impl(g)) + expect_snapshot(density_impl(g, loops = TRUE)) +}) + +test_that("density_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(density_impl(NULL)) +}) + +# 111. mean_degree_impl + +test_that("mean_degree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(mean_degree_impl(g)) + expect_snapshot(mean_degree_impl(g, loops = FALSE)) +}) + +test_that("mean_degree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(mean_degree_impl(NULL)) +}) + +# 112. feedback_arc_set_impl + +test_that("feedback_arc_set_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(feedback_arc_set_impl(g)) + expect_snapshot(feedback_arc_set_impl(g, algo = "exact_ip")) +}) + +test_that("feedback_arc_set_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(feedback_arc_set_impl(NULL)) +}) + +# 113. feedback_vertex_set_impl + +test_that("feedback_vertex_set_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(feedback_vertex_set_impl(g)) +}) + +test_that("feedback_vertex_set_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(feedback_vertex_set_impl(NULL)) +}) + +# 114. is_loop_impl + +test_that("is_loop_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_loop_impl(g)) +}) + +test_that("is_loop_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_loop_impl(NULL)) +}) + +# 115. is_dag_impl + +test_that("is_dag_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_dag_impl(g)) +}) + +test_that("is_dag_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_dag_impl(NULL)) +}) + +# 116. is_acyclic_impl + +test_that("is_acyclic_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_acyclic_impl(g)) +}) + +test_that("is_acyclic_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_acyclic_impl(NULL)) +}) + +# 117. is_simple_impl + +test_that("is_simple_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_simple_impl(g)) +}) + +test_that("is_simple_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_simple_impl(NULL)) +}) + +# 118. is_multiple_impl + +test_that("is_multiple_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_multiple_impl(g)) +}) + +test_that("is_multiple_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_multiple_impl(NULL)) +}) + +# 119. has_loop_impl + +test_that("has_loop_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(has_loop_impl(g)) +}) + +test_that("has_loop_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(has_loop_impl(NULL)) +}) + +# 120. has_multiple_impl + +test_that("has_multiple_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(has_multiple_impl(g)) +}) + +test_that("has_multiple_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(has_multiple_impl(NULL)) +}) + +# 121. count_loops_impl + +test_that("count_loops_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(count_loops_impl(g)) +}) + +test_that("count_loops_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(count_loops_impl(NULL)) +}) + +# 122. count_multiple_impl + +test_that("count_multiple_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(count_multiple_impl(g)) +}) + +test_that("count_multiple_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(count_multiple_impl(NULL)) +}) + +# 123. is_perfect_impl + +test_that("is_perfect_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_perfect_impl(g)) +}) + +test_that("is_perfect_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_perfect_impl(NULL)) +}) + +# 124. eigenvector_centrality_impl + +test_that("eigenvector_centrality_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(eigenvector_centrality_impl(g)) + expect_snapshot(eigenvector_centrality_impl( + g, + directed = TRUE, + scale = FALSE + )) +}) + +test_that("eigenvector_centrality_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(eigenvector_centrality_impl(NULL)) +}) + +# 125. hub_and_authority_scores_impl + +test_that("hub_and_authority_scores_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(5) + expect_snapshot(hub_and_authority_scores_impl(g)) + expect_snapshot(hub_and_authority_scores_impl(g, scale = FALSE)) +}) + +test_that("hub_and_authority_scores_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hub_and_authority_scores_impl(NULL)) +}) + +# 126. unfold_tree_impl + +test_that("unfold_tree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(unfold_tree_impl(g, roots = 1)) + expect_snapshot(unfold_tree_impl(g, mode = "in", roots = 1)) +}) + +test_that("unfold_tree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(unfold_tree_impl(NULL, roots = 1)) +}) + +# 127. is_mutual_impl + +test_that("is_mutual_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_mutual_impl(g)) + expect_snapshot(is_mutual_impl(g, loops = FALSE)) +}) + +test_that("is_mutual_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_mutual_impl(NULL)) +}) + +# 128. has_mutual_impl + +test_that("has_mutual_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(has_mutual_impl(g)) + expect_snapshot(has_mutual_impl(g, loops = FALSE)) +}) + +test_that("has_mutual_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(has_mutual_impl(NULL)) +}) + +# 129. maximum_cardinality_search_impl + +test_that("maximum_cardinality_search_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(maximum_cardinality_search_impl(g)) +}) + +test_that("maximum_cardinality_search_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(maximum_cardinality_search_impl(NULL)) +}) + +# 130. avg_nearest_neighbor_degree_impl + +test_that("avg_nearest_neighbor_degree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(avg_nearest_neighbor_degree_impl(g)) + expect_snapshot(avg_nearest_neighbor_degree_impl( + g, + mode = "in", + neighbor.degree.mode = "out" + )) +}) + +test_that("avg_nearest_neighbor_degree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(avg_nearest_neighbor_degree_impl(NULL)) +}) + +# 131. degree_correlation_vector_impl + +test_that("degree_correlation_vector_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(degree_correlation_vector_impl(g)) + expect_snapshot(degree_correlation_vector_impl( + g, + from.mode = "in", + to.mode = "out", + directed.neighbors = FALSE + )) +}) + +test_that("degree_correlation_vector_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(degree_correlation_vector_impl(NULL)) +}) + +# 132. rich_club_sequence_impl + +test_that("rich_club_sequence_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(rich_club_sequence_impl(g, vertex.order = 1:3)) + expect_snapshot(rich_club_sequence_impl( + g, + vertex.order = 1:3, + normalized = FALSE, + loops = TRUE, + directed = FALSE + )) +}) + +test_that("rich_club_sequence_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + rich_club_sequence_impl(NULL, vertex.order = 1:3) + ) +}) + +# 133. strength_impl + +test_that("strength_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(strength_impl(g)) + expect_snapshot(strength_impl(g, mode = "in", loops = FALSE)) +}) + +test_that("strength_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(strength_impl(NULL)) +}) + +# 134. centralization_impl + +test_that("centralization_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(centralization_impl(c(1, 2, 3))) + expect_snapshot(centralization_impl( + c(1, 2, 3), + theoretical.max = 2, + normalized = FALSE + )) +}) + +test_that("centralization_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(centralization_impl(package_version("1.2.3"))) +}) + +# 135. centralization_degree_impl + +test_that("centralization_degree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(centralization_degree_impl(g)) + expect_snapshot(centralization_degree_impl( + g, + mode = "in", + loops = FALSE, + normalized = FALSE + )) +}) + +test_that("centralization_degree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(centralization_degree_impl(NULL)) +}) + +# 136. centralization_degree_tmax_impl + +test_that("centralization_degree_tmax_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(centralization_degree_tmax_impl(nodes = 3, loops = TRUE)) + expect_snapshot(centralization_degree_tmax_impl( + nodes = 3, + mode = "in", + loops = FALSE + )) +}) + +test_that("centralization_degree_tmax_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + centralization_degree_tmax_impl(nodes = -1, loops = TRUE) + ) +}) + +# 137. centralization_betweenness_impl + +test_that("centralization_betweenness_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(centralization_betweenness_impl(g)) + expect_snapshot(centralization_betweenness_impl( + g, + directed = FALSE, + normalized = FALSE + )) +}) + +test_that("centralization_betweenness_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(centralization_betweenness_impl(NULL)) +}) + +# 138. centralization_betweenness_tmax_impl + +test_that("centralization_betweenness_tmax_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(centralization_betweenness_tmax_impl( + nodes = 3, + directed = TRUE + )) + expect_snapshot(centralization_betweenness_tmax_impl( + nodes = 3, + directed = FALSE + )) +}) + +test_that("centralization_betweenness_tmax_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + centralization_betweenness_tmax_impl(nodes = -1, directed = TRUE) + ) +}) + +# 139. centralization_closeness_impl + +test_that("centralization_closeness_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(centralization_closeness_impl(g)) + expect_snapshot(centralization_closeness_impl( + g, + mode = "in", + normalized = FALSE + )) +}) + +test_that("centralization_closeness_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(centralization_closeness_impl(NULL)) +}) + +# 140. centralization_closeness_tmax_impl + +test_that("centralization_closeness_tmax_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(centralization_closeness_tmax_impl(nodes = 3)) + expect_snapshot(centralization_closeness_tmax_impl(nodes = 3, mode = "in")) +}) + +test_that("centralization_closeness_tmax_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(centralization_closeness_tmax_impl(nodes = -1)) +}) + +# 141. centralization_eigenvector_centrality_impl + +test_that("centralization_eigenvector_centrality_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(centralization_eigenvector_centrality_impl(g)) + expect_snapshot(centralization_eigenvector_centrality_impl( + g, + directed = TRUE, + normalized = FALSE + )) +}) + +test_that("centralization_eigenvector_centrality_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + centralization_eigenvector_centrality_impl(NULL) + ) +}) + +# 142. centralization_eigenvector_centrality_tmax_impl + +test_that("centralization_eigenvector_centrality_tmax_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(centralization_eigenvector_centrality_tmax_impl(nodes = 3)) + expect_snapshot(centralization_eigenvector_centrality_tmax_impl( + nodes = 3, + directed = TRUE + )) +}) + +test_that("centralization_eigenvector_centrality_tmax_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + centralization_eigenvector_centrality_tmax_impl(nodes = -1) + ) +}) + +# 143. assortativity_nominal_impl + +test_that("assortativity_nominal_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(assortativity_nominal_impl(g, c(1, 2, 1))) + expect_snapshot(assortativity_nominal_impl( + g, + c(1, 2, 1), + directed = FALSE, + normalized = FALSE + )) +}) + +test_that("assortativity_nominal_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(assortativity_nominal_impl(NULL, c(1, 2, 1))) +}) + +# 144. assortativity_impl + +test_that("assortativity_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(assortativity_impl(g, c(1, 2, 1))) + expect_snapshot(assortativity_impl( + g, + c(1, 2, 1), + directed = FALSE, + normalized = FALSE + )) +}) + +test_that("assortativity_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(assortativity_impl(NULL, c(1, 2, 1))) +}) + +# 145. assortativity_degree_impl + +test_that("assortativity_degree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(assortativity_degree_impl(g)) + expect_snapshot(assortativity_degree_impl(g, directed = FALSE)) +}) + +test_that("assortativity_degree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(assortativity_degree_impl(NULL)) +}) + +# 146. joint_degree_matrix_impl + +test_that("joint_degree_matrix_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(joint_degree_matrix_impl(g)) + expect_snapshot(joint_degree_matrix_impl( + g, + max.out.degree = 2, + max.in.degree = 2 + )) +}) + +test_that("joint_degree_matrix_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(joint_degree_matrix_impl(NULL)) +}) + +# 147. joint_degree_distribution_impl + +test_that("joint_degree_distribution_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(joint_degree_distribution_impl(g)) + expect_snapshot(joint_degree_distribution_impl( + g, + from.mode = "in", + to.mode = "out", + directed.neighbors = FALSE, + normalized = FALSE, + max.from.degree = 2, + max.to.degree = 2 + )) +}) + +test_that("joint_degree_distribution_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(joint_degree_distribution_impl(NULL)) +}) + +# 148. joint_type_distribution_impl + +test_that("joint_type_distribution_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(joint_type_distribution_impl(g, from.types = c(1, 2, 1))) + expect_snapshot(joint_type_distribution_impl( + g, + from.types = c(1, 2, 1), + to.types = c(1, 2, 1), + directed = FALSE, + normalized = FALSE + )) +}) + +test_that("joint_type_distribution_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + joint_type_distribution_impl(NULL, from.types = c(1, 2, 1)) + ) +}) + +# 149. contract_vertices_impl + +test_that("contract_vertices_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(contract_vertices_impl(g, c(1, 1, 2))) +}) + +test_that("contract_vertices_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(contract_vertices_impl(NULL, c(1, 1, 2))) +}) + +# 150. eccentricity_dijkstra_impl + +test_that("eccentricity_dijkstra_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(eccentricity_dijkstra_impl(g)) + expect_snapshot(eccentricity_dijkstra_impl(g, mode = "in")) +}) + +test_that("eccentricity_dijkstra_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(eccentricity_dijkstra_impl(NULL)) +}) + +# 151. graph_center_dijkstra_impl + +test_that("graph_center_dijkstra_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(graph_center_dijkstra_impl(g)) + expect_snapshot(graph_center_dijkstra_impl(g, mode = "in")) +}) + +test_that("graph_center_dijkstra_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(graph_center_dijkstra_impl(NULL)) +}) + +# 152. radius_dijkstra_impl + +test_that("radius_dijkstra_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(radius_dijkstra_impl(g)) + expect_snapshot(radius_dijkstra_impl(g, mode = "in")) +}) + +test_that("radius_dijkstra_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(radius_dijkstra_impl(NULL)) +}) + +# 153. pseudo_diameter_impl + +test_that("pseudo_diameter_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(pseudo_diameter_impl(g, 1)) + expect_snapshot(pseudo_diameter_impl( + g, + 1, + directed = FALSE, + unconnected = FALSE + )) +}) + +test_that("pseudo_diameter_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(pseudo_diameter_impl(NULL, 1)) +}) + +# 154. pseudo_diameter_dijkstra_impl + +test_that("pseudo_diameter_dijkstra_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(pseudo_diameter_dijkstra_impl(g, start.vid = 1)) + expect_snapshot(pseudo_diameter_dijkstra_impl( + g, + start.vid = 1, + directed = FALSE, + unconnected = FALSE + )) +}) + +test_that("pseudo_diameter_dijkstra_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + pseudo_diameter_dijkstra_impl(NULL, start.vid = 1) + ) +}) + +# 155. diversity_impl + +test_that("diversity_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + E(g)$weight <- c(1, 2) + expect_snapshot(diversity_impl(g)) +}) + +test_that("diversity_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(diversity_impl(NULL)) +}) + +# 156. random_walk_impl + +test_that("random_walk_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(random_walk_impl(g, 1, 2)) + expect_snapshot(random_walk_impl(g, 1, 2, mode = "in", stuck = "error")) +}) + +test_that("random_walk_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(random_walk_impl(NULL, 1, 2)) +}) + +# 157. global_efficiency_impl + +test_that("global_efficiency_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(global_efficiency_impl(g)) + expect_snapshot(global_efficiency_impl(g, directed = FALSE)) +}) + +test_that("global_efficiency_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(global_efficiency_impl(NULL)) +}) + +# 158. local_efficiency_impl + +test_that("local_efficiency_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(local_efficiency_impl(g)) + expect_snapshot(local_efficiency_impl(g, directed = FALSE, mode = "in")) +}) + +test_that("local_efficiency_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(local_efficiency_impl(NULL)) +}) + +# 159. average_local_efficiency_impl + +test_that("average_local_efficiency_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(average_local_efficiency_impl(g)) + expect_snapshot(average_local_efficiency_impl( + g, + directed = FALSE, + mode = "in" + )) +}) + +test_that("average_local_efficiency_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(average_local_efficiency_impl(NULL)) +}) + +# 160. transitive_closure_dag_impl + +test_that("transitive_closure_dag_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3, directed = TRUE) + expect_snapshot(transitive_closure_dag_impl(g)) +}) + +test_that("transitive_closure_dag_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(transitive_closure_dag_impl(NULL)) +}) + +# 161. transitive_closure_impl + +test_that("transitive_closure_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(transitive_closure_impl(g)) +}) + +test_that("transitive_closure_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(transitive_closure_impl(NULL)) +}) + +# 162. trussness_impl + +test_that("trussness_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(trussness_impl(g)) +}) + +test_that("trussness_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(trussness_impl(NULL)) +}) + +# 163. is_graphical_impl + +test_that("is_graphical_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(is_graphical_impl(c(2, 2, 2))) + expect_snapshot(is_graphical_impl( + c(2, 2, 2), + c(1, 1, 1), + allowed.edge.types = "all" + )) +}) + +test_that("is_graphical_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_graphical_impl("a")) +}) + +# 164. bfs_simple_impl + +test_that("bfs_simple_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(bfs_simple_impl(g, 1)) + expect_snapshot(bfs_simple_impl(g, 1, mode = "in")) +}) + +test_that("bfs_simple_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(bfs_simple_impl(NULL, 1)) +}) + +# 165. bipartite_projection_size_impl + +test_that("bipartite_projection_size_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(4) + V(g)$type <- c(TRUE, FALSE, TRUE, FALSE) + expect_snapshot(bipartite_projection_size_impl(g)) +}) + +test_that("bipartite_projection_size_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(bipartite_projection_size_impl(NULL)) +}) + +# 166. biadjacency_impl + +test_that("biadjacency_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + m <- matrix(c(1, 0, 1, 0, 1, 1), nrow = 2) + expect_snapshot(biadjacency_impl(m)) + expect_snapshot(biadjacency_impl( + m, + directed = TRUE, + mode = "in", + multiple = TRUE + )) +}) + +test_that("biadjacency_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(biadjacency_impl("a")) +}) + +# 167. get_biadjacency_impl + +test_that("get_biadjacency_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_biadjacency_impl(g, c(TRUE, FALSE, TRUE))) +}) + +test_that("get_biadjacency_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + get_biadjacency_impl(NULL, c(TRUE, FALSE, TRUE)) + ) +}) + +# 168. is_bipartite_impl + +test_that("is_bipartite_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_bipartite_impl(g)) +}) + +test_that("is_bipartite_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_bipartite_impl(NULL)) +}) + +# 169. bipartite_game_gnp_impl + +test_that("bipartite_game_gnp_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(bipartite_game_gnp_impl(2, 2, 0.5)) + expect_snapshot(bipartite_game_gnp_impl( + 2, + 2, + 0.5, + directed = TRUE, + mode = "in" + )) +}) + +test_that("bipartite_game_gnp_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(bipartite_game_gnp_impl(-1, 2, 0.5)) +}) + +# 170. bipartite_game_gnm_impl + +test_that("bipartite_game_gnm_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(bipartite_game_gnm_impl(2, 2, 1)) + expect_snapshot(bipartite_game_gnm_impl( + 2, + 2, + 1, + directed = TRUE, + mode = "in" + )) +}) + +test_that("bipartite_game_gnm_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(bipartite_game_gnm_impl(-1, 2, 1)) +}) + +# 171. get_laplacian_impl + +test_that("get_laplacian_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_laplacian_impl(g)) + expect_snapshot(get_laplacian_impl( + g, + mode = "in", + normalization = "symmetric", + weights = c(1, 2) + )) +}) + +test_that("get_laplacian_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_laplacian_impl(NULL)) +}) + +# 172. get_laplacian_sparse_impl + +test_that("get_laplacian_sparse_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_laplacian_sparse_impl(g)) + expect_snapshot(get_laplacian_sparse_impl( + g, + mode = "in", + normalization = "symmetric", + weights = c(1, 2) + )) +}) + +test_that("get_laplacian_sparse_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_laplacian_sparse_impl(NULL)) +}) + +# 173. connected_components_impl + +test_that("connected_components_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(connected_components_impl(g)) + expect_snapshot(connected_components_impl(g, mode = "strong", details = TRUE)) +}) + +test_that("connected_components_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(connected_components_impl(NULL)) +}) + +# 174. is_connected_impl + +test_that("is_connected_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_connected_impl(g)) + expect_snapshot(is_connected_impl(g, mode = "strong")) +}) + +test_that("is_connected_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_connected_impl(NULL)) +}) + +# 175. articulation_points_impl + +test_that("articulation_points_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(articulation_points_impl(g)) +}) + +test_that("articulation_points_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(articulation_points_impl(NULL)) +}) + +# 176. biconnected_components_impl + +test_that("biconnected_components_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(biconnected_components_impl(g)) +}) + +test_that("biconnected_components_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(biconnected_components_impl(NULL)) +}) + +# 177. bridges_impl + +test_that("bridges_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(bridges_impl(g)) +}) + +test_that("bridges_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(bridges_impl(NULL)) +}) + +# 178. is_biconnected_impl + +test_that("is_biconnected_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_biconnected_impl(g)) +}) + +test_that("is_biconnected_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_biconnected_impl(NULL)) +}) + +# 179. count_reachable_impl + +test_that("count_reachable_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(5) + expect_snapshot(count_reachable_impl(g, mode = "out")) + expect_snapshot(count_reachable_impl(g, mode = "in")) +}) + +test_that("count_reachable_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(count_reachable_impl(NULL, mode = "out")) +}) + +# 180. bond_percolation_impl + +test_that("bond_percolation_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(bond_percolation_impl(g)) +}) + +test_that("bond_percolation_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(bond_percolation_impl(NULL)) +}) + +# 181. site_percolation_impl + +test_that("site_percolation_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(site_percolation_impl(g)) +}) + +test_that("site_percolation_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(site_percolation_impl(NULL)) +}) + +# 182. edgelist_percolation_impl + +test_that("edgelist_percolation_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(edgelist_percolation_impl(matrix(c(1, 2, 2, 3), ncol = 2))) +}) + +test_that("edgelist_percolation_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(edgelist_percolation_impl("a")) +}) + +# 183. is_clique_impl + +test_that("is_clique_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_clique_impl(g, 1:2)) + expect_snapshot(is_clique_impl(g, 1:2, directed = TRUE)) +}) + +test_that("is_clique_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_clique_impl(NULL, 1:2)) +}) + +# 184. cliques_impl + +test_that("cliques_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(cliques_impl(g)) + expect_snapshot(cliques_impl(g, min = 2, max = 2)) +}) + +test_that("cliques_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(cliques_impl(NULL)) +}) + +# 185. clique_size_hist_impl + +test_that("clique_size_hist_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(clique_size_hist_impl(g)) + expect_snapshot(clique_size_hist_impl(g, min.size = 2, max.size = 2)) +}) + +test_that("clique_size_hist_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(clique_size_hist_impl(NULL)) +}) + +# 186. largest_cliques_impl + +test_that("largest_cliques_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(largest_cliques_impl(g)) +}) + +test_that("largest_cliques_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(largest_cliques_impl(NULL)) +}) + +# 187. maximal_cliques_hist_impl + +test_that("maximal_cliques_hist_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(maximal_cliques_hist_impl(g)) + expect_snapshot(maximal_cliques_hist_impl(g, min.size = 2, max.size = 2)) +}) + +test_that("maximal_cliques_hist_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(maximal_cliques_hist_impl(NULL)) +}) + +# 188. clique_number_impl + +test_that("clique_number_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(clique_number_impl(g)) +}) + +test_that("clique_number_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(clique_number_impl(NULL)) +}) + +# 189. weighted_cliques_impl + +test_that("weighted_cliques_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(weighted_cliques_impl(g)) + expect_snapshot(weighted_cliques_impl( + g, + vertex.weights = c(1, 2, 3), + min.weight = 1, + max.weight = 3, + maximal = TRUE + )) +}) + +test_that("weighted_cliques_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(weighted_cliques_impl(NULL)) +}) + +# 190. largest_weighted_cliques_impl + +test_that("largest_weighted_cliques_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(largest_weighted_cliques_impl(g)) + expect_snapshot(largest_weighted_cliques_impl(g, vertex.weights = c(1, 2, 3))) +}) + +test_that("largest_weighted_cliques_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(largest_weighted_cliques_impl(NULL)) +}) + +# 191. weighted_clique_number_impl + +test_that("weighted_clique_number_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(weighted_clique_number_impl(g)) + expect_snapshot(weighted_clique_number_impl(g, vertex.weights = c(1, 2, 3))) +}) + +test_that("weighted_clique_number_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(weighted_clique_number_impl(NULL)) +}) + +# 192. is_independent_vertex_set_impl + +test_that("is_independent_vertex_set_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_independent_vertex_set_impl(g, 1:2)) +}) + +test_that("is_independent_vertex_set_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_independent_vertex_set_impl(NULL, 1:2)) +}) + +# 193. layout_random_impl + +test_that("layout_random_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_random_impl(g)) +}) + +test_that("layout_random_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_random_impl(NULL)) +}) + +# 194. layout_circle_impl + +test_that("layout_circle_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_circle_impl(g)) + expect_snapshot(layout_circle_impl(g, order = 1:3)) +}) + +test_that("layout_circle_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_circle_impl(NULL)) +}) + +# 195. layout_star_impl + +test_that("layout_star_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_star_impl(g)) + expect_snapshot(layout_star_impl(g, center = 1, order = 1:3)) +}) + +test_that("layout_star_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_star_impl(NULL)) +}) + +# 196. layout_grid_impl + +test_that("layout_grid_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_grid_impl(g)) + expect_snapshot(layout_grid_impl(g, width = 2)) +}) + +test_that("layout_grid_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_grid_impl(NULL)) +}) + +# 197. layout_grid_3d_impl + +test_that("layout_grid_3d_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_grid_3d_impl(g)) + expect_snapshot(layout_grid_3d_impl(g, width = 2, height = 2)) +}) + +test_that("layout_grid_3d_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_grid_3d_impl(NULL)) +}) + +# 198. roots_for_tree_layout_impl + +test_that("roots_for_tree_layout_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(roots_for_tree_layout_impl(g, mode = "out", heuristic = 1)) +}) + +test_that("roots_for_tree_layout_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + roots_for_tree_layout_impl(NULL, mode = "out", heuristic = 1) + ) +}) + +# 199. layout_random_3d_impl + +test_that("layout_random_3d_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_random_3d_impl(g)) +}) + +test_that("layout_random_3d_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_random_3d_impl(NULL)) +}) + +# 200. layout_sphere_impl + +test_that("layout_sphere_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_sphere_impl(g)) +}) + +test_that("layout_sphere_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_sphere_impl(NULL)) +}) + +# 201. layout_sugiyama_impl + +test_that("layout_sugiyama_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_sugiyama_impl(g)) + expect_snapshot(layout_sugiyama_impl( + g, + layers = 1:3, + hgap = 2, + vgap = 2, + maxiter = 10, + weights = c(1, 2) + )) +}) + +test_that("layout_sugiyama_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_sugiyama_impl(NULL)) +}) + +# 202. layout_mds_impl + +test_that("layout_mds_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_mds_impl(g)) + expect_snapshot(layout_mds_impl(g, dist = matrix(1:9, nrow = 3), dim = 3)) +}) + +test_that("layout_mds_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(layout_mds_impl(NULL)) +}) + +# 203. layout_bipartite_impl + +test_that("layout_bipartite_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_bipartite_impl(g, types = c(TRUE, FALSE, TRUE))) + expect_snapshot(layout_bipartite_impl( + g, + types = c(TRUE, FALSE, TRUE), + hgap = 2, + vgap = 2, + maxiter = 10 + )) +}) + +test_that("layout_bipartite_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + layout_bipartite_impl(NULL, types = c(TRUE, FALSE, TRUE)) + ) +}) + +# 204. layout_gem_impl + +test_that("layout_gem_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_gem_impl(g, res = matrix(0, nrow = 3, ncol = 2))) + expect_snapshot(layout_gem_impl( + g, + res = matrix(0, nrow = 3, ncol = 2), + use.seed = TRUE, + maxiter = 10, + temp.max = 2, + temp.min = 0.1, + temp.init = 1 + )) +}) + +test_that("layout_gem_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + layout_gem_impl(NULL, res = matrix(0, nrow = 3, ncol = 2)) + ) +}) + +# 205. layout_davidson_harel_impl + +test_that("layout_davidson_harel_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_davidson_harel_impl( + g, + res = matrix(0, nrow = 3, ncol = 2) + )) + expect_snapshot(layout_davidson_harel_impl( + g, + res = matrix(0, nrow = 3, ncol = 2), + use.seed = TRUE, + maxiter = 10, + fineiter = 5, + cool.fact = 0.5, + weight.node.dist = 2, + weight.border = 1, + weight.edge.lengths = 0.1, + weight.edge.crossings = 0.2, + weight.node.edge.dist = 0.3 + )) +}) + +test_that("layout_davidson_harel_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + layout_davidson_harel_impl(NULL, res = matrix(0, nrow = 3, ncol = 2)) + ) +}) + +# 206. layout_umap_impl + +test_that("layout_umap_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_umap_impl( + g, + res = matrix(0, nrow = 3, ncol = 2), + use.seed = TRUE + )) + expect_snapshot(layout_umap_impl( + g, + res = matrix(0, nrow = 3, ncol = 2), + use.seed = TRUE, + distances = 1:3, + min.dist = 0.1, + epochs = 10, + distances.are.weights = TRUE + )) +}) + +test_that("layout_umap_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + layout_umap_impl(NULL, res = matrix(0, nrow = 3, ncol = 2)) + ) +}) + +# 207. layout_umap_3d_impl + +test_that("layout_umap_3d_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_umap_3d_impl( + g, + res = matrix(0, nrow = 3, ncol = 3), + use.see = TRUE + )) + expect_snapshot(layout_umap_3d_impl( + g, + res = matrix(0, nrow = 3, ncol = 3), + use.seed = TRUE, + distances = 1:3, + min.dist = 0.1, + epochs = 10, + distances.are.weights = TRUE + )) +}) + +test_that("layout_umap_3d_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + layout_umap_3d_impl(NULL, res = matrix(0, nrow = 3, ncol = 3)) + ) +}) + +# 208. layout_umap_compute_weights_impl + +test_that("layout_umap_compute_weights_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_umap_compute_weights_impl( + g, + distances = 1:2, + weights = 1:3 + )) +}) + +test_that("layout_umap_compute_weights_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + layout_umap_compute_weights_impl(NULL, distances = 1:3, weights = 1:3) + ) +}) + +# 209. layout_align_impl + +test_that("layout_align_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(layout_align_impl(g, layout = matrix(0, nrow = 3, ncol = 2))) +}) + +test_that("layout_align_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + layout_align_impl(NULL, layout = matrix(0, nrow = 3, ncol = 2)) + ) +}) + +# 210. similarity_dice_impl + +test_that("similarity_dice_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(similarity_dice_impl(g)) + expect_snapshot(similarity_dice_impl( + g, + vids = 1:2, + mode = "in", + loops = TRUE + )) +}) + +test_that("similarity_dice_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(similarity_dice_impl(NULL)) +}) + +# 211. similarity_dice_es_impl + +test_that("similarity_dice_es_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(similarity_dice_es_impl(g)) + expect_snapshot(similarity_dice_es_impl( + g, + es = 1:2, + mode = "in", + loops = TRUE + )) +}) + +test_that("similarity_dice_es_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(similarity_dice_es_impl(NULL)) +}) + +# 212. similarity_dice_pairs_impl + +test_that("similarity_dice_pairs_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(4) + expect_snapshot(similarity_dice_pairs_impl( + g, + pairs = matrix(c(1, 2, 2, 3), ncol = 2) + )) + expect_snapshot(similarity_dice_pairs_impl( + g, + pairs = matrix(c(1, 2, 2, 3), ncol = 2), + mode = "in", + loops = TRUE + )) +}) + +test_that("similarity_dice_pairs_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + similarity_dice_pairs_impl(NULL, pairs = matrix(c(1, 2, 2, 3), ncol = 2)) + ) +}) + +# 213. similarity_inverse_log_weighted_impl + +test_that("similarity_inverse_log_weighted_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(similarity_inverse_log_weighted_impl(g)) + expect_snapshot(similarity_inverse_log_weighted_impl( + g, + vids = 1:2, + mode = "in" + )) +}) + +test_that("similarity_inverse_log_weighted_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(similarity_inverse_log_weighted_impl(NULL)) +}) + +# 214. similarity_jaccard_impl + +test_that("similarity_jaccard_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(similarity_jaccard_impl(g)) + expect_snapshot(similarity_jaccard_impl( + g, + vids = 1:2, + mode = "in", + loops = TRUE + )) +}) + +test_that("similarity_jaccard_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(similarity_jaccard_impl(NULL)) +}) + +# 215. similarity_jaccard_es_impl + +test_that("similarity_jaccard_es_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(similarity_jaccard_es_impl(g)) + expect_snapshot(similarity_jaccard_es_impl( + g, + es = 1:2, + mode = "in", + loops = TRUE + )) +}) + +test_that("similarity_jaccard_es_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(similarity_jaccard_es_impl(NULL)) +}) + +# 216. similarity_jaccard_pairs_impl + +test_that("similarity_jaccard_pairs_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(4) + expect_snapshot(similarity_jaccard_pairs_impl( + g, + pairs = matrix(c(1, 2, 2, 3), ncol = 2) + )) + expect_snapshot(similarity_jaccard_pairs_impl( + g, + pairs = matrix(c(1, 2, 2, 3), ncol = 2), + mode = "in", + loops = TRUE + )) +}) + +test_that("similarity_jaccard_pairs_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + similarity_jaccard_pairs_impl(NULL, pairs = matrix(c(1, 2, 2, 3), ncol = 2)) + ) +}) + +# 217. compare_communities_impl + +test_that("compare_communities_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(compare_communities_impl(c(1, 2, 1), c(2, 1, 2))) + expect_snapshot(compare_communities_impl( + c(1, 2, 1), + c(2, 1, 2), + method = "nmi" + )) +}) + +test_that("compare_communities_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(compare_communities_impl("a", c(2, 1, 2))) +}) + +# 218. modularity_impl + +test_that("modularity_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(modularity_impl(g, membership = c(1, 2, 1))) + expect_snapshot(modularity_impl( + g, + membership = c(1, 2, 1), + weights = c(1, 2), + resolution = 0.5, + directed = FALSE + )) +}) + +test_that("modularity_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(modularity_impl(NULL, membership = c(1, 2, 1))) +}) + +# 219. modularity_matrix_impl + +test_that("modularity_matrix_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(modularity_matrix_impl(g)) + expect_snapshot(modularity_matrix_impl( + g, + weights = c(1, 2), + resolution = 0.5, + directed = FALSE + )) +}) + +test_that("modularity_matrix_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(modularity_matrix_impl(NULL)) +}) + +# 220. community_fluid_communities_impl + +test_that("community_fluid_communities_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(community_fluid_communities_impl(g, no.of.communities = 2)) +}) + +test_that("community_fluid_communities_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + community_fluid_communities_impl(NULL, no.of.communities = 2) + ) +}) + +# 221. community_label_propagation_impl + +test_that("community_label_propagation_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(community_label_propagation_impl(g)) + expect_snapshot(community_label_propagation_impl( + g, + mode = "in", + weights = c(1, 2), + initial = 1:3, + fixed = c(TRUE, FALSE, TRUE) + )) +}) + +test_that("community_label_propagation_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(community_label_propagation_impl(NULL)) +}) + +# 222. community_multilevel_impl + +test_that("community_multilevel_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(community_multilevel_impl(g)) + expect_snapshot(community_multilevel_impl( + g, + weights = c(1, 2), + resolution = 0.5 + )) +}) + +test_that("community_multilevel_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(community_multilevel_impl(NULL)) +}) + +# 223. community_optimal_modularity_impl + +test_that("community_optimal_modularity_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(community_optimal_modularity_impl(g)) + expect_snapshot(community_optimal_modularity_impl(g, weights = c(1, 2))) +}) + +test_that("community_optimal_modularity_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(community_optimal_modularity_impl(NULL)) +}) + +# 224. community_leiden_impl + +test_that("community_leiden_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(community_leiden_impl( + g, + weights = c(1, 2), + vertex.weights = c(1, 2, 3), + resolution = 0.5, + beta = 0.1, + start = TRUE, + n.iterations = 1, + membership = 1:3 + )) +}) + +test_that("community_leiden_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(community_leiden_impl(NULL, resolution = 1)) +}) + +# 225. split_join_distance_impl + +test_that("split_join_distance_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(split_join_distance_impl(c(1, 2, 1), c(2, 1, 2))) +}) + +test_that("split_join_distance_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(split_join_distance_impl("a", c(2, 1, 2))) +}) + +# 226. community_infomap_impl + +test_that("community_infomap_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(community_infomap_impl(g)) + expect_snapshot(community_infomap_impl( + g, + e.weights = c(1, 2), + v.weights = c(1, 2, 3), + nb.trials = 2 + )) +}) + +test_that("community_infomap_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(community_infomap_impl(NULL)) +}) + +# 227. graphlets_impl + +test_that("graphlets_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + E(g)$weight <- 1:2 + expect_snapshot(graphlets_impl(g)) + expect_snapshot(graphlets_impl(g, weights = c(3, 4), niter = 10)) +}) + +test_that("graphlets_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(graphlets_impl(NULL)) +}) + +# 228. hrg_fit_impl + +test_that("hrg_fit_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + expect_snapshot(hrg_fit_impl(g1)) +}) + +test_that("hrg_fit_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_fit_impl(NULL)) +}) + +# 229. hrg_sample_impl + +test_that("hrg_sample_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(10) + hrg_model <- fit_hrg(g, hrg = NULL, start = FALSE, steps = 0) + expect_snapshot(hrg_sample_impl(hrg_model)) +}) + +test_that("hrg_sample_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_sample_impl(NULL)) +}) + +# 230. hrg_sample_many_impl + +test_that("hrg_sample_many_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(10) + hrg_model <- fit_hrg(g, hrg = NULL, start = FALSE, steps = 0) + expect_snapshot(hrg_sample_many_impl(hrg_model, num.samples = 2)) +}) + +test_that("hrg_sample_many_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_sample_many_impl(NULL, num.samples = 2)) +}) + +# 231. hrg_game_impl + +test_that("hrg_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(10) + hrg_model <- fit_hrg(g, hrg = NULL, start = FALSE, steps = 0) + expect_snapshot(hrg_game_impl(hrg_model)) +}) + +test_that("hrg_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_game_impl(NULL)) +}) + +# 232. hrg_consensus_impl + +# test_that("hrg_consensus_impl basic", { +# withr::local_seed(20250909) +# oldval <- igraph_opt("print.id") +# igraph_options(print.id = FALSE) +# g <- path_graph_impl(3) +# expect_snapshot(hrg_consensus_impl(g)) +# expect_snapshot(hrg_consensus_impl(g, hrg=list(left=1, right=2, prob=0.5, edges=1, vertices=1), start=TRUE, num.samples=2)) +# }) + +test_that("hrg_consensus_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_consensus_impl(NULL)) +}) + +# 233. hrg_predict_impl + +# test_that("hrg_predict_impl basic", { +# withr::local_seed(20250909) +# oldval <- igraph_opt("print.id") +# igraph_options(print.id = FALSE) +# g <- path_graph_impl(3) +# expect_snapshot(hrg_predict_impl(g)) +# expect_snapshot(hrg_predict_impl(g, hrg=list(left=1, right=2, prob=0.5, edges=1, vertices=1), start=TRUE, num.samples=2, num.bins=2)) +# }) + +test_that("hrg_predict_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_predict_impl(NULL)) +}) + +# 234. hrg_create_impl + +test_that("hrg_create_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_tree(5) + expect_snapshot(hrg_create_impl(g, prob = rep(0.5, 2))) +}) + +test_that("hrg_create_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(4, directed = TRUE) + expect_snapshot_igraph_error(hrg_create_impl(g, prob = 0.5)) +}) + +# 235. hrg_resize_impl + +test_that("hrg_resize_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(10) + hrg_model <- fit_hrg(g, hrg = NULL, start = FALSE, steps = 0) + expect_snapshot(hrg_resize_impl(hrg_model, newsize = 5)) +}) + +test_that("hrg_resize_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_resize_impl(-1, newsize = 2)) +}) + +# 236. hrg_size_impl + +test_that("hrg_size_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(10) + hrg_model <- fit_hrg(g, hrg = NULL, start = FALSE, steps = 0) + expect_snapshot(hrg_size_impl(hrg_model)) +}) + +test_that("hrg_size_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(hrg_size_impl(-1)) +}) + +# 237. from_hrg_dendrogram_impl + +test_that("from_hrg_dendrogram_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- make_full_graph(10) + hrg_model <- fit_hrg(g, hrg = NULL, start = FALSE, steps = 0) + expect_snapshot(from_hrg_dendrogram_impl(hrg_model)) +}) + +test_that("from_hrg_dendrogram_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(from_hrg_dendrogram_impl(-1)) +}) + +# 238. get_adjacency_sparse_impl + +test_that("get_adjacency_sparse_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_adjacency_sparse_impl(g)) + expect_snapshot(get_adjacency_sparse_impl( + g, + type = "upper", + weights = c(1, 2), + loops = "none" + )) +}) + +test_that("get_adjacency_sparse_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_adjacency_sparse_impl(NULL)) +}) + +# 239. get_stochastic_impl + +test_that("get_stochastic_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_stochastic_impl(g)) + expect_snapshot(get_stochastic_impl(g, column.wise = TRUE, weights = c(1, 2))) +}) + +test_that("get_stochastic_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_stochastic_impl(NULL)) +}) + +# 240. get_stochastic_sparse_impl + +test_that("get_stochastic_sparse_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(get_stochastic_sparse_impl(g)) + expect_snapshot(get_stochastic_sparse_impl( + g, + column.wise = TRUE, + weights = c(1, 2) + )) +}) + +test_that("get_stochastic_sparse_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(get_stochastic_sparse_impl(NULL)) +}) + +# 241. to_directed_impl + +test_that("to_directed_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(to_directed_impl(g)) + expect_snapshot(to_directed_impl(g, mode = "acyclic")) +}) + +test_that("to_directed_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(to_directed_impl(NULL)) +}) + +# 242. to_undirected_impl + +test_that("to_undirected_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(to_undirected_impl(g)) + expect_snapshot(to_undirected_impl( + g, + mode = "mutual", + edge.attr.comb = "sum" + )) +}) + +test_that("to_undirected_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(to_undirected_impl(NULL)) +}) + +# 243. motifs_randesu_impl + +test_that("motifs_randesu_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(motifs_randesu_impl(g)) + expect_snapshot(motifs_randesu_impl(g, size = 4, cut.prob = rep(0.1, 4))) +}) + +test_that("motifs_randesu_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(motifs_randesu_impl(NULL)) +}) + +# 244. motifs_randesu_estimate_impl + +test_that("motifs_randesu_estimate_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(6) + expect_snapshot(motifs_randesu_estimate_impl(g, size = 3, sample.size = 2)) + expect_snapshot(motifs_randesu_estimate_impl( + g, + size = 4, + cut.prob = rep(0.1, 4), + sample.size = 2, + sample = 1:2 + )) +}) + +test_that("motifs_randesu_estimate_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + motifs_randesu_estimate_impl(NULL, size = 3, sample.size = 2) + ) +}) + +# 245. motifs_randesu_no_impl + +test_that("motifs_randesu_no_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(motifs_randesu_no_impl(g)) + expect_snapshot(motifs_randesu_no_impl( + g, + size = 4, + cut.prob = c(0.1, 0.1, 0.1, 0.1) + )) +}) + +test_that("motifs_randesu_no_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot_igraph_error( + motifs_randesu_no_impl(g, size = 3, cut.prob = c(0.1)) + ) +}) + +# 246. dyad_census_impl + +test_that("dyad_census_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(dyad_census_impl(g)) +}) + +test_that("dyad_census_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(dyad_census_impl(NULL)) +}) + +# 247. triad_census_impl + +test_that("triad_census_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(triad_census_impl(g)) +}) + +test_that("triad_census_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(triad_census_impl(NULL)) +}) + +# 248. count_adjacent_triangles_impl + +test_that("count_adjacent_triangles_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(count_adjacent_triangles_impl(g)) + expect_snapshot(count_adjacent_triangles_impl(g, vids = 1:2)) +}) + +test_that("count_adjacent_triangles_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(count_adjacent_triangles_impl(NULL)) +}) + +# 249. count_triangles_impl + +test_that("count_triangles_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(count_triangles_impl(g)) +}) + +test_that("count_triangles_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(count_triangles_impl(NULL)) +}) + +# 250. local_scan_0_impl + +test_that("local_scan_0_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(local_scan_0_impl(g)) + expect_snapshot(local_scan_0_impl(g, weights = c(1, 2), mode = "in")) +}) + +test_that("local_scan_0_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(local_scan_0_impl(NULL)) +}) + +# 251. local_scan_0_them_impl + +test_that("local_scan_0_them_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(local_scan_0_them_impl(g1, g2)) + expect_snapshot(local_scan_0_them_impl( + g1, + g2, + weights.them = c(1, 2), + mode = "in" + )) +}) + +test_that("local_scan_0_them_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + local_scan_0_them_impl(NULL, path_graph_impl(3)) + ) +}) + +# 252. local_scan_1_ecount_impl + +test_that("local_scan_1_ecount_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(local_scan_1_ecount_impl(g)) + expect_snapshot(local_scan_1_ecount_impl(g, weights = c(1, 2), mode = "in")) +}) + +test_that("local_scan_1_ecount_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(local_scan_1_ecount_impl(NULL)) +}) + +# 253. local_scan_1_ecount_them_impl + +test_that("local_scan_1_ecount_them_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(local_scan_1_ecount_them_impl(g1, g2)) + expect_snapshot(local_scan_1_ecount_them_impl( + g1, + g2, + weights.them = c(1, 2), + mode = "in" + )) +}) + +test_that("local_scan_1_ecount_them_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + local_scan_1_ecount_them_impl(NULL, path_graph_impl(3)) + ) +}) + +# 254. local_scan_k_ecount_impl + +test_that("local_scan_k_ecount_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(local_scan_k_ecount_impl(g, k = 1)) + expect_snapshot(local_scan_k_ecount_impl( + g, + k = 1, + weights = c(1, 2), + mode = "in" + )) +}) + +test_that("local_scan_k_ecount_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(local_scan_k_ecount_impl(NULL, k = 1)) +}) + +# 255. local_scan_k_ecount_them_impl + +test_that("local_scan_k_ecount_them_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(local_scan_k_ecount_them_impl(g1, g2, k = 1)) + expect_snapshot(local_scan_k_ecount_them_impl( + g1, + g2, + k = 1, + weights.them = c(1, 2), + mode = "in" + )) +}) + +test_that("local_scan_k_ecount_them_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + local_scan_k_ecount_them_impl(NULL, path_graph_impl(3), k = 1) + ) +}) + +# 256. local_scan_neighborhood_ecount_impl + +test_that("local_scan_neighborhood_ecount_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(4) + expect_snapshot(local_scan_neighborhood_ecount_impl( + g, + neighborhoods = list(1:2, 2:3, 2:4, 2) + )) + expect_snapshot(local_scan_neighborhood_ecount_impl( + g, + weights = c(1, 2, 3), + neighborhoods = list(1:2, 1:3, 2:4, 1) + )) +}) + +test_that("local_scan_neighborhood_ecount_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + local_scan_neighborhood_ecount_impl(NULL, neighborhoods = list(1:2, 2:3)) + ) +}) + +# 257. local_scan_subset_ecount_impl + +test_that("local_scan_subset_ecount_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(4) + expect_snapshot(local_scan_subset_ecount_impl( + g, + subsets = list(c(1.0, 2.0), c(2.0, 3.0)) + )) + expect_snapshot(local_scan_subset_ecount_impl( + g, + weights = c(1.0, 2.0, 3.0), + subsets = list(c(1.0, 2.0), c(2.0, 3.0)) + )) +}) + +test_that("local_scan_subset_ecount_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(4) + expect_snapshot_igraph_error( + local_scan_subset_ecount_impl(g, subsets = list(1:2, letters[2:3])) + ) +}) + +# 258. list_triangles_impl + +test_that("list_triangles_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(list_triangles_impl(g)) +}) + +test_that("list_triangles_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(list_triangles_impl(NULL)) +}) + +# 259. join_impl + +test_that("join_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(join_impl(g1, g2)) +}) + +test_that("join_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(join_impl(NULL, path_graph_impl(3))) +}) + +# 260. induced_subgraph_map_impl + +test_that("induced_subgraph_map_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(induced_subgraph_map_impl(g, 1:2, impl = "auto")) + expect_snapshot(induced_subgraph_map_impl(g, 1:2, impl = "copy_and_delete")) +}) + +test_that("induced_subgraph_map_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + induced_subgraph_map_impl(NULL, 1:2, impl = "auto") + ) +}) + +# 261. mycielskian_impl + +test_that("mycielskian_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(mycielskian_impl(g)) + expect_snapshot(mycielskian_impl(g, k = 2)) +}) + +test_that("mycielskian_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(mycielskian_impl(NULL)) +}) + +# 262. product_impl + +test_that("product_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(product_impl(g1, g2)) + expect_snapshot(product_impl(g1, g2, type = "tensor")) +}) + +test_that("product_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(product_impl(NULL, path_graph_impl(3))) +}) + +# 263. rooted_product_impl + +test_that("rooted_product_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(rooted_product_impl(g1, g2, root = 1)) +}) + +test_that("rooted_product_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + rooted_product_impl(NULL, path_graph_impl(3), root = 1) + ) +}) + +# 264. gomory_hu_tree_impl + +test_that("gomory_hu_tree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(gomory_hu_tree_impl(g)) + expect_snapshot(gomory_hu_tree_impl(g, capacity = c(1, 2))) +}) + +test_that("gomory_hu_tree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(gomory_hu_tree_impl(NULL)) +}) + +# 265. maxflow_impl + +test_that("maxflow_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(maxflow_impl(g, source = 1, target = 3)) + expect_snapshot(maxflow_impl(g, source = 1, target = 3, capacity = c(1, 2))) +}) + +test_that("maxflow_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(maxflow_impl(NULL, source = 1, target = 3)) +}) + +# 266. residual_graph_impl + +test_that("residual_graph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(residual_graph_impl(g, capacity = c(1, 2), flow = c(1, 2))) +}) + +test_that("residual_graph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + residual_graph_impl(NULL, capacity = c(1, 2), flow = c(1, 2)) + ) +}) + +# 267. reverse_residual_graph_impl + +test_that("reverse_residual_graph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(reverse_residual_graph_impl( + g, + capacity = c(1, 2), + flow = c(1, 2) + )) +}) + +test_that("reverse_residual_graph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + reverse_residual_graph_impl(NULL, capacity = c(1, 2), flow = c(1, 2)) + ) +}) + +# 268. st_mincut_impl + +test_that("st_mincut_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(st_mincut_impl(g, source = 1, target = 3)) + expect_snapshot(st_mincut_impl(g, source = 1, target = 3, capacity = c(1, 2))) +}) + +test_that("st_mincut_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(st_mincut_impl(NULL, source = 1, target = 3)) +}) + +# 269. dominator_tree_impl + +test_that("dominator_tree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3, directed = TRUE) + expect_snapshot(dominator_tree_impl(g, root = 1)) + expect_snapshot(dominator_tree_impl(g, root = 1, mode = "in")) +}) + +test_that("dominator_tree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(dominator_tree_impl(NULL, root = 1)) +}) + +# 270. all_st_cuts_impl + +test_that("all_st_cuts_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3, directed = TRUE) + expect_snapshot(all_st_cuts_impl(g, source = 1, target = 3)) +}) + +test_that("all_st_cuts_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(all_st_cuts_impl(NULL, source = 1, target = 3)) +}) + +# 271. all_st_mincuts_impl + +test_that("all_st_mincuts_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3, directed = TRUE) + expect_snapshot(all_st_mincuts_impl(g, source = 1, target = 3)) + expect_snapshot(all_st_mincuts_impl( + g, + source = 1, + target = 3, + capacity = c(1, 2) + )) +}) + +test_that("all_st_mincuts_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + all_st_mincuts_impl(NULL, source = 1, target = 3) + ) +}) + +# 272. even_tarjan_reduction_impl + +test_that("even_tarjan_reduction_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(even_tarjan_reduction_impl(g)) +}) + +test_that("even_tarjan_reduction_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(even_tarjan_reduction_impl(NULL)) +}) + +# 273. is_separator_impl + +test_that("is_separator_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_separator_impl(g, 1:2)) +}) + +test_that("is_separator_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_separator_impl(NULL, 1:2)) +}) + +# 274. is_minimal_separator_impl + +test_that("is_minimal_separator_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_minimal_separator_impl(g, 1:2)) +}) + +test_that("is_minimal_separator_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_minimal_separator_impl(NULL, 1:2)) +}) + +# 275. all_minimal_st_separators_impl + +test_that("all_minimal_st_separators_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(all_minimal_st_separators_impl(g)) +}) + +test_that("all_minimal_st_separators_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(all_minimal_st_separators_impl(NULL)) +}) + +# 276. minimum_size_separators_impl + +test_that("minimum_size_separators_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(minimum_size_separators_impl(g)) +}) + +test_that("minimum_size_separators_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(minimum_size_separators_impl(NULL)) +}) + +# 277. isoclass_impl + +test_that("isoclass_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(isoclass_impl(g)) +}) + +test_that("isoclass_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(isoclass_impl(NULL)) +}) + +# 278. isomorphic_impl + +test_that("isomorphic_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(isomorphic_impl(g1, g2)) +}) + +test_that("isomorphic_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(isomorphic_impl(NULL, path_graph_impl(3))) +}) + +# 279. isoclass_subgraph_impl + +test_that("isoclass_subgraph_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(5) + expect_snapshot(isoclass_subgraph_impl(g, c(1, 2, 3))) +}) + +test_that("isoclass_subgraph_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(isoclass_subgraph_impl(NULL, 1:2)) +}) + +# 280. isoclass_create_impl + +test_that("isoclass_create_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(isoclass_create_impl(size = 3, number = 1)) + expect_snapshot(isoclass_create_impl(size = 3, number = 1, directed = FALSE)) +}) + +test_that("isoclass_create_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(isoclass_create_impl("a", 1)) +}) + +# 281. isomorphic_vf2_impl + +test_that("isomorphic_vf2_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(isomorphic_vf2_impl(g1, g2)) + expect_snapshot(isomorphic_vf2_impl( + g1, + g2, + vertex.color1 = c(1, 2, 3), + vertex.color2 = c(1, 2, 3), + edge.color1 = c(1, 2), + edge.color2 = c(1, 2) + )) +}) + +test_that("isomorphic_vf2_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(isomorphic_vf2_impl(NULL, path_graph_impl(3))) +}) + +# 282. get_isomorphisms_vf2_callback_impl +# Skipped: requires callback function, not suitable for snapshot test + +# 283. count_isomorphisms_vf2_impl + +test_that("count_isomorphisms_vf2_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(count_isomorphisms_vf2_impl(g1, g2)) + expect_snapshot(count_isomorphisms_vf2_impl( + g1, + g2, + vertex.color1 = c(1, 2, 3), + vertex.color2 = c(1, 2, 3), + edge.color1 = c(1, 2), + edge.color2 = c(1, 2) + )) +}) + +test_that("count_isomorphisms_vf2_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + count_isomorphisms_vf2_impl(NULL, path_graph_impl(3)) + ) +}) + +# 284. get_isomorphisms_vf2_impl + +test_that("get_isomorphisms_vf2_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(get_isomorphisms_vf2_impl(g1, g2)) + expect_snapshot(get_isomorphisms_vf2_impl( + g1, + g2, + vertex.color1 = c(1, 2, 3), + vertex.color2 = c(1, 2, 3), + edge.color1 = c(1, 2), + edge.color2 = c(1, 2) + )) +}) + +test_that("get_isomorphisms_vf2_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + get_isomorphisms_vf2_impl(NULL, path_graph_impl(3)) + ) +}) + +# 285. subisomorphic_impl + +test_that("subisomorphic_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(subisomorphic_impl(g1, g2)) +}) + +test_that("subisomorphic_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(subisomorphic_impl(NULL, path_graph_impl(3))) +}) + +# 286. subisomorphic_vf2_impl + +test_that("subisomorphic_vf2_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(subisomorphic_vf2_impl(g1, g2)) + expect_snapshot(subisomorphic_vf2_impl( + g1, + g2, + vertex.color1 = c(1, 2, 3), + vertex.color2 = c(1, 2, 3), + edge.color1 = c(1, 2), + edge.color2 = c(1, 2) + )) +}) + +test_that("subisomorphic_vf2_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + subisomorphic_vf2_impl(NULL, path_graph_impl(3)) + ) +}) + +# 287. count_subisomorphisms_vf2_impl + +test_that("count_subisomorphisms_vf2_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(count_subisomorphisms_vf2_impl(g1, g2)) + expect_snapshot(count_subisomorphisms_vf2_impl( + g1, + g2, + vertex.color1 = c(1, 2, 3), + vertex.color2 = c(1, 2, 3), + edge.color1 = c(1, 2), + edge.color2 = c(1, 2) + )) +}) + +test_that("count_subisomorphisms_vf2_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + count_subisomorphisms_vf2_impl(NULL, path_graph_impl(3)) + ) +}) + +# 288. get_subisomorphisms_vf2_impl + +test_that("get_subisomorphisms_vf2_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(get_subisomorphisms_vf2_impl(g1, g2)) + expect_snapshot(get_subisomorphisms_vf2_impl( + g1, + g2, + vertex.color1 = c(1, 2, 3), + vertex.color2 = c(1, 2, 3), + edge.color1 = c(1, 2), + edge.color2 = c(1, 2) + )) +}) + +test_that("get_subisomorphisms_vf2_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + get_subisomorphisms_vf2_impl(NULL, path_graph_impl(3)) + ) +}) + +# 289. canonical_permutation_impl + +test_that("canonical_permutation_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(canonical_permutation_impl(g)) + expect_snapshot(canonical_permutation_impl(g, colors = c(1, 2, 3), sh = "fl")) +}) + +test_that("canonical_permutation_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(canonical_permutation_impl(NULL)) +}) + +# 290. permute_vertices_impl + +test_that("permute_vertices_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(permute_vertices_impl(g, permutation = 3:1)) +}) + +test_that("permute_vertices_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(permute_vertices_impl(NULL, permutation = 3:1)) +}) + +# 291. isomorphic_bliss_impl + +test_that("isomorphic_bliss_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + g2 <- path_graph_impl(3) + expect_snapshot(isomorphic_bliss_impl(g1, g2)) + expect_snapshot(isomorphic_bliss_impl( + g1, + g2, + colors1 = c(1, 2, 3), + colors2 = c(1, 2, 3), + sh = "fl" + )) +}) + +test_that("isomorphic_bliss_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(isomorphic_bliss_impl(NULL, path_graph_impl(3))) +}) + +# 292. count_automorphisms_impl + +test_that("count_automorphisms_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(count_automorphisms_impl(g)) + expect_snapshot(count_automorphisms_impl(g, colors = c(1, 2, 3), sh = "fl")) +}) + +test_that("count_automorphisms_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(count_automorphisms_impl(NULL)) +}) + +# 293. automorphism_group_impl + +test_that("automorphism_group_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(automorphism_group_impl(g)) + expect_snapshot(automorphism_group_impl( + g, + colors = c(1, 2, 3), + sh = "fl", + details = TRUE + )) +}) + +test_that("automorphism_group_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(automorphism_group_impl(NULL)) +}) + +# 294. simplify_and_colorize_impl + +test_that("simplify_and_colorize_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(simplify_and_colorize_impl(g)) +}) + +test_that("simplify_and_colorize_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(simplify_and_colorize_impl(NULL)) +}) + +# 295. graph_count_impl + +test_that("graph_count_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(graph_count_impl(3)) + expect_snapshot(graph_count_impl(3, directed = TRUE)) +}) + +test_that("graph_count_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(graph_count_impl("a")) +}) + +# 296. is_matching_impl + +test_that("is_matching_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_matching_impl(g, matching = 1:2)) + expect_snapshot(is_matching_impl( + g, + types = c(TRUE, FALSE, TRUE), + matching = 1:2 + )) +}) + +test_that("is_matching_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_matching_impl(NULL, matching = 1:2)) +}) + +# 297. is_maximal_matching_impl + +test_that("is_maximal_matching_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_maximal_matching_impl(g, matching = 1:2)) + expect_snapshot(is_maximal_matching_impl( + g, + types = c(TRUE, FALSE, TRUE), + matching = 1:2 + )) +}) + +test_that("is_maximal_matching_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_maximal_matching_impl(NULL, matching = 1:2)) +}) + +# 298. maximum_bipartite_matching_impl + +test_that("maximum_bipartite_matching_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(maximum_bipartite_matching_impl( + g, + types = c(TRUE, FALSE, TRUE) + )) + expect_snapshot(maximum_bipartite_matching_impl( + g, + types = c(TRUE, FALSE, TRUE), + weights = c(1, 2), + eps = 1e-5 + )) +}) + +test_that("maximum_bipartite_matching_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + maximum_bipartite_matching_impl(NULL, types = c(TRUE, FALSE, TRUE)) + ) +}) + +# 299. adjacency_spectral_embedding_impl + +test_that("adjacency_spectral_embedding_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(adjacency_spectral_embedding_impl(g, no = 2)) + expect_snapshot(adjacency_spectral_embedding_impl( + g, + no = 2, + weights = c(1, 2), + which = "la", + scaled = FALSE, + cvec = c(1, 2, 3), + options = list(maxiter = 10) + )) +}) + +test_that("adjacency_spectral_embedding_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(adjacency_spectral_embedding_impl(NULL, no = 2)) +}) + +# 300. laplacian_spectral_embedding_impl + +test_that("laplacian_spectral_embedding_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(laplacian_spectral_embedding_impl(g, no = 2)) +}) + +test_that("laplacian_spectral_embedding_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(laplacian_spectral_embedding_impl(NULL, no = 2)) +}) + +# 301. eigen_adjacency_impl + +test_that("eigen_adjacency_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(eigen_adjacency_impl(g)) + expect_snapshot_igraph_error( + eigen_adjacency_impl( + g, + algorithm = "lapack", + which = list(which = "LA"), + options = list(maxiter = 10) + ) + ) +}) + +test_that("eigen_adjacency_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(eigen_adjacency_impl(NULL)) +}) + +# 302. power_law_fit_impl + +test_that("power_law_fit_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(power_law_fit_impl(c(1, 2, 3))) + expect_snapshot(power_law_fit_impl( + c(1, 2, 3), + xmin = 1, + force.continuous = TRUE + )) +}) + +test_that("power_law_fit_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(power_law_fit_impl("a")) +}) + +# 303. sir_impl + +test_that("sir_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(sir_impl(g, beta = 0.1, gamma = 0.1)) + expect_snapshot(sir_impl(g, beta = 0.1, gamma = 0.1, no.sim = 2)) +}) + +test_that("sir_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(sir_impl(NULL, beta = 0.1, gamma = 0.1)) +}) + +# 304. convex_hull_2d_impl + +test_that("convex_hull_2d_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(convex_hull_2d_impl(matrix(1:6, ncol = 2))) +}) + +test_that("convex_hull_2d_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(convex_hull_2d_impl("a")) +}) + +# 305. dim_select_impl + +test_that("dim_select_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(dim_select_impl(c(1, 2, 3))) +}) + +test_that("dim_select_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(dim_select_impl(NULL)) +}) + +# 306. solve_lsap_impl + +test_that("solve_lsap_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(solve_lsap_impl(matrix(1:4, ncol = 2), n = 2)) +}) + +test_that("solve_lsap_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(solve_lsap_impl("a", n = 2)) +}) + +# 307. find_cycle_impl + +test_that("find_cycle_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(find_cycle_impl(g)) + expect_snapshot(find_cycle_impl(g, mode = "in")) +}) + +test_that("find_cycle_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(find_cycle_impl(NULL)) +}) + +# 308. simple_cycles_impl + +test_that("simple_cycles_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(simple_cycles_impl(g)) + expect_snapshot(simple_cycles_impl( + g, + mode = "in", + min.cycle.length = 2, + max.cycle.length = 3 + )) +}) + +test_that("simple_cycles_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(simple_cycles_impl(NULL)) +}) + +# 309. is_eulerian_impl + +test_that("is_eulerian_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_eulerian_impl(g)) +}) + +test_that("is_eulerian_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_eulerian_impl(NULL)) +}) + +# 310. eulerian_path_impl + +test_that("eulerian_path_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(eulerian_path_impl(g)) +}) + +test_that("eulerian_path_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(eulerian_path_impl(NULL)) +}) + +# 311. eulerian_cycle_impl + +test_that("eulerian_cycle_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g1 <- path_graph_impl(3) + expect_snapshot_igraph_error(eulerian_cycle_impl(g1)) + g2 <- cycle_graph_impl(4) + expect_snapshot(eulerian_cycle_impl(g2)) +}) + +test_that("eulerian_cycle_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(eulerian_cycle_impl(NULL)) +}) + +# 312. fundamental_cycles_impl + +test_that("fundamental_cycles_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(fundamental_cycles_impl(g, start = 1)) + expect_snapshot(fundamental_cycles_impl( + g, + start = 1, + bfs.cutoff = 2, + weights = c(1, 2) + )) +}) + +test_that("fundamental_cycles_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(fundamental_cycles_impl(NULL, start = 1)) +}) + +# 313. minimum_cycle_basis_impl + +test_that("minimum_cycle_basis_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(minimum_cycle_basis_impl(g)) + expect_snapshot(minimum_cycle_basis_impl( + g, + bfs.cutoff = 2, + complete = FALSE, + use.cycle.order = FALSE, + weights = c(1, 2) + )) +}) + +test_that("minimum_cycle_basis_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(minimum_cycle_basis_impl(NULL)) +}) + +# 314. is_tree_impl + +test_that("is_tree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_tree_impl(g)) + expect_snapshot(is_tree_impl(g, mode = "in", details = TRUE)) +}) + +test_that("is_tree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_tree_impl(NULL)) +}) + +# 315. is_forest_impl + +test_that("is_forest_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_forest_impl(g)) + expect_snapshot(is_forest_impl(g, mode = "in", details = TRUE)) +}) + +test_that("is_forest_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_forest_impl(NULL)) +}) + +# 316. from_prufer_impl + +test_that("from_prufer_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(from_prufer_impl(1:2)) +}) + +test_that("from_prufer_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(from_prufer_impl("a")) +}) + +# 317. to_prufer_impl + +test_that("to_prufer_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(to_prufer_impl(g)) +}) + +test_that("to_prufer_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(to_prufer_impl(NULL)) +}) + +# 318. tree_from_parent_vector_impl + +test_that("tree_from_parent_vector_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(tree_from_parent_vector_impl(c(-1, 1, 2, 3))) + expect_snapshot(tree_from_parent_vector_impl(c(-1, 1, 2, 3), type = "in")) +}) + +test_that("tree_from_parent_vector_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(tree_from_parent_vector_impl("a")) +}) + +# 319. is_complete_impl + +test_that("is_complete_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_complete_impl(g)) +}) + +test_that("is_complete_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_complete_impl(NULL)) +}) + +# 320. random_spanning_tree_impl + +test_that("random_spanning_tree_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(random_spanning_tree_impl(g, vid = 1)) +}) + +test_that("random_spanning_tree_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(random_spanning_tree_impl(NULL, vid = 1)) +}) + +# 321. tree_game_impl + +test_that("tree_game_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot(tree_game_impl(3)) + expect_snapshot(tree_game_impl(3, directed = TRUE, method = "lerw")) +}) + +test_that("tree_game_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(tree_game_impl("a")) +}) + +# 322. vertex_coloring_greedy_impl + +test_that("vertex_coloring_greedy_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(vertex_coloring_greedy_impl(g)) + expect_snapshot(vertex_coloring_greedy_impl(g, heuristic = "dsatur")) +}) + +test_that("vertex_coloring_greedy_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(vertex_coloring_greedy_impl(NULL)) +}) + +# 323. is_vertex_coloring_impl + +test_that("is_vertex_coloring_impl basic", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_vertex_coloring_impl(g, types = c(1, 2, 3))) +}) + +test_that("is_vertex_coloring_impl errors", { + withr::local_seed(20250909) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + is_vertex_coloring_impl(NULL, types = c(1, 2, 3)) + ) +}) + +# 324. is_bipartite_coloring_impl + +# test_that("is_bipartite_coloring_impl basic", { +# withr::local_seed(20250909) +# oldval <- igraph_opt("print.id") +# igraph_options(print.id = FALSE) +# g <- path_graph_impl(3) +# expect_snapshot(is_bipartite_coloring_impl(g, types = c(TRUE, FALSE, TRUE))) +#}) + +# 325. is_bipartite_coloring_impl + +test_that("is_bipartite_coloring_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(is_bipartite_coloring_impl(g, types = c(TRUE, FALSE, TRUE))) +}) + +test_that("is_bipartite_coloring_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + is_bipartite_coloring_impl(NULL, types = c(TRUE, FALSE, TRUE)) + ) +}) + +# 326. is_edge_coloring_impl + +test_that("is_edge_coloring_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + E(g)$color <- c(1, 2) + expect_snapshot(is_edge_coloring_impl(g, types = c(1, 2))) + expect_snapshot(is_edge_coloring_impl(g)) +}) + +test_that("is_edge_coloring_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(is_edge_coloring_impl(NULL, types = c(1, 2))) +}) + +# 327. deterministic_optimal_imitation_impl + +test_that("deterministic_optimal_imitation_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(deterministic_optimal_imitation_impl( + g, + 1, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3) + )) + expect_snapshot(deterministic_optimal_imitation_impl( + g, + 1, + optimality = "minimum", + quantities = c(1, 2, 3), + strategies = c(1, 2, 3), + mode = "in" + )) +}) + +test_that("deterministic_optimal_imitation_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + deterministic_optimal_imitation_impl( + NULL, + 1, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3) + ) + ) +}) + +# 328. moran_process_impl + +test_that("moran_process_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(moran_process_impl( + g, + weights = c(1, 1), + quantities = c(1, 2, 3), + strategies = c(1, 2, 3), + mode = "in" + )) +}) + +test_that("moran_process_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + moran_process_impl(NULL, quantities = c(1, 2, 3), strategies = c(1, 2, 3)) + ) +}) + +# 329. roulette_wheel_imitation_impl + +test_that("roulette_wheel_imitation_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(roulette_wheel_imitation_impl( + g, + 1, + TRUE, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3) + )) + expect_snapshot(roulette_wheel_imitation_impl( + g, + 1, + FALSE, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3), + mode = "in" + )) +}) + +test_that("roulette_wheel_imitation_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + roulette_wheel_imitation_impl( + NULL, + 1, + TRUE, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3) + ) + ) +}) + +# 330. stochastic_imitation_impl + +test_that("stochastic_imitation_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(stochastic_imitation_impl( + g, + 1, + algo = 1, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3) + )) + expect_snapshot(stochastic_imitation_impl( + g, + 1, + algo = 2, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3), + mode = "in" + )) +}) + +test_that("stochastic_imitation_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + stochastic_imitation_impl( + NULL, + 1, + algo = 1, + quantities = c(1, 2, 3), + strategies = c(1, 2, 3) + ) + ) +}) + +# 331. invalidate_cache_impl + +test_that("invalidate_cache_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(invalidate_cache_impl(g)) +}) + +test_that("invalidate_cache_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error(invalidate_cache_impl(NULL)) +}) + +# 332. vertex_path_from_edge_path_impl + +test_that("vertex_path_from_edge_path_impl basic", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + g <- path_graph_impl(3) + expect_snapshot(vertex_path_from_edge_path_impl( + g, + start = 1, + edge.path = c(1, 2) + )) + expect_snapshot(vertex_path_from_edge_path_impl( + g, + start = 1, + edge.path = c(1), + mode = "in" + )) +}) + +test_that("vertex_path_from_edge_path_impl errors", { + withr::local_seed(12345) + local_igraph_options(print.id = FALSE) + expect_snapshot_igraph_error( + vertex_path_from_edge_path_impl(NULL, start = 1, edge.path = c(1, 2)) + ) +}) + +# 333. version_impl + +test_that("version_impl basic", { + withr::local_seed(12345) + version_impl_clean <- function() { + v <- version_impl() + paste(v$major, v$minor, v$subminor, sep = ".") + } + expect_snapshot(version_impl_clean()) +}) + +test_that("version_impl errors", { + withr::local_seed(12345) + # version_impl() has no parameters, so testing with invalid arguments + expect_snapshot_igraph_error(version_impl("invalid")) +}) diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 0522aeeaae5..0e846eee81a 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -504,7 +504,7 @@ igraph_bipartite_projection: IGNORE: RR, RC, RInit igraph_biadjacency: - DEPS: types ON graph V(graph) + DEPS: types ON res$graph V(res$graph) # Use the name 'type' instead of 'types' (provided by the C core) igraph_is_bipartite: @@ -520,6 +520,9 @@ igraph_bipartite_game_gnp: igraph_bipartite_game: IGNORE: RR, RC +igraph_full_bipartite: + DEPS: types ON res$graph + ####################################### # Spectral properties diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index b44fedd204e..0b3b8d0ddb6 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -260,6 +260,7 @@ ISOCOMPAT_FUNC: HEADER: ~ VERTEXSET_LIST: + CALL: lapply(%I%, function(.x) .x-1) OUTCONV: OUT: |- if (igraph_opt("return.vs.es")) { @@ -267,6 +268,7 @@ VERTEXSET_LIST: } EDGESET_LIST: + CALL: lapply(%I%, function(.x) .x-1) OUTCONV: OUT: |- if (igraph_opt("return.vs.es")) { From ff1d72db58539e995719074b909f1239a83b5517 Mon Sep 17 00:00:00 2001 From: David Schoch Date: Fri, 12 Sep 2025 10:01:03 +0200 Subject: [PATCH 047/154] test: added tests for `plot.shapes.R` (#2139) --- .../_snaps/plot.shapes/edge-test-circle.svg | 59 ++++ .../plot.shapes/edge-test-rectangle.svg | 59 ++++ .../_snaps/plot.shapes/edge-test-square.svg | 59 ++++ .../plot.shapes/mixed-vertex-parameters.svg | 53 ++++ .../_snaps/plot.shapes/pie-chart-vertices.svg | 51 ++++ .../plot.shapes/vertex-shape-circle.svg | 61 ++++ .../plot.shapes/vertex-shape-crectangle.svg | 61 ++++ .../plot.shapes/vertex-shape-csquare.svg | 61 ++++ .../_snaps/plot.shapes/vertex-shape-none.svg | 51 ++++ .../_snaps/plot.shapes/vertex-shape-pie.svg | 81 ++++++ .../plot.shapes/vertex-shape-rectangle.svg | 61 ++++ .../plot.shapes/vertex-shape-sphere.svg | 61 ++++ .../plot.shapes/vertex-shape-square.svg | 61 ++++ .../vertex-shape-test-deprecated.svg | 51 ++++ .../plot.shapes/vertex-shape-test-shape.svg | 51 ++++ .../plot.shapes/vertex-shape-vrectangle.svg | 61 ++++ tests/testthat/test-plot.shapes.R | 274 ++++++++++++++++++ 17 files changed, 1216 insertions(+) create mode 100644 tests/testthat/_snaps/plot.shapes/edge-test-circle.svg create mode 100644 tests/testthat/_snaps/plot.shapes/edge-test-rectangle.svg create mode 100644 tests/testthat/_snaps/plot.shapes/edge-test-square.svg create mode 100644 tests/testthat/_snaps/plot.shapes/mixed-vertex-parameters.svg create mode 100644 tests/testthat/_snaps/plot.shapes/pie-chart-vertices.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-circle.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-crectangle.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-csquare.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-none.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-pie.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-rectangle.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-sphere.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-square.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-test-shape.svg create mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-vrectangle.svg create mode 100644 tests/testthat/test-plot.shapes.R diff --git a/tests/testthat/_snaps/plot.shapes/edge-test-circle.svg b/tests/testthat/_snaps/plot.shapes/edge-test-circle.svg new file mode 100644 index 00000000000..f6152da24ea --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/edge-test-circle.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + +-15 +-10 +-5 +0 +5 +10 +15 + + + + + + +-10 +-5 +0 +5 +10 + +single_coords[,1] +single_coords[,2] + + + + + + + + + + diff --git a/tests/testthat/_snaps/plot.shapes/edge-test-rectangle.svg b/tests/testthat/_snaps/plot.shapes/edge-test-rectangle.svg new file mode 100644 index 00000000000..74578a24b14 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/edge-test-rectangle.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + +-15 +-10 +-5 +0 +5 +10 +15 + + + + + + +-10 +-5 +0 +5 +10 + +single_coords[,1] +single_coords[,2] + + + + + + + + + + diff --git a/tests/testthat/_snaps/plot.shapes/edge-test-square.svg b/tests/testthat/_snaps/plot.shapes/edge-test-square.svg new file mode 100644 index 00000000000..20116a43347 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/edge-test-square.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + +-15 +-10 +-5 +0 +5 +10 +15 + + + + + + +-10 +-5 +0 +5 +10 + +single_coords[,1] +single_coords[,2] + + + + + + + + + + diff --git a/tests/testthat/_snaps/plot.shapes/mixed-vertex-parameters.svg b/tests/testthat/_snaps/plot.shapes/mixed-vertex-parameters.svg new file mode 100644 index 00000000000..3298e4a90fd --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/mixed-vertex-parameters.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 + + diff --git a/tests/testthat/_snaps/plot.shapes/pie-chart-vertices.svg b/tests/testthat/_snaps/plot.shapes/pie-chart-vertices.svg new file mode 100644 index 00000000000..544c1cbdca6 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/pie-chart-vertices.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-circle.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-circle.svg new file mode 100644 index 00000000000..f1759b68ab5 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-circle.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-crectangle.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-crectangle.svg new file mode 100644 index 00000000000..bb306f5ea4e --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-crectangle.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-csquare.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-csquare.svg new file mode 100644 index 00000000000..1c5ff623277 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-csquare.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-none.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-none.svg new file mode 100644 index 00000000000..dc618748444 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-none.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-pie.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-pie.svg new file mode 100644 index 00000000000..8425dc8c3ed --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-pie.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-rectangle.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-rectangle.svg new file mode 100644 index 00000000000..52054a8ef4c --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-rectangle.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-sphere.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-sphere.svg new file mode 100644 index 00000000000..aecb9dd8fb8 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-sphere.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-square.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-square.svg new file mode 100644 index 00000000000..47720d8e7f2 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-square.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg new file mode 100644 index 00000000000..8f4a1e2d8be --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-test-shape.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-test-shape.svg new file mode 100644 index 00000000000..8f4a1e2d8be --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-test-shape.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-vrectangle.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-vrectangle.svg new file mode 100644 index 00000000000..10ae443cd42 --- /dev/null +++ b/tests/testthat/_snaps/plot.shapes/vertex-shape-vrectangle.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + + diff --git a/tests/testthat/test-plot.shapes.R b/tests/testthat/test-plot.shapes.R new file mode 100644 index 00000000000..948cd89fc29 --- /dev/null +++ b/tests/testthat/test-plot.shapes.R @@ -0,0 +1,274 @@ +# Test shapes() function +test_that("shapes() lists all available shapes", { + all_shapes <- shapes() + expect_type(all_shapes, "character") + expect_true(length(all_shapes) > 0) + expect_true("circle" %in% all_shapes) + expect_true("square" %in% all_shapes) + expect_true("rectangle" %in% all_shapes) +}) + +test_that("shapes() returns specific shape functions", { + circle_shape <- shapes("circle") + expect_type(circle_shape, "list") + expect_named(circle_shape, c("clip", "plot")) + expect_type(circle_shape$clip, "closure") + expect_type(circle_shape$plot, "closure") +}) + +test_that("shapes() returns NULL for non-existent shape", { + expect_null(shapes("nonexistent")) +}) + +test_that("add_shape() validates inputs correctly", { + # Valid inputs + expect_true(add_shape("test_shape")) + expect_true("test_shape" %in% shapes()) + + # Invalid shape name + expect_error(add_shape(123), "must be a character") + expect_error(add_shape(c("a", "b")), "must be a character of length 1") + + # Invalid clip function + expect_error( + add_shape("test2", clip = "not_a_function"), + "must be a function" + ) + + # Invalid plot function + expect_error(add_shape("test3", plot = 123), "must be a function") + + # Invalid parameters + expect_error( + add_shape("test4", parameters = c(1, 2, 3)), + "must be a named list" + ) + expect_error( + add_shape("test5", parameters = list(1, 2)), + "must be a named list" + ) +}) + +test_that("add_shape() can override existing shapes", { + original_circle <- shapes("circle") + dummy_plot <- function(coords, v = NULL, params) invisible(NULL) + + add_shape("circle", plot = dummy_plot) + modified_circle <- shapes("circle") + + expect_false(identical(original_circle$plot, modified_circle$plot)) + + # Restore original + add_shape("circle", clip = original_circle$clip, plot = original_circle$plot) +}) + +test_that("shape_noclip() handles different end parameters", { + coords <- matrix(c(0, 0, 10, 10), nrow = 1) + el <- matrix(c(1, 2), nrow = 1) + params <- function(type, param) 5 + + # Test "both" + result_both <- shape_noclip(coords, el, params, "both") + expect_equal(result_both, coords) + + # Test "from" + result_from <- shape_noclip(coords, el, params, "from") + expect_equal(result_from, coords[, 1:2, drop = FALSE]) + + # Test "to" + result_to <- shape_noclip(coords, el, params, "to") + expect_equal(result_to, coords[, 3:4, drop = FALSE]) +}) + +test_that("shape_noplot() returns invisible NULL", { + coords <- matrix(c(0, 0, 10, 10), nrow = 2) + result <- shape_noplot(coords) + expect_null(result) +}) + +test_that("circle clipping works correctly", { + # Setup test data + coords <- matrix(c(0, 0, 10, 0), nrow = 1) # horizontal line + el <- matrix(c(1, 2), nrow = 1) + params <- function(type, param) { + if (param == "size") { + return(2) + } + return(1) + } + + clip_func <- shapes("circle")$clip + + # Test "from" clipping + result_from <- clip_func(coords, el, params, "from") + expect_equal(ncol(result_from), 2) + expect_true(result_from[1, 1] > 0) # Should be clipped inward + + # Test "to" clipping + result_to <- clip_func(coords, el, params, "to") + expect_equal(ncol(result_to), 2) + expect_true(result_to[1, 1] < 10) # Should be clipped inward + + # Test "both" clipping + result_both <- clip_func(coords, el, params, "both") + expect_equal(ncol(result_both), 4) +}) + +test_that("clipping handles empty coordinates", { + empty_coords <- matrix(numeric(0), nrow = 0, ncol = 4) + el <- matrix(numeric(0), nrow = 0, ncol = 2) + params <- function(type, param) 1 + + for (shape_name in c("circle", "square", "rectangle")) { + clip_func <- shapes(shape_name)$clip + result <- clip_func(empty_coords, el, params, "both") + expect_equal(nrow(result), 0) + } +}) + +test_that("all built-in shapes render correctly", { + skip_if_not_installed("vdiffr") + + g <- make_ring(10) + available_shapes <- setdiff(shapes(), "raster") # Exclude raster if not available + + for (shape in available_shapes) { + vdiffr::expect_doppelganger( + paste("vertex shape", shape), + function() { + plot( + g, + vertex.shape = shape, + vertex.size = 15, + vertex.size2 = 10, # For rectangles + vertex.color = "lightblue", + vertex.frame.color = "black", + vertex.pie = if (shape == "pie") list(c(1, 2, 3)) else list(c(0)), + vertex.pie.color = if (shape == "pie") { + list(c("red", "green", "blue")) + } else { + list("white") + }, + layout = layout_in_circle(g) + ) + } + ) + } +}) + +test_that("shapes work with different vertex parameters", { + skip_if_not_installed("vdiffr") + + g <- make_star(6) + + vdiffr::expect_doppelganger( + "mixed vertex parameters", + function() { + plot( + g, + vertex.shape = c("circle", "square", "rectangle", "circle", "square", "rectangle"), + vertex.size = c(10, 15, 20, 25, 30, 35), + vertex.size2 = c(5, 10, 15, 20, 25, 30), + vertex.color = rainbow(6), + vertex.frame.color = "black", + vertex.frame.width = c(1, 2, 3, 1, 2, 3), + layout = layout_as_star(g) + ) + } + ) +}) + +test_that("pie chart vertices work correctly", { + skip_if_not_installed("vdiffr") + + g <- make_ring(4) + + vdiffr::expect_doppelganger( + "pie chart vertices", + function() { + plot( + g, + vertex.shape = "pie", + vertex.pie = list( + c(1, 2, 3), + c(2, 3, 1), + c(3, 1, 2), + c(1, 1, 1) + ), + vertex.pie.color = list( + c("red", "green", "blue"), + c("yellow", "orange", "purple"), + c("pink", "cyan", "magenta"), + c("brown", "gray", "black") + ), + vertex.size = 20, + layout = layout_in_circle(g) + ) + } + ) +}) + +test_that("deprecated functions still work with warnings", { + # Test deprecated wrapper functions + lifecycle::expect_deprecated( + result1 <- igraph.shape.noplot(matrix(c(0, 0), nrow = 1)) + ) + expect_null(result1) + + lifecycle::expect_deprecated( + result2 <- vertex.shapes() + ) + expect_type(result2, "character") + + lifecycle::expect_deprecated( + result3 <- add.vertex.shape("test_deprecated") + ) + expect_true(result3) +}) + +test_that("shape functions handle edge cases", { + skip_if_not_installed("vdiffr") + + # Test with single vertex + single_coords <- matrix(c(0, 0), nrow = 1) + params <- function(type, param) { + switch( + param, + "size" = 5, + "color" = "red", + "frame.color" = "black", + "frame.width" = 1, + 1 + ) + } + + for (shape_name in c("circle", "square", "rectangle")) { + plot_func <- shapes(shape_name)$plot + + vdiffr::expect_doppelganger(paste0("edge-test ", shape_name), function() { + plot( + single_coords, + type = "n", + xlim = c(-10, 10), + ylim = c(-10, 10), + asp = 1 + ) + plot_func(single_coords, NULL, params) + }) + } + + # Test with zero-size vertices + params_zero <- function(type, param) { + if (param == "size") { + return(0) + } + return(1) + } + + for (shape_name in c("circle", "square")) { + clip_func <- shapes(shape_name)$clip + coords <- matrix(c(0, 0, 10, 10), nrow = 1) + el <- matrix(c(1, 2), nrow = 1) + expect_silent(clip_func(coords, el, params_zero, "both")) + } +}) From 0dda55feb6afb64d129974c3c9892eda37e4f8b0 Mon Sep 17 00:00:00 2001 From: David Schoch Date: Fri, 12 Sep 2025 10:30:03 +0200 Subject: [PATCH 048/154] test: added tests for `palette.R` (#2140) --- R/palette.R | 2 +- .../categorical-palette-3-vertices.svg | 40 +++ .../categorical-palette-5-vertices.svg | 46 +++ .../categorical-palette-8-vertices.svg | 55 ++++ .../_snaps/palette/categorical-palette.svg | 55 ++++ .../_snaps/palette/diverging-palette.svg | 55 ++++ .../_snaps/palette/sequential-palette.svg | 55 ++++ tests/testthat/test-degseq.R | 6 + tests/testthat/test-palette.R | 267 ++++++++++++++++++ 9 files changed, 580 insertions(+), 1 deletion(-) create mode 100644 tests/testthat/_snaps/palette/categorical-palette-3-vertices.svg create mode 100644 tests/testthat/_snaps/palette/categorical-palette-5-vertices.svg create mode 100644 tests/testthat/_snaps/palette/categorical-palette-8-vertices.svg create mode 100644 tests/testthat/_snaps/palette/categorical-palette.svg create mode 100644 tests/testthat/_snaps/palette/diverging-palette.svg create mode 100644 tests/testthat/_snaps/palette/sequential-palette.svg create mode 100644 tests/testthat/test-palette.R diff --git a/R/palette.R b/R/palette.R index 47b9ff0676f..2063fbad590 100644 --- a/R/palette.R +++ b/R/palette.R @@ -281,5 +281,5 @@ r_pal <- function(n) { cli::cli_warn("Cannot make {n} divergent colors.") } n <- min(n, length(x)) - if (n == 0) character() else x[[n]] + x[seq_len(n)] } diff --git a/tests/testthat/_snaps/palette/categorical-palette-3-vertices.svg b/tests/testthat/_snaps/palette/categorical-palette-3-vertices.svg new file mode 100644 index 00000000000..702644df565 --- /dev/null +++ b/tests/testthat/_snaps/palette/categorical-palette-3-vertices.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 + + diff --git a/tests/testthat/_snaps/palette/categorical-palette-5-vertices.svg b/tests/testthat/_snaps/palette/categorical-palette-5-vertices.svg new file mode 100644 index 00000000000..f9c5b149fc8 --- /dev/null +++ b/tests/testthat/_snaps/palette/categorical-palette-5-vertices.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 + + diff --git a/tests/testthat/_snaps/palette/categorical-palette-8-vertices.svg b/tests/testthat/_snaps/palette/categorical-palette-8-vertices.svg new file mode 100644 index 00000000000..d70a810cb72 --- /dev/null +++ b/tests/testthat/_snaps/palette/categorical-palette-8-vertices.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 + + diff --git a/tests/testthat/_snaps/palette/categorical-palette.svg b/tests/testthat/_snaps/palette/categorical-palette.svg new file mode 100644 index 00000000000..346d8c4cad8 --- /dev/null +++ b/tests/testthat/_snaps/palette/categorical-palette.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 + + diff --git a/tests/testthat/_snaps/palette/diverging-palette.svg b/tests/testthat/_snaps/palette/diverging-palette.svg new file mode 100644 index 00000000000..d3e8cf5125f --- /dev/null +++ b/tests/testthat/_snaps/palette/diverging-palette.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 + + diff --git a/tests/testthat/_snaps/palette/sequential-palette.svg b/tests/testthat/_snaps/palette/sequential-palette.svg new file mode 100644 index 00000000000..be6cf457135 --- /dev/null +++ b/tests/testthat/_snaps/palette/sequential-palette.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 + + diff --git a/tests/testthat/test-degseq.R b/tests/testthat/test-degseq.R index ada62dc796f..6aab1804e0e 100644 --- a/tests/testthat/test-degseq.R +++ b/tests/testthat/test-degseq.R @@ -33,3 +33,9 @@ test_that("realize_degseq supports the make_(...) syntax", { expect_identical_graphs(g1, g2) }) + +test_that("is_degseq works", { + g <- make_full_graph(10) + expect_true(is_degseq(degree(g))) + expect_true(is_graphical(degree(g))) +}) diff --git a/tests/testthat/test-palette.R b/tests/testthat/test-palette.R new file mode 100644 index 00000000000..1f927ed0599 --- /dev/null +++ b/tests/testthat/test-palette.R @@ -0,0 +1,267 @@ +test_that("categorical_pal() works correctly", { + # Basic functionality + pal1 <- categorical_pal(1) + expect_length(pal1, 1) + expect_equal(pal1, "#E69F00") + + pal3 <- categorical_pal(3) + expect_length(pal3, 3) + expect_equal(pal3, c("#E69F00", "#56B4E9", "#009E73")) + + # Maximum colors + pal8 <- categorical_pal(8) + expect_length(pal8, 8) + expect_equal(pal8[1], "#E69F00") + expect_equal(pal8[8], "#999999") + + # All colors are valid hex codes + expect_true(all(grepl("^#[0-9A-F]{6}$", pal8))) +}) + +test_that("categorical_pal() handles edge cases", { + # Warning for too many colors + expect_warning( + result <- categorical_pal(10), + "Cannot make 10 categorical colors" + ) + expect_length(result, 8) # Should return max available + + # Error for invalid input + expect_error(categorical_pal(0)) + expect_error(categorical_pal(-1)) + expect_error(categorical_pal(NULL)) +}) + +test_that("sequential_pal() works correctly", { + # Test different sizes + pal1 <- sequential_pal(1) + expect_length(pal1, 1) + expect_equal(pal1, "#FEE8C8") + + pal3 <- sequential_pal(3) + expect_length(pal3, 3) + expect_equal(pal3, c("#FEE8C8", "#FDBB84", "#E34A33")) + + # Maximum colors + pal9 <- sequential_pal(9) + expect_length(pal9, 9) + expect_true(all(grepl("^#[0-9A-F]{6}$", pal9))) + + # Sequential order (should get progressively darker/more intense) + # Test that first color is lighter than last + first_color <- pal9[1] + last_color <- pal9[9] + expect_equal(first_color, "#FFF7EC") # Lightest + expect_equal(last_color, "#7F0000") # Darkest +}) + +test_that("sequential_pal() handles edge cases", { + # Zero colors + pal0 <- sequential_pal(0) + expect_length(pal0, 0) + expect_type(pal0, "character") + + # Warning for too many colors + expect_warning( + result <- sequential_pal(15), + "Cannot make 15 sequential colors" + ) + expect_length(result, 9) # Should return max available + + # Error for invalid input + expect_error(sequential_pal(-1)) + expect_error(sequential_pal(NULL)) +}) + +test_that("diverging_pal() works correctly", { + # Test different sizes + pal1 <- diverging_pal(1) + expect_length(pal1, 1) + expect_equal(pal1, "#F1A340") + + pal5 <- diverging_pal(5) + expect_length(pal5, 5) + expect_equal(pal5, c("#E66101", "#FDB863", "#F7F7F7", "#B2ABD2", "#5E3C99")) + + # Maximum colors + pal11 <- diverging_pal(11) + expect_length(pal11, 11) + expect_true(all(grepl("^#[0-9A-F]{6}$", pal11))) + + # Should have neutral color in middle for odd numbers + pal7 <- diverging_pal(7) + expect_equal(pal7[4], "#F7F7F7") # Middle should be neutral +}) + +test_that("diverging_pal() handles edge cases", { + # Warning for too many colors + expect_warning( + result <- diverging_pal(15), + "Cannot make 15 divergent colors" + ) + expect_length(result, 11) # Should return max available + + # Error for invalid input + expect_error(diverging_pal(0)) + expect_error(diverging_pal(-1)) + expect_error(diverging_pal(NULL)) +}) + +test_that("r_pal() works correctly", { + # Test different sizes + pal1 <- r_pal(1) + expect_length(pal1, 1) + + pal3 <- r_pal(3) + expect_length(pal3, 3) + + # Maximum colors (should match R's default palette) + pal8 <- r_pal(8) + expect_length(pal8, 8) + expect_equal(pal8, palette()[1:8]) + + # Colors should be valid R color names or hex codes + expect_true(all(nzchar(pal8))) +}) + +test_that("r_pal() handles edge cases", { + # Warning for too many colors (note: message says "divergent" - this might be a bug!) + expect_warning( + result <- r_pal(15), + "Cannot make 15 divergent colors" # This warning message seems wrong + ) + + # Zero colors + pal0 <- r_pal(0) + expect_length(pal0, 0) + expect_type(pal0, "character") + + # Error for invalid input + expect_error(r_pal(-1)) + expect_error(r_pal(NULL)) +}) +test_that("all palettes return valid colors", { + palettes <- list( + categorical = categorical_pal, + sequential = sequential_pal, + diverging = diverging_pal, + r = r_pal + ) + + for (pal_name in names(palettes)) { + pal_func <- palettes[[pal_name]] + + # Test with small number + colors <- suppressWarnings(pal_func(3)) + expect_true(all(nzchar(colors)), info = paste("Empty colors in", pal_name)) + + # Colors should be unique within palette + expect_equal( + length(colors), + length(unique(colors)), + info = paste("Duplicate colors in", pal_name) + ) + } +}) + +test_that("categorical palette is color-blind friendly", { + # The categorical palette should be distinguishable + # Test that we have the expected color-blind friendly colors + pal8 <- categorical_pal(8) + expected_colors <- c( + "#E69F00", "#56B4E9", "#009E73", "#F0E442", + "#0072B2", "#D55E00", "#CC79A7", "#999999" + ) + expect_equal(pal8, expected_colors) +}) + +test_that("diverging palette is symmetric where appropriate", { + # For odd numbers, middle color should be neutral + for (n in c(3, 5, 7, 9, 11)) { + if (n <= 11) { + pal <- diverging_pal(n) + middle_idx <- ceiling(n / 2) + expect_equal( + pal[middle_idx], + "#F7F7F7", + info = paste("Middle color not neutral for n =", n) + ) + } + } +}) +test_that("palettes work with igraph plotting", { + skip_if_not_installed("vdiffr") + + g <- make_ring(8) + + # Test categorical palette + vdiffr::expect_doppelganger( + "categorical palette", + function() { + V(g)$color <- categorical_pal(vcount(g)) + plot(g, vertex.size = 20, layout = layout_in_circle(g)) + } + ) + + # Test sequential palette + vdiffr::expect_doppelganger( + "sequential palette", + function() { + V(g)$color <- sequential_pal(vcount(g)) + plot(g, vertex.size = 20, layout = layout_in_circle(g)) + } + ) + + # Test diverging palette + vdiffr::expect_doppelganger( + "diverging palette", + function() { + V(g)$color <- diverging_pal(vcount(g)) + plot(g, vertex.size = 20, layout = layout_in_circle(g)) + } + ) +}) + +test_that("palettes work with different graph sizes", { + skip_if_not_installed("vdiffr") + + # Test with different numbers of vertices + for (n in c(3, 5, 8)) { + g <- make_ring(n) + + vdiffr::expect_doppelganger( + paste("categorical palette", n, "vertices"), + function() { + V(g)$color <- categorical_pal(vcount(g)) + plot(g, vertex.size = 25, layout = layout_in_circle(g)) + } + ) + } +}) +test_that("palettes handle unusual inputs gracefully", { + # Test with floating point inputs (should be truncated/converted) + expect_silent(categorical_pal(3.7)) + expect_length(categorical_pal(3.7), 3) + + # Test with very large numbers + expect_warning(categorical_pal(1000)) + expect_warning(sequential_pal(1000)) + expect_warning(diverging_pal(1000)) + + # Test that warnings are informative + expect_warning( + categorical_pal(20), + "Cannot make 20 categorical colors" + ) +}) + +test_that("r_pal warning message bug", { + # This test documents what appears to be a bug in r_pal + # The warning message says "divergent colors" instead of "R palette colors" + expect_warning( + r_pal(15), + "Cannot make 15 divergent colors" # This should probably be "R palette colors" + ) + + # This test can be updated when the bug is fixed +}) From ea0a8bd61b605235acbb0ee86b193d0d7d12a526 Mon Sep 17 00:00:00 2001 From: David Schoch Date: Fri, 12 Sep 2025 12:05:22 +0200 Subject: [PATCH 049/154] chore: add nocov to `tkplot.R` (#2141) --- R/tkplot.R | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/R/tkplot.R b/R/tkplot.R index 9838ce1c683..0e39ec364a8 100644 --- a/R/tkplot.R +++ b/R/tkplot.R @@ -325,6 +325,7 @@ assign(".next", 1, .tkplot.env) #' } #' tkplot <- function(graph, canvas.width = 450, canvas.height = 450, ...) { + # nocov start ensure_igraph(graph) # Libraries @@ -799,12 +800,13 @@ tkplot <- function(graph, canvas.width = 450, canvas.height = 450, ...) { ) tkp.id + # nocov end } ################################################################### # Internal functions handling data about layouts for the GUI ################################################################### - +# nocov start .tkplot.addlayout <- function(name, layout.data) { if (!exists(".layouts", envir = .tkplot.env)) { assign(".layouts", list(), .tkplot.env) @@ -993,7 +995,7 @@ tkplot <- function(graph, canvas.width = 450, canvas.height = 450, ...) { ) ) ) - +# nocov end ################################################################### # Other public functions, misc. ################################################################### @@ -1001,6 +1003,7 @@ tkplot <- function(graph, canvas.width = 450, canvas.height = 450, ...) { #' @rdname tkplot #' @export tk_close <- function(tkp.id, window.close = TRUE) { + # nocov start if (window.close) { cmd <- paste(sep = "", "tkp.", tkp.id, "$top") top <- eval(parse(text = cmd), .tkplot.env) @@ -1010,21 +1013,25 @@ tk_close <- function(tkp.id, window.close = TRUE) { cmd <- paste(sep = "", "tkp.", tkp.id) rm(list = cmd, envir = .tkplot.env) invisible(NULL) + # nocov end } #' @rdname tkplot #' @export tk_off <- function() { + # nocov start eapply(.tkplot.env, function(tkp) { tcltk::tkdestroy(tkp$top) }) rm(list = ls(.tkplot.env), envir = .tkplot.env) invisible(NULL) + # nocov end } #' @rdname tkplot #' @export tk_fit <- function(tkp.id, width = NULL, height = NULL) { + # nocov start tkp <- .tkplot.get(tkp.id) if (is.null(width)) { width <- as.numeric(tcltk::tkwinfo("width", tkp$canvas)) @@ -1051,11 +1058,13 @@ tk_fit <- function(tkp.id, width = NULL, height = NULL) { # Update .tkplot.update.vertices(tkp.id) invisible(NULL) + # nocov end } #' @rdname tkplot #' @export tk_center <- function(tkp.id) { + # nocov start tkp <- .tkplot.get(tkp.id) width <- as.numeric(tcltk::tkwinfo("width", tkp$canvas)) height <- as.numeric(tcltk::tkwinfo("height", tkp$canvas)) @@ -1075,12 +1084,14 @@ tk_center <- function(tkp.id) { # Update .tkplot.update.vertices(tkp.id) invisible(NULL) + # nocov end } #' @rdname tkplot #' @param params Extra parameters in a list, to pass to the layout function. #' @export tk_reshape <- function(tkp.id, newlayout, ..., params) { + # nocov start tkp <- .tkplot.get(tkp.id) new_coords <- do_call( newlayout, @@ -1090,11 +1101,13 @@ tk_reshape <- function(tkp.id, newlayout, ..., params) { tk_fit(tkp.id) .tkplot.update.vertices(tkp.id) invisible(NULL) + # nocov end } #' @rdname tkplot #' @export tk_postscript <- function(tkp.id) { + # nocov start tkp <- .tkplot.get(tkp.id) filename <- tcltk::tkgetSaveFile( @@ -1104,11 +1117,13 @@ tk_postscript <- function(tkp.id) { ) tcltk::tkpostscript(tkp$canvas, file = filename) invisible(NULL) + # nocov end } #' @rdname tkplot #' @export tk_coords <- function(tkp.id, norm = FALSE) { + # nocov start coords <- .tkplot.get(tkp.id, "coords") coords[, 2] <- max(coords[, 2]) - coords[, 2] if (norm) { @@ -1120,20 +1135,24 @@ tk_coords <- function(tkp.id, norm = FALSE) { coords[, 2] <- coords[, 2] / max(coords[, 2]) - 0.5 } coords + # nocov end } #' @rdname tkplot #' @export tk_set_coords <- function(tkp.id, coords) { + # nocov start stopifnot(is.matrix(coords), ncol(coords) == 2) .tkplot.set(tkp.id, "coords", coords) .tkplot.update.vertices(tkp.id) invisible(NULL) + # nocov end } #' @rdname tkplot #' @export tk_rotate <- function(tkp.id, degree = NULL, rad = NULL) { + # nocov start coords <- .tkplot.get(tkp.id, "coords") if (is.null(degree) && is.null(rad)) { @@ -1154,12 +1173,15 @@ tk_rotate <- function(tkp.id, degree = NULL, rad = NULL) { .tkplot.set(tkp.id, "coords", coords) tk_center(tkp.id) invisible(NULL) + # nocov end } #' @rdname tkplot #' @export tk_canvas <- function(tkp.id) { + # nocov start .tkplot.get(tkp.id)$canvas + # nocov end } ################################################################### @@ -1167,6 +1189,7 @@ tk_canvas <- function(tkp.id) { ################################################################### .tkplot.new <- function(tkp) { + # nocov start id <- get(".next", .tkplot.env) assign(".next", id + 1, .tkplot.env) assign("tmp", tkp, .tkplot.env) @@ -1174,34 +1197,42 @@ tk_canvas <- function(tkp.id) { eval(parse(text = cmd), .tkplot.env) rm("tmp", envir = .tkplot.env) id + # nocov end } .tkplot.get <- function(tkp.id, what = NULL) { + # nocov start if (is.null(what)) { get(paste("tkp.", tkp.id, sep = ""), .tkplot.env) } else { cmd <- paste("tkp.", tkp.id, "$", what, sep = "") eval(parse(text = cmd), .tkplot.env) } + # nocov end } .tkplot.set <- function(tkp.id, what, value) { + # nocov start assign("tmp", value, .tkplot.env) cmd <- paste(sep = "", "tkp.", tkp.id, "$", what, "<-tmp") eval(parse(text = cmd), .tkplot.env) rm("tmp", envir = .tkplot.env) TRUE + # nocov end } .tkplot.set.params <- function(tkp.id, what, value) { + # nocov start assign("tmp", value, .tkplot.env) cmd <- paste(sep = "", "tkp.", tkp.id, "$params$", what, "<-tmp") eval(parse(text = cmd), .tkplot.env) rm("tmp", envir = .tkplot.env) TRUE + # nocov end } .tkplot.set.vertex.coords <- function(tkp.id, id, x, y) { + # nocov start cmd <- paste( sep = "", "tkp.", @@ -1216,9 +1247,11 @@ tk_canvas <- function(tkp.id) { ) eval(parse(text = cmd), .tkplot.env) TRUE + # nocov end } .tkplot.set.label.degree <- function(tkp.id, id, phi) { + # nocov start tkp <- .tkplot.get(tkp.id) if (length(tkp$params$label.degree) == 1) { @@ -1241,12 +1274,13 @@ tk_canvas <- function(tkp.id) { eval(parse(text = cmd), .tkplot.env) } TRUE + # nocov end } ################################################################### # Internal functions, creating and updating canvas objects ################################################################### - +# nocov start # Creates a new vertex tk object .tkplot.create.vertex <- function(tkp.id, id, label, x = 0, y = 0) { tkp <- .tkplot.get(tkp.id) @@ -2410,3 +2444,4 @@ i.tkplot.get.edge.lty <- function(edge.lty) { } edge.lty } +# nocov end From 1e3aac92130741ce3f7ec0b98cbedca4a46a16db Mon Sep 17 00:00:00 2001 From: David Schoch Date: Fri, 12 Sep 2025 13:18:24 +0200 Subject: [PATCH 050/154] chore: added more nocov (#2142) --- R/console.R | 2 ++ R/plot.shapes.R | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/R/console.R b/R/console.R index 680ee203ef3..47e748b3402 100644 --- a/R/console.R +++ b/R/console.R @@ -1,3 +1,4 @@ +#nocov start #' The igraph console #' #' @description @@ -330,3 +331,4 @@ close.igraphconsole <- function(con, ...) { pb <- list(widget = pBar, get = get, set = set, label = .lab) list(frame = frame, pb = pb) } +#nocov end diff --git a/R/plot.shapes.R b/R/plot.shapes.R index 7e8bb2d5cd8..9d64483320e 100644 --- a/R/plot.shapes.R +++ b/R/plot.shapes.R @@ -413,7 +413,7 @@ add_shape <- function( } ## These are the predefined shapes - +#nocov start .igraph.shape.circle.clip <- function( coords, el, @@ -1112,7 +1112,7 @@ add_shape <- function( ## does not plot anything at all invisible(NULL) } - +#nocov end #' @importFrom graphics par polygon mypie <- function( x, @@ -1170,7 +1170,7 @@ mypie <- function( ) } } - +#nocov start .igraph.shape.pie.clip <- function( coords, el, @@ -1352,6 +1352,8 @@ mypie <- function( } } +#nocov end + .igraph.shapes <- new.env() .igraph.shapes[["circle"]] <- list( clip = .igraph.shape.circle.clip, From e08591f5cd53dfc99a214106544da80b2715ba14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 12 Sep 2025 14:41:16 +0200 Subject: [PATCH 051/154] test: Stabilize tests on Windows --- tests/testthat/_snaps/aaa-auto.md | 20 ++++++++++---------- tests/testthat/test-aaa-auto.R | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/testthat/_snaps/aaa-auto.md b/tests/testthat/_snaps/aaa-auto.md index 6866c3430cf..ed0a5ad33e8 100644 --- a/tests/testthat/_snaps/aaa-auto.md +++ b/tests/testthat/_snaps/aaa-auto.md @@ -4717,22 +4717,22 @@ # layout_star_impl basic Code - layout_star_impl(g) + round(layout_star_impl(g), 4) Output - [,1] [,2] - [1,] 0 0.000000e+00 - [2,] 1 0.000000e+00 - [3,] -1 1.224647e-16 + [,1] [,2] + [1,] 0 0 + [2,] 1 0 + [3,] -1 0 --- Code - layout_star_impl(g, center = 1, order = 1:3) + round(layout_star_impl(g, center = 1, order = 3:1), 4) Output - [,1] [,2] - [1,] 0 0.000000e+00 - [2,] 1 0.000000e+00 - [3,] -1 1.224647e-16 + [,1] [,2] + [1,] 0 0 + [2,] -1 0 + [3,] 1 0 # layout_star_impl errors diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R index 9a27692368e..4b05a297fc7 100644 --- a/tests/testthat/test-aaa-auto.R +++ b/tests/testthat/test-aaa-auto.R @@ -2914,8 +2914,8 @@ test_that("layout_star_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(layout_star_impl(g)) - expect_snapshot(layout_star_impl(g, center = 1, order = 1:3)) + expect_snapshot(round(layout_star_impl(g), 4)) + expect_snapshot(round(layout_star_impl(g, center = 1, order = 3:1), 4)) }) test_that("layout_star_impl errors", { From 71ba1119bd755fe12ca59fcd750f7865c8c8f120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 12 Sep 2025 16:59:05 +0200 Subject: [PATCH 052/154] test: Skip sanitizer checks with memory leaks --- tests/testthat/test-aaa-auto.R | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R index 4b05a297fc7..6572d21cb1b 100644 --- a/tests/testthat/test-aaa-auto.R +++ b/tests/testthat/test-aaa-auto.R @@ -364,11 +364,13 @@ test_that("mycielski_graph_impl errors", { # 25. adjlist_impl test_that("adjlist_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot(adjlist_impl(list(c(2, 3), c(1), c(1)), mode = "out")) }) test_that("adjlist_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(adjlist_impl(-1, mode = "out")) @@ -2377,6 +2379,7 @@ test_that("trussness_impl errors", { # 163. is_graphical_impl test_that("is_graphical_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot(is_graphical_impl(c(2, 2, 2))) @@ -2388,6 +2391,7 @@ test_that("is_graphical_impl basic", { }) test_that("is_graphical_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(is_graphical_impl("a")) @@ -3382,6 +3386,7 @@ test_that("similarity_jaccard_pairs_impl errors", { # 217. compare_communities_impl test_that("compare_communities_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot(compare_communities_impl(c(1, 2, 1), c(2, 1, 2))) @@ -3393,6 +3398,7 @@ test_that("compare_communities_impl basic", { }) test_that("compare_communities_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(compare_communities_impl("a", c(2, 1, 2))) @@ -3610,6 +3616,7 @@ test_that("hrg_fit_impl errors", { # 229. hrg_sample_impl test_that("hrg_sample_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- make_full_graph(10) @@ -3618,6 +3625,7 @@ test_that("hrg_sample_impl basic", { }) test_that("hrg_sample_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(hrg_sample_impl(NULL)) @@ -3626,6 +3634,7 @@ test_that("hrg_sample_impl errors", { # 230. hrg_sample_many_impl test_that("hrg_sample_many_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- make_full_graph(10) @@ -3634,6 +3643,7 @@ test_that("hrg_sample_many_impl basic", { }) test_that("hrg_sample_many_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(hrg_sample_many_impl(NULL, num.samples = 2)) @@ -3642,6 +3652,7 @@ test_that("hrg_sample_many_impl errors", { # 231. hrg_game_impl test_that("hrg_game_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- make_full_graph(10) @@ -3650,6 +3661,7 @@ test_that("hrg_game_impl basic", { }) test_that("hrg_game_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(hrg_game_impl(NULL)) @@ -3708,6 +3720,7 @@ test_that("hrg_create_impl errors", { # 235. hrg_resize_impl test_that("hrg_resize_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- make_full_graph(10) @@ -3716,6 +3729,7 @@ test_that("hrg_resize_impl basic", { }) test_that("hrg_resize_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(hrg_resize_impl(-1, newsize = 2)) @@ -3724,6 +3738,7 @@ test_that("hrg_resize_impl errors", { # 236. hrg_size_impl test_that("hrg_size_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- make_full_graph(10) @@ -3732,6 +3747,7 @@ test_that("hrg_size_impl basic", { }) test_that("hrg_size_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(hrg_size_impl(-1)) @@ -5184,12 +5200,14 @@ test_that("is_forest_impl errors", { # 316. from_prufer_impl test_that("from_prufer_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot(from_prufer_impl(1:2)) }) test_that("from_prufer_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(from_prufer_impl("a")) @@ -5213,6 +5231,7 @@ test_that("to_prufer_impl errors", { # 318. tree_from_parent_vector_impl test_that("tree_from_parent_vector_impl basic", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot(tree_from_parent_vector_impl(c(-1, 1, 2, 3))) @@ -5220,6 +5239,7 @@ test_that("tree_from_parent_vector_impl basic", { }) test_that("tree_from_parent_vector_impl errors", { + skip_if(Sys.getenv("R_SANITIZER") == "true") withr::local_seed(20250909) local_igraph_options(print.id = FALSE) expect_snapshot_igraph_error(tree_from_parent_vector_impl("a")) From 5cf752a13b1d078c06b7bcc33bc4743fef14a612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 12 Sep 2025 17:49:18 +0200 Subject: [PATCH 053/154] fix: Prevent memory leak --- src/rinterface_extra.c | 2 ++ tests/testthat/test-aaa-auto.R | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 1ab62ad8c14..59b83ff0714 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -3428,12 +3428,14 @@ igraph_error_t R_SEXP_to_vector_int_copy(SEXP sv, igraph_vector_int_t *v) { igraph_integer_t n = Rf_xlength(sv); double *svv=REAL(sv); IGRAPH_CHECK(igraph_vector_int_init(v, n)); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, v); for (igraph_integer_t i = 0; i Date: Tue, 23 Sep 2025 15:10:57 +0200 Subject: [PATCH 054/154] test: Tweak tests --- R/plot.shapes.R | 2 +- .../vertex-shape-test-deprecated.svg | 51 ---------- tests/testthat/test-hrg.R | 93 ++++++++++++++++++- 3 files changed, 92 insertions(+), 54 deletions(-) delete mode 100644 tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg diff --git a/R/plot.shapes.R b/R/plot.shapes.R index 9d64483320e..298e2e3391f 100644 --- a/R/plot.shapes.R +++ b/R/plot.shapes.R @@ -408,7 +408,7 @@ add_shape <- function( } assign(shape, value = list(clip = clip, plot = plot), envir = .igraph.shapes) - do.call(igraph.options, parameters) + do.call(igraph_options, parameters) invisible(TRUE) } diff --git a/tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg b/tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg deleted file mode 100644 index 8f4a1e2d8be..00000000000 --- a/tests/testthat/_snaps/plot.shapes/vertex-shape-test-deprecated.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 - - diff --git a/tests/testthat/test-hrg.R b/tests/testthat/test-hrg.R index 3e636ae107c..381d9669ab1 100644 --- a/tests/testthat/test-hrg.R +++ b/tests/testthat/test-hrg.R @@ -41,8 +41,97 @@ test_that("print.igrapHRG() works", { expect_output(print(small_g, type = "plain"), "->") - big_g <- sample_gnp(110, p = 1 / 2) + sample_gnp(110, p = 1 / 2) - big_hrg <- fit_hrg(big_g) + # big_g <- sample_gnp(110, p = 1 / 2) + sample_gnp(110, p = 1 / 2) + # big_g <- fit_hrg(big_g) + big_hrg <- list( + left = c( + -24, 57, -68, -72, 112, -45, -142, 29, 66, -65, -93, -29, -51, -187, -113, + -175, -91, 122, -197, -138, 158, -36, -89, -210, 188, -74, -125, -39, -41, 5, + -66, -123, 67, -49, -59, -122, -19, -136, -92, -146, 118, -132, 144, -104, + -161, 180, -158, 72, -196, -26, -108, 168, -218, 71, 14, 8, -207, -5, -87, + -81, -4, 27, -183, 19, -111, -181, 117, -77, 37, -141, -20, 115, -162, -212, + -156, 46, -95, 6, -86, 190, -35, 148, -157, 68, -44, 10, 116, -90, -176, 123, + -11, -180, -6, -137, 111, -8, 156, -64, 134, 114, -204, 113, -143, -165, -128, + 28, -199, -194, -148, 189, -129, -54, -159, 0, -34, -185, -67, -94, 64, -178, + -200, 45, -171, -106, -15, -61, 23, -40, -70, -55, -116, -38, 3, 39, 152, + -193, -57, -114, 2, -18, -149, 124, -16, -14, -189, -99, -131, -85, -154, -42, + -163, -32, 119, -103, -152, -50, -201, -28, 121, -23, -3, 110, -177, 12, 9, + -7, 127, -219, 133, 36, -56, -173, -208, -153, -192, -73, -12, 20, -130, 1, 4, + 151, -139, -150, -63, -96, -47, 198, -205, -82, 69, -102, 131, -117, -53, + -198, -118, -133, -145, -206, 154, -211, 163, -37, -155, -168, 11, -115, -140, + -71, 85, -30, 159, -60, -134, 136, 143, -160, -79 + ), + right = c( + -172, 96, -126, 170, 132, 150, 147, -112, 97, 137, 129, 155, -151, 26, 128, + 181, -10, 213, 107, -147, 174, -76, 171, -195, 201, 74, -25, 61, -46, -121, + 59, -48, 73, 47, -80, 52, 32, 176, 58, -216, -209, 161, 157, 93, 214, 191, + -107, 103, -31, 34, 205, 173, -169, 101, 87, -179, -33, 120, 169, -217, 195, + 33, 56, 44, -214, 18, 139, 182, -22, -105, 16, 217, -100, 31, 102, 92, -88, + 76, 22, 196, 162, -52, 185, 81, -2, 38, 172, 211, 135, 126, -203, -101, 210, + 43, 165, 108, 184, -170, 175, 212, 17, 149, 183, 89, -188, 65, 105, 125, -124, + 202, 130, 80, -166, 41, 91, -75, -190, 30, 75, 106, -119, 48, 35, 79, 177, + 215, 99, 193, 207, -215, 70, 208, -120, 51, -21, 146, 77, -144, 54, 153, 138, + 167, 145, 82, 15, 178, 21, -84, 194, 209, -27, 98, 166, -135, -164, -62, 179, + 24, -184, 200, -58, 199, -213, -98, 78, 204, 192, 49, 140, -69, -186, -17, 95, + -167, 142, -174, -43, 88, 25, 83, -202, -83, -78, 186, -191, 40, 7, 206, 63, + -182, 109, 203, 197, 141, -13, 42, 50, 13, 100, -9, 219, 104, 187, 62, 55, + -127, 53, -109, 218, 60, 90, 86, 160, -110, 94, -97, 164, 216, 84 + ), + prob = c( + 0.22866071428571427, 0, 0.966666666666667, 0, 1, 0.26666666666666666, 0.5, + 1, 0, 0.48484848484848486, 0.470588235294117641, 0.8571428571428571, + 0.477453580901856744, 0.44, 0.3076923076923077, 0, 0.5352941176470588, 0, + 0.125, 0.47156084656084657, 1, 0.6666666666666666, 0.6666666666666666, 0, 1, + 0.35714285714285715, 0.6333333333333333, 0.8, 0.2, 1, 0, 0.6428571428571429, + 0, 0.16666666666666666, 0.3333333333333333, 0, 0.7777777777777778, 0, 1, 0, 0, + 0, 0, 1, 0.7142857142857143, 1, 0.41544117647058826, 0, 0.5833333333333334, 1, + 0.9166666666666666, 1, 0.7083333333333334, 0, 1, 0.6666666666666666, 0.75, 1, + 0.5, 0.75, 0, 1, 0.25, 1, 0.5130434782608696, 0.5, 0, 0, 1, + 0.4351851851851852, 0.5609756097560976, 0, 1, 0.6153846153846154, + 0.8888888888888888, 1, 0.16666666666666666, 0, 0.5, 0, 1, 1, 1, 1, 0.375, 1, + 1, 1, 0.5, 1, 0.3888888888888889, 0.4166666666666667, 0.5625, 0, 0, 0, 1, + 0.8571428571428571, 1, 1, 0.5454545454545454, 1, 1, 1, 0.8571428571428571, 0, + 0.5806451612903226, 0.5454545454545454, 0.125, 0, 0.7272727272727273, 0.5, + 0.4444444444444444, 1, 0.461538461538461564, 0.6015037593984962, 1, 0.5, 1, 0, + 0, 0, 1, 0.5, 0.9285714285714286, 1, 0, 0.3333333333333333, + 0.47619047619047616, 0, 0.6923076923076923, 1, 0.3333333333333333, 1, 1, 1, + 0.5, 0.5961538461538461, 1, 1, 1, 1, 0, 0.372549019607843, + 0.6206896551724138, 1, 0.7407407407407407, 0.5, 1, 0.8333333333333334, + 0.6519607843137255, 0.5, 1, 0, 0.5235294117647059, 0.4375, 1, 0.875, 0.25, + 0.1, 0.181818181818181823, 1, 0.75, 0, 0, 0, 1, 0.5, 0, 0, 0.6666666666666666, + 0, 0.56, 0.75, 1, 0.25, 0.25, 0, 1, 1, 0, 1, 1, 0.14285714285714285, 0.8, 0.4, + 0.6326530612244898, 0, 0.5714285714285714, 0.6, 1, 0, 1, 0.5, + 0.4387755102040816, 0.6, 1, 1, 0.13333333333333333, 0.6428571428571429, 1, 1, + 1, 1, 0.7407407407407407, 0.3, 0, 0.5454545454545454, 0.3333333333333333, + 0.4819277108433735, 0, 0.16666666666666666, 1, 0.625, 0, 0, 1, + 0.090909090909090912, 0.3333333333333333 + ), + edges = c( + 2561, 0, 29, 0, 1, 4, 1, 3, 0, 16, 8, 6, 180, 22, 4, 0, 364, 0, 1, 713, 1, 4, + 6, 0, 1, 5, 19, 12, 2, 11, 0, 18, 0, 2, 2, 0, 7, 0, 14, 0, 0, 0, 0, 3, 10, 1, + 226, 0, 21, 15, 11, 1, 17, 0, 1, 4, 3, 2, 1, 9, 0, 1, 1, 1, 118, 2, 0, 0, 5, + 47, 46, 0, 4, 8, 16, 1, 1, 0, 1, 0, 5, 2, 3, 1, 3, 1, 1, 2, 4, 1, 14, 10, 9, + 0, 0, 0, 1, 12, 1, 1, 6, 1, 6, 2, 12, 0, 18, 6, 3, 0, 16, 1, 16, 1, 6, 80, 16, + 3, 1, 0, 0, 0, 13, 1, 13, 4, 0, 2, 10, 0, 18, 4, 1, 1, 2, 2, 2, 62, 1, 2, 11, + 1, 0, 19, 18, 2, 20, 6, 10, 5, 133, 8, 1, 0, 89, 14, 2, 14, 2, 1, 6, 1, 15, 0, + 0, 0, 1, 2, 0, 0, 28, 0, 14, 3, 3, 4, 4, 0, 5, 1, 0, 4, 4, 1, 8, 2, 31, 0, 16, + 9, 1, 0, 1, 5, 258, 3, 7, 4, 4, 9, 1, 2, 1, 10, 20, 3, 0, 84, 1, 40, 0, 2, 1, + 10, 0, 0, 1, 1, 1 + ), + vertices = c( + 220, 2, 11, 3, 2, 16, 3, 4, 2, 34, 18, 8, 42, 51, 14, 5, 54, 2, 9, 82, 2, 5, + 10, 140, 2, 15, 17, 16, 7, 12, 6, 16, 2, 13, 5, 3, 10, 4, 15, 6, 5, 6, 2, 4, + 15, 2, 49, 2, 12, 16, 13, 2, 14, 2, 2, 7, 4, 3, 3, 8, 4, 2, 5, 2, 33, 5, 2, 6, + 6, 21, 83, 2, 4, 14, 19, 2, 5, 2, 3, 2, 6, 3, 4, 2, 6, 2, 2, 3, 9, 2, 20, 14, + 17, 6, 2, 5, 2, 9, 2, 2, 12, 2, 7, 3, 9, 2, 32, 12, 11, 2, 23, 3, 13, 2, 14, + 26, 10, 7, 2, 3, 11, 2, 14, 3, 15, 5, 2, 7, 22, 5, 27, 5, 4, 2, 3, 3, 5, 54, + 2, 3, 12, 2, 6, 52, 30, 3, 28, 8, 11, 7, 29, 17, 2, 10, 27, 18, 3, 17, 9, 11, + 14, 2, 12, 10, 2, 4, 2, 5, 2, 7, 13, 80, 26, 4, 4, 8, 10, 2, 6, 2, 4, 5, 4, 8, + 7, 6, 50, 2, 29, 8, 2, 3, 2, 11, 56, 6, 8, 5, 31, 9, 2, 3, 2, 11, 28, 7, 2, + 25, 4, 84, 2, 13, 2, 10, 3, 3, 2, 12, 4 + ) + ) |> + structure(class = "igraphHRG") # auto, plain because not small expect_output(print(big_hrg), "->") From 3c18c17da673e7ab20525a1eb978ecf3db0c1e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 24 Sep 2025 08:24:38 +0200 Subject: [PATCH 055/154] fledge: CRAN release v2.2.0 (#2157) --- R/versions.R | 5 +++-- README.md | 36 +++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/R/versions.R b/R/versions.R index 08520a5d849..928dde1fe93 100644 --- a/R/versions.R +++ b/R/versions.R @@ -214,7 +214,8 @@ igraph.version <- function() { #' Returns the R package version, #' prints the R package version and C library version. #' -#'#' @return A character scalar, the igraph version string. +#' @return A character scalar, the igraph version string, with an attribute +#' `"c_version"` giving the C library version string. #' @author Gabor Csardi \email{csardi.gabor@@gmail.com} #' @keywords graphs #' @keywords internal @@ -222,7 +223,7 @@ igraph.version <- function() { #' @examples #' igraph_version() #' -igraph_version <- function(software = c("R", "C")) { +igraph_version <- function() { r_version <- getNamespaceInfo("igraph", "spec")[["version"]] version <- structure( diff --git a/README.md b/README.md index 4b922e04932..a500aa3a7ac 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ GNU GPL version 2 or later + + @@ -870,7 +872,7 @@ All contributions to this project are gratefully acknowledged using the [`allcon - +
ngr-t @@ -1888,7 +1890,7 @@ All contributions to this project are gratefully acknowledged using the [`allcon - +
arcresu @@ -1998,7 +2000,7 @@ All contributions to this project are gratefully acknowledged using the [`allcon - +
YulongNiu @@ -2256,7 +2258,7 @@ All contributions to this project are gratefully acknowledged using the [`allcon - +
Carol-seven @@ -2704,7 +2706,7 @@ All contributions to this project are gratefully acknowledged using the [`allcon - +
jldevezas @@ -2774,7 +2776,7 @@ All contributions to this project are gratefully acknowledged using the [`allcon - +
zhiyzuo @@ -3831,16 +3833,22 @@ All contributions to this project are gratefully acknowledged using the [`allcon ucb - - + +
-xiaoying201355 +vagdur + + +
+xiaoying201355 + +
@@ -3876,16 +3884,16 @@ All contributions to this project are gratefully acknowledged using the [`allcon
rfsaldanha + + + +
nipnipj - - - - @@ -3931,3 +3939,5 @@ All contributions to this project are gratefully acknowledged using the [`allcon + + From 37613c26341d9906ff9e8836733fc71b64d3d2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 24 Sep 2025 09:16:05 +0200 Subject: [PATCH 056/154] Fix test --- tests/testthat/test-versions.R | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-versions.R b/tests/testthat/test-versions.R index 65ee19e0b0d..2429e227c24 100644 --- a/tests/testthat/test-versions.R +++ b/tests/testthat/test-versions.R @@ -128,8 +128,9 @@ test_that("igraph_version returns a version string", { "\\b" ) - expect_match(igraph_version("R"), regex) - expect_match(igraph_version(), regex) + version <- igraph_version() + + expect_match(version, regex) c_regex <- paste0( "\\b", # word boundary @@ -139,5 +140,5 @@ test_that("igraph_version returns a version string", { "\\b" ) - expect_match(igraph_version("C"), c_regex) + expect_match(attr(version, "c_version"), c_regex) }) From 70b9390f3a0a95347e83dd67a0b9fb4e7289d4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 24 Sep 2025 10:08:05 +0200 Subject: [PATCH 057/154] https --- CITATION.cff | 4 ++-- CONTRIBUTING.md | 2 +- R/centrality.R | 6 +++--- R/cliques.R | 2 +- R/community.R | 2 +- R/epi.R | 2 +- R/foreign.R | 12 ++++++++---- R/games.R | 4 ++-- R/layout.R | 2 +- R/make.R | 4 ++-- R/sir.R | 2 +- R/topology.R | 4 ++-- man/automorphism_group.Rd | 2 +- man/cluster_leiden.Rd | 2 +- man/count_automorphisms.Rd | 2 +- man/eigen_centrality.Rd | 2 +- man/graph_from_graphdb.Rd | 2 +- man/graph_from_lcf.Rd | 4 ++-- man/ivs.Rd | 2 +- man/layout_with_drl.Rd | 2 +- man/plot.sir.Rd | 2 +- man/power_centrality.Rd | 2 +- man/read_graph.Rd | 4 +++- man/sample_forestfire.Rd | 2 +- man/sample_grg.Rd | 2 +- man/sir.Rd | 2 +- man/write_graph.Rd | 6 ++++-- 27 files changed, 46 insertions(+), 38 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 0ee2b9f50b1..e478f62f85d 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -2,7 +2,7 @@ # CITATION file created with {cffr} R package # See also: https://docs.ropensci.org/cffr/ # -------------------------------------------- - + cff-version: 1.2.0 message: 'To cite package "igraph" in publications use:' type: software @@ -414,7 +414,7 @@ references: title: igraphdata abstract: 'igraphdata: A Collection of Network Data Sets for the ''igraph'' Package' notes: Suggests - url: http://igraph.org + url: https://igraph.org repository: https://CRAN.R-project.org/package=igraphdata authors: - family-names: Csardi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4bf2d341270..f9da7869344 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -175,7 +175,7 @@ some unit testing support functions. In general, if you are not sure about something, please ask! You can open an issue on Github, write to the igraph-help mailing list (see the homepage at -http://igraph.org), or write to Tamás and Gábor. We prefer the public forums, +), or write to Tamás and Gábor. We prefer the public forums, though, because then others can learn from it, too. ## Legal Stuff diff --git a/R/centrality.R b/R/centrality.R index 0ec1c9c38a4..23ca01f4610 100644 --- a/R/centrality.R +++ b/R/centrality.R @@ -1045,7 +1045,7 @@ arpack <- function( if (any(!names(options) %in% names(defaults))) { unknown_options <- setdiff(names(options), names(defaults)) cli::cli_abort( - "Can't use unkown ARPACK {cli::qty(unknown_options)} option{?s}: + "Can't use unkown ARPACK {cli::qty(unknown_options)} option{?s}: {toString(unknown_options)}" ) } @@ -1355,7 +1355,7 @@ eigen_defaults <- function() { #' } #' } #' @author Gabor Csardi \email{csardi.gabor@@gmail.com} and Carter T. Butts -#' () for the +#' () for the #' manual page. #' @references Bonacich, P. (1987). Power and Centrality: A Family of #' Measures. *American Journal of Sociology*, 92, 1170-1182. @@ -1956,7 +1956,7 @@ bonpow.sparse <- function( #' this algorithm; thus, the routine may fail in certain cases. This will be #' fixed when we get a better algorithm. #' @author Carter T. Butts -#' (), ported to +#' (), ported to #' igraph by Gabor Csardi \email{csardi.gabor@@gmail.com} #' @seealso [eigen_centrality()] and [alpha_centrality()] #' @references Bonacich, P. (1972). ``Factoring and Weighting Approaches to diff --git a/R/cliques.R b/R/cliques.R index aa2f09713b9..44565406c19 100644 --- a/R/cliques.R +++ b/R/cliques.R @@ -457,7 +457,7 @@ weighted_clique_num <- weighted_clique_number_impl #' #' `ivs_size()` returns an integer constant. #' @author Tamas Nepusz \email{ntamas@@gmail.com} ported it from the Very Nauty -#' Graph Library by Keith Briggs () and Gabor +#' Graph Library by Keith Briggs () and Gabor #' Csardi \email{csardi.gabor@@gmail.com} wrote the R interface and this manual #' page. #' @references S. Tsukiyama, M. Ide, H. Ariyoshi and I. Shirawaka. A new diff --git a/R/community.R b/R/community.R index d70b02ef4e0..f4e844e1213 100644 --- a/R/community.R +++ b/R/community.R @@ -1532,7 +1532,7 @@ cluster_spinglass <- function( #' [cluster_louvain()], but it is faster and yields higher quality #' solutions. It can optimize both modularity and the Constant Potts Model, #' which does not suffer from the resolution-limit (see preprint -#' http://arxiv.org/abs/1104.3083). +#' ). #' #' The Leiden algorithm consists of three phases: (1) local moving of nodes, #' (2) refinement of the partition and (3) aggregation of the network based on diff --git a/R/epi.R b/R/epi.R index ea955ef94cb..507965304c3 100644 --- a/R/epi.R +++ b/R/epi.R @@ -124,7 +124,7 @@ quantile.sir <- function(x, comp = c("NI", "NS", "NR"), prob, ...) { #' @param \dots Additional arguments are passed to [plot()], that is run #' before any of the curves are added, to create the figure. #' @return Nothing. -#' @author Eric Kolaczyk () and Gabor +#' @author Eric Kolaczyk () and Gabor #' Csardi \email{csardi.gabor@@gmail.com}. #' @seealso [sir()] for running the actual simulation. #' @references Bailey, Norman T. J. (1975). The mathematical theory of diff --git a/R/foreign.R b/R/foreign.R index 4d21b41a36d..d7ccc5c354a 100644 --- a/R/foreign.R +++ b/R/foreign.R @@ -280,7 +280,9 @@ write.graph.fromraw <- function(buffer, file) { #' } #' #' @section DL format: -#' This is a simple textual file format used by UCINET. See for examples. All the forms described here are supported by igraph. +#' This is a simple textual file format used by UCINET. +#' See for examples. +#' All the forms described here are supported by igraph. #' Vertex names and edge weights are also supported and they are added as attributes. #' (If an attribute handler is attached.) #' Note the specification does not mention whether the format is case sensitive or not. @@ -431,7 +433,8 @@ read_graph <- function( #' } #' #' @section LEDA format: -#' This function writes a graph to an output stream in LEDA format. See +#' This function writes a graph to an output stream in LEDA format. +#' See . #' The support for the LEDA format is very basic at the moment; igraph writes only the LEDA graph section which supports one selected vertex and edge #' attribute and no layout information or visual attributes. #' \describe{ @@ -439,7 +442,8 @@ read_graph <- function( #' \item{edge.attr}{Name of edge attribute to include in the file.} #' } #' @section DOT format: -#' DOT is the format used by the widely known GraphViz software, see http://www.graphviz.org for details. The grammar of the DOT format can be found here: http://www.graphviz.org/doc/info/lang.html +#' DOT is the format used by the widely known GraphViz software, see for details. +#' The grammar of the DOT format can be found here: . #' This is only a preliminary implementation, no visualization information is written. #' This format is meant solely for interoperability with Graphviz. It is not recommended for #' data exchange or archival. @@ -772,7 +776,7 @@ write.graph.dot <- function(graph, file) { #' #' Unfortunately the original graph database homepage is now defunct, but see #' its old version at -#' +#' #' for the actual format of a graph database file and other information. #' #' @param url If not `NULL` it is a complete URL with the file to import. diff --git a/R/games.R b/R/games.R index b88eca94a3f..7c9a1d8f996 100644 --- a/R/games.R +++ b/R/games.R @@ -1834,7 +1834,7 @@ traits <- function(...) constructor_spec(sample_traits, ...) #' @return A graph object. If `coords` is `TRUE` then with vertex #' attributes \sQuote{`x`} and \sQuote{`y`}. #' @author Gabor Csardi \email{csardi.gabor@@gmail.com}, first version was -#' written by Keith Briggs (). +#' written by Keith Briggs (). #' @family games #' @export #' @keywords graphs @@ -3028,7 +3028,7 @@ sample_fitness_pl <- static_power_law_game_impl #' @note The version of the model in the published paper is incorrect in the #' sense that it cannot generate the kind of graphs the authors claim. A #' corrected version is available from -#' , our +#' , our #' implementation is based on this. #' @author Gabor Csardi \email{csardi.gabor@@gmail.com} #' @seealso [sample_pa()] for the basic preferential attachment diff --git a/R/layout.R b/R/layout.R index e2605c1bfe6..147f019dc91 100644 --- a/R/layout.R +++ b/R/layout.R @@ -2757,7 +2757,7 @@ layout.drl <- function( #' nature of the DrL algorithm, the three dimensional layout takes #' significantly longer to compute. #' @return A numeric matrix with two columns. -#' @author Shawn Martin () +#' @author Shawn Martin () #' and Gabor Csardi \email{csardi.gabor@@gmail.com} for the R/igraph interface #' and the three dimensional version. #' @seealso [layout()] for other layout generators. diff --git a/R/make.R b/R/make.R index 218486c304c..7a8fa5725e7 100644 --- a/R/make.R +++ b/R/make.R @@ -2577,8 +2577,8 @@ full_citation_graph <- function(...) { #' 3-regular Hamiltonian graphs. It constists of three parameters, the number #' of vertices in the graph, a list of shifts giving additional edges to a #' cycle backbone and another integer giving how many times the shifts should -#' be performed. See for -#' details. +#' be performed. +#' See for details. #' #' #' @aliases graph_from_lcf diff --git a/R/sir.R b/R/sir.R index 5728caa0ffd..78ccdfa2ff2 100644 --- a/R/sir.R +++ b/R/sir.R @@ -96,7 +96,7 @@ #' one requested) if only one quantile is requested. If multiple quantiles are #' requested, then a list of these vectors is returned, one for each quantile. #' @author Gabor Csardi \email{csardi.gabor@@gmail.com}. Eric Kolaczyk -#' () wrote the initial version in R. +#' () wrote the initial version in R. #' @seealso [plot.sir()] to conveniently plot the results #' @references Bailey, Norman T. J. (1975). The mathematical theory of #' infectious diseases and its applications (2nd ed.). London: Griffin. diff --git a/R/topology.R b/R/topology.R index 2e470f3c0c7..9ccfb771510 100644 --- a/R/topology.R +++ b/R/topology.R @@ -1104,7 +1104,7 @@ graph.isomorphic <- isomorphic_impl #' Maximum level. #' } #' } -#' @author Tommi Junttila () for BLISS +#' @author Tommi Junttila () for BLISS #' and Gabor Csardi \email{csardi.gabor@@gmail.com} for the igraph glue code #' and this manual page. #' @seealso [canonical_permutation()], [permute()], @@ -1185,7 +1185,7 @@ count_automorphisms <- count_automorphisms_bliss_impl #' See [count_automorphisms()] for more details. #' } #' } -#' @author Tommi Junttila () for BLISS, +#' @author Tommi Junttila () for BLISS, #' Gabor Csardi \email{csardi.gabor@@gmail.com} for the igraph glue code and #' Tamas Nepusz \email{ntamas@@gmail.com} for this manual page. #' @seealso [canonical_permutation()], [permute()], diff --git a/man/automorphism_group.Rd b/man/automorphism_group.Rd index db65c88d3b0..fc6f8266a59 100644 --- a/man/automorphism_group.Rd +++ b/man/automorphism_group.Rd @@ -87,7 +87,7 @@ Other graph automorphism: \code{\link{count_automorphisms}()} } \author{ -Tommi Junttila (\url{http://users.ics.aalto.fi/tjunttil/}) for BLISS, +Tommi Junttila (\url{https://users.ics.aalto.fi/tjunttil/}) for BLISS, Gabor Csardi \email{csardi.gabor@gmail.com} for the igraph glue code and Tamas Nepusz \email{ntamas@gmail.com} for this manual page. } diff --git a/man/cluster_leiden.Rd b/man/cluster_leiden.Rd index cacc80fa576..cbf925dcdda 100644 --- a/man/cluster_leiden.Rd +++ b/man/cluster_leiden.Rd @@ -64,7 +64,7 @@ The Leiden algorithm is similar to the Louvain algorithm, \code{\link[=cluster_louvain]{cluster_louvain()}}, but it is faster and yields higher quality solutions. It can optimize both modularity and the Constant Potts Model, which does not suffer from the resolution-limit (see preprint -http://arxiv.org/abs/1104.3083). +\url{https://arxiv.org/abs/1104.3083}). } \details{ The Leiden algorithm consists of three phases: (1) local moving of nodes, diff --git a/man/count_automorphisms.Rd b/man/count_automorphisms.Rd index c25c6ed12d4..6bcc661dea8 100644 --- a/man/count_automorphisms.Rd +++ b/man/count_automorphisms.Rd @@ -102,7 +102,7 @@ Other graph automorphism: \code{\link{automorphism_group}()} } \author{ -Tommi Junttila (\url{http://users.ics.aalto.fi/tjunttil/}) for BLISS +Tommi Junttila (\url{https://users.ics.aalto.fi/tjunttil/}) for BLISS and Gabor Csardi \email{csardi.gabor@gmail.com} for the igraph glue code and this manual page. } diff --git a/man/eigen_centrality.Rd b/man/eigen_centrality.Rd index f96a9b340dc..2b0320a800a 100644 --- a/man/eigen_centrality.Rd +++ b/man/eigen_centrality.Rd @@ -139,7 +139,7 @@ Centrality measures } \author{ Gabor Csardi \email{csardi.gabor@gmail.com} and Carter T. Butts -(\url{http://www.faculty.uci.edu/profile.cfm?faculty_id=5057}) for the +(\url{https://www.faculty.uci.edu/profile.cfm?faculty_id=5057}) for the manual page. } \concept{centrality} diff --git a/man/graph_from_graphdb.Rd b/man/graph_from_graphdb.Rd index a875b054b36..689949b77ce 100644 --- a/man/graph_from_graphdb.Rd +++ b/man/graph_from_graphdb.Rd @@ -68,7 +68,7 @@ assembled from the \code{base}, \code{prefix}, \code{type}, \code{nodes}, Unfortunately the original graph database homepage is now defunct, but see its old version at -\url{http://web.archive.org/web/20090215182331/http://amalfi.dis.unina.it/graph/db/doc/graphdbat.html} +\url{https://web.archive.org/web/20090215182331/http://amalfi.dis.unina.it/graph/db/doc/graphdbat.html} for the actual format of a graph database file and other information. } \references{ diff --git a/man/graph_from_lcf.Rd b/man/graph_from_lcf.Rd index 99e11272b24..41ac2b6c9d6 100644 --- a/man/graph_from_lcf.Rd +++ b/man/graph_from_lcf.Rd @@ -24,8 +24,8 @@ LCF is short for Lederberg-Coxeter-Frucht, it is a concise notation for 3-regular Hamiltonian graphs. It constists of three parameters, the number of vertices in the graph, a list of shifts giving additional edges to a cycle backbone and another integer giving how many times the shifts should -be performed. See \url{http://mathworld.wolfram.com/LCFNotation.html} for -details. +be performed. +See \url{https://mathworld.wolfram.com/LCFNotation.html} for details. } \examples{ diff --git a/man/ivs.Rd b/man/ivs.Rd index a7b11abde99..0643adb051f 100644 --- a/man/ivs.Rd +++ b/man/ivs.Rd @@ -100,7 +100,7 @@ Other cliques: } \author{ Tamas Nepusz \email{ntamas@gmail.com} ported it from the Very Nauty -Graph Library by Keith Briggs (\url{http://keithbriggs.info/}) and Gabor +Graph Library by Keith Briggs (\url{https://keithbriggs.info/}) and Gabor Csardi \email{csardi.gabor@gmail.com} wrote the R interface and this manual page. } diff --git a/man/layout_with_drl.Rd b/man/layout_with_drl.Rd index e35ddbcb90f..a1624aeea0c 100644 --- a/man/layout_with_drl.Rd +++ b/man/layout_with_drl.Rd @@ -160,7 +160,7 @@ Reports, 2008. 2936: p. 1-10. \code{\link[=layout]{layout()}} for other layout generators. } \author{ -Shawn Martin (\url{http://www.cs.otago.ac.nz/homepages/smartin/}) +Shawn Martin (\url{https://www.cs.otago.ac.nz/homepages/smartin/}) and Gabor Csardi \email{csardi.gabor@gmail.com} for the R/igraph interface and the three dimensional version. } diff --git a/man/plot.sir.Rd b/man/plot.sir.Rd index c59cf461572..5b0db02b604 100644 --- a/man/plot.sir.Rd +++ b/man/plot.sir.Rd @@ -89,7 +89,7 @@ Processes on graphs \code{\link{time_bins}()} } \author{ -Eric Kolaczyk (\url{http://math.bu.edu/people/kolaczyk/}) and Gabor +Eric Kolaczyk (\url{https://kolaczyk.github.io/}) and Gabor Csardi \email{csardi.gabor@gmail.com}. } \concept{processes} diff --git a/man/power_centrality.Rd b/man/power_centrality.Rd index 9a05d88896e..aeb2c85dd24 100644 --- a/man/power_centrality.Rd +++ b/man/power_centrality.Rd @@ -157,7 +157,7 @@ Centrality measures } \author{ Carter T. Butts -(\url{http://www.faculty.uci.edu/profile.cfm?faculty_id=5057}), ported to +(\url{https://www.faculty.uci.edu/profile.cfm?faculty_id=5057}), ported to igraph by Gabor Csardi \email{csardi.gabor@gmail.com} } \concept{centrality} diff --git a/man/read_graph.Rd b/man/read_graph.Rd index 05d08030b22..3ce30e9c1a5 100644 --- a/man/read_graph.Rd +++ b/man/read_graph.Rd @@ -158,7 +158,9 @@ In EDGE problems, each edge is specified as an edge line (e). \section{DL format}{ -This is a simple textual file format used by UCINET. See \url{http://www.analytictech.com/networks/dataentry.htm} for examples. All the forms described here are supported by igraph. +This is a simple textual file format used by UCINET. +See \url{http://www.analytictech.com/networks/dataentry.htm} for examples. +All the forms described here are supported by igraph. Vertex names and edge weights are also supported and they are added as attributes. (If an attribute handler is attached.) Note the specification does not mention whether the format is case sensitive or not. diff --git a/man/sample_forestfire.Rd b/man/sample_forestfire.Rd index 432851c53d6..76eff55ac99 100644 --- a/man/sample_forestfire.Rd +++ b/man/sample_forestfire.Rd @@ -50,7 +50,7 @@ all the newly cited vertices. } The version of the model in the published paper is incorrect in the sense that it cannot generate the kind of graphs the authors claim. A corrected version is available from -\url{http://www.cs.cmu.edu/~jure/pubs/powergrowth-tkdd.pdf}, our +\url{https://www.cs.cmu.edu/~jure/pubs/powergrowth-tkdd.pdf}, our implementation is based on this. } \examples{ diff --git a/man/sample_grg.Rd b/man/sample_grg.Rd index 335d91b29fc..009fcf6f650 100644 --- a/man/sample_grg.Rd +++ b/man/sample_grg.Rd @@ -74,7 +74,7 @@ Random graph models (games) } \author{ Gabor Csardi \email{csardi.gabor@gmail.com}, first version was -written by Keith Briggs (\url{http://keithbriggs.info/}). +written by Keith Briggs (\url{https://keithbriggs.info/}). } \concept{games} \keyword{graphs} diff --git a/man/sir.Rd b/man/sir.Rd index e4c4873d607..9d765427c62 100644 --- a/man/sir.Rd +++ b/man/sir.Rd @@ -122,7 +122,7 @@ Processes on graphs } \author{ Gabor Csardi \email{csardi.gabor@gmail.com}. Eric Kolaczyk -(\url{http://math.bu.edu/people/kolaczyk/}) wrote the initial version in R. +(\url{https://kolaczyk.github.io/}) wrote the initial version in R. } \concept{processes} \keyword{graphs} diff --git a/man/write_graph.Rd b/man/write_graph.Rd index f1f4a99ca1d..a06166b1812 100644 --- a/man/write_graph.Rd +++ b/man/write_graph.Rd @@ -121,7 +121,8 @@ uniqueness across vertex/edge/graph attributes. Default is TRUE.} \section{LEDA format}{ -This function writes a graph to an output stream in LEDA format. See \url{http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html} +This function writes a graph to an output stream in LEDA format. +See \url{https://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html}. The support for the LEDA format is very basic at the moment; igraph writes only the LEDA graph section which supports one selected vertex and edge attribute and no layout information or visual attributes. \describe{ @@ -132,7 +133,8 @@ attribute and no layout information or visual attributes. \section{DOT format}{ -DOT is the format used by the widely known GraphViz software, see http://www.graphviz.org for details. The grammar of the DOT format can be found here: http://www.graphviz.org/doc/info/lang.html +DOT is the format used by the widely known GraphViz software, see \url{https://www.graphviz.org} for details. +The grammar of the DOT format can be found here: \url{https://www.graphviz.org/doc/info/lang.html}. This is only a preliminary implementation, no visualization information is written. This format is meant solely for interoperability with Graphviz. It is not recommended for data exchange or archival. From 283ec5d9c26f475bebafd4489220e5c50f12655a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 25 Sep 2025 21:33:21 +0200 Subject: [PATCH 058/154] Merge branch 'release-2.2.0' --- DESCRIPTION | 2 +- R/adjacency.R | 8 +++-- R/community.R | 4 ++- R/layout.R | 23 ++++++++---- R/revdep.R | 2 +- tests/testthat/test-adjacency.R | 62 +++++++++++++++++++++++++++++++++ tests/testthat/test-community.R | 37 ++++++++++++++++++++ tests/testthat/test-layout.R | 43 +++++++++++++++++++++++ 8 files changed, 169 insertions(+), 12 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index af537eff6fd..26e1e2235d3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -77,7 +77,7 @@ Config/Needs/coverage: covr Config/Needs/website: here, readr, tibble, xmlparsedata, xml2 Config/testthat/edition: 3 Config/testthat/parallel: true -Config/testthat/start-first: vs-es, scan, vs-operators, weakref, +Config/testthat/start-first: aaa-auto, vs-es, scan, vs-operators, weakref, watts.strogatz.game Encoding: UTF-8 Roxygen: list(markdown = TRUE, roclets = c("collate", "rd", "namespace", diff --git a/R/adjacency.R b/R/adjacency.R index acc53ec1581..c96f3f1a54d 100644 --- a/R/adjacency.R +++ b/R/adjacency.R @@ -153,9 +153,9 @@ graph.adjacency <- function( #' the calculation. If this is `FALSE` then the diagonal is zerod out #' first. #' @param add.colnames Character scalar, whether to add the column names as -#' vertex attributes. If it is \sQuote{`NULL`} (the default) then, if +#' vertex attributes. If it is `NULL` (the default) then, if #' present, column names are added as vertex attribute \sQuote{name}. If -#' \sQuote{`NA`} then they will not be added. If a character constant, +#' `NA` or `FALSE` then they will not be added. If a character constant, #' then it gives the name of the vertex attribute to add. #' @param add.rownames Character scalar, whether to add the row names as vertex #' attributes. Possible values the same as the previous argument. By default @@ -334,6 +334,8 @@ graph_from_adjacency_matrix <- function( } else { add.colnames <- NA } + } else if (isFALSE(add.colnames)) { + add.colnames <- NA } else if (!is.na(add.colnames)) { if (is.null(colnames(adjmatrix))) { cli::cli_warn("No column names to add") @@ -347,6 +349,8 @@ graph_from_adjacency_matrix <- function( } else { add.colnames <- NA } + } else if (isFALSE(add.rownames)) { + add.rownames <- NA } else if (!is.na(add.rownames)) { if (is.null(rownames(adjmatrix))) { cli::cli_warn("No row names to add") diff --git a/R/community.R b/R/community.R index f4e844e1213..c4f9eff03a7 100644 --- a/R/community.R +++ b/R/community.R @@ -919,8 +919,10 @@ modularity.igraph <- function( cli::cli_abort("Membership is not a numerical vector") } membership <- as.numeric(membership) - if (!is.null(weights)) { + if (!is.null(weights) && any(!is.na(weights))) { weights <- as.numeric(weights) + } else { + weights <- NULL } resolution <- as.numeric(resolution) directed <- as.logical(directed) diff --git a/R/layout.R b/R/layout.R index 147f019dc91..81f184843cc 100644 --- a/R/layout.R +++ b/R/layout.R @@ -934,20 +934,23 @@ layout_nicely <- function(graph, dim = 2, ...) { "Non-positive edge weight found, ignoring all weights during graph layout." ) args$weights <- NA + } else { + args$weights <- weights } } } args$graph <- graph - if (is_forest(graph) && vcount(graph) <= 30) { + if (is_forest(graph) && vcount(graph) <= 30 && is.null(args$weights)) { return(do.call(layout_as_tree, args)) } args$dim <- dim if (vcount(graph) < 1000) { - align_layout(graph, do.call(layout_with_fr, args)) + layout <- do.call(layout_with_fr, args) + align_layout(graph, layout) } else { do.call(layout_with_drl, args) } @@ -2529,14 +2532,20 @@ norm_coords <- function( } .layout.norm.col <- function(v, min, max) { - vr <- range(v) - if (vr[1] == vr[2]) { - fac <- 1 + # Likely cause: division by zero upstream + if (all(is.nan(v))) { + diff <- 0 } else { - fac <- (max - min) / (vr[2] - vr[1]) + vr <- range(v) + diff <- diff(vr) } - (v - vr[1]) * fac + min + if (diff == 0) { + return(rep((min + max) / 2, length(v))) + } + + fac <- (max - min) / diff + (v - vr[[1]]) * fac + min } #' @rdname merge_coords diff --git a/R/revdep.R b/R/revdep.R index ac74e1b8c73..7d9e94337ae 100644 --- a/R/revdep.R +++ b/R/revdep.R @@ -12,7 +12,7 @@ pkg_review <- function(pkg, pak = TRUE) { } withr::local_dir(pkg_path) - system("rh") + system("positron .") if (pak) { pak::pak(pkg, dependencies = TRUE, upgrade = TRUE, ask = FALSE) diff --git a/tests/testthat/test-adjacency.R b/tests/testthat/test-adjacency.R index 8f92cfe4845..40a72956e32 100644 --- a/tests/testthat/test-adjacency.R +++ b/tests/testthat/test-adjacency.R @@ -789,3 +789,65 @@ test_that("graph_from_adjacency_matrix errors for NAs", { A <- matrix(c(1, 1, NA, 1), 2, 2) expect_snapshot(graph_from_adjacency_matrix(A), error = TRUE) }) + +test_that("graph_from_adjacency_matrix handles add.colnames and add.rownames = FALSE correctly", { + # Create test matrix with row and column names + M <- matrix(c(0, 1, 1, 0), nrow = 2, ncol = 2) + rownames(M) <- c("A", "B") + colnames(M) <- c("X", "Y") + + # Test default behavior (should add names) + g_default <- graph_from_adjacency_matrix(M) + expect_equal(V(g_default)$name, c("X", "Y")) + + # Test add.colnames = FALSE (should not add column names) + g_no_colnames <- graph_from_adjacency_matrix(M, add.colnames = FALSE) + expect_null(V(g_no_colnames)$name) + + # Test add.rownames = FALSE (should not add row names) + g_no_rownames <- graph_from_adjacency_matrix(M, add.colnames = NA, add.rownames = FALSE) + expect_null(V(g_no_rownames)$name) + + # Test both FALSE + g_no_names <- graph_from_adjacency_matrix( + M, + add.colnames = FALSE, + add.rownames = FALSE + ) + expect_null(V(g_no_names)$name) + + # Test with custom attribute names and FALSE values + g_col_false <- graph_from_adjacency_matrix( + M, + add.colnames = FALSE, + add.rownames = "vertex_id" + ) + expect_equal(V(g_col_false)$vertex_id, c("A", "B")) + expect_null(V(g_col_false)$name) + + g_row_false <- graph_from_adjacency_matrix( + M, + add.colnames = "vertex_name", + add.rownames = FALSE + ) + expect_equal(V(g_row_false)$vertex_name, c("X", "Y")) + expect_null(V(g_row_false)$name) + + # Test matrix without names and FALSE parameters + M_no_names <- matrix(c(0, 1, 1, 0), nrow = 2, ncol = 2) + g_no_names_matrix <- graph_from_adjacency_matrix( + M_no_names, + add.colnames = FALSE, + add.rownames = FALSE + ) + expect_null(V(g_no_names_matrix)$name) + + # Test that FALSE is equivalent to NA behavior + g_na_col <- graph_from_adjacency_matrix(M, add.colnames = NA) + g_false_col <- graph_from_adjacency_matrix(M, add.colnames = FALSE) + expect_equal(vertex_attr_names(g_na_col), vertex_attr_names(g_false_col)) + + g_na_row <- graph_from_adjacency_matrix(M, add.rownames = NA) + g_false_row <- graph_from_adjacency_matrix(M, add.rownames = FALSE) + expect_equal(vertex_attr_names(g_na_row), vertex_attr_names(g_false_row)) +}) diff --git a/tests/testthat/test-community.R b/tests/testthat/test-community.R index 6ee2e8d453e..288af660247 100644 --- a/tests/testthat/test-community.R +++ b/tests/testthat/test-community.R @@ -564,3 +564,40 @@ test_that("contract works", { ) ) }) + +test_that("modularity() handles NA weights correctly", { + # Create a simple graph for testing + g <- make_graph("Zachary") + + # Get a community structure for testing + comm <- cluster_fast_greedy(g) + membership_vec <- membership(comm) + + # Test that modularity works with regular weights + E(g)$weight <- runif(ecount(g)) + mod_with_weights <- modularity(g, membership_vec, weights = E(g)$weight) + expect_true(is.numeric(mod_with_weights)) + expect_length(mod_with_weights, 1) + + # Test that modularity works when all weights are NA + mod_with_all_na <- modularity(g, membership_vec, weights = rep(NA, ecount(g))) + mod_without_weights <- modularity(g, membership_vec, weights = NULL) + expect_equal(mod_with_all_na, mod_without_weights) + + # Test that modularity works when some weights are NA and some are not + mixed_weights <- E(g)$weight + mixed_weights[1:5] <- NA + mod_with_mixed_na <- modularity(g, membership_vec, weights = mixed_weights) + expect_true(is.numeric(mod_with_mixed_na)) + expect_length(mod_with_mixed_na, 1) + + # Test edge case: empty weights vector treated as NA + mod_with_empty <- modularity(g, membership_vec, weights = numeric(0)) + expect_equal(mod_with_empty, mod_without_weights) + + # Test that when all weights are NA, it's equivalent to unweighted + all_na_weights <- rep(NA_real_, ecount(g)) + mod_all_na <- modularity(g, membership_vec, weights = all_na_weights) + mod_unweighted <- modularity(g, membership_vec) + expect_equal(mod_all_na, mod_unweighted) +}) diff --git a/tests/testthat/test-layout.R b/tests/testthat/test-layout.R index ab2acecc309..4594bfec134 100644 --- a/tests/testthat/test-layout.R +++ b/tests/testthat/test-layout.R @@ -30,6 +30,12 @@ test_that("layout_with_fr() deprecated argument", { }) }) +test_that("layout_nicely() works with proper weights and small trees", { + g <- make_star(12, mode = "out") + E(g)$weight <- 5:15 + expect_warning(layout_nicely(g), NA) +}) + test_that("layout_nicely() works with negative weights", { g <- make_graph("petersen") E(g)$weight <- -5:9 @@ -332,3 +338,40 @@ test_that("layout_randomly() errors well", { layout_randomly(g, dim = 4) }) }) + +test_that("layout normalization handles all-NaN coordinates correctly", { + # Test the internal .layout.norm.col function directly + # This tests the fix for all-NaN coordinate normalization + + # Test normal case + normal_coords <- c(1, 2, 3, 4, 5) + normalized <- igraph:::.layout.norm.col(normal_coords, 0, 1) + expect_equal(range(normalized), c(0, 1)) + + # Test all-NaN case (this was the bug that was fixed) + nan_coords <- rep(NaN, 5) + normalized_nan <- igraph:::.layout.norm.col(nan_coords, 0, 1) + expected_middle <- rep(0.5, 5) # Should return middle value (0+1)/2 = 0.5 + expect_equal(normalized_nan, expected_middle) + + # Test all-NaN case with different range + normalized_nan_range <- igraph:::.layout.norm.col(nan_coords, -10, 10) + expected_middle_range <- rep(0, 5) # Should return middle value (-10+10)/2 = 0 + expect_equal(normalized_nan_range, expected_middle_range) + + # Test constant values (difference is zero) + constant_coords <- rep(5, 5) + normalized_constant <- igraph:::.layout.norm.col(constant_coords, 0, 1) + expected_constant_middle <- rep(0.5, 5) + expect_equal(normalized_constant, expected_constant_middle) + + # Test that norm_coords works with all-NaN layouts + layout_all_nan <- matrix(NaN, nrow = 5, ncol = 2) + normalized_layout <- norm_coords(layout_all_nan, 0, 1, 0, 1) + expect_equal(normalized_layout, matrix(c(rep(0.5, 5), rep(0.5, 5)), ncol = 2)) + + # Test 3D layout normalization with all-NaN coordinates + layout_3d_nan <- matrix(NaN, nrow = 3, ncol = 3) + normalized_3d <- norm_coords(layout_3d_nan, 0, 1, 0, 1, 0, 1) + expect_equal(normalized_3d, matrix(rep(0.5, 9), ncol = 3)) +}) From b6b715e3aece5fc2d16b102f997c9e44164e4bf3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 10:53:14 +0200 Subject: [PATCH 059/154] test: Snapshot updates for rcc-smoke (null) (#2170) Co-authored-by: maelle <8360597+maelle@users.noreply.github.com> --- tests/testthat/_snaps/plot/label-rotate.svg | 28 ++++++++--------- .../_snaps/plot/standard-arrow-modes.svg | 30 +++++++++---------- .../_snaps/plot/standard-arrow-sizes.svg | 28 ++++++++--------- tests/testthat/_snaps/plot/standard-arrow.svg | 28 ++++++++--------- 4 files changed, 57 insertions(+), 57 deletions(-) diff --git a/tests/testthat/_snaps/plot/label-rotate.svg b/tests/testthat/_snaps/plot/label-rotate.svg index 7ccc0490c08..e1a54909640 100644 --- a/tests/testthat/_snaps/plot/label-rotate.svg +++ b/tests/testthat/_snaps/plot/label-rotate.svg @@ -25,21 +25,21 @@ - - - - - - - - - + + + + + + + + + -AAAAA -BBBBB -CCCCC -DDDDD -EEEEE +AAAAA +BBBBB +CCCCC +DDDDD +EEEEE diff --git a/tests/testthat/_snaps/plot/standard-arrow-modes.svg b/tests/testthat/_snaps/plot/standard-arrow-modes.svg index 8ccc1656b5e..06de3196243 100644 --- a/tests/testthat/_snaps/plot/standard-arrow-modes.svg +++ b/tests/testthat/_snaps/plot/standard-arrow-modes.svg @@ -25,22 +25,22 @@ - - - - - - - - - - - + + + + + + + + + + + -1 -2 -3 -4 +1 +2 +3 +4 diff --git a/tests/testthat/_snaps/plot/standard-arrow-sizes.svg b/tests/testthat/_snaps/plot/standard-arrow-sizes.svg index b99add14423..abdc0825d90 100644 --- a/tests/testthat/_snaps/plot/standard-arrow-sizes.svg +++ b/tests/testthat/_snaps/plot/standard-arrow-sizes.svg @@ -25,21 +25,21 @@ - - - - - - - - - - + + + + + + + + + + -1 -2 -3 -4 +1 +2 +3 +4 diff --git a/tests/testthat/_snaps/plot/standard-arrow.svg b/tests/testthat/_snaps/plot/standard-arrow.svg index 6025f506d67..5771fe2fbca 100644 --- a/tests/testthat/_snaps/plot/standard-arrow.svg +++ b/tests/testthat/_snaps/plot/standard-arrow.svg @@ -25,21 +25,21 @@ - - - - - - - - - - + + + + + + + + + + -1 -2 -3 -4 +1 +2 +3 +4 From 3c4ff669bf662fd0629b2d84abe191d2ea27da05 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 09:21:27 +0000 Subject: [PATCH 060/154] chore: Auto-update from GitHub Actions (#2181) --- man/graph.adjacency.Rd | 4 ++-- man/graph_from_adjacency_matrix.Rd | 4 ++-- tests/testthat/test-adjacency.R | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/man/graph.adjacency.Rd b/man/graph.adjacency.Rd index 432e1f18c5b..3220fdb6307 100644 --- a/man/graph.adjacency.Rd +++ b/man/graph.adjacency.Rd @@ -37,9 +37,9 @@ the calculation. If this is \code{FALSE} then the diagonal is zerod out first.} \item{add.colnames}{Character scalar, whether to add the column names as -vertex attributes. If it is \sQuote{\code{NULL}} (the default) then, if +vertex attributes. If it is \code{NULL} (the default) then, if present, column names are added as vertex attribute \sQuote{name}. If -\sQuote{\code{NA}} then they will not be added. If a character constant, +\code{NA} or \code{FALSE} then they will not be added. If a character constant, then it gives the name of the vertex attribute to add.} \item{add.rownames}{Character scalar, whether to add the row names as vertex diff --git a/man/graph_from_adjacency_matrix.Rd b/man/graph_from_adjacency_matrix.Rd index 0011507783d..6765ff056b6 100644 --- a/man/graph_from_adjacency_matrix.Rd +++ b/man/graph_from_adjacency_matrix.Rd @@ -40,9 +40,9 @@ the calculation. If this is \code{FALSE} then the diagonal is zerod out first.} \item{add.colnames}{Character scalar, whether to add the column names as -vertex attributes. If it is \sQuote{\code{NULL}} (the default) then, if +vertex attributes. If it is \code{NULL} (the default) then, if present, column names are added as vertex attribute \sQuote{name}. If -\sQuote{\code{NA}} then they will not be added. If a character constant, +\code{NA} or \code{FALSE} then they will not be added. If a character constant, then it gives the name of the vertex attribute to add.} \item{add.rownames}{Character scalar, whether to add the row names as vertex diff --git a/tests/testthat/test-adjacency.R b/tests/testthat/test-adjacency.R index 40a72956e32..b488ca4302d 100644 --- a/tests/testthat/test-adjacency.R +++ b/tests/testthat/test-adjacency.R @@ -805,7 +805,11 @@ test_that("graph_from_adjacency_matrix handles add.colnames and add.rownames = F expect_null(V(g_no_colnames)$name) # Test add.rownames = FALSE (should not add row names) - g_no_rownames <- graph_from_adjacency_matrix(M, add.colnames = NA, add.rownames = FALSE) + g_no_rownames <- graph_from_adjacency_matrix( + M, + add.colnames = NA, + add.rownames = FALSE + ) expect_null(V(g_no_rownames)$name) # Test both FALSE From fa301c685c1129cbddaf01135066119304d2cd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 2 Oct 2025 11:24:22 +0200 Subject: [PATCH 061/154] fix: Pass on `cutoff` arguemnt to `all_simple_paths()` --- R/paths.R | 1 + tests/testthat/test-paths.R | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/R/paths.R b/R/paths.R index 3c60395b2aa..4b16f771bcf 100644 --- a/R/paths.R +++ b/R/paths.R @@ -123,6 +123,7 @@ all_simple_paths <- function( graph, from = from, to = to, + cutoff = cutoff, mode = mode ) ) diff --git a/tests/testthat/test-paths.R b/tests/testthat/test-paths.R index 3a337ea9c4a..85f76ce094c 100644 --- a/tests/testthat/test-paths.R +++ b/tests/testthat/test-paths.R @@ -61,3 +61,13 @@ test_that("graph_center() works -- weights", { E(g)$weight <- seq_len(ecount(g)) expect_equal(as.numeric(graph_center(g)), 7) }) + +test_that("all_simple_paths() passes on cutoff argument", { + g <- make_ring(7) + expect_equal(lengths(all_simple_paths(g, 1, cutoff = 1)), c(2, 2)) + expect_equal(lengths(all_simple_paths(g, 1, cutoff = 2)), c(2, 3, 2, 3)) + expect_equal( + lengths(all_simple_paths(g, 1)), + c(2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7) + ) +}) From bcf6d9b21d8d7d95f3aec1041e86180be7de52af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 5 Oct 2025 15:02:37 +0200 Subject: [PATCH 062/154] ci: Use newer CSAN image --- .github/workflows/build-and-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-check.yml b/.github/workflows/build-and-check.yml index a83f52a280b..79243ca5cbd 100644 --- a/.github/workflows/build-and-check.yml +++ b/.github/workflows/build-and-check.yml @@ -38,11 +38,11 @@ jobs: - name: run sanitizer uses: addnab/docker-run-action@v3 with: - image: ghcr.io/cynkra/docker-images/rigraph-san:latest + image: ghcr.io/cynkra/docker-images/r-debug-csan-igraph:latest options: --rm --platform linux/amd64 -v ${{ github.workspace }}:/rigraph run: | set -e printenv cd rigraph RDcsan CMD INSTALL . --no-byte-compile - TESTTHAT_PARALLEL=false CI=true R_SANITIZER=true RDcsan -q -e 'testthat::test_local(reporter = c("location", "summary"), load_package = "installed")' + CI=true R_SANITIZER=true RDcsan -q -e 'testthat::test_local(reporter = c("location", "summary"), load_package = "installed")' From 852788b3f9138b5d8d28a77edc768e9cd9c8d5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 9 Oct 2025 19:39:40 +0200 Subject: [PATCH 063/154] Check results --- revdep/README.md | 17 +- revdep/cran.md | 31 +- revdep/failures.md | 232 +-------- revdep/problems.md | 1111 +------------------------------------------- 4 files changed, 50 insertions(+), 1341 deletions(-) diff --git a/revdep/README.md b/revdep/README.md index 6abbd372eb1..abacbb31d9e 100644 --- a/revdep/README.md +++ b/revdep/README.md @@ -1,15 +1,12 @@ # Revdeps -## Failed to check (13) +## Failed to check (10) |package |version |error |warning |note | |:---------------|:-------|:-----|:-------|:----| |bnlearn |5.1 |1 | | | -|dataone |2.2.2 |1 | | | -|datapack |1.4.1 |1 | | | |EGAnet |? | | | | |FAfA |? | | | | -|FAIRmaterials |0.4.2.1 |1 | | | |lavaan.shiny |? | | | | |multinma |0.8.1 |1 | | | |randomForestSRC |? | | | | @@ -18,14 +15,12 @@ |streamDAG |? | | | | |TestAnaAPP |? | | | | -## New problems (21) +## New problems (15) |package |version |error |warning |note | |:--------------------|:--------|:------|:-------|:----| |[AnimalHabitatNetwork](problems.md#animalhabitatnetwork)|0.1.0 |__+1__ | | | -|[archeofrag](problems.md#archeofrag)|1.2.0 |__+3__ | |1 | |[CITMIC](problems.md#citmic)|0.1.2 |__+1__ | | | -|[dosearch](problems.md#dosearch)|1.0.11 |__+1__ | |1 | |[DrDimont](problems.md#drdimont)|0.1.4 |__+2__ | |1 | |[egor](problems.md#egor)|1.24.2 |__+1__ | | | |[FCMapper](problems.md#fcmapper)|1.1 |__+1__ | | | @@ -33,14 +28,10 @@ |[incidentally](problems.md#incidentally)|1.0.3 |__+1__ | | | |[IOHanalyzer](problems.md#iohanalyzer)|0.1.8.10 |__+1__ | |2 | |[klassR](problems.md#klassr)|1.0.2 |__+1__ | |1 | -|[manynet](problems.md#manynet)|1.6.0 |__+2__ | | | -|[multinet](problems.md#multinet)|4.2.2 |__+1__ | |1 | +|[multinet](problems.md#multinet)|4.3.1 |__+1__ | |1 | |[mwcsr](problems.md#mwcsr)|0.1.9 |__+2__ | |1 | |[PopComm](problems.md#popcomm)|0.1.0.1 |__+1__ | | | -|[remify](problems.md#remify)|3.2.8 |__+1__ | |1 | |[rsetse](problems.md#rsetse)|0.5.0 |__+2__ | | | |[SEMID](problems.md#semid)|0.4.1 |__+2__ | | | -|[sharpshootR](problems.md#sharpshootr)|2.3.3 |__+1__ | | | -|[tilemaps](problems.md#tilemaps)|0.2.0 |__+2__ | |1 | -|[timeordered](problems.md#timeordered)|1.0.1 |__+1__ | | | +|[timeordered](problems.md#timeordered)|1.0.2 |__+1__ | | | diff --git a/revdep/cran.md b/revdep/cran.md index 354e462bc21..1f84e0b61e4 100644 --- a/revdep/cran.md +++ b/revdep/cran.md @@ -1,9 +1,9 @@ ## revdepcheck results -We checked 37 reverse dependencies (36 from CRAN + 1 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package. +We checked 34 reverse dependencies (33 from CRAN + 1 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package. - * We saw 21 new problems - * We failed to check 12 packages + * We saw 15 new problems + * We failed to check 9 packages Issues with CRAN packages are summarised below. @@ -13,17 +13,9 @@ Issues with CRAN packages are summarised below. * AnimalHabitatNetwork checking examples ... ERROR -* archeofrag - checking examples ... ERROR - checking tests ... ERROR - checking re-building of vignette outputs ... ERROR - * CITMIC checking re-building of vignette outputs ... ERROR -* dosearch - checking tests ... ERROR - * DrDimont checking examples ... ERROR checking re-building of vignette outputs ... ERROR @@ -46,10 +38,6 @@ Issues with CRAN packages are summarised below. * klassR checking examples ... ERROR -* manynet - checking examples ... ERROR - checking tests ... ERROR - * multinet checking examples ... ERROR @@ -60,9 +48,6 @@ Issues with CRAN packages are summarised below. * PopComm checking examples ... ERROR -* remify - checking tests ... ERROR - * rsetse checking examples ... ERROR checking re-building of vignette outputs ... ERROR @@ -71,24 +56,14 @@ Issues with CRAN packages are summarised below. checking examples ... ERROR checking tests ... ERROR -* sharpshootR - checking examples ... ERROR - -* tilemaps - checking examples ... ERROR - checking re-building of vignette outputs ... ERROR - * timeordered checking examples ... ERROR ### Failed to check * bnlearn (NA) -* dataone (NA) -* datapack (NA) * EGAnet (NA) * FAfA (NA) -* FAIRmaterials (NA) * lavaan.shiny (NA) * multinma (NA) * randomForestSRC (NA) diff --git a/revdep/failures.md b/revdep/failures.md index ea5de2bd14e..82e563a6f63 100644 --- a/revdep/failures.md +++ b/revdep/failures.md @@ -423,130 +423,6 @@ ERROR: loading failed * removing ‘/tmp/workdir/bnlearn/old/bnlearn.Rcheck/bnlearn’ -``` -# dataone - -
- -* Version: 2.2.2 -* GitHub: https://github.com/DataONEorg/rdataone -* Source code: https://github.com/cran/dataone -* Date/Publication: 2022-06-10 19:30:02 UTC -* Number of recursive dependencies: 63 - -Run `revdepcheck::cloud_details(, "dataone")` for more info - -
- -## In both - -* checking whether package ‘dataone’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/dataone/new/dataone.Rcheck/00install.out’ for details. - ``` - -## Installation - -### Devel - -``` -* installing *source* package ‘dataone’ ... -** package ‘dataone’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in dyn.load(file, DLLpath = DLLpath, ...) : - unable to load shared object '/usr/local/lib/R/site-library/redland/libs/redland.so': - librdf.so.0: cannot open shared object file: No such file or directory -Calls: ... namespaceImport -> loadNamespace -> library.dynam -> dyn.load -Execution halted -ERROR: lazy loading failed for package ‘dataone’ -* removing ‘/tmp/workdir/dataone/new/dataone.Rcheck/dataone’ - - -``` -### CRAN - -``` -* installing *source* package ‘dataone’ ... -** package ‘dataone’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in dyn.load(file, DLLpath = DLLpath, ...) : - unable to load shared object '/usr/local/lib/R/site-library/redland/libs/redland.so': - librdf.so.0: cannot open shared object file: No such file or directory -Calls: ... namespaceImport -> loadNamespace -> library.dynam -> dyn.load -Execution halted -ERROR: lazy loading failed for package ‘dataone’ -* removing ‘/tmp/workdir/dataone/old/dataone.Rcheck/dataone’ - - -``` -# datapack - -
- -* Version: 1.4.1 -* GitHub: https://github.com/ropensci/datapack -* Source code: https://github.com/cran/datapack -* Date/Publication: 2022-06-10 19:40:01 UTC -* Number of recursive dependencies: 63 - -Run `revdepcheck::cloud_details(, "datapack")` for more info - -
- -## In both - -* checking whether package ‘datapack’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/datapack/new/datapack.Rcheck/00install.out’ for details. - ``` - -## Installation - -### Devel - -``` -* installing *source* package ‘datapack’ ... -** package ‘datapack’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in dyn.load(file, DLLpath = DLLpath, ...) : - unable to load shared object '/usr/local/lib/R/site-library/redland/libs/redland.so': - librdf.so.0: cannot open shared object file: No such file or directory -Calls: ... namespaceImport -> loadNamespace -> library.dynam -> dyn.load -Execution halted -ERROR: lazy loading failed for package ‘datapack’ -* removing ‘/tmp/workdir/datapack/new/datapack.Rcheck/datapack’ - - -``` -### CRAN - -``` -* installing *source* package ‘datapack’ ... -** package ‘datapack’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in dyn.load(file, DLLpath = DLLpath, ...) : - unable to load shared object '/usr/local/lib/R/site-library/redland/libs/redland.so': - librdf.so.0: cannot open shared object file: No such file or directory -Calls: ... namespaceImport -> loadNamespace -> library.dynam -> dyn.load -Execution halted -ERROR: lazy loading failed for package ‘datapack’ -* removing ‘/tmp/workdir/datapack/old/datapack.Rcheck/datapack’ - - ``` # EGAnet @@ -573,7 +449,7 @@ Run `revdepcheck::cloud_details(, "EGAnet")` for more info * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘EGAnet/DESCRIPTION’ ... OK @@ -602,7 +478,7 @@ Status: 1 ERROR * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘EGAnet/DESCRIPTION’ ... OK @@ -647,7 +523,7 @@ Run `revdepcheck::cloud_details(, "FAfA")` for more info * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘FAfA/DESCRIPTION’ ... OK @@ -676,7 +552,7 @@ Status: 1 ERROR * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘FAfA/DESCRIPTION’ ... OK @@ -695,68 +571,6 @@ Status: 1 ERROR -``` -# FAIRmaterials - -
- -* Version: 0.4.2.1 -* GitHub: NA -* Source code: https://github.com/cran/FAIRmaterials -* Date/Publication: 2024-06-27 15:40:02 UTC -* Number of recursive dependencies: 90 - -Run `revdepcheck::cloud_details(, "FAIRmaterials")` for more info - -
- -## In both - -* checking whether package ‘FAIRmaterials’ can be installed ... ERROR - ``` - Installation failed. - See ‘/tmp/workdir/FAIRmaterials/new/FAIRmaterials.Rcheck/00install.out’ for details. - ``` - -## Installation - -### Devel - -``` -* installing *source* package ‘FAIRmaterials’ ... -** package ‘FAIRmaterials’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in dyn.load(file, DLLpath = DLLpath, ...) : - unable to load shared object '/usr/local/lib/R/site-library/redland/libs/redland.so': - librdf.so.0: cannot open shared object file: No such file or directory -Calls: ... asNamespace -> loadNamespace -> library.dynam -> dyn.load -Execution halted -ERROR: lazy loading failed for package ‘FAIRmaterials’ -* removing ‘/tmp/workdir/FAIRmaterials/new/FAIRmaterials.Rcheck/FAIRmaterials’ - - -``` -### CRAN - -``` -* installing *source* package ‘FAIRmaterials’ ... -** package ‘FAIRmaterials’ successfully unpacked and MD5 sums checked -** using staged installation -** R -** inst -** byte-compile and prepare package for lazy loading -Error in dyn.load(file, DLLpath = DLLpath, ...) : - unable to load shared object '/usr/local/lib/R/site-library/redland/libs/redland.so': - librdf.so.0: cannot open shared object file: No such file or directory -Calls: ... asNamespace -> loadNamespace -> library.dynam -> dyn.load -Execution halted -ERROR: lazy loading failed for package ‘FAIRmaterials’ -* removing ‘/tmp/workdir/FAIRmaterials/old/FAIRmaterials.Rcheck/FAIRmaterials’ - - ``` # lavaan.shiny @@ -766,7 +580,7 @@ ERROR: lazy loading failed for package ‘FAIRmaterials’ * GitHub: https://github.com/kylehamilton/lavaan.shiny * Source code: https://github.com/cran/lavaan.shiny * Date/Publication: 2017-04-07 06:05:09 UTC -* Number of recursive dependencies: 114 +* Number of recursive dependencies: 110 Run `revdepcheck::cloud_details(, "lavaan.shiny")` for more info @@ -783,7 +597,7 @@ Run `revdepcheck::cloud_details(, "lavaan.shiny")` for more info * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘lavaan.shiny/DESCRIPTION’ ... OK @@ -812,7 +626,7 @@ Status: 1 ERROR * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘lavaan.shiny/DESCRIPTION’ ... OK @@ -840,7 +654,7 @@ Status: 1 ERROR * GitHub: https://github.com/dmphillippo/multinma * Source code: https://github.com/cran/multinma * Date/Publication: 2025-05-31 00:00:02 UTC -* Number of recursive dependencies: 149 +* Number of recursive dependencies: 150 Run `revdepcheck::cloud_details(, "multinma")` for more info @@ -2874,11 +2688,11 @@ ERROR: compilation failed for package ‘multinma’
-* Version: 3.4.1 +* Version: 3.4.2 * GitHub: https://github.com/kogalur/randomForestSRC * Source code: https://github.com/cran/randomForestSRC -* Date/Publication: 2025-06-08 00:00:02 UTC -* Number of recursive dependencies: 156 +* Date/Publication: 2025-09-30 11:40:02 UTC +* Number of recursive dependencies: 155 Run `revdepcheck::cloud_details(, "randomForestSRC")` for more info @@ -2895,11 +2709,11 @@ Run `revdepcheck::cloud_details(, "randomForestSRC")` for more info * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘randomForestSRC/DESCRIPTION’ ... OK -* this is package ‘randomForestSRC’ version ‘3.4.1’ +* this is package ‘randomForestSRC’ version ‘3.4.2’ * checking package namespace information ... OK * checking package dependencies ... NOTE Package suggested but not available for checking: ‘imbalance’ @@ -2969,11 +2783,11 @@ Status: 1 NOTE * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘randomForestSRC/DESCRIPTION’ ... OK -* this is package ‘randomForestSRC’ version ‘3.4.1’ +* this is package ‘randomForestSRC’ version ‘3.4.2’ * checking package namespace information ... OK * checking package dependencies ... NOTE Package suggested but not available for checking: ‘imbalance’ @@ -3077,7 +2891,7 @@ Run `revdepcheck::cloud_details(, "RSP")` for more info * GitHub: https://github.com/santosoph/sphereML * Source code: https://github.com/cran/sphereML * Date/Publication: 2025-05-09 17:10:06 UTC -* Number of recursive dependencies: 192 +* Number of recursive dependencies: 193 Run `revdepcheck::cloud_details(, "sphereML")` for more info @@ -3094,7 +2908,7 @@ Run `revdepcheck::cloud_details(, "sphereML")` for more info * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘sphereML/DESCRIPTION’ ... OK @@ -3124,7 +2938,7 @@ Status: 1 ERROR * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘sphereML/DESCRIPTION’ ... OK @@ -3153,7 +2967,7 @@ Status: 1 ERROR * GitHub: NA * Source code: https://github.com/cran/streamDAG * Date/Publication: 2025-01-14 21:50:02 UTC -* Number of recursive dependencies: 137 +* Number of recursive dependencies: 136 Run `revdepcheck::cloud_details(, "streamDAG")` for more info @@ -3170,7 +2984,7 @@ Run `revdepcheck::cloud_details(, "streamDAG")` for more info * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘streamDAG/DESCRIPTION’ ... OK @@ -3198,7 +3012,7 @@ Status: 1 ERROR * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘streamDAG/DESCRIPTION’ ... OK @@ -3242,7 +3056,7 @@ Run `revdepcheck::cloud_details(, "TestAnaAPP")` for more info * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘TestAnaAPP/DESCRIPTION’ ... OK @@ -3271,7 +3085,7 @@ Status: 1 ERROR * R was compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 -* running under: Ubuntu 24.04.2 LTS +* running under: Ubuntu 24.04.3 LTS * using session charset: UTF-8 * using option ‘--no-manual’ * checking for file ‘TestAnaAPP/DESCRIPTION’ ... OK diff --git a/revdep/problems.md b/revdep/problems.md index d940d1529c7..e3f16054a16 100644 --- a/revdep/problems.md +++ b/revdep/problems.md @@ -6,7 +6,7 @@ * GitHub: NA * Source code: https://github.com/cran/AnimalHabitatNetwork * Date/Publication: 2019-11-25 19:40:02 UTC -* Number of recursive dependencies: 27 +* Number of recursive dependencies: 22 Run `revdepcheck::cloud_details(, "AnimalHabitatNetwork")` for more info @@ -40,242 +40,6 @@ Run `revdepcheck::cloud_details(, "AnimalHabitatNetwork")` for more info Execution halted ``` -# archeofrag - -
- -* Version: 1.2.0 -* GitHub: https://github.com/sebastien-plutniak/archeofrag -* Source code: https://github.com/cran/archeofrag -* Date/Publication: 2025-03-27 11:50:25 UTC -* Number of recursive dependencies: 62 - -Run `revdepcheck::cloud_details(, "archeofrag")` for more info - -
- -## Newly broken - -* checking examples ... ERROR - ``` - Running examples in ‘archeofrag-Ex.R’ failed - The error most likely occurred in: - - > ### Name: frag.cycles - > ### Title: Count the k-cycles in a graph, for cycles =< k - > ### Aliases: frag.cycles - > ### Keywords: measurement - > - > ### ** Examples - > - > g <- frag.simul.process(n.components=20, vertices=50, disturbance=.15) - Error in `vctrs::vec_c()`: - ! Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - Execution halted - ``` - -* checking tests ... ERROR - ``` - Running ‘testthat.R’ - Running the tests in ‘tests/testthat.R’ failed. - Complete output: - > library(testthat) - > library(archeofrag) - > - > test_check("archeofrag") - More than 2 layers: the 'frag.edges.weighting' function is applied to each pair of layers. - More than 2 layers: the 'frag.edges.weighting' function is applied to each pair of layers. - More than 2 layers: the 'frag.edges.weighting' function is applied to each pair of layers. - More than 2 layers: the 'frag.edges.weighting' function is applied to each pair of layers. - [ FAIL 9 | WARN 0 | SKIP 0 | PASS 58 ] - - ══ Failed tests ════════════════════════════════════════════════════════════════ - ── Error ('test-frag.graph.reduce.R:24:3'): reduce vertice number (not conserving objects nr) ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.graph.reduce.R:24:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.graph.reduce.R:33:3'): reduce vertice number (conserving objects nr, conserving fragments balance) ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.graph.reduce.R:33:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.graph.reduce.R:48:3'): reduce vertice number (conserving fragments balance and inter-units connection) ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.graph.reduce.R:48:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.simul.compare.R:5:3'): frag.simul.compare works ─────────── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.simul.compare.R:5:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.simul.process.R:44:3'): parameters of a generated graph with 2 initial layers are correct ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.simul.process.R:44:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.simul.process.R:56:3'): admixture and cohesion values of a graph with 2 initial layers are correct ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.simul.process.R:56:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.simul.process.R:67:3'): the optional asymmetric.transport.from parameter works ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.simul.process.R:67:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.simul.process.R:84:3'): the optional from.observed.graph parameter works ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.simul.process.R:84:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - ── Error ('test-frag.simul.summarise.R:4:3'): parameters of a constrained generated graph with 1 initial layer are correct ── - - Error in `vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]])`: Can't combine `..1` and `..2` . - Backtrace: - ▆ - 1. ├─archeofrag::frag.simul.process(...) at test-frag.simul.summarise.R:4:3 - 2. │ └─igraph::disjoint_union(g.layer1, g.layer2) - 3. │ └─vctrs::vec_c(attr[[exattr[a]]], va[[exattr[a]]]) - 4. └─vctrs (local) ``() - 5. └─vctrs::vec_default_ptype2(...) - 6. ├─base::withRestarts(...) - 7. │ └─base (local) withOneRestart(expr, restarts[[1L]]) - 8. │ └─base (local) doWithOneRestart(return(expr), restart) - 9. └─vctrs::stop_incompatible_type(...) - 10. └─vctrs:::stop_incompatible(...) - 11. └─vctrs:::stop_vctrs(...) - 12. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call) - - [ FAIL 9 | WARN 0 | SKIP 0 | PASS 58 ] - Error: Test failures - Execution halted - ``` - -* checking re-building of vignette outputs ... ERROR - ``` - Error(s) in re-building vignettes: - --- re-building ‘archeofrag-vignette.Rmd’ using rmarkdown - ``` - -## In both - -* checking data for non-ASCII characters ... NOTE - ``` - Note: found 3 marked UTF-8 strings - ``` - # CITMIC
@@ -314,86 +78,6 @@ Run `revdepcheck::cloud_details(, "CITMIC")` for more info Execution halted ``` -# dosearch - -
- -* Version: 1.0.11 -* GitHub: https://github.com/santikka/dosearch -* Source code: https://github.com/cran/dosearch -* Date/Publication: 2024-07-16 09:50:02 UTC -* Number of recursive dependencies: 90 - -Run `revdepcheck::cloud_details(, "dosearch")` for more info - -
- -## Newly broken - -* checking tests ... ERROR - ``` - Running ‘testthat.R’ - Running the tests in ‘tests/testthat.R’ failed. - Complete output: - > #' @srrstats {G5.2} Error and warning behavior is tested. - > #' @srrstats {G5.2a} Messages are unique. - > #' @srrstats {G5.2b} Conditions are demonstrated. - > #' @srrstats {G5.4, G5.4a, G5.6} Output of dosearch is compared against known - > #' theoretical identifiability and non-identifiability results. - > #' In other words, correctness can be tested independently of the - > #' implementation. - > #' @srrstats {G5.5} The algorithm is deterministic, so this could also be NA - > #' @srrstats {G5.6a} Because the package output is symbolic, the recovery - > #' of e.g., a causal effect is exact. - > #' @srrstats {G5.7} Performance and scalability have been demonstrated - > #' in the JSS paper, and the simulations are too large to run on a single - > #' PC and require a cluster. The replication materials for this simulation - > #' are included in the 'rep' directory. The algorithm has exponential - > #' time and memory complexity in the number of the vertices of the graph, - > #' and it has been hypothesized that the general identifiability problem - > #' itself is NP-hard. - > #' @srrstats {G5.8, G5.8a G5.8b, G5.8c, G5.8d} Edge conditions are tested. - > #' @srrstats {NW6.0} Inputs types are tested. - > #' @noRd - > library(testthat) - > library(dosearch) - > - > test_check("dosearch") - [ FAIL 1 | WARN 3 | SKIP 0 | PASS 294 ] - - ══ Failed tests ════════════════════════════════════════════════════════════════ - ── Error ('test-interface.R:32:3'): igraph graph without names gets named ────── - Error in `FUN(X[[i]], ...)`: Error: Logical index length does not match the number of edges. Recycling is not allowed. - Backtrace: - ▆ - 1. ├─testthat::expect_message(parse_graph(g_igraph), "Argument `graph` is not named, node names have been assigned") at test-interface.R:32:3 - 2. │ └─testthat:::expect_condition_matching(...) - 3. │ └─testthat:::quasi_capture(...) - 4. │ ├─testthat (local) .capture(...) - 5. │ │ └─base::withCallingHandlers(...) - 6. │ └─rlang::eval_bare(quo_get_expr(.quo), quo_get_env(.quo)) - 7. └─dosearch:::parse_graph(g_igraph) - 8. ├─e[(is.na(description) | description != "U")] - 9. └─igraph:::`[.igraph.es`(...) - 10. └─base::lapply(...) - 11. └─igraph (local) FUN(X[[i]], ...) - 12. └─cli::cli_abort("Error: Logical index length does not match the number of edges. Recycling is not allowed.") - 13. └─rlang::abort(...) - - [ FAIL 1 | WARN 3 | SKIP 0 | PASS 294 ] - Error: Test failures - Execution halted - ``` - -## In both - -* checking installed package size ... NOTE - ``` - installed size is 5.9Mb - sub-directories of 1Mb or more: - libs 5.0Mb - ``` - # DrDimont
@@ -402,7 +86,7 @@ Run `revdepcheck::cloud_details(, "dosearch")` for more info * GitHub: NA * Source code: https://github.com/cran/DrDimont * Date/Publication: 2022-09-23 15:40:02 UTC -* Number of recursive dependencies: 124 +* Number of recursive dependencies: 121 Run `revdepcheck::cloud_details(, "DrDimont")` for more info @@ -435,16 +119,16 @@ Run `revdepcheck::cloud_details(, "DrDimont")` for more info + reduction_method="pickHardThreshold", + r_squared=list(default=0.65, metabolite=0.1), + cut_vector=list(default=seq(0.2, 0.5, 0.01))) - [25-09-05 04:12:21] WARNING: Python executable in virtual environment 'r-DrDimont' not found. Either run `install_python_dependencies(package_manager='pip') or set `conda=TRUE` in `drdimont_settings()` if conda installation was used. + [25-10-09 09:41:00] WARNING: Python executable in virtual environment 'r-DrDimont' not found. Either run `install_python_dependencies(package_manager='pip') or set `conda=TRUE` in `drdimont_settings()` if conda installation was used. > > example_individual_graphs <- generate_individual_graphs( + correlation_matrices=correlation_matrices_example, + layers=layers_example, + settings=example_settings) - [25-09-05 04:12:21] Generating graph of layer mrna for groupA... - [25-09-05 04:12:21] Reducing network by WGCNA::pickHardThreshold... - [25-09-05 04:12:21] R2 cutoff: 0.65 - [25-09-05 04:12:22] Cut Threshold: 0.26 + [25-10-09 09:41:00] Generating graph of layer mrna for groupA... + [25-10-09 09:41:00] Reducing network by WGCNA::pickHardThreshold... + [25-10-09 09:41:00] R2 cutoff: 0.65 + [25-10-09 09:41:01] Cut Threshold: 0.26 Error in `graph_from_adjacency_matrix()`: ! Cannot create a graph object because the adjacency matrix contains NAs. @@ -661,7 +345,7 @@ Run `revdepcheck::cloud_details(, "incidentally")` for more info * GitHub: https://github.com/IOHprofiler/IOHAnalyzer * Source code: https://github.com/cran/IOHanalyzer * Date/Publication: 2024-03-01 12:52:37 UTC -* Number of recursive dependencies: 136 +* Number of recursive dependencies: 134 Run `revdepcheck::cloud_details(, "IOHanalyzer")` for more info @@ -701,7 +385,7 @@ Run `revdepcheck::cloud_details(, "IOHanalyzer")` for more info * checking installed package size ... NOTE ``` - installed size is 6.6Mb + installed size is 6.7Mb sub-directories of 1Mb or more: data 1.4Mb libs 3.2Mb @@ -769,92 +453,14 @@ Run `revdepcheck::cloud_details(, "klassR")` for more info Note: found 1764 marked UTF-8 strings ``` -# manynet - -
- -* Version: 1.6.0 -* GitHub: https://github.com/stocnet/manynet -* Source code: https://github.com/cran/manynet -* Date/Publication: 2025-08-22 23:40:02 UTC -* Number of recursive dependencies: 117 - -Run `revdepcheck::cloud_details(, "manynet")` for more info - -
- -## Newly broken - -* checking examples ... ERROR - ``` - Running examples in ‘manynet-Ex.R’ failed - The error most likely occurred in: - - > ### Name: mark_features - > ### Title: Marking networks features - > ### Aliases: mark_features is_connected is_perfect_matching is_eulerian - > ### is_acyclic is_aperiodic - > - > ### ** Examples - > - > is_connected(ison_southern_women) - [1] TRUE - > is_perfect_matching(ison_southern_women) - [1] FALSE - > is_eulerian(ison_brandes) - [1] FALSE - > is_acyclic(ison_algebra) - [1] FALSE - > is_aperiodic(ison_algebra) - Killed - ``` - -* checking tests ... ERROR - ``` - Running ‘testthat.R’ - Running the tests in ‘tests/testthat.R’ failed. - Complete output: - > library(testthat) - > library(manynet) - > - > test_check("manynet") - Starting 2 test processes - - - Error in `private$handle_error()`: - ! testthat subprocess exited in file `test-measure_closure.R` - Caused by error: - ! R session crashed with exit code -9 - Backtrace: - ▆ - 1. └─testthat::test_check("manynet") - 2. └─testthat::test_dir(...) - 3. └─testthat:::test_files(...) - 4. └─testthat:::test_files_parallel(...) - 5. ├─withr::with_dir(...) - 6. │ └─base::force(code) - 7. ├─testthat::with_reporter(...) - 8. │ └─base::tryCatch(...) - 9. │ └─base (local) tryCatchList(expr, classes, parentenv, handlers) - 10. │ └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]]) - 11. │ └─base (local) doTryCatch(return(expr), name, parentenv, handler) - 12. └─testthat:::parallel_event_loop_chunky(queue, reporters, ".") - 13. └─queue$poll(Inf) - 14. └─base::lapply(...) - 15. └─testthat (local) FUN(X[[i]], ...) - 16. └─private$handle_error(msg, i) - 17. └─rlang::abort(...) - Execution halted - ``` - # multinet
-* Version: 4.2.2 +* Version: 4.3.1 * GitHub: NA * Source code: https://github.com/cran/multinet -* Date/Publication: 2025-04-08 07:20:06 UTC +* Date/Publication: 2025-09-23 16:50:02 UTC * Number of recursive dependencies: 13 Run `revdepcheck::cloud_details(, "multinet")` for more info @@ -896,9 +502,9 @@ Run `revdepcheck::cloud_details(, "multinet")` for more info * checking installed package size ... NOTE ``` - installed size is 137.5Mb + installed size is 139.0Mb sub-directories of 1Mb or more: - libs 137.2Mb + libs 138.7Mb ``` # mwcsr @@ -1010,7 +616,7 @@ Run `revdepcheck::cloud_details(, "mwcsr")` for more info * GitHub: NA * Source code: https://github.com/cran/PopComm * Date/Publication: 2025-04-25 15:20:09 UTC -* Number of recursive dependencies: 172 +* Number of recursive dependencies: 173 Run `revdepcheck::cloud_details(, "PopComm")` for more info @@ -1039,540 +645,6 @@ Run `revdepcheck::cloud_details(, "PopComm")` for more info Execution halted ``` -# remify - -
- -* Version: 3.2.8 -* GitHub: https://github.com/TilburgNetworkGroup/remify -* Source code: https://github.com/cran/remify -* Date/Publication: 2025-01-29 13:20:05 UTC -* Number of recursive dependencies: 36 - -Run `revdepcheck::cloud_details(, "remify")` for more info - -
- -## Newly broken - -* checking tests ... ERROR - ``` - Running ‘tinytest.R’ - Running the tests in ‘tests/tinytest.R’ failed. - Complete output: - > if ( requireNamespace("tinytest", quietly=TRUE) ){ - + tinytest::test_package("remify") - + } - - test-rehshape.R............... 0 tests - test-rehshape.R............... 1 tests OK - test-rehshape.R............... 1 tests OK - test-rehshape.R............... 2 tests OK - test-rehshape.R............... 3 tests OK - test-rehshape.R............... 4 tests OK - test-rehshape.R............... 5 tests OK - test-rehshape.R............... 6 tests OK - test-rehshape.R............... 7 tests OK - test-rehshape.R............... 8 tests OK - test-rehshape.R............... 9 tests OK - test-rehshape.R............... 10 tests OK - test-rehshape.R............... 10 tests OK - test-rehshape.R............... 11 tests OK - test-rehshape.R............... 12 tests OK - test-rehshape.R............... 13 tests OK - test-rehshape.R............... 14 tests OK - test-rehshape.R............... 15 tests OK - test-rehshape.R............... 16 tests OK - test-rehshape.R............... 17 tests OK - test-rehshape.R............... 18 tests OK - test-rehshape.R............... 19 tests OK - test-rehshape.R............... 19 tests OK - test-rehshape.R............... 20 tests OK - test-rehshape.R............... 20 tests OK - test-rehshape.R............... 21 tests OK - test-rehshape.R............... 22 tests OK - test-rehshape.R............... 22 tests OK - test-rehshape.R............... 22 tests OK - test-rehshape.R............... 23 tests OK - test-rehshape.R............... 24 tests OK - test-rehshape.R............... 24 tests OK - test-rehshape.R............... 24 tests OK - test-rehshape.R............... 25 tests OK - test-rehshape.R............... 26 tests OK 2.3s - - test-remify-error-messages.R.. 1 tests OK - test-remify-error-messages.R.. 1 tests OK - test-remify-error-messages.R.. 1 tests OK - test-remify-error-messages.R.. 2 tests OK - test-remify-error-messages.R.. 2 tests OK - test-remify-error-messages.R.. 2 tests OK - test-remify-error-messages.R.. 3 tests OK - test-remify-error-messages.R.. 3 tests OK - test-remify-error-messages.R.. 3 tests OK - test-remify-error-messages.R.. 4 tests OK - test-remify-error-messages.R.. 5 tests OK - test-remify-error-messages.R.. 6 tests OK - test-remify-error-messages.R.. 6 tests OK - test-remify-error-messages.R.. 6 tests OK - test-remify-error-messages.R.. 7 tests OK - test-remify-error-messages.R.. 7 tests OK - test-remify-error-messages.R.. 8 tests OK - test-remify-error-messages.R.. 8 tests OK - test-remify-error-messages.R.. 8 tests OK - test-remify-error-messages.R.. 9 tests OK - test-remify-error-messages.R.. 9 tests OK - test-remify-error-messages.R.. 9 tests OK - test-remify-error-messages.R.. 10 tests OK - test-remify-error-messages.R.. 10 tests OK - test-remify-error-messages.R.. 10 tests OK - test-remify-error-messages.R.. 11 tests OK - test-remify-error-messages.R.. 11 tests OK - test-remify-error-messages.R.. 11 tests OK - test-remify-error-messages.R.. 12 tests OK - test-remify-error-messages.R.. 12 tests OK - test-remify-error-messages.R.. 12 tests OK - test-remify-error-messages.R.. 13 tests OK - test-remify-error-messages.R.. 13 tests OK - test-remify-error-messages.R.. 14 tests OK - test-remify-error-messages.R.. 14 tests OK - test-remify-error-messages.R.. 14 tests OK - test-remify-error-messages.R.. 15 tests OK - test-remify-error-messages.R.. 15 tests OK - test-remify-error-messages.R.. 15 tests OK - test-remify-error-messages.R.. 16 tests OK - test-remify-error-messages.R.. 16 tests OK - test-remify-error-messages.R.. 16 tests OK - test-remify-error-messages.R.. 17 tests OK - test-remify-error-messages.R.. 17 tests OK - test-remify-error-messages.R.. 17 tests OK - test-remify-error-messages.R.. 18 tests OK - test-remify-error-messages.R.. 18 tests OK - test-remify-error-messages.R.. 19 tests OK - test-remify-error-messages.R.. 19 tests OK - test-remify-error-messages.R.. 20 tests OK - test-remify-error-messages.R.. 20 tests OK - test-remify-error-messages.R.. 21 tests OK 0.1s - - test-remify-methods.R......... 0 tests - test-remify-methods.R......... 0 tests - test-remify-methods.R......... 1 tests OK - test-remify-methods.R......... 2 tests OK - test-remify-methods.R......... 3 tests OK - test-remify-methods.R......... 4 tests OK - test-remify-methods.R......... 4 tests OK - test-remify-methods.R......... 4 tests OK - test-remify-methods.R......... 4 tests OK - test-remify-methods.R......... 5 tests OK - test-remify-methods.R......... 6 tests OK - test-remify-methods.R......... 7 tests OK - test-remify-methods.R......... 8 tests OK - test-remify-methods.R......... 8 tests OK - test-remify-methods.R......... 8 tests OK - test-remify-methods.R......... 8 tests OK - test-remify-methods.R......... 8 tests OK - test-remify-methods.R......... 9 tests OK - test-remify-methods.R......... 10 tests OK - test-remify-methods.R......... 11 tests OK - test-remify-methods.R......... 12 tests OK - test-remify-methods.R......... 13 tests OK - test-remify-methods.R......... 13 tests OK - test-remify-methods.R......... 13 tests OK - test-remify-methods.R......... 13 tests OK - test-remify-methods.R......... 13 tests OK - test-remify-methods.R......... 13 tests OK - test-remify-methods.R......... 14 tests OK - test-remify-methods.R......... 15 tests OK - test-remify-methods.R......... 16 tests OK - test-remify-methods.R......... 17 tests OK - test-remify-methods.R......... 18 tests OK - test-remify-methods.R......... 18 tests OK - test-remify-methods.R......... 18 tests OK - test-remify-methods.R......... 18 tests OK - test-remify-methods.R......... 18 tests OK - test-remify-methods.R......... 19 tests OK - test-remify-methods.R......... 20 tests OK - test-remify-methods.R......... 21 tests OK - test-remify-methods.R......... 22 tests OK - test-remify-methods.R......... 23 tests OK - test-remify-methods.R......... 23 tests OK - test-remify-methods.R......... 23 tests OK - test-remify-methods.R......... 24 tests OK - test-remify-methods.R......... 25 tests OK - test-remify-methods.R......... 26 tests OK - test-remify-methods.R......... 27 tests OK - test-remify-methods.R......... 27 tests OK - test-remify-methods.R......... 27 tests OK - test-remify-methods.R......... 28 tests OK - test-remify-methods.R......... 29 tests OK - test-remify-methods.R......... 30 tests OK - test-remify-methods.R......... 31 tests OK - test-remify-methods.R......... 31 tests OK - test-remify-methods.R......... 31 tests OK - test-remify-methods.R......... 32 tests OK - test-remify-methods.R......... 33 tests OK - test-remify-methods.R......... 33 tests OK - test-remify-methods.R......... 33 tests OK - test-remify-methods.R......... 34 tests OK - test-remify-methods.R......... 35 tests OK - test-remify-methods.R......... 36 tests OK - test-remify-methods.R......... 37 tests OK - test-remify-methods.R......... 38 tests OK - test-remify-methods.R......... 39 tests OK - test-remify-methods.R......... 40 tests OK - test-remify-methods.R......... 41 tests OK - test-remify-methods.R......... 42 tests OK - test-remify-methods.R......... 43 tests OK - test-remify-methods.R......... 44 tests OK - test-remify-methods.R......... 45 tests OK - test-remify-methods.R......... 46 tests OK - test-remify-methods.R......... 47 tests OK - test-remify-methods.R......... 48 tests OK - test-remify-methods.R......... 49 tests OK - test-remify-methods.R......... 49 tests OK - test-remify-methods.R......... 50 tests OK - test-remify-methods.R......... 51 tests OK - test-remify-methods.R......... 52 tests OK - test-remify-methods.R......... 53 tests OK - test-remify-methods.R......... 54 tests OK - test-remify-methods.R......... 55 tests OK - test-remify-methods.R......... 56 tests OK - test-remify-methods.R......... 57 tests OK - test-remify-methods.R......... 58 tests OK - test-remify-methods.R......... 59 tests OK - test-remify-methods.R......... 60 tests OK - test-remify-methods.R......... 61 tests OK - test-remify-methods.R......... 62 tests OK - test-remify-methods.R......... 63 tests OK - test-remify-methods.R......... 64 tests OK - test-remify-methods.R......... 64 tests OK - test-remify-methods.R......... 65 tests OK - test-remify-methods.R......... 66 tests OK - test-remify-methods.R......... 67 tests OK - test-remify-methods.R......... 68 tests OK - test-remify-methods.R......... 69 tests OK - test-remify-methods.R......... 70 tests OK - test-remify-methods.R......... 71 tests OK - test-remify-methods.R......... 72 tests OK - test-remify-methods.R......... 73 tests OK - test-remify-methods.R......... 74 tests OK - test-remify-methods.R......... 75 tests OK - test-remify-methods.R......... 76 tests OK - test-remify-methods.R......... 76 tests OK - test-remify-methods.R......... 76 tests OK - test-remify-methods.R......... 77 tests OK - test-remify-methods.R......... 78 tests OK - test-remify-methods.R......... 79 tests OK - test-remify-methods.R......... 80 tests OK - test-remify-methods.R......... 81 tests OK - test-remify-methods.R......... 82 tests OK - test-remify-methods.R......... 82 tests OK - test-remify-methods.R......... 82 tests OK - test-remify-methods.R......... 83 tests OK - test-remify-methods.R......... 84 tests OK - test-remify-methods.R......... 85 tests OK - test-remify-methods.R......... 86 tests OK - test-remify-methods.R......... 87 tests OK - test-remify-methods.R......... 88 tests OK - test-remify-methods.R......... 89 tests OK - test-remify-methods.R......... 90 tests OK - test-remify-methods.R......... 90 tests OK - test-remify-methods.R......... 90 tests OK - test-remify-methods.R......... 90 tests OK - test-remify-methods.R......... 91 tests OK - test-remify-methods.R......... 91 tests OK - test-remify-methods.R......... 92 tests 1 fails - test-remify-methods.R......... 93 tests 2 fails - test-remify-methods.R......... 94 tests 3 fails - test-remify-methods.R......... 95 tests 4 fails - test-remify-methods.R......... 96 tests 5 fails - test-remify-methods.R......... 97 tests 6 fails - test-remify-methods.R......... 98 tests 7 fails - test-remify-methods.R......... 98 tests 7 fails - test-remify-methods.R......... 99 tests 8 fails - test-remify-methods.R......... 100 tests 9 fails - test-remify-methods.R......... 101 tests 10 fails - test-remify-methods.R......... 101 tests 10 fails - test-remify-methods.R......... 102 tests 10 fails - test-remify-methods.R......... 103 tests 10 fails - test-remify-methods.R......... 104 tests 10 fails - test-remify-methods.R......... 105 tests 10 fails - test-remify-methods.R......... 106 tests 10 fails - test-remify-methods.R......... 107 tests 10 fails - test-remify-methods.R......... 107 tests 10 fails - test-remify-methods.R......... 107 tests 10 fails - test-remify-methods.R......... 108 tests 10 fails - test-remify-methods.R......... 109 tests 10 fails - test-remify-methods.R......... 109 tests 10 fails - test-remify-methods.R......... 109 tests 10 fails - test-remify-methods.R......... 110 tests 10 fails - test-remify-methods.R......... 110 tests 10 fails - test-remify-methods.R......... 110 tests 10 fails - test-remify-methods.R......... 111 tests 10 fails - test-remify-methods.R......... 111 tests 10 fails - test-remify-methods.R......... 111 tests 10 fails - test-remify-methods.R......... 112 tests 10 fails - test-remify-methods.R......... 112 tests 10 fails - test-remify-methods.R......... 112 tests 10 fails - test-remify-methods.R......... 113 tests 10 fails 7.6s - - test-remify-warning-messages.R 0 tests - test-remify-warning-messages.R 0 tests - test-remify-warning-messages.R 1 tests OK - test-remify-warning-messages.R 1 tests OK - test-remify-warning-messages.R 2 tests OK - test-remify-warning-messages.R 2 tests OK - test-remify-warning-messages.R 2 tests OK - test-remify-warning-messages.R 3 tests OK - test-remify-warning-messages.R 3 tests OK - test-remify-warning-messages.R 3 tests OK - test-remify-warning-messages.R 4 tests OK - test-remify-warning-messages.R 4 tests OK - test-remify-warning-messages.R 4 tests OK - test-remify-warning-messages.R 5 tests OK - test-remify-warning-messages.R 5 tests OK - test-remify-warning-messages.R 5 tests OK - test-remify-warning-messages.R 6 tests OK - test-remify-warning-messages.R 6 tests OK - test-remify-warning-messages.R 6 tests OK - test-remify-warning-messages.R 7 tests OK - test-remify-warning-messages.R 7 tests OK - test-remify-warning-messages.R 7 tests OK - test-remify-warning-messages.R 7 tests OK - test-remify-warning-messages.R 8 tests OK - test-remify-warning-messages.R 9 tests OK - test-remify-warning-messages.R 9 tests OK - test-remify-warning-messages.R 10 tests OK - test-remify-warning-messages.R 11 tests OK - test-remify-warning-messages.R 11 tests OK - test-remify-warning-messages.R 11 tests OK - test-remify-warning-messages.R 12 tests OK - test-remify-warning-messages.R 13 tests OK - test-remify-warning-messages.R 13 tests OK - test-remify-warning-messages.R 14 tests OK - test-remify-warning-messages.R 15 tests OK - test-remify-warning-messages.R 15 tests OK - test-remify-warning-messages.R 15 tests OK - test-remify-warning-messages.R 15 tests OK - test-remify-warning-messages.R 15 tests OK - test-remify-warning-messages.R 16 tests OK - test-remify-warning-messages.R 17 tests OK - test-remify-warning-messages.R 17 tests OK - test-remify-warning-messages.R 18 tests OK - test-remify-warning-messages.R 19 tests OK - test-remify-warning-messages.R 19 tests OK - test-remify-warning-messages.R 19 tests OK - test-remify-warning-messages.R 19 tests OK - test-remify-warning-messages.R 20 tests OK - test-remify-warning-messages.R 21 tests OK - test-remify-warning-messages.R 21 tests OK - test-remify-warning-messages.R 22 tests OK - test-remify-warning-messages.R 23 tests OK - test-remify-warning-messages.R 23 tests OK - test-remify-warning-messages.R 23 tests OK - test-remify-warning-messages.R 23 tests OK - test-remify-warning-messages.R 23 tests OK - test-remify-warning-messages.R 24 tests OK - test-remify-warning-messages.R 25 tests OK - test-remify-warning-messages.R 25 tests OK - test-remify-warning-messages.R 26 tests OK - test-remify-warning-messages.R 27 tests OK - test-remify-warning-messages.R 27 tests OK - test-remify-warning-messages.R 27 tests OK - test-remify-warning-messages.R 27 tests OK - test-remify-warning-messages.R 28 tests OK - test-remify-warning-messages.R 29 tests OK - test-remify-warning-messages.R 29 tests OK - test-remify-warning-messages.R 30 tests OK - test-remify-warning-messages.R 31 tests OK 0.5s - - test-remify.R................. 0 tests - test-remify.R................. 1 tests OK - test-remify.R................. 2 tests OK - test-remify.R................. 3 tests OK - test-remify.R................. 4 tests OK - test-remify.R................. 5 tests OK - test-remify.R................. 6 tests OK - test-remify.R................. 7 tests OK - test-remify.R................. 8 tests OK - test-remify.R................. 9 tests OK - test-remify.R................. 10 tests OK - test-remify.R................. 10 tests OK - test-remify.R................. 10 tests OK - test-remify.R................. 10 tests OK - test-remify.R................. 11 tests OK - test-remify.R................. 12 tests OK - test-remify.R................. 13 tests OK - test-remify.R................. 13 tests OK - test-remify.R................. 13 tests OK - test-remify.R................. 14 tests OK - test-remify.R................. 15 tests OK - test-remify.R................. 15 tests OK - test-remify.R................. 15 tests OK - test-remify.R................. 15 tests OK - test-remify.R................. 16 tests OK - test-remify.R................. 17 tests OK - test-remify.R................. 17 tests OK - test-remify.R................. 17 tests OK - test-remify.R................. 17 tests OK - test-remify.R................. 18 tests OK - test-remify.R................. 19 tests OK - test-remify.R................. 19 tests OK - test-remify.R................. 19 tests OK - test-remify.R................. 19 tests OK - test-remify.R................. 20 tests OK - test-remify.R................. 20 tests OK - test-remify.R................. 21 tests OK - test-remify.R................. 21 tests OK - test-remify.R................. 21 tests OK - test-remify.R................. 21 tests OK - test-remify.R................. 21 tests OK - test-remify.R................. 22 tests OK - test-remify.R................. 22 tests OK - test-remify.R................. 23 tests OK - test-remify.R................. 23 tests OK - test-remify.R................. 23 tests OK - test-remify.R................. 23 tests OK - test-remify.R................. 24 tests OK - test-remify.R................. 24 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 25 tests OK - test-remify.R................. 26 tests OK - test-remify.R................. 26 tests OK - test-remify.R................. 26 tests OK - test-remify.R................. 27 tests OK - test-remify.R................. 27 tests OK - test-remify.R................. 27 tests OK - test-remify.R................. 27 tests OK - test-remify.R................. 28 tests OK - test-remify.R................. 29 tests OK - test-remify.R................. 30 tests OK - test-remify.R................. 30 tests OK - test-remify.R................. 31 tests OK - test-remify.R................. 31 tests OK - test-remify.R................. 32 tests OK - test-remify.R................. 32 tests OK - test-remify.R................. 33 tests OK - test-remify.R................. 33 tests OK - test-remify.R................. 34 tests OK - test-remify.R................. 34 tests OK - test-remify.R................. 34 tests OK - test-remify.R................. 34 tests OK - test-remify.R................. 34 tests OK - test-remify.R................. 35 tests OK - test-remify.R................. 35 tests OK - test-remify.R................. 36 tests OK - test-remify.R................. 37 tests OK - test-remify.R................. 38 tests OK - test-remify.R................. 39 tests OK - test-remify.R................. 40 tests OK - test-remify.R................. 41 tests OK - test-remify.R................. 42 tests OK - test-remify.R................. 43 tests OK - test-remify.R................. 44 tests OK - test-remify.R................. 45 tests OK - test-remify.R................. 45 tests OK - test-remify.R................. 45 tests OK - test-remify.R................. 46 tests OK - test-remify.R................. 47 tests OK - test-remify.R................. 47 tests OK - test-remify.R................. 47 tests OK - test-remify.R................. 48 tests OK - test-remify.R................. 49 tests OK - test-remify.R................. 49 tests OK - test-remify.R................. 50 tests OK - test-remify.R................. 51 tests OK - test-remify.R................. 51 tests OK - test-remify.R................. 52 tests OK - test-remify.R................. 53 tests OK - test-remify.R................. 53 tests OK - test-remify.R................. 54 tests OK - test-remify.R................. 55 tests OK - test-remify.R................. 55 tests OK - test-remify.R................. 55 tests OK - test-remify.R................. 55 tests OK - test-remify.R................. 55 tests OK - test-remify.R................. 56 tests OK - test-remify.R................. 56 tests OK - test-remify.R................. 57 tests OK - test-remify.R................. 57 tests OK - test-remify.R................. 57 tests OK - test-remify.R................. 58 tests OK - test-remify.R................. 58 tests OK - test-remify.R................. 59 tests OK - test-remify.R................. 59 tests OK - test-remify.R................. 59 tests OK - test-remify.R................. 59 tests OK - test-remify.R................. 60 tests OK - test-remify.R................. 60 tests OK - test-remify.R................. 61 tests OK - test-remify.R................. 61 tests OK - test-remify.R................. 61 tests OK - test-remify.R................. 62 tests OK - test-remify.R................. 62 tests OK - test-remify.R................. 63 tests OK 0.5s - ----- FAILED[xcpt]: test-remify-methods.R<349--349> - call| expect_silent(plot(x = out)) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<350--350> - call| expect_silent(plot(x = out, breaks = NULL, palette = NULL, n_intervals = NULL, - call| --> rev = NULL, actors = NULL, pch.degree = NULL, igraph.edge.color = NULL, - call| --> igraph.vertex.color = NULL)) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<351--351> - call| expect_silent(plot(x = out, pch.degree = -1)) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<352--352> - call| expect_silent(plot(x = out, igraph.edge.color = "#000000000", - call| --> igraph.vertex.color = "#000000000")) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<353--353> - call| expect_silent(plot(x = out, igraph.edge.color = "magenta", igraph.vertex.color = "cyan4")) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<354--354> - call| expect_silent(plot(x = out, n_intervals = 5)) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<355--355> - call| expect_silent(plot(x = out, actors = attr(out, "dictionary")$actors$actorName[1:5])) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<362--362> - call| expect_silent(plot(x = out)) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<363--363> - call| expect_silent(plot(x = out, n_intervals = 5)) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - ----- FAILED[xcpt]: test-remify-methods.R<364--364> - call| expect_silent(plot(x = out, actors = attr(out, "dictionary")$actors$actorName[1:5])) - diff| Execution was not silent. A warning was thrown with message - diff| 'vertex attribute frame.color contains NAs. Replacing with default value black' - Error: 10 out of 254 tests failed - Execution halted - ``` - -## In both - -* checking installed package size ... NOTE - ``` - installed size is 9.2Mb - sub-directories of 1Mb or more: - doc 3.5Mb - libs 4.8Mb - ``` - # rsetse
@@ -1581,7 +653,7 @@ Run `revdepcheck::cloud_details(, "remify")` for more info * GitHub: https://github.com/JonnoB/rSETSe * Source code: https://github.com/cran/rsetse * Date/Publication: 2021-06-11 10:00:02 UTC -* Number of recursive dependencies: 79 +* Number of recursive dependencies: 78 Run `revdepcheck::cloud_details(, "rsetse")` for more info @@ -1976,156 +1048,14 @@ Run `revdepcheck::cloud_details(, "SEMID")` for more info Execution halted ``` -# sharpshootR - -
- -* Version: 2.3.3 -* GitHub: https://github.com/ncss-tech/sharpshootR -* Source code: https://github.com/cran/sharpshootR -* Date/Publication: 2025-04-17 06:50:02 UTC -* Number of recursive dependencies: 146 - -Run `revdepcheck::cloud_details(, "sharpshootR")` for more info - -
- -## Newly broken - -* checking examples ... ERROR - ``` - Running examples in ‘sharpshootR-Ex.R’ failed - The error most likely occurred in: - - > ### Name: table5.2 - > ### Title: Table 5.2 from Hole and Campbell, 1985. - > ### Aliases: table5.2 - > ### Keywords: datasets - > - > ### ** Examples - > - > - > data("table5.2") - > - > if(requireNamespace("igraph")) { - + - + # note special incantation to get the "correct" graph structure - + g <- igraph::graph_from_adjacency_matrix(table5.2, mode = 'upper', diag = FALSE, weighted = TRUE) - + - + # visualize - + op <- par(no.readonly = TRUE) - + - + par(mar = c(0,0,0,0)) - + plot(g) - + - + plot(g, vertex.size = sqrt(igraph::degree(g) * 25), vertex.label.family = 'sans') - + - + # find communities - + cm <- igraph::cluster_walktrap(g) - + plot(cm, g, vertex.label.family = 'sans') - + - + par(op) - + } - Error in `igraph::graph_from_adjacency_matrix()`: - ! Cannot create a graph object because the adjacency matrix contains - NAs. - Backtrace: - ▆ - 1. └─igraph::graph_from_adjacency_matrix(table5.2, mode = "upper", diag = FALSE, weighted = TRUE) - 2. └─igraph:::ensure_no_na(adjmatrix, "adjacency matrix") - 3. └─cli::cli_abort(...) - 4. └─rlang::abort(...) - Execution halted - ``` - -# tilemaps - -
- -* Version: 0.2.0 -* GitHub: https://github.com/kaerosen/tilemaps -* Source code: https://github.com/cran/tilemaps -* Date/Publication: 2020-07-10 04:20:02 UTC -* Number of recursive dependencies: 69 - -Run `revdepcheck::cloud_details(, "tilemaps")` for more info - -
- -## Newly broken - -* checking examples ... ERROR - ``` - Running examples in ‘tilemaps-Ex.R’ failed - The error most likely occurred in: - - > ### Name: create_island - > ### Title: Create a Tile for an Island - > ### Aliases: create_island - > - > ### ** Examples - > - > library(sf) - Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.4.0; sf_use_s2() is TRUE - > northeast <- governors[c(6,7,17,18,19,27,28,30,36,37,43),] - > tile_map <- generate_map(northeast$geometry, square = FALSE) - Error: - ! The `neimode` argument of `bfs()` was deprecated in igraph 1.3.0 and - is now defunct. - ℹ Please use the `mode` argument instead. - Backtrace: - ▆ - 1. └─tilemaps::generate_map(northeast$geometry, square = FALSE) - 2. └─igraph::bfs(neighbor_graph, 1, neimode = "all", unreachable = FALSE) - 3. └─lifecycle::deprecate_stop("1.3.0", "bfs(neimode = )", "bfs(mode = )") - 4. └─lifecycle:::deprecate_stop0(msg) - 5. └─rlang::cnd_signal(...) - Execution halted - ``` - -* checking re-building of vignette outputs ... ERROR - ``` - Error(s) in re-building vignettes: - ... - --- re-building ‘tilemaps.Rmd’ using rmarkdown - - Quitting from tilemaps.Rmd:32-41 [unnamed-chunk-2] - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - NULL - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Error: processing vignette 'tilemaps.Rmd' failed with diagnostics: - ℹ In argument: `tile_map = generate_map(geometry, square = FALSE, - flat_topped = TRUE)`. - Caused by error: - ! The `neimode` argument of `bfs()` was deprecated in igraph 1.3.0 and - is now defunct. - ℹ Please use the `mode` argument instead. - --- failed re-building ‘tilemaps.Rmd’ - - SUMMARY: processing the following file failed: - ‘tilemaps.Rmd’ - - Error: Vignette re-building failed. - Execution halted - ``` - -## In both - -* checking dependencies in R code ... NOTE - ``` - Namespace in Imports field not imported from: ‘lwgeom’ - All declared Imports should be used. - ``` - # timeordered
-* Version: 1.0.1 +* Version: 1.0.2 * GitHub: NA * Source code: https://github.com/cran/timeordered -* Date/Publication: 2024-09-15 22:10:02 UTC +* Date/Publication: 2025-09-29 11:10:02 UTC * Number of recursive dependencies: 13 Run `revdepcheck::cloud_details(, "timeordered")` for more info @@ -2171,10 +1101,9 @@ Run `revdepcheck::cloud_details(, "timeordered")` for more info [1] 0.95 [1] 1 > b <- transformspreadbyindividual(sa) - > plot(ts(b),plot.type="single",col=rainbow(ncol(b)),xlab="Time",ylab="Fraction reached") - Error in xy.coords(x, NULL, log = log, setLab = FALSE) : - 'list' object cannot be coerced to type 'double' - Calls: plot -> plot.ts -> plotts -> xy.coords + > heatmap(b, Rowv=NA, Colv=NA, scale='none', xlab="Individual", ylab="Time") + Error in heatmap(b, Rowv = NA, Colv = NA, scale = "none", xlab = "Individual", : + 'x' must be a numeric matrix Execution halted ``` From e067d97090545f03ef8bace5c4bd0bd0be22fc71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 17 Oct 2025 10:39:12 +0200 Subject: [PATCH 064/154] test: Fix flaky test --- tests/testthat/_snaps/centrality.md | 71 +---------------------------- tests/testthat/test-centrality.R | 2 +- 2 files changed, 2 insertions(+), 71 deletions(-) diff --git a/tests/testthat/_snaps/centrality.md b/tests/testthat/_snaps/centrality.md index 3d3701120bb..febfd202987 100644 --- a/tests/testthat/_snaps/centrality.md +++ b/tests/testthat/_snaps/centrality.md @@ -33,80 +33,11 @@ # eigen_centrality() deprecated scale argument Code - eigen_centrality(g, scale = TRUE) + invisible(eigen_centrality(g, scale = TRUE)) Condition Warning: The `scale` argument of `eigen_centrality()` is deprecated as of igraph 2.1.1. i eigen_centrality() will always behave as if scale=TRUE were used. - Output - $vector - [1] 1 1 1 1 1 1 1 1 1 1 - - $value - [1] 2 - - $options - $options$bmat - [1] "I" - - $options$n - [1] 10 - - $options$which - [1] "LA" - - $options$nev - [1] 1 - - $options$tol - [1] 0 - - $options$ncv - [1] 0 - - $options$ldv - [1] 0 - - $options$ishift - [1] 1 - - $options$maxiter - [1] 3000 - - $options$nb - [1] 1 - - $options$mode - [1] 1 - - $options$start - [1] 1 - - $options$sigma - [1] 0 - - $options$sigmai - [1] 0 - - $options$info - [1] 0 - - $options$iter - [1] 1 - - $options$nconv - [1] 1 - - $options$numop - [1] 7 - - $options$numopb - [1] 0 - - $options$numreo - [1] 4 - - --- diff --git a/tests/testthat/test-centrality.R b/tests/testthat/test-centrality.R index 392acf64471..f78a23d8fd8 100644 --- a/tests/testthat/test-centrality.R +++ b/tests/testthat/test-centrality.R @@ -820,7 +820,7 @@ test_that("arpack works for non-symmetric matrices", { test_that("eigen_centrality() deprecated scale argument", { g <- make_ring(10, directed = FALSE) expect_snapshot({ - eigen_centrality(g, scale = TRUE) + invisible(eigen_centrality(g, scale = TRUE)) }) # For some reason, this produces different outputs on Windows and macOS expect_snapshot({ From fb995242e8d34e75f7f8686d5e7bfa31db48e8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Sun, 19 Oct 2025 04:45:40 +0200 Subject: [PATCH 065/154] chore: Use autogen-impl functions for 3 motifs functions (#2152) --- R/motifs.R | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/R/motifs.R b/R/motifs.R index 0612315f14a..c6f2910224f 100644 --- a/R/motifs.R +++ b/R/motifs.R @@ -151,22 +151,14 @@ dyad.census <- function(graph) { #' count_motifs(g, 3) #' sample_motifs(g, 3) motifs <- function(graph, size = 3, cut.prob = NULL) { - ensure_igraph(graph) - - if (!is.null(cut.prob)) { - cut.prob <- as.numeric(cut.prob) - } - if (!is.null(cut.prob) && length(cut.prob) != size) { cli::cli_abort("{arg cut.prob} must be the same length as {.arg size}") } - on.exit(.Call(R_igraph_finalizer)) - res <- .Call( - R_igraph_motifs_randesu, + res <- motifs_randesu_impl( graph, - as.numeric(size), - cut.prob + size = size, + cut.prob = cut.prob ) res[is.nan(res)] <- NA res @@ -200,20 +192,14 @@ motifs <- function(graph, size = 3, cut.prob = NULL) { count_motifs <- function(graph, size = 3, cut.prob = NULL) { ensure_igraph(graph) - if (!is.null(cut.prob)) { - cut.prob <- as.numeric(cut.prob) - } - if (!is.null(cut.prob) && length(cut.prob) != size) { cli::cli_abort("{arg cut.prob} must be the same length as {.arg size}") } - on.exit(.Call(R_igraph_finalizer)) - .Call( - R_igraph_motifs_randesu_no, + motifs_randesu_no_impl( graph, - as.numeric(size), - cut.prob + size = size, + cut.prob = cut.prob ) } @@ -258,10 +244,6 @@ sample_motifs <- function( ) { ensure_igraph(graph) - if (!is.null(cut.prob)) { - cut.prob <- as.numeric(cut.prob) - } - if (!is.null(cut.prob) && length(cut.prob) != size) { cli::cli_abort("{arg cut.prob} must be the same length as {.arg size}") } @@ -275,13 +257,11 @@ sample_motifs <- function( sample.size <- 0 } - on.exit(.Call(R_igraph_finalizer)) - .Call( - R_igraph_motifs_randesu_estimate, + motifs_randesu_estimate_impl( graph, - as.numeric(size), - cut.prob, - as.numeric(sample.size), + size = size, + cut.prob = cut.prob, + sample.size = sample.size, sample ) } From 09302cffe2128ae306bb9f265935384b6b333e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Thu, 4 Sep 2025 11:05:44 +0200 Subject: [PATCH 066/154] chore: use `centralization_degree_tmax_imp()` (#2101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Szabolcs Horvát --- R/centralization.R | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/R/centralization.R b/R/centralization.R index 0925dc67cc4..f5c6e906beb 100644 --- a/R/centralization.R +++ b/R/centralization.R @@ -403,18 +403,16 @@ centr_degree_tmax <- function( ensure_igraph(graph, optional = TRUE) nodes <- as.numeric(nodes) - mode <- switch( - igraph.match.arg(mode), - "out" = 1, - "in" = 2, - "all" = 3, - "total" = 3 - ) + loops <- as.logical(loops) - on.exit(.Call(R_igraph_finalizer)) # Function call - res <- .Call(R_igraph_centralization_degree_tmax, graph, nodes, mode, loops) + res <- centralization_degree_tmax_impl( + graph, + nodes = nodes, + mode = mode, + loops = loops + ) res } From 0b0a937b35105eab95fd57861fd0886403aa2188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 7 Sep 2025 18:45:02 +0200 Subject: [PATCH 067/154] fledge: CRAN pre-release v2.1.99.9900 (#2112) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: schochastics --- CITATION.cff | 57 ++++++++++++++++++++++++++++++++++++------ cran-comments.md | 2 +- src/rinterface_extra.c | 4 --- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index e478f62f85d..f6e2ebcf333 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -8,7 +8,7 @@ message: 'To cite package "igraph" in publications use:' type: software license: GPL-2.0-or-later title: 'igraph: Network Analysis and Visualization' -version: 2.1.3 +version: 2.1.99 identifiers: - type: doi value: 10.32614/CRAN.package.igraph @@ -45,14 +45,26 @@ authors: given-names: Kirill email: kirill@cynkra.com orcid: https://orcid.org/0000-0002-1416-3412 +- family-names: Schoch + given-names: David + email: david.schoch@cynkra.com + orcid: https://orcid.org/0000-0003-2952-4812 +- family-names: Salmon + given-names: Maëlle + email: maelle@cynkra.com + orcid: https://orcid.org/0000-0002-2815-0399 preferred-citation: type: article title: The igraph software package for complex network research authors: - - family-names: Csardi - given-names: Gabor + - family-names: Csárdi + given-names: Gábor + email: csardi.gabor@gmail.com + orcid: https://orcid.org/0000-0001-7098-9676 - family-names: Nepusz - given-names: Tamas + given-names: Tamás + email: ntamas@gmail.com + orcid: https://orcid.org/0000-0002-1451-338X journal: InterJournal volume: Complex Systems year: '2006' @@ -75,6 +87,32 @@ keywords: - network-graph - r references: +- type: article + title: igraph enables fast and robust network analysis across programming languages + authors: + - family-names: Antonov + given-names: Michael + - family-names: Csárdi + given-names: Gábor + - family-names: Horvát + given-names: Szabolcs + - family-names: Müller + given-names: Kirill + - family-names: Nepusz + given-names: Tamás + - family-names: Noom + given-names: Daniel + - family-names: Salmon + given-names: Maëlle + - family-names: Traag + given-names: Vincent + - family-names: Welles + given-names: Brooke Foucault + - family-names: Zanini + given-names: Fabio + journal: arXiv preprint arXiv:2311.10260 + year: '2023' + doi: 10.48550/arXiv.2311.10260 - type: manual title: 'igraph: Network Analysis and Visualization in R' authors: @@ -92,8 +130,12 @@ references: given-names: Daniel - family-names: Müller given-names: Kirill + - family-names: Schoch + given-names: David + - family-names: Salmon + given-names: Maëlle year: '2025' - notes: R package version 2.1.3 + notes: R package version 2.1.99 doi: 10.5281/zenodo.7682609 url: https://CRAN.R-project.org/package=igraph - type: software @@ -126,7 +168,7 @@ references: authors: - family-names: Csárdi given-names: Gábor - email: csardi.gabor@gmail.com + email: gabor@posit.co year: '2025' doi: 10.32614/CRAN.package.cli - type: software @@ -184,7 +226,7 @@ references: title: Matrix abstract: 'Matrix: Sparse and Dense Matrix Classes and Methods' notes: Imports - url: https://R-forge.R-project.org/tracker/?atid=294&group_id=61 + url: https://Matrix.R-forge.R-project.org repository: https://CRAN.R-project.org/package=Matrix authors: - family-names: Bates @@ -226,6 +268,7 @@ references: email: hadley@posit.co year: '2025' doi: 10.32614/CRAN.package.rlang + version: '>= 1.1.0' - type: software title: stats abstract: 'R: A Language and Environment for Statistical Computing' diff --git a/cran-comments.md b/cran-comments.md index 52f31944dd6..6ea8a5424c5 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,4 +1,4 @@ -igraph 2.1.3 +igraph 2.1.99.9900 ## Cran Repository Policy diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 59b83ff0714..9bc514e5759 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -8587,7 +8587,6 @@ SEXP R_igraph_add_env(SEXP graph) { SET_CLASS(result, Rf_duplicate(GET_CLASS(graph))); } -#if defined(R_VERSION) && R_VERSION >= R_Version(4, 1, 0) // Get the base namespace SEXP base_ns = PROTECT(R_FindNamespace(Rf_mkString("base"))); px++; // Get the emptyenv function @@ -8596,9 +8595,6 @@ SEXP R_igraph_add_env(SEXP graph) { SEXP empty_env = PROTECT(Rf_eval(Rf_lang1(empty_env_fun), R_GlobalEnv)); px++; // Evaluate the call SEXP env = PROTECT(R_NewEnv(empty_env, 0, 0)); px++; -#else - SEXP env = Rf_allocSExp(ENVSXP); -#endif SET_VECTOR_ELT(result, igraph_t_idx_env, env); From efa52473146b94816a38b8785d180ad07e11db13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 16:22:17 +0200 Subject: [PATCH 068/154] chore: autogenerate `igraph_neighbors()` (#2151) --- R/aaa-auto.R | 20 +++++++++++ R/interface.R | 14 ++------ patch/0007-deps.patch | 24 +++++++++++++ src/rinterface.c | 36 ++++++++++++++++++++ src/rinterface_extra.c | 24 ------------- src/vendor/cigraph/interfaces/functions.yaml | 1 + tools/stimulus/functions-R.yaml | 3 -- 7 files changed, 84 insertions(+), 38 deletions(-) create mode 100644 patch/0007-deps.patch diff --git a/R/aaa-auto.R b/R/aaa-auto.R index 26e49b83a33..ced3036737f 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -59,6 +59,26 @@ vcount_impl <- function(graph) { res } +neighbors_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once"), multiple=TRUE) { + # Argument checks + ensure_igraph(graph) + vid <- as_igraph_vs(graph, vid) + if (length(vid) == 0) { + stop("No vertex was specified") + } + mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + multiple <- as.logical(multiple) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_neighbors, graph, vid-1, mode, loops, multiple) + if (igraph_opt("return.vs.es")) { + res <- create_vs(graph, res) + } + res +} + degree_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once")) { # Argument checks ensure_igraph(graph) diff --git a/R/interface.R b/R/interface.R index 404b2ea044d..5ae535c82c5 100644 --- a/R/interface.R +++ b/R/interface.R @@ -349,22 +349,14 @@ ecount <- gsize #' intersection(n1, n34) neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) { ensure_igraph(graph) - if (is.character(mode)) { - mode <- igraph.match.arg(mode) - mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3) - } + mode <- igraph.match.arg(mode) + v <- as_igraph_vs(graph, v) if (length(v) == 0) { stop("No vertex was specified") } - on.exit(.Call(R_igraph_finalizer)) - res <- .Call(R_igraph_neighbors, graph, v - 1, as.numeric(mode)) + 1L - - if (igraph_opt("return.vs.es")) { - res <- create_vs(graph, res) - } - res + neighbors_impl(graph, vid = v, mode = mode) } #' Incident edges of a vertex in a graph diff --git a/patch/0007-deps.patch b/patch/0007-deps.patch new file mode 100644 index 00000000000..e94f643a207 --- /dev/null +++ b/patch/0007-deps.patch @@ -0,0 +1,24 @@ +From eb04b1de45d13baf0d7b78d09fe568a69745ecc3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Kirill=20M=C3=BCller?= +Date: Sun, 19 Oct 2025 16:22:43 +0200 +Subject: [PATCH] deps + +--- + src/vendor/cigraph/interfaces/functions.yaml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml +index 5ee970b5d8..560bf6157d 100644 +--- a/src/vendor/cigraph/interfaces/functions.yaml ++++ b/src/vendor/cigraph/interfaces/functions.yaml +@@ -63,6 +63,7 @@ igraph_neighbors: + PARAMS: |- + GRAPH graph, OUT VERTEX_INDICES neis, VERTEX vid, NEIMODE mode=ALL, + LOOPS loops=TWICE, BOOLEAN multiple=True ++ DEPS: neis ON graph, vid ON graph + FLAGS: no_rng + + igraph_is_directed: +-- +2.50.1 + diff --git a/src/rinterface.c b/src/rinterface.c index 7a24a72012b..36e56be32b8 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -188,6 +188,42 @@ SEXP R_igraph_vcount(SEXP graph) { return(r_result); } +/*-------------------------------------------/ +/ igraph_neighbors / +/-------------------------------------------*/ +SEXP R_igraph_neighbors(SEXP graph, SEXP vid, SEXP mode, SEXP loops, SEXP multiple) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_int_t c_neis; + igraph_integer_t c_vid; + igraph_neimode_t c_mode; + igraph_loops_t c_loops; + igraph_bool_t c_multiple; + SEXP neis; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + IGRAPH_R_CHECK(igraph_vector_int_init(&c_neis, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_neis); + c_vid = (igraph_integer_t) REAL(vid)[0]; + c_mode = (igraph_neimode_t) Rf_asInteger(mode); + c_loops = (igraph_loops_t) Rf_asInteger(loops); + IGRAPH_R_CHECK_BOOL(multiple); + c_multiple = LOGICAL(multiple)[0]; + /* Call igraph */ + IGRAPH_R_CHECK(igraph_neighbors(&c_graph, &c_neis, c_vid, c_mode, c_loops, c_multiple)); + + /* Convert output */ + PROTECT(neis=R_igraph_vector_int_to_SEXPp1(&c_neis)); + igraph_vector_int_destroy(&c_neis); + IGRAPH_FINALLY_CLEAN(1); + r_result = neis; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_degree / /-------------------------------------------*/ diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 9bc514e5759..1ab15370db6 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -3885,30 +3885,6 @@ SEXP R_igraph_ecount(SEXP graph) { return result; } -SEXP R_igraph_neighbors(SEXP graph, SEXP pvid, SEXP pmode) { - - igraph_t g; - igraph_vector_int_t neis; - SEXP result; - igraph_real_t vid; - igraph_neimode_t mode; - // FIXME: Expose - igraph_loops_t loops = IGRAPH_NO_LOOPS; - igraph_bool_t multiple = false; - - igraph_vector_int_init(&neis, 0); - vid=REAL(pvid)[0]; - mode = (igraph_neimode_t) Rf_asInteger(pmode); - R_SEXP_to_igraph(graph, &g); - IGRAPH_R_CHECK(igraph_neighbors(&g, &neis, (igraph_integer_t) vid, mode, loops, multiple)); - - PROTECT(result=R_igraph_vector_int_to_SEXP(&neis)); - igraph_vector_int_destroy(&neis); - - UNPROTECT(1); - return result; -} - SEXP R_igraph_delete_edges(SEXP graph, SEXP edges) { igraph_es_t es; diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml index 5ee970b5d8a..560bf6157d4 100644 --- a/src/vendor/cigraph/interfaces/functions.yaml +++ b/src/vendor/cigraph/interfaces/functions.yaml @@ -63,6 +63,7 @@ igraph_neighbors: PARAMS: |- GRAPH graph, OUT VERTEX_INDICES neis, VERTEX vid, NEIMODE mode=ALL, LOOPS loops=TWICE, BOOLEAN multiple=True + DEPS: neis ON graph, vid ON graph FLAGS: no_rng igraph_is_directed: diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 0e846eee81a..245beac246c 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -28,9 +28,6 @@ igraph_vcount: igraph_ecount: IGNORE: RR, RC -igraph_neighbors: - IGNORE: RR, RC - igraph_is_directed: IGNORE: RR, RC From fa5a3d413a1892af6bed3da125acbce3eedf3d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 16:18:26 +0200 Subject: [PATCH 069/154] Remove optional output --- src/rinterface.c | 13 +++---------- tools/stimulus/functions-R.yaml | 4 ++++ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/rinterface.c b/src/rinterface.c index 36e56be32b8..7f1ca6c4096 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -12982,7 +12982,7 @@ SEXP R_igraph_is_bipartite_coloring(SEXP graph, SEXP types) { igraph_t c_graph; igraph_vector_bool_t c_types; igraph_bool_t c_res; - igraph_neimode_t c_mode; + SEXP res; SEXP mode; @@ -12992,20 +12992,13 @@ SEXP R_igraph_is_bipartite_coloring(SEXP graph, SEXP types) { R_SEXP_to_vector_bool(types, &c_types); /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_is_bipartite_coloring(&c_graph, &c_types, &c_res, NULL)); + IGRAPH_R_CHECK(igraph_is_bipartite_coloring(&c_graph, &c_types, &c_res, 0)); PutRNGstate(); /* Convert output */ - PROTECT(r_result=NEW_LIST(2)); - PROTECT(r_names=NEW_CHARACTER(2)); PROTECT(res=NEW_LOGICAL(1)); LOGICAL(res)[0]=c_res; - SET_VECTOR_ELT(r_result, 0, res); - SET_VECTOR_ELT(r_result, 1, mode); - SET_STRING_ELT(r_names, 0, Rf_mkChar("res")); - SET_STRING_ELT(r_names, 1, Rf_mkChar("mode")); - SET_NAMES(r_result, r_names); - UNPROTECT(3); + r_result = res; UNPROTECT(1); return(r_result); diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 245beac246c..cc035d42299 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -997,6 +997,10 @@ igraph_from_prufer: igraph_vertex_coloring_greedy: +igraph_is_bipartite_coloring: + PARAMS: GRAPH graph, BIPARTITE_TYPES types, OUT BOOLEAN res, OPTIONAL OUT NULL mode + DEPS: types ON graph + ####################################### # Other, (yet) undocumented functions ####################################### From e7911975d362c1d792764d79fc61949c89bae5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 16:42:16 +0200 Subject: [PATCH 070/154] Remove tests where function is gone --- tests/testthat/test-aaa-auto.R | 342 --------------------------------- 1 file changed, 342 deletions(-) diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R index b51a615c7b2..d7351bdc455 100644 --- a/tests/testthat/test-aaa-auto.R +++ b/tests/testthat/test-aaa-auto.R @@ -43,21 +43,6 @@ test_that("copy_impl errors", { expect_snapshot_igraph_error(copy_impl(NULL)) }) -# 4. delete_vertices_idx_impl - -test_that("delete_vertices_idx_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- empty_impl(3) - expect_snapshot(delete_vertices_idx_impl(g, 1)) -}) - -test_that("delete_vertices_idx_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(delete_vertices_idx_impl(NULL, 1)) -}) - # 5. vcount_impl test_that("vcount_impl basic", { @@ -338,18 +323,6 @@ test_that("kautz_impl errors", { expect_snapshot_igraph_error(kautz_impl(-1, 3)) }) -# 23. lcf_vector_impl -test_that("lcf_vector_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(lcf_vector_impl(10, c(3, -3, 4), 2)) -}) -test_that("lcf_vector_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(lcf_vector_impl(-1, c(3, -3, 4), 2)) -}) - # 24. mycielski_graph_impl test_that("mycielski_graph_impl basic", { withr::local_seed(20250909) @@ -843,55 +816,6 @@ test_that("dot_product_game_impl errors", { expect_snapshot_igraph_error(dot_product_game_impl(NULL)) }) -# 52. sample_sphere_surface_impl - -test_that("sample_sphere_surface_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(sample_sphere_surface_impl(3, 5)) - expect_snapshot(sample_sphere_surface_impl( - 3, - 5, - radius = 2, - positive = FALSE - )) -}) - -test_that("sample_sphere_surface_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(sample_sphere_surface_impl(-1, 5)) -}) - -# 53. sample_sphere_volume_impl - -test_that("sample_sphere_volume_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(sample_sphere_volume_impl(3, 5)) - expect_snapshot(sample_sphere_volume_impl(3, 5, radius = 2, positive = FALSE)) -}) - -test_that("sample_sphere_volume_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(sample_sphere_volume_impl(-1, 5)) -}) - -# 54. sample_dirichlet_impl - -test_that("sample_dirichlet_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(sample_dirichlet_impl(5, c(1, 1, 1))) -}) - -test_that("sample_dirichlet_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(sample_dirichlet_impl(-1, c(1, 1, 1))) -}) - # 55. are_adjacent_impl test_that("are_adjacent_impl basic", { @@ -1873,27 +1797,6 @@ test_that("centralization_degree_impl errors", { expect_snapshot_igraph_error(centralization_degree_impl(NULL)) }) -# 136. centralization_degree_tmax_impl - -test_that("centralization_degree_tmax_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(centralization_degree_tmax_impl(nodes = 3, loops = TRUE)) - expect_snapshot(centralization_degree_tmax_impl( - nodes = 3, - mode = "in", - loops = FALSE - )) -}) - -test_that("centralization_degree_tmax_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - centralization_degree_tmax_impl(nodes = -1, loops = TRUE) - ) -}) - # 137. centralization_betweenness_impl test_that("centralization_betweenness_impl basic", { @@ -2155,54 +2058,6 @@ test_that("contract_vertices_impl errors", { expect_snapshot_igraph_error(contract_vertices_impl(NULL, c(1, 1, 2))) }) -# 150. eccentricity_dijkstra_impl - -test_that("eccentricity_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(eccentricity_dijkstra_impl(g)) - expect_snapshot(eccentricity_dijkstra_impl(g, mode = "in")) -}) - -test_that("eccentricity_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(eccentricity_dijkstra_impl(NULL)) -}) - -# 151. graph_center_dijkstra_impl - -test_that("graph_center_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(graph_center_dijkstra_impl(g)) - expect_snapshot(graph_center_dijkstra_impl(g, mode = "in")) -}) - -test_that("graph_center_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(graph_center_dijkstra_impl(NULL)) -}) - -# 152. radius_dijkstra_impl - -test_that("radius_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(radius_dijkstra_impl(g)) - expect_snapshot(radius_dijkstra_impl(g, mode = "in")) -}) - -test_that("radius_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(radius_dijkstra_impl(NULL)) -}) - # 153. pseudo_diameter_impl test_that("pseudo_diameter_impl basic", { @@ -2224,29 +2079,6 @@ test_that("pseudo_diameter_impl errors", { expect_snapshot_igraph_error(pseudo_diameter_impl(NULL, 1)) }) -# 154. pseudo_diameter_dijkstra_impl - -test_that("pseudo_diameter_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(pseudo_diameter_dijkstra_impl(g, start.vid = 1)) - expect_snapshot(pseudo_diameter_dijkstra_impl( - g, - start.vid = 1, - directed = FALSE, - unconnected = FALSE - )) -}) - -test_that("pseudo_diameter_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - pseudo_diameter_dijkstra_impl(NULL, start.vid = 1) - ) -}) - # 155. diversity_impl test_that("diversity_impl basic", { @@ -2331,21 +2163,6 @@ test_that("average_local_efficiency_impl errors", { expect_snapshot_igraph_error(average_local_efficiency_impl(NULL)) }) -# 160. transitive_closure_dag_impl - -test_that("transitive_closure_dag_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3, directed = TRUE) - expect_snapshot(transitive_closure_dag_impl(g)) -}) - -test_that("transitive_closure_dag_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(transitive_closure_dag_impl(NULL)) -}) - # 161. transitive_closure_impl test_that("transitive_closure_impl basic", { @@ -5359,138 +5176,6 @@ test_that("is_edge_coloring_impl errors", { expect_snapshot_igraph_error(is_edge_coloring_impl(NULL, types = c(1, 2))) }) -# 327. deterministic_optimal_imitation_impl - -test_that("deterministic_optimal_imitation_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(deterministic_optimal_imitation_impl( - g, - 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - )) - expect_snapshot(deterministic_optimal_imitation_impl( - g, - 1, - optimality = "minimum", - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("deterministic_optimal_imitation_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - deterministic_optimal_imitation_impl( - NULL, - 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - ) - ) -}) - -# 328. moran_process_impl - -test_that("moran_process_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(moran_process_impl( - g, - weights = c(1, 1), - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("moran_process_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - moran_process_impl(NULL, quantities = c(1, 2, 3), strategies = c(1, 2, 3)) - ) -}) - -# 329. roulette_wheel_imitation_impl - -test_that("roulette_wheel_imitation_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(roulette_wheel_imitation_impl( - g, - 1, - TRUE, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - )) - expect_snapshot(roulette_wheel_imitation_impl( - g, - 1, - FALSE, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("roulette_wheel_imitation_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - roulette_wheel_imitation_impl( - NULL, - 1, - TRUE, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - ) - ) -}) - -# 330. stochastic_imitation_impl - -test_that("stochastic_imitation_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(stochastic_imitation_impl( - g, - 1, - algo = 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - )) - expect_snapshot(stochastic_imitation_impl( - g, - 1, - algo = 2, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("stochastic_imitation_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - stochastic_imitation_impl( - NULL, - 1, - algo = 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - ) - ) -}) - # 331. invalidate_cache_impl test_that("invalidate_cache_impl basic", { @@ -5506,33 +5191,6 @@ test_that("invalidate_cache_impl errors", { expect_snapshot_igraph_error(invalidate_cache_impl(NULL)) }) -# 332. vertex_path_from_edge_path_impl - -test_that("vertex_path_from_edge_path_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(vertex_path_from_edge_path_impl( - g, - start = 1, - edge.path = c(1, 2) - )) - expect_snapshot(vertex_path_from_edge_path_impl( - g, - start = 1, - edge.path = c(1), - mode = "in" - )) -}) - -test_that("vertex_path_from_edge_path_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - vertex_path_from_edge_path_impl(NULL, start = 1, edge.path = c(1, 2)) - ) -}) - # 333. version_impl test_that("version_impl basic", { From 7043ebe4a6fb13796e4cad52d8d610bb095e54e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 16:42:16 +0200 Subject: [PATCH 071/154] Remove snapshots for tests where function is gone --- tests/testthat/_snaps/aaa-auto.md | 379 ------------------------------ 1 file changed, 379 deletions(-) diff --git a/tests/testthat/_snaps/aaa-auto.md b/tests/testthat/_snaps/aaa-auto.md index ed0a5ad33e8..5619db795f5 100644 --- a/tests/testthat/_snaps/aaa-auto.md +++ b/tests/testthat/_snaps/aaa-auto.md @@ -55,30 +55,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# delete_vertices_idx_impl basic - - Code - delete_vertices_idx_impl(g, 1) - Output - $graph - IGRAPH D--- 2 0 -- - + edges: - - $idx - [1] 0 1 2 - - $invidx - [1] 1 2 - - -# delete_vertices_idx_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # vcount_impl basic Code @@ -500,25 +476,6 @@ Error in `kautz_impl()`: ! At vendor/cigraph/src/constructors/kautz.c:xx : `m' and `n' should be non-negative in a Kautz graph, Invalid value -# lcf_vector_impl basic - - Code - lcf_vector_impl(10, c(3, -3, 4), 2) - Output - IGRAPH U--- 10 16 -- LCF graph - + attr: name (g/c) - + edges: - [1] 1-- 2 1-- 4 1--10 2-- 3 2-- 5 2-- 9 3-- 4 3-- 7 4-- 5 4-- 7 5-- 6 6-- 7 - [13] 6--10 7-- 8 8-- 9 9--10 - -# lcf_vector_impl errors - - Code - x - Condition - Error in `lcf_vector_impl()`: - ! At vendor/cigraph/src/graph/type_indexededgelist.c:xx : Number of vertices must not be negative. Invalid value - # mycielski_graph_impl basic Code @@ -1243,80 +1200,6 @@ Error in `dot_product_game_impl()`: ! REAL() can only be applied to a 'numeric', not a 'NULL' -# sample_sphere_surface_impl basic - - Code - sample_sphere_surface_impl(3, 5) - Output - [,1] [,2] [,3] [,4] [,5] - [1,] 0.87877523 0.8206548 0.1430028 0.6349227 0.99933629 - [2,] 0.05165973 0.5261159 0.1145481 0.2979741 0.02649327 - [3,] 0.47443162 0.2229974 0.9830712 0.7128005 0.02500179 - ---- - - Code - sample_sphere_surface_impl(3, 5, radius = 2, positive = FALSE) - Output - [,1] [,2] [,3] [,4] [,5] - [1,] -0.4904253 -1.4825368 -0.5141332 1.95644246 0.369407 - [2,] -1.6787252 1.1329528 -0.7872709 -0.41498660 1.953509 - [3,] -0.9702395 0.7200713 1.7651832 -0.01090904 0.217584 - -# sample_sphere_surface_impl errors - - Code - x - Condition - Error in `sample_sphere_surface_impl()`: - ! At vendor/cigraph/src/games/dotproduct.c:xx : Sphere must be at least two dimensional to sample from surface. Invalid value - -# sample_sphere_volume_impl basic - - Code - sample_sphere_volume_impl(3, 5) - Output - [,1] [,2] [,3] [,4] [,5] - [1,] 0.67165090 0.6105364 0.09806950 0.4132698 0.73325518 - [2,] 0.03948371 0.3914105 0.07855561 0.1939507 0.01943923 - [3,] 0.36260970 0.1659017 0.67417787 0.4639603 0.01834487 - ---- - - Code - sample_sphere_volume_impl(3, 5, radius = 2, positive = FALSE) - Output - [,1] [,2] [,3] [,4] [,5] - [1,] 1.903629152 -1.3795904 -1.2061886 0.9035986 -1.1692436 - [2,] -0.159619927 0.2402815 -0.1258477 0.1842403 -1.4940836 - [3,] 0.003829883 1.2440192 0.6204597 1.5776103 0.4096058 - -# sample_sphere_volume_impl errors - - Code - x - Condition - Error in `sample_sphere_volume_impl()`: - ! At vendor/cigraph/src/games/dotproduct.c:xx : Sphere must be at least two dimensional to sample from surface. Invalid value - -# sample_dirichlet_impl basic - - Code - sample_dirichlet_impl(5, c(1, 1, 1)) - Output - [,1] [,2] [,3] [,4] [,5] - [1,] 0.6298008 0.4168413 0.29594281 0.2432340 0.1516815 - [2,] 0.1093984 0.3461600 0.08924333 0.4251328 0.3561426 - [3,] 0.2608008 0.2369988 0.61481386 0.3316331 0.4921759 - -# sample_dirichlet_impl errors - - Code - x - Condition - Error in `sample_dirichlet_impl()`: - ! At vendor/cigraph/src/games/dotproduct.c:xx : Number of samples should be non-negative, got -1. Invalid value - # are_adjacent_impl basic Code @@ -3031,28 +2914,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# centralization_degree_tmax_impl basic - - Code - centralization_degree_tmax_impl(nodes = 3, loops = TRUE) - Output - [1] 6 - ---- - - Code - centralization_degree_tmax_impl(nodes = 3, mode = "in", loops = FALSE) - Output - [1] 4 - -# centralization_degree_tmax_impl errors - - Code - x - Condition - Error in `centralization_degree_tmax_impl()`: - ! At vendor/cigraph/src/centrality/centralization.c:xx : Number of vertices must not be negative. Invalid value - # centralization_betweenness_impl basic Code @@ -3529,74 +3390,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# eccentricity_dijkstra_impl basic - - Code - eccentricity_dijkstra_impl(g) - Output - [1] 2 1 2 - ---- - - Code - eccentricity_dijkstra_impl(g, mode = "in") - Output - [1] 2 1 2 - -# eccentricity_dijkstra_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# graph_center_dijkstra_impl basic - - Code - graph_center_dijkstra_impl(g) - Output - + 1/3 vertex: - [1] 2 - ---- - - Code - graph_center_dijkstra_impl(g, mode = "in") - Output - + 1/3 vertex: - [1] 2 - -# graph_center_dijkstra_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# radius_dijkstra_impl basic - - Code - radius_dijkstra_impl(g) - Output - [1] 1 - ---- - - Code - radius_dijkstra_impl(g, mode = "in") - Output - [1] 1 - -# radius_dijkstra_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # pseudo_diameter_impl basic Code @@ -3635,44 +3428,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# pseudo_diameter_dijkstra_impl basic - - Code - pseudo_diameter_dijkstra_impl(g, start.vid = 1) - Output - $diameter - [1] 2 - - $from - [1] 0 - - $to - [1] 2 - - ---- - - Code - pseudo_diameter_dijkstra_impl(g, start.vid = 1, directed = FALSE, unconnected = FALSE) - Output - $diameter - [1] 2 - - $from - [1] 0 - - $to - [1] 2 - - -# pseudo_diameter_dijkstra_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # diversity_impl basic Code @@ -3790,23 +3545,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# transitive_closure_dag_impl basic - - Code - transitive_closure_dag_impl(g) - Output - IGRAPH D--- 3 3 -- - + edges: - [1] 1->3 1->2 2->3 - -# transitive_closure_dag_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # transitive_closure_impl basic Code @@ -9941,99 +9679,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# deterministic_optimal_imitation_impl basic - - Code - deterministic_optimal_imitation_impl(g, 1, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3)) - Output - [1] 2 2 3 - ---- - - Code - deterministic_optimal_imitation_impl(g, 1, optimality = "minimum", quantities = c( - 1, 2, 3), strategies = c(1, 2, 3), mode = "in") - Output - [1] 1 2 3 - -# deterministic_optimal_imitation_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# moran_process_impl basic - - Code - moran_process_impl(g, weights = c(1, 1), quantities = c(1, 2, 3), strategies = c( - 1, 2, 3), mode = "in") - Output - $quantities - [1] 1 3 3 - - $strategies - [1] 1 3 3 - - -# moran_process_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# roulette_wheel_imitation_impl basic - - Code - roulette_wheel_imitation_impl(g, 1, TRUE, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3)) - Output - [1] 1 2 3 - ---- - - Code - roulette_wheel_imitation_impl(g, 1, FALSE, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3), mode = "in") - Output - [1] 3 2 3 - -# roulette_wheel_imitation_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# stochastic_imitation_impl basic - - Code - stochastic_imitation_impl(g, 1, algo = 1, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3)) - Output - [1] 1 2 3 - ---- - - Code - stochastic_imitation_impl(g, 1, algo = 2, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3), mode = "in") - Output - [1] 1 2 3 - -# stochastic_imitation_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # invalidate_cache_impl basic Code @@ -10051,30 +9696,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# vertex_path_from_edge_path_impl basic - - Code - vertex_path_from_edge_path_impl(g, start = 1, edge.path = c(1, 2)) - Output - + 3/3 vertices: - [1] 1 2 3 - ---- - - Code - vertex_path_from_edge_path_impl(g, start = 1, edge.path = c(1), mode = "in") - Output - + 2/3 vertices: - [1] 1 2 - -# vertex_path_from_edge_path_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # version_impl basic Code From c625e025b8af983036a0fa7eaf6c7858d667a8d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 19:42:57 +0200 Subject: [PATCH 072/154] Add impl --- R/aaa-auto.R | 14 ++++++++++++++ tools/stimulus/functions-R.yaml | 5 ----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index ced3036737f..c87505879b0 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -2070,6 +2070,20 @@ centralization_degree_impl <- function(graph, mode=c("all", "out", "in", "total" res } +centralization_degree_tmax_impl <- function(graph=NULL, nodes=0, mode=c("all", "out", "in", "total"), loops) { + # Argument checks + if (!is.null(graph)) ensure_igraph(graph) + nodes <- as.numeric(nodes) + mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_centralization_degree_tmax, graph, nodes, mode, loops) + + res +} + centralization_betweenness_impl <- function(graph, directed=TRUE, normalized=TRUE) { # Argument checks ensure_igraph(graph) diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index cc035d42299..d8ffec62c50 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -408,11 +408,6 @@ igraph_centralization: igraph_centralization_degree: -igraph_centralization_degree_tmax: - IGNORE: RR - # temporarily coded manually because we need to handle a deprecation - # between igraph 1.3.0 and 1.4.0 - igraph_centralization_betweenness: igraph_centralization_betweenness_tmax: From 5d83878cd94effed77e372cac392147d7bd561c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 19:44:26 +0200 Subject: [PATCH 073/154] Fix C++ signature --- src/cpp11.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp11.cpp b/src/cpp11.cpp index cfa33f7d5f7..f51d3eeafb0 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -368,7 +368,7 @@ extern SEXP R_igraph_nearest_neighbor_graph(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_neighborhood(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_neighborhood_graphs(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_neighborhood_size(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_neighbors(SEXP, SEXP, SEXP); +extern SEXP R_igraph_neighbors(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_no_components(SEXP, SEXP); extern SEXP R_igraph_path_graph(SEXP, SEXP, SEXP); extern SEXP R_igraph_path_length_hist(SEXP, SEXP); @@ -841,7 +841,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_neighborhood", (DL_FUNC) &R_igraph_neighborhood, 5}, {"R_igraph_neighborhood_graphs", (DL_FUNC) &R_igraph_neighborhood_graphs, 5}, {"R_igraph_neighborhood_size", (DL_FUNC) &R_igraph_neighborhood_size, 5}, - {"R_igraph_neighbors", (DL_FUNC) &R_igraph_neighbors, 3}, + {"R_igraph_neighbors", (DL_FUNC) &R_igraph_neighbors, 5}, {"R_igraph_no_components", (DL_FUNC) &R_igraph_no_components, 2}, {"R_igraph_path_graph", (DL_FUNC) &R_igraph_path_graph, 3}, {"R_igraph_path_length_hist", (DL_FUNC) &R_igraph_path_length_hist, 2}, From b62d95dae22830537eff2a69eed8e1c6dacb8145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 20:00:31 +0200 Subject: [PATCH 074/154] Tweak tests --- tests/testthat/test-aaa-auto.R | 79 ++++++++++++++-------------------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R index d7351bdc455..a6f6732b83a 100644 --- a/tests/testthat/test-aaa-auto.R +++ b/tests/testthat/test-aaa-auto.R @@ -874,13 +874,13 @@ test_that("get_shortest_path_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(get_shortest_path_impl(g, 1, 3)) + expect_snapshot(get_shortest_path_impl(g, from = 1, to = 3)) }) test_that("get_shortest_path_impl errors", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(get_shortest_path_impl(NULL, 1, 3)) + expect_snapshot_igraph_error(get_shortest_path_impl(NULL, from = 1, to = 3)) }) # 59. get_shortest_path_bellman_ford_impl @@ -919,13 +919,17 @@ test_that("get_all_shortest_paths_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(get_all_shortest_paths_impl(g, 1, 3)) + expect_snapshot(get_all_shortest_paths_impl(g, from = 1, to = 3)) }) test_that("get_all_shortest_paths_impl errors", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(get_all_shortest_paths_impl(NULL, 1, 3)) + expect_snapshot_igraph_error(get_all_shortest_paths_impl( + NULL, + from = 1, + to = 3 + )) }) # 62. get_all_shortest_paths_dijkstra_impl @@ -1355,7 +1359,7 @@ test_that("maxdegree_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(maxdegree_impl(g)) - expect_snapshot(maxdegree_impl(g, mode = "in", loops = FALSE)) + expect_snapshot(maxdegree_impl(g, mode = "in", loops = "twice")) }) test_that("maxdegree_impl errors", { @@ -1584,11 +1588,7 @@ test_that("eigenvector_centrality_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(eigenvector_centrality_impl(g)) - expect_snapshot(eigenvector_centrality_impl( - g, - directed = TRUE, - scale = FALSE - )) + expect_snapshot(eigenvector_centrality_impl(g, mode = "out")) }) test_that("eigenvector_centrality_impl errors", { @@ -1603,8 +1603,7 @@ test_that("hub_and_authority_scores_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- make_full_graph(5) - expect_snapshot(hub_and_authority_scores_impl(g)) - expect_snapshot(hub_and_authority_scores_impl(g, scale = FALSE)) + expect_snapshot(suppressWarnings(hub_and_authority_scores_impl(g))) }) test_that("hub_and_authority_scores_impl errors", { @@ -1748,7 +1747,7 @@ test_that("strength_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(strength_impl(g)) - expect_snapshot(strength_impl(g, mode = "in", loops = FALSE)) + expect_snapshot(strength_impl(g, mode = "in", loops = "twice")) }) test_that("strength_impl errors", { @@ -1786,7 +1785,7 @@ test_that("centralization_degree_impl basic", { expect_snapshot(centralization_degree_impl( g, mode = "in", - loops = FALSE, + loops = "twice", normalized = FALSE )) }) @@ -1884,7 +1883,7 @@ test_that("centralization_eigenvector_centrality_impl basic", { expect_snapshot(centralization_eigenvector_centrality_impl(g)) expect_snapshot(centralization_eigenvector_centrality_impl( g, - directed = TRUE, + mode = "out", normalized = FALSE )) }) @@ -1905,7 +1904,7 @@ test_that("centralization_eigenvector_centrality_tmax_impl basic", { expect_snapshot(centralization_eigenvector_centrality_tmax_impl(nodes = 3)) expect_snapshot(centralization_eigenvector_centrality_tmax_impl( nodes = 3, - directed = TRUE + mode = "out" )) }) @@ -2064,10 +2063,10 @@ test_that("pseudo_diameter_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(pseudo_diameter_impl(g, 1)) + expect_snapshot(pseudo_diameter_impl(g, start.vid = 1)) expect_snapshot(pseudo_diameter_impl( g, - 1, + start.vid = 1, directed = FALSE, unconnected = FALSE )) @@ -3051,7 +3050,7 @@ test_that("similarity_dice_impl basic", { expect_snapshot(similarity_dice_impl(g)) expect_snapshot(similarity_dice_impl( g, - vids = 1:2, + vit.from = 1:2, mode = "in", loops = TRUE )) @@ -3139,7 +3138,7 @@ test_that("similarity_jaccard_impl basic", { expect_snapshot(similarity_jaccard_impl(g)) expect_snapshot(similarity_jaccard_impl( g, - vids = 1:2, + vit.from = 1:2, mode = "in", loops = TRUE )) @@ -3283,13 +3282,17 @@ test_that("community_label_propagation_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(community_label_propagation_impl(g)) + expect_snapshot(community_label_propagation_impl( + g, + lpa.variant = "dominance" + )) expect_snapshot(community_label_propagation_impl( g, mode = "in", weights = c(1, 2), initial = 1:3, - fixed = c(TRUE, FALSE, TRUE) + fixed = c(TRUE, FALSE, TRUE), + lpa.variant = "retention" )) }) @@ -3344,7 +3347,7 @@ test_that("community_leiden_impl basic", { expect_snapshot(community_leiden_impl( g, weights = c(1, 2), - vertex.weights = c(1, 2, 3), + vertex.out.weights = c(1, 2, 3), resolution = 0.5, beta = 0.1, start = TRUE, @@ -3382,8 +3385,8 @@ test_that("community_infomap_impl basic", { expect_snapshot(community_infomap_impl(g)) expect_snapshot(community_infomap_impl( g, - e.weights = c(1, 2), - v.weights = c(1, 2, 3), + edge.weights = c(1, 2), + vertex.weights = c(1, 2, 3), nb.trials = 2 )) }) @@ -3933,12 +3936,12 @@ test_that("local_scan_neighborhood_ecount_impl basic", { g <- path_graph_impl(4) expect_snapshot(local_scan_neighborhood_ecount_impl( g, - neighborhoods = list(1:2, 2:3, 2:4, 2) + neighborhoods = list(1:2 - 1, 2:3 - 1, 2:4 - 1, 2 - 1) )) expect_snapshot(local_scan_neighborhood_ecount_impl( g, weights = c(1, 2, 3), - neighborhoods = list(1:2, 1:3, 2:4, 1) + neighborhoods = list(1:2 - 1, 1:3 - 1, 2:4 - 1, 1 - 1) )) }) @@ -4532,7 +4535,7 @@ test_that("canonical_permutation_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(canonical_permutation_impl(g)) - expect_snapshot(canonical_permutation_impl(g, colors = c(1, 2, 3), sh = "fl")) + expect_snapshot(canonical_permutation_impl(g, colors = c(1, 2, 3))) }) test_that("canonical_permutation_impl errors", { @@ -4586,7 +4589,7 @@ test_that("count_automorphisms_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(count_automorphisms_impl(g)) - expect_snapshot(count_automorphisms_impl(g, colors = c(1, 2, 3), sh = "fl")) + expect_snapshot(count_automorphisms_impl(g, colors = c(1, 2, 3))) }) test_that("count_automorphisms_impl errors", { @@ -4604,9 +4607,7 @@ test_that("automorphism_group_impl basic", { expect_snapshot(automorphism_group_impl(g)) expect_snapshot(automorphism_group_impl( g, - colors = c(1, 2, 3), - sh = "fl", - details = TRUE + colors = c(1, 2, 3) )) }) @@ -4809,20 +4810,6 @@ test_that("sir_impl errors", { expect_snapshot_igraph_error(sir_impl(NULL, beta = 0.1, gamma = 0.1)) }) -# 304. convex_hull_2d_impl - -test_that("convex_hull_2d_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(convex_hull_2d_impl(matrix(1:6, ncol = 2))) -}) - -test_that("convex_hull_2d_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(convex_hull_2d_impl("a")) -}) - # 305. dim_select_impl test_that("dim_select_impl basic", { From 4bad310d69a63f6b0c3b4c666e44d9ba3b783d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 21:25:47 +0200 Subject: [PATCH 075/154] aaa --- tests/testthat/_snaps/aaa-auto.md | 169 ++++++------------------------ 1 file changed, 34 insertions(+), 135 deletions(-) diff --git a/tests/testthat/_snaps/aaa-auto.md b/tests/testthat/_snaps/aaa-auto.md index 5619db795f5..a755d144f68 100644 --- a/tests/testthat/_snaps/aaa-auto.md +++ b/tests/testthat/_snaps/aaa-auto.md @@ -736,7 +736,7 @@ x Condition Error in `erdos_renyi_game_gnp_impl()`: - ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices. Invalid value + ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices for G(n,p) model. Invalid value # erdos_renyi_game_gnm_impl basic @@ -762,7 +762,7 @@ x Condition Error in `erdos_renyi_game_gnm_impl()`: - ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices. Invalid value + ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices for G(n,m) model. Invalid value # growing_random_game_impl basic @@ -908,11 +908,11 @@ Code simple_interconnected_islands_game_impl(2, 3, 0.5, 1) Output - IGRAPH U--- 6 5 -- Interconnected islands model + IGRAPH U--- 6 6 -- Interconnected islands model + attr: name (g/c), islands.n (g/n), islands.size (g/n), islands.pin | (g/n), n.inter (g/n) + edges: - [1] 1--2 1--3 2--3 3--6 5--6 + [1] 1--2 1--3 2--3 2--6 4--5 4--6 # simple_interconnected_islands_game_impl errors @@ -1166,7 +1166,7 @@ x Condition Error in `correlated_pair_game_impl()`: - ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices. Invalid value + ! At vendor/cigraph/src/games/erdos_renyi.c:xx : Invalid number of vertices for G(n,p) model. Invalid value # dot_product_game_impl basic @@ -1174,7 +1174,7 @@ dot_product_game_impl(matrix(0.5, 5, 2)) Condition Warning in `dot_product_game_impl()`: - At vendor/cigraph/src/games/dotproduct.c:90 : Greater than 1 connection probability in dot-product graph. + At vendor/cigraph/src/games/dotproduct.c:87 : Greater than 1 connection probability in dot-product graph. Output IGRAPH U--- 2 1 -- + edge: @@ -1186,7 +1186,7 @@ dot_product_game_impl(matrix(0.5, 5, 2), directed = TRUE) Condition Warning in `dot_product_game_impl()`: - At vendor/cigraph/src/games/dotproduct.c:90 : Greater than 1 connection probability in dot-product graph. + At vendor/cigraph/src/games/dotproduct.c:87 : Greater than 1 connection probability in dot-product graph. Output IGRAPH D--- 2 2 -- + edges: @@ -1294,7 +1294,7 @@ # get_shortest_path_impl basic Code - get_shortest_path_impl(g, 1, 3) + get_shortest_path_impl(g, from = 1, to = 3) Output $vertices + 3/3 vertices: @@ -1360,7 +1360,7 @@ # get_all_shortest_paths_impl basic Code - get_all_shortest_paths_impl(g, 1, 3) + get_all_shortest_paths_impl(g, from = 1, to = 3) Output $vpaths $vpaths[[1]] @@ -2016,7 +2016,7 @@ transitivity_barrat_impl(g) Condition Warning in `transitivity_barrat_impl()`: - At vendor/cigraph/src/properties/triangles.c:913 : No weights given for Barrat's transitivity, unweighted version is used. + At vendor/cigraph/src/properties/triangles.c:889 : No weights given for Barrat's transitivity, unweighted version is used. Output [1] NaN 0 NaN @@ -2026,7 +2026,7 @@ transitivity_barrat_impl(g, mode = "zero") Condition Warning in `transitivity_barrat_impl()`: - At vendor/cigraph/src/properties/triangles.c:913 : No weights given for Barrat's transitivity, unweighted version is used. + At vendor/cigraph/src/properties/triangles.c:889 : No weights given for Barrat's transitivity, unweighted version is used. Output [1] 0 0 0 @@ -2092,7 +2092,7 @@ --- Code - maxdegree_impl(g, mode = "in", loops = FALSE) + maxdegree_impl(g, mode = "in", loops = "twice") Output [1] 2 @@ -2412,10 +2412,10 @@ --- Code - eigenvector_centrality_impl(g, directed = TRUE, scale = FALSE) + eigenvector_centrality_impl(g, mode = "out") Output $vector - [1] 0.5000000 0.7071068 0.5000000 + [1] 0.7071068 1.0000000 0.7071068 $value [1] 1.414214 @@ -2494,7 +2494,7 @@ # hub_and_authority_scores_impl basic Code - hub_and_authority_scores_impl(g) + suppressWarnings(hub_and_authority_scores_impl(g)) Output $hub [1] 1 1 1 1 1 @@ -2568,83 +2568,6 @@ ---- - - Code - hub_and_authority_scores_impl(g, scale = FALSE) - Output - $hub - [1] 0.4472136 0.4472136 0.4472136 0.4472136 0.4472136 - - $authority - [1] 0.4472136 0.4472136 0.4472136 0.4472136 0.4472136 - - $value - [1] 16 - - $options - $options$bmat - [1] "I" - - $options$n - [1] 5 - - $options$which - [1] "LA" - - $options$nev - [1] 1 - - $options$tol - [1] 0 - - $options$ncv - [1] 0 - - $options$ldv - [1] 0 - - $options$ishift - [1] 1 - - $options$maxiter - [1] 3000 - - $options$nb - [1] 1 - - $options$mode - [1] 1 - - $options$start - [1] 1 - - $options$sigma - [1] 0 - - $options$sigmai - [1] 0 - - $options$info - [1] 0 - - $options$iter - [1] 1 - - $options$nconv - [1] 1 - - $options$numop - [1] 4 - - $options$numopb - [1] 0 - - $options$numreo - [1] 4 - - - # hub_and_authority_scores_impl errors Code @@ -2842,7 +2765,7 @@ --- Code - strength_impl(g, mode = "in", loops = FALSE) + strength_impl(g, mode = "in", loops = "twice") Output [1] 1 2 1 @@ -2894,7 +2817,7 @@ --- Code - centralization_degree_impl(g, mode = "in", loops = FALSE, normalized = FALSE) + centralization_degree_impl(g, mode = "in", loops = "twice", normalized = FALSE) Output $res [1] 1 2 1 @@ -3117,7 +3040,7 @@ --- Code - centralization_eigenvector_centrality_impl(g, directed = TRUE, normalized = FALSE) + centralization_eigenvector_centrality_impl(g, mode = "out", normalized = FALSE) Output $vector [1] 0.7071068 1.0000000 0.7071068 @@ -3207,12 +3130,12 @@ Code centralization_eigenvector_centrality_tmax_impl(nodes = 3) Output - [1] 1 + [1] 2 --- Code - centralization_eigenvector_centrality_tmax_impl(nodes = 3, directed = TRUE) + centralization_eigenvector_centrality_tmax_impl(nodes = 3, mode = "out") Output [1] 2 @@ -3393,7 +3316,7 @@ # pseudo_diameter_impl basic Code - pseudo_diameter_impl(g, 1) + pseudo_diameter_impl(g, start.vid = 1) Output $diameter [1] 2 @@ -3408,7 +3331,7 @@ --- Code - pseudo_diameter_impl(g, 1, directed = FALSE, unconnected = FALSE) + pseudo_diameter_impl(g, start.vid = 1, directed = FALSE, unconnected = FALSE) Output $diameter [1] 2 @@ -3783,7 +3706,7 @@ x Condition Error in `bipartite_game_gnp_impl()`: - ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite graph. Invalid value + ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite G(n,p) model. Invalid value # bipartite_game_gnm_impl basic @@ -3819,7 +3742,7 @@ x Condition Error in `bipartite_game_gnm_impl()`: - ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite graph. Invalid value + ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite G(n,m) model. Invalid value # get_laplacian_impl basic @@ -4858,7 +4781,7 @@ --- Code - similarity_dice_impl(g, vids = 1:2, mode = "in", loops = TRUE) + similarity_dice_impl(g, vit.from = 1:2, mode = "in", loops = TRUE) Output [,1] [,2] [1,] 1.0 0.8 @@ -4957,7 +4880,7 @@ --- Code - similarity_jaccard_impl(g, vids = 1:2, mode = "in", loops = TRUE) + similarity_jaccard_impl(g, vit.from = 1:2, mode = "in", loops = TRUE) Output [,1] [,2] [1,] 1.0000000 0.6666667 @@ -5109,7 +5032,7 @@ # community_label_propagation_impl basic Code - community_label_propagation_impl(g) + community_label_propagation_impl(g, lpa.variant = "dominance") Output [1] 0 0 0 @@ -5117,7 +5040,7 @@ Code community_label_propagation_impl(g, mode = "in", weights = c(1, 2), initial = 1: - 3, fixed = c(TRUE, FALSE, TRUE)) + 3, fixed = c(TRUE, FALSE, TRUE), lpa.variant = "retention") Output [1] 0 1 1 @@ -5204,7 +5127,7 @@ # community_leiden_impl basic Code - community_leiden_impl(g, weights = c(1, 2), vertex.weights = c(1, 2, 3), + community_leiden_impl(g, weights = c(1, 2), vertex.out.weights = c(1, 2, 3), resolution = 0.5, beta = 0.1, start = TRUE, n.iterations = 1, membership = 1:3) Output $membership @@ -5262,7 +5185,7 @@ --- Code - community_infomap_impl(g, e.weights = c(1, 2), v.weights = c(1, 2, 3), + community_infomap_impl(g, edge.weights = c(1, 2), vertex.weights = c(1, 2, 3), nb.trials = 2) Output $membership @@ -5813,7 +5736,7 @@ triad_census_impl(g) Condition Warning in `triad_census_impl()`: - At vendor/cigraph/src/misc/motifs.c:1157 : Triad census called on an undirected graph. All connections will be treated as mutual. + At vendor/cigraph/src/misc/motifs.c:1167 : Triad census called on an undirected graph. All connections will be treated as mutual. Output [1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 @@ -6926,7 +6849,7 @@ --- Code - canonical_permutation_impl(g, colors = c(1, 2, 3), sh = "fl") + canonical_permutation_impl(g, colors = c(1, 2, 3)) Output $labeling [1] 1 2 3 @@ -7122,7 +7045,7 @@ --- Code - count_automorphisms_impl(g, colors = c(1, 2, 3), sh = "fl") + count_automorphisms_impl(g, colors = c(1, 2, 3)) Output $nof_nodes [1] 1 @@ -7164,7 +7087,7 @@ --- Code - automorphism_group_impl(g, colors = c(1, 2, 3), sh = "fl", details = TRUE) + automorphism_group_impl(g, colors = c(1, 2, 3)) Output $generators list() @@ -9190,30 +9113,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# convex_hull_2d_impl basic - - Code - convex_hull_2d_impl(matrix(1:6, ncol = 2)) - Output - $resverts - [1] 1 3 - - $rescoords - [,1] [,2] - [1,] 1 4 - [2,] 3 6 - - -# convex_hull_2d_impl errors - - Code - x - Condition - Warning in `convex_hull_2d_impl()`: - NAs introduced by coercion - Error in `convex_hull_2d_impl()`: - ! REAL() can only be applied to a 'numeric', not a 'character' - # dim_select_impl basic Code From 2a6ff7640d91259e0188162bff58b3ce15ee69a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 19 Oct 2025 22:00:53 +0200 Subject: [PATCH 076/154] PR --- .github/workflows/R-CMD-check.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index e6f9d69d0c7..a68f3c859e4 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -16,6 +16,7 @@ on: branches: - main - master + - next workflow_dispatch: inputs: ref: From 49376fa7bad91615cc7218260dee150513b3ffb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 20 Oct 2025 07:27:47 +0200 Subject: [PATCH 077/154] Document --- R/make.R | 2 +- R/other.R | 2 +- R/paths.R | 4 ++-- R/triangles.R | 2 +- man/cluster_label_prop.Rd | 2 +- man/convex_hull.Rd | 2 +- man/count_triangles.Rd | 2 +- man/eccentricity.Rd | 2 +- man/feedback_arc_set.Rd | 2 +- man/feedback_vertex_set.Rd | 2 +- man/graph_from_lcf.Rd | 2 +- man/igraph_version.Rd | 9 +++++---- man/is_acyclic.Rd | 2 +- man/is_dag.Rd | 2 +- man/radius.Rd | 2 +- man/sample_chung_lu.Rd | 2 +- man/sample_correlated_gnp.Rd | 2 +- man/sample_correlated_gnp_pair.Rd | 2 +- man/sample_dot_product.Rd | 2 +- man/sample_fitness.Rd | 2 +- man/sample_fitness_pl.Rd | 2 +- man/sample_forestfire.Rd | 2 +- man/sample_growing.Rd | 2 +- man/sample_hierarchical_sbm.Rd | 2 +- man/sample_islands.Rd | 2 +- man/sample_k_regular.Rd | 2 +- man/sample_sbm.Rd | 2 +- man/sample_tree.Rd | 2 +- man/sir.Rd | 2 +- 29 files changed, 34 insertions(+), 33 deletions(-) diff --git a/R/make.R b/R/make.R index 7a8fa5725e7..0fb6b6d2b89 100644 --- a/R/make.R +++ b/R/make.R @@ -2599,7 +2599,7 @@ full_citation_graph <- function(...) { #' g2 <- make_graph("Franklin") #' isomorphic(g1, g2) #' @export -#' @cdocs igraph_lcf_vector +#' @cdocs igraph_lcf graph_from_lcf <- function( shifts, ..., diff --git a/R/other.R b/R/other.R index c6a86b55e95..a3ecbc39f30 100644 --- a/R/other.R +++ b/R/other.R @@ -222,5 +222,5 @@ igraph.i.spMatrix <- function(M) { #' convex_hull(M) #' @family other #' @export -#' @cdocs igraph_convex_hull +#' @cdocs igraph_convex_hull_2d convex_hull <- convex_hull_impl diff --git a/R/paths.R b/R/paths.R index 4b16f771bcf..1c47dac63ff 100644 --- a/R/paths.R +++ b/R/paths.R @@ -270,7 +270,7 @@ max_cardinality <- maximum_cardinality_search_impl #' eccentricity(g) #' @family paths #' @export -#' @cdocs igraph_eccentricity_dijkstra +#' @cdocs igraph_eccentricity eccentricity <- function( graph, vids = V(graph), @@ -325,7 +325,7 @@ eccentricity <- function( #' radius(g) #' @family paths #' @export -#' @cdocs igraph_radius_dijkstra +#' @cdocs igraph_radius radius <- function( graph, ..., diff --git a/R/triangles.R b/R/triangles.R index d9d31fe665c..00bf6fc7207 100644 --- a/R/triangles.R +++ b/R/triangles.R @@ -93,5 +93,5 @@ triangles <- list_triangles_impl #' @export #' @rdname count_triangles -#' @cdocs igraph_adjacent_triangles +#' @cdocs igraph_count_adjacent_triangles count_triangles <- count_adjacent_triangles_impl diff --git a/man/cluster_label_prop.Rd b/man/cluster_label_prop.Rd index 25c61d2ca0f..d092ca9a061 100644 --- a/man/cluster_label_prop.Rd +++ b/man/cluster_label_prop.Rd @@ -11,7 +11,7 @@ cluster_label_prop( mode = c("out", "in", "all"), initial = NULL, fixed = NULL, - lta_variant = c("dominance", "retention", "fast") + lpa_variant = c("dominance", "retention", "fast") ) } \arguments{ diff --git a/man/convex_hull.Rd b/man/convex_hull.Rd index b500ab2615e..45a17e0fb2a 100644 --- a/man/convex_hull.Rd +++ b/man/convex_hull.Rd @@ -45,5 +45,5 @@ Tamas Nepusz \email{ntamas@gmail.com} } \concept{other} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Nongraph.html#igraph_convex_hull}{\code{convex_hull()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Spatial.html#igraph_convex_hull_2d}{\code{convex_hull_2d()}}.} diff --git a/man/count_triangles.Rd b/man/count_triangles.Rd index 8db87f9e930..46764c13d21 100644 --- a/man/count_triangles.Rd +++ b/man/count_triangles.Rd @@ -63,5 +63,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com} } \concept{triangles} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Motifs.html#igraph_list_triangles}{\code{list_triangles()}}, \href{https://igraph.org/c/html/latest/igraph-Motifs.html#igraph_adjacent_triangles}{\code{adjacent_triangles()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Motifs.html#igraph_list_triangles}{\code{list_triangles()}}, \href{https://igraph.org/c/html/latest/igraph-Motifs.html#igraph_count_adjacent_triangles}{\code{count_adjacent_triangles()}}.} diff --git a/man/eccentricity.Rd b/man/eccentricity.Rd index a4678a78d2d..19a64315619 100644 --- a/man/eccentricity.Rd +++ b/man/eccentricity.Rd @@ -68,5 +68,5 @@ Other paths: \code{\link{radius}()} } \concept{paths} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_eccentricity_dijkstra}{\code{eccentricity_dijkstra()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_eccentricity}{\code{eccentricity()}}.} diff --git a/man/feedback_arc_set.Rd b/man/feedback_arc_set.Rd index 59a41641f6a..ebf760a59d3 100644 --- a/man/feedback_arc_set.Rd +++ b/man/feedback_arc_set.Rd @@ -88,5 +88,5 @@ Graph cycles \concept{cycles} \concept{structural.properties} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_feedback_arc_set}{\code{feedback_arc_set()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cycles.html#igraph_feedback_arc_set}{\code{feedback_arc_set()}}.} diff --git a/man/feedback_vertex_set.Rd b/man/feedback_vertex_set.Rd index 06f635f7ee5..e9039b29160 100644 --- a/man/feedback_vertex_set.Rd +++ b/man/feedback_vertex_set.Rd @@ -74,5 +74,5 @@ Graph cycles \concept{cycles} \concept{structural.properties} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_feedback_vertex_set}{\code{feedback_vertex_set()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cycles.html#igraph_feedback_vertex_set}{\code{feedback_vertex_set()}}.} diff --git a/man/graph_from_lcf.Rd b/man/graph_from_lcf.Rd index 41ac2b6c9d6..b2a5618baed 100644 --- a/man/graph_from_lcf.Rd +++ b/man/graph_from_lcf.Rd @@ -42,5 +42,5 @@ functions on the its manual page for creating special graphs. Gabor Csardi \email{csardi.gabor@gmail.com} } \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_lcf_vector}{\code{lcf_vector()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_lcf}{\code{lcf()}}.} diff --git a/man/igraph_version.Rd b/man/igraph_version.Rd index 426390911cb..07a9401d173 100644 --- a/man/igraph_version.Rd +++ b/man/igraph_version.Rd @@ -4,15 +4,16 @@ \alias{igraph_version} \title{Query igraph's version string} \usage{ -igraph_version(software = c("R", "C")) +igraph_version() +} +\value{ +A character scalar, the igraph version string, with an attribute +\code{"c_version"} giving the C library version string. } \description{ Returns the R package version, prints the R package version and C library version. } -\details{ -#' @return A character scalar, the igraph version string. -} \examples{ igraph_version() diff --git a/man/is_acyclic.Rd b/man/is_acyclic.Rd index 21a8b7dc86d..6881e4e95b0 100644 --- a/man/is_acyclic.Rd +++ b/man/is_acyclic.Rd @@ -67,5 +67,5 @@ Other structural.properties: \concept{cycles} \concept{structural.properties} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_is_acyclic}{\code{is_acyclic()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cycles.html#igraph_is_acyclic}{\code{is_acyclic()}}.} diff --git a/man/is_dag.Rd b/man/is_dag.Rd index 0c651de7b3e..08c2a30d9f8 100644 --- a/man/is_dag.Rd +++ b/man/is_dag.Rd @@ -71,5 +71,5 @@ Tamas Nepusz \email{ntamas@gmail.com} for the C code, Gabor Csardi \concept{cycles} \concept{structural.properties} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_is_dag}{\code{is_dag()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cycles.html#igraph_is_dag}{\code{is_dag()}}.} diff --git a/man/radius.Rd b/man/radius.Rd index 16cb54ccbe5..0f353e271fb 100644 --- a/man/radius.Rd +++ b/man/radius.Rd @@ -61,5 +61,5 @@ Other paths: \code{\link{graph_center}()} } \concept{paths} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_radius_dijkstra}{\code{radius_dijkstra()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Structural.html#igraph_radius}{\code{radius()}}.} diff --git a/man/sample_chung_lu.Rd b/man/sample_chung_lu.Rd index 28a0dfdbd5b..f0d00d6cc2f 100644 --- a/man/sample_chung_lu.Rd +++ b/man/sample_chung_lu.Rd @@ -202,5 +202,5 @@ Random graph models (games) \code{\link{sample_tree}()} } \concept{games} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_chung_lu_game}{\code{chung_lu_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_chung_lu_game}{\code{chung_lu_game()}}.} diff --git a/man/sample_correlated_gnp.Rd b/man/sample_correlated_gnp.Rd index 215c5f1c4c3..565a0b2293e 100644 --- a/man/sample_correlated_gnp.Rd +++ b/man/sample_correlated_gnp.Rd @@ -84,5 +84,5 @@ Random graph models (games) \code{\link{sample_tree}()} } \concept{games} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_correlated_game}{\code{correlated_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_correlated_game}{\code{correlated_game()}}.} diff --git a/man/sample_correlated_gnp_pair.Rd b/man/sample_correlated_gnp_pair.Rd index 8244f3a5bcc..9e397212ef7 100644 --- a/man/sample_correlated_gnp_pair.Rd +++ b/man/sample_correlated_gnp_pair.Rd @@ -78,5 +78,5 @@ Random graph models (games) } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_correlated_pair_game}{\code{correlated_pair_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_correlated_pair_game}{\code{correlated_pair_game()}}.} diff --git a/man/sample_dot_product.Rd b/man/sample_dot_product.Rd index 44e6f018a5a..c9baf59e001 100644 --- a/man/sample_dot_product.Rd +++ b/man/sample_dot_product.Rd @@ -89,5 +89,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_dot_product_game}{\code{dot_product_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_dot_product_game}{\code{dot_product_game()}}.} diff --git a/man/sample_fitness.Rd b/man/sample_fitness.Rd index 1502423df95..28d1ec28925 100644 --- a/man/sample_fitness.Rd +++ b/man/sample_fitness.Rd @@ -111,5 +111,5 @@ Tamas Nepusz \email{ntamas@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_static_fitness_game}{\code{static_fitness_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_static_fitness_game}{\code{static_fitness_game()}}.} diff --git a/man/sample_fitness_pl.Rd b/man/sample_fitness_pl.Rd index 166c910685a..003c9ae2411 100644 --- a/man/sample_fitness_pl.Rd +++ b/man/sample_fitness_pl.Rd @@ -120,5 +120,5 @@ Tamas Nepusz \email{ntamas@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_static_power_law_game}{\code{static_power_law_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_static_power_law_game}{\code{static_power_law_game()}}.} diff --git a/man/sample_forestfire.Rd b/man/sample_forestfire.Rd index 76eff55ac99..9ada534faf1 100644 --- a/man/sample_forestfire.Rd +++ b/man/sample_forestfire.Rd @@ -109,5 +109,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_forest_fire_game}{\code{forest_fire_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_forest_fire_game}{\code{forest_fire_game()}}.} diff --git a/man/sample_growing.Rd b/man/sample_growing.Rd index 6423905fb78..7ba98da51ad 100644 --- a/man/sample_growing.Rd +++ b/man/sample_growing.Rd @@ -74,5 +74,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_growing_random_game}{\code{growing_random_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_growing_random_game}{\code{growing_random_game()}}.} diff --git a/man/sample_hierarchical_sbm.Rd b/man/sample_hierarchical_sbm.Rd index 9f7e79f906e..f62dc6e2f59 100644 --- a/man/sample_hierarchical_sbm.Rd +++ b/man/sample_hierarchical_sbm.Rd @@ -91,5 +91,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_hsbm_game}{\code{hsbm_game()}}, \href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_hsbm_list_game}{\code{hsbm_list_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_hsbm_game}{\code{hsbm_game()}}, \href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_hsbm_list_game}{\code{hsbm_list_game()}}.} diff --git a/man/sample_islands.Rd b/man/sample_islands.Rd index 20c0536f2fe..324d88cb57a 100644 --- a/man/sample_islands.Rd +++ b/man/sample_islands.Rd @@ -68,5 +68,5 @@ Samuel Thiriot } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_simple_interconnected_islands_game}{\code{simple_interconnected_islands_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_simple_interconnected_islands_game}{\code{simple_interconnected_islands_game()}}.} diff --git a/man/sample_k_regular.Rd b/man/sample_k_regular.Rd index 102511c17da..9074a8e79cf 100644 --- a/man/sample_k_regular.Rd +++ b/man/sample_k_regular.Rd @@ -80,5 +80,5 @@ Tamas Nepusz \email{ntamas@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_k_regular_game}{\code{k_regular_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_k_regular_game}{\code{k_regular_game()}}.} diff --git a/man/sample_sbm.Rd b/man/sample_sbm.Rd index e11e2c4315a..1fe65860ee8 100644 --- a/man/sample_sbm.Rd +++ b/man/sample_sbm.Rd @@ -85,5 +85,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com} } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_sbm_game}{\code{sbm_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_sbm_game}{\code{sbm_game()}}.} diff --git a/man/sample_tree.Rd b/man/sample_tree.Rd index f2e025926a5..1857319212f 100644 --- a/man/sample_tree.Rd +++ b/man/sample_tree.Rd @@ -66,5 +66,5 @@ Random graph models (games) } \concept{games} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_tree_game}{\code{tree_game()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Games.html#igraph_tree_game}{\code{tree_game()}}.} diff --git a/man/sir.Rd b/man/sir.Rd index 9d765427c62..d413677b05a 100644 --- a/man/sir.Rd +++ b/man/sir.Rd @@ -126,5 +126,5 @@ Gabor Csardi \email{csardi.gabor@gmail.com}. Eric Kolaczyk } \concept{processes} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Spatial-Games.html#igraph_sir}{\code{sir()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Processes.html#igraph_sir}{\code{sir()}}.} From 609a3031af45d6d76914dfc5376a633f7ae109de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 21 Oct 2025 05:48:16 +0200 Subject: [PATCH 078/154] Remove unused args --- R/topology.R | 18 ------------------ man/automorphism_group.Rd | 20 -------------------- 2 files changed, 38 deletions(-) diff --git a/R/topology.R b/R/topology.R index 9ccfb771510..a8d50883863 100644 --- a/R/topology.R +++ b/R/topology.R @@ -1155,24 +1155,6 @@ count_automorphisms <- count_automorphisms_bliss_impl #' vertices, or, if there is no such vertex attribute, it simply assumes that #' all vertices have the same color. Pass NULL explicitly if the graph has a #' `color` vertex attribute but you do not want to use it. -#' @param sh The splitting heuristics for the BLISS algorithm. Possible values -#' are: -#' \sQuote{`f`}: -#' first non-singleton cell, -#' \sQuote{`fl`}: -#' first largest non-singleton cell, -#' \sQuote{`fs`}: -#' first smallest non-singleton cell, -#' \sQuote{`fm`}: -#' first maximally non-trivially connected -#' non-singleton cell, -#' \sQuote{`flm`}: -#' first largest maximally -#' non-trivially connected non-singleton cell, -#' \sQuote{`fsm`}: -#' first smallest maximally non-trivially connected non-singleton cell. -#' @param details Specifies whether to provide additional details about the -#' BLISS internals in the result. #' @return When `details` is `FALSE`, a list of vertex permutations #' that form a generating set of the automorphism group of the input graph. #' When `details` is `TRUE`, a named list with two members: diff --git a/man/automorphism_group.Rd b/man/automorphism_group.Rd index fc6f8266a59..f67e6cc13e8 100644 --- a/man/automorphism_group.Rd +++ b/man/automorphism_group.Rd @@ -15,26 +15,6 @@ automorphism. When omitted, igraph uses the \code{color} attribute of the vertices, or, if there is no such vertex attribute, it simply assumes that all vertices have the same color. Pass NULL explicitly if the graph has a \code{color} vertex attribute but you do not want to use it.} - -\item{sh}{The splitting heuristics for the BLISS algorithm. Possible values -are: -\sQuote{\code{f}}: -first non-singleton cell, -\sQuote{\code{fl}}: -first largest non-singleton cell, -\sQuote{\code{fs}}: -first smallest non-singleton cell, -\sQuote{\code{fm}}: -first maximally non-trivially connected -non-singleton cell, -\sQuote{\code{flm}}: -first largest maximally -non-trivially connected non-singleton cell, -\sQuote{\code{fsm}}: -first smallest maximally non-trivially connected non-singleton cell.} - -\item{details}{Specifies whether to provide additional details about the -BLISS internals in the result.} } \value{ When \code{details} is \code{FALSE}, a list of vertex permutations From ed066c65d68a8d9939d6dda017d6694aa2d591e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 21 Oct 2025 05:51:17 +0200 Subject: [PATCH 079/154] Document missing arg --- R/centralization.R | 4 +++- man/centr_eigen_tmax.Rd | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/R/centralization.R b/R/centralization.R index f5c6e906beb..82ffe41c31c 100644 --- a/R/centralization.R +++ b/R/centralization.R @@ -685,7 +685,9 @@ centr_eigen <- function( #' @param directed logical scalar, whether to consider edge directions #' during the calculation. Ignored in undirected graphs. #' @param scale `r lifecycle::badge("deprecated")` Ignored. Computing -#' eigenvector centralization requires normalized eigenvector centrality scores. +#' eigenvector centralization requires normalized eigenvector centrality scores. +#' @param mode This is the same as the `mode` argument of +#' `degree()`. #' @return Real scalar, the theoretical maximum (unnormalized) graph #' eigenvector centrality score for graphs with given vertex count and #' other parameters. diff --git a/man/centr_eigen_tmax.Rd b/man/centr_eigen_tmax.Rd index 8b7718a95d6..b8d6a39f0f9 100644 --- a/man/centr_eigen_tmax.Rd +++ b/man/centr_eigen_tmax.Rd @@ -24,6 +24,9 @@ during the calculation. Ignored in undirected graphs.} \item{scale}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Ignored. Computing eigenvector centralization requires normalized eigenvector centrality scores.} + +\item{mode}{This is the same as the \code{mode} argument of +\code{degree()}.} } \value{ Real scalar, the theoretical maximum (unnormalized) graph From 6c5af56158d45d5bcfb1bccc8e5cb252b769e148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 22 Oct 2025 17:36:07 +0200 Subject: [PATCH 080/154] Remove preprocessing --- R/paths.R | 1 - R/pp.R | 24 ------------------------ src/cpp11.cpp | 2 -- src/rinterface_extra.c | 21 --------------------- 4 files changed, 48 deletions(-) delete mode 100644 R/pp.R diff --git a/R/paths.R b/R/paths.R index 1c47dac63ff..4a5aff74546 100644 --- a/R/paths.R +++ b/R/paths.R @@ -127,7 +127,6 @@ all_simple_paths <- function( mode = mode ) ) - res <- get.all.simple.paths.pp(res) if (igraph_opt("return.vs.es")) { res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) diff --git a/R/pp.R b/R/pp.R deleted file mode 100644 index d452b97fa12..00000000000 --- a/R/pp.R +++ /dev/null @@ -1,24 +0,0 @@ -# IGraph R package -# Copyright (C) 2014 Gabor Csardi -# 334 Harvard street, Cambridge, MA 02139 USA -# -# 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA -# -################################################################### - -get.all.simple.paths.pp <- function(vect) { - .Call(R_igraph_get_all_simple_paths_pp, vect) -} diff --git a/src/cpp11.cpp b/src/cpp11.cpp index f51d3eeafb0..2d967eb6a56 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -192,7 +192,6 @@ extern SEXP R_igraph_get_all_eids_between(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_shortest_paths_dijkstra(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_simple_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_get_all_simple_paths_pp(SEXP); extern SEXP R_igraph_get_attr_mode(SEXP, SEXP); extern SEXP R_igraph_get_biadjacency(SEXP, SEXP, SEXP); extern SEXP R_igraph_get_diameter(SEXP, SEXP, SEXP, SEXP); @@ -665,7 +664,6 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_get_all_shortest_paths", (DL_FUNC) &R_igraph_get_all_shortest_paths, 5}, {"R_igraph_get_all_shortest_paths_dijkstra", (DL_FUNC) &R_igraph_get_all_shortest_paths_dijkstra, 5}, {"R_igraph_get_all_simple_paths", (DL_FUNC) &R_igraph_get_all_simple_paths, 6}, - {"R_igraph_get_all_simple_paths_pp", (DL_FUNC) &R_igraph_get_all_simple_paths_pp, 1}, {"R_igraph_get_attr_mode", (DL_FUNC) &R_igraph_get_attr_mode, 2}, {"R_igraph_get_biadjacency", (DL_FUNC) &R_igraph_get_biadjacency, 3}, {"R_igraph_get_diameter", (DL_FUNC) &R_igraph_get_diameter, 4}, diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 1ab15370db6..69d54585872 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -8449,27 +8449,6 @@ int igraphhcass2(int n, const int *ia, const int *ib, return 0; } /* hcass2_ */ -SEXP R_igraph_get_all_simple_paths_pp(SEXP vector) { - SEXP result; - igraph_integer_t no=0, n=Rf_xlength(vector); - double *vec=REAL(vector), *p=vec, *pp=vec; - for (igraph_integer_t i=0; i Date: Tue, 21 Oct 2025 23:45:57 +0200 Subject: [PATCH 081/154] Restore for now --- R/aaa-auto.R | 40 ++++++++++++ src/rinterface.c | 110 ++++++++++++++++++++++++++++++++ src/rinterface.h | 16 +++++ src/rinterface_extra.c | 26 ++++++++ tools/stimulus/functions-R.yaml | 15 +++++ 5 files changed, 207 insertions(+) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index c87505879b0..e509db76cd0 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -5602,3 +5602,43 @@ version_impl <- function() { res } +sample_sphere_surface_impl <- function(dim, n=1, radius=1, positive=TRUE) { + # Argument checks + dim <- as.numeric(dim) + n <- as.numeric(n) + radius <- as.numeric(radius) + positive <- as.logical(positive) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_sample_sphere_surface, dim, n, radius, positive) + + res +} + +sample_sphere_volume_impl <- function(dim, n=1, radius=1, positive=TRUE) { + # Argument checks + dim <- as.numeric(dim) + n <- as.numeric(n) + radius <- as.numeric(radius) + positive <- as.logical(positive) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_sample_sphere_volume, dim, n, radius, positive) + + res +} + +sample_dirichlet_impl <- function(n, alpha) { + # Argument checks + n <- as.numeric(n) + alpha <- as.numeric(alpha) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_sample_dirichlet, n, alpha) + + res +} + diff --git a/src/rinterface.c b/src/rinterface.c index 7f1ca6c4096..d88c05db4e3 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -13137,3 +13137,113 @@ SEXP R_igraph_version(void) { UNPROTECT(1); return(r_result); } + +/*-------------------------------------------/ +/ igraph_sample_sphere_surface / +/-------------------------------------------*/ +SEXP R_igraph_sample_sphere_surface(SEXP dim, SEXP n, SEXP radius, SEXP positive) { + /* Declarations */ + igraph_integer_t c_dim; + igraph_integer_t c_n; + igraph_real_t c_radius; + igraph_bool_t c_positive; + igraph_matrix_t c_res; + SEXP res; + + SEXP r_result; + /* Convert input */ + IGRAPH_R_CHECK_INT(dim); + c_dim = (igraph_integer_t) REAL(dim)[0]; + IGRAPH_R_CHECK_INT(n); + c_n = (igraph_integer_t) REAL(n)[0]; + IGRAPH_R_CHECK_REAL(radius); + c_radius = REAL(radius)[0]; + IGRAPH_R_CHECK_BOOL(positive); + c_positive = LOGICAL(positive)[0]; + IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); + IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_sample_sphere_surface(c_dim, c_n, c_radius, c_positive, &c_res)); + PutRNGstate(); + + /* Convert output */ + PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); + igraph_matrix_destroy(&c_res); + IGRAPH_FINALLY_CLEAN(1); + r_result = res; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_sample_sphere_volume / +/-------------------------------------------*/ +SEXP R_igraph_sample_sphere_volume(SEXP dim, SEXP n, SEXP radius, SEXP positive) { + /* Declarations */ + igraph_integer_t c_dim; + igraph_integer_t c_n; + igraph_real_t c_radius; + igraph_bool_t c_positive; + igraph_matrix_t c_res; + SEXP res; + + SEXP r_result; + /* Convert input */ + IGRAPH_R_CHECK_INT(dim); + c_dim = (igraph_integer_t) REAL(dim)[0]; + IGRAPH_R_CHECK_INT(n); + c_n = (igraph_integer_t) REAL(n)[0]; + IGRAPH_R_CHECK_REAL(radius); + c_radius = REAL(radius)[0]; + IGRAPH_R_CHECK_BOOL(positive); + c_positive = LOGICAL(positive)[0]; + IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); + IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_sample_sphere_volume(c_dim, c_n, c_radius, c_positive, &c_res)); + PutRNGstate(); + + /* Convert output */ + PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); + igraph_matrix_destroy(&c_res); + IGRAPH_FINALLY_CLEAN(1); + r_result = res; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_sample_dirichlet / +/-------------------------------------------*/ +SEXP R_igraph_sample_dirichlet(SEXP n, SEXP alpha) { + /* Declarations */ + igraph_integer_t c_n; + igraph_vector_t c_alpha; + igraph_matrix_t c_res; + SEXP res; + + SEXP r_result; + /* Convert input */ + IGRAPH_R_CHECK_INT(n); + c_n = (igraph_integer_t) REAL(n)[0]; + R_SEXP_to_vector(alpha, &c_alpha); + IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); + IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_sample_dirichlet(c_n, &c_alpha, &c_res)); + PutRNGstate(); + + /* Convert output */ + PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); + igraph_matrix_destroy(&c_res); + IGRAPH_FINALLY_CLEAN(1); + r_result = res; + + UNPROTECT(1); + return(r_result); +} diff --git a/src/rinterface.h b/src/rinterface.h index c80d3998497..60098ed5a7b 100644 --- a/src/rinterface.h +++ b/src/rinterface.h @@ -150,3 +150,19 @@ void R_check_bool_scalar(SEXP value); igraph_error_t R_get_int_scalar(SEXP sexp, R_xlen_t index, igraph_integer_t *res); igraph_error_t R_get_real_scalar(SEXP sexp, R_xlen_t index, igraph_real_t *res); igraph_error_t R_get_bool_scalar(SEXP sexp, R_xlen_t index, igraph_bool_t *res); + +igraph_error_t igraph_sample_sphere_surface(igraph_integer_t dim, + igraph_integer_t n, + igraph_real_t radius, + igraph_bool_t positive, + igraph_matrix_t *res); + +igraph_error_t igraph_sample_sphere_volume(igraph_integer_t dim, + igraph_integer_t n, + igraph_real_t radius, + igraph_bool_t positive, + igraph_matrix_t *res); + +igraph_error_t igraph_sample_dirichlet(igraph_integer_t n, + const igraph_vector_t *alpha, + igraph_matrix_t *res); diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 69d54585872..c64becf90cc 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -21,6 +21,8 @@ */ +#include "igraph_random.h" +#include "igraph_sampling.h" #include "rinterface.h" #include "rrandom.h" @@ -8575,3 +8577,27 @@ SEXP R_igraph_add_env(SEXP graph) { SEXP R_igraph_get_graph_id(SEXP graph) { return Rf_findVar(Rf_install("myid"), R_igraph_graph_env(graph)); } + +igraph_error_t igraph_sample_sphere_surface(igraph_integer_t dim, + igraph_integer_t n, + igraph_real_t radius, + igraph_bool_t positive, + igraph_matrix_t *res) { + return igraph_rng_sample_sphere_surface(igraph_rng_default(), dim, n, radius, + positive, res); +} + +igraph_error_t igraph_sample_sphere_volume(igraph_integer_t dim, + igraph_integer_t n, + igraph_real_t radius, + igraph_bool_t positive, + igraph_matrix_t *res) { + return igraph_rng_sample_sphere_volume(igraph_rng_default(), dim, n, radius, + positive, res); +} + +igraph_error_t igraph_sample_dirichlet(igraph_integer_t n, + const igraph_vector_t *alpha, + igraph_matrix_t *res) { + return igraph_rng_sample_dirichlet(igraph_rng_default(), n, alpha, res); +} diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index d8ffec62c50..591e1f70df4 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -228,6 +228,21 @@ igraph_correlated_pair_game: igraph_dot_product_game: +# HACK +igraph_sample_sphere_surface: + PARAMS: |- + INTEGER dim, INTEGER n=1, REAL radius=1, + BOOLEAN positive=True, OUT MATRIX res + +igraph_sample_sphere_volume: + PARAMS: |- + INTEGER dim, INTEGER n=1, REAL radius=1, + BOOLEAN positive=True, OUT MATRIX res + +igraph_sample_dirichlet: + PARAMS: INTEGER n, VECTOR alpha, OUT MATRIX res + + ####################################### # Basic query functions ####################################### From a7290cd8ef068e3fe370de98411e186c34755c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 22 Oct 2025 17:22:32 +0200 Subject: [PATCH 082/154] Register --- src/cpp11.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cpp11.cpp b/src/cpp11.cpp index 2d967eb6a56..7329f158e75 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -408,6 +408,9 @@ extern SEXP R_igraph_ring(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_rooted_product(SEXP, SEXP, SEXP); extern SEXP R_igraph_roots_for_tree_layout(SEXP, SEXP, SEXP); extern SEXP R_igraph_running_mean(SEXP, SEXP); +extern SEXP R_igraph_sample_dirichlet(SEXP, SEXP); +extern SEXP R_igraph_sample_sphere_surface(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_sample_sphere_volume(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_sbm_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_set_verbose(SEXP); extern SEXP R_igraph_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); @@ -880,6 +883,9 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_rooted_product", (DL_FUNC) &R_igraph_rooted_product, 3}, {"R_igraph_roots_for_tree_layout", (DL_FUNC) &R_igraph_roots_for_tree_layout, 3}, {"R_igraph_running_mean", (DL_FUNC) &R_igraph_running_mean, 2}, + {"R_igraph_sample_dirichlet", (DL_FUNC) &R_igraph_sample_dirichlet, 2}, + {"R_igraph_sample_sphere_surface", (DL_FUNC) &R_igraph_sample_sphere_surface, 4}, + {"R_igraph_sample_sphere_volume", (DL_FUNC) &R_igraph_sample_sphere_volume, 4}, {"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}, From 8f93aebfafbdfd797e91df1ff58fee5706067922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 22 Oct 2025 17:47:42 +0200 Subject: [PATCH 083/154] Loops --- R/centralization.R | 17 +++++++++-------- man/centr_degree_tmax.Rd | 11 +++++++---- man/centralization.degree.tmax.Rd | 7 +++++-- man/centralize.Rd | 2 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/R/centralization.R b/R/centralization.R index 82ffe41c31c..acbc39fb769 100644 --- a/R/centralization.R +++ b/R/centralization.R @@ -308,7 +308,7 @@ NULL #' #' # Calculate centralization from pre-computed scores #' deg <- degree(g) -#' tmax <- centr_degree_tmax(g, loops = FALSE) +#' tmax <- centr_degree_tmax(g, loops = "none") #' centralize(deg, tmax) #' #' # The most centralized graph according to eigenvector centrality @@ -369,8 +369,11 @@ centr_degree <- centralization_degree_impl #' @param nodes The number of vertices. This is ignored if the graph is given. #' @param mode This is the same as the `mode` argument of `degree()`. Ignored #' if `graph` is given and the graph is undirected. -#' @param loops Logical scalar, whether to consider loops edges when -#' calculating the degree. +#' @param loops Character string, +#' `"none"` (the default) ignores loop edges; +#' `"once"` counts each loop edge only once; +#' `"twice"` counts each loop edge twice in undirected graphs. +#' and once in directed graphs. #' @return Real scalar, the theoretical maximum (unnormalized) graph degree #' centrality score for graphs with given order and other parameters. #' @@ -381,8 +384,8 @@ centr_degree <- centralization_degree_impl #' @examples #' # A BA graph is quite centralized #' g <- sample_pa(1000, m = 4) -#' centr_degree(g, normalized = FALSE)$centralization %>% -#' `/`(centr_degree_tmax(g, loops = FALSE)) +#' centr_degree(g, normalized = FALSE)$centralization / +#' centr_degree_tmax(g, loops = "twice") #' centr_degree(g, normalized = TRUE)$centralization centr_degree_tmax <- function( graph = NULL, @@ -396,7 +399,7 @@ centr_degree_tmax <- function( what = "centr_degree_tmax(loops = 'must be explicit')", details = "The default value (currently `FALSE`) will be dropped in the next release. Add an explicit value for the `loops` argument." ) - loops <- FALSE + loops <- "none" } # Argument checks @@ -404,8 +407,6 @@ centr_degree_tmax <- function( nodes <- as.numeric(nodes) - loops <- as.logical(loops) - # Function call res <- centralization_degree_tmax_impl( graph, diff --git a/man/centr_degree_tmax.Rd b/man/centr_degree_tmax.Rd index edb61533072..274ea5b5a05 100644 --- a/man/centr_degree_tmax.Rd +++ b/man/centr_degree_tmax.Rd @@ -19,8 +19,11 @@ centr_degree_tmax( \item{mode}{This is the same as the \code{mode} argument of \code{degree()}. Ignored if \code{graph} is given and the graph is undirected.} -\item{loops}{Logical scalar, whether to consider loops edges when -calculating the degree.} +\item{loops}{Character string, +\code{"none"} (the default) ignores loop edges; +\code{"once"} counts each loop edge only once; +\code{"twice"} counts each loop edge twice in undirected graphs. +and once in directed graphs.} } \value{ Real scalar, the theoretical maximum (unnormalized) graph degree @@ -32,8 +35,8 @@ See \code{\link[=centralize]{centralize()}} for a summary of graph centralizatio \examples{ # A BA graph is quite centralized g <- sample_pa(1000, m = 4) -centr_degree(g, normalized = FALSE)$centralization \%>\% - `/`(centr_degree_tmax(g, loops = FALSE)) +centr_degree(g, normalized = FALSE)$centralization / + centr_degree_tmax(g, loops = "twice") centr_degree(g, normalized = TRUE)$centralization } \seealso{ diff --git a/man/centralization.degree.tmax.Rd b/man/centralization.degree.tmax.Rd index fa664f658f5..f5cfa9a37df 100644 --- a/man/centralization.degree.tmax.Rd +++ b/man/centralization.degree.tmax.Rd @@ -19,8 +19,11 @@ centralization.degree.tmax( \item{mode}{This is the same as the \code{mode} argument of \code{degree()}. Ignored if \code{graph} is given and the graph is undirected.} -\item{loops}{Logical scalar, whether to consider loops edges when -calculating the degree.} +\item{loops}{Character string, +\code{"none"} (the default) ignores loop edges; +\code{"once"} counts each loop edge only once; +\code{"twice"} counts each loop edge twice in undirected graphs. +and once in directed graphs.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} diff --git a/man/centralize.Rd b/man/centralize.Rd index 134db123a5b..e9969cb9238 100644 --- a/man/centralize.Rd +++ b/man/centralize.Rd @@ -56,7 +56,7 @@ centr_eigen(g, directed = FALSE)$centralization # Calculate centralization from pre-computed scores deg <- degree(g) -tmax <- centr_degree_tmax(g, loops = FALSE) +tmax <- centr_degree_tmax(g, loops = "none") centralize(deg, tmax) # The most centralized graph according to eigenvector centrality From d9fef1c9424616ad1a2f71587883ea7e19ab4013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 25 Oct 2025 22:09:56 +0200 Subject: [PATCH 084/154] switch_igraph_arg() --- R/utils-assert-args.R | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/R/utils-assert-args.R b/R/utils-assert-args.R index 98f63ea5240..52a3f5f06f7 100644 --- a/R/utils-assert-args.R +++ b/R/utils-assert-args.R @@ -16,6 +16,15 @@ ensure_igraph <- function(graph, optional = FALSE) { } } +switch_igraph_arg <- function( + arg, + ..., + error_call = rlang::caller_env() +) { + values <- ...names() + match <- igraph.match.arg(arg, values, error_call = error_call) + switch(match, ...) +} igraph.match.arg <- function( arg, From 59659749897ae78ecbbf06095dd4c213a1508ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 25 Oct 2025 22:31:16 +0200 Subject: [PATCH 085/154] Define switch_igraph_arg() --- tools/stimulus/types-RR.yaml | 76 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index 0b3b8d0ddb6..812dc9f4320 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -65,7 +65,7 @@ ATTRIBUTES: CONNECTEDNESS: DEFAULT: WEAK: c("weak", "strong") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "weak"=1L, "strong"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "weak" = 1L, "strong" = 2L)' NEIMODE: DEFAULT: @@ -73,7 +73,7 @@ NEIMODE: IN: c("in", "out", "all", "total") OUT: c("out", "in", "all", "total") TOTAL: c("total", "out", "in", "all") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "out"=1L, "in"=2L, "all"=3L, "total"=3L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)' TODIRECTED: DEFAULT: @@ -81,19 +81,19 @@ TODIRECTED: MUTUAL: c("mutual", "arbitrary", "random", "acyclic") RANDOM: c("random", "arbitrary", "mutual", "acyclic") ACYCLIC: c("acyclic", "arbitrary", "mutual", "random") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "arbitrary"=0L, "mutual"=1L, "random"=2L, "acyclic"=3L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "arbitrary" = 0L, "mutual" = 1L, "random" = 2L, "acyclic" = 3L)' TOUNDIRECTED: DEFAULT: COLLAPSE: c("collapse", "each", "mutual") EACH: c("each", "collapse", "mutual") MUTUAL: c("mutual", "collapse", "each") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "collapse"=1L, "each"=0L, "mutual"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "collapse" = 1L, "each" = 0L, "mutual" = 2L)' TRANSITIVITY_MODE: DEFAULT: NAN: c("nan", "zero") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "nan"=0L, "zero"=1L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "nan" = 0L, "zero" = 1L)' INT: INCONV: '%I% <- as.integer(%I%)' @@ -297,7 +297,7 @@ BLISSSH: '"fm"': c("fm", "f", "fs", "fl", "flm", "fsm") '"flm"': c("flm", "f", "fs", "fl", "fm", "fsm") '"fsm"': c("fsm", "f", "fs", "fl", "fm", "flm") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "f"=0L, "fl"=1L, "fs"=2L, "fm"=3L, "flm"=4L, "fsm"=5L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L)' BLISSINFO: {} @@ -308,12 +308,12 @@ COMMCMP: DEFAULT: VI: c("vi", "nmi", "split.join", "rand", "adjusted.rand") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "vi"=0L, "nmi"=1L, "split.join"=2L, "rand"=3L, "adjusted.rand"=4L) + %I% <- switch_igraph_arg(%I%, "vi" = 0L, "nmi" = 1L, "split.join" = 2L, "rand" = 3L, "adjusted.rand" = 4L) SUBGRAPH_IMPL: DEFAULT: AUTO: c("auto", "copy_and_delete", "create_from_scratch") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "auto"=0L, "copy_and_delete"=1L, "create_from_scratch"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "auto" = 0L, "copy_and_delete" = 1L, "create_from_scratch" = 2L)' EDGE_ATTRIBUTE_COMBINATION: DEFAULT: @@ -326,7 +326,7 @@ VERTEX_ATTRIBUTE_COMBINATION: INCONV: '%I% <- igraph.i.attribute.combination(%I%)' ADD_WEIGHTS: - INCONV: '%I% <- switch(igraph.match.arg(%I%), "no"=0L, "yes"=1L, "auto"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "no" = 0L, "yes" = 1L, "auto" = 2L)' HRG: DEFAULT: @@ -340,7 +340,7 @@ HRG: RECIP: DEFAULT: DEFAULT: c("default", "ratio") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "default"=0L, "ratio"=1L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "default" = 0L, "ratio" = 1L)' SPARSEMAT: INCONV: requireNamespace("Matrix", quietly = TRUE); %I% <- as(as(as(%I%, "dMatrix"), "generalMatrix"), "CsparseMatrix") @@ -369,9 +369,9 @@ EIGENALGO: DEFAULT: ARPACK: c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "auto"=0L, "lapack"=1L, - "arpack"=2L, "comp_auto"=3L, "comp_lapack"=4L, - "comp_arpack"=5L) + %I% <- switch_igraph_arg(%I%, "auto" = 0L, "lapack" = 1L, + "arpack" = 2L, "comp_auto" = 3L, "comp_lapack" = 4L, + "comp_arpack" = 5L) EIGENWHICH: DEFAULT: @@ -383,18 +383,18 @@ EIGENWHICH: EIGENWHICHPOS: DEFAULT: ASE: c("lm", "la", "sa") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "lm"=0L, "la"=2L, "sa"=3L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "lm" = 0L, "la" = 2L, "sa" = 3L)' LAPLACIAN_NORMALIZATION: DEFAULT: UNNORMALIZED: c("unnormalized", "symmetric", "left", "right") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "unnormalized"=0L, "symmetric"=1L, "left"=2L, "right"=3L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "unnormalized" = 0L, "symmetric" = 1L, "left" = 2L, "right" = 3L)' LOOPS: DEFAULT: ONCE: c("once", "none", "twice") TWICE: c("twice", "none", "once") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "none"=0L, "twice"=1L, "once"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "none" = 0L, "twice" = 1L, "once" = 2L)' SIRLIST: {} @@ -402,7 +402,7 @@ PAGERANKALGO: DEFAULT: PRPACK: c("prpack", "arpack") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "arpack"=1L, "prpack"=2L) + %I% <- switch_igraph_arg(%I%, "arpack" = 1L, "prpack" = 2L) PAGERANKOPT: INCONV: |- @@ -425,15 +425,15 @@ LSETYPE: DEFAULT: Default: c("default", "D-A", "DAD", "I-DAD", "OAP") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), + %I% <- switch_igraph_arg(%I%, "default"=if (is_directed(%I1%)) 3L else 0L, - "da"=0L, "d-a"=0L, "idad"=1L, "i-dad"=1L, "dad"=2L, - "oap"=3L) + "da" = 0L, "d-a" = 0L, "idad" = 1L, "i-dad" = 1L, "dad" = 2L, + "oap" = 3L) RWSTUCK: DEFAULT: RETURN: c("return", "error") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "error" = 0L, "return" = 1L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "error" = 0L, "return" = 1L)' LPA_VARIANT: DEFAULT: @@ -441,8 +441,8 @@ LPA_VARIANT: RETENTION: c("retention", "dominance", "fast") FAST: c("fast", "dominance", "retention") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), - "dominance"=0L, "retention"=1L, "fast"=2L) + %I% <- switch_igraph_arg(%I%, + "dominance" = 0L, "retention" = 1L, "fast" = 2L) EDGE_TYPE_SW: DEFAULT: @@ -451,8 +451,8 @@ EDGE_TYPE_SW: MULTI: c("multi", "simple", "loops", "all") ALL: c("all", "simple", "loops", "multi") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), - "simple"=0L, "loop"=1L, "loops"=1L, "multi"=6L, "multiple"=6L, "all"=7L) + %I% <- switch_igraph_arg(%I%, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) GRAPH_PRODUCT_TYPE: DEFAULT: @@ -462,20 +462,20 @@ GRAPH_PRODUCT_TYPE: TENSOR: c("tensor", "cartesian", "lexicographic", "strong", "modular") MODULAR: c("modular", "cartesian", "lexicographic", "strong", "tensor") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "cartesian"=0L, "lexicographic"=1L, "strong"=2L, "tensor"=3L, "modular"=4L) + %I% <- switch_igraph_arg(%I%, "cartesian" = 0L, "lexicographic" = 1L, "strong" = 2L, "tensor" = 3L, "modular" = 4L) RANDOM_TREE_METHOD: DEFAULT: PRUFER: c("prufer", "lerw") LERW: c("lerw", "prufer") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "prufer"=0L, "lerw"=1L) + %I% <- switch_igraph_arg(%I%, "prufer" = 0L, "lerw" = 1L) GREEDY_COLORING_HEURISTIC: DEFAULT: NEIGHBORS: c("colored_neighbors", "dsatur") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "colored_neighbors"=0L, "dsatur"=1L) + %I% <- switch_igraph_arg(%I%, "colored_neighbors" = 0L, "dsatur" = 1L) REALIZE_DEGSEQ_METHOD: DEFAULT: @@ -483,52 +483,52 @@ REALIZE_DEGSEQ_METHOD: LARGEST: c("largest", "smallest", "index") INDEX: c("index", "smallest", "largest") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "smallest"=0L, "largest"=1L, "index"=2L) + %I% <- switch_igraph_arg(%I%, "smallest" = 0L, "largest" = 1L, "index" = 2L) FAS_ALGORITHM: DEFAULT: EXACT_IP: c("exact_ip", "approx_eades") APPROX_EADES: c("approx_eades", "exact_ip") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "exact_ip"=0L, "approx_eades"=1L) + %I% <- switch_igraph_arg(%I%, "exact_ip" = 0L, "approx_eades" = 1L) FVS_ALGORITHM: DEFAULT: EXACT_IP: c("exact_ip") INCONV: |- - %I% <- switch(igraph.match.arg(%I%), "exact_ip"=0L) + %I% <- switch_igraph_arg(%I%, "exact_ip" = 0L) WHEEL_MODE: DEFAULT: OUT: c("out", "in", "undirected", "mutual") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "out"=0L, "in"=1L, "undirected"=2L, "mutual"=3L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "out" = 0L, "in" = 1L, "undirected" = 2L, "mutual" = 3L)' TREE_MODE: DEFAULT: OUT: c("out", "in", "undirected") UNDIRECTED: c("undirected", "out", "in") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "out"=0L, "in"=1L, "undirected"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "out" = 0L, "in" = 1L, "undirected" = 2L)' VORONOI_TIEBREAKER: DEFAULT: RANDOM: c("random", "first", "last") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "first"=0L, "last"=1L, "random"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "first" = 0L, "last" = 1L, "random" = 2L)' GETADJACENCY: DEFAULT: BOTH: c("both", "upper", "lower") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "upper"=0L, "lower"=1L, "both"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "upper" = 0L, "lower" = 1L, "both" = 2L)' OPTIMALITY: DEFAULT: MINIMUM: c("minimum", "maximum") MAXIMUM: c("maximum", "minimum") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "minimum"=0L, "maximum"=1L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "minimum" = 0L, "maximum" = 1L)' CHUNG_LU_VARIANT: DEFAULT: ORIGINAL: c("original", "maxent", "nr") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "original"=0L, "maxent"=1L, "nr"=2L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "original" = 0L, "maxent" = 1L, "nr" = 2L)' EDGE_WEIGHTS: INCONV: |- @@ -555,4 +555,4 @@ VERTEX_WEIGHTS: MSTALGORITHM: DEFAULT: AUTOMATIC: c("automatic", "unweighted", "prim", "kruskal") - INCONV: '%I% <- switch(igraph.match.arg(%I%), "automatic"=0L, "unweighted"=1L, "prim"=2L, "kruskal"=3L)' + INCONV: '%I% <- switch_igraph_arg(%I%, "automatic" = 0L, "unweighted" = 1L, "prim" = 2L, "kruskal" = 3L)' From dabf2500baa79ee7e1c7feef26c4c0e5d805d986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 25 Oct 2025 22:31:27 +0200 Subject: [PATCH 086/154] Render switch_igraph_arg() --- R/aaa-auto.R | 266 +++++++++++++++++++++++++-------------------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index e509db76cd0..a4b92c6f23a 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -66,8 +66,8 @@ neighbors_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loop if (length(vid) == 0) { stop("No vertex was specified") } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) multiple <- as.logical(multiple) on.exit( .Call(R_igraph_finalizer) ) @@ -83,8 +83,8 @@ degree_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total" # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -122,8 +122,8 @@ incident_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loops if (length(vid) == 0) { stop("No vertex was specified") } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -137,7 +137,7 @@ incident_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loops wheel_impl <- function(n, mode=c("out", "in", "undirected", "mutual"), center=0) { # Argument checks n <- as.numeric(n) - mode <- switch(igraph.match.arg(mode), "out"=0L, "in"=1L, "undirected"=2L, "mutual"=3L) + mode <- switch_igraph_arg(mode, "out" = 0L, "in" = 1L, "undirected" = 2L, "mutual" = 3L) center <- as.numeric(center) on.exit( .Call(R_igraph_finalizer) ) @@ -216,7 +216,7 @@ cycle_graph_impl <- function(n, directed=FALSE, mutual=FALSE) { symmetric_tree_impl <- function(branches, type=c("out", "in", "undirected")) { # Argument checks branches <- as.numeric(branches) - type <- switch(igraph.match.arg(type), "out"=0L, "in"=1L, "undirected"=2L) + type <- switch_igraph_arg(type, "out" = 0L, "in" = 1L, "undirected" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -229,7 +229,7 @@ regular_tree_impl <- function(h, k=3, type=c("undirected", "out", "in")) { # Argument checks h <- as.numeric(h) k <- as.numeric(k) - type <- switch(igraph.match.arg(type), "out"=0L, "in"=1L, "undirected"=2L) + type <- switch_igraph_arg(type, "out" = 0L, "in" = 1L, "undirected" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -348,7 +348,7 @@ mycielski_graph_impl <- function(k) { adjlist_impl <- function(adjlist, mode=c("out", "in", "all", "total"), duplicate=TRUE) { # Argument checks adjlist <- lapply(adjlist, function(x) as.numeric(x)-1) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) duplicate <- as.logical(duplicate) on.exit( .Call(R_igraph_finalizer) ) @@ -363,7 +363,7 @@ full_bipartite_impl <- function(n1, n2, directed=FALSE, mode=c("all", "out", "in n1 <- as.numeric(n1) n2 <- as.numeric(n2) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -378,7 +378,7 @@ full_multipartite_impl <- function(n, directed=FALSE, mode=c("all", "out", "in", # Argument checks n <- as.numeric(n) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -391,9 +391,9 @@ realize_degree_sequence_impl <- function(out.deg, in.deg=NULL, allowed.edge.type # Argument checks out.deg <- as.numeric(out.deg) if (!is.null(in.deg)) in.deg <- as.numeric(in.deg) - allowed.edge.types <- switch(igraph.match.arg(allowed.edge.types), - "simple"=0L, "loop"=1L, "loops"=1L, "multi"=6L, "multiple"=6L, "all"=7L) - method <- switch(igraph.match.arg(method), "smallest"=0L, "largest"=1L, "index"=2L) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) + method <- switch_igraph_arg(method, "smallest" = 0L, "largest" = 1L, "index" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -414,9 +414,9 @@ realize_bipartite_degree_sequence_impl <- function(degrees1, degrees2, allowed.e # Argument checks degrees1 <- as.numeric(degrees1) degrees2 <- as.numeric(degrees2) - allowed.edge.types <- switch(igraph.match.arg(allowed.edge.types), - "simple"=0L, "loop"=1L, "loops"=1L, "multi"=6L, "multiple"=6L, "all"=7L) - method <- switch(igraph.match.arg(method), "smallest"=0L, "largest"=1L, "index"=2L) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) + method <- switch_igraph_arg(method, "smallest" = 0L, "largest" = 1L, "index" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -586,7 +586,7 @@ rewire_directed_edges_impl <- function(graph, prob, loops=FALSE, mode=c("out", " ensure_igraph(graph) prob <- as.numeric(prob) loops <- as.logical(loops) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -645,7 +645,7 @@ chung_lu_game_impl <- function(out.weights, in.weights=NULL, ..., loops=TRUE, va out.weights <- as.numeric(out.weights) if (!is.null(in.weights)) in.weights <- as.numeric(in.weights) loops <- as.logical(loops) - variant <- switch(igraph.match.arg(variant), "original"=0L, "maxent"=1L, "nr"=2L) + variant <- switch_igraph_arg(variant, "original" = 0L, "maxent" = 1L, "nr" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -877,7 +877,7 @@ closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "tot # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -901,7 +901,7 @@ closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -941,7 +941,7 @@ get_shortest_path_impl <- function(graph, weights=NULL, from, to, mode=c("out", if (length(to) == 0) { stop("No vertex was specified") } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -974,7 +974,7 @@ get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, m } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1007,7 +1007,7 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode= } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1037,7 +1037,7 @@ get_all_shortest_paths_impl <- function(graph, weights=NULL, from, to, mode=c("o stop("No vertex was specified") } to <- as_igraph_vs(graph, to) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1062,7 +1062,7 @@ get_all_shortest_paths_dijkstra_impl <- function(graph, from, to=V(graph), weigh } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1084,8 +1084,8 @@ voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - tiebreaker <- switch(igraph.match.arg(tiebreaker), "first"=0L, "last"=1L, "random"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + tiebreaker <- switch_igraph_arg(tiebreaker, "first" = 0L, "last" = 1L, "random" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1104,7 +1104,7 @@ get_all_simple_paths_impl <- function(graph, from, to=V(graph), minlen=-1, maxle to <- as_igraph_vs(graph, to) minlen <- as.numeric(minlen) maxlen <- as.numeric(maxlen) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1134,7 +1134,7 @@ get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mod if (length(to) == 0) { stop("No vertex was specified") } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1162,7 +1162,7 @@ get_widest_path_impl <- function(graph, from, to, weights, mode=c("out", "in", " } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1192,7 +1192,7 @@ get_widest_paths_impl <- function(graph, from, to=V(graph), weights, mode=c("out } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1214,7 +1214,7 @@ widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph), } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1236,7 +1236,7 @@ widest_path_widths_floyd_warshall_impl <- function(graph, from=V(graph), to=V(gr } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1386,7 +1386,7 @@ harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1410,7 +1410,7 @@ harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V(graph), directed=TRUE, damping=0.85, personalized=NULL, weights=NULL, options=NULL) { # Argument checks ensure_igraph(graph) - algo <- switch(igraph.match.arg(algo), "arpack"=1L, "prpack"=2L) + algo <- switch_igraph_arg(algo, "arpack" = 1L, "prpack" = 2L) vids <- as_igraph_vs(graph, vids) directed <- as.logical(directed) damping <- as.numeric(damping) @@ -1445,7 +1445,7 @@ personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V personalized_pagerank_vs_impl <- function(graph, algo=c("prpack", "arpack"), vids=V(graph), directed=TRUE, damping=0.85, reset.vids, weights=NULL, options=NULL, details=FALSE) { # Argument checks ensure_igraph(graph) - algo <- switch(igraph.match.arg(algo), "arpack"=1L, "prpack"=2L) + algo <- switch_igraph_arg(algo, "arpack" = 1L, "prpack" = 2L) vids <- as_igraph_vs(graph, vids) directed <- as.logical(directed) damping <- as.numeric(damping) @@ -1484,7 +1484,7 @@ induced_subgraph_impl <- function(graph, vids, impl=c("auto", "copy_and_delete", # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - impl <- switch(igraph.match.arg(impl), "auto"=0L, "copy_and_delete"=1L, "create_from_scratch"=2L) + impl <- switch_igraph_arg(impl, "auto" = 0L, "copy_and_delete" = 1L, "create_from_scratch" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1570,7 +1570,7 @@ simplify_impl <- function(graph, remove.multiple=TRUE, remove.loops=TRUE, edge.a transitivity_undirected_impl <- function(graph, mode=c("nan", "zero")) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "nan"=0L, "zero"=1L) + mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1583,7 +1583,7 @@ transitivity_local_undirected_impl <- function(graph, vids=V(graph), mode=c("nan # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "nan"=0L, "zero"=1L) + mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1595,7 +1595,7 @@ transitivity_local_undirected_impl <- function(graph, vids=V(graph), mode=c("nan transitivity_avglocal_undirected_impl <- function(graph, mode=c("nan", "zero")) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "nan"=0L, "zero"=1L) + mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1616,7 +1616,7 @@ transitivity_barrat_impl <- function(graph, vids=V(graph), weights=NULL, mode=c( } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "nan"=0L, "zero"=1L) + mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1644,7 +1644,7 @@ reciprocity_impl <- function(graph, ignore.loops=TRUE, mode=c("default", "ratio" # Argument checks ensure_igraph(graph) ignore.loops <- as.logical(ignore.loops) - mode <- switch(igraph.match.arg(mode), "default"=0L, "ratio"=1L) + mode <- switch_igraph_arg(mode, "default" = 0L, "ratio" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1658,8 +1658,8 @@ maxdegree_impl <- function(graph, ..., v=V(graph), mode=c("all", "out", "in", "t check_dots_empty() ensure_igraph(graph) v <- as_igraph_vs(graph, v) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1703,7 +1703,7 @@ feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "e } else { weights <- NULL } - algo <- switch(igraph.match.arg(algo), "exact_ip"=0L, "approx_eades"=1L) + algo <- switch_igraph_arg(algo, "exact_ip" = 0L, "approx_eades" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1725,7 +1725,7 @@ feedback_vertex_set_impl <- function(graph, weights=NULL, algo=c("exact_ip")) { } else { weights <- NULL } - algo <- switch(igraph.match.arg(algo), "exact_ip"=0L) + algo <- switch_igraph_arg(algo, "exact_ip" = 0L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -1853,7 +1853,7 @@ is_perfect_impl <- function(graph) { eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total"), weights=NULL, options=arpack_defaults()) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1901,7 +1901,7 @@ hub_and_authority_scores_impl <- function(graph, weights=NULL, options=arpack_de unfold_tree_impl <- function(graph, mode=c("all", "out", "in", "total"), roots) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) roots <- as.numeric(roots) on.exit( .Call(R_igraph_finalizer) ) @@ -1953,8 +1953,8 @@ avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all", # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - neighbor.degree.mode <- switch(igraph.match.arg(neighbor.degree.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + neighbor.degree.mode <- switch_igraph_arg(neighbor.degree.mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1984,8 +1984,8 @@ degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out } else { weights <- NULL } - from.mode <- switch(igraph.match.arg(from.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - to.mode <- switch(igraph.match.arg(to.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + from.mode <- switch_igraph_arg(from.mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + to.mode <- switch_igraph_arg(to.mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) directed.neighbors <- as.logical(directed.neighbors) on.exit( .Call(R_igraph_finalizer) ) @@ -2022,8 +2022,8 @@ strength_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "tota # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -2059,8 +2059,8 @@ centralization_impl <- function(scores, theoretical.max=0, normalized=TRUE) { centralization_degree_impl <- function(graph, mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once"), normalized=TRUE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) @@ -2074,8 +2074,8 @@ centralization_degree_tmax_impl <- function(graph=NULL, nodes=0, mode=c("all", " # Argument checks if (!is.null(graph)) ensure_igraph(graph) nodes <- as.numeric(nodes) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2113,7 +2113,7 @@ centralization_betweenness_tmax_impl <- function(graph=NULL, nodes=0, directed=T centralization_closeness_impl <- function(graph, mode=c("out", "in", "all", "total"), normalized=TRUE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) @@ -2127,7 +2127,7 @@ centralization_closeness_tmax_impl <- function(graph=NULL, nodes=0, mode=c("out" # Argument checks if (!is.null(graph)) ensure_igraph(graph) nodes <- as.numeric(nodes) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2139,7 +2139,7 @@ centralization_closeness_tmax_impl <- function(graph=NULL, nodes=0, mode=c("out" centralization_eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total"), options=arpack_defaults(), normalized=TRUE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) options <- modify_list(arpack_defaults(), options) normalized <- as.logical(normalized) @@ -2154,7 +2154,7 @@ centralization_eigenvector_centrality_tmax_impl <- function(graph=NULL, nodes=0, # Argument checks if (!is.null(graph)) ensure_igraph(graph) nodes <- as.numeric(nodes) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2236,8 +2236,8 @@ joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out } else { weights <- NULL } - from.mode <- switch(igraph.match.arg(from.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - to.mode <- switch(igraph.match.arg(to.mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + from.mode <- switch_igraph_arg(from.mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + to.mode <- switch_igraph_arg(to.mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) directed.neighbors <- as.logical(directed.neighbors) normalized <- as.logical(normalized) max.from.degree <- as.numeric(max.from.degree) @@ -2298,7 +2298,7 @@ eccentricity_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all", weights <- NULL } vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2320,7 +2320,7 @@ graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "t } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2342,7 +2342,7 @@ radius_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total") } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2413,9 +2413,9 @@ random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "i if (length(start) == 0) { stop("No vertex was specified") } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) steps <- as.numeric(steps) - stuck <- switch(igraph.match.arg(stuck), "error" = 0L, "return" = 1L) + stuck <- switch_igraph_arg(stuck, "error" = 0L, "return" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2462,7 +2462,7 @@ local_efficiency_impl <- function(graph, weights=NULL, vids=V(graph), directed=T } vids <- as_igraph_vs(graph, vids) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2485,7 +2485,7 @@ average_local_efficiency_impl <- function(graph, weights=NULL, directed=TRUE, mo weights <- NULL } directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2520,8 +2520,8 @@ is_graphical_impl <- function(out.deg, in.deg=NULL, allowed.edge.types=c("simple # Argument checks out.deg <- as.numeric(out.deg) if (!is.null(in.deg)) in.deg <- as.numeric(in.deg) - allowed.edge.types <- switch(igraph.match.arg(allowed.edge.types), - "simple"=0L, "loop"=1L, "loops"=1L, "multi"=6L, "multiple"=6L, "all"=7L) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2537,7 +2537,7 @@ bfs_simple_impl <- function(graph, root, mode=c("out", "in", "all", "total")) { if (length(root) == 0) { stop("No vertex was specified") } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2577,7 +2577,7 @@ biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", "out", " # Argument checks biadjmatrix[] <- as.numeric(biadjmatrix) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) multiple <- as.logical(multiple) on.exit( .Call(R_igraph_finalizer) ) @@ -2593,7 +2593,7 @@ weighted_biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", # Argument checks biadjmatrix[] <- as.numeric(biadjmatrix) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2643,7 +2643,7 @@ bipartite_game_gnp_impl <- function(n1, n2, p, directed=FALSE, mode=c("all", "ou n2 <- as.numeric(n2) p <- as.numeric(p) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2658,7 +2658,7 @@ bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou n2 <- as.numeric(n2) m <- as.numeric(m) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) multiple <- as.logical(multiple) on.exit( .Call(R_igraph_finalizer) ) @@ -2676,7 +2676,7 @@ bipartite_iea_game_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou n2 <- as.numeric(n2) m <- as.numeric(m) directed <- as.logical(directed) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2690,8 +2690,8 @@ bipartite_iea_game_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou get_laplacian_impl <- function(graph, mode=c("out", "in", "all", "total"), normalization=c("unnormalized", "symmetric", "left", "right"), weights=NULL) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - normalization <- switch(igraph.match.arg(normalization), "unnormalized"=0L, "symmetric"=1L, "left"=2L, "right"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + normalization <- switch_igraph_arg(normalization, "unnormalized" = 0L, "symmetric" = 1L, "left" = 2L, "right" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -2711,8 +2711,8 @@ get_laplacian_impl <- function(graph, mode=c("out", "in", "all", "total"), norma get_laplacian_sparse_impl <- function(graph, mode=c("out", "in", "all", "total"), normalization=c("unnormalized", "symmetric", "left", "right"), weights=NULL) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) - normalization <- switch(igraph.match.arg(normalization), "unnormalized"=0L, "symmetric"=1L, "left"=2L, "right"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + normalization <- switch_igraph_arg(normalization, "unnormalized" = 0L, "symmetric" = 1L, "left" = 2L, "right" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -2732,7 +2732,7 @@ get_laplacian_sparse_impl <- function(graph, mode=c("out", "in", "all", "total") connected_components_impl <- function(graph, mode=c("weak", "strong"), details=FALSE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "weak"=1L, "strong"=2L) + mode <- switch_igraph_arg(mode, "weak" = 1L, "strong" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2746,7 +2746,7 @@ connected_components_impl <- function(graph, mode=c("weak", "strong"), details=F is_connected_impl <- function(graph, mode=c("weak", "strong")) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "weak"=1L, "strong"=2L) + mode <- switch_igraph_arg(mode, "weak" = 1L, "strong" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -2808,7 +2808,7 @@ is_biconnected_impl <- function(graph) { count_reachable_impl <- function(graph, mode) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3065,7 +3065,7 @@ layout_grid_3d_impl <- function(graph, width=0, height=0) { roots_for_tree_layout_impl <- function(graph, mode=c("out", "in", "all", "total"), heuristic) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3295,7 +3295,7 @@ similarity_dice_impl <- function(graph, vit.from=V(graph), vit.to=V(graph), mode ensure_igraph(graph) 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) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) @@ -3309,7 +3309,7 @@ similarity_dice_es_impl <- function(graph, es=E(graph), mode=c("all", "out", "in # Argument checks ensure_igraph(graph) es <- as_igraph_es(graph, es) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) @@ -3322,7 +3322,7 @@ similarity_dice_es_impl <- function(graph, es=E(graph), mode=c("all", "out", "in similarity_dice_pairs_impl <- function(graph, pairs, mode=c("all", "out", "in", "total"), loops=FALSE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) @@ -3336,7 +3336,7 @@ similarity_inverse_log_weighted_impl <- function(graph, vids=V(graph), mode=c("a # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3350,7 +3350,7 @@ similarity_jaccard_impl <- function(graph, vit.from=V(graph), vit.to=V(graph), m ensure_igraph(graph) 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) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) @@ -3364,7 +3364,7 @@ similarity_jaccard_es_impl <- function(graph, es=E(graph), mode=c("all", "out", # Argument checks ensure_igraph(graph) es <- as_igraph_es(graph, es) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) @@ -3377,7 +3377,7 @@ similarity_jaccard_es_impl <- function(graph, es=E(graph), mode=c("all", "out", similarity_jaccard_pairs_impl <- function(graph, pairs, mode=c("all", "out", "in", "total"), loops=FALSE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) @@ -3391,7 +3391,7 @@ compare_communities_impl <- function(comm1, comm2, method=c("vi", "nmi", "split. # Argument checks comm1 <- as.numeric(comm1) comm2 <- as.numeric(comm2) - method <- switch(igraph.match.arg(method), "vi"=0L, "nmi"=1L, "split.join"=2L, "rand"=3L, "adjusted.rand"=4L) + method <- switch_igraph_arg(method, "vi" = 0L, "nmi" = 1L, "split.join" = 2L, "rand" = 3L, "adjusted.rand" = 4L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3458,7 +3458,7 @@ community_fluid_communities_impl <- function(graph, no.of.communities) { community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", "total"), weights=NULL, initial=NULL, fixed=NULL, lpa.variant) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -3469,8 +3469,8 @@ community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", " } if (!is.null(initial)) initial <- as.numeric(initial)-1 if (!is.null(fixed)) fixed <- as.logical(fixed) - lpa.variant <- switch(igraph.match.arg(lpa.variant), - "dominance"=0L, "retention"=1L, "fast"=2L) + lpa.variant <- switch_igraph_arg(lpa.variant, + "dominance" = 0L, "retention" = 1L, "fast" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3780,7 +3780,7 @@ from_hrg_dendrogram_impl <- function(hrg) { get_adjacency_sparse_impl <- function(graph, type=c("both", "upper", "lower"), weights=NULL, loops=c("once", "none", "twice")) { # Argument checks ensure_igraph(graph) - type <- switch(igraph.match.arg(type), "upper"=0L, "lower"=1L, "both"=2L) + type <- switch_igraph_arg(type, "upper" = 0L, "lower" = 1L, "both" = 2L) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -3789,7 +3789,7 @@ get_adjacency_sparse_impl <- function(graph, type=c("both", "upper", "lower"), w } else { weights <- NULL } - loops <- switch(igraph.match.arg(loops), "none"=0L, "twice"=1L, "once"=2L) + loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3841,7 +3841,7 @@ get_stochastic_sparse_impl <- function(graph, column.wise=FALSE, weights=NULL) { to_directed_impl <- function(graph, mode=c("mutual", "arbitrary", "random", "acyclic")) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "arbitrary"=0L, "mutual"=1L, "random"=2L, "acyclic"=3L) + mode <- switch_igraph_arg(mode, "arbitrary" = 0L, "mutual" = 1L, "random" = 2L, "acyclic" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3853,7 +3853,7 @@ to_directed_impl <- function(graph, mode=c("mutual", "arbitrary", "random", "acy to_undirected_impl <- function(graph, mode=c("collapse", "each", "mutual"), edge.attr.comb=igraph_opt("edge.attr.comb")) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "collapse"=1L, "each"=0L, "mutual"=2L) + mode <- switch_igraph_arg(mode, "collapse" = 1L, "each" = 0L, "mutual" = 2L) edge.attr.comb <- igraph.i.attribute.combination(edge.attr.comb) on.exit( .Call(R_igraph_finalizer) ) @@ -3960,7 +3960,7 @@ local_scan_0_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "t } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3981,7 +3981,7 @@ local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "i } else { weights.them <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4001,7 +4001,7 @@ local_scan_1_ecount_impl <- function(graph, weights=NULL, mode=c("out", "in", "a } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4022,7 +4022,7 @@ local_scan_1_ecount_them_impl <- function(us, them, weights.them=NULL, mode=c("o } else { weights.them <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4043,7 +4043,7 @@ local_scan_k_ecount_impl <- function(graph, k, weights=NULL, mode=c("out", "in", } else { weights <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4065,7 +4065,7 @@ local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c } else { weights.them <- NULL } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4141,7 +4141,7 @@ induced_subgraph_map_impl <- function(graph, vids, impl) { # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) - impl <- switch(igraph.match.arg(impl), "auto"=0L, "copy_and_delete"=1L, "create_from_scratch"=2L) + impl <- switch_igraph_arg(impl, "auto" = 0L, "copy_and_delete" = 1L, "create_from_scratch" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4166,7 +4166,7 @@ product_impl <- function(g1, g2, type=c("cartesian", "lexicographic", "strong", # Argument checks ensure_igraph(g1) ensure_igraph(g2) - type <- switch(igraph.match.arg(type), "cartesian"=0L, "lexicographic"=1L, "strong"=2L, "tensor"=3L, "modular"=4L) + type <- switch_igraph_arg(type, "cartesian" = 0L, "lexicographic" = 1L, "strong" = 2L, "tensor" = 3L, "modular" = 4L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4327,7 +4327,7 @@ dominator_tree_impl <- function(graph, root, mode=c("out", "in", "all", "total") if (length(root) == 0) { stop("No vertex was specified") } - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4941,7 +4941,7 @@ canonical_permutation_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", if (!is.null(colors)) { colors <- as.numeric(colors)-1 } - sh <- switch(igraph.match.arg(sh), "f"=0L, "fl"=1L, "fs"=2L, "fm"=3L, "flm"=4L, "fsm"=5L) + sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4986,7 +4986,7 @@ isomorphic_bliss_impl <- function(graph1, graph2, colors1=NULL, colors2=NULL, sh if (!is.null(colors2)) { colors2 <- as.numeric(colors2)-1 } - sh <- switch(igraph.match.arg(sh), "f"=0L, "fl"=1L, "fs"=2L, "fm"=3L, "flm"=4L, "fsm"=5L) + sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5008,7 +5008,7 @@ count_automorphisms_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", " if (!is.null(colors)) { colors <- as.numeric(colors)-1 } - sh <- switch(igraph.match.arg(sh), "f"=0L, "fl"=1L, "fs"=2L, "fm"=3L, "flm"=4L, "fsm"=5L) + sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5030,7 +5030,7 @@ automorphism_group_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", "f if (!is.null(colors)) { colors <- as.numeric(colors)-1 } - sh <- switch(igraph.match.arg(sh), "f"=0L, "fl"=1L, "fs"=2L, "fm"=3L, "flm"=4L, "fsm"=5L) + sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5123,7 +5123,7 @@ adjacency_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" } else { weights <- NULL } - which <- switch(igraph.match.arg(which), "lm"=0L, "la"=2L, "sa"=3L) + which <- switch_igraph_arg(which, "lm" = 0L, "la" = 2L, "sa" = 3L) scaled <- as.logical(scaled) cvec <- as.numeric(cvec) options <- modify_list(arpack_defaults(), options) @@ -5147,11 +5147,11 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" } else { weights <- NULL } - which <- switch(igraph.match.arg(which), "lm"=0L, "la"=2L, "sa"=3L) - type <- switch(igraph.match.arg(type), + which <- switch_igraph_arg(which, "lm" = 0L, "la" = 2L, "sa" = 3L) + type <- switch_igraph_arg(type, "default"=if (is_directed(graph)) 3L else 0L, - "da"=0L, "d-a"=0L, "idad"=1L, "i-dad"=1L, "dad"=2L, - "oap"=3L) + "da" = 0L, "d-a" = 0L, "idad" = 1L, "i-dad" = 1L, "dad" = 2L, + "oap" = 3L) scaled <- as.logical(scaled) options <- modify_list(arpack_defaults(), options) @@ -5165,9 +5165,9 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c(" eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack"), which=list(), options=arpack_defaults(), storage) { # Argument checks ensure_igraph(graph) - algorithm <- switch(igraph.match.arg(algorithm), "auto"=0L, "lapack"=1L, - "arpack"=2L, "comp_auto"=3L, "comp_lapack"=4L, - "comp_arpack"=5L) + algorithm <- switch_igraph_arg(algorithm, "auto" = 0L, "lapack" = 1L, + "arpack" = 2L, "comp_auto" = 3L, "comp_lapack" = 4L, + "comp_arpack" = 5L) which.tmp <- eigen_defaults(); which.tmp[ names(which) ] <- which ; which <- which.tmp options <- modify_list(arpack_defaults(), options) @@ -5244,7 +5244,7 @@ solve_lsap_impl <- function(c, n) { find_cycle_impl <- function(graph, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5261,7 +5261,7 @@ find_cycle_impl <- function(graph, mode=c("out", "in", "all", "total")) { simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), min.cycle.length=-1, max.cycle.length=-1) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) min.cycle.length <- as.numeric(min.cycle.length) max.cycle.length <- as.numeric(max.cycle.length) @@ -5364,7 +5364,7 @@ minimum_cycle_basis_impl <- function(graph, bfs.cutoff=-1, complete=TRUE, use.cy is_tree_impl <- function(graph, mode=c("out", "in", "all", "total"), details=FALSE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5381,7 +5381,7 @@ is_tree_impl <- function(graph, mode=c("out", "in", "all", "total"), details=FAL is_forest_impl <- function(graph, mode=c("out", "in", "all", "total"), details=FALSE) { # Argument checks ensure_igraph(graph) - mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5425,7 +5425,7 @@ to_prufer_impl <- function(graph) { tree_from_parent_vector_impl <- function(parents, type=c("out", "in", "undirected")) { # Argument checks parents <- as.numeric(parents)-1 - type <- switch(igraph.match.arg(type), "out"=0L, "in"=1L, "undirected"=2L) + type <- switch_igraph_arg(type, "out" = 0L, "in" = 1L, "undirected" = 2L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5456,7 +5456,7 @@ minimum_spanning_tree_impl <- function(graph, weights=NULL, method=c("automatic" } else { weights <- NULL } - method <- switch(igraph.match.arg(method), "automatic"=0L, "unweighted"=1L, "prim"=2L, "kruskal"=3L) + method <- switch_igraph_arg(method, "automatic" = 0L, "unweighted" = 1L, "prim" = 2L, "kruskal" = 3L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5488,7 +5488,7 @@ tree_game_impl <- function(n, directed=FALSE, method=c("lerw", "prufer")) { # Argument checks n <- as.numeric(n) directed <- as.logical(directed) - method <- switch(igraph.match.arg(method), "prufer"=0L, "lerw"=1L) + method <- switch_igraph_arg(method, "prufer" = 0L, "lerw" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -5514,7 +5514,7 @@ nearest_neighbor_graph_impl <- function(points, metric, neighbors, cutoff, direc vertex_coloring_greedy_impl <- function(graph, heuristic=c("colored_neighbors", "dsatur")) { # Argument checks ensure_igraph(graph) - heuristic <- switch(igraph.match.arg(heuristic), "colored_neighbors"=0L, "dsatur"=1L) + heuristic <- switch_igraph_arg(heuristic, "colored_neighbors" = 0L, "dsatur" = 1L) on.exit( .Call(R_igraph_finalizer) ) # Function call From 6833709ac5eba0adf791ae1409c93d432526e177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 24 Oct 2025 07:45:07 +0200 Subject: [PATCH 087/154] vendor: Update vendored sources to igraph/igraph@2d1bce327e4e9229fdfa9d18a000d3a21e2ac1a5 --- R/aaa-auto.R | 389 +- src/cpp11.cpp | 96 +- src/rinterface.c | 781 ++- src/sources-igraph.mk | 2 +- src/vendor/cigraph/.all-contributorsrc | 45 + src/vendor/cigraph/.gitignore | 1 + src/vendor/cigraph/ACKNOWLEDGEMENTS.md | 32 +- src/vendor/cigraph/CHANGELOG.md | 2355 +++---- src/vendor/cigraph/CONTRIBUTING.md | 26 +- src/vendor/cigraph/CONTRIBUTORS.md | 7 + src/vendor/cigraph/CONTRIBUTORS.txt | 5 + src/vendor/cigraph/README.md | 6 +- src/vendor/cigraph/VERSIONING.md | 58 + src/vendor/cigraph/azure-pipelines.yml | 27 +- src/vendor/cigraph/etc/cmake/packaging.cmake | 2 +- src/vendor/cigraph/etc/cmake/summary.cmake | 13 +- src/vendor/cigraph/include/igraph.h | 2 +- src/vendor/cigraph/include/igraph_adjlist.h | 42 +- src/vendor/cigraph/include/igraph_arpack.h | 8 +- .../cigraph/include/igraph_attributes.h | 32 +- src/vendor/cigraph/include/igraph_bipartite.h | 45 +- src/vendor/cigraph/include/igraph_bitset.h | 38 +- .../cigraph/include/igraph_bitset_list.h | 2 +- src/vendor/cigraph/include/igraph_blas.h | 2 +- .../cigraph/include/igraph_centrality.h | 109 +- src/vendor/cigraph/include/igraph_cliques.h | 132 +- .../cigraph/include/igraph_cocitation.h | 2 +- .../cigraph/include/igraph_cohesive_blocks.h | 2 +- src/vendor/cigraph/include/igraph_coloring.h | 2 +- src/vendor/cigraph/include/igraph_community.h | 56 +- src/vendor/cigraph/include/igraph_complex.h | 2 +- .../cigraph/include/igraph_components.h | 14 +- src/vendor/cigraph/include/igraph_config.h.in | 2 +- src/vendor/cigraph/include/igraph_constants.h | 78 +- .../cigraph/include/igraph_constructors.h | 55 +- .../cigraph/include/igraph_conversion.h | 2 +- src/vendor/cigraph/include/igraph_cycles.h | 43 +- src/vendor/cigraph/include/igraph_datatype.h | 4 +- src/vendor/cigraph/include/igraph_decls.h | 11 +- src/vendor/cigraph/include/igraph_dqueue.h | 2 +- .../cigraph/include/igraph_dqueue_pmt.h | 8 +- src/vendor/cigraph/include/igraph_eigen.h | 46 +- src/vendor/cigraph/include/igraph_embedding.h | 8 +- src/vendor/cigraph/include/igraph_epidemics.h | 4 +- src/vendor/cigraph/include/igraph_error.h | 6 +- src/vendor/cigraph/include/igraph_eulerian.h | 2 +- src/vendor/cigraph/include/igraph_flow.h | 54 +- src/vendor/cigraph/include/igraph_foreign.h | 12 +- src/vendor/cigraph/include/igraph_games.h | 145 +- .../cigraph/include/igraph_graph_list.h | 2 +- .../cigraph/include/igraph_graphicality.h | 20 +- src/vendor/cigraph/include/igraph_graphlets.h | 6 +- src/vendor/cigraph/include/igraph_heap.h | 2 +- src/vendor/cigraph/include/igraph_heap_pmt.h | 10 +- src/vendor/cigraph/include/igraph_hrg.h | 19 +- src/vendor/cigraph/include/igraph_interface.h | 34 +- src/vendor/cigraph/include/igraph_interrupt.h | 2 +- .../cigraph/include/igraph_isomorphism.h | 23 +- src/vendor/cigraph/include/igraph_iterators.h | 68 +- src/vendor/cigraph/include/igraph_lapack.h | 2 +- src/vendor/cigraph/include/igraph_layout.h | 65 +- src/vendor/cigraph/include/igraph_lsap.h | 4 +- src/vendor/cigraph/include/igraph_matching.h | 4 +- src/vendor/cigraph/include/igraph_matrix.h | 2 +- .../cigraph/include/igraph_matrix_list.h | 2 +- .../cigraph/include/igraph_matrix_pmt.h | 74 +- src/vendor/cigraph/include/igraph_memory.h | 2 +- src/vendor/cigraph/include/igraph_mixing.h | 27 +- src/vendor/cigraph/include/igraph_motifs.h | 18 +- .../cigraph/include/igraph_neighborhood.h | 14 +- src/vendor/cigraph/include/igraph_nongraph.h | 11 +- src/vendor/cigraph/include/igraph_operators.h | 38 +- src/vendor/cigraph/include/igraph_paths.h | 65 +- src/vendor/cigraph/include/igraph_pmt.h | 4 +- src/vendor/cigraph/include/igraph_pmt_off.h | 2 +- src/vendor/cigraph/include/igraph_progress.h | 2 +- src/vendor/cigraph/include/igraph_psumtree.h | 16 +- src/vendor/cigraph/include/igraph_qsort.h | 2 +- src/vendor/cigraph/include/igraph_random.h | 17 +- .../cigraph/include/igraph_reachability.h | 4 +- src/vendor/cigraph/include/igraph_sampling.h | 8 +- src/vendor/cigraph/include/igraph_scan.h | 6 +- .../cigraph/include/igraph_separators.h | 3 +- src/vendor/cigraph/include/igraph_setup.h | 2 +- src/vendor/cigraph/include/igraph_sparsemat.h | 62 +- src/vendor/cigraph/include/igraph_spatial.h | 46 +- src/vendor/cigraph/include/igraph_stack.h | 2 +- src/vendor/cigraph/include/igraph_stack_pmt.h | 10 +- src/vendor/cigraph/include/igraph_statusbar.h | 2 +- .../cigraph/include/igraph_structural.h | 30 +- src/vendor/cigraph/include/igraph_strvector.h | 24 +- .../cigraph/include/igraph_threading.h.in | 2 +- .../cigraph/include/igraph_transitivity.h | 4 +- .../cigraph/include/igraph_typed_list_pmt.h | 34 +- src/vendor/cigraph/include/igraph_types.h | 12 +- src/vendor/cigraph/include/igraph_vector.h | 8 +- .../cigraph/include/igraph_vector_list.h | 2 +- .../cigraph/include/igraph_vector_pmt.h | 65 +- .../cigraph/include/igraph_vector_ptr.h | 25 +- .../cigraph/include/igraph_vector_type.h | 2 +- .../cigraph/include/igraph_version.h.in | 4 +- src/vendor/cigraph/include/igraph_visitor.h | 22 +- src/vendor/cigraph/interfaces/functions.yaml | 285 +- src/vendor/cigraph/interfaces/types.yaml | 24 +- src/vendor/cigraph/src/CMakeLists.txt | 18 +- .../cigraph/src/centrality/betweenness.c | 463 +- .../src/centrality/centrality_internal.h | 2 +- .../cigraph/src/centrality/centrality_other.c | 10 +- .../cigraph/src/centrality/centralization.c | 14 +- src/vendor/cigraph/src/centrality/closeness.c | 80 +- src/vendor/cigraph/src/centrality/coreness.c | 42 +- .../cigraph/src/centrality/eigenvector.c | 38 +- .../cigraph/src/centrality/hub_authority.c | 44 +- src/vendor/cigraph/src/centrality/pagerank.c | 146 +- src/vendor/cigraph/src/centrality/prpack.cpp | 6 +- .../centrality/prpack/prpack_igraph_graph.cpp | 6 +- .../cigraph/src/centrality/prpack_internal.h | 2 +- src/vendor/cigraph/src/centrality/truss.cpp | 34 +- .../cigraph/src/cliques/cliquer/cliquer.c | 42 +- .../cigraph/src/cliques/cliquer_internal.h | 12 +- .../cigraph/src/cliques/cliquer_wrapper.c | 59 +- src/vendor/cigraph/src/cliques/cliques.c | 234 +- src/vendor/cigraph/src/cliques/glet.c | 140 +- .../cigraph/src/cliques/maximal_cliques.c | 278 +- .../src/cliques/maximal_cliques_template.h | 90 +- .../src/community/community_internal.h | 34 + .../cigraph/src/community/community_misc.c | 183 +- .../cigraph/src/community/edge_betweenness.c | 114 +- .../cigraph/src/community/fast_modularity.c | 92 +- src/vendor/cigraph/src/community/fluid.c | 10 +- src/vendor/cigraph/src/community/infomap.cpp | 55 +- .../cigraph/src/community/label_propagation.c | 40 +- .../src/community/leading_eigenvector.c | 132 +- src/vendor/cigraph/src/community/leiden.c | 408 +- src/vendor/cigraph/src/community/louvain.c | 96 +- src/vendor/cigraph/src/community/modularity.c | 88 +- .../src/community/optimal_modularity.c | 12 +- .../src/community/spinglass/NetDataTypes.cpp | 8 +- .../src/community/spinglass/NetDataTypes.h | 88 +- .../src/community/spinglass/NetRoutines.cpp | 14 +- .../src/community/spinglass/NetRoutines.h | 2 +- .../src/community/spinglass/clustertool.cpp | 24 +- .../src/community/spinglass/pottsmodel_2.cpp | 172 +- .../src/community/spinglass/pottsmodel_2.h | 36 +- src/vendor/cigraph/src/community/voronoi.c | 50 +- .../src/community/walktrap/walktrap.cpp | 12 +- .../walktrap/walktrap_communities.cpp | 2 +- .../community/walktrap/walktrap_communities.h | 4 +- .../src/community/walktrap/walktrap_graph.cpp | 8 +- .../src/community/walktrap/walktrap_graph.h | 2 +- .../src/community/walktrap/walktrap_heap.cpp | 2 +- .../src/community/walktrap/walktrap_heap.h | 2 +- .../src/connectivity/cohesive_blocks.c | 68 +- .../cigraph/src/connectivity/components.c | 194 +- .../cigraph/src/connectivity/percolation.c | 56 +- .../cigraph/src/connectivity/reachability.c | 46 +- .../cigraph/src/connectivity/separators.c | 108 +- .../cigraph/src/constructors/adjacency.c | 200 +- .../cigraph/src/constructors/atlas-edges.h | 6 +- src/vendor/cigraph/src/constructors/atlas.c | 16 +- .../src/constructors/basic_constructors.c | 18 +- .../cigraph/src/constructors/circulant.c | 14 +- .../cigraph/src/constructors/de_bruijn.c | 16 +- src/vendor/cigraph/src/constructors/famous.c | 74 +- src/vendor/cigraph/src/constructors/full.c | 74 +- .../src/constructors/generalized_petersen.c | 20 +- src/vendor/cigraph/src/constructors/kautz.c | 30 +- .../cigraph/src/constructors/lattices.c | 92 +- src/vendor/cigraph/src/constructors/lcf.c | 28 +- .../cigraph/src/constructors/linegraph.c | 32 +- .../cigraph/src/constructors/mycielskian.c | 38 +- src/vendor/cigraph/src/constructors/prufer.c | 14 +- src/vendor/cigraph/src/constructors/regular.c | 106 +- src/vendor/cigraph/src/constructors/trees.c | 12 +- src/vendor/cigraph/src/core/bitset.c | 162 +- src/vendor/cigraph/src/core/bitset_list.c | 2 +- src/vendor/cigraph/src/core/buckets.c | 46 +- src/vendor/cigraph/src/core/buckets.h | 34 +- src/vendor/cigraph/src/core/cutheap.c | 34 +- src/vendor/cigraph/src/core/cutheap.h | 16 +- src/vendor/cigraph/src/core/dqueue.c | 2 +- src/vendor/cigraph/src/core/dqueue.pmt | 12 +- src/vendor/cigraph/src/core/error.c | 4 +- src/vendor/cigraph/src/core/estack.c | 16 +- src/vendor/cigraph/src/core/estack.h | 12 +- .../cigraph/src/core/fixed_vectorlist.c | 6 +- .../cigraph/src/core/fixed_vectorlist.h | 6 +- src/vendor/cigraph/src/core/genheap.c | 44 +- src/vendor/cigraph/src/core/genheap.h | 22 +- src/vendor/cigraph/src/core/grid.c | 38 +- src/vendor/cigraph/src/core/grid.h | 26 +- src/vendor/cigraph/src/core/heap.c | 2 +- src/vendor/cigraph/src/core/heap.pmt | 32 +- src/vendor/cigraph/src/core/indheap.c | 160 +- src/vendor/cigraph/src/core/indheap.h | 54 +- src/vendor/cigraph/src/core/interruption.c | 2 +- src/vendor/cigraph/src/core/interruption.h | 4 +- src/vendor/cigraph/src/core/marked_queue.c | 18 +- src/vendor/cigraph/src/core/marked_queue.h | 14 +- src/vendor/cigraph/src/core/math.h | 2 +- src/vendor/cigraph/src/core/matrix.c | 34 +- src/vendor/cigraph/src/core/matrix.pmt | 324 +- src/vendor/cigraph/src/core/matrix_list.c | 2 +- src/vendor/cigraph/src/core/memory.c | 2 +- src/vendor/cigraph/src/core/printing.c | 2 +- src/vendor/cigraph/src/core/progress.c | 2 +- src/vendor/cigraph/src/core/psumtree.c | 18 +- src/vendor/cigraph/src/core/set.c | 36 +- src/vendor/cigraph/src/core/set.h | 22 +- src/vendor/cigraph/src/core/setup.c | 3 +- src/vendor/cigraph/src/core/sparsemat.c | 231 +- src/vendor/cigraph/src/core/stack.c | 2 +- src/vendor/cigraph/src/core/stack.pmt | 20 +- src/vendor/cigraph/src/core/statusbar.c | 2 +- src/vendor/cigraph/src/core/strvector.c | 76 +- src/vendor/cigraph/src/core/trie.c | 26 +- src/vendor/cigraph/src/core/trie.h | 16 +- src/vendor/cigraph/src/core/typed_list.pmt | 70 +- src/vendor/cigraph/src/core/vector.c | 76 +- src/vendor/cigraph/src/core/vector.pmt | 407 +- src/vendor/cigraph/src/core/vector_list.c | 2 +- src/vendor/cigraph/src/core/vector_ptr.c | 64 +- .../src/{misc => cycles}/cycle_bases.c | 106 +- .../feedback_sets.c} | 136 +- .../feedback_sets.h} | 8 +- .../src/{misc => cycles}/order_cycle.cpp | 32 +- .../src/{misc => cycles}/order_cycle.h | 2 +- src/vendor/cigraph/src/cycles/simple_cycles.c | 93 +- src/vendor/cigraph/src/f2c.h | 2 +- src/vendor/cigraph/src/flow/flow.c | 332 +- src/vendor/cigraph/src/flow/flow_conversion.c | 10 +- src/vendor/cigraph/src/flow/flow_internal.h | 6 +- src/vendor/cigraph/src/flow/st-cuts.c | 286 +- src/vendor/cigraph/src/games/barabasi.c | 118 +- .../cigraph/src/games/callaway_traits.c | 18 +- src/vendor/cigraph/src/games/chung_lu.c | 12 +- src/vendor/cigraph/src/games/citations.c | 62 +- src/vendor/cigraph/src/games/correlated.c | 107 +- .../cigraph/src/games/degree_sequence.c | 112 +- .../degree_sequence_vl/degree_sequence_vl.h | 2 +- .../degree_sequence_vl/gengraph_definitions.h | 10 +- .../gengraph_degree_sequence.cpp | 34 +- .../gengraph_degree_sequence.h | 24 +- .../gengraph_graph_molloy_hash.cpp | 202 +- .../gengraph_graph_molloy_hash.h | 66 +- .../gengraph_graph_molloy_optimized.cpp | 274 +- .../gengraph_graph_molloy_optimized.h | 80 +- .../games/degree_sequence_vl/gengraph_hash.h | 54 +- .../gengraph_mr-connected.cpp | 2 +- .../games/degree_sequence_vl/gengraph_qsort.h | 98 +- src/vendor/cigraph/src/games/dotproduct.c | 17 +- src/vendor/cigraph/src/games/erdos_renyi.c | 895 +-- src/vendor/cigraph/src/games/establishment.c | 14 +- src/vendor/cigraph/src/games/forestfire.c | 42 +- src/vendor/cigraph/src/games/grg.c | 10 +- src/vendor/cigraph/src/games/growing_random.c | 24 +- src/vendor/cigraph/src/games/islands.c | 18 +- src/vendor/cigraph/src/games/k_regular.c | 4 +- src/vendor/cigraph/src/games/preference.c | 66 +- src/vendor/cigraph/src/games/recent_degree.c | 56 +- src/vendor/cigraph/src/games/sbm.c | 236 +- src/vendor/cigraph/src/games/static_fitness.c | 46 +- src/vendor/cigraph/src/games/tree.c | 18 +- src/vendor/cigraph/src/games/watts_strogatz.c | 17 +- src/vendor/cigraph/src/graph/adjlist.c | 100 +- src/vendor/cigraph/src/graph/attributes.c | 18 +- src/vendor/cigraph/src/graph/attributes.h | 4 +- src/vendor/cigraph/src/graph/basic_query.c | 8 +- src/vendor/cigraph/src/graph/caching.c | 2 +- src/vendor/cigraph/src/graph/caching.h | 2 +- src/vendor/cigraph/src/graph/cattributes.c | 322 +- src/vendor/cigraph/src/graph/graph_list.c | 2 +- src/vendor/cigraph/src/graph/internal.h | 2 +- src/vendor/cigraph/src/graph/iterators.c | 134 +- src/vendor/cigraph/src/graph/type_common.c | 22 +- .../cigraph/src/graph/type_indexededgelist.c | 267 +- src/vendor/cigraph/src/graph/visitors.c | 70 +- src/vendor/cigraph/src/hrg/dendro.h | 2 +- src/vendor/cigraph/src/hrg/graph.h | 4 +- src/vendor/cigraph/src/hrg/graph_simp.h | 2 +- src/vendor/cigraph/src/hrg/hrg.cc | 114 +- src/vendor/cigraph/src/hrg/hrg_types.cc | 4 +- src/vendor/cigraph/src/hrg/rbtree.h | 2 +- src/vendor/cigraph/src/hrg/splittree_eq.h | 2 +- .../cigraph/src/internal/glpk_support.c | 2 +- .../cigraph/src/internal/glpk_support.h | 2 +- .../cigraph/src/internal/gmp_internal.h | 2 +- src/vendor/cigraph/src/internal/hacks.c | 2 +- src/vendor/cigraph/src/internal/hacks.h | 2 +- src/vendor/cigraph/src/internal/lsap.c | 112 +- src/vendor/cigraph/src/internal/utils.c | 141 +- src/vendor/cigraph/src/internal/utils.h | 9 +- src/vendor/cigraph/src/io/dimacs.c | 28 +- src/vendor/cigraph/src/io/dl-header.h | 6 +- src/vendor/cigraph/src/io/dl-lexer.l | 4 +- src/vendor/cigraph/src/io/dl-parser.y | 34 +- src/vendor/cigraph/src/io/dl.c | 4 +- src/vendor/cigraph/src/io/dot.c | 30 +- src/vendor/cigraph/src/io/edgelist.c | 8 +- src/vendor/cigraph/src/io/gml-header.h | 2 +- src/vendor/cigraph/src/io/gml-lexer.l | 4 +- src/vendor/cigraph/src/io/gml-parser.y | 6 +- src/vendor/cigraph/src/io/gml-tree.c | 52 +- src/vendor/cigraph/src/io/gml-tree.h | 40 +- src/vendor/cigraph/src/io/gml.c | 88 +- src/vendor/cigraph/src/io/graphdb.c | 12 +- src/vendor/cigraph/src/io/graphml.c | 41 +- src/vendor/cigraph/src/io/leda.c | 16 +- src/vendor/cigraph/src/io/lgl-header.h | 4 +- src/vendor/cigraph/src/io/lgl-lexer.l | 4 +- src/vendor/cigraph/src/io/lgl-parser.y | 8 +- src/vendor/cigraph/src/io/lgl.c | 26 +- src/vendor/cigraph/src/io/ncol-header.h | 2 +- src/vendor/cigraph/src/io/ncol-lexer.l | 4 +- src/vendor/cigraph/src/io/ncol-parser.y | 8 +- src/vendor/cigraph/src/io/ncol.c | 22 +- src/vendor/cigraph/src/io/pajek-header.h | 14 +- src/vendor/cigraph/src/io/pajek-lexer.l | 4 +- src/vendor/cigraph/src/io/pajek-parser.y | 56 +- src/vendor/cigraph/src/io/pajek.c | 54 +- src/vendor/cigraph/src/io/parse_utils.c | 10 +- src/vendor/cigraph/src/io/parse_utils.h | 4 +- src/vendor/cigraph/src/isomorphism/bliss.cc | 24 +- .../cigraph/src/isomorphism/isoclasses.c | 62 +- .../cigraph/src/isomorphism/isoclasses.h | 2 +- .../src/isomorphism/isomorphism_misc.c | 16 +- src/vendor/cigraph/src/isomorphism/lad.c | 228 +- src/vendor/cigraph/src/isomorphism/queries.c | 8 +- src/vendor/cigraph/src/isomorphism/vf2.c | 130 +- src/vendor/cigraph/src/layout/align.c | 44 +- src/vendor/cigraph/src/layout/circular.c | 22 +- .../cigraph/src/layout/davidson_harel.c | 66 +- src/vendor/cigraph/src/layout/drl/drl_Node.h | 4 +- .../cigraph/src/layout/drl/drl_Node_3d.h | 4 +- .../cigraph/src/layout/drl/drl_graph.cpp | 46 +- src/vendor/cigraph/src/layout/drl/drl_graph.h | 26 +- .../cigraph/src/layout/drl/drl_graph_3d.cpp | 38 +- .../cigraph/src/layout/drl/drl_graph_3d.h | 26 +- .../cigraph/src/layout/drl/drl_layout.cpp | 2 +- .../cigraph/src/layout/drl/drl_layout_3d.cpp | 2 +- .../cigraph/src/layout/fruchterman_reingold.c | 74 +- src/vendor/cigraph/src/layout/gem.c | 14 +- src/vendor/cigraph/src/layout/graphopt.c | 48 +- src/vendor/cigraph/src/layout/kamada_kawai.c | 62 +- src/vendor/cigraph/src/layout/large_graph.c | 44 +- .../cigraph/src/layout/layout_bipartite.c | 11 +- src/vendor/cigraph/src/layout/layout_grid.c | 10 +- .../cigraph/src/layout/layout_internal.h | 4 +- src/vendor/cigraph/src/layout/layout_random.c | 54 +- src/vendor/cigraph/src/layout/mds.c | 24 +- src/vendor/cigraph/src/layout/merge_dla.c | 34 +- src/vendor/cigraph/src/layout/merge_grid.c | 30 +- src/vendor/cigraph/src/layout/merge_grid.h | 16 +- .../cigraph/src/layout/reingold_tilford.c | 124 +- src/vendor/cigraph/src/layout/sugiyama.c | 308 +- src/vendor/cigraph/src/layout/umap.c | 142 +- src/vendor/cigraph/src/linalg/arpack.c | 16 +- .../cigraph/src/linalg/arpack_internal.h | 2 +- src/vendor/cigraph/src/linalg/blas.c | 10 +- src/vendor/cigraph/src/linalg/blas_internal.h | 2 +- src/vendor/cigraph/src/linalg/eigen.c | 47 +- src/vendor/cigraph/src/linalg/lapack.c | 8 +- .../cigraph/src/linalg/lapack_internal.h | 2 +- src/vendor/cigraph/src/math/complex.c | 2 +- src/vendor/cigraph/src/math/safe_intop.c | 52 +- src/vendor/cigraph/src/math/safe_intop.h | 42 +- src/vendor/cigraph/src/math/utils.c | 2 +- src/vendor/cigraph/src/misc/bipartite.c | 1004 +-- src/vendor/cigraph/src/misc/chordality.c | 34 +- src/vendor/cigraph/src/misc/cocitation.c | 80 +- src/vendor/cigraph/src/misc/coloring.c | 90 +- src/vendor/cigraph/src/misc/conversion.c | 86 +- .../cigraph/src/misc/degree_sequence.cpp | 485 +- src/vendor/cigraph/src/misc/embedding.c | 107 +- src/vendor/cigraph/src/misc/graphicality.c | 139 +- src/vendor/cigraph/src/misc/graphicality.h | 11 +- src/vendor/cigraph/src/misc/matching.c | 48 +- src/vendor/cigraph/src/misc/mixing.c | 233 +- src/vendor/cigraph/src/misc/motifs.c | 213 +- src/vendor/cigraph/src/misc/other.c | 201 +- src/vendor/cigraph/src/misc/power_law_fit.c | 2 +- src/vendor/cigraph/src/misc/scan.c | 126 +- src/vendor/cigraph/src/misc/sir.c | 22 +- src/vendor/cigraph/src/misc/spanning_trees.c | 94 +- src/vendor/cigraph/src/operators/add_edge.c | 4 +- .../cigraph/src/operators/complementer.c | 8 +- src/vendor/cigraph/src/operators/compose.c | 18 +- .../src/operators/connect_neighborhood.c | 62 +- src/vendor/cigraph/src/operators/contract.c | 28 +- src/vendor/cigraph/src/operators/difference.c | 18 +- .../cigraph/src/operators/disjoint_union.c | 36 +- .../cigraph/src/operators/intersection.c | 32 +- src/vendor/cigraph/src/operators/join.c | 12 +- .../cigraph/src/operators/misc_internal.c | 32 +- .../cigraph/src/operators/misc_internal.h | 2 +- src/vendor/cigraph/src/operators/permute.c | 16 +- src/vendor/cigraph/src/operators/products.c | 168 +- src/vendor/cigraph/src/operators/reverse.c | 10 +- src/vendor/cigraph/src/operators/rewire.c | 22 +- .../cigraph/src/operators/rewire_edges.c | 82 +- .../cigraph/src/operators/rewire_internal.h | 4 +- src/vendor/cigraph/src/operators/simplify.c | 12 +- src/vendor/cigraph/src/operators/subgraph.c | 58 +- src/vendor/cigraph/src/operators/subgraph.h | 2 +- src/vendor/cigraph/src/operators/union.c | 28 +- .../cigraph/src/paths/all_shortest_paths.c | 67 +- src/vendor/cigraph/src/paths/astar.c | 28 +- src/vendor/cigraph/src/paths/bellman_ford.c | 187 +- src/vendor/cigraph/src/paths/dijkstra.c | 266 +- src/vendor/cigraph/src/paths/distances.c | 88 +- src/vendor/cigraph/src/paths/eulerian.c | 62 +- src/vendor/cigraph/src/paths/floyd_warshall.c | 86 +- src/vendor/cigraph/src/paths/histogram.c | 22 +- src/vendor/cigraph/src/paths/johnson.c | 111 +- src/vendor/cigraph/src/paths/paths_internal.h | 119 + src/vendor/cigraph/src/paths/random_walk.c | 30 +- src/vendor/cigraph/src/paths/shortest_paths.c | 228 +- src/vendor/cigraph/src/paths/simple_paths.c | 50 +- src/vendor/cigraph/src/paths/sparsifier.c | 139 +- src/vendor/cigraph/src/paths/unweighted.c | 201 +- src/vendor/cigraph/src/paths/voronoi.c | 46 +- src/vendor/cigraph/src/paths/widest_paths.c | 340 +- .../cigraph/src/properties/basic_properties.c | 80 +- src/vendor/cigraph/src/properties/complete.c | 26 +- .../cigraph/src/properties/constraint.c | 12 +- .../src/properties/convergence_degree.c | 18 +- src/vendor/cigraph/src/properties/dag.c | 22 +- src/vendor/cigraph/src/properties/degrees.c | 105 +- src/vendor/cigraph/src/properties/ecc.c | 58 +- src/vendor/cigraph/src/properties/girth.c | 73 +- src/vendor/cigraph/src/properties/loops.c | 16 +- .../cigraph/src/properties/multiplicity.c | 64 +- .../cigraph/src/properties/neighborhood.c | 94 +- src/vendor/cigraph/src/properties/perfect.c | 16 +- .../src/properties/properties_internal.h | 2 +- src/vendor/cigraph/src/properties/rich_club.c | 24 +- src/vendor/cigraph/src/properties/spectral.c | 26 +- src/vendor/cigraph/src/properties/trees.c | 79 +- src/vendor/cigraph/src/properties/triangles.c | 136 +- .../src/properties/triangles_template.h | 20 +- .../src/properties/triangles_template1.h | 20 +- src/vendor/cigraph/src/random/random.c | 70 +- .../cigraph/src/random/random_device.cpp | 2 +- .../cigraph/src/random/random_internal.h | 4 +- src/vendor/cigraph/src/random/rng_glibc2.c | 2 +- src/vendor/cigraph/src/random/rng_mt19937.c | 2 +- src/vendor/cigraph/src/random/rng_pcg32.c | 2 +- src/vendor/cigraph/src/random/rng_pcg64.c | 2 +- src/vendor/cigraph/src/random/sampling.c | 16 +- .../cigraph/src/spatial/beta_skeleton.cpp | 816 +++ src/vendor/cigraph/src/spatial/convex_hull.c | 188 + src/vendor/cigraph/src/spatial/delaunay.c | 280 + src/vendor/cigraph/src/spatial/edge_lengths.c | 119 + .../src/spatial/nanoflann_internal.hpp | 121 + .../cigraph/src/spatial/nearest_neighbor.cpp | 138 +- .../cigraph/src/spatial/spatial_internal.h | 34 + src/vendor/cigraph/src/version.c | 28 +- src/vendor/cigraph/vendor/CMakeLists.txt | 1 + src/vendor/cigraph/vendor/cs/cs.h | 4 +- .../infomap/src/core/BiasedMapEquation.cpp | 2 + .../infomap/src/core/BiasedMapEquation.h | 2 + .../vendor/infomap/src/core/InfomapBase.h | 3 + .../infomap/src/core/InfomapOptimizer.h | 2 + .../infomap/src/core/InfomapOptimizerBase.h | 2 + .../vendor/infomap/src/core/MapEquation.h | 2 + .../infomap/src/core/MemMapEquation.cpp | 2 + .../vendor/infomap/src/core/MemMapEquation.h | 2 + .../infomap/src/core/MetaMapEquation.cpp | 2 + .../vendor/infomap/src/core/MetaMapEquation.h | 2 + .../infomap/src/io/ProgramInterface.cpp | 21 + .../vendor/infomap/src/io/ProgramInterface.h | 6 + .../cigraph/vendor/infomap/src/utils/Log.h | 13 +- .../vendor/lapack/fortran_intrinsics.c | 2 +- src/vendor/cigraph/vendor/mini-gmp/mini-gmp.c | 116 +- src/vendor/cigraph/vendor/mini-gmp/mini-gmp.h | 1 + src/vendor/cigraph/vendor/qhull/CHANGES.md | 12 + .../cigraph/vendor/qhull/CMakeLists.txt | 48 + src/vendor/cigraph/vendor/qhull/COPYING.txt | 39 + src/vendor/cigraph/vendor/qhull/README.txt | 720 +++ .../vendor/qhull/libqhull_r/accessors_r.c | 69 + .../cigraph/vendor/qhull/libqhull_r/geom2_r.c | 2302 +++++++ .../cigraph/vendor/qhull/libqhull_r/geom_r.c | 1284 ++++ .../cigraph/vendor/qhull/libqhull_r/geom_r.h | 189 + .../vendor/qhull/libqhull_r/global_r.c | 2268 +++++++ .../cigraph/vendor/qhull/libqhull_r/io_r.c | 4128 ++++++++++++ .../cigraph/vendor/qhull/libqhull_r/io_r.h | 166 + .../vendor/qhull/libqhull_r/libqhull_r.c | 1754 ++++++ .../vendor/qhull/libqhull_r/libqhull_r.h | 1281 ++++ .../cigraph/vendor/qhull/libqhull_r/mem_r.c | 566 ++ .../cigraph/vendor/qhull/libqhull_r/mem_r.h | 235 + .../cigraph/vendor/qhull/libqhull_r/merge_r.c | 5589 +++++++++++++++++ .../cigraph/vendor/qhull/libqhull_r/merge_r.h | 238 + .../cigraph/vendor/qhull/libqhull_r/poly2_r.c | 3959 ++++++++++++ .../cigraph/vendor/qhull/libqhull_r/poly_r.c | 1448 +++++ .../cigraph/vendor/qhull/libqhull_r/poly_r.h | 310 + .../vendor/qhull/libqhull_r/qhull_ra.h | 161 + .../cigraph/vendor/qhull/libqhull_r/qset_r.c | 1383 ++++ .../cigraph/vendor/qhull/libqhull_r/qset_r.h | 515 ++ .../vendor/qhull/libqhull_r/random_r.c | 249 + .../vendor/qhull/libqhull_r/random_r.h | 41 + .../vendor/qhull/libqhull_r/rboxlib_r.c | 854 +++ .../cigraph/vendor/qhull/libqhull_r/stat_r.c | 727 +++ .../cigraph/vendor/qhull/libqhull_r/stat_r.h | 563 ++ .../cigraph/vendor/qhull/libqhull_r/user_r.c | 617 ++ .../cigraph/vendor/qhull/libqhull_r/user_r.h | 1061 ++++ .../vendor/qhull/libqhull_r/usermem_r.c | 102 + .../vendor/qhull/libqhull_r/userprintf_r.c | 68 + .../qhull/libqhull_r/userprintf_rbox_r.c | 53 + src/vendor/igraph_threading.h | 2 +- src/vendor/igraph_version.h | 14 +- src/vendor/io/dl-lexer.c | 4 +- src/vendor/io/dl-parser.c | 30 +- src/vendor/io/gml-lexer.c | 4 +- src/vendor/io/gml-parser.c | 4 +- src/vendor/io/lgl-lexer.c | 4 +- src/vendor/io/lgl-parser.c | 4 +- src/vendor/io/ncol-lexer.c | 4 +- src/vendor/io/ncol-parser.c | 4 +- src/vendor/io/pajek-lexer.c | 4 +- src/vendor/io/pajek-parser.c | 52 +- src/vendor/io/parsers/dl-parser.h | 2 +- src/vendor/io/parsers/lgl-parser.h | 2 +- src/vendor/io/parsers/ncol-parser.h | 2 +- src/vendor/io/parsers/pajek-parser.h | 2 +- 524 files changed, 49707 insertions(+), 12645 deletions(-) create mode 100644 src/vendor/cigraph/VERSIONING.md create mode 100644 src/vendor/cigraph/src/community/community_internal.h rename src/vendor/cigraph/src/{misc => cycles}/cycle_bases.c (86%) rename src/vendor/cigraph/src/{misc/feedback_arc_set.c => cycles/feedback_sets.c} (92%) rename src/vendor/cigraph/src/{misc/feedback_arc_set.h => cycles/feedback_sets.h} (92%) rename src/vendor/cigraph/src/{misc => cycles}/order_cycle.cpp (72%) rename src/vendor/cigraph/src/{misc => cycles}/order_cycle.h (98%) create mode 100644 src/vendor/cigraph/src/paths/paths_internal.h create mode 100644 src/vendor/cigraph/src/spatial/beta_skeleton.cpp create mode 100644 src/vendor/cigraph/src/spatial/convex_hull.c create mode 100644 src/vendor/cigraph/src/spatial/delaunay.c create mode 100644 src/vendor/cigraph/src/spatial/edge_lengths.c create mode 100644 src/vendor/cigraph/src/spatial/nanoflann_internal.hpp create mode 100644 src/vendor/cigraph/src/spatial/spatial_internal.h create mode 100644 src/vendor/cigraph/vendor/qhull/CHANGES.md create mode 100644 src/vendor/cigraph/vendor/qhull/CMakeLists.txt create mode 100644 src/vendor/cigraph/vendor/qhull/COPYING.txt create mode 100644 src/vendor/cigraph/vendor/qhull/README.txt create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/accessors_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/geom2_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/global_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/poly2_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/qhull_ra.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/rboxlib_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.h create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/usermem_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_r.c create mode 100644 src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_rbox_r.c diff --git a/R/aaa-auto.R b/R/aaa-auto.R index a4b92c6f23a..4987848c663 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -369,7 +369,7 @@ full_bipartite_impl <- function(n1, n2, directed=FALSE, mode=c("all", "out", "in # Function call res <- .Call(R_igraph_full_bipartite, n1, n2, directed, mode) if (igraph_opt("add.vertex.names") && is_named(res$graph)) { - names(res$types) <- vertex_attr(res$graph, "name") + names(res$types) <- vertex_attr(res$graph, "name", ) } res } @@ -470,31 +470,34 @@ turan_impl <- function(n, r) { res } -erdos_renyi_game_gnp_impl <- function(n, p, directed=FALSE, loops=FALSE) { +erdos_renyi_game_gnp_impl <- function(n, p, directed=FALSE, allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) { # Argument checks n <- as.numeric(n) p <- as.numeric(p) directed <- as.logical(directed) - loops <- as.logical(loops) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) + edge.labeled <- as.logical(edge.labeled) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_erdos_renyi_game_gnp, n, p, directed, loops) + res <- .Call(R_igraph_erdos_renyi_game_gnp, n, p, directed, allowed.edge.types, edge.labeled) res } -erdos_renyi_game_gnm_impl <- function(n, m, directed=FALSE, loops=FALSE, multiple=FALSE) { +erdos_renyi_game_gnm_impl <- function(n, m, directed=FALSE, allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) { # Argument checks n <- as.numeric(n) m <- as.numeric(m) directed <- as.logical(directed) - loops <- as.logical(loops) - multiple <- as.logical(multiple) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) + edge.labeled <- as.logical(edge.labeled) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_erdos_renyi_game_gnm, n, m, directed, loops, multiple) + res <- .Call(R_igraph_erdos_renyi_game_gnm, n, m, directed, allowed.edge.types, edge.labeled) res } @@ -567,16 +570,16 @@ asymmetric_preference_game_impl <- function(nodes, out.types, in.types, type.dis res } -rewire_edges_impl <- function(graph, prob, loops=FALSE, multiple=FALSE) { +rewire_edges_impl <- function(graph, prob, allowed.edge.types=c("simple", "loops", "multi", "all")) { # Argument checks ensure_igraph(graph) prob <- as.numeric(prob) - loops <- as.logical(loops) - multiple <- as.logical(multiple) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_rewire_edges, graph, prob, loops, multiple) + res <- .Call(R_igraph_rewire_edges, graph, prob, allowed.edge.types) res } @@ -659,17 +662,17 @@ chung_lu_game_impl <- function(out.weights, in.weights=NULL, ..., loops=TRUE, va res } -static_fitness_game_impl <- function(no.of.edges, fitness.out, fitness.in=NULL, loops=FALSE, multiple=FALSE) { +static_fitness_game_impl <- function(no.of.edges, fitness.out, fitness.in=NULL, allowed.edge.types=c("simple", "loops", "multi", "all")) { # Argument checks no.of.edges <- as.numeric(no.of.edges) fitness.out <- as.numeric(fitness.out) if (!is.null(fitness.in)) fitness.in <- as.numeric(fitness.in) - loops <- as.logical(loops) - multiple <- as.logical(multiple) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_static_fitness_game, no.of.edges, fitness.out, fitness.in, loops, multiple) + res <- .Call(R_igraph_static_fitness_game, no.of.edges, fitness.out, fitness.in, allowed.edge.types) if (igraph_opt("add.params")) { res$name <- 'Static fitness model' @@ -680,19 +683,19 @@ static_fitness_game_impl <- function(no.of.edges, fitness.out, fitness.in=NULL, res } -static_power_law_game_impl <- function(no.of.nodes, no.of.edges, exponent.out, exponent.in=-1, loops=FALSE, multiple=FALSE, finite.size.correction=TRUE) { +static_power_law_game_impl <- function(no.of.nodes, no.of.edges, exponent.out, exponent.in=-1, allowed.edge.types=c("simple", "loops", "multi", "all"), finite.size.correction=TRUE) { # Argument checks no.of.nodes <- as.numeric(no.of.nodes) no.of.edges <- as.numeric(no.of.edges) exponent.out <- as.numeric(exponent.out) exponent.in <- as.numeric(exponent.in) - loops <- as.logical(loops) - multiple <- as.logical(multiple) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) finite.size.correction <- as.logical(finite.size.correction) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_static_power_law_game, no.of.nodes, no.of.edges, exponent.out, exponent.in, loops, multiple, finite.size.correction) + res <- .Call(R_igraph_static_power_law_game, no.of.nodes, no.of.edges, exponent.out, exponent.in, allowed.edge.types, finite.size.correction) if (igraph_opt("add.params")) { res$name <- 'Static power law model' @@ -725,17 +728,17 @@ k_regular_game_impl <- function(no.of.nodes, k, directed=FALSE, multiple=FALSE) res } -sbm_game_impl <- function(n, pref.matrix, block.sizes, directed=FALSE, loops=FALSE) { +sbm_game_impl <- function(pref.matrix, block.sizes, directed=FALSE, allowed.edge.types=c("simple", "loops", "multi", "all")) { # Argument checks - n <- as.numeric(n) pref.matrix[] <- as.numeric(pref.matrix) block.sizes <- as.numeric(block.sizes) directed <- as.logical(directed) - loops <- as.logical(loops) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_sbm_game, n, pref.matrix, block.sizes, directed, loops) + res <- .Call(R_igraph_sbm_game, pref.matrix, block.sizes, directed, allowed.edge.types) if (igraph_opt("add.params")) { res$name <- 'Stochastic block model' @@ -897,7 +900,7 @@ closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "tot res } -closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE, cutoff=-1) { +closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE, cutoff=UNLIMITED) { # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) @@ -1094,7 +1097,7 @@ voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in res } -get_all_simple_paths_impl <- function(graph, from, to=V(graph), minlen=-1, maxlen=-1, mode=c("out", "in", "all", "total")) { +get_all_simple_paths_impl <- function(graph, from, to=V(graph), mode=c("out", "in", "all", "total"), minlen=UNLIMITED, maxlen=UNLIMITED, max.results=UNLIMITED) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) @@ -1102,13 +1105,14 @@ get_all_simple_paths_impl <- function(graph, from, to=V(graph), minlen=-1, maxle stop("No vertex was specified") } to <- as_igraph_vs(graph, to) + mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) minlen <- as.numeric(minlen) maxlen <- as.numeric(maxlen) - mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) + max.results <- as.numeric(max.results) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_get_all_simple_paths, graph, from-1, to-1, minlen, maxlen, mode) + res <- .Call(R_igraph_get_all_simple_paths, graph, from-1, to-1, mode, minlen, maxlen, max.results) res } @@ -1267,11 +1271,9 @@ spanner_impl <- function(graph, stretch, weights=NULL) { res } -betweenness_cutoff_impl <- function(graph, vids=V(graph), directed=TRUE, weights=NULL, cutoff=-1) { +betweenness_cutoff_impl <- function(graph, weights=NULL, vids=V(graph), directed=TRUE, normalized=FALSE, cutoff=UNLIMITED) { # Argument checks ensure_igraph(graph) - vids <- as_igraph_vs(graph, vids) - directed <- as.logical(directed) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1280,24 +1282,23 @@ betweenness_cutoff_impl <- function(graph, vids=V(graph), directed=TRUE, weights } else { weights <- NULL } + vids <- as_igraph_vs(graph, vids) + directed <- as.logical(directed) + normalized <- as.logical(normalized) cutoff <- as.numeric(cutoff) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_betweenness_cutoff, graph, vids-1, directed, weights, cutoff) + res <- .Call(R_igraph_betweenness_cutoff, graph, weights, vids-1, directed, normalized, cutoff) if (igraph_opt("add.vertex.names") && is_named(graph)) { names(res) <- vertex_attr(graph, "name", vids) } res } -betweenness_subset_impl <- function(graph, vids=V(graph), directed=TRUE, sources=V(graph), targets=V(graph), weights=NULL) { +betweenness_subset_impl <- function(graph, weights=NULL, vids=V(graph), sources=V(graph), targets=V(graph), directed=TRUE, normalized=FALSE) { # Argument checks ensure_igraph(graph) - vids <- as_igraph_vs(graph, vids) - directed <- as.logical(directed) - sources <- as_igraph_vs(graph, sources) - targets <- as_igraph_vs(graph, targets) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1306,20 +1307,24 @@ betweenness_subset_impl <- function(graph, vids=V(graph), directed=TRUE, sources } else { weights <- NULL } + vids <- as_igraph_vs(graph, vids) + sources <- as_igraph_vs(graph, sources) + targets <- as_igraph_vs(graph, targets) + directed <- as.logical(directed) + normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_betweenness_subset, graph, vids-1, directed, sources-1, targets-1, weights) + res <- .Call(R_igraph_betweenness_subset, graph, weights, vids-1, sources-1, targets-1, directed, normalized) if (igraph_opt("add.vertex.names") && is_named(graph)) { names(res) <- vertex_attr(graph, "name", vids) } res } -edge_betweenness_impl <- function(graph, directed=TRUE, weights=NULL) { +edge_betweenness_impl <- function(graph, weights=NULL, eids=E(graph), directed=TRUE, normalized=FALSE) { # Argument checks ensure_igraph(graph) - directed <- as.logical(directed) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1328,18 +1333,20 @@ edge_betweenness_impl <- function(graph, directed=TRUE, weights=NULL) { } else { weights <- NULL } + eids <- as_igraph_es(graph, eids) + directed <- as.logical(directed) + normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_edge_betweenness, graph, directed, weights) + res <- .Call(R_igraph_edge_betweenness, graph, weights, eids-1, directed, normalized) res } -edge_betweenness_cutoff_impl <- function(graph, directed=TRUE, weights=NULL, cutoff=-1) { +edge_betweenness_cutoff_impl <- function(graph, weights=NULL, eids=E(graph), directed=TRUE, normalized=FALSE, cutoff=UNLIMITED) { # Argument checks ensure_igraph(graph) - directed <- as.logical(directed) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1348,22 +1355,21 @@ edge_betweenness_cutoff_impl <- function(graph, directed=TRUE, weights=NULL, cut } else { weights <- NULL } + eids <- as_igraph_es(graph, eids) + directed <- as.logical(directed) + normalized <- as.logical(normalized) cutoff <- as.numeric(cutoff) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_edge_betweenness_cutoff, graph, directed, weights, cutoff) + res <- .Call(R_igraph_edge_betweenness_cutoff, graph, weights, eids-1, directed, normalized, cutoff) res } -edge_betweenness_subset_impl <- function(graph, eids=E(graph), directed=TRUE, sources=V(graph), targets=V(graph), weights=NULL) { +edge_betweenness_subset_impl <- function(graph, weights=NULL, sources=V(graph), targets=V(graph), eids=E(graph), directed=TRUE, normalized=FALSE) { # Argument checks ensure_igraph(graph) - eids <- as_igraph_es(graph, eids) - directed <- as.logical(directed) - sources <- as_igraph_vs(graph, sources) - targets <- as_igraph_vs(graph, targets) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1372,17 +1378,20 @@ edge_betweenness_subset_impl <- function(graph, eids=E(graph), directed=TRUE, so } else { weights <- NULL } + sources <- as_igraph_vs(graph, sources) + targets <- as_igraph_vs(graph, targets) + eids <- as_igraph_es(graph, eids) + directed <- as.logical(directed) + normalized <- as.logical(normalized) 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", eids) - } + res <- .Call(R_igraph_edge_betweenness_subset, graph, weights, sources-1, targets-1, eids-1, directed, normalized) + res } -harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE, cutoff=-1) { +harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE, cutoff=UNLIMITED) { # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) @@ -1407,14 +1416,9 @@ harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", res } -personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V(graph), directed=TRUE, damping=0.85, personalized=NULL, weights=NULL, options=NULL) { +personalized_pagerank_impl <- function(graph, weights=NULL, reset=NULL, damping=0.85, directed=TRUE, vids=V(graph), algo=c("prpack", "arpack"), options=NULL) { # Argument checks ensure_igraph(graph) - algo <- switch_igraph_arg(algo, "arpack" = 1L, "prpack" = 2L) - vids <- as_igraph_vs(graph, vids) - directed <- as.logical(directed) - damping <- as.numeric(damping) - if (!is.null(personalized)) personalized <- as.numeric(personalized) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1423,6 +1427,11 @@ personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V } else { weights <- NULL } + if (!is.null(reset)) reset <- as.numeric(reset) + damping <- as.numeric(damping) + directed <- as.logical(directed) + vids <- as_igraph_vs(graph, vids) + algo <- switch_igraph_arg(algo, "arpack" = 1L, "prpack" = 2L) if (is.null(options)) { if (algo == 0L) { options <- list(niter=1000, eps=0.001) @@ -1435,21 +1444,16 @@ personalized_pagerank_impl <- function(graph, algo=c("prpack", "arpack"), vids=V on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_personalized_pagerank, graph, algo, vids-1, directed, damping, personalized, weights, options) + res <- .Call(R_igraph_personalized_pagerank, graph, weights, reset, damping, directed, vids-1, algo, options) if (igraph_opt("add.vertex.names") && is_named(graph)) { names(res$vector) <- vertex_attr(graph, "name", vids) } res } -personalized_pagerank_vs_impl <- function(graph, algo=c("prpack", "arpack"), vids=V(graph), directed=TRUE, damping=0.85, reset.vids, weights=NULL, options=NULL, details=FALSE) { +personalized_pagerank_vs_impl <- function(graph, weights=NULL, reset.vids, damping=0.85, directed=TRUE, vids=V(graph), algo=c("prpack", "arpack"), options=NULL, details=FALSE) { # Argument checks ensure_igraph(graph) - algo <- switch_igraph_arg(algo, "arpack" = 1L, "prpack" = 2L) - vids <- as_igraph_vs(graph, vids) - directed <- as.logical(directed) - damping <- as.numeric(damping) - reset.vids <- as_igraph_vs(graph, reset.vids) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -1458,6 +1462,11 @@ personalized_pagerank_vs_impl <- function(graph, algo=c("prpack", "arpack"), vid } else { weights <- NULL } + reset.vids <- as_igraph_vs(graph, reset.vids) + damping <- as.numeric(damping) + directed <- as.logical(directed) + vids <- as_igraph_vs(graph, vids) + algo <- switch_igraph_arg(algo, "arpack" = 1L, "prpack" = 2L) if (is.null(options)) { if (algo == 0L) { options <- list(niter=1000, eps=0.001) @@ -1470,7 +1479,7 @@ personalized_pagerank_vs_impl <- function(graph, algo=c("prpack", "arpack"), vid on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_personalized_pagerank_vs, graph, algo, vids-1, directed, damping, reset.vids-1, weights, options) + res <- .Call(R_igraph_personalized_pagerank_vs, graph, weights, reset.vids-1, damping, directed, vids-1, algo, options) if (igraph_opt("add.vertex.names") && is_named(graph)) { names(res$vector) <- vertex_attr(graph, "name", vids) } @@ -1668,14 +1677,22 @@ maxdegree_impl <- function(graph, ..., v=V(graph), mode=c("all", "out", "in", "t res } -density_impl <- function(graph, loops=FALSE) { +density_impl <- function(graph, weights=NULL, loops=FALSE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && !all(is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_density, graph, loops) + res <- .Call(R_igraph_density, graph, weights, loops) res } @@ -2163,23 +2180,39 @@ centralization_eigenvector_centrality_tmax_impl <- function(graph=NULL, nodes=0, res } -assortativity_nominal_impl <- function(graph, types, directed=TRUE, normalized=TRUE) { +assortativity_nominal_impl <- function(graph, weights=NULL, types, directed=TRUE, normalized=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && !all(is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } types <- as.numeric(types)-1 directed <- as.logical(directed) normalized <- as.logical(normalized) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_assortativity_nominal, graph, types, directed, normalized) + res <- .Call(R_igraph_assortativity_nominal, graph, weights, types, directed, normalized) res } -assortativity_impl <- function(graph, values, values.in=NULL, directed=TRUE, normalized=TRUE) { +assortativity_impl <- function(graph, weights=NULL, values, values.in=NULL, directed=TRUE, normalized=TRUE) { # Argument checks ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && !all(is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } values <- as.numeric(values) if (!is.null(values.in)) values.in <- as.numeric(values.in) directed <- as.logical(directed) @@ -2187,7 +2220,7 @@ assortativity_impl <- function(graph, values, values.in=NULL, directed=TRUE, nor on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_assortativity, graph, values, values.in, directed, normalized) + res <- .Call(R_igraph_assortativity, graph, weights, values, values.in, directed, normalized) res } @@ -2204,7 +2237,7 @@ assortativity_degree_impl <- function(graph, directed=TRUE) { res } -joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=-1, max.in.degree=-1) { +joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=UNLIMITED, max.in.degree=UNLIMITED) { # Argument checks ensure_igraph(graph) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { @@ -2225,7 +2258,7 @@ joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=-1, max res } -joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE, normalized=TRUE, max.from.degree=-1, max.to.degree=-1) { +joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE, normalized=TRUE, max.from.degree=UNLIMITED, max.to.degree=UNLIMITED) { # Argument checks ensure_igraph(graph) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { @@ -2562,7 +2595,7 @@ bipartite_projection_size_impl <- function(graph, types=NULL) { create_bipartite_impl <- function(types, edges, directed=FALSE) { # Argument checks - types <- handle_vertex_type_arg(types, graph) + types <- handle_vertex_type_arg(types, %I1%) edges <- as.numeric(edges) directed <- as.logical(directed) @@ -2599,7 +2632,7 @@ weighted_biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", # Function call res <- .Call(R_igraph_weighted_biadjacency, biadjmatrix, directed, mode) if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$types) <- vertex_attr(graph, "name") + names(res$types) <- vertex_attr(graph, "name", ) } res } @@ -2652,20 +2685,22 @@ bipartite_game_gnp_impl <- function(n1, n2, p, directed=FALSE, mode=c("all", "ou res } -bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "out", "in", "total"), multiple=FALSE) { +bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "out", "in", "total"), allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) { # Argument checks n1 <- as.numeric(n1) n2 <- as.numeric(n2) m <- as.numeric(m) directed <- as.logical(directed) mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) - multiple <- as.logical(multiple) + allowed.edge.types <- switch_igraph_arg(allowed.edge.types, + "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L) + edge.labeled <- as.logical(edge.labeled) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_bipartite_game_gnm, n1, n2, m, directed, mode, multiple) - if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$types) <- vertex_attr(graph, "name") + res <- .Call(R_igraph_bipartite_game_gnm, n1, n2, m, directed, mode, allowed.edge.types, edge.labeled) + if (igraph_opt("add.vertex.names") && is_named()) { + names(res$types) <- vertex_attr(, "name", ) } res } @@ -2682,7 +2717,7 @@ bipartite_iea_game_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou # Function call res <- .Call(R_igraph_bipartite_iea_game, n1, n2, m, directed, mode) if (igraph_opt("add.vertex.names") && is_named(graph)) { - names(res$types) <- vertex_attr(graph, "name") + names(res$types) <- vertex_attr(graph, "name", ) } res } @@ -2805,7 +2840,7 @@ is_biconnected_impl <- function(graph) { res } -count_reachable_impl <- function(graph, mode) { +count_reachable_impl <- function(graph, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) @@ -2865,15 +2900,16 @@ is_clique_impl <- function(graph, candidate, directed=FALSE) { res } -cliques_impl <- function(graph, min=0, max=0) { +cliques_impl <- function(graph, min=UNLIMITED, max=UNLIMITED, max.results=UNLIMITED) { # Argument checks ensure_igraph(graph) min <- as.numeric(min) max <- as.numeric(max) + max.results <- as.numeric(max.results) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_cliques, graph, min, max) + res <- .Call(R_igraph_cliques, graph, min, max, max.results) res } @@ -2926,7 +2962,7 @@ clique_number_impl <- function(graph) { res } -weighted_cliques_impl <- function(graph, vertex.weights=NULL, min.weight=0, max.weight=0, maximal=FALSE) { +weighted_cliques_impl <- function(graph, vertex.weights=NULL, maximal=FALSE, min.weight=UNLIMITED, max.weight=UNLIMITED, max.results=UNLIMITED) { # Argument checks ensure_igraph(graph) if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) { @@ -2937,13 +2973,14 @@ weighted_cliques_impl <- function(graph, vertex.weights=NULL, min.weight=0, max. } else { vertex.weights <- NULL } + maximal <- as.logical(maximal) min.weight <- as.numeric(min.weight) max.weight <- as.numeric(max.weight) - maximal <- as.logical(maximal) + max.results <- as.numeric(max.results) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_weighted_cliques, graph, vertex.weights, min.weight, max.weight, maximal) + res <- .Call(R_igraph_weighted_cliques, graph, vertex.weights, maximal, min.weight, max.weight, max.results) res } @@ -3290,17 +3327,17 @@ layout_align_impl <- function(graph, layout) { res } -similarity_dice_impl <- function(graph, vit.from=V(graph), vit.to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { +similarity_dice_impl <- function(graph, from=V(graph), to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { # Argument checks ensure_igraph(graph) - vit.from <- as_igraph_vs(graph, vit.from) - vit.to <- as_igraph_vs(graph, vit.to) + from <- as_igraph_vs(graph, from) + to <- as_igraph_vs(graph, to) mode <- switch_igraph_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, vit.from-1, vit.to-1, mode, loops) + res <- .Call(R_igraph_similarity_dice, graph, from-1, to-1, mode, loops) res } @@ -3345,17 +3382,17 @@ similarity_inverse_log_weighted_impl <- function(graph, vids=V(graph), mode=c("a res } -similarity_jaccard_impl <- function(graph, vit.from=V(graph), vit.to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { +similarity_jaccard_impl <- function(graph, from=V(graph), to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { # Argument checks ensure_igraph(graph) - vit.from <- as_igraph_vs(graph, vit.from) - vit.to <- as_igraph_vs(graph, vit.to) + from <- as_igraph_vs(graph, from) + to <- as_igraph_vs(graph, to) mode <- switch_igraph_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, vit.from-1, vit.to-1, mode, loops) + res <- .Call(R_igraph_similarity_jaccard, graph, from-1, to-1, mode, loops) res } @@ -3455,7 +3492,7 @@ community_fluid_communities_impl <- function(graph, no.of.communities) { res } -community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", "total"), weights=NULL, initial=NULL, fixed=NULL, lpa.variant) { +community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", "total"), weights=NULL, initial=NULL, fixed=NULL, lpa.variant=c("dominance", "retention", "fast")) { # Argument checks ensure_igraph(graph) mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) @@ -3519,7 +3556,7 @@ community_optimal_modularity_impl <- function(graph, weights=NULL, resolution=1. res } -community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, vertex.in.weights=NULL, resolution, beta=0.01, start, n.iterations=2, membership=NULL) { +community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, vertex.in.weights=NULL, resolution, beta=0.01, start=FALSE, n.iterations=2, membership=NULL) { # Argument checks ensure_igraph(graph) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { @@ -3559,6 +3596,30 @@ community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, res } +community_leiden_simple_impl <- function(graph, weights=NULL, objective, resolution, beta=0.01, start=FALSE, n.iterations=2, membership=NULL) { + # Argument checks + ensure_igraph(graph) + if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { + weights <- E(graph)$weight + } + if (!is.null(weights) && !all(is.na(weights))) { + weights <- as.numeric(weights) + } else { + weights <- NULL + } + resolution <- as.numeric(resolution) + beta <- as.numeric(beta) + start <- as.logical(start) + n.iterations <- as.numeric(n.iterations) + if (!is.null(membership)) membership <- as.numeric(membership) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_community_leiden_simple, graph, weights, objective, resolution, beta, start, n.iterations, membership) + + res +} + split_join_distance_impl <- function(comm1, comm2) { # Argument checks comm1 <- as.numeric(comm1) @@ -3571,7 +3632,7 @@ split_join_distance_impl <- function(comm1, comm2) { res } -community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL, nb.trials=10) { +community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL, nb.trials=10, is.regularized=FALSE, regularization.strength=1) { # Argument checks ensure_igraph(graph) if (is.null(edge.weights) && "weight" %in% edge_attr_names(graph)) { @@ -3591,10 +3652,12 @@ community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL vertex.weights <- NULL } nb.trials <- as.numeric(nb.trials) + is.regularized <- as.logical(is.regularized) + regularization.strength <- as.numeric(regularization.strength) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_community_infomap, graph, edge.weights, vertex.weights, nb.trials) + res <- .Call(R_igraph_community_infomap, graph, edge.weights, vertex.weights, nb.trials, is.regularized, regularization.strength) res } @@ -4137,7 +4200,7 @@ join_impl <- function(left, right) { res } -induced_subgraph_map_impl <- function(graph, vids, impl) { +induced_subgraph_map_impl <- function(graph, vids, impl=c("auto", "copy_and_delete", "create_from_scratch")) { # Argument checks ensure_igraph(graph) vids <- as_igraph_vs(graph, vids) @@ -4509,11 +4572,11 @@ count_automorphisms_impl <- function(graph, colors=NULL) { isoclass_subgraph_impl <- function(graph, vids) { # Argument checks ensure_igraph(graph) - vids <- as.numeric(vids) + vids <- as_igraph_vs(graph, vids) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_isoclass_subgraph, graph, vids) + res <- .Call(R_igraph_isoclass_subgraph, graph, vids-1) res } @@ -5207,13 +5270,13 @@ sir_impl <- function(graph, beta, gamma, no.sim=100) { res } -convex_hull_impl <- function(data) { +convex_hull_2d_impl <- function(data) { # Argument checks data[] <- as.numeric(data) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_convex_hull, data) + res <- .Call(R_igraph_convex_hull_2d, data) res } @@ -5258,16 +5321,17 @@ find_cycle_impl <- function(graph, mode=c("out", "in", "all", "total")) { res } -simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), min.cycle.length=-1, max.cycle.length=-1) { +simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), min.cycle.length=UNLIMITED, max.cycle.length=UNLIMITED, max.results=UNLIMITED) { # Argument checks ensure_igraph(graph) mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L) min.cycle.length <- as.numeric(min.cycle.length) max.cycle.length <- as.numeric(max.cycle.length) + max.results <- as.numeric(max.results) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_simple_cycles, graph, mode, min.cycle.length, max.cycle.length) + res <- .Call(R_igraph_simple_cycles, graph, mode, min.cycle.length, max.cycle.length, max.results) res } @@ -5315,14 +5379,9 @@ eulerian_cycle_impl <- function(graph) { res } -fundamental_cycles_impl <- function(graph, start=-1, bfs.cutoff=-1, weights=NULL) { +fundamental_cycles_impl <- function(graph, weights=NULL, start=NULL, bfs.cutoff=UNLIMITED) { # Argument checks ensure_igraph(graph) - if (!is.null(start)) start <- as_igraph_vs(graph, start) - if (length(start) == 0) { - stop("No vertex was specified") - } - bfs.cutoff <- as.numeric(bfs.cutoff) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -5331,20 +5390,22 @@ fundamental_cycles_impl <- function(graph, start=-1, bfs.cutoff=-1, weights=NULL } else { weights <- NULL } + if (!is.null(start)) start <- as_igraph_vs(graph, start) + if (length(start) == 0) { + stop("No vertex was specified") + } + bfs.cutoff <- as.numeric(bfs.cutoff) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_fundamental_cycles, graph, start-1, bfs.cutoff, weights) + res <- .Call(R_igraph_fundamental_cycles, graph, weights, start-1, bfs.cutoff) res } -minimum_cycle_basis_impl <- function(graph, bfs.cutoff=-1, complete=TRUE, use.cycle.order=TRUE, weights=NULL) { +minimum_cycle_basis_impl <- function(graph, weights=NULL, bfs.cutoff=UNLIMITED, complete=TRUE, use.cycle.order=TRUE) { # Argument checks ensure_igraph(graph) - bfs.cutoff <- as.numeric(bfs.cutoff) - complete <- as.logical(complete) - use.cycle.order <- as.logical(use.cycle.order) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -5353,10 +5414,13 @@ minimum_cycle_basis_impl <- function(graph, bfs.cutoff=-1, complete=TRUE, use.cy } else { weights <- NULL } + bfs.cutoff <- as.numeric(bfs.cutoff) + complete <- as.logical(complete) + use.cycle.order <- as.logical(use.cycle.order) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_minimum_cycle_basis, graph, bfs.cutoff, complete, use.cycle.order, weights) + res <- .Call(R_igraph_minimum_cycle_basis, graph, weights, bfs.cutoff, complete, use.cycle.order) res } @@ -5467,7 +5531,7 @@ minimum_spanning_tree_impl <- function(graph, weights=NULL, method=c("automatic" res } -random_spanning_tree_impl <- function(graph, vid=-1) { +random_spanning_tree_impl <- function(graph, vid=NULL) { # Argument checks ensure_igraph(graph) if (!is.null(vid)) vid <- as_igraph_vs(graph, vid) @@ -5511,6 +5575,87 @@ nearest_neighbor_graph_impl <- function(points, metric, neighbors, cutoff, direc res } +delaunay_graph_impl <- function(points) { + # Argument checks + points[] <- as.numeric(points) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_delaunay_graph, points) + + res +} + +gabriel_graph_impl <- function(points) { + # Argument checks + points[] <- as.numeric(points) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_gabriel_graph, points) + + res +} + +relative_neighborhood_graph_impl <- function(points) { + # Argument checks + points[] <- as.numeric(points) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_relative_neighborhood_graph, points) + + res +} + +lune_beta_skeleton_impl <- function(points, beta=1) { + # Argument checks + points[] <- as.numeric(points) + beta <- as.numeric(beta) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_lune_beta_skeleton, points, beta) + + res +} + +circle_beta_skeleton_impl <- function(points, beta=1) { + # Argument checks + points[] <- as.numeric(points) + beta <- as.numeric(beta) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_circle_beta_skeleton, points, beta) + + res +} + +beta_weighted_gabriel_graph_impl <- function(points, max.beta=UNLIMITED) { + # Argument checks + points[] <- as.numeric(points) + max.beta <- as.numeric(max.beta) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_beta_weighted_gabriel_graph, points, max.beta) + + res +} + +spatial_edge_lengths_impl <- function(graph, points, METRIC) { + # Argument checks + ensure_igraph(graph) + points[] <- as.numeric(points) + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_spatial_edge_lengths, graph, points, METRIC) + + res +} + vertex_coloring_greedy_impl <- function(graph, heuristic=c("colored_neighbors", "dsatur")) { # Argument checks ensure_igraph(graph) diff --git a/src/cpp11.cpp b/src/cpp11.cpp index 7329f158e75..ad77d25fc5d 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -41,9 +41,9 @@ extern SEXP R_igraph_are_adjacent(SEXP, SEXP, SEXP); extern SEXP R_igraph_arpack(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_arpack_unpack_complex(SEXP, SEXP, SEXP); extern SEXP R_igraph_articulation_points(SEXP); -extern SEXP R_igraph_assortativity(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_assortativity(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_assortativity_degree(SEXP, SEXP); -extern SEXP R_igraph_assortativity_nominal(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_assortativity_nominal(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_asymmetric_preference_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_atlas(SEXP); extern SEXP R_igraph_automorphism_group(SEXP, SEXP); @@ -53,14 +53,15 @@ extern SEXP R_igraph_average_path_length(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_avg_nearest_neighbor_degree(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_barabasi_aging_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_barabasi_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_betweenness_cutoff(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_betweenness_subset(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_beta_weighted_gabriel_graph(SEXP, SEXP); +extern SEXP R_igraph_betweenness_cutoff(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_betweenness_subset(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bfs(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bfs_simple(SEXP, SEXP, SEXP); extern SEXP R_igraph_biadjacency(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bibcoupling(SEXP, SEXP); extern SEXP R_igraph_biconnected_components(SEXP); -extern SEXP R_igraph_bipartite_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_bipartite_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bipartite_game_gnp(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bipartite_iea_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_bipartite_projection(SEXP, SEXP, SEXP, SEXP); @@ -80,12 +81,13 @@ extern SEXP R_igraph_centralization_degree_tmax(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization_eigenvector_centrality(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_centralization_eigenvector_centrality_tmax(SEXP, SEXP, SEXP); extern SEXP R_igraph_chung_lu_game(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_circle_beta_skeleton(SEXP, SEXP); extern SEXP R_igraph_circulant(SEXP, SEXP, SEXP); extern SEXP R_igraph_cited_type_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_citing_cited_type_game(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_clique_number(SEXP); extern SEXP R_igraph_clique_size_hist(SEXP, SEXP, SEXP); -extern SEXP R_igraph_cliques(SEXP, SEXP, SEXP); +extern SEXP R_igraph_cliques(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_closeness(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_closeness_cutoff(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_cocitation(SEXP, SEXP); @@ -94,10 +96,11 @@ extern SEXP R_igraph_cohesive_blocks(SEXP); extern SEXP R_igraph_community_edge_betweenness(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_fastgreedy(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_fluid_communities(SEXP, SEXP); -extern SEXP R_igraph_community_infomap(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_community_infomap(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_label_propagation(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_leading_eigenvector(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_leiden(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_community_leiden_simple(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_community_multilevel(SEXP, SEXP, SEXP); extern SEXP R_igraph_community_optimal_modularity(SEXP, SEXP, SEXP); extern SEXP R_igraph_community_to_membership2(SEXP, SEXP, SEXP); @@ -108,7 +111,7 @@ extern SEXP R_igraph_connect_neighborhood(SEXP, SEXP, SEXP); extern SEXP R_igraph_connected_components(SEXP, SEXP); extern SEXP R_igraph_constraint(SEXP, SEXP, SEXP); extern SEXP R_igraph_contract_vertices(SEXP, SEXP, SEXP); -extern SEXP R_igraph_convex_hull(SEXP); +extern SEXP R_igraph_convex_hull_2d(SEXP); extern SEXP R_igraph_copy(SEXP); extern SEXP R_igraph_copy_env(SEXP); extern SEXP R_igraph_copy_from(SEXP); @@ -133,10 +136,11 @@ extern SEXP R_igraph_decompose(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_degree(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_degree_correlation_vector(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_degree_sequence_game(SEXP, SEXP, SEXP); +extern SEXP R_igraph_delaunay_graph(SEXP); extern SEXP R_igraph_delete_edges(SEXP, SEXP); extern SEXP R_igraph_delete_vertices(SEXP, SEXP); extern SEXP R_igraph_delete_vertices_map(SEXP, SEXP); -extern SEXP R_igraph_density(SEXP, SEXP); +extern SEXP R_igraph_density(SEXP, SEXP, SEXP); extern SEXP R_igraph_dfs(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_diameter(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_difference(SEXP, SEXP); @@ -149,9 +153,9 @@ extern SEXP R_igraph_dyad_census(SEXP); extern SEXP R_igraph_ecc(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_eccentricity(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_ecount(SEXP); -extern SEXP R_igraph_edge_betweenness(SEXP, SEXP, SEXP); -extern SEXP R_igraph_edge_betweenness_cutoff(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_edge_betweenness_subset(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_edge_betweenness(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_edge_betweenness_cutoff(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_edge_betweenness_subset(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_edge_connectivity(SEXP, SEXP); extern SEXP R_igraph_edge_disjoint_paths(SEXP, SEXP, SEXP); extern SEXP R_igraph_edgelist_percolation(SEXP); @@ -160,7 +164,7 @@ extern SEXP R_igraph_eigen_adjacency(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_eigenvector_centrality(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_empty(SEXP, SEXP); extern SEXP R_igraph_erdos_renyi_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_erdos_renyi_game_gnp(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_erdos_renyi_game_gnp(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_es_adj(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_es_pairs(SEXP, SEXP, SEXP); extern SEXP R_igraph_es_path(SEXP, SEXP, SEXP); @@ -183,6 +187,7 @@ extern SEXP R_igraph_full_bipartite(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_full_citation(SEXP, SEXP); extern SEXP R_igraph_full_multipartite(SEXP, SEXP, SEXP); extern SEXP R_igraph_fundamental_cycles(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_gabriel_graph(SEXP); extern SEXP R_igraph_generalized_petersen(SEXP, SEXP); extern SEXP R_igraph_get_adjacency(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_adjacency_sparse(SEXP, SEXP, SEXP, SEXP); @@ -191,7 +196,7 @@ extern SEXP R_igraph_get_adjlist(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_eids_between(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_all_shortest_paths_dijkstra(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_get_all_simple_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_get_all_simple_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_get_attr_mode(SEXP, SEXP); extern SEXP R_igraph_get_biadjacency(SEXP, SEXP, SEXP); extern SEXP R_igraph_get_diameter(SEXP, SEXP, SEXP, SEXP); @@ -335,6 +340,7 @@ extern SEXP R_igraph_local_scan_k_ecount(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_local_scan_k_ecount_them(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_local_scan_neighborhood_ecount(SEXP, SEXP, SEXP); extern SEXP R_igraph_local_scan_subset_ecount(SEXP, SEXP, SEXP); +extern SEXP R_igraph_lune_beta_skeleton(SEXP, SEXP); extern SEXP R_igraph_make_weak_ref(SEXP, SEXP, SEXP); extern SEXP R_igraph_maxdegree(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_maxflow(SEXP, SEXP, SEXP, SEXP); @@ -397,12 +403,13 @@ extern SEXP R_igraph_realize_degree_sequence(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_recent_degree_aging_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_reciprocity(SEXP, SEXP, SEXP); extern SEXP R_igraph_regular_tree(SEXP, SEXP, SEXP); +extern SEXP R_igraph_relative_neighborhood_graph(SEXP); extern SEXP R_igraph_residual_graph(SEXP, SEXP, SEXP); extern SEXP R_igraph_reverse_edges(SEXP, SEXP); extern SEXP R_igraph_reverse_residual_graph(SEXP, SEXP, SEXP); extern SEXP R_igraph_rewire(SEXP, SEXP, SEXP); extern SEXP R_igraph_rewire_directed_edges(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_rewire_edges(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_rewire_edges(SEXP, SEXP, SEXP); extern SEXP R_igraph_rich_club_sequence(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_ring(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_rooted_product(SEXP, SEXP, SEXP); @@ -411,7 +418,7 @@ extern SEXP R_igraph_running_mean(SEXP, SEXP); extern SEXP R_igraph_sample_dirichlet(SEXP, SEXP); extern SEXP R_igraph_sample_sphere_surface(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_sample_sphere_volume(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_sbm_game(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_sbm_game(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_set_verbose(SEXP); extern SEXP R_igraph_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_dice(SEXP, SEXP, SEXP, SEXP, SEXP); @@ -421,7 +428,7 @@ extern SEXP R_igraph_similarity_inverse_log_weighted(SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_jaccard(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_jaccard_es(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_similarity_jaccard_pairs(SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_simple_cycles(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_simple_cycles(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_simple_interconnected_islands_game(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_simplify(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_simplify_and_colorize(SEXP); @@ -429,6 +436,7 @@ extern SEXP R_igraph_sir(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_site_percolation(SEXP, SEXP); extern SEXP R_igraph_solve_lsap(SEXP, SEXP); extern SEXP R_igraph_spanner(SEXP, SEXP, SEXP); +extern SEXP R_igraph_spatial_edge_lengths(SEXP, SEXP, SEXP); extern SEXP R_igraph_spinglass_community(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_spinglass_my_community(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_split_join_distance(SEXP, SEXP); @@ -438,8 +446,8 @@ extern SEXP R_igraph_st_mincut(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_st_mincut_value(SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_st_vertex_connectivity(SEXP, SEXP, SEXP); extern SEXP R_igraph_star(SEXP, SEXP, SEXP); -extern SEXP R_igraph_static_fitness_game(SEXP, SEXP, SEXP, SEXP, SEXP); -extern SEXP R_igraph_static_power_law_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_static_fitness_game(SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_static_power_law_game(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_strength(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_subcomponent(SEXP, SEXP, SEXP); extern SEXP R_igraph_subgraph_from_edges(SEXP, SEXP, SEXP); @@ -481,7 +489,7 @@ extern SEXP R_igraph_weak_ref_value(SEXP); extern SEXP R_igraph_weighted_adjacency(SEXP, SEXP, SEXP); extern SEXP R_igraph_weighted_biadjacency(SEXP, SEXP, SEXP); extern SEXP R_igraph_weighted_clique_number(SEXP, SEXP); -extern SEXP R_igraph_weighted_cliques(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP R_igraph_weighted_cliques(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_wheel(SEXP, SEXP, SEXP); extern SEXP R_igraph_widest_path_widths_dijkstra(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_igraph_widest_path_widths_floyd_warshall(SEXP, SEXP, SEXP, SEXP, SEXP); @@ -516,9 +524,9 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_arpack", (DL_FUNC) &R_igraph_arpack, 5}, {"R_igraph_arpack_unpack_complex", (DL_FUNC) &R_igraph_arpack_unpack_complex, 3}, {"R_igraph_articulation_points", (DL_FUNC) &R_igraph_articulation_points, 1}, - {"R_igraph_assortativity", (DL_FUNC) &R_igraph_assortativity, 5}, + {"R_igraph_assortativity", (DL_FUNC) &R_igraph_assortativity, 6}, {"R_igraph_assortativity_degree", (DL_FUNC) &R_igraph_assortativity_degree, 2}, - {"R_igraph_assortativity_nominal", (DL_FUNC) &R_igraph_assortativity_nominal, 4}, + {"R_igraph_assortativity_nominal", (DL_FUNC) &R_igraph_assortativity_nominal, 5}, {"R_igraph_asymmetric_preference_game", (DL_FUNC) &R_igraph_asymmetric_preference_game, 6}, {"R_igraph_atlas", (DL_FUNC) &R_igraph_atlas, 1}, {"R_igraph_automorphism_group", (DL_FUNC) &R_igraph_automorphism_group, 2}, @@ -528,14 +536,15 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_avg_nearest_neighbor_degree", (DL_FUNC) &R_igraph_avg_nearest_neighbor_degree, 5}, {"R_igraph_barabasi_aging_game", (DL_FUNC) &R_igraph_barabasi_aging_game, 12}, {"R_igraph_barabasi_game", (DL_FUNC) &R_igraph_barabasi_game, 9}, - {"R_igraph_betweenness_cutoff", (DL_FUNC) &R_igraph_betweenness_cutoff, 5}, - {"R_igraph_betweenness_subset", (DL_FUNC) &R_igraph_betweenness_subset, 6}, + {"R_igraph_beta_weighted_gabriel_graph", (DL_FUNC) &R_igraph_beta_weighted_gabriel_graph, 2}, + {"R_igraph_betweenness_cutoff", (DL_FUNC) &R_igraph_betweenness_cutoff, 6}, + {"R_igraph_betweenness_subset", (DL_FUNC) &R_igraph_betweenness_subset, 7}, {"R_igraph_bfs", (DL_FUNC) &R_igraph_bfs, 15}, {"R_igraph_bfs_simple", (DL_FUNC) &R_igraph_bfs_simple, 3}, {"R_igraph_biadjacency", (DL_FUNC) &R_igraph_biadjacency, 4}, {"R_igraph_bibcoupling", (DL_FUNC) &R_igraph_bibcoupling, 2}, {"R_igraph_biconnected_components", (DL_FUNC) &R_igraph_biconnected_components, 1}, - {"R_igraph_bipartite_game_gnm", (DL_FUNC) &R_igraph_bipartite_game_gnm, 6}, + {"R_igraph_bipartite_game_gnm", (DL_FUNC) &R_igraph_bipartite_game_gnm, 7}, {"R_igraph_bipartite_game_gnp", (DL_FUNC) &R_igraph_bipartite_game_gnp, 5}, {"R_igraph_bipartite_iea_game", (DL_FUNC) &R_igraph_bipartite_iea_game, 5}, {"R_igraph_bipartite_projection", (DL_FUNC) &R_igraph_bipartite_projection, 4}, @@ -555,12 +564,13 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_centralization_eigenvector_centrality", (DL_FUNC) &R_igraph_centralization_eigenvector_centrality, 4}, {"R_igraph_centralization_eigenvector_centrality_tmax", (DL_FUNC) &R_igraph_centralization_eigenvector_centrality_tmax, 3}, {"R_igraph_chung_lu_game", (DL_FUNC) &R_igraph_chung_lu_game, 4}, + {"R_igraph_circle_beta_skeleton", (DL_FUNC) &R_igraph_circle_beta_skeleton, 2}, {"R_igraph_circulant", (DL_FUNC) &R_igraph_circulant, 3}, {"R_igraph_cited_type_game", (DL_FUNC) &R_igraph_cited_type_game, 5}, {"R_igraph_citing_cited_type_game", (DL_FUNC) &R_igraph_citing_cited_type_game, 5}, {"R_igraph_clique_number", (DL_FUNC) &R_igraph_clique_number, 1}, {"R_igraph_clique_size_hist", (DL_FUNC) &R_igraph_clique_size_hist, 3}, - {"R_igraph_cliques", (DL_FUNC) &R_igraph_cliques, 3}, + {"R_igraph_cliques", (DL_FUNC) &R_igraph_cliques, 4}, {"R_igraph_closeness", (DL_FUNC) &R_igraph_closeness, 5}, {"R_igraph_closeness_cutoff", (DL_FUNC) &R_igraph_closeness_cutoff, 6}, {"R_igraph_cocitation", (DL_FUNC) &R_igraph_cocitation, 2}, @@ -569,10 +579,11 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_community_edge_betweenness", (DL_FUNC) &R_igraph_community_edge_betweenness, 8}, {"R_igraph_community_fastgreedy", (DL_FUNC) &R_igraph_community_fastgreedy, 5}, {"R_igraph_community_fluid_communities", (DL_FUNC) &R_igraph_community_fluid_communities, 2}, - {"R_igraph_community_infomap", (DL_FUNC) &R_igraph_community_infomap, 4}, + {"R_igraph_community_infomap", (DL_FUNC) &R_igraph_community_infomap, 6}, {"R_igraph_community_label_propagation", (DL_FUNC) &R_igraph_community_label_propagation, 6}, {"R_igraph_community_leading_eigenvector", (DL_FUNC) &R_igraph_community_leading_eigenvector, 9}, {"R_igraph_community_leiden", (DL_FUNC) &R_igraph_community_leiden, 9}, + {"R_igraph_community_leiden_simple", (DL_FUNC) &R_igraph_community_leiden_simple, 8}, {"R_igraph_community_multilevel", (DL_FUNC) &R_igraph_community_multilevel, 3}, {"R_igraph_community_optimal_modularity", (DL_FUNC) &R_igraph_community_optimal_modularity, 3}, {"R_igraph_community_to_membership2", (DL_FUNC) &R_igraph_community_to_membership2, 3}, @@ -583,7 +594,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_connected_components", (DL_FUNC) &R_igraph_connected_components, 2}, {"R_igraph_constraint", (DL_FUNC) &R_igraph_constraint, 3}, {"R_igraph_contract_vertices", (DL_FUNC) &R_igraph_contract_vertices, 3}, - {"R_igraph_convex_hull", (DL_FUNC) &R_igraph_convex_hull, 1}, + {"R_igraph_convex_hull_2d", (DL_FUNC) &R_igraph_convex_hull_2d, 1}, {"R_igraph_copy", (DL_FUNC) &R_igraph_copy, 1}, {"R_igraph_copy_env", (DL_FUNC) &R_igraph_copy_env, 1}, {"R_igraph_copy_from", (DL_FUNC) &R_igraph_copy_from, 1}, @@ -608,10 +619,11 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_degree", (DL_FUNC) &R_igraph_degree, 4}, {"R_igraph_degree_correlation_vector", (DL_FUNC) &R_igraph_degree_correlation_vector, 5}, {"R_igraph_degree_sequence_game", (DL_FUNC) &R_igraph_degree_sequence_game, 3}, + {"R_igraph_delaunay_graph", (DL_FUNC) &R_igraph_delaunay_graph, 1}, {"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_map", (DL_FUNC) &R_igraph_delete_vertices_map, 2}, - {"R_igraph_density", (DL_FUNC) &R_igraph_density, 2}, + {"R_igraph_density", (DL_FUNC) &R_igraph_density, 3}, {"R_igraph_dfs", (DL_FUNC) &R_igraph_dfs, 12}, {"R_igraph_diameter", (DL_FUNC) &R_igraph_diameter, 4}, {"R_igraph_difference", (DL_FUNC) &R_igraph_difference, 2}, @@ -624,9 +636,9 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_ecc", (DL_FUNC) &R_igraph_ecc, 5}, {"R_igraph_eccentricity", (DL_FUNC) &R_igraph_eccentricity, 4}, {"R_igraph_ecount", (DL_FUNC) &R_igraph_ecount, 1}, - {"R_igraph_edge_betweenness", (DL_FUNC) &R_igraph_edge_betweenness, 3}, - {"R_igraph_edge_betweenness_cutoff", (DL_FUNC) &R_igraph_edge_betweenness_cutoff, 4}, - {"R_igraph_edge_betweenness_subset", (DL_FUNC) &R_igraph_edge_betweenness_subset, 6}, + {"R_igraph_edge_betweenness", (DL_FUNC) &R_igraph_edge_betweenness, 5}, + {"R_igraph_edge_betweenness_cutoff", (DL_FUNC) &R_igraph_edge_betweenness_cutoff, 6}, + {"R_igraph_edge_betweenness_subset", (DL_FUNC) &R_igraph_edge_betweenness_subset, 7}, {"R_igraph_edge_connectivity", (DL_FUNC) &R_igraph_edge_connectivity, 2}, {"R_igraph_edge_disjoint_paths", (DL_FUNC) &R_igraph_edge_disjoint_paths, 3}, {"R_igraph_edgelist_percolation", (DL_FUNC) &R_igraph_edgelist_percolation, 1}, @@ -635,7 +647,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_eigenvector_centrality", (DL_FUNC) &R_igraph_eigenvector_centrality, 4}, {"R_igraph_empty", (DL_FUNC) &R_igraph_empty, 2}, {"R_igraph_erdos_renyi_game_gnm", (DL_FUNC) &R_igraph_erdos_renyi_game_gnm, 5}, - {"R_igraph_erdos_renyi_game_gnp", (DL_FUNC) &R_igraph_erdos_renyi_game_gnp, 4}, + {"R_igraph_erdos_renyi_game_gnp", (DL_FUNC) &R_igraph_erdos_renyi_game_gnp, 5}, {"R_igraph_es_adj", (DL_FUNC) &R_igraph_es_adj, 4}, {"R_igraph_es_pairs", (DL_FUNC) &R_igraph_es_pairs, 3}, {"R_igraph_es_path", (DL_FUNC) &R_igraph_es_path, 3}, @@ -658,6 +670,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_full_citation", (DL_FUNC) &R_igraph_full_citation, 2}, {"R_igraph_full_multipartite", (DL_FUNC) &R_igraph_full_multipartite, 3}, {"R_igraph_fundamental_cycles", (DL_FUNC) &R_igraph_fundamental_cycles, 4}, + {"R_igraph_gabriel_graph", (DL_FUNC) &R_igraph_gabriel_graph, 1}, {"R_igraph_generalized_petersen", (DL_FUNC) &R_igraph_generalized_petersen, 2}, {"R_igraph_get_adjacency", (DL_FUNC) &R_igraph_get_adjacency, 4}, {"R_igraph_get_adjacency_sparse", (DL_FUNC) &R_igraph_get_adjacency_sparse, 4}, @@ -666,7 +679,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_get_all_eids_between", (DL_FUNC) &R_igraph_get_all_eids_between, 4}, {"R_igraph_get_all_shortest_paths", (DL_FUNC) &R_igraph_get_all_shortest_paths, 5}, {"R_igraph_get_all_shortest_paths_dijkstra", (DL_FUNC) &R_igraph_get_all_shortest_paths_dijkstra, 5}, - {"R_igraph_get_all_simple_paths", (DL_FUNC) &R_igraph_get_all_simple_paths, 6}, + {"R_igraph_get_all_simple_paths", (DL_FUNC) &R_igraph_get_all_simple_paths, 7}, {"R_igraph_get_attr_mode", (DL_FUNC) &R_igraph_get_attr_mode, 2}, {"R_igraph_get_biadjacency", (DL_FUNC) &R_igraph_get_biadjacency, 3}, {"R_igraph_get_diameter", (DL_FUNC) &R_igraph_get_diameter, 4}, @@ -810,6 +823,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_local_scan_k_ecount_them", (DL_FUNC) &R_igraph_local_scan_k_ecount_them, 5}, {"R_igraph_local_scan_neighborhood_ecount", (DL_FUNC) &R_igraph_local_scan_neighborhood_ecount, 3}, {"R_igraph_local_scan_subset_ecount", (DL_FUNC) &R_igraph_local_scan_subset_ecount, 3}, + {"R_igraph_lune_beta_skeleton", (DL_FUNC) &R_igraph_lune_beta_skeleton, 2}, {"R_igraph_make_weak_ref", (DL_FUNC) &R_igraph_make_weak_ref, 3}, {"R_igraph_maxdegree", (DL_FUNC) &R_igraph_maxdegree, 4}, {"R_igraph_maxflow", (DL_FUNC) &R_igraph_maxflow, 4}, @@ -872,12 +886,13 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_recent_degree_aging_game", (DL_FUNC) &R_igraph_recent_degree_aging_game, 10}, {"R_igraph_reciprocity", (DL_FUNC) &R_igraph_reciprocity, 3}, {"R_igraph_regular_tree", (DL_FUNC) &R_igraph_regular_tree, 3}, + {"R_igraph_relative_neighborhood_graph", (DL_FUNC) &R_igraph_relative_neighborhood_graph, 1}, {"R_igraph_residual_graph", (DL_FUNC) &R_igraph_residual_graph, 3}, {"R_igraph_reverse_edges", (DL_FUNC) &R_igraph_reverse_edges, 2}, {"R_igraph_reverse_residual_graph", (DL_FUNC) &R_igraph_reverse_residual_graph, 3}, {"R_igraph_rewire", (DL_FUNC) &R_igraph_rewire, 3}, {"R_igraph_rewire_directed_edges", (DL_FUNC) &R_igraph_rewire_directed_edges, 4}, - {"R_igraph_rewire_edges", (DL_FUNC) &R_igraph_rewire_edges, 4}, + {"R_igraph_rewire_edges", (DL_FUNC) &R_igraph_rewire_edges, 3}, {"R_igraph_rich_club_sequence", (DL_FUNC) &R_igraph_rich_club_sequence, 6}, {"R_igraph_ring", (DL_FUNC) &R_igraph_ring, 4}, {"R_igraph_rooted_product", (DL_FUNC) &R_igraph_rooted_product, 3}, @@ -886,7 +901,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_sample_dirichlet", (DL_FUNC) &R_igraph_sample_dirichlet, 2}, {"R_igraph_sample_sphere_surface", (DL_FUNC) &R_igraph_sample_sphere_surface, 4}, {"R_igraph_sample_sphere_volume", (DL_FUNC) &R_igraph_sample_sphere_volume, 4}, - {"R_igraph_sbm_game", (DL_FUNC) &R_igraph_sbm_game, 5}, + {"R_igraph_sbm_game", (DL_FUNC) &R_igraph_sbm_game, 4}, {"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, 5}, @@ -896,7 +911,7 @@ static const R_CallMethodDef CallEntries[] = { {"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_cycles", (DL_FUNC) &R_igraph_simple_cycles, 4}, + {"R_igraph_simple_cycles", (DL_FUNC) &R_igraph_simple_cycles, 5}, {"R_igraph_simple_interconnected_islands_game", (DL_FUNC) &R_igraph_simple_interconnected_islands_game, 4}, {"R_igraph_simplify", (DL_FUNC) &R_igraph_simplify, 4}, {"R_igraph_simplify_and_colorize", (DL_FUNC) &R_igraph_simplify_and_colorize, 1}, @@ -904,6 +919,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_site_percolation", (DL_FUNC) &R_igraph_site_percolation, 2}, {"R_igraph_solve_lsap", (DL_FUNC) &R_igraph_solve_lsap, 2}, {"R_igraph_spanner", (DL_FUNC) &R_igraph_spanner, 3}, + {"R_igraph_spatial_edge_lengths", (DL_FUNC) &R_igraph_spatial_edge_lengths, 3}, {"R_igraph_spinglass_community", (DL_FUNC) &R_igraph_spinglass_community, 11}, {"R_igraph_spinglass_my_community", (DL_FUNC) &R_igraph_spinglass_my_community, 6}, {"R_igraph_split_join_distance", (DL_FUNC) &R_igraph_split_join_distance, 2}, @@ -913,8 +929,8 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_st_mincut_value", (DL_FUNC) &R_igraph_st_mincut_value, 4}, {"R_igraph_st_vertex_connectivity", (DL_FUNC) &R_igraph_st_vertex_connectivity, 3}, {"R_igraph_star", (DL_FUNC) &R_igraph_star, 3}, - {"R_igraph_static_fitness_game", (DL_FUNC) &R_igraph_static_fitness_game, 5}, - {"R_igraph_static_power_law_game", (DL_FUNC) &R_igraph_static_power_law_game, 7}, + {"R_igraph_static_fitness_game", (DL_FUNC) &R_igraph_static_fitness_game, 4}, + {"R_igraph_static_power_law_game", (DL_FUNC) &R_igraph_static_power_law_game, 6}, {"R_igraph_strength", (DL_FUNC) &R_igraph_strength, 5}, {"R_igraph_subcomponent", (DL_FUNC) &R_igraph_subcomponent, 3}, {"R_igraph_subgraph_from_edges", (DL_FUNC) &R_igraph_subgraph_from_edges, 3}, @@ -956,7 +972,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_weighted_adjacency", (DL_FUNC) &R_igraph_weighted_adjacency, 3}, {"R_igraph_weighted_biadjacency", (DL_FUNC) &R_igraph_weighted_biadjacency, 3}, {"R_igraph_weighted_clique_number", (DL_FUNC) &R_igraph_weighted_clique_number, 2}, - {"R_igraph_weighted_cliques", (DL_FUNC) &R_igraph_weighted_cliques, 5}, + {"R_igraph_weighted_cliques", (DL_FUNC) &R_igraph_weighted_cliques, 6}, {"R_igraph_wheel", (DL_FUNC) &R_igraph_wheel, 3}, {"R_igraph_widest_path_widths_dijkstra", (DL_FUNC) &R_igraph_widest_path_widths_dijkstra, 5}, {"R_igraph_widest_path_widths_floyd_warshall", (DL_FUNC) &R_igraph_widest_path_widths_floyd_warshall, 5}, diff --git a/src/rinterface.c b/src/rinterface.c index d88c05db4e3..c1863699877 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -1314,13 +1314,14 @@ SEXP R_igraph_turan(SEXP n, SEXP r) { /*-------------------------------------------/ / igraph_erdos_renyi_game_gnp / /-------------------------------------------*/ -SEXP R_igraph_erdos_renyi_game_gnp(SEXP n, SEXP p, SEXP directed, SEXP loops) { +SEXP R_igraph_erdos_renyi_game_gnp(SEXP n, SEXP p, SEXP directed, SEXP allowed_edge_types, SEXP edge_labeled) { /* Declarations */ igraph_t c_graph; igraph_integer_t c_n; igraph_real_t c_p; igraph_bool_t c_directed; - igraph_bool_t c_loops; + igraph_edge_type_sw_t c_allowed_edge_types; + igraph_bool_t c_edge_labeled; SEXP graph; SEXP r_result; @@ -1331,11 +1332,12 @@ SEXP R_igraph_erdos_renyi_game_gnp(SEXP n, SEXP p, SEXP directed, SEXP loops) { c_p = REAL(p)[0]; IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; + c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); + IGRAPH_R_CHECK_BOOL(edge_labeled); + c_edge_labeled = LOGICAL(edge_labeled)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_erdos_renyi_game_gnp(&c_graph, c_n, c_p, c_directed, c_loops)); + IGRAPH_R_CHECK(igraph_erdos_renyi_game_gnp(&c_graph, c_n, c_p, c_directed, c_allowed_edge_types, c_edge_labeled)); PutRNGstate(); /* Convert output */ @@ -1352,14 +1354,14 @@ SEXP R_igraph_erdos_renyi_game_gnp(SEXP n, SEXP p, SEXP directed, SEXP loops) { /*-------------------------------------------/ / igraph_erdos_renyi_game_gnm / /-------------------------------------------*/ -SEXP R_igraph_erdos_renyi_game_gnm(SEXP n, SEXP m, SEXP directed, SEXP loops, SEXP multiple) { +SEXP R_igraph_erdos_renyi_game_gnm(SEXP n, SEXP m, SEXP directed, SEXP allowed_edge_types, SEXP edge_labeled) { /* Declarations */ igraph_t c_graph; igraph_integer_t c_n; igraph_integer_t c_m; igraph_bool_t c_directed; - igraph_bool_t c_loops; - igraph_bool_t c_multiple; + igraph_edge_type_sw_t c_allowed_edge_types; + igraph_bool_t c_edge_labeled; SEXP graph; SEXP r_result; @@ -1370,13 +1372,12 @@ SEXP R_igraph_erdos_renyi_game_gnm(SEXP n, SEXP m, SEXP directed, SEXP loops, SE c_m = (igraph_integer_t) REAL(m)[0]; IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; - IGRAPH_R_CHECK_BOOL(multiple); - c_multiple = LOGICAL(multiple)[0]; + c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); + IGRAPH_R_CHECK_BOOL(edge_labeled); + c_edge_labeled = LOGICAL(edge_labeled)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_erdos_renyi_game_gnm(&c_graph, c_n, c_m, c_directed, c_loops, c_multiple)); + IGRAPH_R_CHECK(igraph_erdos_renyi_game_gnm(&c_graph, c_n, c_m, c_directed, c_allowed_edge_types, c_edge_labeled)); PutRNGstate(); /* Convert output */ @@ -1593,12 +1594,11 @@ SEXP R_igraph_asymmetric_preference_game(SEXP nodes, SEXP out_types, SEXP in_typ /*-------------------------------------------/ / igraph_rewire_edges / /-------------------------------------------*/ -SEXP R_igraph_rewire_edges(SEXP graph, SEXP prob, SEXP loops, SEXP multiple) { +SEXP R_igraph_rewire_edges(SEXP graph, SEXP prob, SEXP allowed_edge_types) { /* Declarations */ igraph_t c_graph; igraph_real_t c_prob; - igraph_bool_t c_loops; - igraph_bool_t c_multiple; + igraph_edge_type_sw_t c_allowed_edge_types; SEXP r_result; /* Convert input */ @@ -1606,13 +1606,10 @@ SEXP R_igraph_rewire_edges(SEXP graph, SEXP prob, SEXP loops, SEXP multiple) { IGRAPH_FINALLY(igraph_destroy, &c_graph); IGRAPH_R_CHECK_REAL(prob); c_prob = REAL(prob)[0]; - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; - IGRAPH_R_CHECK_BOOL(multiple); - c_multiple = LOGICAL(multiple)[0]; + c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_rewire_edges(&c_graph, c_prob, c_loops, c_multiple)); + IGRAPH_R_CHECK(igraph_rewire_edges(&c_graph, c_prob, c_allowed_edge_types)); PutRNGstate(); /* Convert output */ @@ -1778,14 +1775,13 @@ SEXP R_igraph_chung_lu_game(SEXP out_weights, SEXP in_weights, SEXP loops, SEXP /*-------------------------------------------/ / igraph_static_fitness_game / /-------------------------------------------*/ -SEXP R_igraph_static_fitness_game(SEXP no_of_edges, SEXP fitness_out, SEXP fitness_in, SEXP loops, SEXP multiple) { +SEXP R_igraph_static_fitness_game(SEXP no_of_edges, SEXP fitness_out, SEXP fitness_in, SEXP allowed_edge_types) { /* Declarations */ igraph_t c_graph; igraph_integer_t c_no_of_edges; igraph_vector_t c_fitness_out; igraph_vector_t c_fitness_in; - igraph_bool_t c_loops; - igraph_bool_t c_multiple; + igraph_edge_type_sw_t c_allowed_edge_types; SEXP graph; SEXP r_result; @@ -1796,13 +1792,10 @@ SEXP R_igraph_static_fitness_game(SEXP no_of_edges, SEXP fitness_out, SEXP fitne if (!Rf_isNull(fitness_in)) { R_SEXP_to_vector(fitness_in, &c_fitness_in); } - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; - IGRAPH_R_CHECK_BOOL(multiple); - c_multiple = LOGICAL(multiple)[0]; + c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_static_fitness_game(&c_graph, c_no_of_edges, &c_fitness_out, (Rf_isNull(fitness_in) ? NULL : &c_fitness_in), c_loops, c_multiple)); + IGRAPH_R_CHECK(igraph_static_fitness_game(&c_graph, c_no_of_edges, &c_fitness_out, (Rf_isNull(fitness_in) ? NULL : &c_fitness_in), c_allowed_edge_types)); PutRNGstate(); /* Convert output */ @@ -1819,15 +1812,14 @@ SEXP R_igraph_static_fitness_game(SEXP no_of_edges, SEXP fitness_out, SEXP fitne /*-------------------------------------------/ / igraph_static_power_law_game / /-------------------------------------------*/ -SEXP R_igraph_static_power_law_game(SEXP no_of_nodes, SEXP no_of_edges, SEXP exponent_out, SEXP exponent_in, SEXP loops, SEXP multiple, SEXP finite_size_correction) { +SEXP R_igraph_static_power_law_game(SEXP no_of_nodes, SEXP no_of_edges, SEXP exponent_out, SEXP exponent_in, SEXP allowed_edge_types, SEXP finite_size_correction) { /* Declarations */ igraph_t c_graph; igraph_integer_t c_no_of_nodes; igraph_integer_t c_no_of_edges; igraph_real_t c_exponent_out; igraph_real_t c_exponent_in; - igraph_bool_t c_loops; - igraph_bool_t c_multiple; + igraph_edge_type_sw_t c_allowed_edge_types; igraph_bool_t c_finite_size_correction; SEXP graph; @@ -1841,15 +1833,12 @@ SEXP R_igraph_static_power_law_game(SEXP no_of_nodes, SEXP no_of_edges, SEXP exp c_exponent_out = REAL(exponent_out)[0]; IGRAPH_R_CHECK_REAL(exponent_in); c_exponent_in = REAL(exponent_in)[0]; - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; - IGRAPH_R_CHECK_BOOL(multiple); - c_multiple = LOGICAL(multiple)[0]; + c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); IGRAPH_R_CHECK_BOOL(finite_size_correction); c_finite_size_correction = LOGICAL(finite_size_correction)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_static_power_law_game(&c_graph, c_no_of_nodes, c_no_of_edges, c_exponent_out, c_exponent_in, c_loops, c_multiple, c_finite_size_correction)); + IGRAPH_R_CHECK(igraph_static_power_law_game(&c_graph, c_no_of_nodes, c_no_of_edges, c_exponent_out, c_exponent_in, c_allowed_edge_types, c_finite_size_correction)); PutRNGstate(); /* Convert output */ @@ -1904,30 +1893,26 @@ SEXP R_igraph_k_regular_game(SEXP no_of_nodes, SEXP k, SEXP directed, SEXP multi /*-------------------------------------------/ / igraph_sbm_game / /-------------------------------------------*/ -SEXP R_igraph_sbm_game(SEXP n, SEXP pref_matrix, SEXP block_sizes, SEXP directed, SEXP loops) { +SEXP R_igraph_sbm_game(SEXP pref_matrix, SEXP block_sizes, SEXP directed, SEXP allowed_edge_types) { /* Declarations */ igraph_t c_graph; - igraph_integer_t c_n; igraph_matrix_t c_pref_matrix; igraph_vector_int_t c_block_sizes; igraph_bool_t c_directed; - igraph_bool_t c_loops; + igraph_edge_type_sw_t c_allowed_edge_types; SEXP graph; SEXP r_result; /* Convert input */ - IGRAPH_R_CHECK_INT(n); - c_n = (igraph_integer_t) REAL(n)[0]; R_SEXP_to_matrix(pref_matrix, &c_pref_matrix); IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(block_sizes, &c_block_sizes)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_block_sizes); IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_BOOL(loops); - c_loops = LOGICAL(loops)[0]; + c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_sbm_game(&c_graph, c_n, &c_pref_matrix, &c_block_sizes, c_directed, c_loops)); + IGRAPH_R_CHECK(igraph_sbm_game(&c_graph, &c_pref_matrix, &c_block_sizes, c_directed, c_allowed_edge_types)); PutRNGstate(); /* Convert output */ @@ -2028,8 +2013,8 @@ SEXP R_igraph_hsbm_list_game(SEXP n, SEXP mlist, SEXP rholist, SEXP Clist, SEXP /-------------------------------------------*/ SEXP R_igraph_correlated_game(SEXP old_graph, SEXP corr, SEXP p, SEXP permutation) { /* Declarations */ - igraph_t c_old_graph; igraph_t c_new_graph; + igraph_t c_old_graph; igraph_real_t c_corr; igraph_real_t c_p; igraph_vector_int_t c_permutation; @@ -2051,7 +2036,7 @@ SEXP R_igraph_correlated_game(SEXP old_graph, SEXP corr, SEXP p, SEXP permutatio } /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_correlated_game(&c_old_graph, &c_new_graph, c_corr, c_p, (Rf_isNull(permutation) ? NULL : &c_permutation))); + IGRAPH_R_CHECK(igraph_correlated_game(&c_new_graph, &c_old_graph, c_corr, c_p, (Rf_isNull(permutation) ? NULL : &c_permutation))); PutRNGstate(); /* Convert output */ @@ -2747,15 +2732,16 @@ SEXP R_igraph_voronoi(SEXP graph, SEXP generators, SEXP weights, SEXP mode, SEXP /*-------------------------------------------/ / igraph_get_all_simple_paths / /-------------------------------------------*/ -SEXP R_igraph_get_all_simple_paths(SEXP graph, SEXP from, SEXP to, SEXP minlen, SEXP maxlen, SEXP mode) { +SEXP R_igraph_get_all_simple_paths(SEXP graph, SEXP from, SEXP to, SEXP mode, SEXP minlen, SEXP maxlen, SEXP max_results) { /* Declarations */ igraph_t c_graph; igraph_vector_int_list_t c_res; igraph_integer_t c_from; igraph_vs_t c_to; + igraph_neimode_t c_mode; igraph_integer_t c_minlen; igraph_integer_t c_maxlen; - igraph_neimode_t c_mode; + igraph_integer_t c_max_results; SEXP res; SEXP r_result; @@ -2768,14 +2754,16 @@ SEXP R_igraph_get_all_simple_paths(SEXP graph, SEXP from, SEXP to, SEXP minlen, c_from = (igraph_integer_t) REAL(from)[0]; igraph_vector_int_t c_to_data; R_SEXP_to_igraph_vs(to, &c_graph, &c_to, &c_to_data); + c_mode = (igraph_neimode_t) Rf_asInteger(mode); IGRAPH_R_CHECK_INT(minlen); c_minlen = (igraph_integer_t) REAL(minlen)[0]; IGRAPH_R_CHECK_INT(maxlen); c_maxlen = (igraph_integer_t) REAL(maxlen)[0]; - c_mode = (igraph_neimode_t) Rf_asInteger(mode); + IGRAPH_R_CHECK_INT(max_results); + c_max_results = (igraph_integer_t) REAL(max_results)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_get_all_simple_paths(&c_graph, &c_res, c_from, c_to, c_minlen, c_maxlen, c_mode)); + IGRAPH_R_CHECK(igraph_get_all_simple_paths(&c_graph, &c_res, c_from, c_to, c_mode, c_minlen, c_maxlen, c_max_results)); PutRNGstate(); /* Convert output */ @@ -3102,33 +3090,36 @@ SEXP R_igraph_spanner(SEXP graph, SEXP stretch, SEXP weights) { /*-------------------------------------------/ / igraph_betweenness_cutoff / /-------------------------------------------*/ -SEXP R_igraph_betweenness_cutoff(SEXP graph, SEXP vids, SEXP directed, SEXP weights, SEXP cutoff) { +SEXP R_igraph_betweenness_cutoff(SEXP graph, SEXP weights, SEXP vids, SEXP directed, SEXP normalized, SEXP cutoff) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_t c_res; igraph_vs_t c_vids; igraph_bool_t c_directed; - igraph_vector_t c_weights; + igraph_bool_t c_normalized; igraph_real_t c_cutoff; SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); igraph_vector_int_t c_vids_data; R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + IGRAPH_R_CHECK_BOOL(normalized); + c_normalized = LOGICAL(normalized)[0]; IGRAPH_R_CHECK_REAL(cutoff); c_cutoff = REAL(cutoff)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_betweenness_cutoff(&c_graph, &c_res, c_vids, c_directed, (Rf_isNull(weights) ? NULL : &c_weights), c_cutoff)); + IGRAPH_R_CHECK(igraph_betweenness_cutoff(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_vids, c_directed, c_normalized, c_cutoff)); PutRNGstate(); /* Convert output */ @@ -3146,36 +3137,39 @@ SEXP R_igraph_betweenness_cutoff(SEXP graph, SEXP vids, SEXP directed, SEXP weig /*-------------------------------------------/ / igraph_betweenness_subset / /-------------------------------------------*/ -SEXP R_igraph_betweenness_subset(SEXP graph, SEXP vids, SEXP directed, SEXP sources, SEXP targets, SEXP weights) { +SEXP R_igraph_betweenness_subset(SEXP graph, SEXP weights, SEXP vids, SEXP sources, SEXP targets, SEXP directed, SEXP normalized) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_t c_res; igraph_vs_t c_vids; - igraph_bool_t c_directed; igraph_vs_t c_sources; igraph_vs_t c_targets; - igraph_vector_t c_weights; + igraph_bool_t c_directed; + igraph_bool_t c_normalized; SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); igraph_vector_int_t c_vids_data; R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; igraph_vector_int_t c_sources_data; R_SEXP_to_igraph_vs(sources, &c_graph, &c_sources, &c_sources_data); igraph_vector_int_t c_targets_data; R_SEXP_to_igraph_vs(targets, &c_graph, &c_targets, &c_targets_data); - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + IGRAPH_R_CHECK_BOOL(normalized); + c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_betweenness_subset(&c_graph, &c_res, c_vids, c_directed, c_sources, c_targets, (Rf_isNull(weights) ? NULL : &c_weights))); + IGRAPH_R_CHECK(igraph_betweenness_subset(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_vids, c_sources, c_targets, c_directed, c_normalized)); PutRNGstate(); /* Convert output */ @@ -3197,33 +3191,41 @@ SEXP R_igraph_betweenness_subset(SEXP graph, SEXP vids, SEXP directed, SEXP sour /*-------------------------------------------/ / igraph_edge_betweenness / /-------------------------------------------*/ -SEXP R_igraph_edge_betweenness(SEXP graph, SEXP directed, SEXP weights) { +SEXP R_igraph_edge_betweenness(SEXP graph, SEXP weights, SEXP eids, SEXP directed, SEXP normalized) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_t c_res; + igraph_es_t c_eids; igraph_bool_t c_directed; - igraph_vector_t c_weights; + igraph_bool_t c_normalized; SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); + igraph_vector_int_t c_eids_data; + IGRAPH_R_CHECK(R_SEXP_to_igraph_es(eids, &c_graph, &c_eids, &c_eids_data)); IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + IGRAPH_R_CHECK_BOOL(normalized); + c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_edge_betweenness(&c_graph, &c_res, c_directed, (Rf_isNull(weights) ? NULL : &c_weights))); + IGRAPH_R_CHECK(igraph_edge_betweenness(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_eids, c_directed, c_normalized)); PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); igraph_vector_destroy(&c_res); IGRAPH_FINALLY_CLEAN(1); + igraph_vector_int_destroy(&c_eids_data); + igraph_es_destroy(&c_eids); r_result = res; UNPROTECT(1); @@ -3233,36 +3235,44 @@ SEXP R_igraph_edge_betweenness(SEXP graph, SEXP directed, SEXP weights) { /*-------------------------------------------/ / igraph_edge_betweenness_cutoff / /-------------------------------------------*/ -SEXP R_igraph_edge_betweenness_cutoff(SEXP graph, SEXP directed, SEXP weights, SEXP cutoff) { +SEXP R_igraph_edge_betweenness_cutoff(SEXP graph, SEXP weights, SEXP eids, SEXP directed, SEXP normalized, SEXP cutoff) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_t c_res; + igraph_es_t c_eids; igraph_bool_t c_directed; - igraph_vector_t c_weights; + igraph_bool_t c_normalized; igraph_real_t c_cutoff; SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); + igraph_vector_int_t c_eids_data; + IGRAPH_R_CHECK(R_SEXP_to_igraph_es(eids, &c_graph, &c_eids, &c_eids_data)); IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + IGRAPH_R_CHECK_BOOL(normalized); + c_normalized = LOGICAL(normalized)[0]; IGRAPH_R_CHECK_REAL(cutoff); c_cutoff = REAL(cutoff)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_edge_betweenness_cutoff(&c_graph, &c_res, c_directed, (Rf_isNull(weights) ? NULL : &c_weights), c_cutoff)); + IGRAPH_R_CHECK(igraph_edge_betweenness_cutoff(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_eids, c_directed, c_normalized, c_cutoff)); PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); igraph_vector_destroy(&c_res); IGRAPH_FINALLY_CLEAN(1); + igraph_vector_int_destroy(&c_eids_data); + igraph_es_destroy(&c_eids); r_result = res; UNPROTECT(1); @@ -3272,48 +3282,51 @@ SEXP R_igraph_edge_betweenness_cutoff(SEXP graph, SEXP directed, SEXP weights, S /*-------------------------------------------/ / igraph_edge_betweenness_subset / /-------------------------------------------*/ -SEXP R_igraph_edge_betweenness_subset(SEXP graph, SEXP eids, SEXP directed, SEXP sources, SEXP targets, SEXP weights) { +SEXP R_igraph_edge_betweenness_subset(SEXP graph, SEXP weights, SEXP sources, SEXP targets, SEXP eids, SEXP directed, SEXP normalized) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_t c_res; - igraph_es_t c_eids; - igraph_bool_t c_directed; igraph_vs_t c_sources; igraph_vs_t c_targets; - igraph_vector_t c_weights; + igraph_es_t c_eids; + igraph_bool_t c_directed; + igraph_bool_t c_normalized; SEXP res; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_res, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_res); - igraph_vector_int_t c_eids_data; - IGRAPH_R_CHECK(R_SEXP_to_igraph_es(eids, &c_graph, &c_eids, &c_eids_data)); - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; igraph_vector_int_t c_sources_data; R_SEXP_to_igraph_vs(sources, &c_graph, &c_sources, &c_sources_data); igraph_vector_int_t c_targets_data; R_SEXP_to_igraph_vs(targets, &c_graph, &c_targets, &c_targets_data); - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + igraph_vector_int_t c_eids_data; + IGRAPH_R_CHECK(R_SEXP_to_igraph_es(eids, &c_graph, &c_eids, &c_eids_data)); + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + IGRAPH_R_CHECK_BOOL(normalized); + c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_edge_betweenness_subset(&c_graph, &c_res, c_eids, c_directed, c_sources, c_targets, (Rf_isNull(weights) ? NULL : &c_weights))); + IGRAPH_R_CHECK(igraph_edge_betweenness_subset(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_sources, c_targets, c_eids, c_directed, c_normalized)); PutRNGstate(); /* Convert output */ PROTECT(res=R_igraph_vector_to_SEXP(&c_res)); igraph_vector_destroy(&c_res); IGRAPH_FINALLY_CLEAN(1); - igraph_vector_int_destroy(&c_eids_data); - igraph_es_destroy(&c_eids); igraph_vector_int_destroy(&c_sources_data); igraph_vs_destroy(&c_sources); igraph_vector_int_destroy(&c_targets_data); igraph_vs_destroy(&c_targets); + igraph_vector_int_destroy(&c_eids_data); + igraph_es_destroy(&c_eids); r_result = res; UNPROTECT(1); @@ -3369,17 +3382,17 @@ SEXP R_igraph_harmonic_centrality_cutoff(SEXP graph, SEXP vids, SEXP mode, SEXP /*-------------------------------------------/ / igraph_personalized_pagerank / /-------------------------------------------*/ -SEXP R_igraph_personalized_pagerank(SEXP graph, SEXP algo, SEXP vids, SEXP directed, SEXP damping, SEXP personalized, SEXP weights, SEXP options) { +SEXP R_igraph_personalized_pagerank(SEXP graph, SEXP weights, SEXP reset, SEXP damping, SEXP directed, SEXP vids, SEXP algo, SEXP options) { /* Declarations */ igraph_t c_graph; - igraph_pagerank_algo_t c_algo; + igraph_vector_t c_weights; igraph_vector_t c_vector; igraph_real_t c_value; - igraph_vs_t c_vids; - igraph_bool_t c_directed; + igraph_vector_t c_reset; igraph_real_t c_damping; - igraph_vector_t c_personalized; - igraph_vector_t c_weights; + igraph_bool_t c_directed; + igraph_vs_t c_vids; + igraph_pagerank_algo_t c_algo; igraph_arpack_options_t c_options1; void* c_options; SEXP vector; @@ -3388,21 +3401,21 @@ SEXP R_igraph_personalized_pagerank(SEXP graph, SEXP algo, SEXP vids, SEXP direc SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - c_algo = (igraph_pagerank_algo_t) Rf_asInteger(algo); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_vector, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_vector); - igraph_vector_int_t c_vids_data; - R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; + if (!Rf_isNull(reset)) { + R_SEXP_to_vector(reset, &c_reset); + } IGRAPH_R_CHECK_REAL(damping); c_damping = REAL(damping)[0]; - if (!Rf_isNull(personalized)) { - R_SEXP_to_vector(personalized, &c_personalized); - } - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + igraph_vector_int_t c_vids_data; + R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); + c_algo = (igraph_pagerank_algo_t) Rf_asInteger(algo); if (!Rf_isNull(options)) { if (c_algo == IGRAPH_PAGERANK_ALGO_ARPACK) { R_SEXP_to_igraph_arpack_options(options, &c_options1); @@ -3413,7 +3426,7 @@ SEXP R_igraph_personalized_pagerank(SEXP graph, SEXP algo, SEXP vids, SEXP direc } /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_personalized_pagerank(&c_graph, c_algo, &c_vector, &c_value, c_vids, c_directed, c_damping, (Rf_isNull(personalized) ? NULL : &c_personalized), (Rf_isNull(weights) ? NULL : &c_weights), c_options)); + IGRAPH_R_CHECK(igraph_personalized_pagerank(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_vector, &c_value, (Rf_isNull(reset) ? NULL : &c_reset), c_damping, c_directed, c_vids, c_algo, c_options)); PutRNGstate(); /* Convert output */ @@ -3447,17 +3460,17 @@ SEXP R_igraph_personalized_pagerank(SEXP graph, SEXP algo, SEXP vids, SEXP direc /*-------------------------------------------/ / igraph_personalized_pagerank_vs / /-------------------------------------------*/ -SEXP R_igraph_personalized_pagerank_vs(SEXP graph, SEXP algo, SEXP vids, SEXP directed, SEXP damping, SEXP reset_vids, SEXP weights, SEXP options) { +SEXP R_igraph_personalized_pagerank_vs(SEXP graph, SEXP weights, SEXP reset_vids, SEXP damping, SEXP directed, SEXP vids, SEXP algo, SEXP options) { /* Declarations */ igraph_t c_graph; - igraph_pagerank_algo_t c_algo; + igraph_vector_t c_weights; igraph_vector_t c_vector; igraph_real_t c_value; - igraph_vs_t c_vids; - igraph_bool_t c_directed; - igraph_real_t c_damping; igraph_vs_t c_reset_vids; - igraph_vector_t c_weights; + igraph_real_t c_damping; + igraph_bool_t c_directed; + igraph_vs_t c_vids; + igraph_pagerank_algo_t c_algo; igraph_arpack_options_t c_options1; void* c_options; SEXP vector; @@ -3466,20 +3479,20 @@ SEXP R_igraph_personalized_pagerank_vs(SEXP graph, SEXP algo, SEXP vids, SEXP di SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - c_algo = (igraph_pagerank_algo_t) Rf_asInteger(algo); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK(igraph_vector_init(&c_vector, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &c_vector); - igraph_vector_int_t c_vids_data; - R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); - IGRAPH_R_CHECK_BOOL(directed); - c_directed = LOGICAL(directed)[0]; - IGRAPH_R_CHECK_REAL(damping); - c_damping = REAL(damping)[0]; igraph_vector_int_t c_reset_vids_data; R_SEXP_to_igraph_vs(reset_vids, &c_graph, &c_reset_vids, &c_reset_vids_data); - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + IGRAPH_R_CHECK_REAL(damping); + c_damping = REAL(damping)[0]; + IGRAPH_R_CHECK_BOOL(directed); + c_directed = LOGICAL(directed)[0]; + igraph_vector_int_t c_vids_data; + R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); + c_algo = (igraph_pagerank_algo_t) Rf_asInteger(algo); if (!Rf_isNull(options)) { if (c_algo == IGRAPH_PAGERANK_ALGO_ARPACK) { R_SEXP_to_igraph_arpack_options(options, &c_options1); @@ -3490,7 +3503,7 @@ SEXP R_igraph_personalized_pagerank_vs(SEXP graph, SEXP algo, SEXP vids, SEXP di } /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_personalized_pagerank_vs(&c_graph, c_algo, &c_vector, &c_value, c_vids, c_directed, c_damping, c_reset_vids, (Rf_isNull(weights) ? NULL : &c_weights), c_options)); + IGRAPH_R_CHECK(igraph_personalized_pagerank_vs(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_vector, &c_value, c_reset_vids, c_damping, c_directed, c_vids, c_algo, c_options)); PutRNGstate(); /* Convert output */ @@ -3501,10 +3514,10 @@ SEXP R_igraph_personalized_pagerank_vs(SEXP graph, SEXP algo, SEXP vids, SEXP di IGRAPH_FINALLY_CLEAN(1); PROTECT(value=NEW_NUMERIC(1)); REAL(value)[0]=c_value; - igraph_vector_int_destroy(&c_vids_data); - igraph_vs_destroy(&c_vids); igraph_vector_int_destroy(&c_reset_vids_data); igraph_vs_destroy(&c_reset_vids); + igraph_vector_int_destroy(&c_vids_data); + igraph_vs_destroy(&c_vids); if (c_algo == IGRAPH_PAGERANK_ALGO_ARPACK) { PROTECT(options = R_igraph_arpack_options_to_SEXP(&c_options1)); } else { @@ -3997,9 +4010,10 @@ SEXP R_igraph_maxdegree(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { /*-------------------------------------------/ / igraph_density / /-------------------------------------------*/ -SEXP R_igraph_density(SEXP graph, SEXP loops) { +SEXP R_igraph_density(SEXP graph, SEXP weights, SEXP loops) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_real_t c_res; igraph_bool_t c_loops; SEXP res; @@ -4007,11 +4021,14 @@ SEXP R_igraph_density(SEXP graph, SEXP loops) { SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_density(&c_graph, &c_res, c_loops)); + IGRAPH_R_CHECK(igraph_density(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_res, c_loops)); PutRNGstate(); /* Convert output */ @@ -5248,9 +5265,10 @@ SEXP R_igraph_centralization_eigenvector_centrality_tmax(SEXP graph, SEXP nodes, /*-------------------------------------------/ / igraph_assortativity_nominal / /-------------------------------------------*/ -SEXP R_igraph_assortativity_nominal(SEXP graph, SEXP types, SEXP directed, SEXP normalized) { +SEXP R_igraph_assortativity_nominal(SEXP graph, SEXP weights, SEXP types, SEXP directed, SEXP normalized) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_int_t c_types; igraph_real_t c_res; igraph_bool_t c_directed; @@ -5260,6 +5278,9 @@ SEXP R_igraph_assortativity_nominal(SEXP graph, SEXP types, SEXP directed, SEXP SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } R_SEXP_to_vector_int_copy(types, &c_types); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_types); IGRAPH_R_CHECK_BOOL(directed); @@ -5268,7 +5289,7 @@ SEXP R_igraph_assortativity_nominal(SEXP graph, SEXP types, SEXP directed, SEXP c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_assortativity_nominal(&c_graph, &c_types, &c_res, c_directed, c_normalized)); + IGRAPH_R_CHECK(igraph_assortativity_nominal(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_types, &c_res, c_directed, c_normalized)); PutRNGstate(); /* Convert output */ @@ -5285,9 +5306,10 @@ SEXP R_igraph_assortativity_nominal(SEXP graph, SEXP types, SEXP directed, SEXP /*-------------------------------------------/ / igraph_assortativity / /-------------------------------------------*/ -SEXP R_igraph_assortativity(SEXP graph, SEXP values, SEXP values_in, SEXP directed, SEXP normalized) { +SEXP R_igraph_assortativity(SEXP graph, SEXP weights, SEXP values, SEXP values_in, SEXP directed, SEXP normalized) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_t c_values; igraph_vector_t c_values_in; igraph_real_t c_res; @@ -5298,6 +5320,9 @@ SEXP R_igraph_assortativity(SEXP graph, SEXP values, SEXP values_in, SEXP direct SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } R_SEXP_to_vector(values, &c_values); if (!Rf_isNull(values_in)) { R_SEXP_to_vector(values_in, &c_values_in); @@ -5308,7 +5333,7 @@ SEXP R_igraph_assortativity(SEXP graph, SEXP values, SEXP values_in, SEXP direct c_normalized = LOGICAL(normalized)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_assortativity(&c_graph, &c_values, (Rf_isNull(values_in) ? NULL : &c_values_in), &c_res, c_directed, c_normalized)); + IGRAPH_R_CHECK(igraph_assortativity(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_values, (Rf_isNull(values_in) ? NULL : &c_values_in), &c_res, c_directed, c_normalized)); PutRNGstate(); /* Convert output */ @@ -6403,7 +6428,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 multiple) { +SEXP R_igraph_bipartite_game_gnm(SEXP n1, SEXP n2, SEXP m, SEXP directed, SEXP mode, SEXP allowed_edge_types, SEXP edge_labeled) { /* Declarations */ igraph_t c_graph; igraph_vector_bool_t c_types; @@ -6412,7 +6437,8 @@ 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; + igraph_edge_type_sw_t c_allowed_edge_types; + igraph_bool_t c_edge_labeled; SEXP graph; SEXP types; @@ -6429,11 +6455,12 @@ 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]; + c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types); + IGRAPH_R_CHECK_BOOL(edge_labeled); + c_edge_labeled = LOGICAL(edge_labeled)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_bipartite_game_gnm(&c_graph, &c_types, c_n1, c_n2, c_m, c_directed, c_mode, c_multiple)); + IGRAPH_R_CHECK(igraph_bipartite_game_gnm(&c_graph, &c_types, c_n1, c_n2, c_m, c_directed, c_mode, c_allowed_edge_types, c_edge_labeled)); PutRNGstate(); /* Convert output */ @@ -7043,12 +7070,13 @@ SEXP R_igraph_is_clique(SEXP graph, SEXP candidate, SEXP directed) { /*-------------------------------------------/ / igraph_cliques / /-------------------------------------------*/ -SEXP R_igraph_cliques(SEXP graph, SEXP min_size, SEXP max_size) { +SEXP R_igraph_cliques(SEXP graph, SEXP min_size, SEXP max_size, SEXP max_results) { /* Declarations */ igraph_t c_graph; igraph_vector_int_list_t c_res; igraph_integer_t c_min_size; igraph_integer_t c_max_size; + igraph_integer_t c_max_results; SEXP res; SEXP r_result; @@ -7062,9 +7090,11 @@ SEXP R_igraph_cliques(SEXP graph, SEXP min_size, SEXP max_size) { c_min_size = (igraph_integer_t) REAL(min_size)[0]; IGRAPH_R_CHECK_INT(max_size); c_max_size = (igraph_integer_t) REAL(max_size)[0]; + IGRAPH_R_CHECK_INT(max_results); + c_max_results = (igraph_integer_t) REAL(max_results)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_cliques(&c_graph, &c_res, c_min_size, c_max_size)); + IGRAPH_R_CHECK(igraph_cliques(&c_graph, &c_res, c_min_size, c_max_size, c_max_results)); PutRNGstate(); /* Convert output */ @@ -7208,14 +7238,15 @@ SEXP R_igraph_clique_number(SEXP graph) { /*-------------------------------------------/ / igraph_weighted_cliques / /-------------------------------------------*/ -SEXP R_igraph_weighted_cliques(SEXP graph, SEXP vertex_weights, SEXP min_weight, SEXP max_weight, SEXP maximal) { +SEXP R_igraph_weighted_cliques(SEXP graph, SEXP vertex_weights, SEXP maximal, SEXP min_weight, SEXP max_weight, SEXP max_results) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_vertex_weights; igraph_vector_int_list_t c_res; + igraph_bool_t c_maximal; igraph_real_t c_min_weight; igraph_real_t c_max_weight; - igraph_bool_t c_maximal; + igraph_integer_t c_max_results; SEXP res; SEXP r_result; @@ -7228,15 +7259,17 @@ SEXP R_igraph_weighted_cliques(SEXP graph, SEXP vertex_weights, SEXP min_weight, igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_res); + IGRAPH_R_CHECK_BOOL(maximal); + c_maximal = LOGICAL(maximal)[0]; IGRAPH_R_CHECK_REAL(min_weight); c_min_weight = REAL(min_weight)[0]; IGRAPH_R_CHECK_REAL(max_weight); c_max_weight = REAL(max_weight)[0]; - IGRAPH_R_CHECK_BOOL(maximal); - c_maximal = LOGICAL(maximal)[0]; + IGRAPH_R_CHECK_INT(max_results); + c_max_results = (igraph_integer_t) REAL(max_results)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_weighted_cliques(&c_graph, (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), &c_res, c_min_weight, c_max_weight, c_maximal)); + IGRAPH_R_CHECK(igraph_weighted_cliques(&c_graph, (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), &c_res, c_maximal, c_min_weight, c_max_weight, c_max_results)); PutRNGstate(); /* Convert output */ @@ -7688,24 +7721,20 @@ SEXP R_igraph_layout_sugiyama(SEXP graph, SEXP layers, SEXP hgap, SEXP vgap, SEX /* Declarations */ igraph_t c_graph; igraph_matrix_t c_res; - igraph_t c_extd_graph; - igraph_vector_int_t c_extd_to_orig_eids; + igraph_matrix_list_t c_routing; igraph_vector_int_t c_layers; igraph_real_t c_hgap; igraph_real_t c_vgap; igraph_integer_t c_maxiter; igraph_vector_t c_weights; SEXP res; - SEXP extd_graph; - SEXP extd_to_orig_eids; + SEXP routing; SEXP r_result, r_names; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - IGRAPH_R_CHECK(igraph_vector_int_init(&c_extd_to_orig_eids, 0)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_extd_to_orig_eids); if (!Rf_isNull(layers)) { R_SEXP_to_vector_int_copy(layers, &c_layers); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_layers); @@ -7724,32 +7753,23 @@ SEXP R_igraph_layout_sugiyama(SEXP graph, SEXP layers, SEXP hgap, SEXP vgap, SEX } /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_layout_sugiyama(&c_graph, &c_res, &c_extd_graph, &c_extd_to_orig_eids, (Rf_isNull(layers) ? NULL : &c_layers), c_hgap, c_vgap, c_maxiter, (Rf_isNull(weights) ? NULL : &c_weights))); + IGRAPH_R_CHECK(igraph_layout_sugiyama(&c_graph, &c_res, &c_routing, (Rf_isNull(layers) ? NULL : &c_layers), c_hgap, c_vgap, c_maxiter, (Rf_isNull(weights) ? NULL : &c_weights))); PutRNGstate(); /* Convert output */ - PROTECT(r_result=NEW_LIST(3)); - PROTECT(r_names=NEW_CHARACTER(3)); + PROTECT(r_result=NEW_LIST(2)); + PROTECT(r_names=NEW_CHARACTER(2)); PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); igraph_matrix_destroy(&c_res); IGRAPH_FINALLY_CLEAN(1); - IGRAPH_FINALLY(igraph_destroy, &c_extd_graph); - PROTECT(extd_graph=R_igraph_to_SEXP(&c_extd_graph)); - IGRAPH_I_DESTROY(&c_extd_graph); - IGRAPH_FINALLY_CLEAN(1); - PROTECT(extd_to_orig_eids=R_igraph_vector_int_to_SEXPp1(&c_extd_to_orig_eids)); - igraph_vector_int_destroy(&c_extd_to_orig_eids); - IGRAPH_FINALLY_CLEAN(1); igraph_vector_int_destroy(&c_layers); IGRAPH_FINALLY_CLEAN(1); SET_VECTOR_ELT(r_result, 0, res); - SET_VECTOR_ELT(r_result, 1, extd_graph); - SET_VECTOR_ELT(r_result, 2, extd_to_orig_eids); + SET_VECTOR_ELT(r_result, 1, routing); SET_STRING_ELT(r_names, 0, Rf_mkChar("res")); - SET_STRING_ELT(r_names, 1, Rf_mkChar("extd_graph")); - SET_STRING_ELT(r_names, 2, Rf_mkChar("extd_to_orig_eids")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("routing")); SET_NAMES(r_result, r_names); - UNPROTECT(4); + UNPROTECT(3); UNPROTECT(1); return(r_result); @@ -8078,12 +8098,12 @@ SEXP R_igraph_layout_align(SEXP graph, SEXP layout) { /*-------------------------------------------/ / igraph_similarity_dice / /-------------------------------------------*/ -SEXP R_igraph_similarity_dice(SEXP graph, SEXP vit_from, SEXP vit_to, SEXP mode, SEXP loops) { +SEXP R_igraph_similarity_dice(SEXP graph, SEXP from, SEXP to, SEXP mode, SEXP loops) { /* Declarations */ igraph_t c_graph; igraph_matrix_t c_res; - igraph_vs_t c_vit_from; - igraph_vs_t c_vit_to; + igraph_vs_t c_from; + igraph_vs_t c_to; igraph_neimode_t c_mode; igraph_bool_t c_loops; SEXP res; @@ -8093,26 +8113,26 @@ SEXP R_igraph_similarity_dice(SEXP graph, SEXP vit_from, SEXP vit_to, SEXP mode, R_SEXP_to_igraph(graph, &c_graph); IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - 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); + igraph_vector_int_t c_from_data; + R_SEXP_to_igraph_vs(from, &c_graph, &c_from, &c_from_data); + igraph_vector_int_t c_to_data; + R_SEXP_to_igraph_vs(to, &c_graph, &c_to, &c_to_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_similarity_dice(&c_graph, &c_res, c_vit_from, c_vit_to, c_mode, c_loops)); + IGRAPH_R_CHECK(igraph_similarity_dice(&c_graph, &c_res, c_from, c_to, c_mode, c_loops)); PutRNGstate(); /* 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_vit_from_data); - igraph_vs_destroy(&c_vit_from); - igraph_vector_int_destroy(&c_vit_to_data); - igraph_vs_destroy(&c_vit_to); + igraph_vector_int_destroy(&c_from_data); + igraph_vs_destroy(&c_from); + igraph_vector_int_destroy(&c_to_data); + igraph_vs_destroy(&c_to); r_result = res; UNPROTECT(1); @@ -8236,12 +8256,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 vit_from, SEXP vit_to, SEXP mode, SEXP loops) { +SEXP R_igraph_similarity_jaccard(SEXP graph, SEXP from, SEXP to, SEXP mode, SEXP loops) { /* Declarations */ igraph_t c_graph; igraph_matrix_t c_res; - igraph_vs_t c_vit_from; - igraph_vs_t c_vit_to; + igraph_vs_t c_from; + igraph_vs_t c_to; igraph_neimode_t c_mode; igraph_bool_t c_loops; SEXP res; @@ -8251,26 +8271,26 @@ SEXP R_igraph_similarity_jaccard(SEXP graph, SEXP vit_from, SEXP vit_to, SEXP mo R_SEXP_to_igraph(graph, &c_graph); IGRAPH_R_CHECK(igraph_matrix_init(&c_res, 0, 0)); IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - 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); + igraph_vector_int_t c_from_data; + R_SEXP_to_igraph_vs(from, &c_graph, &c_from, &c_from_data); + igraph_vector_int_t c_to_data; + R_SEXP_to_igraph_vs(to, &c_graph, &c_to, &c_to_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_similarity_jaccard(&c_graph, &c_res, c_vit_from, c_vit_to, c_mode, c_loops)); + IGRAPH_R_CHECK(igraph_similarity_jaccard(&c_graph, &c_res, c_from, c_to, c_mode, c_loops)); PutRNGstate(); /* 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_vit_from_data); - igraph_vs_destroy(&c_vit_from); - igraph_vector_int_destroy(&c_vit_to_data); - igraph_vs_destroy(&c_vit_to); + igraph_vector_int_destroy(&c_from_data); + igraph_vs_destroy(&c_from); + igraph_vector_int_destroy(&c_to_data); + igraph_vs_destroy(&c_to); r_result = res; UNPROTECT(1); @@ -8736,15 +8756,84 @@ SEXP R_igraph_community_leiden(SEXP graph, SEXP weights, SEXP vertex_out_weights } /*-------------------------------------------/ -/ igraph_split_join_distance / +/ igraph_community_leiden_simple / /-------------------------------------------*/ -SEXP R_igraph_split_join_distance(SEXP comm1, SEXP comm2) { +SEXP R_igraph_community_leiden_simple(SEXP graph, SEXP weights, SEXP objective, SEXP resolution, SEXP beta, SEXP start, SEXP n_iterations, SEXP membership) { /* Declarations */ - igraph_vector_int_t c_comm1; - igraph_vector_int_t c_comm2; - igraph_integer_t c_distance12; - igraph_integer_t c_distance21; - SEXP distance12; + igraph_t c_graph; + igraph_vector_t c_weights; + igraph_leiden_objective_t c_objective; + igraph_real_t c_resolution; + igraph_real_t c_beta; + igraph_bool_t c_start; + igraph_integer_t c_n_iterations; + igraph_vector_int_t c_membership; + igraph_integer_t c_nb_clusters; + igraph_real_t c_quality; + SEXP nb_clusters; + SEXP quality; + + SEXP r_result, r_names; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } + c_objective = (igraph_leiden_objective_t) Rf_asInteger(objective); + IGRAPH_R_CHECK_REAL(resolution); + c_resolution = REAL(resolution)[0]; + IGRAPH_R_CHECK_REAL(beta); + c_beta = REAL(beta)[0]; + IGRAPH_R_CHECK_BOOL(start); + c_start = LOGICAL(start)[0]; + IGRAPH_R_CHECK_INT(n_iterations); + c_n_iterations = (igraph_integer_t) REAL(n_iterations)[0]; + if (!Rf_isNull(membership)) { + IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(membership, &c_membership)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); + } else { + IGRAPH_R_CHECK(igraph_vector_int_init(&c_membership, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); + } + c_nb_clusters=0; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_community_leiden_simple(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), c_objective, c_resolution, c_beta, c_start, c_n_iterations, &c_membership, &c_nb_clusters, &c_quality)); + PutRNGstate(); + + /* Convert output */ + PROTECT(r_result=NEW_LIST(3)); + PROTECT(r_names=NEW_CHARACTER(3)); + PROTECT(membership=R_igraph_vector_int_to_SEXP(&c_membership)); + igraph_vector_int_destroy(&c_membership); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(nb_clusters=NEW_NUMERIC(1)); + REAL(nb_clusters)[0]=(double) c_nb_clusters; + PROTECT(quality=NEW_NUMERIC(1)); + REAL(quality)[0]=c_quality; + SET_VECTOR_ELT(r_result, 0, membership); + SET_VECTOR_ELT(r_result, 1, nb_clusters); + SET_VECTOR_ELT(r_result, 2, quality); + SET_STRING_ELT(r_names, 0, Rf_mkChar("membership")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("nb_clusters")); + SET_STRING_ELT(r_names, 2, Rf_mkChar("quality")); + SET_NAMES(r_result, r_names); + UNPROTECT(4); + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_split_join_distance / +/-------------------------------------------*/ +SEXP R_igraph_split_join_distance(SEXP comm1, SEXP comm2) { + /* Declarations */ + igraph_vector_int_t c_comm1; + igraph_vector_int_t c_comm2; + igraph_integer_t c_distance12; + igraph_integer_t c_distance21; + SEXP distance12; SEXP distance21; SEXP r_result, r_names; @@ -8785,12 +8874,14 @@ SEXP R_igraph_split_join_distance(SEXP comm1, SEXP comm2) { /*-------------------------------------------/ / igraph_community_infomap / /-------------------------------------------*/ -SEXP R_igraph_community_infomap(SEXP graph, SEXP edge_weights, SEXP vertex_weights, SEXP nb_trials) { +SEXP R_igraph_community_infomap(SEXP graph, SEXP edge_weights, SEXP vertex_weights, SEXP nb_trials, SEXP is_regularized, SEXP regularization_strength) { /* Declarations */ igraph_t c_graph; igraph_vector_t c_edge_weights; igraph_vector_t c_vertex_weights; igraph_integer_t c_nb_trials; + igraph_bool_t c_is_regularized; + igraph_real_t c_regularization_strength; igraph_vector_int_t c_membership; igraph_real_t c_codelength; SEXP membership; @@ -8807,11 +8898,15 @@ SEXP R_igraph_community_infomap(SEXP graph, SEXP edge_weights, SEXP vertex_weigh } IGRAPH_R_CHECK_INT(nb_trials); c_nb_trials = (igraph_integer_t) REAL(nb_trials)[0]; + IGRAPH_R_CHECK_BOOL(is_regularized); + c_is_regularized = LOGICAL(is_regularized)[0]; + IGRAPH_R_CHECK_REAL(regularization_strength); + c_regularization_strength = REAL(regularization_strength)[0]; IGRAPH_R_CHECK(igraph_vector_int_init(&c_membership, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_community_infomap(&c_graph, (Rf_isNull(edge_weights) ? NULL : &c_edge_weights), (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), c_nb_trials, &c_membership, &c_codelength)); + IGRAPH_R_CHECK(igraph_community_infomap(&c_graph, (Rf_isNull(edge_weights) ? NULL : &c_edge_weights), (Rf_isNull(vertex_weights) ? NULL : &c_vertex_weights), c_nb_trials, c_is_regularized, c_regularization_strength, &c_membership, &c_codelength)); PutRNGstate(); /* Convert output */ @@ -10880,24 +10975,24 @@ SEXP R_igraph_count_automorphisms(SEXP graph, SEXP colors) { SEXP R_igraph_isoclass_subgraph(SEXP graph, SEXP vids) { /* Declarations */ igraph_t c_graph; - igraph_vector_int_t c_vids; + igraph_vs_t c_vids; igraph_integer_t c_isoclass; SEXP isoclass; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); - IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(vids, &c_vids)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vids); + igraph_vector_int_t c_vids_data; + R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); c_isoclass=0; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_isoclass_subgraph(&c_graph, &c_vids, &c_isoclass)); + IGRAPH_R_CHECK(igraph_isoclass_subgraph(&c_graph, c_vids, &c_isoclass)); PutRNGstate(); /* Convert output */ - igraph_vector_int_destroy(&c_vids); - IGRAPH_FINALLY_CLEAN(1); + igraph_vector_int_destroy(&c_vids_data); + igraph_vs_destroy(&c_vids); PROTECT(isoclass=NEW_NUMERIC(1)); REAL(isoclass)[0]=(double) c_isoclass; r_result = isoclass; @@ -12156,9 +12251,9 @@ SEXP R_igraph_sir(SEXP graph, SEXP beta, SEXP gamma, SEXP no_sim) { } /*-------------------------------------------/ -/ igraph_convex_hull / +/ igraph_convex_hull_2d / /-------------------------------------------*/ -SEXP R_igraph_convex_hull(SEXP data) { +SEXP R_igraph_convex_hull_2d(SEXP data) { /* Declarations */ igraph_matrix_t c_data; igraph_vector_int_t c_resverts; @@ -12175,7 +12270,7 @@ SEXP R_igraph_convex_hull(SEXP data) { IGRAPH_FINALLY(igraph_matrix_destroy, &c_rescoords); /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_convex_hull(&c_data, &c_resverts, &c_rescoords)); + IGRAPH_R_CHECK(igraph_convex_hull_2d(&c_data, &c_resverts, &c_rescoords)); PutRNGstate(); /* Convert output */ @@ -12305,7 +12400,7 @@ SEXP R_igraph_find_cycle(SEXP graph, SEXP mode) { /*-------------------------------------------/ / igraph_simple_cycles / /-------------------------------------------*/ -SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP min_cycle_length, SEXP max_cycle_length) { +SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP min_cycle_length, SEXP max_cycle_length, SEXP max_results) { /* Declarations */ igraph_t c_graph; igraph_vector_int_list_t c_vertices; @@ -12313,6 +12408,7 @@ SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP min_cycle_length, SEXP m igraph_neimode_t c_mode; igraph_integer_t c_min_cycle_length; igraph_integer_t c_max_cycle_length; + igraph_integer_t c_max_results; SEXP vertices; SEXP edges; @@ -12332,9 +12428,11 @@ SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP min_cycle_length, SEXP m c_min_cycle_length = (igraph_integer_t) REAL(min_cycle_length)[0]; IGRAPH_R_CHECK_INT(max_cycle_length); c_max_cycle_length = (igraph_integer_t) REAL(max_cycle_length)[0]; + IGRAPH_R_CHECK_INT(max_results); + c_max_results = (igraph_integer_t) REAL(max_results)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_simple_cycles(&c_graph, &c_vertices, &c_edges, c_mode, c_min_cycle_length, c_max_cycle_length)); + IGRAPH_R_CHECK(igraph_simple_cycles(&c_graph, &c_vertices, &c_edges, c_mode, c_min_cycle_length, c_max_cycle_length, c_max_results)); PutRNGstate(); /* Convert output */ @@ -12483,18 +12581,21 @@ SEXP R_igraph_eulerian_cycle(SEXP graph) { /*-------------------------------------------/ / igraph_fundamental_cycles / /-------------------------------------------*/ -SEXP R_igraph_fundamental_cycles(SEXP graph, SEXP start, SEXP bfs_cutoff, SEXP weights) { +SEXP R_igraph_fundamental_cycles(SEXP graph, SEXP weights, SEXP start, SEXP bfs_cutoff) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_int_list_t c_basis; igraph_integer_t c_start; - igraph_integer_t c_bfs_cutoff; - igraph_vector_t c_weights; + igraph_real_t c_bfs_cutoff; SEXP basis; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } if (0 != igraph_vector_int_list_init(&c_basis, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } @@ -12502,14 +12603,11 @@ SEXP R_igraph_fundamental_cycles(SEXP graph, SEXP start, SEXP bfs_cutoff, SEXP w if (!Rf_isNull(start)) { c_start = (igraph_integer_t) REAL(start)[0]; } - IGRAPH_R_CHECK_INT(bfs_cutoff); - c_bfs_cutoff = (igraph_integer_t) REAL(bfs_cutoff)[0]; - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } + IGRAPH_R_CHECK_REAL(bfs_cutoff); + c_bfs_cutoff = REAL(bfs_cutoff)[0]; /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_fundamental_cycles(&c_graph, &c_basis, (Rf_isNull(start) ? -1 : c_start), c_bfs_cutoff, (Rf_isNull(weights) ? NULL : &c_weights))); + IGRAPH_R_CHECK(igraph_fundamental_cycles(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_basis, (Rf_isNull(start) ? NULL : c_start), c_bfs_cutoff)); PutRNGstate(); /* Convert output */ @@ -12525,35 +12623,35 @@ SEXP R_igraph_fundamental_cycles(SEXP graph, SEXP start, SEXP bfs_cutoff, SEXP w /*-------------------------------------------/ / igraph_minimum_cycle_basis / /-------------------------------------------*/ -SEXP R_igraph_minimum_cycle_basis(SEXP graph, SEXP bfs_cutoff, SEXP complete, SEXP use_cycle_order, SEXP weights) { +SEXP R_igraph_minimum_cycle_basis(SEXP graph, SEXP weights, SEXP bfs_cutoff, SEXP complete, SEXP use_cycle_order) { /* Declarations */ igraph_t c_graph; + igraph_vector_t c_weights; igraph_vector_int_list_t c_basis; - igraph_integer_t c_bfs_cutoff; + igraph_real_t c_bfs_cutoff; igraph_bool_t c_complete; igraph_bool_t c_use_cycle_order; - igraph_vector_t c_weights; SEXP basis; SEXP r_result; /* Convert input */ R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(weights)) { + R_SEXP_to_vector(weights, &c_weights); + } if (0 != igraph_vector_int_list_init(&c_basis, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_basis); - IGRAPH_R_CHECK_INT(bfs_cutoff); - c_bfs_cutoff = (igraph_integer_t) REAL(bfs_cutoff)[0]; + IGRAPH_R_CHECK_REAL(bfs_cutoff); + c_bfs_cutoff = REAL(bfs_cutoff)[0]; IGRAPH_R_CHECK_BOOL(complete); c_complete = LOGICAL(complete)[0]; IGRAPH_R_CHECK_BOOL(use_cycle_order); c_use_cycle_order = LOGICAL(use_cycle_order)[0]; - if (!Rf_isNull(weights)) { - R_SEXP_to_vector(weights, &c_weights); - } /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_minimum_cycle_basis(&c_graph, &c_basis, c_bfs_cutoff, c_complete, c_use_cycle_order, (Rf_isNull(weights) ? NULL : &c_weights))); + IGRAPH_R_CHECK(igraph_minimum_cycle_basis(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_basis, c_bfs_cutoff, c_complete, c_use_cycle_order)); PutRNGstate(); /* Convert output */ @@ -12822,7 +12920,7 @@ SEXP R_igraph_random_spanning_tree(SEXP graph, SEXP vid) { } /* Call igraph */ GetRNGstate(); - IGRAPH_R_CHECK(igraph_random_spanning_tree(&c_graph, &c_res, (Rf_isNull(vid) ? -1 : c_vid))); + IGRAPH_R_CHECK(igraph_random_spanning_tree(&c_graph, &c_res, (Rf_isNull(vid) ? NULL : c_vid))); PutRNGstate(); /* Convert output */ @@ -12908,6 +13006,227 @@ SEXP R_igraph_nearest_neighbor_graph(SEXP points, SEXP metric, SEXP neighbors, S return(r_result); } +/*-------------------------------------------/ +/ igraph_delaunay_graph / +/-------------------------------------------*/ +SEXP R_igraph_delaunay_graph(SEXP points) { + /* Declarations */ + igraph_t c_graph; + igraph_matrix_t c_points; + SEXP graph; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_matrix(points, &c_points); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_delaunay_graph(&c_graph, &c_points)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + r_result = graph; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_gabriel_graph / +/-------------------------------------------*/ +SEXP R_igraph_gabriel_graph(SEXP points) { + /* Declarations */ + igraph_t c_graph; + igraph_matrix_t c_points; + SEXP graph; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_matrix(points, &c_points); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_gabriel_graph(&c_graph, &c_points)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + r_result = graph; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_relative_neighborhood_graph / +/-------------------------------------------*/ +SEXP R_igraph_relative_neighborhood_graph(SEXP points) { + /* Declarations */ + igraph_t c_graph; + igraph_matrix_t c_points; + SEXP graph; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_matrix(points, &c_points); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_relative_neighborhood_graph(&c_graph, &c_points)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + r_result = graph; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_lune_beta_skeleton / +/-------------------------------------------*/ +SEXP R_igraph_lune_beta_skeleton(SEXP points, SEXP beta) { + /* Declarations */ + igraph_t c_graph; + igraph_matrix_t c_points; + igraph_real_t c_beta; + SEXP graph; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_matrix(points, &c_points); + IGRAPH_R_CHECK_REAL(beta); + c_beta = REAL(beta)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_lune_beta_skeleton(&c_graph, &c_points, c_beta)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + r_result = graph; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_circle_beta_skeleton / +/-------------------------------------------*/ +SEXP R_igraph_circle_beta_skeleton(SEXP points, SEXP beta) { + /* Declarations */ + igraph_t c_graph; + igraph_matrix_t c_points; + igraph_real_t c_beta; + SEXP graph; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_matrix(points, &c_points); + IGRAPH_R_CHECK_REAL(beta); + c_beta = REAL(beta)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_circle_beta_skeleton(&c_graph, &c_points, c_beta)); + PutRNGstate(); + + /* Convert output */ + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + r_result = graph; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_beta_weighted_gabriel_graph / +/-------------------------------------------*/ +SEXP R_igraph_beta_weighted_gabriel_graph(SEXP points, SEXP max_beta) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_t c_weights; + igraph_matrix_t c_points; + igraph_real_t c_max_beta; + SEXP graph; + SEXP weights; + + SEXP r_result, r_names; + /* Convert input */ + IGRAPH_R_CHECK(igraph_vector_init(&c_weights, 0)); + IGRAPH_FINALLY(igraph_vector_destroy, &c_weights); + weights=R_GlobalEnv; /* hack to have a non-NULL value */ + R_SEXP_to_matrix(points, &c_points); + IGRAPH_R_CHECK_REAL(max_beta); + c_max_beta = REAL(max_beta)[0]; + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_beta_weighted_gabriel_graph(&c_graph, &c_weights, &c_points, c_max_beta)); + PutRNGstate(); + + /* Convert output */ + PROTECT(r_result=NEW_LIST(2)); + PROTECT(r_names=NEW_CHARACTER(2)); + IGRAPH_FINALLY(igraph_destroy, &c_graph); + PROTECT(graph=R_igraph_to_SEXP(&c_graph)); + IGRAPH_I_DESTROY(&c_graph); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(weights=R_igraph_0orvector_to_SEXP(&c_weights)); + igraph_vector_destroy(&c_weights); + IGRAPH_FINALLY_CLEAN(1); + SET_VECTOR_ELT(r_result, 0, graph); + SET_VECTOR_ELT(r_result, 1, weights); + SET_STRING_ELT(r_names, 0, Rf_mkChar("graph")); + SET_STRING_ELT(r_names, 1, Rf_mkChar("weights")); + SET_NAMES(r_result, r_names); + UNPROTECT(3); + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_spatial_edge_lengths / +/-------------------------------------------*/ +SEXP R_igraph_spatial_edge_lengths(SEXP graph, SEXP points, SEXP METRIC) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_t c_lengths; + igraph_matrix_t c_points; + igraph_metric_t c_METRIC; + SEXP lengths; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + R_SEXP_to_matrix(points, &c_points); + c_METRIC = (igraph_metric_t) Rf_asInteger(METRIC); + /* Call igraph */ + GetRNGstate(); + IGRAPH_R_CHECK(igraph_spatial_edge_lengths(&c_graph, c_lengths, &c_points, c_METRIC)); + PutRNGstate(); + + /* Convert output */ + + r_result = lengths; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_vertex_coloring_greedy / /-------------------------------------------*/ diff --git a/src/sources-igraph.mk b/src/sources-igraph.mk index 8cf31ee3e5f..6b0876ae8fd 100644 --- a/src/sources-igraph.mk +++ b/src/sources-igraph.mk @@ -1 +1 @@ -IGRAPH_SOURCES=vendor/arpack/dgetv0.o vendor/arpack/dlaqrb.o vendor/arpack/dmout.o vendor/arpack/dnaitr.o vendor/arpack/dnapps.o vendor/arpack/dnaup2.o vendor/arpack/dnaupd.o vendor/arpack/dnconv.o vendor/arpack/dneigh.o vendor/arpack/dneupd.o vendor/arpack/dngets.o vendor/arpack/dsaitr.o vendor/arpack/dsapps.o vendor/arpack/dsaup2.o vendor/arpack/dsaupd.o vendor/arpack/dsconv.o vendor/arpack/dseigt.o vendor/arpack/dsesrt.o vendor/arpack/dseupd.o vendor/arpack/dsgets.o vendor/arpack/dsortc.o vendor/arpack/dsortr.o vendor/arpack/dstatn.o vendor/arpack/dstats.o vendor/arpack/dstqrb.o vendor/arpack/dvout.o vendor/arpack/ivout.o vendor/arpack/second.o vendor/arpack/wrap.o vendor/cigraph/src/centrality/betweenness.o vendor/cigraph/src/centrality/centrality_other.o vendor/cigraph/src/centrality/centralization.o vendor/cigraph/src/centrality/closeness.o vendor/cigraph/src/centrality/coreness.o vendor/cigraph/src/centrality/eigenvector.o vendor/cigraph/src/centrality/hub_authority.o vendor/cigraph/src/centrality/pagerank.o vendor/cigraph/src/centrality/prpack.o vendor/cigraph/src/centrality/prpack/prpack_base_graph.o vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_ge_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_gs_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_scc_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_schur_graph.o vendor/cigraph/src/centrality/prpack/prpack_result.o vendor/cigraph/src/centrality/prpack/prpack_solver.o vendor/cigraph/src/centrality/prpack/prpack_utils.o vendor/cigraph/src/centrality/truss.o vendor/cigraph/src/cliques/cliquer/cliquer.o vendor/cigraph/src/cliques/cliquer/cliquer_graph.o vendor/cigraph/src/cliques/cliquer/reorder.o vendor/cigraph/src/cliques/cliquer_wrapper.o vendor/cigraph/src/cliques/cliques.o vendor/cigraph/src/cliques/glet.o vendor/cigraph/src/cliques/maximal_cliques.o vendor/cigraph/src/community/community_misc.o vendor/cigraph/src/community/edge_betweenness.o vendor/cigraph/src/community/fast_modularity.o vendor/cigraph/src/community/fluid.o vendor/cigraph/src/community/infomap.o vendor/cigraph/src/community/label_propagation.o vendor/cigraph/src/community/leading_eigenvector.o vendor/cigraph/src/community/leiden.o vendor/cigraph/src/community/louvain.o vendor/cigraph/src/community/modularity.o vendor/cigraph/src/community/optimal_modularity.o vendor/cigraph/src/community/spinglass/NetDataTypes.o vendor/cigraph/src/community/spinglass/NetRoutines.o vendor/cigraph/src/community/spinglass/clustertool.o vendor/cigraph/src/community/spinglass/pottsmodel_2.o vendor/cigraph/src/community/voronoi.o vendor/cigraph/src/community/walktrap/walktrap.o vendor/cigraph/src/community/walktrap/walktrap_communities.o vendor/cigraph/src/community/walktrap/walktrap_graph.o vendor/cigraph/src/community/walktrap/walktrap_heap.o vendor/cigraph/src/connectivity/cohesive_blocks.o vendor/cigraph/src/connectivity/components.o vendor/cigraph/src/connectivity/percolation.o vendor/cigraph/src/connectivity/reachability.o vendor/cigraph/src/connectivity/separators.o vendor/cigraph/src/constructors/adjacency.o vendor/cigraph/src/constructors/atlas.o vendor/cigraph/src/constructors/basic_constructors.o vendor/cigraph/src/constructors/circulant.o vendor/cigraph/src/constructors/de_bruijn.o vendor/cigraph/src/constructors/famous.o vendor/cigraph/src/constructors/full.o vendor/cigraph/src/constructors/generalized_petersen.o vendor/cigraph/src/constructors/kautz.o vendor/cigraph/src/constructors/lattices.o vendor/cigraph/src/constructors/lcf.o vendor/cigraph/src/constructors/linegraph.o vendor/cigraph/src/constructors/mycielskian.o vendor/cigraph/src/constructors/prufer.o vendor/cigraph/src/constructors/regular.o vendor/cigraph/src/constructors/trees.o vendor/cigraph/src/core/bitset.o vendor/cigraph/src/core/bitset_list.o vendor/cigraph/src/core/buckets.o vendor/cigraph/src/core/cutheap.o vendor/cigraph/src/core/dqueue.o vendor/cigraph/src/core/error.o vendor/cigraph/src/core/estack.o vendor/cigraph/src/core/fixed_vectorlist.o vendor/cigraph/src/core/genheap.o vendor/cigraph/src/core/grid.o vendor/cigraph/src/core/heap.o vendor/cigraph/src/core/indheap.o vendor/cigraph/src/core/interruption.o vendor/cigraph/src/core/marked_queue.o vendor/cigraph/src/core/matrix.o vendor/cigraph/src/core/matrix_list.o vendor/cigraph/src/core/memory.o vendor/cigraph/src/core/printing.o vendor/cigraph/src/core/progress.o vendor/cigraph/src/core/psumtree.o vendor/cigraph/src/core/set.o vendor/cigraph/src/core/setup.o vendor/cigraph/src/core/sparsemat.o vendor/cigraph/src/core/stack.o vendor/cigraph/src/core/statusbar.o vendor/cigraph/src/core/strvector.o vendor/cigraph/src/core/trie.o vendor/cigraph/src/core/vector.o vendor/cigraph/src/core/vector_list.o vendor/cigraph/src/core/vector_ptr.o vendor/cigraph/src/cycles/simple_cycles.o vendor/cigraph/src/flow/flow.o vendor/cigraph/src/flow/flow_conversion.o vendor/cigraph/src/flow/st-cuts.o vendor/cigraph/src/games/barabasi.o vendor/cigraph/src/games/callaway_traits.o vendor/cigraph/src/games/chung_lu.o vendor/cigraph/src/games/citations.o vendor/cigraph/src/games/correlated.o vendor/cigraph/src/games/degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_random.o vendor/cigraph/src/games/dotproduct.o vendor/cigraph/src/games/erdos_renyi.o vendor/cigraph/src/games/establishment.o vendor/cigraph/src/games/forestfire.o vendor/cigraph/src/games/grg.o vendor/cigraph/src/games/growing_random.o vendor/cigraph/src/games/islands.o vendor/cigraph/src/games/k_regular.o vendor/cigraph/src/games/preference.o vendor/cigraph/src/games/recent_degree.o vendor/cigraph/src/games/sbm.o vendor/cigraph/src/games/static_fitness.o vendor/cigraph/src/games/tree.o vendor/cigraph/src/games/watts_strogatz.o vendor/cigraph/src/graph/adjlist.o vendor/cigraph/src/graph/attributes.o vendor/cigraph/src/graph/basic_query.o vendor/cigraph/src/graph/caching.o vendor/cigraph/src/graph/cattributes.o vendor/cigraph/src/graph/graph_list.o vendor/cigraph/src/graph/iterators.o vendor/cigraph/src/graph/type_common.o vendor/cigraph/src/graph/type_indexededgelist.o vendor/cigraph/src/graph/visitors.o vendor/cigraph/src/hrg/hrg.o vendor/cigraph/src/hrg/hrg_types.o vendor/cigraph/src/internal/glpk_support.o vendor/cigraph/src/internal/hacks.o vendor/cigraph/src/internal/lsap.o vendor/cigraph/src/internal/qsort.o vendor/cigraph/src/internal/qsort_r.o vendor/cigraph/src/internal/utils.o vendor/cigraph/src/io/dimacs.o vendor/cigraph/src/io/dl.o vendor/cigraph/src/io/dot.o vendor/cigraph/src/io/edgelist.o vendor/cigraph/src/io/gml-tree.o vendor/cigraph/src/io/gml.o vendor/cigraph/src/io/graphdb.o vendor/cigraph/src/io/graphml.o vendor/cigraph/src/io/leda.o vendor/cigraph/src/io/lgl.o vendor/cigraph/src/io/ncol.o vendor/cigraph/src/io/pajek.o vendor/cigraph/src/io/parse_utils.o vendor/cigraph/src/isomorphism/bliss.o vendor/cigraph/src/isomorphism/bliss/defs.o vendor/cigraph/src/isomorphism/bliss/graph.o vendor/cigraph/src/isomorphism/bliss/heap.o vendor/cigraph/src/isomorphism/bliss/orbit.o vendor/cigraph/src/isomorphism/bliss/partition.o vendor/cigraph/src/isomorphism/bliss/uintseqhash.o vendor/cigraph/src/isomorphism/bliss/utils.o vendor/cigraph/src/isomorphism/isoclasses.o vendor/cigraph/src/isomorphism/isomorphism_misc.o vendor/cigraph/src/isomorphism/lad.o vendor/cigraph/src/isomorphism/queries.o vendor/cigraph/src/isomorphism/vf2.o vendor/cigraph/src/layout/align.o vendor/cigraph/src/layout/circular.o vendor/cigraph/src/layout/davidson_harel.o vendor/cigraph/src/layout/drl/DensityGrid.o vendor/cigraph/src/layout/drl/DensityGrid_3d.o vendor/cigraph/src/layout/drl/drl_graph.o vendor/cigraph/src/layout/drl/drl_graph_3d.o vendor/cigraph/src/layout/drl/drl_layout.o vendor/cigraph/src/layout/drl/drl_layout_3d.o vendor/cigraph/src/layout/drl/drl_parse.o vendor/cigraph/src/layout/fruchterman_reingold.o vendor/cigraph/src/layout/gem.o vendor/cigraph/src/layout/graphopt.o vendor/cigraph/src/layout/kamada_kawai.o vendor/cigraph/src/layout/large_graph.o vendor/cigraph/src/layout/layout_bipartite.o vendor/cigraph/src/layout/layout_grid.o vendor/cigraph/src/layout/layout_random.o vendor/cigraph/src/layout/mds.o vendor/cigraph/src/layout/merge_dla.o vendor/cigraph/src/layout/merge_grid.o vendor/cigraph/src/layout/reingold_tilford.o vendor/cigraph/src/layout/sugiyama.o vendor/cigraph/src/layout/umap.o vendor/cigraph/src/linalg/arpack.o vendor/cigraph/src/linalg/blas.o vendor/cigraph/src/linalg/eigen.o vendor/cigraph/src/linalg/lapack.o vendor/cigraph/src/math/complex.o vendor/cigraph/src/math/safe_intop.o vendor/cigraph/src/math/utils.o vendor/cigraph/src/misc/bipartite.o vendor/cigraph/src/misc/chordality.o vendor/cigraph/src/misc/cocitation.o vendor/cigraph/src/misc/coloring.o vendor/cigraph/src/misc/conversion.o vendor/cigraph/src/misc/cycle_bases.o vendor/cigraph/src/misc/degree_sequence.o vendor/cigraph/src/misc/embedding.o vendor/cigraph/src/misc/feedback_arc_set.o vendor/cigraph/src/misc/graphicality.o vendor/cigraph/src/misc/matching.o vendor/cigraph/src/misc/mixing.o vendor/cigraph/src/misc/motifs.o vendor/cigraph/src/misc/order_cycle.o vendor/cigraph/src/misc/other.o vendor/cigraph/src/misc/power_law_fit.o vendor/cigraph/src/misc/scan.o vendor/cigraph/src/misc/sir.o vendor/cigraph/src/misc/spanning_trees.o vendor/cigraph/src/operators/add_edge.o vendor/cigraph/src/operators/complementer.o vendor/cigraph/src/operators/compose.o vendor/cigraph/src/operators/connect_neighborhood.o vendor/cigraph/src/operators/contract.o vendor/cigraph/src/operators/difference.o vendor/cigraph/src/operators/disjoint_union.o vendor/cigraph/src/operators/intersection.o vendor/cigraph/src/operators/join.o vendor/cigraph/src/operators/misc_internal.o vendor/cigraph/src/operators/permute.o vendor/cigraph/src/operators/products.o vendor/cigraph/src/operators/reverse.o vendor/cigraph/src/operators/rewire.o vendor/cigraph/src/operators/rewire_edges.o vendor/cigraph/src/operators/simplify.o vendor/cigraph/src/operators/subgraph.o vendor/cigraph/src/operators/union.o vendor/cigraph/src/paths/all_shortest_paths.o vendor/cigraph/src/paths/astar.o vendor/cigraph/src/paths/bellman_ford.o vendor/cigraph/src/paths/dijkstra.o vendor/cigraph/src/paths/distances.o vendor/cigraph/src/paths/eulerian.o vendor/cigraph/src/paths/floyd_warshall.o vendor/cigraph/src/paths/histogram.o vendor/cigraph/src/paths/johnson.o vendor/cigraph/src/paths/random_walk.o vendor/cigraph/src/paths/shortest_paths.o vendor/cigraph/src/paths/simple_paths.o vendor/cigraph/src/paths/sparsifier.o vendor/cigraph/src/paths/unweighted.o vendor/cigraph/src/paths/voronoi.o vendor/cigraph/src/paths/widest_paths.o vendor/cigraph/src/properties/basic_properties.o vendor/cigraph/src/properties/complete.o vendor/cigraph/src/properties/constraint.o vendor/cigraph/src/properties/convergence_degree.o vendor/cigraph/src/properties/dag.o vendor/cigraph/src/properties/degrees.o vendor/cigraph/src/properties/ecc.o vendor/cigraph/src/properties/girth.o vendor/cigraph/src/properties/loops.o vendor/cigraph/src/properties/multiplicity.o vendor/cigraph/src/properties/neighborhood.o vendor/cigraph/src/properties/perfect.o vendor/cigraph/src/properties/rich_club.o vendor/cigraph/src/properties/spectral.o vendor/cigraph/src/properties/trees.o vendor/cigraph/src/properties/triangles.o vendor/cigraph/src/random/random.o vendor/cigraph/src/random/random_device.o vendor/cigraph/src/random/rng_glibc2.o vendor/cigraph/src/random/rng_mt19937.o vendor/cigraph/src/random/rng_pcg32.o vendor/cigraph/src/random/rng_pcg64.o vendor/cigraph/src/random/sampling.o vendor/cigraph/src/spatial/nearest_neighbor.o vendor/cigraph/src/version.o vendor/cigraph/vendor/cs/cs_add.o vendor/cigraph/vendor/cs/cs_amd.o vendor/cigraph/vendor/cs/cs_chol.o vendor/cigraph/vendor/cs/cs_cholsol.o vendor/cigraph/vendor/cs/cs_compress.o vendor/cigraph/vendor/cs/cs_counts.o vendor/cigraph/vendor/cs/cs_cumsum.o vendor/cigraph/vendor/cs/cs_dfs.o vendor/cigraph/vendor/cs/cs_dmperm.o vendor/cigraph/vendor/cs/cs_droptol.o vendor/cigraph/vendor/cs/cs_dropzeros.o vendor/cigraph/vendor/cs/cs_dupl.o vendor/cigraph/vendor/cs/cs_entry.o vendor/cigraph/vendor/cs/cs_ereach.o vendor/cigraph/vendor/cs/cs_etree.o vendor/cigraph/vendor/cs/cs_fkeep.o vendor/cigraph/vendor/cs/cs_gaxpy.o vendor/cigraph/vendor/cs/cs_happly.o vendor/cigraph/vendor/cs/cs_house.o vendor/cigraph/vendor/cs/cs_ipvec.o vendor/cigraph/vendor/cs/cs_leaf.o vendor/cigraph/vendor/cs/cs_load.o vendor/cigraph/vendor/cs/cs_lsolve.o vendor/cigraph/vendor/cs/cs_ltsolve.o vendor/cigraph/vendor/cs/cs_lu.o vendor/cigraph/vendor/cs/cs_lusol.o vendor/cigraph/vendor/cs/cs_malloc.o vendor/cigraph/vendor/cs/cs_maxtrans.o vendor/cigraph/vendor/cs/cs_multiply.o vendor/cigraph/vendor/cs/cs_norm.o vendor/cigraph/vendor/cs/cs_permute.o vendor/cigraph/vendor/cs/cs_pinv.o vendor/cigraph/vendor/cs/cs_post.o vendor/cigraph/vendor/cs/cs_print.o vendor/cigraph/vendor/cs/cs_pvec.o vendor/cigraph/vendor/cs/cs_qr.o vendor/cigraph/vendor/cs/cs_qrsol.o vendor/cigraph/vendor/cs/cs_randperm.o vendor/cigraph/vendor/cs/cs_reach.o vendor/cigraph/vendor/cs/cs_scatter.o vendor/cigraph/vendor/cs/cs_scc.o vendor/cigraph/vendor/cs/cs_schol.o vendor/cigraph/vendor/cs/cs_spsolve.o vendor/cigraph/vendor/cs/cs_sqr.o vendor/cigraph/vendor/cs/cs_symperm.o vendor/cigraph/vendor/cs/cs_tdfs.o vendor/cigraph/vendor/cs/cs_transpose.o vendor/cigraph/vendor/cs/cs_updown.o vendor/cigraph/vendor/cs/cs_usolve.o vendor/cigraph/vendor/cs/cs_util.o vendor/cigraph/vendor/cs/cs_utsolve.o vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.o vendor/cigraph/vendor/infomap/src/core/InfoEdge.o vendor/cigraph/vendor/infomap/src/core/InfoNode.o vendor/cigraph/vendor/infomap/src/core/InfomapBase.o vendor/cigraph/vendor/infomap/src/core/MemMapEquation.o vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.o vendor/cigraph/vendor/infomap/src/core/StateNetwork.o vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.o vendor/cigraph/vendor/infomap/src/io/ClusterMap.o vendor/cigraph/vendor/infomap/src/io/Config.o vendor/cigraph/vendor/infomap/src/io/Network.o vendor/cigraph/vendor/infomap/src/io/Output.o vendor/cigraph/vendor/infomap/src/io/ProgramInterface.o vendor/cigraph/vendor/infomap/src/utils/FileURI.o vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.o vendor/cigraph/vendor/infomap/src/utils/Log.o vendor/cigraph/vendor/pcg/pcg-advance-128.o vendor/cigraph/vendor/pcg/pcg-advance-64.o vendor/cigraph/vendor/pcg/pcg-output-128.o vendor/cigraph/vendor/pcg/pcg-output-32.o vendor/cigraph/vendor/pcg/pcg-output-64.o vendor/cigraph/vendor/pcg/pcg-rngs-128.o vendor/cigraph/vendor/pcg/pcg-rngs-64.o vendor/cigraph/vendor/plfit/gss.o vendor/cigraph/vendor/plfit/hzeta.o vendor/cigraph/vendor/plfit/kolmogorov.o vendor/cigraph/vendor/plfit/lbfgs.o vendor/cigraph/vendor/plfit/mt.o vendor/cigraph/vendor/plfit/options.o vendor/cigraph/vendor/plfit/plfit.o vendor/cigraph/vendor/plfit/plfit_error.o vendor/cigraph/vendor/plfit/rbinom.o vendor/cigraph/vendor/plfit/sampling.o vendor/io/dl-lexer.o vendor/io/dl-parser.o vendor/io/gml-lexer.o vendor/io/gml-parser.o vendor/io/lgl-lexer.o vendor/io/lgl-parser.o vendor/io/ncol-lexer.o vendor/io/ncol-parser.o vendor/io/pajek-lexer.o vendor/io/pajek-parser.o vendor/simpleraytracer/Color.o vendor/simpleraytracer/Light.o vendor/simpleraytracer/Point.o vendor/simpleraytracer/Ray.o vendor/simpleraytracer/RayTracer.o vendor/simpleraytracer/RayVector.o vendor/simpleraytracer/Shape.o vendor/simpleraytracer/Sphere.o vendor/simpleraytracer/Triangle.o vendor/simpleraytracer/unit_limiter.o vendor/uuid/clear.o vendor/uuid/compare.o vendor/uuid/copy.o vendor/uuid/gen_uuid.o vendor/uuid/isnull.o vendor/uuid/pack.o vendor/uuid/parse.o vendor/uuid/unpack.o vendor/uuid/unparse.o +IGRAPH_SOURCES=vendor/arpack/dgetv0.o vendor/arpack/dlaqrb.o vendor/arpack/dmout.o vendor/arpack/dnaitr.o vendor/arpack/dnapps.o vendor/arpack/dnaup2.o vendor/arpack/dnaupd.o vendor/arpack/dnconv.o vendor/arpack/dneigh.o vendor/arpack/dneupd.o vendor/arpack/dngets.o vendor/arpack/dsaitr.o vendor/arpack/dsapps.o vendor/arpack/dsaup2.o vendor/arpack/dsaupd.o vendor/arpack/dsconv.o vendor/arpack/dseigt.o vendor/arpack/dsesrt.o vendor/arpack/dseupd.o vendor/arpack/dsgets.o vendor/arpack/dsortc.o vendor/arpack/dsortr.o vendor/arpack/dstatn.o vendor/arpack/dstats.o vendor/arpack/dstqrb.o vendor/arpack/dvout.o vendor/arpack/ivout.o vendor/arpack/second.o vendor/arpack/wrap.o vendor/cigraph/src/centrality/betweenness.o vendor/cigraph/src/centrality/centrality_other.o vendor/cigraph/src/centrality/centralization.o vendor/cigraph/src/centrality/closeness.o vendor/cigraph/src/centrality/coreness.o vendor/cigraph/src/centrality/eigenvector.o vendor/cigraph/src/centrality/hub_authority.o vendor/cigraph/src/centrality/pagerank.o vendor/cigraph/src/centrality/prpack.o vendor/cigraph/src/centrality/prpack/prpack_base_graph.o vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_ge_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_gs_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_scc_graph.o vendor/cigraph/src/centrality/prpack/prpack_preprocessed_schur_graph.o vendor/cigraph/src/centrality/prpack/prpack_result.o vendor/cigraph/src/centrality/prpack/prpack_solver.o vendor/cigraph/src/centrality/prpack/prpack_utils.o vendor/cigraph/src/centrality/truss.o vendor/cigraph/src/cliques/cliquer/cliquer.o vendor/cigraph/src/cliques/cliquer/cliquer_graph.o vendor/cigraph/src/cliques/cliquer/reorder.o vendor/cigraph/src/cliques/cliquer_wrapper.o vendor/cigraph/src/cliques/cliques.o vendor/cigraph/src/cliques/glet.o vendor/cigraph/src/cliques/maximal_cliques.o vendor/cigraph/src/community/community_misc.o vendor/cigraph/src/community/edge_betweenness.o vendor/cigraph/src/community/fast_modularity.o vendor/cigraph/src/community/fluid.o vendor/cigraph/src/community/infomap.o vendor/cigraph/src/community/label_propagation.o vendor/cigraph/src/community/leading_eigenvector.o vendor/cigraph/src/community/leiden.o vendor/cigraph/src/community/louvain.o vendor/cigraph/src/community/modularity.o vendor/cigraph/src/community/optimal_modularity.o vendor/cigraph/src/community/spinglass/NetDataTypes.o vendor/cigraph/src/community/spinglass/NetRoutines.o vendor/cigraph/src/community/spinglass/clustertool.o vendor/cigraph/src/community/spinglass/pottsmodel_2.o vendor/cigraph/src/community/voronoi.o vendor/cigraph/src/community/walktrap/walktrap.o vendor/cigraph/src/community/walktrap/walktrap_communities.o vendor/cigraph/src/community/walktrap/walktrap_graph.o vendor/cigraph/src/community/walktrap/walktrap_heap.o vendor/cigraph/src/connectivity/cohesive_blocks.o vendor/cigraph/src/connectivity/components.o vendor/cigraph/src/connectivity/percolation.o vendor/cigraph/src/connectivity/reachability.o vendor/cigraph/src/connectivity/separators.o vendor/cigraph/src/constructors/adjacency.o vendor/cigraph/src/constructors/atlas.o vendor/cigraph/src/constructors/basic_constructors.o vendor/cigraph/src/constructors/circulant.o vendor/cigraph/src/constructors/de_bruijn.o vendor/cigraph/src/constructors/famous.o vendor/cigraph/src/constructors/full.o vendor/cigraph/src/constructors/generalized_petersen.o vendor/cigraph/src/constructors/kautz.o vendor/cigraph/src/constructors/lattices.o vendor/cigraph/src/constructors/lcf.o vendor/cigraph/src/constructors/linegraph.o vendor/cigraph/src/constructors/mycielskian.o vendor/cigraph/src/constructors/prufer.o vendor/cigraph/src/constructors/regular.o vendor/cigraph/src/constructors/trees.o vendor/cigraph/src/core/bitset.o vendor/cigraph/src/core/bitset_list.o vendor/cigraph/src/core/buckets.o vendor/cigraph/src/core/cutheap.o vendor/cigraph/src/core/dqueue.o vendor/cigraph/src/core/error.o vendor/cigraph/src/core/estack.o vendor/cigraph/src/core/fixed_vectorlist.o vendor/cigraph/src/core/genheap.o vendor/cigraph/src/core/grid.o vendor/cigraph/src/core/heap.o vendor/cigraph/src/core/indheap.o vendor/cigraph/src/core/interruption.o vendor/cigraph/src/core/marked_queue.o vendor/cigraph/src/core/matrix.o vendor/cigraph/src/core/matrix_list.o vendor/cigraph/src/core/memory.o vendor/cigraph/src/core/printing.o vendor/cigraph/src/core/progress.o vendor/cigraph/src/core/psumtree.o vendor/cigraph/src/core/set.o vendor/cigraph/src/core/setup.o vendor/cigraph/src/core/sparsemat.o vendor/cigraph/src/core/stack.o vendor/cigraph/src/core/statusbar.o vendor/cigraph/src/core/strvector.o vendor/cigraph/src/core/trie.o vendor/cigraph/src/core/vector.o vendor/cigraph/src/core/vector_list.o vendor/cigraph/src/core/vector_ptr.o vendor/cigraph/src/cycles/cycle_bases.o vendor/cigraph/src/cycles/feedback_sets.o vendor/cigraph/src/cycles/order_cycle.o vendor/cigraph/src/cycles/simple_cycles.o vendor/cigraph/src/flow/flow.o vendor/cigraph/src/flow/flow_conversion.o vendor/cigraph/src/flow/st-cuts.o vendor/cigraph/src/games/barabasi.o vendor/cigraph/src/games/callaway_traits.o vendor/cigraph/src/games/chung_lu.o vendor/cigraph/src/games/citations.o vendor/cigraph/src/games/correlated.o vendor/cigraph/src/games/degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.o vendor/cigraph/src/games/degree_sequence_vl/gengraph_random.o vendor/cigraph/src/games/dotproduct.o vendor/cigraph/src/games/erdos_renyi.o vendor/cigraph/src/games/establishment.o vendor/cigraph/src/games/forestfire.o vendor/cigraph/src/games/grg.o vendor/cigraph/src/games/growing_random.o vendor/cigraph/src/games/islands.o vendor/cigraph/src/games/k_regular.o vendor/cigraph/src/games/preference.o vendor/cigraph/src/games/recent_degree.o vendor/cigraph/src/games/sbm.o vendor/cigraph/src/games/static_fitness.o vendor/cigraph/src/games/tree.o vendor/cigraph/src/games/watts_strogatz.o vendor/cigraph/src/graph/adjlist.o vendor/cigraph/src/graph/attributes.o vendor/cigraph/src/graph/basic_query.o vendor/cigraph/src/graph/caching.o vendor/cigraph/src/graph/cattributes.o vendor/cigraph/src/graph/graph_list.o vendor/cigraph/src/graph/iterators.o vendor/cigraph/src/graph/type_common.o vendor/cigraph/src/graph/type_indexededgelist.o vendor/cigraph/src/graph/visitors.o vendor/cigraph/src/hrg/hrg.o vendor/cigraph/src/hrg/hrg_types.o vendor/cigraph/src/internal/glpk_support.o vendor/cigraph/src/internal/hacks.o vendor/cigraph/src/internal/lsap.o vendor/cigraph/src/internal/qsort.o vendor/cigraph/src/internal/qsort_r.o vendor/cigraph/src/internal/utils.o vendor/cigraph/src/io/dimacs.o vendor/cigraph/src/io/dl.o vendor/cigraph/src/io/dot.o vendor/cigraph/src/io/edgelist.o vendor/cigraph/src/io/gml-tree.o vendor/cigraph/src/io/gml.o vendor/cigraph/src/io/graphdb.o vendor/cigraph/src/io/graphml.o vendor/cigraph/src/io/leda.o vendor/cigraph/src/io/lgl.o vendor/cigraph/src/io/ncol.o vendor/cigraph/src/io/pajek.o vendor/cigraph/src/io/parse_utils.o vendor/cigraph/src/isomorphism/bliss.o vendor/cigraph/src/isomorphism/bliss/defs.o vendor/cigraph/src/isomorphism/bliss/graph.o vendor/cigraph/src/isomorphism/bliss/heap.o vendor/cigraph/src/isomorphism/bliss/orbit.o vendor/cigraph/src/isomorphism/bliss/partition.o vendor/cigraph/src/isomorphism/bliss/uintseqhash.o vendor/cigraph/src/isomorphism/bliss/utils.o vendor/cigraph/src/isomorphism/isoclasses.o vendor/cigraph/src/isomorphism/isomorphism_misc.o vendor/cigraph/src/isomorphism/lad.o vendor/cigraph/src/isomorphism/queries.o vendor/cigraph/src/isomorphism/vf2.o vendor/cigraph/src/layout/align.o vendor/cigraph/src/layout/circular.o vendor/cigraph/src/layout/davidson_harel.o vendor/cigraph/src/layout/drl/DensityGrid.o vendor/cigraph/src/layout/drl/DensityGrid_3d.o vendor/cigraph/src/layout/drl/drl_graph.o vendor/cigraph/src/layout/drl/drl_graph_3d.o vendor/cigraph/src/layout/drl/drl_layout.o vendor/cigraph/src/layout/drl/drl_layout_3d.o vendor/cigraph/src/layout/drl/drl_parse.o vendor/cigraph/src/layout/fruchterman_reingold.o vendor/cigraph/src/layout/gem.o vendor/cigraph/src/layout/graphopt.o vendor/cigraph/src/layout/kamada_kawai.o vendor/cigraph/src/layout/large_graph.o vendor/cigraph/src/layout/layout_bipartite.o vendor/cigraph/src/layout/layout_grid.o vendor/cigraph/src/layout/layout_random.o vendor/cigraph/src/layout/mds.o vendor/cigraph/src/layout/merge_dla.o vendor/cigraph/src/layout/merge_grid.o vendor/cigraph/src/layout/reingold_tilford.o vendor/cigraph/src/layout/sugiyama.o vendor/cigraph/src/layout/umap.o vendor/cigraph/src/linalg/arpack.o vendor/cigraph/src/linalg/blas.o vendor/cigraph/src/linalg/eigen.o vendor/cigraph/src/linalg/lapack.o vendor/cigraph/src/math/complex.o vendor/cigraph/src/math/safe_intop.o vendor/cigraph/src/math/utils.o vendor/cigraph/src/misc/bipartite.o vendor/cigraph/src/misc/chordality.o vendor/cigraph/src/misc/cocitation.o vendor/cigraph/src/misc/coloring.o vendor/cigraph/src/misc/conversion.o vendor/cigraph/src/misc/degree_sequence.o vendor/cigraph/src/misc/embedding.o vendor/cigraph/src/misc/graphicality.o vendor/cigraph/src/misc/matching.o vendor/cigraph/src/misc/mixing.o vendor/cigraph/src/misc/motifs.o vendor/cigraph/src/misc/other.o vendor/cigraph/src/misc/power_law_fit.o vendor/cigraph/src/misc/scan.o vendor/cigraph/src/misc/sir.o vendor/cigraph/src/misc/spanning_trees.o vendor/cigraph/src/operators/add_edge.o vendor/cigraph/src/operators/complementer.o vendor/cigraph/src/operators/compose.o vendor/cigraph/src/operators/connect_neighborhood.o vendor/cigraph/src/operators/contract.o vendor/cigraph/src/operators/difference.o vendor/cigraph/src/operators/disjoint_union.o vendor/cigraph/src/operators/intersection.o vendor/cigraph/src/operators/join.o vendor/cigraph/src/operators/misc_internal.o vendor/cigraph/src/operators/permute.o vendor/cigraph/src/operators/products.o vendor/cigraph/src/operators/reverse.o vendor/cigraph/src/operators/rewire.o vendor/cigraph/src/operators/rewire_edges.o vendor/cigraph/src/operators/simplify.o vendor/cigraph/src/operators/subgraph.o vendor/cigraph/src/operators/union.o vendor/cigraph/src/paths/all_shortest_paths.o vendor/cigraph/src/paths/astar.o vendor/cigraph/src/paths/bellman_ford.o vendor/cigraph/src/paths/dijkstra.o vendor/cigraph/src/paths/distances.o vendor/cigraph/src/paths/eulerian.o vendor/cigraph/src/paths/floyd_warshall.o vendor/cigraph/src/paths/histogram.o vendor/cigraph/src/paths/johnson.o vendor/cigraph/src/paths/random_walk.o vendor/cigraph/src/paths/shortest_paths.o vendor/cigraph/src/paths/simple_paths.o vendor/cigraph/src/paths/sparsifier.o vendor/cigraph/src/paths/unweighted.o vendor/cigraph/src/paths/voronoi.o vendor/cigraph/src/paths/widest_paths.o vendor/cigraph/src/properties/basic_properties.o vendor/cigraph/src/properties/complete.o vendor/cigraph/src/properties/constraint.o vendor/cigraph/src/properties/convergence_degree.o vendor/cigraph/src/properties/dag.o vendor/cigraph/src/properties/degrees.o vendor/cigraph/src/properties/ecc.o vendor/cigraph/src/properties/girth.o vendor/cigraph/src/properties/loops.o vendor/cigraph/src/properties/multiplicity.o vendor/cigraph/src/properties/neighborhood.o vendor/cigraph/src/properties/perfect.o vendor/cigraph/src/properties/rich_club.o vendor/cigraph/src/properties/spectral.o vendor/cigraph/src/properties/trees.o vendor/cigraph/src/properties/triangles.o vendor/cigraph/src/random/random.o vendor/cigraph/src/random/random_device.o vendor/cigraph/src/random/rng_glibc2.o vendor/cigraph/src/random/rng_mt19937.o vendor/cigraph/src/random/rng_pcg32.o vendor/cigraph/src/random/rng_pcg64.o vendor/cigraph/src/random/sampling.o vendor/cigraph/src/spatial/beta_skeleton.o vendor/cigraph/src/spatial/convex_hull.o vendor/cigraph/src/spatial/delaunay.o vendor/cigraph/src/spatial/edge_lengths.o vendor/cigraph/src/spatial/nearest_neighbor.o vendor/cigraph/src/version.o vendor/cigraph/vendor/cs/cs_add.o vendor/cigraph/vendor/cs/cs_amd.o vendor/cigraph/vendor/cs/cs_chol.o vendor/cigraph/vendor/cs/cs_cholsol.o vendor/cigraph/vendor/cs/cs_compress.o vendor/cigraph/vendor/cs/cs_counts.o vendor/cigraph/vendor/cs/cs_cumsum.o vendor/cigraph/vendor/cs/cs_dfs.o vendor/cigraph/vendor/cs/cs_dmperm.o vendor/cigraph/vendor/cs/cs_droptol.o vendor/cigraph/vendor/cs/cs_dropzeros.o vendor/cigraph/vendor/cs/cs_dupl.o vendor/cigraph/vendor/cs/cs_entry.o vendor/cigraph/vendor/cs/cs_ereach.o vendor/cigraph/vendor/cs/cs_etree.o vendor/cigraph/vendor/cs/cs_fkeep.o vendor/cigraph/vendor/cs/cs_gaxpy.o vendor/cigraph/vendor/cs/cs_happly.o vendor/cigraph/vendor/cs/cs_house.o vendor/cigraph/vendor/cs/cs_ipvec.o vendor/cigraph/vendor/cs/cs_leaf.o vendor/cigraph/vendor/cs/cs_load.o vendor/cigraph/vendor/cs/cs_lsolve.o vendor/cigraph/vendor/cs/cs_ltsolve.o vendor/cigraph/vendor/cs/cs_lu.o vendor/cigraph/vendor/cs/cs_lusol.o vendor/cigraph/vendor/cs/cs_malloc.o vendor/cigraph/vendor/cs/cs_maxtrans.o vendor/cigraph/vendor/cs/cs_multiply.o vendor/cigraph/vendor/cs/cs_norm.o vendor/cigraph/vendor/cs/cs_permute.o vendor/cigraph/vendor/cs/cs_pinv.o vendor/cigraph/vendor/cs/cs_post.o vendor/cigraph/vendor/cs/cs_print.o vendor/cigraph/vendor/cs/cs_pvec.o vendor/cigraph/vendor/cs/cs_qr.o vendor/cigraph/vendor/cs/cs_qrsol.o vendor/cigraph/vendor/cs/cs_randperm.o vendor/cigraph/vendor/cs/cs_reach.o vendor/cigraph/vendor/cs/cs_scatter.o vendor/cigraph/vendor/cs/cs_scc.o vendor/cigraph/vendor/cs/cs_schol.o vendor/cigraph/vendor/cs/cs_spsolve.o vendor/cigraph/vendor/cs/cs_sqr.o vendor/cigraph/vendor/cs/cs_symperm.o vendor/cigraph/vendor/cs/cs_tdfs.o vendor/cigraph/vendor/cs/cs_transpose.o vendor/cigraph/vendor/cs/cs_updown.o vendor/cigraph/vendor/cs/cs_usolve.o vendor/cigraph/vendor/cs/cs_util.o vendor/cigraph/vendor/cs/cs_utsolve.o vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.o vendor/cigraph/vendor/infomap/src/core/InfoEdge.o vendor/cigraph/vendor/infomap/src/core/InfoNode.o vendor/cigraph/vendor/infomap/src/core/InfomapBase.o vendor/cigraph/vendor/infomap/src/core/MemMapEquation.o vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.o vendor/cigraph/vendor/infomap/src/core/StateNetwork.o vendor/cigraph/vendor/infomap/src/core/iterators/InfomapIterator.o vendor/cigraph/vendor/infomap/src/io/ClusterMap.o vendor/cigraph/vendor/infomap/src/io/Config.o vendor/cigraph/vendor/infomap/src/io/Network.o vendor/cigraph/vendor/infomap/src/io/Output.o vendor/cigraph/vendor/infomap/src/io/ProgramInterface.o vendor/cigraph/vendor/infomap/src/utils/FileURI.o vendor/cigraph/vendor/infomap/src/utils/FlowCalculator.o vendor/cigraph/vendor/infomap/src/utils/Log.o vendor/cigraph/vendor/pcg/pcg-advance-128.o vendor/cigraph/vendor/pcg/pcg-advance-64.o vendor/cigraph/vendor/pcg/pcg-output-128.o vendor/cigraph/vendor/pcg/pcg-output-32.o vendor/cigraph/vendor/pcg/pcg-output-64.o vendor/cigraph/vendor/pcg/pcg-rngs-128.o vendor/cigraph/vendor/pcg/pcg-rngs-64.o vendor/cigraph/vendor/plfit/gss.o vendor/cigraph/vendor/plfit/hzeta.o vendor/cigraph/vendor/plfit/kolmogorov.o vendor/cigraph/vendor/plfit/lbfgs.o vendor/cigraph/vendor/plfit/mt.o vendor/cigraph/vendor/plfit/options.o vendor/cigraph/vendor/plfit/plfit.o vendor/cigraph/vendor/plfit/plfit_error.o vendor/cigraph/vendor/plfit/rbinom.o vendor/cigraph/vendor/plfit/sampling.o vendor/cigraph/vendor/qhull/libqhull_r/accessors_r.o vendor/cigraph/vendor/qhull/libqhull_r/geom2_r.o vendor/cigraph/vendor/qhull/libqhull_r/geom_r.o vendor/cigraph/vendor/qhull/libqhull_r/global_r.o vendor/cigraph/vendor/qhull/libqhull_r/io_r.o vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.o vendor/cigraph/vendor/qhull/libqhull_r/mem_r.o vendor/cigraph/vendor/qhull/libqhull_r/merge_r.o vendor/cigraph/vendor/qhull/libqhull_r/poly2_r.o vendor/cigraph/vendor/qhull/libqhull_r/poly_r.o vendor/cigraph/vendor/qhull/libqhull_r/qset_r.o vendor/cigraph/vendor/qhull/libqhull_r/random_r.o vendor/cigraph/vendor/qhull/libqhull_r/rboxlib_r.o vendor/cigraph/vendor/qhull/libqhull_r/stat_r.o vendor/cigraph/vendor/qhull/libqhull_r/user_r.o vendor/cigraph/vendor/qhull/libqhull_r/usermem_r.o vendor/cigraph/vendor/qhull/libqhull_r/userprintf_r.o vendor/cigraph/vendor/qhull/libqhull_r/userprintf_rbox_r.o vendor/io/dl-lexer.o vendor/io/dl-parser.o vendor/io/gml-lexer.o vendor/io/gml-parser.o vendor/io/lgl-lexer.o vendor/io/lgl-parser.o vendor/io/ncol-lexer.o vendor/io/ncol-parser.o vendor/io/pajek-lexer.o vendor/io/pajek-parser.o vendor/simpleraytracer/Color.o vendor/simpleraytracer/Light.o vendor/simpleraytracer/Point.o vendor/simpleraytracer/Ray.o vendor/simpleraytracer/RayTracer.o vendor/simpleraytracer/RayVector.o vendor/simpleraytracer/Shape.o vendor/simpleraytracer/Sphere.o vendor/simpleraytracer/Triangle.o vendor/simpleraytracer/unit_limiter.o vendor/uuid/clear.o vendor/uuid/compare.o vendor/uuid/copy.o vendor/uuid/gen_uuid.o vendor/uuid/isnull.o vendor/uuid/pack.o vendor/uuid/parse.o vendor/uuid/unpack.o vendor/uuid/unparse.o diff --git a/src/vendor/cigraph/.all-contributorsrc b/src/vendor/cigraph/.all-contributorsrc index 49313cde70f..7da6c0da962 100644 --- a/src/vendor/cigraph/.all-contributorsrc +++ b/src/vendor/cigraph/.all-contributorsrc @@ -675,6 +675,51 @@ "contributions": [ "code" ] + }, + { + "login": "VRajesh7649", + "name": "Varun Rajesh", + "avatar_url": "https://avatars.githubusercontent.com/u/56133137?v=4", + "profile": "https://github.com/VRajesh7649", + "contributions": [ + "code" + ] + }, + { + "login": "stevesajeev1", + "name": "Steve Sajeev", + "avatar_url": "https://avatars.githubusercontent.com/u/76565057?v=4", + "profile": "https://github.com/stevesajeev1", + "contributions": [ + "code" + ] + }, + { + "login": "RohithS98", + "name": "Rohith Sudheer", + "avatar_url": "https://avatars.githubusercontent.com/u/36558130?v=4", + "profile": "https://github.com/RohithS98", + "contributions": [ + "code" + ] + }, + { + "login": "GrishaVar", + "name": "Grisha", + "avatar_url": "https://avatars.githubusercontent.com/u/33952698?v=4", + "profile": "https://github.com/GrishaVar", + "contributions": [ + "code" + ] + }, + { + "login": "Antonov548", + "name": "Michael Antonov", + "avatar_url": "https://avatars.githubusercontent.com/u/22891541?v=4", + "profile": "https://github.com/Antonov548", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7 diff --git a/src/vendor/cigraph/.gitignore b/src/vendor/cigraph/.gitignore index 27d538e059c..d451ba1045a 100644 --- a/src/vendor/cigraph/.gitignore +++ b/src/vendor/cigraph/.gitignore @@ -8,3 +8,4 @@ /build /build-* /tools/**/*.pyc +/include/igraph_version.h diff --git a/src/vendor/cigraph/ACKNOWLEDGEMENTS.md b/src/vendor/cigraph/ACKNOWLEDGEMENTS.md index f5af679d320..97021084735 100644 --- a/src/vendor/cigraph/ACKNOWLEDGEMENTS.md +++ b/src/vendor/cigraph/ACKNOWLEDGEMENTS.md @@ -50,6 +50,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #### [bliss 0.75](https://users.aalto.fi/~tjunttil/bliss/) Copyright (c) 2003-2021 Tommi Junttila. @@ -93,6 +94,7 @@ Copyright (C) 2010-2011 Tamás Nepusz. License: [GNU GPLv2][gpl2] or later + #### DrL Copyright 2007 Sandia Corporation. Under the terms of Contract @@ -220,9 +222,9 @@ use or performance of this software. #### [SuiteSparse](http://www.suitesparse.com) - * CXSPARSE: a Concise Sparse Matrix package - Extended. Copyright (c) 2006-2017, Timothy A. Davis. +CXSPARSE: a Concise Sparse Matrix package - Extended. Copyright (c) 2006-2017, Timothy A. Davis. - License: [GNU LGPLv2.1][lgpl2] or later +License: [GNU LGPLv2.1][lgpl2] or later #### [Infomap](https://www.mapequation.org/) @@ -257,8 +259,34 @@ Copyright (C) 1998-2012 Daniel Veillard. License: [MIT license][mit] +#### [nanoflann](https://github.com/jlblancoc/nanoflann) + +Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). +Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). +Copyright 2011 Jose L. Blanco (joseluisblancoc@gmail.com). + +License: [BSD license][bsd] + + +#### [Qhull](http://www.qhull.org/) + +Qhull, Copyright (c) 1993-2020 + +C.B. Barber, Arlington, MA + +and + +The National Science and Technology Research Center for +Computation and Visualization of Geometric Structures +(The Geometry Center) +University of Minnesota + +License: [Qhull license][qhull] + + [bsd]: https://opensource.org/license/BSD-2-Clause [mit]: https://opensource.org/licenses/mit-license.html + [qhull]: http://www.qhull.org/COPYING.txt [gpl2]: https://www.gnu.org/licenses/gpl-2.0.html [lgpl2]: https://www.gnu.org/licenses/lgpl-2.1.html [gpl3]: https://www.gnu.org/licenses/gpl-3.0.html diff --git a/src/vendor/cigraph/CHANGELOG.md b/src/vendor/cigraph/CHANGELOG.md index 9a4cebbe9fc..a5e564f08b9 100644 --- a/src/vendor/cigraph/CHANGELOG.md +++ b/src/vendor/cigraph/CHANGELOG.md @@ -1,149 +1,263 @@ # igraph C library changelog -## [develop] +## [main] + +### Fixed + + - Eliminated references to `exit()` from the igraph shared library. These were accidentally introduced into igraph 1.0.0 through Qhull and Infomap. + - Eliminated references to `std::cout` from the igraph shared library, as required by CRAN. + - Fixed a bug in `igraph_hub_and_authority_scores()` that printed a warning about zero entries in the result even when the number of zeros was below the threshold used in the corresponding checks. + - Fixed compilation and tests when Infomap support is disabled. + +### Other + +- Documentation improvements. + +## [1.0.0] + +Nearly twenty years after the first igraph release, igraph 1.0 has finally arrived. This release focuses on providing a stable and more consistent interface that users and downstream maintainers can rely on with confidence, as well as adding new features that required API-breaking changes. There is now an official versioning policy, see [`VERSIONING.md`](VERSIONING.md). + +### Highlights + +- A more consistent and more predictable API. +- Explicit versioning policy. +- Several random graph generators, including the Erdős-Rényi generators, can now produce graphs with multi-edges. +- Several functions that can generate a large number of results (cliques, cycles, etc.) now have a feature to limit the number of returned results, or to return a single result only. +- Functionality for generating several kinds of spatial networks. ### Breaking changes - - igraph now requires a C++ compiler that supports the C++14 standard. - - Interruption handlers do not take a `void*` argument any more; this is relevant to maintainers of higher-level interfaces only. - - Interruption handlers now return an `igraph_bool_t` instead of an `igraph_error_t`; the returned value must be true if the calculation has to be interrupted and false otherwise. - - `igraph_rng_set_default()` now returns a pointer to the previous RNG. Furthermore, this function now only stores a pointer to the `igraph_rng_t` struct passed to it, instead of copying the struct. Thus the `igraph_rng_t` must continue to exist for as long as it is used as the default RNG. - - `igraph_delete_vertices_map()` (formerly called `igraph_delete_vertices_idx()`) and `igraph_induced_subgraph_map()` now use -1 to represent unmapped vertices in the returned forward mapping vector and they do not offset vertex indices by 1 any more. (Note that the inverse map always behaved this way, this change makes the two mappings consistent). - - `igraph_distances()`, `igraph_distances_cutoff()`, `igraph_get_shortest_path()`, `igraph_get_shortest_paths()` and `igraph_get_all_shortest_paths()` gained a `weights` argument. The functions now automatically select the appropriate implementation (unweighted, Dijkstra, Bellman-Ford or Johnson) algorithm based on whether weights are present and whether there are negative weights or not. You can still call the individual methods by their more specific names. - - `igraph_distances_johnson()` now takes a mode parameter to determine in which direction paths should be followed. - - `igraph_vector_shuffle()` no longer returns an error code. - - `igraph_vector_swap()` no longer returns an error code. - - `igraph_matrix_swap()` no longer returns an error code. - - `igraph_vector_list_swap()` and `igraph_graph_list_swap()` no longer return an error code. - - `igraph_vector_swap_elements()` no longer returns an error code. - - `igraph_vector_reverse()` no longer returns an error code. - - `igraph_vector_list_swap_elements()` and `igraph_graph_list_swap_elements()` no longer return an error code. - - `igraph_similarity_jaccard()` and `igraph_similarity_dice()` now take two sets of vertices to create vertex pairs of, instead of one. - - `igraph_subisomorphic_lad()` does not have a CPU time limit parameter any more. If you wish to stop the calculation from another thread or a higher level interface, use igraph's interruption mechanism. - - `igraph_read_graph_ncol()` and `igraph_read_graph_lgl()` now uses a default edge weight of 1 instead of 0 for files that do not contain edge weights for at least some of the edges. - - `igraph_count_automorphisms()` has been renamed to `igraph_count_automorphisms_bliss()` because it has a BLISS-specific interface. A new `igraph_count_automorphisms()` function was added with a simplified interface that does not depend on BLISS. - - `igraph_automorphism_group()` has been renamed to `igraph_automorphism_group_bliss()` because it has a BLISS-specific interface. A new `igraph_automorphism_group()` function was added with a simplified interface that does not depend on BLISS. - - `igraph_canonical_permutation()` has been renamed to `igraph_canonical_permutation_bliss()` because it has a BLISS-specific interface. A new `igraph_canonical_permutation()` function was added with a simplified interface that does not depend on BLISS. - - The `IGRAPH_EINVEVECTOR` error code was removed; `igraph_create()` and `igraph_add_edges()` that used to return this error code for invalid edge vectors will now return `IGRAPH_EINVAL` instead. - - The `IGRAPH_NONSQUARE` error code was removed; functions that used this error code now return `IGRAPH_EINVAL` instead when encountering a non-square matrix. - - The `IGRAPH_EGLP` error code and all other GLP-specific error codes (starting with `IGRAPH_GLP_`) were removed; functions that used this error code now return `IGRAPH_FAILURE` instead, providing more details in the message associated to the error code. - - The `IGRAPH_ELAPACK` error code was removed; functions that used this error code now return `IGRAPH_FAILURE` instead, providing more details in the message associated to the error code. - - The `IGRAPH_CPUTIME` error code was removed in favour of the interruption mechanism built into igraph. - - The unused `IGRAPH_EDIVZERO` and `IGRAPH_EATTRIBUTES` error codes were removed with no replacement. - - ARPACK-specific error codes (starting with `IGRAPH_ARPACK_...`) were replaced with a single `IGRAPH_EARPACK` error code. Details about the underlying ARPACK failure are provided in the error message. - - A new error code called `IGRAPH_EINVEID` was added for cases when an invalid edge ID was encountered in an edge ID vector. - - `igraph_progress()`, `igraph_progressf()` and `IGRAPH_PROGRESS()` do not convert error codes to `IGRAPH_INTERRUPTED` any more. Any error code returned from the progress handler function is forwarded intact to the caller. If you want to trigger the interruption of the current calculation from the progress handler without reporting an error, report `IGRAPH_INTERRUPTED` explicitly. It is the responsibility of higher-level interfaces to handle this error code appropriately. - - `igraph_status()`, `igraph_statusf()` and their macro versions (`IGRAPH_STATUS()` and `IGRAPH_STATUSF()`) do not convert error codes to `IGRAPH_INTERRUPTED` any more. Any error code returned from the status handler function is forwarded intact to the caller. If you want to trigger the interruption of the current calculation from the status handler without reporting an error, report `IGRAPH_INTERRUPTED` explicitly. It is the responsibility of higher-level interfaces to handle this error code appropriately. - - `igraph_community_edge_betweenness()` now takes both a `weights` and a `lengths` parameter. Egde weights (interpreted as connection strengths) are used to divide betweenness scores before selecting them for removal as well as for the modularity computation. Edge lengths are used for defining shortest path lengths during the betweenness computation. This fixes issues #2229 and #1040. - - `igraph_get_biadjacency()` now takes a `weights` parameter, and can optionally create weighted biadjacency matrices. - - `igraph_community_label_propagation()` changed signature to allow specification of LPA variants. A new fast label propagation variant was added. - - `igraph_eigenvector_centrality()`, `igraph_centralization_eigenvector_centrality()` and `igraph_centralization_eigenvector_centrality_tmax()` now use a `mode` parameter with possible values `IGRAPH_OUT`, `IGRAPH_IN` or `IGRAPH_ALL` to control how edge directions are considered. Previously they used a boolean `directed` parameter. - - `igraph_eigenvector_centrality()`, `igraph_centralization_eigenvector_centrality()` and `igraph_centralization_eigenvector_centrality_tmax()` no longer have a `scale` parameter. The result is now always scaled so that the largest centrality value is 1. - - `igraph_hub_and_authority_scores()` no longer has a `scale` parameter. The result is now always scaled so that the largest hub and authority scores are each 1. - - `igraph_minimum_spanning_tree()` takes a new `method` parameter that controls the algorithm used for finding the spanning tree. Kruskal's algorithm was added. - - `igraph_get_all_simple_paths()` returns its results in an integer vector list (`igraph_vector_int_list_t`) instead of a single integer vector. - - `igraph_get_all_simple_paths()` now has an additional parameter that allows restricting paths by minimum length as well. - - `igraph_strvector_print()` no longer takes a file parameter. Use `igraph_strvector_fprint()` to print to a file. - - `igraph_community_optimal_modularity()` now takes a `resolution` parameter and its `weight` parameter was moved to the second place. - - `igraph_attribute_handler_t` members that formerly took an untyped `igraph_vector_ptr_t` argument are now taking a typed `igraph_attribute_record_list_t` argument instead. - - The deprecated `IGRAPH_ATTRIBUTE_DEFAULT` value of the `igraph_attribute_type_t` enum was removed. - - The `gettype` member of `igraph_attribute_table_t` was renamed to `get_type` for sake of consistency with the naming scheme of other struct members. - - Attribute table members that retrieve graph, vertex or edge attributes must not clear the incoming result vector any more; results must be appended to the end of the provided result vector instead. - - The `value` member of `igraph_attribute_record_t` is now a union that can be used to formally treat the associated pointer as an `igraph_vector_t*`, `igraph_strvector_t*` or `igraph_vector_bool_t*`. - - `igraph_lcf()` was renamed to `igraph_lcf_small()` and `igraph_lcf_vector()` was renamed to `igraph_lcf()`. Now `igraph_lcf()` takes shifts as a vector input, while `igraph_lcf_small()` accepts a shorthand notation where shifts are given as a variable number of function arguments. - - The deprecated `igraph_rng_get_dirichlet()` function was removed. - - `igraph_motifs_randesu_no()` and `igraph_motifs_randesu_estimate()` now take an `igraph_real_t` as their `result` argument to prevent overflows when igraph is compiled with 32-bit integers. - - The weighted variants of `igraph_diameter()`, `igraph_pseudo_diameter()`, `igraph_radius()`, `igraph_graph_center()`, `igraph_eccentricity()` and `igraph_average_path_length()` were merged into the undirected ones by adding a new argument named `weights` in the second position. - - The `weights` parameter of `igraph_average_path_length()`, `igraph_global_efficiency()`, `igraph_local_efficiency()` and `igraph_average_local_efficiency()` were moved to the second position, after the `graph` itself, for sake of consistency with other functions. - - `igraph_edges()` gained a new `bycol` argument that determines the order in which the edges are returned. `bycol` = 0 reproduces the existing behaviour, while `bycol` = 1 returns the edges suitable for a matrix stored in column-wise order. - - `igraph_neighbors()` and `igraph_vs_adj()` gained two extra arguments to specify what to do with loop and multiple edges. This makes their interfaces consistent with `igraph_adjlist_init()`. - - `igraph_incident()` and `igraph_es_incident()` gained an extra arguments to specify what to do with loop edges. This makes their interfaces consistent with `igraph_inclist_init()`. - - `igraph_multiple_t` was removed from the public API as it is essentially a boolean. The symbolic constants `IGRAPH_MULTIPLE` and `IGRAPH_NO_MULTIPLE` were kept to improve readability of code written directly in C. - - The semantics of the `igraph_permute_vertices()` permutation argument has changed: the i-th element of the vector now contains the index of the _original_ vertex that will be mapped to the i-th vertex in the new graph. This is now consistent with how other igraph functions treat permutations and vertex index vectors; for instance, you can now pass the result of `igraph_topological_sorting()` directly to `igraph_permute_vertices()` to obtain a new graph where the vertices are sorted topologically. - - As a consequence to the change in the semantics of the `igraph_permute_vertices()` permutation argument, the semantics of the permutations returned from `igraph_canonical_permutation()` and `igraph_canonical_permutation_bliss()` have also been inverted to maintain the invariant that the output of these functions can be fed into `igraph_permute_vertices()` directly. - - The type of the `loops` argument of `igraph_adjlist_init_complementer()`, `igraph_centralization_degree()`, `igraph_centralization_degree_tmax()`, `igraph_degree()`, `igraph_maxdegree()`, `igraph_sort_vertex_ids_by_degree()` and `igraph_strength()` was changed to `igraph_loops_t` from `igraph_bool_t`, allowing finer-grained control about how loop edges are treated. - - `igraph_adjacency()` now treats `IGRAPH_LOOPS_TWICE` as `IGRAPH_LOOPS_ONCE` when the mode is `IGRAPH_ADJ_DIRECTED`, `IGRAPH_ADJ_UPPER` or `IGRAPH_ADJ_LOWER`. For directed graphs, this is for the sake of consistency with the rest of the library where `IGRAPH_LOOPS_TWICE` is considered for undirected graphs only. For the "upper" and "lower" modes, double-counting the diagonal makes no sense because the double-counting artifact appears when you add the _transpose_ of an upper (or lower) diagonal matrix on top of the matrix itself. See Github issue #2501 for more context. - - `igraph_strvector_push_back_len()` now takes a length parameter of `size_t` instead of `igraph_integer_t`. - - `igraph_sample_dirichlet()`, `igraph_sample_sphere_surface()` and `igraph_sample_sphere_volume()` were removed in favour of `igraph_rng_sample_dirichlet()`, `igraph_rng_sample_sphere_surface()` and `igraph_rng_sample_sphere_volume()`, which allow the user to specify the random number generator to use. - - The `RNG_BEGIN()` and `RNG_END()` macros were removed. You are now responsible for seeding the RNG before using any igraph function that may use random numbers by calling `igraph_rng_seed(igraph_rng_default(), ...)`. - - The deprecated `igraph_sparsemat()` and `igraph_weighted_sparsemat()` functions were removed; use `igraph_get_adjacency_sparse()` instead. - - `igraph_is_simple()` gained an extra `igraph_bool_t` argument that decides whether edge directions should be considered. Directed graphs with a mutual edge pair are treated as non-simple if this argument is set to `IGRAPH_UNDIRECTED` (which treats the graph as if it was undirected). - - `igraph_community_leiden()` now takes two `vertex_out_weights` and `vertex_in_weights` parameters in order to support directed graphs, instead of the previou single `node_weights` parameter. To obtain the old behavior for undirected graphs, pass the vertex weights as `vertex_out_weights` and set `vertex_in_weights` to `NULL`. - - `igraph_rewire()` now takes an `igraph_edge_type_sw_t` parameter to specify whether to create self-loops. The `igraph_rewiring_t` enum type was removed. Instead of the old `IGRAPH_REWIRING_SIMPLE`, use `IGRAPH_SIMPLE_SW`. Instead of the old `IGRAPH_REWIRING_SIMPLE_LOOPS`, use `IGRAPH_LOOPS_SW`. - - The `history` parameter of `igraph_community_leading_eigenvector()` is now a pointer to an `igraph_vector_int_t` instead of an `igraph_vector_t`. +This section lists API-breaking changes in this version, and provides guidance on adapting code written for igraph 0.10.x. + +#### General changes + +- igraph now requires a C++ compiler that supports the C++14 standard. +- `igraph_setup()` is now recommended to be called before using the library. This function may gain essential functions in the future. See the "Added" section below for details. +- `igraph_integer_t` was renamed to `igraph_int_t`, but `igraph_integer_t` is kept as an alias and it will remain available for at least the next major version. Library headers and source code uses `igraph_int_t` from now on. +- `igraph_rng_set_default()` now returns a pointer to the previous default RNG. Furthermore, this function now only stores a pointer to the `igraph_rng_t` struct passed to it, instead of copying the struct. Thus the `igraph_rng_t` object must continue to exist for as long as it is used as the default RNG. +- Interruption handlers do not take a `void *` argument anymore; this is relevant to maintainers of higher-level interfaces only. +- Interruption handlers now return an `igraph_bool_t` instead of an `igraph_error_t`; the returned value must be true if the calculation has to be interrupted and false otherwise. +- `igraph_status()`, `igraph_statusf()` and their macro versions (`IGRAPH_STATUS()` and `IGRAPH_STATUSF()`) do not convert error codes to `IGRAPH_INTERRUPTED` any more. Any error code returned from the status handler function is forwarded intact to the caller. If you want to trigger the interruption of the current calculation from the status handler without reporting an error, report `IGRAPH_INTERRUPTED` explicitly. It is the responsibility of higher-level interfaces to handle this error code appropriately. +- The `RNG_BEGIN()` and `RNG_END()` macros were removed. You are now responsible for seeding the RNG before using any igraph function that may use random numbers by calling `igraph_rng_seed(igraph_rng_default(), ...)`, or by simply ensuring that `igraph_setup()` was called before the first use of the library. +- Projects that depend on igraph must only include the `` header. While an igraph installation includes several sub-headers, these are for organizational purposes only, and their contents may change without notice. Only `#include ` is supported. + +#### Error codes + +- The `IGRAPH_EINVEVECTOR` error code was removed; `igraph_create()` and `igraph_add_edges()` that used to return this error code for invalid edge vectors will now return `IGRAPH_EINVAL` instead. +- The `IGRAPH_NONSQUARE` error code was removed; functions that used this error code now return `IGRAPH_EINVAL` instead when encountering a non-square matrix. +- The `IGRAPH_EGLP` error code and all other GLP-specific error codes (starting with `IGRAPH_GLP_`) were removed; functions that used this error code now return `IGRAPH_FAILURE` instead, providing more details in the message associated to the error code. +- The `IGRAPH_ELAPACK` error code was removed; functions that used this error code now return `IGRAPH_FAILURE` instead, providing more details in the message associated to the error code. +- The `IGRAPH_CPUTIME` error code was removed in favour of the interruption mechanism built into igraph. +- The unused `IGRAPH_EDIVZERO` and `IGRAPH_EATTRIBUTES` error codes were removed with no replacement. +- The deprecated error code `IGRAPH_ENEGLOOP` was removed. Use `IGRAPH_ENEGCYCLE` instead. The underlying numerical value is the same as it was for `IGRAPH_ENEGLOOP`. +- ARPACK-specific error codes (starting with `IGRAPH_ARPACK_...`) were replaced with a single `IGRAPH_EARPACK` error code. Details about the underlying ARPACK failure are provided in the error message. +- A new error code called `IGRAPH_EINVEID` was added for cases when an invalid edge ID was encountered in an edge ID vector. + +#### Core data structures + +- `igraph_strvector_push_back_len()` now takes a length parameter of `size_t` instead of `igraph_int_t`. +- `igraph_strvector_print()` no longer takes a file parameter. Use `igraph_strvector_fprint()` to print to a file. +- `igraph_vector_reverse()` no longer returns an error code. +- `igraph_vector_shuffle()` no longer returns an error code. +- `igraph_vector_swap()` and `igraph_matrix_swap()` no longer return an error code. +- `igraph_vector_list_swap()` and `igraph_graph_list_swap()` no longer return an error code. +- `igraph_vector_swap_elements()` no longer returns an error code. +- `igraph_vector_list_swap_elements()` and `igraph_graph_list_swap_elements()` no longer return an error code. +- `igraph_matrix_copy_to()` gained an `igraph_matrix_storage_t storage` parameter that specifies whether the data should be written in column-major or row-major format. +- `igraph_vector_view()`, `igraph_matrix_view()`, `igraph_matrix_view_from_vector()`, and `igraph_vector_ptr_view()` now return their result as a return value instead of an output parameter. This allows assigning the value to a `const` variable without triggering warnings with modern compilers. + +#### Attribute handling + +- `igraph_attribute_handler_t` members that formerly took an untyped `igraph_vector_ptr_t` argument are now taking a typed `igraph_attribute_record_list_t` argument instead. +- The deprecated `IGRAPH_ATTRIBUTE_DEFAULT` value of the `igraph_attribute_type_t` enum was removed. +- The `gettype` member of `igraph_attribute_table_t` was renamed to `get_type` for consistency with the naming scheme of other struct members. +- Attribute table members that retrieve graph, vertex or edge attributes must not clear the incoming result vector any more; results must be appended to the end of the provided result vector instead. +- The `value` member of `igraph_attribute_record_t` is now a union that can be used to formally treat the associated pointer as an `igraph_vector_t *`, `igraph_strvector_t *` or `igraph_vector_bool_t *`. + +#### Core graph manipulation + +- `igraph_delete_vertices_map()` (formerly called `igraph_delete_vertices_idx()`) and `igraph_induced_subgraph_map()` now use `-1` to represent unmapped vertices in the returned forward mapping vector and they do not offset vertex indices by 1 any more. Note that the inverse map always behaved this way, this change makes the two mappings consistent. +- `igraph_edges()` gained a new `igraph_bool_t bycol` argument that determines the order in which the edges are returned. `bycol = false` reproduces the existing behaviour, while `bycol = true` returns the edges suitable for a matrix stored in column-wise order. +- `igraph_neighbors()` and `igraph_vs_adj()` gained two extra arguments, `igraph_loops_t loops` and `igraph_bool_t multiple` to specify what to do with loop and multiple edges. This makes their interfaces consistent with `igraph_adjlist_init()`. Use `loops = IGRAPH_LOOPS_TWICE` and `multiple = true` to reproduce the previous behavior. +- `igraph_incident()` and `igraph_es_incident()` gained an extra `igraph_loops_t loops` argument to specify what to do with loop edges. This makes their interfaces consistent with `igraph_inclist_init()`. Use `loops = IGRAPH_LOOPS_TWICE` to reproduce the previous behavior. +- The `igraph_multiple_t` enum type was removed from the public API as it was essentially a Boolean. The symbolic constants `IGRAPH_MULTIPLE` (same as `true`) and `IGRAPH_NO_MULTIPLE` (same as `false`) were kept to improve readability of code written directly in C. + +#### Basic graph properties + +- `igraph_density()` now takes an optional `weights` parameter. +- `igraph_is_simple()` gained an extra `igraph_bool_t` argument that decides whether edge directions should be considered. Directed graphs with a mutual edge pair are treated as non-simple if this argument is set to `IGRAPH_UNDIRECTED` (which treats the graph as if it was undirected). +- The type of the `loops` argument of `igraph_adjlist_init_complementer()`, `igraph_centralization_degree()`, `igraph_centralization_degree_tmax()`, `igraph_degree()`, `igraph_maxdegree()`, `igraph_sort_vertex_ids_by_degree()` and `igraph_strength()` was changed to `igraph_loops_t` from `igraph_bool_t`, allowing finer-grained control about how loop edges are treated. Pass `IGRAPH_LOOPS_TWICE` and `IGRAPH_NO_LOOPS` to reproduce the previous behaviour of `true` and `false`. +- `igraph_get_biadjacency()` now takes a `weights` parameter, and can optionally create weighted biadjacency matrices. +- `igraph_adjacency()` now treats `IGRAPH_LOOPS_TWICE` as `IGRAPH_LOOPS_ONCE` when the mode is `IGRAPH_ADJ_DIRECTED`, `IGRAPH_ADJ_UPPER` or `IGRAPH_ADJ_LOWER`. For directed graphs, this is for the sake of consistency with the rest of the library where `IGRAPH_LOOPS_TWICE` is considered for undirected graphs only. For the "upper" and "lower" modes, double-counting the diagonal makes no sense because the double-counting artifact appears when you add the _transpose_ of an upper (or lower) diagonal matrix on top of the matrix itself. See Github issue #2501 for more context. + +#### Graph generators + +- `igraph_barabasi_game()`, `igraph_barabasi_aging_game()`, `igraph_recent_degree_game()` and `igraph_recent_degree_aging_game()` no longer interprets an empty `outseq` vector as a missing out-degree sequence. Pass `NULL` if you don't wish to specify an out-degree sequence. +- `igraph_degree_sequence_game()` no longer interprets an empty in-degree vector as a request for generating undirected graphs. To generate undirected graphs, pass `NULL` for in-degrees. +- `igraph_erdos_renyi_game_gnm()` uses a `igraph_edge_type_sw_t allowed_edge_types` parameter instead of `igraph_bool_t loops`, and can now uniformly sample not only simple graphs but also multigraphs. It also gained an `edge_labeled` Boolean parameter which controls whether to sample from the set of ordered edge lists (equivalent to `igraph_iea_game()` for multigraphs). +- `igraph_erdos_renyi_game_gnp()` uses a `igraph_edge_type_sw_t allowed_edge_types` parameter instead of `igraph_bool_t loops`, and can now sample multigraphs from a maximum entropy model with a prescribed _expected_ edge multiplicity. It also gained an `edge_labeled` Boolean parameter which controls whether to sample from the set of ordered edge lists. +- `igraph_bipartite_game_gnm()` gained an `igraph_edge_type_sw_t allowed_edge_types` parameter, and can now uniformly sample not only simple graphs but also multigraphs. It also gained an `edge_labeled` Boolean parameter which controls whether to sample from the set of ordered edge lists (equivalent to `igraph_bipartite_iea_game()` for multigraphs). +- `igraph_bipartite_game_gnp()` gained an `igraph_edge_type_sw_t allowed_edge_types` parameter, and can now sample multigraphs from a maximum entropy model with a prescribed _expected_ edge multiplicity. It also gained an `edge_labeled` Boolean parameter which controls whether to sample from the set of ordered edge lists. +- `igraph_lcf()` was renamed to `igraph_lcf_small()` and `igraph_lcf_vector()` was renamed to `igraph_lcf()`. Now `igraph_lcf()` takes shifts as a vector input, while `igraph_lcf_small()` accepts a shorthand notation where shifts are given as a variable number of function arguments. +- `igraph_sbm_game()` uses an `igraph_edge_type_sw_t allowed_edge_types` parameter instead of `igraph_bool_t loops` and now supports generating graphs with multi-edges. The parameter determining the total number of vertices (`n`) was removed as it was redundant. +- `igraph_rewire_edges()` uses an `igraph_edge_type_sw_t allowed_edge_types` parameter instead of `loops` and `multiple`. +- `igraph_rewire()` now takes an `igraph_edge_type_sw_t allowed_edge_types` parameter to specify whether to create self-loops. The `igraph_rewiring_t` enum type was removed. Instead of the old `IGRAPH_REWIRING_SIMPLE`, use `IGRAPH_SIMPLE_SW`. Instead of the old `IGRAPH_REWIRING_SIMPLE_LOOPS`, use `IGRAPH_LOOPS_SW`. +- `igraph_rewire()` now takes an optional `igraph_rewiring_stats_t *` output argument. You can pass the appropriate struct there to find out the number of successful swaps during the rewiring operation. +- `igraph_watts_strogatz_game()` uses an `igraph_edge_type_sw_t allowed_edge_types` parameter instead of `loops` and `multiple`. +- `igraph_static_fitness_game()` uses an `igraph_edge_type_sw_t allowed_edge_types` parameter instead of `loops` and `multiple`. +- `igraph_static_power_law_game()` uses an `igraph_edge_type_sw_t allowed_edge_types` parameter instead of `loops` and `multiple`. +- `igraph_correlated_game()` now takes the graph being constructed as the _first_ argument to remain consistent with other graph constructors. Earlier versions used to take the original graph as the first argument. +- The semantics of the `permutation` argument of `igraph_correlated_game()` and `igraph_correlated_pair_game()` has changed: the i-th element of the vector now contains the index of the _original_ vertex that will be mapped to the i-th vertex in the new graph. This is consistent with how `igraph_permute_vertices()` operates (which has also changed in igraph 1.0). + +#### Paths and cycles + +- `igraph_distances()`, `igraph_distances_cutoff()`, `igraph_get_shortest_path()`, `igraph_get_shortest_paths()` and `igraph_get_all_shortest_paths()` gained a `weights` argument. The functions now automatically select the appropriate implementation (unweighted, Dijkstra, Bellman-Ford or Johnson) algorithm based on whether weights are present and whether there are negative weights or not. You can still call the individual methods by their more specific names. +- `igraph_distances_johnson()` now takes an `igraph_neimode_t mode` parameter to determine in which direction paths should be followed. +- The weighted variants of `igraph_diameter()`, `igraph_pseudo_diameter()`, `igraph_radius()`, `igraph_graph_center()`, `igraph_eccentricity()` and `igraph_average_path_length()` were merged into the undirected ones by adding a new argument named `weights` in the second position. +- The `weights` parameter of `igraph_average_path_length()`, `igraph_global_efficiency()`, `igraph_local_efficiency()` and `igraph_average_local_efficiency()` were moved to the second position, after the `graph` itself, for consistency with other functions. +- `igraph_get_all_simple_paths()` returns its results in an integer vector list (`igraph_vector_int_list_t`) instead of a single integer vector. +- `igraph_get_all_simple_paths()` now has an additional parameter that allows restricting paths by minimum length as well, and its `mode` parameter was moved to before the path length limit parameters. +- `igraph_get_all_simple_paths()` gained a `max_results` parameter to limit the number of returned results. Pass `1` to return a single result, or `IGRAPH_UNLIMITED` to return all results. +- `igraph_simple_cycles()` gained a `max_results` parameter to limit the number of returned results. Pass `1` to return a single result, or `IGRAPH_UNLIMITED` to return all results. + +#### Community detection + +- `igraph_community_edge_betweenness()` now takes both a `weights` and a `lengths` parameter. Edge weights (interpreted as connection strengths) are used to divide betweenness scores before selecting them for removal as well as for the modularity computation. Edge lengths are used for defining shortest path lengths during the betweenness computation. This fixes issues #2229 and #1040. +- `igraph_community_infomap()` now supports regularization and gained the `is_regularized` and `regularization_strength` parameters. +- `igraph_community_label_propagation()` changed signature to allow specification of label propagation algorithm (LPA) variants. A new fast label propagation variant was added. +- `igraph_community_leiden()` now takes two `vertex_out_weights` and `vertex_in_weights` parameters in order to support directed graphs, instead of the previous single `node_weights` parameter. To obtain the old behavior for undirected graphs, pass the vertex weights as `vertex_out_weights` and set `vertex_in_weights` to `NULL`. +- The `history` parameter of `igraph_community_leading_eigenvector()` is now a pointer to an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- `igraph_community_optimal_modularity()` now takes a `resolution` parameter and its `weight` parameter was moved to the second place. +- `igraph_community_spinglass_single()` now uses `igraph_real_t` for its `inner_links` and `outer_links` output parameters, as these return not simply edge counts, but the sum of the weights of some edges. + +#### Isomorphism functions and permutations + +- `igraph_count_automorphisms()` has been renamed to `igraph_count_automorphisms_bliss()` because it has a BLISS-specific interface. A new `igraph_count_automorphisms()` function was added with a simplified interface that does not depend on BLISS. +- `igraph_automorphism_group()` has been renamed to `igraph_automorphism_group_bliss()` because it has a BLISS-specific interface. A new `igraph_automorphism_group()` function was added with a simplified interface that does not depend on BLISS. +- `igraph_canonical_permutation()` has been renamed to `igraph_canonical_permutation_bliss()` because it has a BLISS-specific interface. A new `igraph_canonical_permutation()` function was added with a simplified interface that does not depend on BLISS. +- `igraph_subisomorphic_lad()` does not have a CPU time limit parameter any more. If you wish to stop the calculation from another thread or a higher level interface, use igraph's interruption mechanism. +- The semantics of the `igraph_permute_vertices()` permutation argument has changed: the i-th element of the vector now contains the index of the _original_ vertex that will be mapped to the i-th vertex in the new graph. This is now consistent with how other igraph functions treat permutations and vertex index vectors; for instance, you can now pass the result of `igraph_topological_sorting()` directly to `igraph_permute_vertices()` to obtain a new graph where the vertices are sorted topologically. +- As a consequence to the change in the semantics of the `igraph_permute_vertices()` permutation argument, the semantics of the permutations returned from `igraph_canonical_permutation()` and `igraph_canonical_permutation_bliss()` have also been inverted to maintain the invariant that the output of these functions can be fed into `igraph_permute_vertices()` directly. +- `igraph_isoclass_subgraph()` now takes a parameter of type `igraph_vs_t vids` instead of `igraph_vector_int_t vids`. Apply `igraph_vss_vector()` to the vector of vertex IDs to convert it to an `igraph_vs_t`. + +#### Centralities + +- All betweenness functions got a `normalized` parameter to support normalizing the result by the number of vertex pairs in the graph. At the same time, their parameter ordering was standardized. The following functions are affected: `igraph_betweenness()`, `igraph_betweenness_cutoff()`, `igraph_edge_betweenness()`, `igraph_edge_betweenness_cutoff()`, `igraph_betweenness_subset()`, `igraph_edge_betweenness_subset()`. +- `igraph_edge_betweenness()` and `igraph_edge_betweenness_cutoff()` now have an `eids` parameter to return only a subset of results. This makes their interface consistent with other betweenness functions. +- `igraph_eigenvector_centrality()`, `igraph_centralization_eigenvector_centrality()` and `igraph_centralization_eigenvector_centrality_tmax()` now use a `mode` parameter with possible values `IGRAPH_OUT`, `IGRAPH_IN` or `IGRAPH_ALL` to control how edge directions are considered. Previously they used a boolean `directed` parameter. +- `igraph_eigenvector_centrality()`, `igraph_centralization_eigenvector_centrality()` and `igraph_centralization_eigenvector_centrality_tmax()` no longer have a `scale` parameter. The result is now always scaled so that the largest centrality value is 1. +- `igraph_hub_and_authority_scores()` no longer has a `scale` parameter. The result is now always scaled so that the largest hub and authority scores are each 1. +- `igraph_pagerank()`, `igraph_personalized_pagerank()` and `igraph_personalized_pagerank_vs()` had their parameter ordering standardized. + +#### Cliques and independent sets + +- `igraph_cliques()`, `igraph_weighed_cliques()`, `igraph_maximal_cliques()`, `igraph_maximal_cliques_file()`, `igraph_maximal_cliques_subset()`, `igraph_independent_sets()` and `igraph_maximal_independent_sets()` received a `max_results` parameter to limit the number of returned results. Pass `1` to return a single result, or `IGRAPH_UNLIMITED` to return all results. +- `igraph_maximal_independent_sets()` received `min_size` and `max_size` parameters that control the range of independent set sizes that are returned. +- `igraph_weighted_cliques()` had its parameter ordering standardized: the `igraph_bool_t maximal` parameter now comes before the `min_weight` / `max_weight` parameters. +- `igraph_maximal_cliques_callback()` had its parameter ordering standardized: the `igraph_clique_handler_t *cliquehandler_fn, void *arg` parameter pair now comes at the end, making this function consistent with `igraph_cliques_callback()`. + +#### Layouts + +- `igraph_layout_sugiyama()` does not return an "extended graph" anymore. The bends in the edges of the layout are encoded in a list of matrices instead; each item in the list belongs to an edge of the original graph and contains the control points of the edge in a row-wise fashion. The matrix will have no rows if no control points are needed on the edge. + +#### Other network analysis + +- `igraph_similarity_jaccard()` and `igraph_similarity_dice()` now take two sets of vertices (`to` and `from` parameters) to create vertex pairs of, instead of one. Pass the same vertex set to both parameters to recover the previous behaviour. +- `igraph_minimum_spanning_tree()` takes a new `method` parameter that controls the algorithm used for finding the spanning tree. Kruskal's algorithm was added. +- `igraph_motifs_randesu_no()` and `igraph_motifs_randesu_estimate()` now take an `igraph_real_t` as their `result` argument to prevent overflows when igraph is compiled with 32-bit integers. +- The `igraph_motifs_handler_t` callback type now takes a `const igraph_vector_int_t *vids` parameter. Previously this was not formally `const`, even though it was not allowed to modify `vids`. This affects uses of `igraph_motifs_randesu_callback()`. +- The experimental functions `igraph_fundamental_cycles()` and `igraph_minimum_cycle_basis()` now use the type `igraph_real_t` for their `bfs_cutoff` parameter, and had their `weights` parameter moved to the 2nd position. + +#### Foreign formats + +- `igraph_read_graph_ncol()` and `igraph_read_graph_lgl()` now uses a default edge weight of 1 instead of 0 for files that do not contain edge weights for at least some of the edges. ### Added - - `igraph_setup()` performs all initialization tasks that are recommended before using the igraph library. Right now this function only initializes igraph's internal random number generator with a seed based on the current time, but it may also perform other tasks in the future. It is recommended to call this function before using any other function from the library (although most of the functions will work fine now even if this function is not called). - - `igraph_int_t` may now be used as an alias to `igraph_integer_t`. - - `igraph_erdos_renyi_game_gnm()` gained a `multiple` Boolean argument to uniformly sample G(n,m) graphs with multi-edges. - - `igraph_bipartite_game_gnm()` gained a `multiple` Boolean argument to uniformly sample bipartite G(n,m) graphs with multi-edges. - - `igraph_iea_game()` samples random multigraphs through independent edge assignment. - - `igraph_bipartite_iea_game()` samples random bipartite multigraph through independent edge assignment. - - `igraph_weighted_biadjacency()` creates a weighted graph from a bipartite adjacency matrix. - - `igraph_vector_ptr_capacity()` returns the allocated capacity of a pointer vector. - - `igraph_vector_ptr_resize_min()` deallocates unused capacity of a pointer vector. - - `igraph_strvector_fprint()` prints a string vector to a file. - - `igraph_rng_sample_dirichlet()`, `igraph_rng_sample_sphere_volume()` and `igraph_rng_sample_sphere_surface()` samples vectors from a Dirichlet distribution or from the volume or surface of a sphere while allowing the user to specify the random number generator to use. - - `igraph_nearest_neighbor_graph()` computes a neighborhood graph of spatial points based on a neighbor count, cutoff distance, and chosen metric. Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2788! +- `igraph_setup()` performs all initialization tasks that are recommended before using the igraph library. Right now this function only initializes igraph's internal random number generator with a practically random seed, but it may also perform other tasks in the future. It is recommended to call this function before using any other function from the library (although most of the functions will work fine now even if this function is not called). +- `igraph_iea_game()` samples random multigraphs through independent edge assignment. +- `igraph_bipartite_iea_game()` samples random bipartite multigraph through independent edge assignment. +- `igraph_weighted_biadjacency()` creates a weighted graph from a bipartite adjacency matrix. +- `igraph_vector_ptr_capacity()` returns the allocated capacity of a pointer vector. +- `igraph_vector_ptr_resize_min()` deallocates unused capacity of a pointer vector. +- `igraph_strvector_fprint()` prints a string vector to a file. +- `igraph_rng_sample_dirichlet()`, `igraph_rng_sample_sphere_volume()` and `igraph_rng_sample_sphere_surface()` samples vectors from a Dirichlet distribution or from the volume or surface of a sphere while allowing the user to specify the random number generator to use. +- `igraph_nearest_neighbor_graph()` computes a neighborhood graph of spatial points based on a neighbor count, cutoff distance, and chosen metric (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2788! +- `igraph_delaunay_graph()` computes a Delaunay graph of a spatial point set (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2806! +- `igraph_gabriel_graph()` computes the Gabriel graph of a spatial point set (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2827! +- `igraph_relative_neighborhood_graph()` computes the relative neighborhood graph of a spatial point set (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2827! +- `igraph_lune_beta_skeleton()` and `igraph_circle_beta_skeleton()` compute the lune and circle based β-skeletons of a spatial point set (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2827! +- `igraph_beta_weighted_gabriel_graph()` computes a Gabriel graph of a spatial point set, along with a threshold β value for each edge, at which the edge ceases to be part of the lune-based β-skeleton (experimental function). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2827! +- `igraph_spatial_edge_lengths()` computes edge lengths based on spatial vertex coordinates (experimental function). +- `igraph_community_leiden_simple()` is a simplified interface to `igraph_community_leiden()` that allows selecting the objective function to maximize directly. +- `igraph_vector_difference_and_intersection_sorted()` calculates the intersection and the differences of two vectors simultaneously. +- `IGRAPH_UNLIMITED`, defined to `-1`, is a convenience constant for use with various "size limit" parameters, such as number of cliques returned, maximum path length, number of results returned, etc. It indicates that no limit should be used. ### Changed - - The Pajek format reader and writer now map vertex labels to the `name` vertex attribute in igraph. The `id` attribute is no longer used. - - `igraph_minimum_size_separators()` no longer returns any separating vertex sets for complete graphs. Prior to igraph 1.0, it would return all `n - 1` size vertex subsets where `n` is the vertex count. - - `igraph_community_edge_betweenness()` now treats edges with large weights as strong connections. - - `igraph_biadjacency()` now truncates non-integer matrix entries to their integer part instead of rounding them up. This brings consistency with related functions such as `igraph_adjacency()`. - - The order of edges in the graph returned by `igraph_(weighted_)adjacency()` and `igraph_biadjacency()` has changed. Note that these functions do not guarantee any specific edge order. - - `igraph_eigenvector_centrality()` now warns about eigenvector centralities equal to zero, as these indicate a disconnected graph, for which eigenvector centrality is not meaningful. - - `igraph_hub_and_authority_scores()` now warns when a large fraction of centrality scores are zero, as this indicates a non-unique solution, and thus the returned result may not be meaningful. - - `igraph_hub_and_authority_scores()` now warns when providing an undirected graph as input, and falls back to the equivalent eigenvector centrality computation. - - `igraph_get_stochastic_sparse()` no longer throws an error when some row or column sums are zero. This brings its behaviour in line with `igraph_get_stochastic()`. - - `igraph_vector_append()`, `igraph_strvector_append()` and `igraph_vector_ptr_append()` now use a different allocation strategy: if the `to` vector has insufficient capacity, they double its capacity. Previously they reserved precisely as much capacity as needed for appending the `from` vector. - - `igraph_degree_sequence_game()` no longer interprets an empty in-degree vector as a request for generating undirected graphs. To generate undirected graphs, pass `NULL` for in-degrees. - - `igraph_barabasi_game()`, `igraph_barabasi_aging_game()`, `igraph_recent_degree_game()` and `igraph_recent_degree_aging_game()` no longer interprets an empty `outseq` vector as a missing out-degree sequence. Pass `NULL` if you don't wish to specify an out-degree sequence. - - The implementation of the Infomap algorithm behind `igraph_community_infomap()` has been updated with a more recent version (2.8.0), while keeping the API compatible with previous igraph versions. Isolated vertices are now supported. - - The following functions are not experimental any more: `igraph_count_loops()`, `igraph_distances_cutoff()`, `igraph_distances_floyd_warshall()`, `igraph_distances_dijkstra_cutoff()`, `igraph_enter_safelocale()`, `igraph_exit_safelocale()`, `igraph_get_shortest_path_astar()`, `igraph_graph_power()`, `igraph_hexagonal_lattice()`, `igraph_hypercube()`, `igraph_is_clique()`, `igraph_is_independent_vertex_set()`, `igraph_join()`,`igraph_joint_degree_distribution()`, `igraph_joint_degree_matrix()`, `igraph_joint_type_distribution()`, `igraph_layout_merge_dla()`, `igraph_mean_degree()`, `igraph_transitive_closure()`, `igraph_tree_from_parent_vector()`, `igraph_triangular_lattice()`. +- The Pajek format reader and writer now map vertex labels to the `name` vertex attribute in igraph. The `id` attribute is no longer used. +- `igraph_minimum_size_separators()` no longer returns any separating vertex sets for complete graphs. Prior to igraph 1.0, it would return all `n - 1` size vertex subsets where `n` is the vertex count. +- `igraph_community_edge_betweenness()` now treats edges with large weights as strong connections. +- `igraph_biadjacency()` now truncates non-integer matrix entries to their integer part instead of rounding them up. This brings consistency with related functions such as `igraph_adjacency()`. +- The order of edges in the graph returned by `igraph_(weighted_)adjacency()` and `igraph_biadjacency()` has changed. Note that these functions do not guarantee any specific edge order. +- `igraph_eigenvector_centrality()` now warns about eigenvector centralities equal to zero, as these indicate a disconnected graph, for which eigenvector centrality is not meaningful. +- `igraph_hub_and_authority_scores()` now warns when a large fraction of centrality scores are zero, as this indicates a non-unique solution, and thus the returned result may not be meaningful. +- `igraph_hub_and_authority_scores()` now warns when providing an undirected graph as input, and falls back to the equivalent eigenvector centrality computation. +- `igraph_get_stochastic_sparse()` no longer throws an error when some row or column sums are zero. This brings its behaviour in line with `igraph_get_stochastic()`. +- `igraph_vector_append()`, `igraph_strvector_append()` and `igraph_vector_ptr_append()` now use a different allocation strategy: if the `to` vector has insufficient capacity, they double its capacity. Previously they reserved precisely as much capacity as needed for appending the `from` vector. +- The implementation of the Infomap algorithm behind `igraph_community_infomap()` has been updated with a more recent version (2.8.0). Isolated vertices are now supported. +- `igraph_vector_difference_sorted()` now handles multisets properly (and documents how the multiplicities are handled). + +### Finalized experimental functions + +- The following functions are not experimental any more: `igraph_count_loops()`, `igraph_count_reachable()`, `igraph_degree_correlation_vector`, `igraph_distances_cutoff()`, `igraph_distances_floyd_warshall()`, `igraph_distances_dijkstra_cutoff()`, `igraph_ecc()`, `igraph_enter_safelocale()`, `igraph_exit_safelocale()`, `igraph_feedback_vertex_set()`, `igraph_find_cycle()`, `igraph_get_shortest_path_astar()`, `igraph_graph_power()`, `igraph_hexagonal_lattice()`, `igraph_hypercube()`, `igraph_is_bipartite_coloring()`, `igraph_is_clique()`, `igraph_is_complete()`, `igraph_is_edge_coloring()`, `igraph_is_vertex_coloring()`, `igraph_is_independent_vertex_set()`, `igraph_join()`,`igraph_joint_degree_distribution()`, `igraph_joint_degree_matrix()`, `igraph_joint_type_distribution()`, `igraph_layout_align()`, `igraph_layout_merge_dla()`, `igraph_mean_degree()`, `igraph_radius()`, `igraph_realize_bipartite_degree_sequence()`, `igraph_reachability()`, `igraph_transitive_closure()`, `igraph_tree_from_parent_vector()`, `igraph_triangular_lattice()`, `igraph_vector_intersection_size_sorted()`, `igraph_voronoi()`. ### Fixed - - `igraph_community_spinglass_single()` now uses `igraph_real_t` for its `inner_links` and `outer_links` output parameters, as these return not simply edge counts, but the sum of the weights of some edges. +- `igraph_community_spinglass_single()` now uses `igraph_real_t` for its `inner_links` and `outer_links` output parameters, as these return not simply edge counts, but the sum of the weights of some edges. Thus these results are no longer incorrectly rounded. +- `igraph_correlated_game()` and `igraph_correlated_pair_game()` validate their `permutation` argument. ### Removed - - Removed `igraph_Calloc()`, `igraph_Realloc()` and `igraph_Free()`. Use `IGRAPH_CALLOC()`, `IGRAPH_REALLOC()` and `IGRAPH_FREE()` instead. - - The deprecated `igraph_automorphisms()` was removed. Use `igraph_count_automorphisms()` or `igraph_count_automorphisms_bliss()` instead. - - The deprecated `igraph_decompose_destroy()` was removed. - - The deprecated `igraph_hub_score()` and `igraph_authority_score()` were removed. - - The deprecated `igraph_vector_copy()` and `igraph_matrix_copy()` were removed. Use `igraph_vector_init_copy()` and `igraph_matrix_init_copy()` instead. - - The deprecated `igraph_vector_e()`, `igraph_vector_e_ptr()`, `igraph_matrix_e()` and `igraph_matrix_e_ptr()` were removed. Use the alternatives ending in `_get()` and `_get_ptr()` instead. - - The deprecated `igraph_vs_seq()`, `igraph_vss_seq()`, `igraph_es_seq()`, `igraph_ess_range()`, and `igraph_vector_init_seq()` were removed. Use the `range` alternatives instead of the old `seq` ones. - - The deprecated `igraph_erdos_renyi_game()` and `igraph_bipartite_game()` were removed. Use the corresponding functions with `_gnm()` and `_gnp()` in the name instead. - - The deprecated `igraph_tree()` was removed. Use `igraph_kary_tree()` instead. - - The deprecated `igraph_lattice()` was removed. Use `igraph_square_lattice()` instead. - - The deprecated `igraph_minimum_spanning_tree_prim()` was removed. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. - - The deprecated `igraph_minimum_spanning_tree_unweighted()` was removed. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. - - The deprecated `igraph_get_sparsemat()` was removed. Use `igraph_get_adjacency_sparse()` instead. - - The deprecated `igraph_get_stochastic_sparsemat()` was removed. Use `igraph_get_stochastic_sparse()` instead. - - The deprecated `igraph_are_connected()` was removed. Use `igraph_are_adjacent()` instead. - - The deprecated `igraph_laplacian()` was removed. Use `igraph_get_laplacian()` or `igraph_get_laplacian_sparse()` instead. - - The deprecated `igraph_subgraph_edges()` was removed. Use `igraph_subgraph_from_edges()` instead. - - The deprecated `igraph_read_graph_dimacs()` and `igraph_write_graph_dimacs()` were removed. These names may be re-used in the future. Use `igraph_read_graph_dimacs_flow()` and `igraph_write_graph_dimacs_flow()` instead. - - The deprecated `igraph_isomorphic_function_vf2()` was removed. Use `igraph_get_isomorphisms_vf2_callback()` instead. - - The deprecated `igraph_subisomorphic_function_vf2()` was removed. Use `igraph_get_subisomorphisms_vf2_callback()` instead. - - The deprecated `igraph_isomorphic_34()` was removed. Its functionality is accessible through `igraph_isomorphic()`. - - The deprecated `igraph_transitive_closure_dag()` was removed. Use `igraph_transitive_closure()` instead, which works for all graphs, not just DAGs. - - The deprecated `igraph_vector_move_interval2()` was removed. - - The deprecated `igraph_sparsemat_copy()` was removed. Use `igraph_sparsemat_init_copy()` instead. - - The deprecated `igraph_sparsemat_eye()` was removed. Use `igraph_sparsemat_init_eye()` instead. - - The deprecated `igraph_sparsemat_diag()` was removed. Use `igraph_sparsemat_init_diag()` instead. - - The deprecated `igraph_zeroin()` was removed. - - The deprecated `igraph_random_edge_walk()` was removed. Its functionality is incorporated in `igraph_random_walk()`. - - The deprecated `igraph_vector_qsort_ind()` was removed. Use `igraph_vector_sort_ind()` instead. - - The deprecated `igraph_vector_binsearch2()` was removed. Use `igraph_vector_contains_sorted()` instead. - - The deprecated `igraph_deterministic_optimal_imitation()`, `igraph_moran_process()`, `igraph_roulette_wheel_imitation()` and `igraph_stochastic_imitation()` functions were removed. - - The unused enum type `igraph_fileformat_type_t` was removed. - - The deprecated `igraph_adjacent_triangles()` was removed. Use `igraph_count_adjacent_triangles()` instead. - - The macros `IGRAPH_POSINFINITY` and `IGRAPH_NEGINFINITY` were removed. Use `IGRAPH_INFINITY` and `-IGRAPH_INFINITY` instead. +- Removed `igraph_Calloc()`, `igraph_Realloc()` and `igraph_Free()`. Use `IGRAPH_CALLOC()`, `IGRAPH_REALLOC()` and `IGRAPH_FREE()` instead. +- The deprecated `igraph_adjacent_triangles()` was removed. Use `igraph_count_adjacent_triangles()` instead. +- The deprecated `igraph_are_connected()` was removed. Use `igraph_are_adjacent()` instead. +- The deprecated `igraph_automorphisms()` was removed. Use `igraph_count_automorphisms()` or `igraph_count_automorphisms_bliss()` instead. +- The deprecated `igraph_convex_hull()` was removed. Use `igraph_convex_hull_2d()` instead. +- The deprecated `igraph_decompose_destroy()` was removed. +- The deprecated `igraph_hub_score()` and `igraph_authority_score()` were removed. +- The deprecated `igraph_vs_seq()`, `igraph_vss_seq()`, `igraph_es_seq()`, `igraph_ess_range()`, and `igraph_vector_init_seq()` were removed. Use the `range` alternatives instead of the old `seq` ones. +- The deprecated `igraph_erdos_renyi_game()` and `igraph_bipartite_game()` were removed. Use the corresponding functions with `_gnm()` and `_gnp()` in the name instead. +- The deprecated `igraph_tree()` was removed. Use `igraph_kary_tree()` instead. +- The deprecated `igraph_lattice()` was removed. Use `igraph_square_lattice()` instead. +- The deprecated `igraph_minimum_spanning_tree_prim()` was removed. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. +- The deprecated `igraph_minimum_spanning_tree_unweighted()` was removed. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. +- The deprecated `igraph_get_sparsemat()` was removed. Use `igraph_get_adjacency_sparse()` instead. +- The deprecated `igraph_get_stochastic_sparsemat()` was removed. Use `igraph_get_stochastic_sparse()` instead. +- The deprecated `igraph_laplacian()` was removed. Use `igraph_get_laplacian()` or `igraph_get_laplacian_sparse()` instead. +- The deprecated `igraph_subgraph_edges()` was removed. Use `igraph_subgraph_from_edges()` instead. +- The deprecated `igraph_read_graph_dimacs()` and `igraph_write_graph_dimacs()` were removed. These names may be re-used in the future. Use `igraph_read_graph_dimacs_flow()` and `igraph_write_graph_dimacs_flow()` instead. +- The deprecated `igraph_isomorphic_function_vf2()` was removed. Use `igraph_get_isomorphisms_vf2_callback()` instead. +- The deprecated `igraph_subisomorphic_function_vf2()` was removed. Use `igraph_get_subisomorphisms_vf2_callback()` instead. +- The deprecated `igraph_isomorphic_34()` was removed. Its functionality is accessible through `igraph_isomorphic()`. +- The deprecated `igraph_transitive_closure_dag()` was removed. Use `igraph_transitive_closure()` instead, which works for all graphs, not just DAGs. +- The deprecated `igraph_sparsemat_copy()` was removed. Use `igraph_sparsemat_init_copy()` instead. +- The deprecated `igraph_sparsemat_eye()` was removed. Use `igraph_sparsemat_init_eye()` instead. +- The deprecated `igraph_sparsemat_diag()` was removed. Use `igraph_sparsemat_init_diag()` instead. +- The deprecated `igraph_sparsemat()` and `igraph_weighted_sparsemat()` functions were removed; use `igraph_get_adjacency_sparse()` instead. +- The deprecated `igraph_random_edge_walk()` was removed. Its functionality is incorporated in `igraph_random_walk()`. +- The deprecated `igraph_vector_qsort_ind()` was removed. Use `igraph_vector_sort_ind()` instead. +- The deprecated `igraph_vector_binsearch2()` was removed. Use `igraph_vector_contains_sorted()` instead. +- The deprecated `igraph_vector_copy()` and `igraph_matrix_copy()` were removed. Use `igraph_vector_init_copy()` and `igraph_matrix_init_copy()` instead. +- The deprecated `igraph_vector_e()`, `igraph_vector_e_ptr()`, `igraph_matrix_e()` and `igraph_matrix_e_ptr()` were removed. Use the alternatives ending in `_get()` and `_get_ptr()` instead. +- The deprecated `igraph_vector_move_interval2()` was removed. +- The deprecated `igraph_rng_get_dirichlet()` function was removed. +- The deprecated `igraph_zeroin()` was removed. +- The deprecated `igraph_deterministic_optimal_imitation()`, `igraph_moran_process()`, `igraph_roulette_wheel_imitation()` and `igraph_stochastic_imitation()` functions were removed. +- `igraph_sample_dirichlet()`, `igraph_sample_sphere_surface()` and `igraph_sample_sphere_volume()` were removed in favour of `igraph_rng_sample_dirichlet()`, `igraph_rng_sample_sphere_surface()` and `igraph_rng_sample_sphere_volume()`, which allow the user to specify the random number generator to use. +- The unused enum type `igraph_fileformat_type_t` was removed. +- The macros `IGRAPH_POSINFINITY` and `IGRAPH_NEGINFINITY` were removed. Use `IGRAPH_INFINITY` and `-IGRAPH_INFINITY` instead. +- Removed `igraph_sparsemat_view()` as its design was broken and required the user to reach into the internals of `igraph_sparmsemat_t` to destroy it properly. ### Deprecated @@ -151,377 +265,389 @@ ### Other - - Improved performance when creating graphs from dense adjacency matrices (`igraph_adjacency()` and `igraph_weighted_adjacency()`). +- The documentation was reorganized. +- Various documentation improvements. +- Improved performance when creating graphs from dense adjacency matrices (`igraph_adjacency()` and `igraph_weighted_adjacency()`). -## [master] +## [0.10.17] - 2025-09-19 ### Added - - `igraph_layout_align()` attempts to align a graph layout with the coordinate axes in a visually pleasing manner (experimental function). - - `igraph_product()` supports the lexicographic, strong and modular graph products. Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2772 and #2793! - - `igraph_rooted_product()` computes the the rooted graph product. Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2793! - - `igraph_mycielskian()` and `igraph_mycielski_graph()` compute a Mycielski transformation of a graph, and a Mycielski graph, respectively. Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2741! - - `igraph_path_graph()` is a convenience wrapper for `igraph_ring()` with `circular=false`. - - `igraph_cycle_graph()` is a convenience wrapper for `igraph_ring()` with `circular=true`. - - `igraph_bond_percolation()`, `igraph_site_percolation()` and `igraph_edgelist_percolation()` calculates the time evolution of the size of the giant component of a graph when edges or vertices are added one by one in a certain (or random) order. Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2778! - - `igraph_invert_permutation()` inverts a permutation stored in an integer vector. - - `igraph_is_vertex_coloring()` and `igraph_is_edge_coloring()` check if a vertex or edge coloring is valid, i.e. whether adjacenct vertices/edges always have distinct colors. Thanks to Sarah Rashidi @its-serah for contributing this in #2807! - - `igraph_rich_club_sequence()` calculates how the density of a graph changes as vertices are removed. Thanks to Zara Zong @minifinity for contributing this in #2740! +- `igraph_layout_align()` attempts to align a graph layout with the coordinate axes in a visually pleasing manner (experimental function). +- `igraph_product()` supports the lexicographic, strong and modular graph products. Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2772 and #2793! +- `igraph_rooted_product()` computes the rooted graph product (experimental function). Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2793! +- `igraph_mycielskian()` (experimental function) and `igraph_mycielski_graph()` compute a Mycielski transformation of a graph, and a Mycielski graph, respectively. Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2741! +- `igraph_path_graph()` is a convenience wrapper for `igraph_ring()` with `circular=false`. +- `igraph_cycle_graph()` is a convenience wrapper for `igraph_ring()` with `circular=true`. +- `igraph_site_percolation()`, `igraph_bond_percolation()` and `igraph_edgelist_percolation()` compute the evolution of the size of the giant component of a graph when vertices (site percolation) or edges (bond percolation) are added one by one in a given order (experimental functions). Thanks to Arnór Friðriksson @Zepeacedust for implementing this in #2778! +- `igraph_invert_permutation()` inverts a permutation stored in an integer vector. +- `igraph_is_vertex_coloring()` and `igraph_is_edge_coloring()` check if a vertex or edge coloring is valid, i.e. whether adjacent vertices/edges always have distinct colors (experimental functions). Thanks to Sarah Rashidi @its-serah for contributing this in #2807! +- `igraph_is_bipartite_coloring()` checks if a bipartite type assignment is valid, i.e. whether adjacent vertices always have different types (experimental function). Thanks to Sarah Rashidi @its-serah for contributing this in #2807! +- `igraph_rich_club_sequence()` calculates how the density of a graph changes as vertices are removed (experimental function). Thanks to Zara Zong @minifinity for contributing this in #2740! ### Changed - - `igraph_bipartite_game_gnp()` can now generate graphs with more than a hundred million vertices. Thanks to Dev Lohani @devlohani99 for implementing this in #2767! - - `igraph_reindex_membership()` now supports arbitrary cluster indices. Previously, it would error when indices are not within `0 .. n-1` where `n` is the membership vector length. +- `igraph_bipartite_game_gnp()` can now generate graphs with more than a hundred million vertices. Thanks to Dev Lohani @devlohani99 for implementing this in #2767! +- `igraph_reindex_membership()` now supports arbitrary cluster indices. Previously, it would error when indices are not within `0 .. n-1` where `n` is the membership vector length. +- `igraph_modularity()` now supports arbitrary cluster indices. However, ensuring that cluster indices are within the range `0 .. n-1`, where `n` is the vertex count, allows for better performance. ### Fixed - - Fix failure in SIR simulation due to roundoff errors creating slightly negative rates. - - Fix infinite coordinates for certain path graphs with `igraph_layout_kamada_kawai_3d()`. - - `igraph_community_leiden()` did not iterate until the partition ceased to change when `n_iterations < 0`. Thanks to Lucas Lopes Felipe @lucaslopes for fixing this in #2799! +- Fix failure in SIR simulation due to roundoff errors creating slightly negative rates. +- Fix infinite coordinates for certain path graphs with `igraph_layout_kamada_kawai_3d()`. +- `igraph_community_leiden()` did not iterate until the partition ceased to change when `n_iterations < 0`. Thanks to Lucas Lopes Felipe @lucaslopes for fixing this in #2799! +- The widest path functions `igraph_widest_path_widths_floyd_warshall()`, `igraph_widest_path_widths_dijkstra()`, `igraph_get_widest_paths()`, and `igraph_get_widest_path()` incorrectly ignored edges with positive infinite width. Now they ignore edges with negative infinite width. +- `igraph_cliques_callback()` would sometimes fail to respect a request to stop (i.e. returning `IGRAPH_STOP`) from the callback. This is now corrected. +- `igraph_hypercube()` now validates the hypercube dimension and prevents negative values. +- `igraph_sparsemat_view()` checks for out-of-memory conditions. +- Fix assertion error when stopping search early in `igraph_simple_cycles_callback()` by returning `IGRAPH_STOP` from the callback. ### Deprecated - - `igraph_sparsemat()` and `igraph_weighted_sparsemat()` are now deprecated; their functionality is duplicated by `igraph_get_adjacency_sparse()`. They will be removed in veresion 1.0. +- `igraph_sparsemat()` and `igraph_weighted_sparsemat()` are now deprecated; their functionality is duplicated by `igraph_get_adjacency_sparse()`. They will be removed in version 1.0. +- `igraph_convex_hull()` is deprecated in favour of `igraph_convex_hull_2d()` and scheduled for removal in 1.0. ### Other - - Documentation improvements, including a new glossary. - - Simple cycle search (`igraph_simple_cycles()` and `igraph_simple_cycles_callback()`) is sped up by skipping cycle search from some redundant start vertices. Thanks to Tim Bernhard @GenieTim for contributing this improvement in #2714! +- Documentation improvements, including a new glossary. +- Simple cycle search (`igraph_simple_cycles()` and `igraph_simple_cycles_callback()`) is sped up by skipping cycle search from some redundant start vertices. Thanks to Tim Bernhard @GenieTim for contributing this improvement in #2714! +- `igraph_realize_degree_sequence()` is significantly sped up for simple undirected graphs, and now has near-linear complexity for this case. Thanks to Zara Zong @ minifinity for implementing this in #2786! ## [0.10.16] - 2025-06-10 ### Added - - `igraph_count_triangles()` counts undirected triangles in a graph. - - `igraph_count_adjacent_triangles()` (rename of `igraph_adjacent_triangles()`). - - `igraph_rng_get_bool()` and `RNG_BOOL()` produce a single random boolean. - - `igraph_product()` computes various kinds of graph products of two graphs. Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2748! +- `igraph_count_triangles()` counts undirected triangles in a graph. +- `igraph_count_adjacent_triangles()` (rename of `igraph_adjacent_triangles()`). +- `igraph_rng_get_bool()` and `RNG_BOOL()` produce a single random boolean. +- `igraph_product()` computes various kinds of graph products of two graphs. Thanks to Gulshan Kumar @gulshan-123 for contributing this functionality in #2748! ### Changed - - `igraph_neighborhood_size()`, `igraph_neighborhood()` and `igraph_neighborhood_graphs()` now accept a negative `order` value and interpret it as infinite order. Previously, a negative `order` value was disallowed. - - `igraph_famous()` now accepts `Groetzsch` as an alias of `Grotzsch`. - - `igraph_vertex_path_from_edge_path()` can now determine the start vertex automatically. +- `igraph_neighborhood_size()`, `igraph_neighborhood()` and `igraph_neighborhood_graphs()` now accept a negative `order` value and interpret it as infinite order. Previously, a negative `order` value was disallowed. +- `igraph_famous()` now accepts `Groetzsch` as an alias of `Grotzsch`. +- `igraph_vertex_path_from_edge_path()` can now determine the start vertex automatically. ### Fixed - - `igraph_largest_independent_vertex_sets()` and `igraph_maximal_independent_vertex_sets()` would sometimes return incorrect results for graphs with self-loops. This is now corrected. - - `igraph_vertex_path_from_edge_path()` now validates the start vertex. - - Fixed a memory leak in the GraphML parser for cases when the `id` attribute was specified multiple times within the same XML tag. +- `igraph_largest_independent_vertex_sets()` and `igraph_maximal_independent_vertex_sets()` would sometimes return incorrect results for graphs with self-loops. This is now corrected. +- `igraph_vertex_path_from_edge_path()` now validates the start vertex. +- Fixed a memory leak in the GraphML parser for cases when the `id` attribute was specified multiple times within the same XML tag. ### Deprecated - - The undocumented function `igraph_vector_sumsq()` is deprecated. Use `igraph_blas_dnrm2()` to compute the Euclidean norm of real vectors. - - `igraph_adjacent_triangles()` is deprecated and scheduled for removal in 1.0. - - `igraph_deterministic_optimal_imitation()`, `igraph_moran_process()`, `igraph_roulette_wheel_imitation()` and `igraph_stochastic_imitation()` are now deprecated and scheduled for removal in 1.0. - - `igraph_rng_get_dirichlet()` is deprecated and scheduled for removal in 1.0. Its interface is inconsistent with the other `igraph_rng_get_...()` functions and we have a replacemenet for it in `igraph_sample_dirichlet()`. igraph 1.0 will gain an `igraph_rng_sample_dirichlet()` function that lets the caller pass in an `igraph_rng_t` instance as well. +- The undocumented function `igraph_vector_sumsq()` is deprecated. Use `igraph_blas_dnrm2()` to compute the Euclidean norm of real vectors. +- `igraph_adjacent_triangles()` is deprecated and scheduled for removal in 1.0. +- `igraph_deterministic_optimal_imitation()`, `igraph_moran_process()`, `igraph_roulette_wheel_imitation()` and `igraph_stochastic_imitation()` are now deprecated and scheduled for removal in 1.0. +- `igraph_rng_get_dirichlet()` is deprecated and scheduled for removal in 1.0. Its interface is inconsistent with the other `igraph_rng_get_...()` functions and we have a replacemenet for it in `igraph_sample_dirichlet()`. igraph 1.0 will gain an `igraph_rng_sample_dirichlet()` function that lets the caller pass in an `igraph_rng_t` instance as well. ### Other - - Workaround for bug in CMake 3.31.0, see https://gitlab.kitware.com/cmake/cmake/-/issues/26449 - - Updated the vendored `plfit` library to version 1.0.0. This works around a bug in some MSVC / Windows SDK versions that define a `NAN` macro that is not a compile-time constant. - - Updated vendored BLAS to 3.12.0 and vendored ARPACK to ARPACK-NG 3.7.0. - - Re-translated vendored BLAS/LAPACK/ARPACK sources with f2c version 20240504. - - The performance of `igraph_transitivity_undirected()` is improved by a factor of about 2.5. - - The performance of `igraph_degree_sequence_game()` is improved when using `IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE`. - - Documentation improvements and fixes. +- Workaround for bug in CMake 3.31.0, see +- Updated the vendored `plfit` library to version 1.0.0. This works around a bug in some MSVC / Windows SDK versions that define a `NAN` macro that is not a compile-time constant. +- Updated vendored BLAS to 3.12.0 and vendored ARPACK to ARPACK-NG 3.7.0. +- Re-translated vendored BLAS/LAPACK/ARPACK sources with f2c version 20240504. +- The performance of `igraph_transitivity_undirected()` is improved by a factor of about 2.5. +- The performance of `igraph_degree_sequence_game()` is improved when using `IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE`. +- Documentation improvements and fixes. ## [0.10.15] ### Added - - `igraph_bitset_update()` copies the contents of one bitset into another (experimental function). - - `igraph_vector_sort_ind()` (rename of `igraph_vector_qsort_ind()`). - - `igraph_vector_contains_sorted()` (rename of `igraph_vector_binsearch2()`). - - `igraph_vector_reverse_section()` reverses a contiguous section of a vector. - - `igraph_vector_rotate_left()` applies a cyclic permutation to a vector. - - `igraph_strvector_swap_elements()` swaps two strings in an `igraph_strvector_t`. - - `igraph_find_cycle()` finds a single cycle in a graph, if it exists (experimental function). - - `igraph_feedback_vertex_set()` finds a minimum feedback vertex set in a directed or undirected graph (experimental function). - - `igraph_simple_cycles()` and `igraph_simple_cycles_callback()` find all simple cycles in a graph, optionally with an upper bound on the cycle length (experimental functions). Many thanks to Tim Bernhard @GenieTim for contributing this functionality in #2181. +- `igraph_bitset_update()` copies the contents of one bitset into another (experimental function). +- `igraph_vector_sort_ind()` (rename of `igraph_vector_qsort_ind()`). +- `igraph_vector_contains_sorted()` (rename of `igraph_vector_binsearch2()`). +- `igraph_vector_reverse_section()` reverses a contiguous section of a vector. +- `igraph_vector_rotate_left()` applies a cyclic permutation to a vector. +- `igraph_strvector_swap_elements()` swaps two strings in an `igraph_strvector_t`. +- `igraph_find_cycle()` finds a single cycle in a graph, if it exists (experimental function). +- `igraph_feedback_vertex_set()` finds a minimum feedback vertex set in a directed or undirected graph (experimental function). +- `igraph_simple_cycles()` and `igraph_simple_cycles_callback()` find all simple cycles in a graph, optionally with an upper bound on the cycle length (experimental functions). Many thanks to Tim Bernhard @GenieTim for contributing this functionality in #2181. ### Changed - - `igraph_feedback_arc_set()` uses a much faster method for solving the exact minimum feedback arc set problem. The new method (`IGRAPH_FAS_EXACT_IP_CG`) is used by default (i.e. with `IGRAPH_FAS_EXACT_IP`), but the previous method is also kept available (`IGRAPH_FAS_EXACT_IP_TI`). - - `igraph_motifs_randesu()`, `igraph_motifs_randesu_callback()`, `igraph_motifs_randesu_estimate()` and `igraph_motifs_randesu_no()` now accept `NULL` for their `cut_prob` parameter, signifying that a complete search should be performed. - - `igraph_centralization_eigenvector_centrality_tmax()` and `igraph_centralization_eigenvector_centrality()` cannot produce meaningful results without normalizing vertex-level eigenvector centrality in a well-defined way. This was not the case when using `scale=false`. These functions now ignore the value of the `scale` parameter and always scale vertex-level centrality scores to have a maximum of 1. If you require a different type of normalization for the vertex-level eigenvector centrality scores, perform this normalization manually, and call `igraph_centralization()` to compute the centralization. - - When `igraph_eigenvector_centrality()` receives a directed acyclic graph as input, it now produces an eigenvector which has 1s in sink vertices and 0s everywhere else. Previously, it would return an all-zero vector. Note that eigenvector centrality is not uniquely defined for graphs that are not (strongly) connected, and both of these results can be considered valid. This change is to ensure consistency with the definition of the theoretical maximum of eigenvector centralization, which assumes the in-star to be the most centralized directed network. +- `igraph_feedback_arc_set()` uses a much faster method for solving the exact minimum feedback arc set problem. The new method (`IGRAPH_FAS_EXACT_IP_CG`) is used by default (i.e. with `IGRAPH_FAS_EXACT_IP`), but the previous method is also kept available (`IGRAPH_FAS_EXACT_IP_TI`). +- `igraph_motifs_randesu()`, `igraph_motifs_randesu_callback()`, `igraph_motifs_randesu_estimate()` and `igraph_motifs_randesu_no()` now accept `NULL` for their `cut_prob` parameter, signifying that a complete search should be performed. +- `igraph_centralization_eigenvector_centrality_tmax()` and `igraph_centralization_eigenvector_centrality()` cannot produce meaningful results without normalizing vertex-level eigenvector centrality in a well-defined way. This was not the case when using `scale=false`. These functions now ignore the value of the `scale` parameter and always scale vertex-level centrality scores to have a maximum of 1. If you require a different type of normalization for the vertex-level eigenvector centrality scores, perform this normalization manually, and call `igraph_centralization()` to compute the centralization. +- When `igraph_eigenvector_centrality()` receives a directed acyclic graph as input, it now produces an eigenvector which has 1s in sink vertices and 0s everywhere else. Previously, it would return an all-zero vector. Note that eigenvector centrality is not uniquely defined for graphs that are not (strongly) connected, and both of these results can be considered valid. This change is to ensure consistency with the definition of the theoretical maximum of eigenvector centralization, which assumes the in-star to be the most centralized directed network. ### Fixed - - `igraph_layout_drl()` and `igraph_layout_drl_3d()` would crash with an assertion failure when interrupted. This is now fixed. - - Removed broken interruption support from `igraph_community_spinglass_single()`. - - In rare cases `igraph_community_multilevel()` could enter an infinite loop. This is now corrected. - - Fixed null-dereference in `igraph_community_voronoi()` when requesting `modularity` but not `membership`. - - Fixed null-dereference in `igraph_community_optimal_modularity()` when requesting `modularity` but not `membership` and passing a null graph or singleton graph. - - `igraph_layout_umap()` and `igraph_layout_umap_3d()` would crash when passing `distances=NULL` and `distances_are_weights=true`. This is now fixed. - - `igraph_layout_umap()` and `igraph_layout_umap_3d()` would crash on interruption. This is now fixed. - - `igraph_read_graph_pajek()` now warns about duplicate vertex IDs in input files. - - The documented `igraph_strvector_resize_min()` was missing from headers. - - `igraph_feedback_arc_set()` now validates the edge weights. - - `igraph_layout_lgl()` was not working correctly since igraph 0.10.0 due to a poor choice of initial coordinates. This is now fixed. - - `igraph_centralization_degree_tmax()`, `igraph_centralization_betweenness_tmax()`, `igraph_centralization_closeness_tmax()`, and `igraph_centralization_eigenvector_centrality_tmax()` now validate their `nodes` parameter. - - `igraph_centralization_degree_tmax()`, `igraph_centralization_betweenness_tmax()`, `igraph_centralization_closeness_tmax()`, and `igraph_centralization_eigenvector_centrality_tmax()` now return NaN for zero-vertex graphs. Previously they would return invalid values. - - `igraph_centralization_eigenvector_centrality_tmax()` now returns 0 for the undirected singleton graph. Previous it would return an invalid value. - - `igraph_motifs_randesu_estimate()` now validates the sample size. - - `igraph_bipartite_projection_size()` now validates the bipartite `types` vector. +- `igraph_layout_drl()` and `igraph_layout_drl_3d()` would crash with an assertion failure when interrupted. This is now fixed. +- Removed broken interruption support from `igraph_community_spinglass_single()`. +- In rare cases `igraph_community_multilevel()` could enter an infinite loop. This is now corrected. +- Fixed null-dereference in `igraph_community_voronoi()` when requesting `modularity` but not `membership`. +- Fixed null-dereference in `igraph_community_optimal_modularity()` when requesting `modularity` but not `membership` and passing a null graph or singleton graph. +- `igraph_layout_umap()` and `igraph_layout_umap_3d()` would crash when passing `distances=NULL` and `distances_are_weights=true`. This is now fixed. +- `igraph_layout_umap()` and `igraph_layout_umap_3d()` would crash on interruption. This is now fixed. +- `igraph_read_graph_pajek()` now warns about duplicate vertex IDs in input files. +- The documented `igraph_strvector_resize_min()` was missing from headers. +- `igraph_feedback_arc_set()` now validates the edge weights. +- `igraph_layout_lgl()` was not working correctly since igraph 0.10.0 due to a poor choice of initial coordinates. This is now fixed. +- `igraph_centralization_degree_tmax()`, `igraph_centralization_betweenness_tmax()`, `igraph_centralization_closeness_tmax()`, and `igraph_centralization_eigenvector_centrality_tmax()` now validate their `nodes` parameter. +- `igraph_centralization_degree_tmax()`, `igraph_centralization_betweenness_tmax()`, `igraph_centralization_closeness_tmax()`, and `igraph_centralization_eigenvector_centrality_tmax()` now return NaN for zero-vertex graphs. Previously they would return invalid values. +- `igraph_centralization_eigenvector_centrality_tmax()` now returns 0 for the undirected singleton graph. Previous it would return an invalid value. +- `igraph_motifs_randesu_estimate()` now validates the sample size. +- `igraph_bipartite_projection_size()` now validates the bipartite `types` vector. ### Deprecated - - `igraph_minimum_spanning_tree_prim()` and `igraph_minimum_spanning_tree_unweighted()` are deprecated. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. - - `igraph_array3_t` and all associated functions are deprecated and scheduled for removal in igraph 1.0. - - `igraph_vector_qsort_ind()` is deprecated in favour of `igraph_vector_sort_ind()`. - - `igraph_vector_binsearch2()` is deprecated in favour of `igraph_vector_contains_sorted()`. +- `igraph_minimum_spanning_tree_prim()` and `igraph_minimum_spanning_tree_unweighted()` are deprecated. Use `igraph_minimum_spanning_tree()` in conjunction with `igraph_subgraph_from_edges()` instead. +- `igraph_array3_t` and all associated functions are deprecated and scheduled for removal in igraph 1.0. +- `igraph_vector_qsort_ind()` is deprecated in favour of `igraph_vector_sort_ind()`. +- `igraph_vector_binsearch2()` is deprecated in favour of `igraph_vector_contains_sorted()`. +- The error code `IGRAPH_ENEGLOOP` is deprecated in favour of the newly introduced `IGRAPH_ENEGCYCLE`. The underlying integer code did not change. ### Other - - Fixed multiple memory leaks in benchmark programs. - - Documentation improvements. +- Fixed multiple memory leaks in benchmark programs. +- Documentation improvements. ## [0.10.13] ### Added - - `igraph_bitset_fill()` sets all elements of a bitset to the same value (experimental function). - - `igraph_bitset_null()` clears all elements of a bitset (experimental function). - - `igraph_bitset_is_all_zero()`, `igraph_bitset_is_all_one()`, `igraph_bitset_is_any_zero()`, `igraph_bitset_is_any_one()` check if any/all elements of a bitset are zeros/ones (experimental functions). - - `igraph_chung_lu_game()` implements the classic Chung-Lu model, as well as a number of its variants (experimental function). - - `igraph_mean_degree()` computes the average of vertex degrees (experimental function). - - `igraph_count_loops()` counts self-loops in the graph (experimental function). - - `igraph_is_clique()` checks if all pairs within a set of vertices are connected (experimental function). - - `igraph_is_independent_vertex_set()` checks if no pairs within a set of vertices are connected (experimental function). - - `igraph_hypercube()` creates a hypercube graph (experimental function). - - `igraph_vector_intersection_size_sorted()` counts elements common to two sorted vectors (experimental function). - - `igraph_stack_capacity()` returns the allocated capacity of a stack. - - `igraph_vector_is_all_finite()` checks if all elements in a vector are finite (i.e. neither NaN nor Inf). +- `igraph_bitset_fill()` sets all elements of a bitset to the same value (experimental function). +- `igraph_bitset_null()` clears all elements of a bitset (experimental function). +- `igraph_bitset_is_all_zero()`, `igraph_bitset_is_all_one()`, `igraph_bitset_is_any_zero()`, `igraph_bitset_is_any_one()` check if any/all elements of a bitset are zeros/ones (experimental functions). +- `igraph_chung_lu_game()` implements the classic Chung-Lu model, as well as a number of its variants (experimental function). +- `igraph_mean_degree()` computes the average of vertex degrees (experimental function). +- `igraph_count_loops()` counts self-loops in the graph (experimental function). +- `igraph_is_clique()` checks if all pairs within a set of vertices are connected (experimental function). +- `igraph_is_independent_vertex_set()` checks if no pairs within a set of vertices are connected (experimental function). +- `igraph_hypercube()` creates a hypercube graph (experimental function). +- `igraph_vector_intersection_size_sorted()` counts elements common to two sorted vectors (experimental function). +- `igraph_stack_capacity()` returns the allocated capacity of a stack. +- `igraph_vector_is_all_finite()` checks if all elements in a vector are finite (i.e. neither NaN nor Inf). ### Fixed - - Fixed a bug that incorrectly cached that a graph has no multiple edges when `igraph_init_adjlist()` was called with `IGRAPH_NO_LOOPS` and `IGRAPH_NO_MULTIPLE` and all the multi-edges were loop edges. - - `igraph_is_forest()` would fail to set the result variable when testing for a directed forest, and it was already cached that the graph was not an undirected forest. - - `igraph_hub_and_authority_scores()` no longer clips negative results to zeros when negative weights are present. - - Fixed an assertion failure in `igraph_realize_bipartite_degree_sequence()` with some non-graphical degree sequences when requesting simple bipartite graphs. - - `igraph_static_fitness_game()` checks the input more carefully, and avoids an infinite loop in rare edge cases, such as when (almost) all fitness scores are zero. - - `igraph_arpack_rnsolve()` used the incorrect error message text for some errors. This is now corrected. - - Corrected the detection of some MSVC-specific bitset intrinsics during configuration. - - Corrected a bug in the fallback implementation of `igraph_bitset_countl_zero()` when `IGRAPH_INTEGER_SIZE` was set to 32. This fallback implementation was _not_ used with GCC, Clang, or MSVC. +- Fixed a bug that incorrectly cached that a graph has no multiple edges when `igraph_init_adjlist()` was called with `IGRAPH_NO_LOOPS` and `IGRAPH_NO_MULTIPLE` and all the multi-edges were loop edges. +- `igraph_is_forest()` would fail to set the result variable when testing for a directed forest, and it was already cached that the graph was not an undirected forest. +- `igraph_hub_and_authority_scores()` no longer clips negative results to zeros when negative weights are present. +- Fixed an assertion failure in `igraph_realize_bipartite_degree_sequence()` with some non-graphical degree sequences when requesting simple bipartite graphs. +- `igraph_static_fitness_game()` checks the input more carefully, and avoids an infinite loop in rare edge cases, such as when (almost) all fitness scores are zero. +- `igraph_arpack_rnsolve()` used the incorrect error message text for some errors. This is now corrected. +- Corrected the detection of some MSVC-specific bitset intrinsics during configuration. +- Corrected a bug in the fallback implementation of `igraph_bitset_countl_zero()` when `IGRAPH_INTEGER_SIZE` was set to 32. This fallback implementation was _not_ used with GCC, Clang, or MSVC. ### Changed - - `igraph_is_graphical()` and `igraph_is_bigraphical()` are now linear-time in all cases, and generally several times faster than before (thanks to @gendelpiekel, contributed in #2605). - - `igraph_erdos_renyi_game_gnp()` can now generate graphs with more than a hundred million vertices. - - `igraph_hub_and_authority_scores()` now warns when negative edge weights are present. - - `igraph_layout_lgl()` now uses a BFS tree rooted in the vertex specified as `proot` to guide the layout. Previously it used an unspecified (arbitrary) spanning tree. - - Updated the internal heuristics used by igraph's ARPACK interface, `igraph_arpack_rssolve()` and `igraph_arpack_rnsolve()`, to improve the robustness of calculations. - - Updated the initial vector construction in `igraph_hub_and_authority_scores()`, `igraph_eigenvector_centrality()` and `igraph_(personalized_)pagerank()` with `IGRAPH_PAGERANK_ALGO_ARPACK`. This improves the robustness and convergence of calculations. +- `igraph_is_graphical()` and `igraph_is_bigraphical()` are now linear-time in all cases, and generally several times faster than before (thanks to @gendelpiekel, contributed in #2605). +- `igraph_erdos_renyi_game_gnp()` can now generate graphs with more than a hundred million vertices. +- `igraph_hub_and_authority_scores()` now warns when negative edge weights are present. +- `igraph_layout_lgl()` now uses a BFS tree rooted in the vertex specified as `proot` to guide the layout. Previously it used an unspecified (arbitrary) spanning tree. +- Updated the internal heuristics used by igraph's ARPACK interface, `igraph_arpack_rssolve()` and `igraph_arpack_rnsolve()`, to improve the robustness of calculations. +- Updated the initial vector construction in `igraph_hub_and_authority_scores()`, `igraph_eigenvector_centrality()` and `igraph_(personalized_)pagerank()` with `IGRAPH_PAGERANK_ALGO_ARPACK`. This improves the robustness and convergence of calculations. ### Other - - Documentation improvements. - - Reduced the memory usage of several functions by using bitsets instead of boolean vectors. - - `igraph_vector_intersect_sorted()` has better performance when the input vector sizes are similar. +- Documentation improvements. +- Reduced the memory usage of several functions by using bitsets instead of boolean vectors. +- `igraph_vector_intersect_sorted()` has better performance when the input vector sizes are similar. ## [0.10.12] - 2024-05-06 ### Added - - `igraph_transitive_closure()` computes the transitive closure of a graph (experimental function). - - `igraph_reachability()` determines which vertices are reachable from each other in a graph (experimental function). - - `igraph_count_reachable()` counts how many vertices are reachable from each vertex (experimental function). - - Added a bitset data structure, `igraph_bitset_t`, and a set of corresponding functions (experimental functionality). +- `igraph_transitive_closure()` computes the transitive closure of a graph (experimental function). +- `igraph_reachability()` determines which vertices are reachable from each other in a graph (experimental function). +- `igraph_count_reachable()` counts how many vertices are reachable from each vertex (experimental function). +- Added a bitset data structure, `igraph_bitset_t`, and a set of corresponding functions (experimental functionality). ### Fixed - - `igraph_community_label_propagation()` is now interruptible. - - `igraph_is_bipartite()` would on rare occasions return invalid results when the cache was employed. - - `igraph_weighted_adjacency()` correctly passes through NaN values with `IGRAPH_ADJ_MAX`, and correctly recognizes symmetric adjacency matrices containing NaN values with `IGRAPH_ADJ_UNDIRECTED`. - - `igraph_read_graph_gml()` can now read GML files that use ids larger than what is representable on 32 bits, provided that igraph was configured with a 64-bit `igraph_integer_t` size. - - Fixed a performance issue in `igraph_read_graph_graphml()` with files containing a very large number of entities, such as `>`. - - `igraph_read_graph_pajek()` has improved vertex ID validation that better matches that of Pajek's own behavior. +- `igraph_community_label_propagation()` is now interruptible. +- `igraph_is_bipartite()` would on rare occasions return invalid results when the cache was employed. +- `igraph_weighted_adjacency()` correctly passes through NaN values with `IGRAPH_ADJ_MAX`, and correctly recognizes symmetric adjacency matrices containing NaN values with `IGRAPH_ADJ_UNDIRECTED`. +- `igraph_read_graph_gml()` can now read GML files that use ids larger than what is representable on 32 bits, provided that igraph was configured with a 64-bit `igraph_integer_t` size. +- Fixed a performance issue in `igraph_read_graph_graphml()` with files containing a very large number of entities, such as `>`. +- `igraph_read_graph_pajek()` has improved vertex ID validation that better matches that of Pajek's own behavior. ### Changed - - `igraph_eigenvector_centrality()` no longer issues a warning when the input is directed and weighted. When using this function, keep in mind that eigenvector centrality is well-defined only for (strongly) connected graphs, and edges with zero weights are effectively treated as absent. +- `igraph_eigenvector_centrality()` no longer issues a warning when the input is directed and weighted. When using this function, keep in mind that eigenvector centrality is well-defined only for (strongly) connected graphs, and edges with zero weights are effectively treated as absent. ### Deprecated - - `igraph_transitive_closure_dag()` is deprecated in favour of `igraph_transitive_closure()` +- `igraph_transitive_closure_dag()` is deprecated in favour of `igraph_transitive_closure()` ### Other - - Documentation improvements. - - `igraph_strength()` and `igraph_degree(loops=false)` are now faster when calculating values for all vertices (contributed by @gendelpiekel in #2602) +- Documentation improvements. +- `igraph_strength()` and `igraph_degree(loops=false)` are now faster when calculating values for all vertices (contributed by @gendelpiekel in #2602) ## [0.10.11] - 2024-04-02 ### Added - - `igraph_is_complete()` checks whether there is a connection between all pairs of vertices (experimental function, contributed by Aymeric Agon-Rambosson @aagon in #2510). - - `igraph_join()` creates the _join_ of two graphs (experimental function, contributed by Quinn Buratynski @GanzuraTheConsumer in #2508). +- `igraph_is_complete()` checks whether there is a connection between all pairs of vertices (experimental function, contributed by Aymeric Agon-Rambosson @aagon in #2510). +- `igraph_join()` creates the _join_ of two graphs (experimental function, contributed by Quinn Buratynski @GanzuraTheConsumer in #2508). ### Fixed - - Fixed a corruption of the "finally" stack in `igraph_write_graph_gml()` for certain invalid GML files. - - Fixed a memory leak in `igraph_write_graph_lgl()` when vertex names were present but edge weights were not. - - Fixed the handling of duplicate edge IDs in `igraph_subgraph_from_edges()`. - - Fixed conversion of sparse matrices to dense with `igraph_sparsemat_as_matrix()` when sparse matrix object did not make use of its full allocated capacity. - - `igraph_write_graph_ncol()` and `igraph_write_graph_lgl()` now refuse to write vertex names which would result in an invalid file that cannot be read back in. - - `igraph_write_graph_gml()` now ignores graph attributes called `edge` or `node` with a warning. Writing these would create an invalid GML file that igraph couldn't read back. - - `igraph_disjoint_union()` and `igraph_disjoint_union_many()` now check for overflow. - - `igraph_read_graph_graphml()` now correctly compares attribute values with certain expected values, meaning that prefixes of valid values of `attr.type` are not accepted anymore. - - Empty IDs are not allowed any more in `` tags of GraphML files as this is a violation of the GraphML specification. - - `igraph_is_separator()` and `igraph_is_minimal_separator()` now work correctly with disconnected graphs. - - `igraph_linegraph()` now considers self-loops to be self-adjacent in undirected graphs, bringing consistency with how directed graphs were already handled in previous versions. - - `igraph_all_st_mincuts()` now correctly returns all minimum cuts. This also fixes a problem with `igraph_minimum_size_separators()`. - - Corrected minor error in `igraph_community_label_propagation()` when adding labels to isolated nodes with some fixed labels present. - - `igraph_community_spinglass()` no longer crashes when passing an edgeless graph and an empty weight vector. - - `igraph_rewire()` no longer crashes on graphs with more than three vertices but fewer than two edges. +- Fixed a corruption of the "finally" stack in `igraph_write_graph_gml()` for certain invalid GML files. +- Fixed a memory leak in `igraph_write_graph_lgl()` when vertex names were present but edge weights were not. +- Fixed the handling of duplicate edge IDs in `igraph_subgraph_from_edges()`. +- Fixed conversion of sparse matrices to dense with `igraph_sparsemat_as_matrix()` when sparse matrix object did not make use of its full allocated capacity. +- `igraph_write_graph_ncol()` and `igraph_write_graph_lgl()` now refuse to write vertex names which would result in an invalid file that cannot be read back in. +- `igraph_write_graph_gml()` now ignores graph attributes called `edge` or `node` with a warning. Writing these would create an invalid GML file that igraph couldn't read back. +- `igraph_disjoint_union()` and `igraph_disjoint_union_many()` now check for overflow. +- `igraph_read_graph_graphml()` now correctly compares attribute values with certain expected values, meaning that prefixes of valid values of `attr.type` are not accepted anymore. +- Empty IDs are not allowed any more in `` tags of GraphML files as this is a violation of the GraphML specification. +- `igraph_is_separator()` and `igraph_is_minimal_separator()` now work correctly with disconnected graphs. +- `igraph_linegraph()` now considers self-loops to be self-adjacent in undirected graphs, bringing consistency with how directed graphs were already handled in previous versions. +- `igraph_all_st_mincuts()` now correctly returns all minimum cuts. This also fixes a problem with `igraph_minimum_size_separators()`. +- Corrected minor error in `igraph_community_label_propagation()` when adding labels to isolated nodes with some fixed labels present. +- `igraph_community_spinglass()` no longer crashes when passing an edgeless graph and an empty weight vector. +- `igraph_rewire()` no longer crashes on graphs with more than three vertices but fewer than two edges. ### Changed - - `igraph_rewire()` on longer throws an error on graphs with fewer than four vertices. These graphs are now returned unchanged, just like other graphs which are the unique realization of their degree sequence. +- `igraph_rewire()` on longer throws an error on graphs with fewer than four vertices. These graphs are now returned unchanged, just like other graphs which are the unique realization of their degree sequence. ### Other - - Performance: `igraph_is_simple()` now makes more granular use of the cache. - - Performance: `igraph_degree()` now makes use of the cache when checking for self-loops. - - The performance of `igraph_is_minimal_separator()` was improved. - - `igraph_is_graphical()` now performs graphicality checks for degree sequences of simple directed graphs in linear time, an improvement from the previously used quadratic algorithm (contributed by Arnar Bjarni Arnarson @Tagl in #2537). - - Documentation improvements. +- Performance: `igraph_is_simple()` now makes more granular use of the cache. +- Performance: `igraph_degree()` now makes use of the cache when checking for self-loops. +- The performance of `igraph_is_minimal_separator()` was improved. +- `igraph_is_graphical()` now performs graphicality checks for degree sequences of simple directed graphs in linear time, an improvement from the previously used quadratic algorithm (contributed by Arnar Bjarni Arnarson @Tagl in #2537). +- Documentation improvements. ## [0.10.10] - 2024-02-13 ### Fixed - - When `igraph_is_forest()` determined that a graph is not a directed forest, and the `roots` output parameter was set to `NULL`, it would incorrectly cache that the graph is also not an undirected forest. - - `igraph_spanner()` now correctly ignores edge directions, and no longer crashes on directed graphs. +- When `igraph_is_forest()` determined that a graph is not a directed forest, and the `roots` output parameter was set to `NULL`, it would incorrectly cache that the graph is also not an undirected forest. +- `igraph_spanner()` now correctly ignores edge directions, and no longer crashes on directed graphs. ### Deprecated - - `igraph_are_connected()` is renamed to `igraph_are_adjacent()`; the old name is kept available until at least igraph 1.0. +- `igraph_are_connected()` is renamed to `igraph_are_adjacent()`; the old name is kept available until at least igraph 1.0. ### Other - - Documentation improvements. +- Documentation improvements. ## [0.10.9] - 2024-02-02 ### Added - - `igraph_is_biconnected()` checks if a graph is biconnected. - - `igraph_realize_bipartite_degree_sequence()` constructs a bipartite graph that has the given bidegree sequence, optionally ensuring that it is connected (PR #2425 by Lára Margrét Hólmfríðardóttir @larah19). +- `igraph_is_biconnected()` checks if a graph is biconnected. +- `igraph_realize_bipartite_degree_sequence()` constructs a bipartite graph that has the given bidegree sequence, optionally ensuring that it is connected (PR #2425 by Lára Margrét Hólmfríðardóttir @larah19). ### Fixed - - More robust error handling in HRG code. - - Fixed infinite loop in `igraph_hrg_sample_many()`. - - `igraph_community_fastgreedy()` no longer crashes when providing a modularity vector only, but not a merges matrix of membership vector. - - The graph property cache was not initialized correctly on systems where the size of `bool` was not 1 byte (#2477). - - Compatibility with libxml2 version 2.12 (#2442). +- More robust error handling in HRG code. +- Fixed infinite loop in `igraph_hrg_sample_many()`. +- `igraph_community_fastgreedy()` no longer crashes when providing a modularity vector only, but not a merges matrix of membership vector. +- The graph property cache was not initialized correctly on systems where the size of `bool` was not 1 byte (#2477). +- Compatibility with libxml2 version 2.12 (#2442). ### Deprecated - - The macro `STR()` is deprecated; use the function `igraph_strvector_get()` instead. +- The macro `STR()` is deprecated; use the function `igraph_strvector_get()` instead. ### Other - - Performance: Reduced memory usage and improved initialization performance for `igraph_strvector_t`. - - Performance: Improved cache use by `igraph_is_bipartite()`. - - The documentation is now also generated in Texinfo format. - - Documentation improvements. +- Performance: Reduced memory usage and improved initialization performance for `igraph_strvector_t`. +- Performance: Improved cache use by `igraph_is_bipartite()`. +- The documentation is now also generated in Texinfo format. +- Documentation improvements. ## [0.10.8] - 2023-11-17 ### Added - - `igraph_joint_degree_matrix()` computes the joint degree matrix, i.e. counts connections between vertices of different degrees (PR #2407 by Lára Margrét Hólmfríðardóttir @larah19). - - `igraph_joint_degree_distribution()` computes the joint distribution of degrees at either end of edges. - - `igraph_joint_type_distribution()` computes the joint distribution of vertex categories at either end of edges, i.e. the mixing matrix. - - `igraph_degree_correlation_vector()` computes the degree correlation function and its various directed generalizations. +- `igraph_joint_degree_matrix()` computes the joint degree matrix, i.e. counts connections between vertices of different degrees (PR #2407 by Lára Margrét Hólmfríðardóttir @larah19). +- `igraph_joint_degree_distribution()` computes the joint distribution of degrees at either end of edges. +- `igraph_joint_type_distribution()` computes the joint distribution of vertex categories at either end of edges, i.e. the mixing matrix. +- `igraph_degree_correlation_vector()` computes the degree correlation function and its various directed generalizations. ### Changed - - The behaviour of the Pajek format reader and writer is now more closely aligned with the Pajek software and the reader is more tolerant of input it cannot interpret. Only those vertex and edge parameters are treated as valid which Pajek itself understands, therefore support for `size` is now dropped, and support for the `font` edge parameter is added. See http://mrvar.fdv.uni-lj.si/pajek/DrawEPS.htm for more information. Invalid/unrecognized parameters are now converted to igraph attributes by the reader, but just as before, they are not output by the writer. - - The Pajek format writer now encodes newline and quotation mark characters in a Pajek-compatible manner (`\n` and `"`, respectively). - - `igraph_avg_nearest_neighbor_degree()` now supports non-simple graphs. +- The behaviour of the Pajek format reader and writer is now more closely aligned with the Pajek software and the reader is more tolerant of input it cannot interpret. Only those vertex and edge parameters are treated as valid which Pajek itself understands, therefore support for `size` is now dropped, and support for the `font` edge parameter is added. See for more information. Invalid/unrecognized parameters are now converted to igraph attributes by the reader, but just as before, they are not output by the writer. +- The Pajek format writer now encodes newline and quotation mark characters in a Pajek-compatible manner (`\n` and `"`, respectively). +- `igraph_avg_nearest_neighbor_degree()` now supports non-simple graphs. ### Fixed - - Resolved "ignoring duplicate libraries" warning when building tests with Xcode 15 on macOS. - - Fixed the handling of duplicate vertex IDs in `igraph_induced_subgraph()`. - - `igraph_vector_which_min()` and `igraph_vector_which_max()` no longer allow zero-length input, which makes them consistent with other similar functions, and was the originally intended behaviour. Passing zero-length input is invalid use and currently triggers an assertion failure. - - `igraph_erdos_renyi_game_gnm()` and `igraph_erdos_renyi_game_gnp()` are now interruptible. - - `igraph_de_bruijn()` and `igraph_kautz()` are now interruptible. - - `igraph_full()`, `igraph_full_citation()`, `igraph_full_multipartite()` and `igraph_turan()` are now interruptible. - - `igraph_avg_nearest_neighbor_degree()` did not compute `knnk` correctly in the weighted case. - - Fixed variadic arguments of invalid types, which could cause incorrect behaviour with `igraph_matrix_print()`, as well as test suite failures, on some platforms. 32-bit x86 was affected when setting `IGRAPH_INTEGER_SIZE` to 64. - - `igraph_subisomorphic_lad()` now returns a single null map when the pattern is the null graph. - - `igraph_community_spinglass()` now checks its parameters more carefully. - - `igraph_similarity_dice_pairs()` and `igraph_similarity_jaccard_pairs()` now validate vertex IDs. - - `igraph_maxflow()` now returns an error code if the source and target vertices are the same. It used to get stuck in an infinite loop in earlier versions when the `flow` argument was non-NULL. +- Resolved "ignoring duplicate libraries" warning when building tests with Xcode 15 on macOS. +- Fixed the handling of duplicate vertex IDs in `igraph_induced_subgraph()`. +- `igraph_vector_which_min()` and `igraph_vector_which_max()` no longer allow zero-length input, which makes them consistent with other similar functions, and was the originally intended behaviour. Passing zero-length input is invalid use and currently triggers an assertion failure. +- `igraph_erdos_renyi_game_gnm()` and `igraph_erdos_renyi_game_gnp()` are now interruptible. +- `igraph_de_bruijn()` and `igraph_kautz()` are now interruptible. +- `igraph_full()`, `igraph_full_citation()`, `igraph_full_multipartite()` and `igraph_turan()` are now interruptible. +- `igraph_avg_nearest_neighbor_degree()` did not compute `knnk` correctly in the weighted case. +- Fixed variadic arguments of invalid types, which could cause incorrect behaviour with `igraph_matrix_print()`, as well as test suite failures, on some platforms. 32-bit x86 was affected when setting `IGRAPH_INTEGER_SIZE` to 64. +- `igraph_subisomorphic_lad()` now returns a single null map when the pattern is the null graph. +- `igraph_community_spinglass()` now checks its parameters more carefully. +- `igraph_similarity_dice_pairs()` and `igraph_similarity_jaccard_pairs()` now validate vertex IDs. +- `igraph_maxflow()` now returns an error code if the source and target vertices are the same. It used to get stuck in an infinite loop in earlier versions when the `flow` argument was non-NULL. ### Other - - Updated vendored mini-gmp to 6.3.0. - - `igraph_connected_components()` makes better use of the cache, improving overall performance. - - Documentation improvements. +- Updated vendored mini-gmp to 6.3.0. +- `igraph_connected_components()` makes better use of the cache, improving overall performance. +- Documentation improvements. ## [0.10.7] - 2023-09-04 ### Added - - `igraph_radius_dijkstra()` computes the graph radius with weighted edges (experimental function). - - `igraph_graph_center_dijkstra()` computes the graph center, i.e. the set of minimum eccentricity vertices, with weighted edges (experimental function). +- `igraph_radius_dijkstra()` computes the graph radius with weighted edges (experimental function). +- `igraph_graph_center_dijkstra()` computes the graph center, i.e. the set of minimum eccentricity vertices, with weighted edges (experimental function). ### Fixed - - `igraph_full_bipartite()` now checks for overflow. - - `igraph_bipartite_game_gnm()` and `igraph_bipartite_game_gnp()` are now more robust to overflow. - - Bipartite graph creation functions now check input arguments. - - `igraph_write_graph_dot()` now quotes real numbers written in exponential notation as necessary. - - Independent vertex set finding functions could trigger the fatal error "Finally stack too large" when called on large graphs. +- `igraph_full_bipartite()` now checks for overflow. +- `igraph_bipartite_game_gnm()` and `igraph_bipartite_game_gnp()` are now more robust to overflow. +- Bipartite graph creation functions now check input arguments. +- `igraph_write_graph_dot()` now quotes real numbers written in exponential notation as necessary. +- Independent vertex set finding functions could trigger the fatal error "Finally stack too large" when called on large graphs. ### Deprecated - - `igraph_bipartite_game()` is now deprecated; use `igraph_bipartite_game_gnm()` and `igraph_bipartite_game_gnp()` instead. +- `igraph_bipartite_game()` is now deprecated; use `igraph_bipartite_game_gnm()` and `igraph_bipartite_game_gnp()` instead. ### Other - - Documentation improvements. +- Documentation improvements. ## [0.10.6] - 2023-07-13 ### Fixed - - Compatibility with libxml2 2.11. - - Fixed some converge failures in `igraph_community_voronoi()`. - - `IGRAPH_CALLOC()` and `IGRAPH_REALLOC()` now check for overflow. - - CMake packages created with the `install` target of the CMake build system are now relocatable, i.e. the generated `igraph-targets.cmake` file does not contain absolute paths any more. +- Compatibility with libxml2 2.11. +- Fixed some converge failures in `igraph_community_voronoi()`. +- `IGRAPH_CALLOC()` and `IGRAPH_REALLOC()` now check for overflow. +- CMake packages created with the `install` target of the CMake build system are now relocatable, i.e. the generated `igraph-targets.cmake` file does not contain absolute paths any more. ## [0.10.5] - 2023-06-29 ### Added - - `igraph_graph_power()` computes the kth power of a graph (experimental function). - - `igraph_community_voronoi()` for detecting communities using Voronoi partitioning (experimental function). +- `igraph_graph_power()` computes the kth power of a graph (experimental function). +- `igraph_community_voronoi()` for detecting communities using Voronoi partitioning (experimental function). ### Changed - - `igraph_community_walktrap()` no longer requires `modularity` and `merges` to be non-NULL when `membership` is non-NULL. - - `igraph_isomorphic()` now supports multigraphs. - - Shortest path related functions now consistently ignore edges with positive infinite weights. +- `igraph_community_walktrap()` no longer requires `modularity` and `merges` to be non-NULL when `membership` is non-NULL. +- `igraph_isomorphic()` now supports multigraphs. +- Shortest path related functions now consistently ignore edges with positive infinite weights. ### Fixed - - `igraph_hub_and_authority_scores()`, `igraph_hub_score()` and `igraph_authority_score()` considered self-loops only once on the diagonal of the adjacency matrix of undirected graphs, thus the result was not identical to that obtained by `igraph_eigenvector_centrality()` on loopy undirected graphs. This is now corrected. - - `igraph_community_infomap()` now checks edge and vertex weights for validity. - - `igraph_minimum_spanning_tree()` and `igraph_minimum_spanning_tree_prim()` now check that edge weights are not NaN. - - Fixed an initialization error in the string attribute combiner of the C attribute handler. - - Fixed an issue with the weighted clique number calculation when all the weights were the same. - - HRG functions now require a graph with at least 3 vertices; previous versions crashed with smaller graphs. - - `igraph_arpack_rssolve()` and `igraph_arpack_rnsolve()`, i.e. the ARPACK interface in igraph, are now interruptible. As a result, several other functions that rely on ARPACK (eigenvector centrality, hub and authority scores, etc.) also became interruptible. - - `igraph_get_shortest_paths_dijkstra()`, `igraph_get_all_shortest_paths_dijkstra()` and `igraph_get_shortest_paths_bellman_ford()` now validate the `from` vertex. - - Fixed bugs in `igraph_local_scan_1_ecount()` for weighted undirected graphs which would miscount loops and multi-edges. +- `igraph_hub_and_authority_scores()`, `igraph_hub_score()` and `igraph_authority_score()` considered self-loops only once on the diagonal of the adjacency matrix of undirected graphs, thus the result was not identical to that obtained by `igraph_eigenvector_centrality()` on loopy undirected graphs. This is now corrected. +- `igraph_community_infomap()` now checks edge and vertex weights for validity. +- `igraph_minimum_spanning_tree()` and `igraph_minimum_spanning_tree_prim()` now check that edge weights are not NaN. +- Fixed an initialization error in the string attribute combiner of the C attribute handler. +- Fixed an issue with the weighted clique number calculation when all the weights were the same. +- HRG functions now require a graph with at least 3 vertices; previous versions crashed with smaller graphs. +- `igraph_arpack_rssolve()` and `igraph_arpack_rnsolve()`, i.e. the ARPACK interface in igraph, are now interruptible. As a result, several other functions that rely on ARPACK (eigenvector centrality, hub and authority scores, etc.) also became interruptible. +- `igraph_get_shortest_paths_dijkstra()`, `igraph_get_all_shortest_paths_dijkstra()` and `igraph_get_shortest_paths_bellman_ford()` now validate the `from` vertex. +- Fixed bugs in `igraph_local_scan_1_ecount()` for weighted undirected graphs which would miscount loops and multi-edges. ### Deprecated @@ -532,60 +658,60 @@ ### Other - - Improved performance for `igraph_vertex_connectivity()`. - - `igraph_simplify()` makes use of the cache, and avoids simplification when the graph is already known to be simple. - - Documentation improvements. +- Improved performance for `igraph_vertex_connectivity()`. +- `igraph_simplify()` makes use of the cache, and avoids simplification when the graph is already known to be simple. +- Documentation improvements. ## [0.10.4] - 2023-01-26 ### Added - - `igraph_get_shortest_path_astar()` finds a shortest path with the A* algorithm. - - `igraph_vertex_coloring_greedy()` now supports the DSatur heuristics through `IGRAPH_COLORING_GREEDY_DSATUR` (#2284, thanks to @professorcode1). +- `igraph_get_shortest_path_astar()` finds a shortest path with the A* algorithm. +- `igraph_vertex_coloring_greedy()` now supports the DSatur heuristics through `IGRAPH_COLORING_GREEDY_DSATUR` (#2284, thanks to @professorcode1). ### Changed - - The `test` build target now only _runs_ the unit tests, but it does not _build_ them. In order to both build and run tests, use the `check` target, which continues to behave as before (PR #2291). - - The experimental function `igraph_distances_floyd_warshall()` now has `from` and `to` parameters for choosing source and target vertices. - - The experimental function `igraph_distances_floyd_warshall()` now has an additional `method` parameter to select a specific algorithm. A faster "Tree" variant of the Floyd-Warshall algorithm is now available (#2267, thanks to @rfulekjames). +- The `test` build target now only _runs_ the unit tests, but it does not _build_ them. In order to both build and run tests, use the `check` target, which continues to behave as before (PR #2291). +- The experimental function `igraph_distances_floyd_warshall()` now has `from` and `to` parameters for choosing source and target vertices. +- The experimental function `igraph_distances_floyd_warshall()` now has an additional `method` parameter to select a specific algorithm. A faster "Tree" variant of the Floyd-Warshall algorithm is now available (#2267, thanks to @rfulekjames). ### Fixed - - The Bellman-Ford shortest path finder is now interruptible. - - The Floyd-Warshall shortest path finder is now interruptible. - - Running CTest no longer builds the tests automatically, as this interfered with VSCode, which would invoke the `ctest` executable after configuring a project in order to determine test executables. Use the `build_tests` target to build the tests first, or use the `check` target to both _build_ and _run_ all unit tests (PR #2291). +- The Bellman-Ford shortest path finder is now interruptible. +- The Floyd-Warshall shortest path finder is now interruptible. +- Running CTest no longer builds the tests automatically, as this interfered with VSCode, which would invoke the `ctest` executable after configuring a project in order to determine test executables. Use the `build_tests` target to build the tests first, or use the `check` target to both _build_ and _run_ all unit tests (PR #2291). ### Other - - Improved the performance and memory usage of `igraph_widest_path_widths_floyd_warshall()`. - - Documentation improvements. +- Improved the performance and memory usage of `igraph_widest_path_widths_floyd_warshall()`. +- Documentation improvements. ## [0.10.3] - 2022-12-30 ### Added - - `igraph_matrix_init_array()` to initialize an igraph matrix by copying an existing C array in column-major or row-major order. - - `igraph_layout_umap_compute_weights()` computes weights for the UMAP layout algorithm from distances. This used to be part of `igraph_layout_umap()`, but it is now in a separate function to allow the user to experiment with different weighting schemes. - - `igraph_triangular_lattice()` to generate triangular lattices of various kinds (#2235, thanks to @rfulekjames). - - `igraph_hexagonal_lattice()` to generate hexagonal lattices of various kinds (#2262, thanks to @rfulekjames). - - `igraph_tree_from_parent_vector()` to create a tree or a forest from a parent vector (i.e. a vector that encodes the parent vertex of each vertex). - - `igraph_induced_subgraph_edges()` produces the IDs of edges contained within a subgraph induced by the given vertices. +- `igraph_matrix_init_array()` to initialize an igraph matrix by copying an existing C array in column-major or row-major order. +- `igraph_layout_umap_compute_weights()` computes weights for the UMAP layout algorithm from distances. This used to be part of `igraph_layout_umap()`, but it is now in a separate function to allow the user to experiment with different weighting schemes. +- `igraph_triangular_lattice()` to generate triangular lattices of various kinds (#2235, thanks to @rfulekjames). +- `igraph_hexagonal_lattice()` to generate hexagonal lattices of various kinds (#2262, thanks to @rfulekjames). +- `igraph_tree_from_parent_vector()` to create a tree or a forest from a parent vector (i.e. a vector that encodes the parent vertex of each vertex). +- `igraph_induced_subgraph_edges()` produces the IDs of edges contained within a subgraph induced by the given vertices. ### Changed - - The signature of the experimental `igraph_layout_umap()` function changed; the last argument is now a Boolean that specifies whether distances should already be treated as weights, and the sampling probability argument was removed. +- The signature of the experimental `igraph_layout_umap()` function changed; the last argument is now a Boolean that specifies whether distances should already be treated as weights, and the sampling probability argument was removed. ### Fixed - - `igraph_transitivity_barrat()`, `igraph_community_fluid_communities()`, `igraph_sir()`, `igraph_trussness()` and graphlet functions did not correctly detect when a directed input graph had effective multi-edges due to ignoring edge directions. Such graphs are now rejected by these functions. - - Fixed a bug in `igraph_2dgrid_move()` that sometimes crashed the Large Graph Layout function when a grid cell became empty. - - `igraph_pagerank()` and `igraph_personalized_pagerank()` would fail to converge when the ARPACK implementation was used and a vertex had more than one outgoing edge but all these edges had zero weights. - - `igraph_pagerank()` and `igraph_personalized_pagerank()` no longer allow negative weights. Previously, edges with negative weights were silently ignored when using the PRPACK implementation. The ARPACK implementation would issue a warning saying that they are ignored, but in fact it computed an incorrect result. - - `igraph_all_st_cuts()` and `igraph_all_st_mincuts()` no longer trigger the "Finally stack too large" fatal error when called on certain large graphs. This was a regression in igraph 0.10. - - `igraph_community_label_propagation()` no longer rounds weights to integers. This was a regression in igraph 0.10. - - `igraph_read_graph_graphdb()` does more thorough checks on the input file. - - `igraph_calloc()` did not zero-initialize the allocated memory. This is now corrected. Note that the macro `IGRAPH_CALLOC()` was _not_ affected. - - Fixed new warnings issued by the Xcode 14.1 toolchain. +- `igraph_transitivity_barrat()`, `igraph_community_fluid_communities()`, `igraph_sir()`, `igraph_trussness()` and graphlet functions did not correctly detect when a directed input graph had effective multi-edges due to ignoring edge directions. Such graphs are now rejected by these functions. +- Fixed a bug in `igraph_2dgrid_move()` that sometimes crashed the Large Graph Layout function when a grid cell became empty. +- `igraph_pagerank()` and `igraph_personalized_pagerank()` would fail to converge when the ARPACK implementation was used and a vertex had more than one outgoing edge but all these edges had zero weights. +- `igraph_pagerank()` and `igraph_personalized_pagerank()` no longer allow negative weights. Previously, edges with negative weights were silently ignored when using the PRPACK implementation. The ARPACK implementation would issue a warning saying that they are ignored, but in fact it computed an incorrect result. +- `igraph_all_st_cuts()` and `igraph_all_st_mincuts()` no longer trigger the "Finally stack too large" fatal error when called on certain large graphs. This was a regression in igraph 0.10. +- `igraph_community_label_propagation()` no longer rounds weights to integers. This was a regression in igraph 0.10. +- `igraph_read_graph_graphdb()` does more thorough checks on the input file. +- `igraph_calloc()` did not zero-initialize the allocated memory. This is now corrected. Note that the macro `IGRAPH_CALLOC()` was _not_ affected. +- Fixed new warnings issued by the Xcode 14.1 toolchain. ### Deprecated @@ -593,78 +719,78 @@ ### Other - - Significantly improved performance for `igraph_matrix_transpose()`. - - Documentation improvements. +- Significantly improved performance for `igraph_matrix_transpose()`. +- Documentation improvements. ## [0.10.2] - 2022-10-14 ### Added - - `igraph_distances_cutoff()` and `igraph_distances_dijkstra_cutoff()` calculate shortest paths with an upper limit on the path length (experimental functions). - - `igraph_distances_floyd_warshall()` for computing all-pairs shortest path lengths in dense graphs (experimental function). - - `igraph_ecc()` computes the edge clustering coefficient of some edges (experimental function). - - `igraph_voronoi()` computes a Voronoi partitioning of vertices (experimental function). - - `igraph_count_multiple_1()` determines the multiplicity of a single edge in the graph. - - `igraph_dqueue_get()` accesses an element in a queue by index. - - `igraph_degree_1()` efficiently retrieves the degee of a single vertex. - - `igraph_lazy_adjlist_has()` and `igraph_lazy_inclist_has()` to check if adjacent vertices / incident edges have already been computed and stored for a given vertex in a lazy adjlist / inclist. +- `igraph_distances_cutoff()` and `igraph_distances_dijkstra_cutoff()` calculate shortest paths with an upper limit on the path length (experimental functions). +- `igraph_distances_floyd_warshall()` for computing all-pairs shortest path lengths in dense graphs (experimental function). +- `igraph_ecc()` computes the edge clustering coefficient of some edges (experimental function). +- `igraph_voronoi()` computes a Voronoi partitioning of vertices (experimental function). +- `igraph_count_multiple_1()` determines the multiplicity of a single edge in the graph. +- `igraph_dqueue_get()` accesses an element in a queue by index. +- `igraph_degree_1()` efficiently retrieves the degee of a single vertex. +- `igraph_lazy_adjlist_has()` and `igraph_lazy_inclist_has()` to check if adjacent vertices / incident edges have already been computed and stored for a given vertex in a lazy adjlist / inclist. ### Changed - - `igraph_edge()` now verifies that the input edge ID is valid. - - `igraph_community_leading_eigenvector()`, `igraph_adjacency_spectral_embedding()`, `igraph_laplacian_spectral_embedding()`, `igraph_arpack_rssolve()` and `igraph_arpack_rnsolve()` now generate a random starting vector using igraph's own RNG if needed instead of relying on LAPACK or ARPACK to do so. This makes sure that the results obtained from these functions remain the same if igraph's RNG is seeded with the same value. - - `igraph_community_leading_eigenvector()` does not stop the splitting process any more when there are multiple equally likely splits (indicated by the multiplicity of the leading eigenvector being larger than 1). The algorithm picks an arbitrary split instead and proceeds normally. +- `igraph_edge()` now verifies that the input edge ID is valid. +- `igraph_community_leading_eigenvector()`, `igraph_adjacency_spectral_embedding()`, `igraph_laplacian_spectral_embedding()`, `igraph_arpack_rssolve()` and `igraph_arpack_rnsolve()` now generate a random starting vector using igraph's own RNG if needed instead of relying on LAPACK or ARPACK to do so. This makes sure that the results obtained from these functions remain the same if igraph's RNG is seeded with the same value. +- `igraph_community_leading_eigenvector()` does not stop the splitting process any more when there are multiple equally likely splits (indicated by the multiplicity of the leading eigenvector being larger than 1). The algorithm picks an arbitrary split instead and proceeds normally. ### Fixed - - Fixed a bug in `igraph_get_k_shortest_paths()` that sometimes yielded incorrect results on undirected graphs when the `mode` argument was set to `IGRAPH_OUT` or `IGRAPH_IN`. - - `igraph_trussness()` is now interruptible. - - `igraph_spanner()` is now interruptible. - - `igraph_layout_umap()` and `igraph_layout_umap3d()` are now interruptible. - - In some rare cases, roundoff errors would cause `igraph_distance_johnson()` to fail on graphs with negative weights. - - `igraph_eulerian_cycle()` and `igraph_eulerian_path()` now returns a more specific error code (`IGRAPH_ENOSOL`) when the graph contains no Eulerian cycle or path. - - `igraph_heap_init_array()` did not copy the array data correctly for non-real specializations. - - `igraph_layout_umap_3d()` now actually uses three dimensions. - - `igraph_layout_umap()` and `igraph_layout_umap_3d()` are now interruptible. - - `igraph_vit_create()` and `igraph_eit_create()` no longer fails when trying to create an iterator for the null graph or edgeless graph from an empty range-based vertex or edge selector. - - `igraph_write_graph_leda()` did not correctly print attribute names in some warning messages. - - Addressed new warnings introduced by Clang 15. - - In the generated pkg-config file, libxml2 is now placed in the `Requires.private` section instead of the `Libs.private` one. +- Fixed a bug in `igraph_get_k_shortest_paths()` that sometimes yielded incorrect results on undirected graphs when the `mode` argument was set to `IGRAPH_OUT` or `IGRAPH_IN`. +- `igraph_trussness()` is now interruptible. +- `igraph_spanner()` is now interruptible. +- `igraph_layout_umap()` and `igraph_layout_umap3d()` are now interruptible. +- In some rare cases, roundoff errors would cause `igraph_distance_johnson()` to fail on graphs with negative weights. +- `igraph_eulerian_cycle()` and `igraph_eulerian_path()` now returns a more specific error code (`IGRAPH_ENOSOL`) when the graph contains no Eulerian cycle or path. +- `igraph_heap_init_array()` did not copy the array data correctly for non-real specializations. +- `igraph_layout_umap_3d()` now actually uses three dimensions. +- `igraph_layout_umap()` and `igraph_layout_umap_3d()` are now interruptible. +- `igraph_vit_create()` and `igraph_eit_create()` no longer fails when trying to create an iterator for the null graph or edgeless graph from an empty range-based vertex or edge selector. +- `igraph_write_graph_leda()` did not correctly print attribute names in some warning messages. +- Addressed new warnings introduced by Clang 15. +- In the generated pkg-config file, libxml2 is now placed in the `Requires.private` section instead of the `Libs.private` one. ### Removed - - Removed unused and undocumented `igraph_bfgs()` function. - - Removed the undocumented function `igraph_complex_mod()`. Use `igraph_complex_abs()` instead, as it has identical functionality. +- Removed unused and undocumented `igraph_bfgs()` function. +- Removed the undocumented function `igraph_complex_mod()`. Use `igraph_complex_abs()` instead, as it has identical functionality. ### Deprecated - - The `IGRAPH_EDRL` error code was deprecated; the DrL algorithm now returns `IGRAPH_FAILURE` when it used to return `IGRAPH_EDRL` (not likely to happen in practice). - - The undocumented function `igraph_dqueue_e()` is now deprecated and replaced by `igraph_dqueue_get()`. - - `igraph_finite()`, `igraph_is_nan()`, `igraph_is_inf()`, `igraph_is_posinf()` and `igraph_is_neginf()` are now deprecated. They were relics from a time when no standard alternatives existed. Use the C99 standard `isfinite()`, `isnan()` and `isinf()` instead. +- The `IGRAPH_EDRL` error code was deprecated; the DrL algorithm now returns `IGRAPH_FAILURE` when it used to return `IGRAPH_EDRL` (not likely to happen in practice). +- The undocumented function `igraph_dqueue_e()` is now deprecated and replaced by `igraph_dqueue_get()`. +- `igraph_finite()`, `igraph_is_nan()`, `igraph_is_inf()`, `igraph_is_posinf()` and `igraph_is_neginf()` are now deprecated. They were relics from a time when no standard alternatives existed. Use the C99 standard `isfinite()`, `isnan()` and `isinf()` instead. ### Other - - Documentation improvements. +- Documentation improvements. ## [0.10.1] - 2022-09-08 ### Fixed - - Corrected a regression (compared to igraph 0.9) in weighted clique search functions. - - `igraph_girth()` no longer fails when the graph has no cycles and the `girth` parameter is set to `NULL`. - - `igraph_write_graph_gml()` did not respect entity encoding options when writing the `Creator` line. - - Fixed potential memory leak on out-of-memory condition in `igraph_asymmetric_preference_game()`, `igraph_vs_copy()` and `igraph_es_copy()`. - - Fixed an assertion failure in `igraph_barabasi_game()` and `igraph_barabasi_aging_game()` when passing in negative degree exponents. - - Fixed a compilation failure with some old Clang versions. +- Corrected a regression (compared to igraph 0.9) in weighted clique search functions. +- `igraph_girth()` no longer fails when the graph has no cycles and the `girth` parameter is set to `NULL`. +- `igraph_write_graph_gml()` did not respect entity encoding options when writing the `Creator` line. +- Fixed potential memory leak on out-of-memory condition in `igraph_asymmetric_preference_game()`, `igraph_vs_copy()` and `igraph_es_copy()`. +- Fixed an assertion failure in `igraph_barabasi_game()` and `igraph_barabasi_aging_game()` when passing in negative degree exponents. +- Fixed a compilation failure with some old Clang versions. ### Changed - - `igraph_write_graph_leda()` can now write boolean attributes. +- `igraph_write_graph_leda()` can now write boolean attributes. ### Other - - Support for ARM64 on Windows. - - Documentation improvements. +- Support for ARM64 on Windows. +- Documentation improvements. ## [0.10.0] - 2022-09-05 @@ -674,489 +800,485 @@ This release focuses on infrastructural improvements, stability, and making the Some of the highlights are: - - A consistent use of `igraph_integer_t` for all indices and most integer quantities, both in the API and internally. This type is 64-bit by default on all 64-bit systems, bringing support for very large graphs with more than 2 billion vertices. Previously, vertex and edge indices were often represented as `igraph_real_t`. The move to an `igraph_integer_t` also implies a change from `igraph_vector_t` to `igraph_vector_int_t` in many functions. - - The random number generation framework has been overhauled. Sampling from the full range of `igraph_integer_t` is now possible. Similarly, the sampling of random reals has been improved to utilize almost the full range of the mantissa of an `igraph_real_t`. - - There is a new fully memory-managed container type for lists of vectors (`igraph_vector_list_t`), replacing most previous uses of the non-managed `igraph_vector_ptr_t`. Functions that previously used `igraph_vector_ptr_t` to return results and relied on the user to manage memory appropriately are now using `igraph_vector_list_t`, `igraph_graph_list_t` or similar and manage memory on their own. - - Some simple graph properties, such as whether a graph contains self-loops or multi-edges, or whether it is connected, are now cached in the graph data structure. Querying these properties for a second time will take constant computational time. The `igraph_invalidate_cache()` function is provided for debugging purposes. It will invaidate all cache entries. - - File format readers are much more robust and more tolerant of invalid input. - - igraph is much more resilient to overflow errors. - - Many improvements to robustness and reliability, made possible by internal refactorings. +- A consistent use of `igraph_integer_t` for all indices and most integer quantities, both in the API and internally. This type is 64-bit by default on all 64-bit systems, bringing support for very large graphs with more than 2 billion vertices. Previously, vertex and edge indices were often represented as `igraph_real_t`. The move to an `igraph_integer_t` also implies a change from `igraph_vector_t` to `igraph_vector_int_t` in many functions. +- The random number generation framework has been overhauled. Sampling from the full range of `igraph_integer_t` is now possible. Similarly, the sampling of random reals has been improved to utilize almost the full range of the mantissa of an `igraph_real_t`. +- There is a new fully memory-managed container type for lists of vectors (`igraph_vector_list_t`), replacing most previous uses of the non-managed `igraph_vector_ptr_t`. Functions that previously used `igraph_vector_ptr_t` to return results and relied on the user to manage memory appropriately are now using `igraph_vector_list_t`, `igraph_graph_list_t` or similar and manage memory on their own. +- Some simple graph properties, such as whether a graph contains self-loops or multi-edges, or whether it is connected, are now cached in the graph data structure. Querying these properties for a second time will take constant computational time. The `igraph_invalidate_cache()` function is provided for debugging purposes. It will invaidate all cache entries. +- File format readers are much more robust and more tolerant of invalid input. +- igraph is much more resilient to overflow errors. +- Many improvements to robustness and reliability, made possible by internal refactorings. ### Breaking changes - - igraph now requires CMake 3.18 or later. - - In order to facilitate the usage of graphs with more than 2 billion vertices and edges, we have made the size of the `igraph_integer_t` data type to be 32 bits on 32-bit platforms and 64 bits on 64-bit platforms by default. You also have the option to compile a 32-bit igraph variant on a 64-bit platform by changing the `IGRAPH_INTEGER_SIZE` build variable in CMake to 32. - - `igraph_bool_t` is now a C99 `bool` and not an `int`. Similarly, `igraph_vector_bool_t` now consumes `sizeof(bool)` bytes per entry only, not `sizeof(int)`. The standard constants `true` and `false` may be used for Boolean values for readability. - - The random number generator interface, `igraph_rng_type_t`, has been overhauled. Check the declaration of the type for details. - - The default random number generator has been changed from Mersenne Twister to PCG32. - - Functions related to spectral coarse graining (i.e. all functions starting with `igraph_scg_...`) were separated into a project of its own. If you wish to keep on using these functions, please refer to the repository hosting the spectral coarse graining code at https://github.com/igraph/igraph-scg . The spectral coarse graining code was updated to support igraph 0.10. - - Since `igraph_integer_t` aims to be the largest integer size that is feasible on a particular platform, there is no need for generic data types based on `long int` anymore. The `long` variants of generic data types (e.g., `igraph_vector_long_t`) are therefore removed; you should use the corresponding `int` variant instead, whose elements are of type `igraph_integer_t`. - - Generic data types based on `float` were removed as they were not used anywhere in the library. - - Several igraph functions that used to take a `long int` or return a `long int` now takes or returns an `igraph_integer_t` instead to make the APIs more consistent. Similarly, igraph functions that used `igraph_vector_t` for arguments that take or return _integral_ vectors (e.g., vertex or edge indices) now take `igraph_vector_int_t` instead. Graph-related functions where the API was changed due to this reason are listed below, one by one. - - Similarly, igraph functions that used to accept the `long` variant of a generic igraph data type (e.g., `igraph_vector_long_t`) now take the `int` variant of the same data type. - - The type `igraph_stack_ptr_t` and its associated functions were removed. Use `igraph_vector_ptr_t` and associated functions instead. - - Error handlers should no longer perform a `longjmp()`. Doing so will introduce memory leaks, as resource cleanup is now done in multiple stages, through multiple calls to the error handler. Thus, the error handler should either abort execution immediately (as the default handler does), or report the error, call `IGRAPH_FINALLY_FREE()`, and return normally. - - Most callback functions now return an error code. In previous versions they returned a boolean value indicating whether to terminate the search. A request to stop the search is now indicated with the special return code `IGRAPH_STOP`. - - `igraph_add_edges()` now uses an `igraph_vector_int_t` for its `edges` parameter. - - `igraph_adjacency()` no longer accepts a negative number of edges in its adjacency matrix. When negative entries are found, an error is generated. - - `igraph_adjacency()` gained an additional `loops` argument that lets you specify whether the diagonal entries should be ignored or should be interpreted as raw edge counts or _twice_ the number of edges (which is common in linear algebra contexts). - - `igraph_all_minimal_st_separators()` now returns the separators in an `igraph_vector_int_list_t` containing `igraph_vector_int_t` vectors. - - `igraph_all_st_cuts()` and `igraph_all_st_mincuts()` now return the cuts in an `igraph_vector_int_list_t` containing `igraph_vector_int_t` vectors. - - `igraph_arpack_unpack_complex()` now uses `igraph_integer_t` for its `nev` argument instead of `long int`. - - `igraph_articulation_points()` now uses an `igraph_vector_int_t` to return the list of articulation points, not an `igraph_vector_t`. - - `igraph_assortativity_nominal()` now accepts vertex types in an `igraph_vector_int_t` instead of an `igraph_vector_t`. - - `igraph_asymmetric_preferennce_game()` now uses an `igraph_vector_int_t` to return the types of the nodes in the generated graph. - - `igraph_atlas()` now uses `igraph_integer_t` for its `number` argument. - - `igraph_automorphism_group()` now returns the generators in an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. - - `igraph_barabasi_game()`, `igraph_barabasi_aging_game()`, `igraph_recent_degree_game()` and `igraph_recent_degree_aging_game()` now use an `igraph_vector_int_t` for the out-degree sequence of the nodes being generated instead of an `igraph_vector_t`. - - `igraph_bfs()` now takes an `igraph_vector_int_t` for its `roots`, `restricted`, `order`, `father`, `pred`, `succ` and `dist` arguments instead of an `igraph_vector_t`. - - `igraph_bfs_simple()` now takes `igraph_vector_int_t` for its `vids`, `layers` and `parents` arguments instead of an `igraph_vector_t`. - - `igraph_bfs_simple()` now returns -1 in `parents` for the root node of the traversal, and -2 for unreachable vertices. This is now consistent with other functions that return a parent vector. - - `igraph_biconnected_components()` now uses an `igraph_vector_int_t` to return the list of articulation points, not an `igraph_vector_t`. Also, the container used for the edges and vertices of the components is now an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. - - `igraph_bipartite_projection()` now uses `igraph_vector_int_t` to return `multiplicity1` and `multiplicity2`, not `igraph_vector_t`. - - `igraph_bridges()` now uses an `igraph_vector_int_t` to return the list of bridges, not an `igraph_vector_t`. - - `igraph_callaway_traits_game()` returns the node types in an `igraph_vector_int_t` instead of an `igraph_vector_t`. - - `igraph_canonical_permutation()` now uses an `igraph_vector_int_t` for its labeling parameter. - - `igraph_cattribute_list()` now uses `igraph_vector_int_t` to return `gtypes`, `vtypes` and `etypes`. - - `igraph_cited_type_game()` now uses an `igraph_vector_int_t` for its types parameter. - - `igraph_citing_cited_type_game()` now uses an `igraph_vector_int_t` for its +- igraph now requires CMake 3.18 or later. +- In order to facilitate the usage of graphs with more than 2 billion vertices and edges, we have made the size of the `igraph_integer_t` data type to be 32 bits on 32-bit platforms and 64 bits on 64-bit platforms by default. You also have the option to compile a 32-bit igraph variant on a 64-bit platform by changing the `IGRAPH_INTEGER_SIZE` build variable in CMake to 32. +- `igraph_bool_t` is now a C99 `bool` and not an `int`. Similarly, `igraph_vector_bool_t` now consumes `sizeof(bool)` bytes per entry only, not `sizeof(int)`. The standard constants `true` and `false` may be used for Boolean values for readability. +- The random number generator interface, `igraph_rng_type_t`, has been overhauled. Check the declaration of the type for details. +- The default random number generator has been changed from Mersenne Twister to PCG32. +- Functions related to spectral coarse graining (i.e. all functions starting with `igraph_scg_...`) were separated into a project of its own. If you wish to keep on using these functions, please refer to the repository hosting the spectral coarse graining code at . The spectral coarse graining code was updated to support igraph 0.10. +- Since `igraph_integer_t` aims to be the largest integer size that is feasible on a particular platform, there is no need for generic data types based on `long int` anymore. The `long` variants of generic data types (e.g., `igraph_vector_long_t`) are therefore removed; you should use the corresponding `int` variant instead, whose elements are of type `igraph_integer_t`. +- Generic data types based on `float` were removed as they were not used anywhere in the library. +- Several igraph functions that used to take a `long int` or return a `long int` now takes or returns an `igraph_integer_t` instead to make the APIs more consistent. Similarly, igraph functions that used `igraph_vector_t` for arguments that take or return _integral_ vectors (e.g., vertex or edge indices) now take `igraph_vector_int_t` instead. Graph-related functions where the API was changed due to this reason are listed below, one by one. +- Similarly, igraph functions that used to accept the `long` variant of a generic igraph data type (e.g., `igraph_vector_long_t`) now take the `int` variant of the same data type. +- The type `igraph_stack_ptr_t` and its associated functions were removed. Use `igraph_vector_ptr_t` and associated functions instead. +- Error handlers should no longer perform a `longjmp()`. Doing so will introduce memory leaks, as resource cleanup is now done in multiple stages, through multiple calls to the error handler. Thus, the error handler should either abort execution immediately (as the default handler does), or report the error, call `IGRAPH_FINALLY_FREE()`, and return normally. +- Most callback functions now return an error code. In previous versions they returned a boolean value indicating whether to terminate the search. A request to stop the search is now indicated with the special return code `IGRAPH_STOP`. +- `igraph_add_edges()` now uses an `igraph_vector_int_t` for its `edges` parameter. +- `igraph_adjacency()` no longer accepts a negative number of edges in its adjacency matrix. When negative entries are found, an error is generated. +- `igraph_adjacency()` gained an additional `loops` argument that lets you specify whether the diagonal entries should be ignored or should be interpreted as raw edge counts or _twice_ the number of edges (which is common in linear algebra contexts). +- `igraph_all_minimal_st_separators()` now returns the separators in an `igraph_vector_int_list_t` containing `igraph_vector_int_t` vectors. +- `igraph_all_st_cuts()` and `igraph_all_st_mincuts()` now return the cuts in an `igraph_vector_int_list_t` containing `igraph_vector_int_t` vectors. +- `igraph_arpack_unpack_complex()` now uses `igraph_integer_t` for its `nev` argument instead of `long int`. +- `igraph_articulation_points()` now uses an `igraph_vector_int_t` to return the list of articulation points, not an `igraph_vector_t`. +- `igraph_assortativity_nominal()` now accepts vertex types in an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- `igraph_asymmetric_preferennce_game()` now uses an `igraph_vector_int_t` to return the types of the nodes in the generated graph. +- `igraph_atlas()` now uses `igraph_integer_t` for its `number` argument. +- `igraph_automorphism_group()` now returns the generators in an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. +- `igraph_barabasi_game()`, `igraph_barabasi_aging_game()`, `igraph_recent_degree_game()` and `igraph_recent_degree_aging_game()` now use an `igraph_vector_int_t` for the out-degree sequence of the nodes being generated instead of an `igraph_vector_t`. +- `igraph_bfs()` now takes an `igraph_vector_int_t` for its `roots`, `restricted`, `order`, `father`, `pred`, `succ` and `dist` arguments instead of an `igraph_vector_t`. +- `igraph_bfs_simple()` now takes `igraph_vector_int_t` for its `vids`, `layers` and `parents` arguments instead of an `igraph_vector_t`. +- `igraph_bfs_simple()` now returns -1 in `parents` for the root node of the traversal, and -2 for unreachable vertices. This is now consistent with other functions that return a parent vector. +- `igraph_biconnected_components()` now uses an `igraph_vector_int_t` to return the list of articulation points, not an `igraph_vector_t`. Also, the container used for the edges and vertices of the components is now an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. +- `igraph_bipartite_projection()` now uses `igraph_vector_int_t` to return `multiplicity1` and `multiplicity2`, not `igraph_vector_t`. +- `igraph_bridges()` now uses an `igraph_vector_int_t` to return the list of bridges, not an `igraph_vector_t`. +- `igraph_callaway_traits_game()` returns the node types in an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- `igraph_canonical_permutation()` now uses an `igraph_vector_int_t` for its labeling parameter. +- `igraph_cattribute_list()` now uses `igraph_vector_int_t` to return `gtypes`, `vtypes` and `etypes`. +- `igraph_cited_type_game()` now uses an `igraph_vector_int_t` for its types parameter. +- `igraph_citing_cited_type_game()` now uses an `igraph_vector_int_t` for its types parameter. - - `igraph_clique_handler_t` now uses an `igraph_vector_int_t` for its `clique` parameter, and must return an `igraph_error_t`. Use `IGRAPH_STOP` as the return code to terminate the search prematurely. The vector that the handler receives is owned by the clique search routine. If you want to hold on to the vector for a longer period of time, you need to make a copy of it in the handler. Cliques passed to the callback are marked as `const` as a reminder to this change. - - The `res` parameter of `igraph_cliques()` is now an `igraph_vector_int_list_t`. - - Callbacks used by `igraph_cliques_callback()` need to be updated to account for the fact that the callback does not own the clique passed to it any more; the callback needs to make a copy if it wants to hold on to the clique for a longer period of time. If the callback does not need to store the clique, it does not need to do anything any more, and it must not destroy or free the clique. - - `igraph_closeness()` and `igraph_closeness_cutoff()` now use an `igraph_vector_int_t` to return `reachable_count`, not an `igraph_vector_t`. - - `igraph_cohesive_blocks()` now uses an `igraph_vector_int_t` to return the mapping from block indices to parent block indices, and the `cohesion`; also, it uses an `igraph_vector_int_list_t` to return the blocks themselves instead of a pointer vector of `igraph_vector_t`. - - The `igraph_community_eb_get_merges()` bridges parameter now starts the indices into the edge removal vector at 0, not 1. - - The `igraph_community_eb_get_merges()` now reports an error when not all edges in the graph are removed, instead of a nonsensical result. - - `igraph_community_edge_betweenness()` now uses an `igraph_vector_int_t` to return the edge IDs in the order of their removal as well as the list of edge IDs whose removal broke a single component into two. - - `igraph_community_fluid_communities()` does not provide the modularity in a separate output argument any more; use `igraph_modularity()` to retrieve the modularity if you need it. - - `igraph_community_infomap()` now uses `igraph_integer_t` for its `nb_trials` argument. - - `igraph_community_label_propagation()` now uses an `igraph_vector_int_t` for its `initial` parameter. It also takes a `mode` argument that specifies how labels should be propagated along edges (forward, backward or ignoring edge directions). - - `igraph_community_label_propagation()` does not provide the modularity in a separate output argument any more; use `igraph_modularity()` to retrieve the modularity if you need it. - - `igraph_community_leiden()` has an additional parameter to indicate the number of iterations to perform (PR #2177). - - `igraph_community_walktrap()`, `igraph_community_edge_betweenness()`, `igraph_community_eb_get_merges()`, `igraph_community_fastgreedy()`, `igraph_community_to_membership()`, `igraph_le_community_to_membership()`, `igraph_community_leading_eigenvector()` now use an `igraph_vector_int_t` for their `merges` parameter. - - `igraph_community_walktrap()` now uses `igraph_integer_t` for its `steps` argument. - - `igraph_coreness()` now uses an `igraph_vector_int_t` to return the coreness +- `igraph_clique_handler_t` now uses an `igraph_vector_int_t` for its `clique` parameter, and must return an `igraph_error_t`. Use `IGRAPH_STOP` as the return code to terminate the search prematurely. The vector that the handler receives is owned by the clique search routine. If you want to hold on to the vector for a longer period of time, you need to make a copy of it in the handler. Cliques passed to the callback are marked as `const` as a reminder to this change. +- The `res` parameter of `igraph_cliques()` is now an `igraph_vector_int_list_t`. +- Callbacks used by `igraph_cliques_callback()` need to be updated to account for the fact that the callback does not own the clique passed to it any more; the callback needs to make a copy if it wants to hold on to the clique for a longer period of time. If the callback does not need to store the clique, it does not need to do anything any more, and it must not destroy or free the clique. +- `igraph_closeness()` and `igraph_closeness_cutoff()` now use an `igraph_vector_int_t` to return `reachable_count`, not an `igraph_vector_t`. +- `igraph_cohesive_blocks()` now uses an `igraph_vector_int_t` to return the mapping from block indices to parent block indices, and the `cohesion`; also, it uses an `igraph_vector_int_list_t` to return the blocks themselves instead of a pointer vector of `igraph_vector_t`. +- The `igraph_community_eb_get_merges()` bridges parameter now starts the indices into the edge removal vector at 0, not 1. +- The `igraph_community_eb_get_merges()` now reports an error when not all edges in the graph are removed, instead of a nonsensical result. +- `igraph_community_edge_betweenness()` now uses an `igraph_vector_int_t` to return the edge IDs in the order of their removal as well as the list of edge IDs whose removal broke a single component into two. +- `igraph_community_fluid_communities()` does not provide the modularity in a separate output argument any more; use `igraph_modularity()` to retrieve the modularity if you need it. +- `igraph_community_infomap()` now uses `igraph_integer_t` for its `nb_trials` argument. +- `igraph_community_label_propagation()` now uses an `igraph_vector_int_t` for its `initial` parameter. It also takes a `mode` argument that specifies how labels should be propagated along edges (forward, backward or ignoring edge directions). +- `igraph_community_label_propagation()` does not provide the modularity in a separate output argument any more; use `igraph_modularity()` to retrieve the modularity if you need it. +- `igraph_community_leiden()` has an additional parameter to indicate the number of iterations to perform (PR #2177). +- `igraph_community_walktrap()`, `igraph_community_edge_betweenness()`, `igraph_community_eb_get_merges()`, `igraph_community_fastgreedy()`, `igraph_community_to_membership()`, `igraph_le_community_to_membership()`, `igraph_community_leading_eigenvector()` now use an `igraph_vector_int_t` for their `merges` parameter. +- `igraph_community_walktrap()` now uses `igraph_integer_t` for its `steps` argument. +- `igraph_coreness()` now uses an `igraph_vector_int_t` to return the coreness values. - - `igraph_convex_hull()` now uses an `igraph_vector_int_t` to return the indices of the input vertices that were chosen to be in the convex hull. - - `igraph_correlated_game()` and `igraph_correlated_pair_game()` now take an `igraph_vector_int_t` as the permutation vector, not an `igraph_vector_t`. - - `igraph_create()` now uses an `igraph_vector_int_t` for its `edges` parameter. - - `igraph_create_bipartite()` now uses an `igraph_vector_int_t` for its `edges` parameter. - - `igraph_compose()` now returns the edge maps in an `igraph_vector_int_t` instead of an `igraph_vector_t`. - - `igraph_count_multiple()` now returns the multiplicities in an `igraph_vector_int_t` instead of an `igraph_vector_t`. - - `igraph_decompose()` now uses an `igraph_integer_t` for its `maxcompno` and `minelements` arguments instead of a `long int`. - - `igraph_degree()` now uses an `igraph_vector_int_t` to return the degrees. If you need the degrees in a vector containing floating-point numbers instead (e.g., because you want to pass them on to some other function that takes an `igraph_vector_t`), use `igraph_strength()` instead with a null weight vector. - - `igraph_degree_sequence_game()` now takes degree sequences represented as `igraph_vector_int_t` instead of `igraph_vector_t`. - - `igraph_degseq_t`, used by `igraph_degree_sequence_game()`, uses new names for its constants. The old names are deprecated, but retained for compatibility. See `igraph_constants.h` to see which new name corresponds to which old one. - - `igraph_delete_vertices_idx()` now uses `igraph_vector_int_t` vectors to return the mapping and the inverse mapping of old vertex IDs to new ones. - - `igraph_deterministic_optimal_imitation()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. - - `igraph_dfs()` now takes an `igraph_vector_int_t` for its `order`, `order_out`, `father` and `dist` arguments instead of an `igraph_vector_t`. Furthermore, these vectors will contain -2 for vertices that have not been visited; in earlier versions, they used to contain NaN instead. Note that -1 is still used in the `father` vector to indicate the root of a DFS tree. - - `igraph_diameter()` and `igraph_diameter_dijkstra()` now use `igraph_vector_int_t` vectors to return the list of vertex and edge IDs in the diameter. - - `igraph_dominator_tree()` now takes an `igraph_vector_int_t` for its `dom` and `leftout` arguments instead of an `igraph_vector_t`. - - `igraph_dyad_census()` now uses `igraph_real_t` instead of `igraph_integer_t` for its output arguments, and it no longer returns -1 when overflow occurs. - - `igraph_edges()` now takes an `igraph_vector_int_t` for its `edges` argument instead of an `igraph_vector_t`. - - `igraph_es_multipairs()` was removed; you can use the newly added `igraph_es_all_between()` instead. - - `igraph_establishment_game()` now takes an `igraph_vector_int_t` for its `node_type_vec` argument instead of an `igraph_vector_t`. - - `igraph_eulerian_path()` and `igraph_eulerian_cycle()` now use `igraph_vector_int_t` to return the list of edge and vertex IDs participating in an Eulerian path or cycle instead of an `igraph_vector_t`. - - `igraph_feedback_arc_set()` now uses an `igraph_vector_int_t` to return the IDs of the edges in the feedback arc set instead of an `igraph_vector_t`. - - `igraph_get_adjacency()` no longer has the `eids` argument, which would produce an adjacency matrix where non-zero values were 1-based (not 0-based) edge IDs. If you need a matrix with edge IDs, create it manually. - - `igraph_get_adjacency_sparse()` now returns the sparse adjacency matrix in an `igraph_sparsemat_t` structure, and it assumes that the input matrix is _initialized_ for sake of consistency with other igraph functions. - - `igraph_get_adjacency()` and `igraph_get_adjacency_sparse()` now has a `loops` argument that lets the user specify how loop edges should be handled. - - `igraph_get_edgelist()` now uses an `igraph_vector_int_t` for its `res` parameter. - - `igraph_get_eids()` now uses `igraph_vector_int_t` to return lists of edge IDs and to receive lists of vertex IDs. - - The `path` argument of `igraph_get_eids()` was removed. You can replicate the old behaviour by constructing the list of vertex IDs explicitly from the path by duplicating each vertex in the path except the first and last ones. A helper function called `igraph_expand_path_to_pairs()` is provided to ease the transition. - - `igraph_get_eids_multi()` was removed as its design was fundamentally broken; there was no way to retrieve the IDs of all edges between a specific pair of vertices without knowing in advance how many such edges there are in the graph. Use `igraph_get_all_eids_between()` instead. - - `igraph_get_incidence()` now returns the vertex IDs corresponding to the rows and columns of the incidence matrix as `igraph_vector_int_t`. - - `igraph_get_shortest_path()`, `igraph_get_shortest_path_bellman_ford()` and `igraph_get_shortest_path_dijkstra()` now use `igraph_vector_int_t` vectors to return the list of vertex and edge IDs in the shortest path. - - `igraph_get_shortest_paths()`, `igraph_get_shortest_paths_dijkstra()` and `igraph_get_shortest_paths_bellman_ford()` now use an `igraph_vector_int_t` to return the predecessors and inbound edges instead of an `igraph_vector_long_t`. - - The functions `igraph_get_all_shortest_paths()`, `igraph_get_all_shortest_paths_dijkstra()`, `igraph_get_shortest_paths()`, `igraph_get_shortest_paths_bellman_ford()` and `igraph_get_shortest_paths_dijkstra()` now return paths in an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. - - The vector of parents in `igraph_get_shortest_paths()`, `igraph_get_shortest_paths_bellman_ford()` and `igraph_get_shortest_paths_dijkstra()` now use -1 to represent the starting vertex, and -2 for unreachable vertices. - - The `maps` parameters in `igraph_get_isomorphisms_vf2()` and `igraph_get_subisomorphisms_vf2()` are now of type `igraph_vector_int_list_t`. - - `igraph_get_stochastic()` now has an additional `weights` argument for edge weights. - - `igraph_get_stochastic_sparse()` now returns the sparse adjacency matrix in an `igraph_sparsemat_t` structure, and it assumes that the input matrix is _initialized_ for sake of consistency with other igraph functions. It also received an additional `weights` argument for edge weights. - - `igraph_girth()` now uses an `igraph_vector_int_t` for its `circle` parameter. - - `igraph_girth()` now uses `igraph_real_t` as the return value so we can return infinity for graphs with no cycles (instead of zero). - - The `cliques` parameters of type `igraph_vector_ptr_t` in `igraph_graphlets()`, `igraph_graphlets_candidate_basis()` and `igraph_graphlets_project()` were changed to an `igraph_vector_int_list_t`. - - `igraph_hrg_init()` and `igraph_hrg_resize()` now takes an `igraph_integer_t` as their size arguments instead of an `int`. - - `igraph_hrg_consensus()` now returns the parent vector in an `igraph_vector_int_t` instead of an `igraph_vector_t`. - - `igraph_hrg_create()` now takes a vector of probabilities corresponding to the internal nodes of the dendogram. It used to also take probabilities for the leaf nodes and then ignore them. - - `igraph_hrg_predict()` now uses an `igraph_vector_int_t` for its `edges` parameter. - - `igraph_hrg_sample()` now always samples a single graph only. Use `igraph_hrg_sample_many()` if you need more than one sample, and call `igraph_hrg_fit()` beforehand if you do not have a HRG model but only a single input graph. - - `igraph_hrg_size()` now returns an `igraph_integer_t` instead of an `int`. - - `igraph_incidence()` does not accept negative incidence counts any more. - - `igraph_incident()` now uses an `igraph_vector_int_t` for its `eids` parameter. - - The `res` parameter in `igraph_independent_vertex_sets()` is now an `igraph_vector_int_list_t`. - - `igraph_induced_subgraph_map()` now uses `igraph_vector_int_t` vectors to return the mapping and the inverse mapping of old vertex IDs to new ones. - - `igraph_intersection()` now uses an `igraph_vector_int_t` for its `edge_map1` and `edge_map2` parameters. - - The `edgemaps` parameter of `igraph_intersection_many()` is now an `igraph_vector_int_list_t` instead of a pointer vector. - - `igraph_is_chordal()` now uses an `igraph_vector_int_t` for its `alpha`, `alpham1` and `fill_in` parameters. - - `igraph_is_graphical()` and `igraph_is_bigraphical()` now take degree sequences represented as `igraph_vector_int_t` instead of `igraph_vector_t`. - - `igraph_is_matching()`, `igraph_is_maximal_matching()` and `igraph_maximum_bipartite_matching` now use an `igraph_vector_int_t` to return the matching instead of an `igraph_vector_long_t`. - - `igraph_is_mutual()` has an additional parameter which controls whether directed self-loops are considered mutual. - - The `vids` parameter for `igraph_isoclass_subgraph()` is now an `igraph_vector_int_t` instead of `igraph_vector_t`. - - `igraph_isomorphic_vf2()`, `igraph_get_isomorphisms_vf2_callback()` (which used to be called `igraph_isomorphic_function_vf2()`) and `igraph_isohandler_t` now all use `igraph_vector_int_t` for their `map12` and `map21` parameters. - - The `cliques` parameter of type `igraph_vector_ptr_t` in `igraph_largest_cliques()` was changed to an `igraph_vector_int_list_t`. - - The `res` parameters of type `igraph_vector_ptr_t` in `igraph_largest_independent_vertex_sets()` and `igraph_largest_weighted_cliques()` were changed to an `igraph_vector_int_list_t`. - - The dimension vector parameter for `igraph_square_lattice()` (used to be `igraph_lattice()`) is now an `igraph_vector_int_t` instead of `igraph_vector_t`. - - The maxiter parameter of `igraph_layout_bipartite()` is now an `igraph_integer_t` instead of `long int`. - - The fixed parameter of `igraph_layout_drl()` and `igraph_layout_drl_3d()` was removed as it has never been implemented properly. - - The width parameter of `igraph_layout_grid()` is now an `igraph_integer_t` instead of `long int`. - - The width and height parameters of `igraph_layout_grid_3d()` are now `igraph_integer_t` instead of `long int`. - - The dimension parameter of `igraph_layout_mds()` is now an `igraph_integer_t` instead of `long int`. - - The `roots` and `rootlevel` parameters of `igraph_layout_reingold_tilford()` are now `igraph_vector_int_t` instead of `igraph_vector_t`. - - The `roots` and `rootlevel` parameters of `igraph_layout_reingold_tilford_circular()` are now `igraph_vector_int_t` instead of `igraph_vector_t`. - - The order parameter of `igraph_layout_star()` is now an `igraph_vector_int_t` instead of an `igraph_vector_t`. - - The maxiter parameter of `igraph_layout_sugiyama()` is now an `igraph_integer_t` instead of `long int`. Also, the function now uses an `igraph_vector_int_t` for its `extd_to_orig_eids` parameter. - - The shifts parameter of `igraph_lcf_vector()` is now an `igraph_vector_int_t` instead of an `igraph_vector_t`. - - `igraph_matrix_minmax()`, `igraph_matrix_which_minmax()`, `igraph_matrix_which_min()` and `igraph_matrix_which_max()` no longer return an error code. The return type is now `void`. These functions never fail. - - `igraph_maxflow()` now uses an `igraph_vector_int_t` for its `cut`, `partition` and `partition2` parameters. - - The `igraph_maxflow_stats_t` struct now contains `igraph_integer_t` values instead of `int` ones. - - The `res` parameters in `igraph_maximal_cliques()` and `igraph_maximal_cliques_subset()` are now of type `igraph_vector_int_list_t`. - - Callbacks used by `igraph_maximal_cliques_callback()` need to be updated to account for the fact that the callback does not own the clique passed to it any more; the callback needs to make a copy if it wants to hold on to the clique for a longer period of time. If the callback does not need to store the clique, it does not need to do anything any more, and it must not destroy or free the clique. - - The `res` parameter in `igraph_maximal_independent_vertex_sets()` is now an `igraph_vector_int_list_t`. - - `igraph_maximum_cardinality_search()` now uses an `igraph_vector_int_t` for its `alpha` and `alpham1` arguments. - - `igraph_mincut()` now uses an `igraph_vector_int_t` for its `cut`, `partition` and `partition2` parameters. - - `igraph_moran_process()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. - - Motif callbacks of type `igraph_motifs_handler_t` now take an `igraph_vector_int_t` with the vertex IDs instead of an `igraph_vector_t`, and use `igraph_integer_t` for the isoclass parameter. - - Motif functions now use `igraph_integer_t` instead of `int` for their `size` parameter. - - `igraph_neighborhood_size()` now uses an `igraph_vector_int_t` for its `res` parameter. - - The `res` parameter of `igraph_neighborhood()` is now an `igraph_vector_int_list_t`. - - `igraph_neighbors()` now uses an `igraph_vector_int_t` for its `neis` parameter. - - `igraph_permute_vertices()` now takes an `igraph_vector_int_t` as the permutation vector. - - `igraph_power_law_fit()` does not calculate the p-value automatically any more because the previous estimation method did not match the results from the original paper of Clauset, Shalizi and Newman (2009) and the implementation of the method outlined in the paper runs slower than the previous naive estimate. A separate function named `igraph_plfit_result_calculate_p_value()` is now provided for calculating the p-value. The automatic selection of the `x_min` cutoff also uses a different method than earlier versions. As a consequence, results might be slightly different if you used tests where the `x_min` cutoff was selected automatically. The new behaviour is now consistent with the defaults of the underlying `plfit` library. - - `igraph_preference_game()` now uses an `igraph_vector_int_t` to return the types of the nodes in the generated graph. - - `igraph_random_walk()` now uses an `igraph_vector_int_t` for its results. Also, the function now takes both vertices and edges as parameters. It can return IDs of vertices and/or edges on the walk. The function now takes weights as a parameter to support weighted graphs. - - `igraph_random_edge_walk()` now uses an `igraph_vector_int_t` for its `edgewalk` parameter. - - `igraph_read_graph_dimacs_flow()` now uses an `igraph_vector_int_t` for its label parameter. - - `igraph_read_graph_graphml()` now uses `igraph_integer_t` for its `index` argument. - - `igraph_read_graph_pajek()` now creates a Boolean `type` attribute for bipartite graphs. Previously it created a numeric attribute. - - `igraph_realize_degree_sequence()` now uses an `igraph_vector_int_t` for its `outdeg` and `indeg` parameters. - - `igraph_reindex_membership()` now uses an `igraph_vector_int_t` for its `new_to_old` parameter. - - `igraph_rng_seed()` now requires an `igraph_uint_t` as its seed arguments. RNG implementations are free to use only the lower bits of the seed if they do not support 64-bit seeds. - - `igraph_rngtype_rand` (i.e. the RNG that is based on BSD `rand()`) was removed due to poor statistical properties that sometimes resulted in weird artifacts like all-even "random" numbers when igraph's usage patterns happened to line up with the shortcomings of the `rand()` generator in a certain way. - - `igraph_roulette_wheel_imitation()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. - - `igraph_similarity_dice_pairs()` now uses an `igraph_vector_int_t` for its `pairs` parameter. - - `igraph_similarity_jaccard_pairs()` now uses an `igraph_vector_int_t` for its `pairs` parameter. - - `igraph_simple_interconnected_islands_game()` does not generate multi-edges between islands any more. - - `igraph_sort_vertex_ids_by_degree()` and `igraph_topological_sorting()` now use an `igraph_vector_int_t` to return the vertex IDs instead of an `igraph_vector_t`. - - `igraph_spanning_tree()`, `igraph_minimum_spanning_tree()` and `igraph_random_spanning_tree()` now all use an `igraph_vector_int_t` to return the vector of edge IDs in the spanning tree instead of an `igraph_vector_t`. - - `igraph_sparsemat_cholsol()`, `igraph_sparsemat_lusol()`, `igraph_sparsemat_symbqr()` and `igraph_sparsemat_symblu()` now take an `igraph_integer_t` as their `order` parameter. - - `igraph_sparsemat_count_nonzero()` and `igraph_sparsemat_count_nonzerotol()` now return an `igraph_integer_t`. - - `igraph_sparsemat_is_symmetric()` now returns an error code and the result itself is provided in an output argument. - - The `values` argument of `igraph_sparsemat_transpose()` was removed; now the function always copies the values over to the transposed matrix. - - `igraph_spmatrix_t` and related functions were removed as they mostly duplicated functionality that was already present in `igraph_sparsemat_t`. Functions that used `igraph_spmatrix_t` in the library now use `igraph_sparsemat_t`. - - `igraph_stochastic_imitation()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. - - `igraph_st_mincut()` now uses an `igraph_vector_int_t` for its `cut`, `partition` and `partition2` parameters. - - `igraph_st_vertex_connectivity()` now ignores edges between source and target for `IGRAPH_VCONN_NEI_IGNORE` - - `igraph_strvector_get()` now returns strings in the return value, not in an output argument. - - `igraph_subcomponent()` now uses an `igraph_integer_t` for the seed vertex instead of an `igraph_real_t`. It also uses an `igraph_vector_int_t` to return the list of vertices in the same component as the seed vertex instead of an `igraph_vector_t`. - - `igraph_subisomorphic_vf2()`, `igraph_get_subisomorphisms_vf2_callback()` (which used to be called `igraph_subisomorphic_function_vf2()`) and `igraph_isomorphic_bliss()` now all use `igraph_vector_int_t` for their `map12` and `map21` parameters. - - The `maps` parameters in `igraph_subisomorphic_lad()`, `igraph_get_isomorphisms_vf2()` and `igraph_get_subisomorphisms_vf2()` are now of type `igraph_vector_int_list_t`. - - `igraph_subisomorphic_lad()` now uses an `igraph_vector_int_t` for its `map` parameter. Also, its `domains` parameter is now an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. - - `igraph_unfold_tree()` now uses an `igraph_vector_int_t` for its `vertex_index` and `roots` parameters. - - `igraph_union()` now uses an `igraph_vector_int_t` for its `edge_map1` and `edge_map2` parameters. - - The `edgemaps` parameter of `igraph_union_many()` is now an `igraph_vector_int_list_t` instead of a pointer vector. - - `igraph_vector_init_copy()` was refactored to take _another_ vector that the newly initialized vector should copy. The old array-based initialization function is now called `igraph_vector_init_array()`. - - `igraph_vector_ptr_init_copy()` was renamed to `igraph_vector_ptr_init_array()` for sake of consistency. - - `igraph_vs_vector()`, `igraph_vss_vector()` and `igraph_vs_vector_copy()` now all take an `igraph_vector_int_t` as the vector of vertex IDs, not an `igraph_vector_t`. Similarly, `igraph_vs_as_vector()` now returns the vector of matched vertex IDs in an `igraph_vector_int_t`, not an `igraph_vector_t`. - - The `res` parameter of `igraph_weighted_cliques()` is now an `igraph_vector_int_list_t`. - - `igraph_write_graph_dimacs_flow()` now uses `igraph_integer_t` for the source and target vertex index instead of a `long int`. - - `igraph_vector_*()`, `igraph_matrix_*()`, `igraph_stack_*()`, `igraph_array_*()` and several other generic igraph data types now use `igraph_integer_t` for indexing, _not_ `long int`. Please refer to the headers for the exact details; the list of affected functions is too large to include here. - - `igraph_vector_minmax()` and `igraph_vector_which_minmax()` no longer return an error code. The return type is now `void`. These functions never fail. - - `igraph_vector_order()` was removed; use `igraph_vector_int_pair_order()` instead. (The original function worked for vectors containing integers only). - - `igraph_vector_resize_min()` and `igraph_matrix_resize_min()` no longer return an error code (return type is now `void`). The vector or matrix is always left in a consistent state by these functions, with all data intact, even if releasing unused storage is not successful. - - `igraph_vector_qsort_ind()` and its variants now take an `igraph_order_t` enum instead of a boolean to denote whether the order should be ascending or descending. - - `igraph_weighted_adjacency()` now returns the weights in a separate vector instead of storing it in a vertex attribute. The reason is twofold: first, the previous solution worked only with the C attribute handler (not the ones from the higher-level interfaces), and second, it wasn't consistent with other igraph functions that use weights provided as separate arguments. - - The `loops` argument of `igraph_weighted_adjacency()` was converted to an `igraph_loops_t` for sake of consistency with `igraph_adjacency()` and `igraph_get_adjacency()`. - - `igraph_write_graph_gml()` takes an additional bitfield parameter controlling some aspects of writing the GML file. - - The `add_edges()` function in the attribute handler now takes an `igraph_vector_int_t` for its `edges` parameter instead of an `igraph_vector_t`. The `add_vertices()` function now takes an `igraph_integer_t` for the vertex count instead of a `long int`. The `combine_vertices()` and `combine_edges()` functions now take an `igraph_vector_ptr_t` containing vectors of type `igraph_vector_int_t` in their `merges` parameters. The `get_info()` function now uses `igraph_vector_int_t` to return the types of the graph, vertex and edge attribute types. The `permute_vertices()` and `permute_edges()` functions in the attribute handler tables now take an `igraph_vector_int_t` instead of an `igraph_vector_t` for the index vectors. These are relevant only to maintainers of higher level interfaces to igraph; they should update their attribute handlers accordingly. - - igraph functions that interface with external libraries such as BLAS or LAPACK may now fail if the underlying BLAS or LAPACK implementation cannot handle the size of input vectors or matrices (BLAS and LAPACK are usually limited to vectors whose size fits in an `int`). `igraph_blas_dgemv()` and `igraph_blas_dgemv_array()` thus now return an `igraph_error_t`, which may be set to `IGRAPH_EOVERFLOW` if the input vectors or matrices are too large. - - Functions that used an `igraph_vector_t` to represent cluster size and cluster membership now use an `igraph_vector_int_t` instead. These are: - - `igraph_connected_components()` (used to be `igraph_clusters()` in 0.9 and before) - - `igraph_community_eb_get_merges()` - - `igraph_community_edge_betweenness()` - - `igraph_community_fastgreedy()` - - `igraph_community_fluid_communities()` - - `igraph_community_infomap()` - - `igraph_community_label_propagation()` - - `igraph_community_leading_eigenvector()` - - `igraph_community_leiden()` - - `igraph_community_multilevel()` - - `igraph_community_optimal_modularity()` - - `igraph_community_spinglass()` - - `igraph_community_spinglass_single()` - - `igraph_community_to_membership()` - - `igraph_community_walktrap()` - - `igraph_compare_communities()` - - `igraph_le_community_to_membership()` - - `igraph_modularity()` - - `igraph_reindex_membership()` - - `igraph_split_join_distance()` - - `igraph_community_multilevel()` additionally uses a `igraph_matrix_int_t` instead of `igraph_matrix_t()` for its memberships parameter. - - `IGRAPH_TOTAL` was removed from the `igraph_neimode_t` enum; use the equivalent `IGRAPH_ALL` instead. +- `igraph_create()` now uses an `igraph_vector_int_t` for its `edges` parameter. +- `igraph_create_bipartite()` now uses an `igraph_vector_int_t` for its `edges` parameter. +- `igraph_compose()` now returns the edge maps in an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- `igraph_count_multiple()` now returns the multiplicities in an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- `igraph_decompose()` now uses an `igraph_integer_t` for its `maxcompno` and `minelements` arguments instead of a `long int`. +- `igraph_degree()` now uses an `igraph_vector_int_t` to return the degrees. If you need the degrees in a vector containing floating-point numbers instead (e.g., because you want to pass them on to some other function that takes an `igraph_vector_t`), use `igraph_strength()` instead with a null weight vector. +- `igraph_degree_sequence_game()` now takes degree sequences represented as `igraph_vector_int_t` instead of `igraph_vector_t`. +- `igraph_degseq_t`, used by `igraph_degree_sequence_game()`, uses new names for its constants. The old names are deprecated, but retained for compatibility. See `igraph_constants.h` to see which new name corresponds to which old one. +- `igraph_delete_vertices_idx()` now uses `igraph_vector_int_t` vectors to return the mapping and the inverse mapping of old vertex IDs to new ones. +- `igraph_deterministic_optimal_imitation()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. +- `igraph_dfs()` now takes an `igraph_vector_int_t` for its `order`, `order_out`, `father` and `dist` arguments instead of an `igraph_vector_t`. Furthermore, these vectors will contain -2 for vertices that have not been visited; in earlier versions, they used to contain NaN instead. Note that -1 is still used in the `father` vector to indicate the root of a DFS tree. +- `igraph_diameter()` and `igraph_diameter_dijkstra()` now use `igraph_vector_int_t` vectors to return the list of vertex and edge IDs in the diameter. +- `igraph_dominator_tree()` now takes an `igraph_vector_int_t` for its `dom` and `leftout` arguments instead of an `igraph_vector_t`. +- `igraph_dyad_census()` now uses `igraph_real_t` instead of `igraph_integer_t` for its output arguments, and it no longer returns -1 when overflow occurs. +- `igraph_edges()` now takes an `igraph_vector_int_t` for its `edges` argument instead of an `igraph_vector_t`. +- `igraph_es_multipairs()` was removed; you can use the newly added `igraph_es_all_between()` instead. +- `igraph_establishment_game()` now takes an `igraph_vector_int_t` for its `node_type_vec` argument instead of an `igraph_vector_t`. +- `igraph_eulerian_path()` and `igraph_eulerian_cycle()` now use `igraph_vector_int_t` to return the list of edge and vertex IDs participating in an Eulerian path or cycle instead of an `igraph_vector_t`. +- `igraph_feedback_arc_set()` now uses an `igraph_vector_int_t` to return the IDs of the edges in the feedback arc set instead of an `igraph_vector_t`. +- `igraph_get_adjacency()` no longer has the `eids` argument, which would produce an adjacency matrix where non-zero values were 1-based (not 0-based) edge IDs. If you need a matrix with edge IDs, create it manually. +- `igraph_get_adjacency_sparse()` now returns the sparse adjacency matrix in an `igraph_sparsemat_t` structure, and it assumes that the input matrix is _initialized_ for sake of consistency with other igraph functions. +- `igraph_get_adjacency()` and `igraph_get_adjacency_sparse()` now has a `loops` argument that lets the user specify how loop edges should be handled. +- `igraph_get_edgelist()` now uses an `igraph_vector_int_t` for its `res` parameter. +- `igraph_get_eids()` now uses `igraph_vector_int_t` to return lists of edge IDs and to receive lists of vertex IDs. +- The `path` argument of `igraph_get_eids()` was removed. You can replicate the old behaviour by constructing the list of vertex IDs explicitly from the path by duplicating each vertex in the path except the first and last ones. A helper function called `igraph_expand_path_to_pairs()` is provided to ease the transition. +- `igraph_get_eids_multi()` was removed as its design was fundamentally broken; there was no way to retrieve the IDs of all edges between a specific pair of vertices without knowing in advance how many such edges there are in the graph. Use `igraph_get_all_eids_between()` instead. +- `igraph_get_incidence()` now returns the vertex IDs corresponding to the rows and columns of the incidence matrix as `igraph_vector_int_t`. +- `igraph_get_shortest_path()`, `igraph_get_shortest_path_bellman_ford()` and `igraph_get_shortest_path_dijkstra()` now use `igraph_vector_int_t` vectors to return the list of vertex and edge IDs in the shortest path. +- `igraph_get_shortest_paths()`, `igraph_get_shortest_paths_dijkstra()` and `igraph_get_shortest_paths_bellman_ford()` now use an `igraph_vector_int_t` to return the predecessors and inbound edges instead of an `igraph_vector_long_t`. +- The functions `igraph_get_all_shortest_paths()`, `igraph_get_all_shortest_paths_dijkstra()`, `igraph_get_shortest_paths()`, `igraph_get_shortest_paths_bellman_ford()` and `igraph_get_shortest_paths_dijkstra()` now return paths in an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. +- The vector of parents in `igraph_get_shortest_paths()`, `igraph_get_shortest_paths_bellman_ford()` and `igraph_get_shortest_paths_dijkstra()` now use -1 to represent the starting vertex, and -2 for unreachable vertices. +- The `maps` parameters in `igraph_get_isomorphisms_vf2()` and `igraph_get_subisomorphisms_vf2()` are now of type `igraph_vector_int_list_t`. +- `igraph_get_stochastic()` now has an additional `weights` argument for edge weights. +- `igraph_get_stochastic_sparse()` now returns the sparse adjacency matrix in an `igraph_sparsemat_t` structure, and it assumes that the input matrix is _initialized_ for sake of consistency with other igraph functions. It also received an additional `weights` argument for edge weights. +- `igraph_girth()` now uses an `igraph_vector_int_t` for its `circle` parameter. +- `igraph_girth()` now uses `igraph_real_t` as the return value so we can return infinity for graphs with no cycles (instead of zero). +- The `cliques` parameters of type `igraph_vector_ptr_t` in `igraph_graphlets()`, `igraph_graphlets_candidate_basis()` and `igraph_graphlets_project()` were changed to an `igraph_vector_int_list_t`. +- `igraph_hrg_init()` and `igraph_hrg_resize()` now takes an `igraph_integer_t` as their size arguments instead of an `int`. +- `igraph_hrg_consensus()` now returns the parent vector in an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- `igraph_hrg_create()` now takes a vector of probabilities corresponding to the internal nodes of the dendogram. It used to also take probabilities for the leaf nodes and then ignore them. +- `igraph_hrg_predict()` now uses an `igraph_vector_int_t` for its `edges` parameter. +- `igraph_hrg_sample()` now always samples a single graph only. Use `igraph_hrg_sample_many()` if you need more than one sample, and call `igraph_hrg_fit()` beforehand if you do not have a HRG model but only a single input graph. +- `igraph_hrg_size()` now returns an `igraph_integer_t` instead of an `int`. +- `igraph_incidence()` does not accept negative incidence counts any more. +- `igraph_incident()` now uses an `igraph_vector_int_t` for its `eids` parameter. +- The `res` parameter in `igraph_independent_vertex_sets()` is now an `igraph_vector_int_list_t`. +- `igraph_induced_subgraph_map()` now uses `igraph_vector_int_t` vectors to return the mapping and the inverse mapping of old vertex IDs to new ones. +- `igraph_intersection()` now uses an `igraph_vector_int_t` for its `edge_map1` and `edge_map2` parameters. +- The `edgemaps` parameter of `igraph_intersection_many()` is now an `igraph_vector_int_list_t` instead of a pointer vector. +- `igraph_is_chordal()` now uses an `igraph_vector_int_t` for its `alpha`, `alpham1` and `fill_in` parameters. +- `igraph_is_graphical()` and `igraph_is_bigraphical()` now take degree sequences represented as `igraph_vector_int_t` instead of `igraph_vector_t`. +- `igraph_is_matching()`, `igraph_is_maximal_matching()` and `igraph_maximum_bipartite_matching` now use an `igraph_vector_int_t` to return the matching instead of an `igraph_vector_long_t`. +- `igraph_is_mutual()` has an additional parameter which controls whether directed self-loops are considered mutual. +- The `vids` parameter for `igraph_isoclass_subgraph()` is now an `igraph_vector_int_t` instead of `igraph_vector_t`. +- `igraph_isomorphic_vf2()`, `igraph_get_isomorphisms_vf2_callback()` (which used to be called `igraph_isomorphic_function_vf2()`) and `igraph_isohandler_t` now all use `igraph_vector_int_t` for their `map12` and `map21` parameters. +- The `cliques` parameter of type `igraph_vector_ptr_t` in `igraph_largest_cliques()` was changed to an `igraph_vector_int_list_t`. +- The `res` parameters of type `igraph_vector_ptr_t` in `igraph_largest_independent_vertex_sets()` and `igraph_largest_weighted_cliques()` were changed to an `igraph_vector_int_list_t`. +- The dimension vector parameter for `igraph_square_lattice()` (used to be `igraph_lattice()`) is now an `igraph_vector_int_t` instead of `igraph_vector_t`. +- The maxiter parameter of `igraph_layout_bipartite()` is now an `igraph_integer_t` instead of `long int`. +- The fixed parameter of `igraph_layout_drl()` and `igraph_layout_drl_3d()` was removed as it has never been implemented properly. +- The width parameter of `igraph_layout_grid()` is now an `igraph_integer_t` instead of `long int`. +- The width and height parameters of `igraph_layout_grid_3d()` are now `igraph_integer_t` instead of `long int`. +- The dimension parameter of `igraph_layout_mds()` is now an `igraph_integer_t` instead of `long int`. +- The `roots` and `rootlevel` parameters of `igraph_layout_reingold_tilford()` are now `igraph_vector_int_t` instead of `igraph_vector_t`. +- The `roots` and `rootlevel` parameters of `igraph_layout_reingold_tilford_circular()` are now `igraph_vector_int_t` instead of `igraph_vector_t`. +- The order parameter of `igraph_layout_star()` is now an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- The maxiter parameter of `igraph_layout_sugiyama()` is now an `igraph_integer_t` instead of `long int`. Also, the function now uses an `igraph_vector_int_t` for its `extd_to_orig_eids` parameter. +- The shifts parameter of `igraph_lcf_vector()` is now an `igraph_vector_int_t` instead of an `igraph_vector_t`. +- `igraph_matrix_minmax()`, `igraph_matrix_which_minmax()`, `igraph_matrix_which_min()` and `igraph_matrix_which_max()` no longer return an error code. The return type is now `void`. These functions never fail. +- `igraph_maxflow()` now uses an `igraph_vector_int_t` for its `cut`, `partition` and `partition2` parameters. +- The `igraph_maxflow_stats_t` struct now contains `igraph_integer_t` values instead of `int` ones. +- The `res` parameters in `igraph_maximal_cliques()` and `igraph_maximal_cliques_subset()` are now of type `igraph_vector_int_list_t`. +- Callbacks used by `igraph_maximal_cliques_callback()` need to be updated to account for the fact that the callback does not own the clique passed to it any more; the callback needs to make a copy if it wants to hold on to the clique for a longer period of time. If the callback does not need to store the clique, it does not need to do anything any more, and it must not destroy or free the clique. +- The `res` parameter in `igraph_maximal_independent_vertex_sets()` is now an `igraph_vector_int_list_t`. +- `igraph_maximum_cardinality_search()` now uses an `igraph_vector_int_t` for its `alpha` and `alpham1` arguments. +- `igraph_mincut()` now uses an `igraph_vector_int_t` for its `cut`, `partition` and `partition2` parameters. +- `igraph_moran_process()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. +- Motif callbacks of type `igraph_motifs_handler_t` now take an `igraph_vector_int_t` with the vertex IDs instead of an `igraph_vector_t`, and use `igraph_integer_t` for the isoclass parameter. +- Motif functions now use `igraph_integer_t` instead of `int` for their `size` parameter. +- `igraph_neighborhood_size()` now uses an `igraph_vector_int_t` for its `res` parameter. +- The `res` parameter of `igraph_neighborhood()` is now an `igraph_vector_int_list_t`. +- `igraph_neighbors()` now uses an `igraph_vector_int_t` for its `neis` parameter. +- `igraph_permute_vertices()` now takes an `igraph_vector_int_t` as the permutation vector. +- `igraph_power_law_fit()` does not calculate the p-value automatically any more because the previous estimation method did not match the results from the original paper of Clauset, Shalizi and Newman (2009) and the implementation of the method outlined in the paper runs slower than the previous naive estimate. A separate function named `igraph_plfit_result_calculate_p_value()` is now provided for calculating the p-value. The automatic selection of the `x_min` cutoff also uses a different method than earlier versions. As a consequence, results might be slightly different if you used tests where the `x_min` cutoff was selected automatically. The new behaviour is now consistent with the defaults of the underlying `plfit` library. +- `igraph_preference_game()` now uses an `igraph_vector_int_t` to return the types of the nodes in the generated graph. +- `igraph_random_walk()` now uses an `igraph_vector_int_t` for its results. Also, the function now takes both vertices and edges as parameters. It can return IDs of vertices and/or edges on the walk. The function now takes weights as a parameter to support weighted graphs. +- `igraph_random_edge_walk()` now uses an `igraph_vector_int_t` for its `edgewalk` parameter. +- `igraph_read_graph_dimacs_flow()` now uses an `igraph_vector_int_t` for its label parameter. +- `igraph_read_graph_graphml()` now uses `igraph_integer_t` for its `index` argument. +- `igraph_read_graph_pajek()` now creates a Boolean `type` attribute for bipartite graphs. Previously it created a numeric attribute. +- `igraph_realize_degree_sequence()` now uses an `igraph_vector_int_t` for its `outdeg` and `indeg` parameters. +- `igraph_reindex_membership()` now uses an `igraph_vector_int_t` for its `new_to_old` parameter. +- `igraph_rng_seed()` now requires an `igraph_uint_t` as its seed arguments. RNG implementations are free to use only the lower bits of the seed if they do not support 64-bit seeds. +- `igraph_rngtype_rand` (i.e. the RNG that is based on BSD `rand()`) was removed due to poor statistical properties that sometimes resulted in weird artifacts like all-even "random" numbers when igraph's usage patterns happened to line up with the shortcomings of the `rand()` generator in a certain way. +- `igraph_roulette_wheel_imitation()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. +- `igraph_similarity_dice_pairs()` now uses an `igraph_vector_int_t` for its `pairs` parameter. +- `igraph_similarity_jaccard_pairs()` now uses an `igraph_vector_int_t` for its `pairs` parameter. +- `igraph_simple_interconnected_islands_game()` does not generate multi-edges between islands any more. +- `igraph_sort_vertex_ids_by_degree()` and `igraph_topological_sorting()` now use an `igraph_vector_int_t` to return the vertex IDs instead of an `igraph_vector_t`. +- `igraph_spanning_tree()`, `igraph_minimum_spanning_tree()` and `igraph_random_spanning_tree()` now all use an `igraph_vector_int_t` to return the vector of edge IDs in the spanning tree instead of an `igraph_vector_t`. +- `igraph_sparsemat_cholsol()`, `igraph_sparsemat_lusol()`, `igraph_sparsemat_symbqr()` and `igraph_sparsemat_symblu()` now take an `igraph_integer_t` as their `order` parameter. +- `igraph_sparsemat_count_nonzero()` and `igraph_sparsemat_count_nonzerotol()` now return an `igraph_integer_t`. +- `igraph_sparsemat_is_symmetric()` now returns an error code and the result itself is provided in an output argument. +- The `values` argument of `igraph_sparsemat_transpose()` was removed; now the function always copies the values over to the transposed matrix. +- `igraph_spmatrix_t` and related functions were removed as they mostly duplicated functionality that was already present in `igraph_sparsemat_t`. Functions that used `igraph_spmatrix_t` in the library now use `igraph_sparsemat_t`. +- `igraph_stochastic_imitation()` now expects the list of strategies in an `igraph_vector_int_t` instead of an `igraph_int_t`. +- `igraph_st_mincut()` now uses an `igraph_vector_int_t` for its `cut`, `partition` and `partition2` parameters. +- `igraph_st_vertex_connectivity()` now ignores edges between source and target for `IGRAPH_VCONN_NEI_IGNORE` +- `igraph_strvector_get()` now returns strings in the return value, not in an output argument. +- `igraph_subcomponent()` now uses an `igraph_integer_t` for the seed vertex instead of an `igraph_real_t`. It also uses an `igraph_vector_int_t` to return the list of vertices in the same component as the seed vertex instead of an `igraph_vector_t`. +- `igraph_subisomorphic_vf2()`, `igraph_get_subisomorphisms_vf2_callback()` (which used to be called `igraph_subisomorphic_function_vf2()`) and `igraph_isomorphic_bliss()` now all use `igraph_vector_int_t` for their `map12` and `map21` parameters. +- The `maps` parameters in `igraph_subisomorphic_lad()`, `igraph_get_isomorphisms_vf2()` and `igraph_get_subisomorphisms_vf2()` are now of type `igraph_vector_int_list_t`. +- `igraph_subisomorphic_lad()` now uses an `igraph_vector_int_t` for its `map` parameter. Also, its `domains` parameter is now an `igraph_vector_int_list_t` instead of a pointer vector containing `igraph_vector_t` objects. +- `igraph_unfold_tree()` now uses an `igraph_vector_int_t` for its `vertex_index` and `roots` parameters. +- `igraph_union()` now uses an `igraph_vector_int_t` for its `edge_map1` and `edge_map2` parameters. +- The `edgemaps` parameter of `igraph_union_many()` is now an `igraph_vector_int_list_t` instead of a pointer vector. +- `igraph_vector_init_copy()` was refactored to take _another_ vector that the newly initialized vector should copy. The old array-based initialization function is now called `igraph_vector_init_array()`. +- `igraph_vector_ptr_init_copy()` was renamed to `igraph_vector_ptr_init_array()` for sake of consistency. +- `igraph_vs_vector()`, `igraph_vss_vector()` and `igraph_vs_vector_copy()` now all take an `igraph_vector_int_t` as the vector of vertex IDs, not an `igraph_vector_t`. Similarly, `igraph_vs_as_vector()` now returns the vector of matched vertex IDs in an `igraph_vector_int_t`, not an `igraph_vector_t`. +- The `res` parameter of `igraph_weighted_cliques()` is now an `igraph_vector_int_list_t`. +- `igraph_write_graph_dimacs_flow()` now uses `igraph_integer_t` for the source and target vertex index instead of a `long int`. +- `igraph_vector_*()`, `igraph_matrix_*()`, `igraph_stack_*()`, `igraph_array_*()` and several other generic igraph data types now use `igraph_integer_t` for indexing, _not_ `long int`. Please refer to the headers for the exact details; the list of affected functions is too large to include here. +- `igraph_vector_minmax()` and `igraph_vector_which_minmax()` no longer return an error code. The return type is now `void`. These functions never fail. +- `igraph_vector_order()` was removed; use `igraph_vector_int_pair_order()` instead. (The original function worked for vectors containing integers only). +- `igraph_vector_resize_min()` and `igraph_matrix_resize_min()` no longer return an error code (return type is now `void`). The vector or matrix is always left in a consistent state by these functions, with all data intact, even if releasing unused storage is not successful. +- `igraph_vector_qsort_ind()` and its variants now take an `igraph_order_t` enum instead of a boolean to denote whether the order should be ascending or descending. +- `igraph_weighted_adjacency()` now returns the weights in a separate vector instead of storing it in a vertex attribute. The reason is twofold: first, the previous solution worked only with the C attribute handler (not the ones from the higher-level interfaces), and second, it wasn't consistent with other igraph functions that use weights provided as separate arguments. +- The `loops` argument of `igraph_weighted_adjacency()` was converted to an `igraph_loops_t` for sake of consistency with `igraph_adjacency()` and `igraph_get_adjacency()`. +- `igraph_write_graph_gml()` takes an additional bitfield parameter controlling some aspects of writing the GML file. +- The `add_edges()` function in the attribute handler now takes an `igraph_vector_int_t` for its `edges` parameter instead of an `igraph_vector_t`. The `add_vertices()` function now takes an `igraph_integer_t` for the vertex count instead of a `long int`. The `combine_vertices()` and `combine_edges()` functions now take an `igraph_vector_ptr_t` containing vectors of type `igraph_vector_int_t` in their `merges` parameters. The `get_info()` function now uses `igraph_vector_int_t` to return the types of the graph, vertex and edge attribute types. The `permute_vertices()` and `permute_edges()` functions in the attribute handler tables now take an `igraph_vector_int_t` instead of an `igraph_vector_t` for the index vectors. These are relevant only to maintainers of higher level interfaces to igraph; they should update their attribute handlers accordingly. +- igraph functions that interface with external libraries such as BLAS or LAPACK may now fail if the underlying BLAS or LAPACK implementation cannot handle the size of input vectors or matrices (BLAS and LAPACK are usually limited to vectors whose size fits in an `int`). `igraph_blas_dgemv()` and `igraph_blas_dgemv_array()` thus now return an `igraph_error_t`, which may be set to `IGRAPH_EOVERFLOW` if the input vectors or matrices are too large. +- Functions that used an `igraph_vector_t` to represent cluster size and cluster membership now use an `igraph_vector_int_t` instead. These are: + - `igraph_connected_components()` (used to be `igraph_clusters()` in 0.9 and before) + - `igraph_community_eb_get_merges()` + - `igraph_community_edge_betweenness()` + - `igraph_community_fastgreedy()` + - `igraph_community_fluid_communities()` + - `igraph_community_infomap()` + - `igraph_community_label_propagation()` + - `igraph_community_leading_eigenvector()` + - `igraph_community_leiden()` + - `igraph_community_multilevel()` + - `igraph_community_optimal_modularity()` + - `igraph_community_spinglass()` + - `igraph_community_spinglass_single()` + - `igraph_community_to_membership()` + - `igraph_community_walktrap()` + - `igraph_compare_communities()` + - `igraph_le_community_to_membership()` + - `igraph_modularity()` + - `igraph_reindex_membership()` + - `igraph_split_join_distance()` + - `igraph_community_multilevel()` additionally uses a `igraph_matrix_int_t` instead of `igraph_matrix_t()` for its memberships parameter. +- `IGRAPH_TOTAL` was removed from the `igraph_neimode_t` enum; use the equivalent `IGRAPH_ALL` instead. ### Added - - A new integer type, `igraph_uint_t` has been added. This is the unsigned pair of `igraph_integer_t` and they are always consistent in size. - - A new container type, `igraph_vector_list_t` has been added, replacing most uses of `igraph_vector_ptr_t` in the API where it was used to hold a variable-length list of vectors. The type contains `igraph_vector_t` objects, and it is fully memory managed (i.e. its contents do not need to be allocated and destroyed manually). There is also a variant named `igraph_vector_int_list_t` for vectors of `igraph_vector_int_t` objects. - - A new container type, `igraph_matrix_list_t` has been added, replacing most uses of `igraph_vector_ptr_t` in the API where it was used to hold a variable-length list of matrices. The type contains `igraph_matrix_t` objects, and it is fully memory managed (i.e. its contents do not need to be allocated and destroyed manually). - - A new container type, `igraph_graph_list_t` has been added, replacing most uses of `igraph_vector_ptr_t` in the API where it was used to hold a variable-length list of graphs. The type contains `igraph_t` objects, and it is fully memory managed (i.e. its contents do not need to be allocated and destroyed manually). - - The vector container type, `igraph_vector_t`, has been extended with a new variant whose functions all start with `igraph_vector_fortran_int_...`. This vector container can be used for interfacing with Fortran code as it guarantees that the integers in the vector are compatible with Fortran integers. Note that `igraph_vector_int_t` is not suitable any more, as the elements of `igraph_vector_int_t` are of type `igraph_integer_t`, whose size may differ on 32-bit and 64-bit platforms, depending on how igraph was compiled. - - `igraph_adjlist_init_from_inclist()` to create an adjacency list from an already existing incidence list by resolving edge IDs to their corresponding endpoints. This function is useful for algorithms when both an adjacency and an incidence list is needed and they should be in the same order. - - `igraph_almost_equals()` and `igraph_cmp_epsilon()` to compare floating point numbers with a relative tolerance. - - `igraph_betweenness_subset()` and `igraph_edge_betweenness_subset()` calculates betweenness and edge betweenness scores using shortest paths between a subset of vertices only (#1711, thanks to @guyroznb) - - `igraph_blas_dgemm()` to multiply two matrices. - - `igraph_calloc()` and `igraph_realloc()` are now publicly exposed; these functions provide variants of `calloc()` and `realloc()` that can safely be deallocated within igraph functions. - - `igraph_circulant()` to create circulant graphs (#1856, thanks to @Gomango999). - - `igraph_complex_almost_equals()` to compare complex numbers with a relative tolerance. - - `igraph_eccentricity_dijkstra()` finds the longest weighted path length among all shortest paths between a set of vertices. - - `igraph_enter_safelocale()` and `igraph_exit_safelocale()` for temporarily setting the locale to C. Foreign format readers and writers require a locale which uses a decimal point instead of decimal comma. - - `igraph_es_all_between()` to create an edge selector that selects all edges between a pair of vertices. - - `igraph_full_multipartite()` generates full multipartite graphs (a generalization of bipartite graphs to multiple groups). - - `igraph_fundamental_cycles()` computes a fundamental cycle basis (experimental). - - `igraph_generalized_petersen()` to create generalized Petersen graphs (#1844, thanks to @alexsyou). - - `igraph_get_all_eids_between()` returns the IDs of all edges between a pair of vertices. - - `igraph_get_k_shortest_paths()` finds the k shortest paths between a source and a target vertex. - - `igraph_get_laplacian()` and `igraph_get_laplacian_sparse()` return the Laplacian matrix of the graph as a dense or sparse matrix, with various kinds of normalizations. They replace the now-deprecated `igraph_laplacian()` function. This makes the API consistent with `igraph_get_adjacency()` and `igraph_get_adjacency_sparse()`. - - `igraph_get_widest_path()`, `igraph_get_widest_paths()`, `igraph_widest_path_widths_dijkstra()` and `igraph_widest_path_widths_floyd_warshall()` to find widest paths (#1893, thanks to @Gomango999). - - `igraph_graph_center()` finds the central vertices of the graph. The central vertices are the ones having a minimum eccentricity (PR #2084, thanks to @pradkrish). - - `igraph_graph_count()` returns the number of unlabelled graphs on a given number of vertices. It is meant to find the maximum isoclass value. - - `igraph_has_mutual()` checks if a directed graph has any mutual edges. - - `igraph_heap_clear()` and `igraph_heap_min_clear()` remove all elements from an `igraph_heap_t` or an `igraph_heap_min_t`, respectively. - - `igraph_invalidate_cache()` invalidates all cached graph properties, forcing their recomputation next time they are requested. This function should not be needed in everyday usage, but may be useful in debugging and benchmarking. - - `igraph_is_forest()` to check whether a graph is a forest (#1888, thanks to @rohitt28). - - `igraph_is_acyclic()` to check whether a graph is acyclic (#1945, thanks to @borsgeorgica). - - `igraph_is_perfect()` to check whether a graph is a perfect graph (#1730, thanks to @guyroznb). - - `igraph_hub_and_authority_scores()` calculates the hub and authority scores of a graph as a matching pair. - - `igraph_layout_umap()` and `igraph_layout_umap_3d()` to lay out a graph in 2D or 3D space using the UMAP dimensionality reduction algorithm. - - `igraph_local_scan_subset_ecount()` counts the number of edges in induced sugraphs from a subset of vertices. - - `igraph_matrix_view_from_vector()` allows interpreting the data stored in a vector as a matrix of the specified size. - - `igraph_minimum_cycle_basis()` computes an unweighted minimum cycle basis (experimental). - - `igraph_pseudo_diameter()` and `igraph_pseudo_diameter_dijkstra()` to determine a lower bound for the diameter of a graph (unweighted or weighted). - - `igraph_regular_tree()` creates a regular tree where all internal vertices have the same total degree. - - `igraph_rngtype_pcg32` and `igraph_rngtype_pcg64` implement 32-bit and 64-bit variants of the PCG random number generator. - - `igraph_rng_get_pois()` generates random variates from the Poisson distribution. - - `igraph_roots_for_tree_layout()` computes a set of roots suitable for a nice tree layout. - - `igraph_spanner()` calculates a spanner of a graph with a given stretch factor (#1752, thanks to @guyroznb) - - `igraph_sparse_adjacency()` and `igraph_sparse_weighted_adjacency()` constructs graphs from (weighted) sparse matrices. - - `igraph_sparsemat_get()` to retrieve a single element of a sparse matrix. - - `igraph_sparsemat_normalize_rows()` and `igraph_sparsemat_normalize_cols()` to normalize sparse matrices row-wise or column-wise. - - `igraph_stack_capacity()` to query the capacity of a stack. - - `igraph_strvector_capacity()` returns the maximum number of strings that can be stored in a string vector without reallocating the memory block holding the pointers to the individual strings. - - `igraph_strvector_merge()` moves all strings from one string vectors to the end of another without re-allocating them. - - `igraph_strvector_push_back_len()` adds a new string to the end of a string vector and allows the user to specify the length of the string being added. - - `igraph_strvector_reserve()` reserves space for a given number of string pointers in a string vector. - - `igraph_symmetric_tree()` to create a tree with the specified number of branches at each level (#1859, thanks to @YuliYudith and @DoruntinaM). - - `igraph_trussness()` calculates the trussness of each edge in the graph (#1034, thanks to @alexperrone) - - `igraph_turan()` generates Turán graphs (#2088, thanks to @pradkrish) - - `igraph_vector_all_almost_e()`, `igraph_vector_complex_all_almost_e()`, `igraph_matrix_all_almost_e()`, `igraph_matrix_complex_all_almost_e()` for elementwise comparisons of floating point vector and matrices with a relative tolerance. - - `igraph_vector_complex_zapsmall()` and `igraph_matrix_complex_zapsmall()` for replacing small components of complex vector or matrix elements with exact zeros. - - `igraph_vector_lex_cmp_untyped()` and `igraph_vector_colex_cmp_untyped()` for lexicographic and colexicographic comparison of vectors, similarly to `igraph_vector_lex_cmp()` and `igraph_vector_colex_cmp()`. The difference between the two variants is that the untyped versions declare the vectors as `const void*`, making the functions suitable as comparators for `qsort()`. - - `igraph_vector_permute()` functions to permute a vector based on an index vector. - - `igraph_vector_ptr_sort_ind()` to obtain an index vector that would sort a vector of pointers based on some comparison function. - - `igraph_vector_range()` to fill an existing vector with a range of increasing numbers. - - `igraph_vector_remove_fast()` functions to remove an item from a vector by swapping it with the last element and then popping it off. It allows one to remove an item from a vector in constant time if the order of items does not matter. - - `igraph_vertex_path_from_edge_path()` converts a sequence of edge IDs representing a path to an equivalent sequence of vertex IDs that represent the vertices the path travelled through. - - `igraph_vs_range()`, `igraph_vss_range()`, `igraph_es_range()` and `igraph_ess_range()` creates vertex and edge sequences from C-style intervals (closed from the left, open from the right). - - `igraph_wheel()` to create a wheel graph (#1938, thanks to @kwofach). +- A new integer type, `igraph_uint_t` has been added. This is the unsigned pair of `igraph_integer_t` and they are always consistent in size. +- A new container type, `igraph_vector_list_t` has been added, replacing most uses of `igraph_vector_ptr_t` in the API where it was used to hold a variable-length list of vectors. The type contains `igraph_vector_t` objects, and it is fully memory managed (i.e. its contents do not need to be allocated and destroyed manually). There is also a variant named `igraph_vector_int_list_t` for vectors of `igraph_vector_int_t` objects. +- A new container type, `igraph_matrix_list_t` has been added, replacing most uses of `igraph_vector_ptr_t` in the API where it was used to hold a variable-length list of matrices. The type contains `igraph_matrix_t` objects, and it is fully memory managed (i.e. its contents do not need to be allocated and destroyed manually). +- A new container type, `igraph_graph_list_t` has been added, replacing most uses of `igraph_vector_ptr_t` in the API where it was used to hold a variable-length list of graphs. The type contains `igraph_t` objects, and it is fully memory managed (i.e. its contents do not need to be allocated and destroyed manually). +- The vector container type, `igraph_vector_t`, has been extended with a new variant whose functions all start with `igraph_vector_fortran_int_...`. This vector container can be used for interfacing with Fortran code as it guarantees that the integers in the vector are compatible with Fortran integers. Note that `igraph_vector_int_t` is not suitable any more, as the elements of `igraph_vector_int_t` are of type `igraph_integer_t`, whose size may differ on 32-bit and 64-bit platforms, depending on how igraph was compiled. +- `igraph_adjlist_init_from_inclist()` to create an adjacency list from an already existing incidence list by resolving edge IDs to their corresponding endpoints. This function is useful for algorithms when both an adjacency and an incidence list is needed and they should be in the same order. +- `igraph_almost_equals()` and `igraph_cmp_epsilon()` to compare floating point numbers with a relative tolerance. +- `igraph_betweenness_subset()` and `igraph_edge_betweenness_subset()` calculates betweenness and edge betweenness scores using shortest paths between a subset of vertices only (#1711, thanks to @guyroznb) +- `igraph_blas_dgemm()` to multiply two matrices. +- `igraph_calloc()` and `igraph_realloc()` are now publicly exposed; these functions provide variants of `calloc()` and `realloc()` that can safely be deallocated within igraph functions. +- `igraph_circulant()` to create circulant graphs (#1856, thanks to @Gomango999). +- `igraph_complex_almost_equals()` to compare complex numbers with a relative tolerance. +- `igraph_eccentricity_dijkstra()` finds the longest weighted path length among all shortest paths between a set of vertices. +- `igraph_enter_safelocale()` and `igraph_exit_safelocale()` for temporarily setting the locale to C. Foreign format readers and writers require a locale which uses a decimal point instead of decimal comma. +- `igraph_es_all_between()` to create an edge selector that selects all edges between a pair of vertices. +- `igraph_full_multipartite()` generates full multipartite graphs (a generalization of bipartite graphs to multiple groups). +- `igraph_fundamental_cycles()` computes a fundamental cycle basis (experimental). +- `igraph_generalized_petersen()` to create generalized Petersen graphs (#1844, thanks to @alexsyou). +- `igraph_get_all_eids_between()` returns the IDs of all edges between a pair of vertices. +- `igraph_get_k_shortest_paths()` finds the k shortest paths between a source and a target vertex. +- `igraph_get_laplacian()` and `igraph_get_laplacian_sparse()` return the Laplacian matrix of the graph as a dense or sparse matrix, with various kinds of normalizations. They replace the now-deprecated `igraph_laplacian()` function. This makes the API consistent with `igraph_get_adjacency()` and `igraph_get_adjacency_sparse()`. +- `igraph_get_widest_path()`, `igraph_get_widest_paths()`, `igraph_widest_path_widths_dijkstra()` and `igraph_widest_path_widths_floyd_warshall()` to find widest paths (#1893, thanks to @Gomango999). +- `igraph_graph_center()` finds the central vertices of the graph. The central vertices are the ones having a minimum eccentricity (PR #2084, thanks to @pradkrish). +- `igraph_graph_count()` returns the number of unlabelled graphs on a given number of vertices. It is meant to find the maximum isoclass value. +- `igraph_has_mutual()` checks if a directed graph has any mutual edges. +- `igraph_heap_clear()` and `igraph_heap_min_clear()` remove all elements from an `igraph_heap_t` or an `igraph_heap_min_t`, respectively. +- `igraph_invalidate_cache()` invalidates all cached graph properties, forcing their recomputation next time they are requested. This function should not be needed in everyday usage, but may be useful in debugging and benchmarking. +- `igraph_is_forest()` to check whether a graph is a forest (#1888, thanks to @rohitt28). +- `igraph_is_acyclic()` to check whether a graph is acyclic (#1945, thanks to @borsgeorgica). +- `igraph_is_perfect()` to check whether a graph is a perfect graph (#1730, thanks to @guyroznb). +- `igraph_hub_and_authority_scores()` calculates the hub and authority scores of a graph as a matching pair. +- `igraph_layout_umap()` and `igraph_layout_umap_3d()` to lay out a graph in 2D or 3D space using the UMAP dimensionality reduction algorithm. +- `igraph_local_scan_subset_ecount()` counts the number of edges in induced sugraphs from a subset of vertices. +- `igraph_matrix_view_from_vector()` allows interpreting the data stored in a vector as a matrix of the specified size. +- `igraph_minimum_cycle_basis()` computes an unweighted minimum cycle basis (experimental). +- `igraph_pseudo_diameter()` and `igraph_pseudo_diameter_dijkstra()` to determine a lower bound for the diameter of a graph (unweighted or weighted). +- `igraph_regular_tree()` creates a regular tree where all internal vertices have the same total degree. +- `igraph_rngtype_pcg32` and `igraph_rngtype_pcg64` implement 32-bit and 64-bit variants of the PCG random number generator. +- `igraph_rng_get_pois()` generates random variates from the Poisson distribution. +- `igraph_roots_for_tree_layout()` computes a set of roots suitable for a nice tree layout. +- `igraph_spanner()` calculates a spanner of a graph with a given stretch factor (#1752, thanks to @guyroznb) +- `igraph_sparse_adjacency()` and `igraph_sparse_weighted_adjacency()` constructs graphs from (weighted) sparse matrices. +- `igraph_sparsemat_get()` to retrieve a single element of a sparse matrix. +- `igraph_sparsemat_normalize_rows()` and `igraph_sparsemat_normalize_cols()` to normalize sparse matrices row-wise or column-wise. +- `igraph_stack_capacity()` to query the capacity of a stack. +- `igraph_strvector_capacity()` returns the maximum number of strings that can be stored in a string vector without reallocating the memory block holding the pointers to the individual strings. +- `igraph_strvector_merge()` moves all strings from one string vectors to the end of another without re-allocating them. +- `igraph_strvector_push_back_len()` adds a new string to the end of a string vector and allows the user to specify the length of the string being added. +- `igraph_strvector_reserve()` reserves space for a given number of string pointers in a string vector. +- `igraph_symmetric_tree()` to create a tree with the specified number of branches at each level (#1859, thanks to @YuliYudith and @DoruntinaM). +- `igraph_trussness()` calculates the trussness of each edge in the graph (#1034, thanks to @alexperrone) +- `igraph_turan()` generates Turán graphs (#2088, thanks to @pradkrish) +- `igraph_vector_all_almost_e()`, `igraph_vector_complex_all_almost_e()`, `igraph_matrix_all_almost_e()`, `igraph_matrix_complex_all_almost_e()` for elementwise comparisons of floating point vector and matrices with a relative tolerance. +- `igraph_vector_complex_zapsmall()` and `igraph_matrix_complex_zapsmall()` for replacing small components of complex vector or matrix elements with exact zeros. +- `igraph_vector_lex_cmp_untyped()` and `igraph_vector_colex_cmp_untyped()` for lexicographic and colexicographic comparison of vectors, similarly to `igraph_vector_lex_cmp()` and `igraph_vector_colex_cmp()`. The difference between the two variants is that the untyped versions declare the vectors as `const void*`, making the functions suitable as comparators for `qsort()`. +- `igraph_vector_permute()` functions to permute a vector based on an index vector. +- `igraph_vector_ptr_sort_ind()` to obtain an index vector that would sort a vector of pointers based on some comparison function. +- `igraph_vector_range()` to fill an existing vector with a range of increasing numbers. +- `igraph_vector_remove_fast()` functions to remove an item from a vector by swapping it with the last element and then popping it off. It allows one to remove an item from a vector in constant time if the order of items does not matter. +- `igraph_vertex_path_from_edge_path()` converts a sequence of edge IDs representing a path to an equivalent sequence of vertex IDs that represent the vertices the path travelled through. +- `igraph_vs_range()`, `igraph_vss_range()`, `igraph_es_range()` and `igraph_ess_range()` creates vertex and edge sequences from C-style intervals (closed from the left, open from the right). +- `igraph_wheel()` to create a wheel graph (#1938, thanks to @kwofach). ### Removed - - `igraph_adjlist_remove_duplicate()`, `igraph_betweenness_estimate()`, `igraph_closeness_estimate()`, `igraph_edge_betweenness_estimate()`, `igraph_inclist_remove_duplicate()`, `igraph_is_degree_sequence()` and `igraph_is_graphical_degree_sequence()` were deprecated earlier in 0.9.0 and are now removed in this release. - - `igraph_dnorm()`, `igraph_strvector_move_interval()`, `igraph_strvector_permdelete()` and `igraph_strvector_remove_negidx()` were removed. These are not breaking changes as the functions were never documented, they were only exposed from one of the headers. - - `igraph_eigen_laplacian()`, `igraph_es_fromto()` and `igraph_maximum_matching()` were removed. These are not breaking changes either as the functions were never implemented, they returned an error code unconditionally. +- `igraph_adjlist_remove_duplicate()`, `igraph_betweenness_estimate()`, `igraph_closeness_estimate()`, `igraph_edge_betweenness_estimate()`, `igraph_inclist_remove_duplicate()`, `igraph_is_degree_sequence()` and `igraph_is_graphical_degree_sequence()` were deprecated earlier in 0.9.0 and are now removed in this release. +- `igraph_dnorm()`, `igraph_strvector_move_interval()`, `igraph_strvector_permdelete()` and `igraph_strvector_remove_negidx()` were removed. These are not breaking changes as the functions were never documented, they were only exposed from one of the headers. +- `igraph_eigen_laplacian()`, `igraph_es_fromto()` and `igraph_maximum_matching()` were removed. These are not breaking changes either as the functions were never implemented, they returned an error code unconditionally. ### Changed - - `igraph_degree_sequence_game()` now supports an additional method, `IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE`, an edge-switching MCMC sampler. - - `igraph_get_adjacency()` and `igraph_get_adjacency_sparse()` now count loop edges _twice_ in undirected graphs when using `IGRAPH_GET_ADJACENCY_BOTH`. This is to ensure consistency with `IGRAPH_GET_ADJACENCY_UPPER` and `IGRAPH_GET_ADJACENCY_LOWER` such that the sum of the upper and the lower triangle matrix is equal to the full adjacency matrix even in the presence of loop edges. - - `igraph_matrix_print()` and `igraph_matrix_fprint()` functions now align columns when priting. - - `igraph_read_graph_gml()` now supports graph attributes (in addition to vertex and edge attributes). - - `igraph_read_graph_gml()` now uses NaN as the default numerical attribute values instead of 0. - - The Pajek parser in `igraph_read_graph_pajek()` is now less strict and accepts more files. - - `igraph_ring()` no longer simplifies its result when generating a one- or two-vertex graph. The one-cycle has a self-loop and the undirected two-cycle has parallel edges. - - `igraph_vector_view()` now allows `data` to be `NULL` in the special case when `length == 0`. - - `igraph_version()` no longer returns an error code. - - `igraph_write_graph_gml()` uses the `creator` parameter in a different way: the supplied string is now written into the Creator line as-is instead of being appended to a default value. - - `igraph_write_graph_gml()` skips writing NaN values. These two changes ensure consistent round-tripping. - - `igraph_write_graph_gml()` and `igraph_read_graph_gml()` now have limited support for entity encoding. - - `igraph_write_graph_ncol()` now preserves the edge ordering of the graph when writing an NCOL file. - - igraph functions that take an ARPACK options object now also accept `NULL` in place of an options object, and they will fall back to using a default object provided by `igraph_arpack_options_get_default()`. - - Foreign format readers now present more informative error messages. - - The default tolerance of the zapsmall functions is now `eps^(2/3)` instead of `eps^(1/2)` where eps is the machine epsilon of `igraph_real_t`. - - It is now possible to override the uniform integer and the Poisson samplers in the random number generator interface. +- `igraph_degree_sequence_game()` now supports an additional method, `IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE`, an edge-switching MCMC sampler. +- `igraph_get_adjacency()` and `igraph_get_adjacency_sparse()` now count loop edges _twice_ in undirected graphs when using `IGRAPH_GET_ADJACENCY_BOTH`. This is to ensure consistency with `IGRAPH_GET_ADJACENCY_UPPER` and `IGRAPH_GET_ADJACENCY_LOWER` such that the sum of the upper and the lower triangle matrix is equal to the full adjacency matrix even in the presence of loop edges. +- `igraph_matrix_print()` and `igraph_matrix_fprint()` functions now align columns when priting. +- `igraph_read_graph_gml()` now supports graph attributes (in addition to vertex and edge attributes). +- `igraph_read_graph_gml()` now uses NaN as the default numerical attribute values instead of 0. +- The Pajek parser in `igraph_read_graph_pajek()` is now less strict and accepts more files. +- `igraph_ring()` no longer simplifies its result when generating a one- or two-vertex graph. The one-cycle has a self-loop and the undirected two-cycle has parallel edges. +- `igraph_vector_view()` now allows `data` to be `NULL` in the special case when `length == 0`. +- `igraph_version()` no longer returns an error code. +- `igraph_write_graph_gml()` uses the `creator` parameter in a different way: the supplied string is now written into the Creator line as-is instead of being appended to a default value. +- `igraph_write_graph_gml()` skips writing NaN values. These two changes ensure consistent round-tripping. +- `igraph_write_graph_gml()` and `igraph_read_graph_gml()` now have limited support for entity encoding. +- `igraph_write_graph_ncol()` now preserves the edge ordering of the graph when writing an NCOL file. +- igraph functions that take an ARPACK options object now also accept `NULL` in place of an options object, and they will fall back to using a default object provided by `igraph_arpack_options_get_default()`. +- Foreign format readers now present more informative error messages. +- The default tolerance of the zapsmall functions is now `eps^(2/3)` instead of `eps^(1/2)` where eps is the machine epsilon of `igraph_real_t`. +- It is now possible to override the uniform integer and the Poisson samplers in the random number generator interface. ### Fixed - - When an error occurs during parsing DL, GML, NCOL, LGL or Pajek files, line numbers are now reported correctly. - - The GraphML parser does not print to stderr any more in case of encoding errors and other error conditions originating from the underlying `libxml2` library. - - The GraphML parser would omit some edges and vertices when reading files with custom attribute types, such as those produced by yEd. This is now corrected. - - The GML parser no longer mixes up Inf and NaN and -Inf now works. - - The GML parser now supports nodes with no id field. - - The GML parser now performs more stringent checks on the input file, such as verifying that `id`, `source`, `target` and `directed` fields are not duplicated. - - The core data structures (vector, etc.) have overflow checks now. - - Deterministic graph generators, as well as most random ones, have overflow checks now. - - Graphs no longer lose all their attributes after calling `igraph_contract_vertices()`. - - `igraph_hrg_init()` does not throw an assertion error anymore for zero vertices. - - `igraph_matrix_complex_create()` and `igraph_matrix_complex_create_polar()` now set their sizes correctly. - - `igraph_random_walk()` took one fewer steps than specified. - - `igraph_sparsemat_getelements_sorted()` did not sort the elements for triplet matrices correctly; this is fixed now. - - `igraph_write_graph_gml()` no longer produces corrupt output when some string attribute values contain `"` characters. +- When an error occurs during parsing DL, GML, NCOL, LGL or Pajek files, line numbers are now reported correctly. +- The GraphML parser does not print to stderr any more in case of encoding errors and other error conditions originating from the underlying `libxml2` library. +- The GraphML parser would omit some edges and vertices when reading files with custom attribute types, such as those produced by yEd. This is now corrected. +- The GML parser no longer mixes up Inf and NaN and -Inf now works. +- The GML parser now supports nodes with no id field. +- The GML parser now performs more stringent checks on the input file, such as verifying that `id`, `source`, `target` and `directed` fields are not duplicated. +- The core data structures (vector, etc.) have overflow checks now. +- Deterministic graph generators, as well as most random ones, have overflow checks now. +- Graphs no longer lose all their attributes after calling `igraph_contract_vertices()`. +- `igraph_hrg_init()` does not throw an assertion error anymore for zero vertices. +- `igraph_matrix_complex_create()` and `igraph_matrix_complex_create_polar()` now set their sizes correctly. +- `igraph_random_walk()` took one fewer steps than specified. +- `igraph_sparsemat_getelements_sorted()` did not sort the elements for triplet matrices correctly; this is fixed now. +- `igraph_write_graph_gml()` no longer produces corrupt output when some string attribute values contain `"` characters. ### Deprecated - - `igraph_clusters()` has been renamed to `igraph_connected_components()`; the old name is deprecated and will be removed in 0.11. - - `igraph_complex_eq_tol()` is now deprecated in favour of `igraph_complex_almost_equals()`. - - `igraph_get_sparsemat()` is deprecated in favour of `igraph_get_adjacency_sparse()`, and will be removed in 0.11. Note that `igraph_get_adjacency_sparse()` takes an _initialized_ sparse matrix as input, unlike `igraph_get_sparsemat()` which takes an uninitialized one. - - `igraph_get_stochastic_sparsemat()` is deprecated in favour of `igraph_get_stochastic_sparse()`, and will be removed in 0.11. Note that `igraph_get_stochastic_sparse()` takes an _initialized_ sparse matrix as input, unlike `igraph_get_stochastic_sparsemat()`, which takes an uninitialized one. - - `igraph_isomorphic_34()` has been deprecated in favour of `igraph_isomorphic()`. Note that `igraph_isomorphic()` calls an optimized version for directed graphs of size 3 and 4, and undirected graphs with 3-6 vertices, so there is no need for a separate function. - - `igraph_laplacian()` is now deprecated; use `igraph_get_laplacian()` or `igraph_get_laplacian_sparse()` depending on whether you need a dense or a sparse matrix. - - `igraph_lattice()` has been renamed to `igraph_square_lattice()` to indicate that this function generates square lattices only. The old name is deprecated and will either be removed in 0.11 or will be changed to become a generic lattice generator that also supports other types of lattices. - - `igraph_local_scan_neighborhood_ecount()` is now deprecated in favour of `igraph_local_scan_subset_ecount()`. - - `igraph_matrix_all_e_tol()` is now deprecated in favour of `igraph_matrix_all_almost_e()`. - - `igraph_matrix_copy()` is now deprecated; use `igraph_matrix_init_copy()` instead. The new name emphasizes that the function _initializes_ the first argument instead of expecting an already-initialized target matrix. The old name will be removed in 0.11. - - `igraph_matrix_e()` and `igraph_matrix_e_ptr()` have been renamed to `igraph_matrix_get()` and `igraph_matrix_get_ptr()`. The old names are deprecated and will be removed in 0.11. +- `igraph_clusters()` has been renamed to `igraph_connected_components()`; the old name is deprecated and will be removed in 0.11. +- `igraph_complex_eq_tol()` is now deprecated in favour of `igraph_complex_almost_equals()`. +- `igraph_get_sparsemat()` is deprecated in favour of `igraph_get_adjacency_sparse()`, and will be removed in 0.11. Note that `igraph_get_adjacency_sparse()` takes an _initialized_ sparse matrix as input, unlike `igraph_get_sparsemat()` which takes an uninitialized one. +- `igraph_get_stochastic_sparsemat()` is deprecated in favour of `igraph_get_stochastic_sparse()`, and will be removed in 0.11. Note that `igraph_get_stochastic_sparse()` takes an _initialized_ sparse matrix as input, unlike `igraph_get_stochastic_sparsemat()`, which takes an uninitialized one. +- `igraph_isomorphic_34()` has been deprecated in favour of `igraph_isomorphic()`. Note that `igraph_isomorphic()` calls an optimized version for directed graphs of size 3 and 4, and undirected graphs with 3-6 vertices, so there is no need for a separate function. +- `igraph_laplacian()` is now deprecated; use `igraph_get_laplacian()` or `igraph_get_laplacian_sparse()` depending on whether you need a dense or a sparse matrix. +- `igraph_lattice()` has been renamed to `igraph_square_lattice()` to indicate that this function generates square lattices only. The old name is deprecated and will either be removed in 0.11 or will be changed to become a generic lattice generator that also supports other types of lattices. +- `igraph_local_scan_neighborhood_ecount()` is now deprecated in favour of `igraph_local_scan_subset_ecount()`. +- `igraph_matrix_all_e_tol()` is now deprecated in favour of `igraph_matrix_all_almost_e()`. +- `igraph_matrix_copy()` is now deprecated; use `igraph_matrix_init_copy()` instead. The new name emphasizes that the function _initializes_ the first argument instead of expecting an already-initialized target matrix. The old name will be removed in 0.11. +- `igraph_matrix_e()` and `igraph_matrix_e_ptr()` have been renamed to `igraph_matrix_get()` and `igraph_matrix_get_ptr()`. The old names are deprecated and will be removed in 0.11. - `igraph_random_edge_walk()` has been deprecated by `igraph_random_walk()` to support edges and/or vertices for the random walk in a single function. It will be removed in 0.11. - - `igraph_read_graph_dimacs()` has been renamed to `igraph_read_graph_dimacs_flow()`; the old name is deprecated and might be re-used as a generic DIMACS reader in the future. Also, the function now uses `igraph_integer_t` as the source and target vertex IDs instead of a `long int`. - - `igraph_shortest_paths()` and related functions were renamed to `igraph_distances()`; the old name was unfortunate because these functions calculated _path lengths_ only and not the paths themselves. The old names are deprecated and will be removed in 0.11. - - `igraph_sparsemat_copy()`, `igraph_sparsemat_diag()` and `igraph_sparsemat_eye()` have been renamed to `igraph_sparsemat_init_copy()`, `igraph_sparsemat_init_diag()` and `igraph_sparsemat_init_eye()` to indicate that they _initialize_ a new sparse matrix. The old names are deprecated and will be removed in 0.11. - - `igraph_strvector_add()` has been renamed to `igraph_strvector_push_back()` for sake of consistency with other vector-like data structures; the old name is deprecated and will be removed in 0.11. - - `igraph_strvector_copy()` has been renamed to `igraph_strvector_init_copy()` for sake of consistency with other vector-like data structures; the old name is deprecated and will be removed in 0.11. - - `igraph_strvector_get()` now returns a `const char*` and not a `char*` to indicate that you are not supposed to modify the string in the vector directly. If you do want to modify it and you are aware of the implications (i.e. the new string must not be longer than the original one), you can cast away the constness of the return value before modifying it. - - `igraph_strvector_set2()` has been renamed to `igraph_strvector_set_len()`; the old name is deprecated and will be removed in 0.11. - - `igraph_tree()` has been renamed to `igraph_kary_tree()`; the old name is deprecated and will be removed in 0.11. - - `igraph_vector_e()` and `igraph_vector_e_ptr()` have been renamed to `igraph_vector_get()` and `igraph_vector_get_ptr()`. The old names are deprecated and will be removed in 0.11. - - `igraph_vector_e_tol()` is now deprecated in favour of `igraph_vector_all_almost_e()`. - - `igraph_vector_copy()` is now deprecated; use `igraph_vector_init_copy()` instead. The new name emphasizes that the function _initializes_ the first argument instead of expecting an already-initialized target vector. The old name will be removed in 0.11. - - `igraph_vector_init_seq()` is now deprecated in favour of `igraph_vector_init_range()`, which uses C-style intervals (closed from the left and open from the right). - - `igraph_vs_seq()`, `igraph_vss_seq()`, `igraph_es_seq()` and `igraph_ess_seq()` are now deprecated in favour of `igraph_vs_range()`, `igraph_vss_range()`, `igraph_es_range()` and `igraph_ess_range()` because these use C-style intervals (closed from the left, open from the right). - - `igraph_write_graph_dimacs()` has been renamed to `igraph_write_graph_dimacs_flow()`; the old name is deprecated and might be re-used as a generic DIMACS writer in the future. Also, the function now uses `igraph_integer_t` as the source and target vertex IDs instead of a `long int`. - - `igraph_zeroin()` is deprecated and will be removed in 0.11, with no replacement. The function is not graph-related and was never part of the public API. - - The macros `igraph_Calloc`, `igraph_Realloc` and `igraph_Free` have been deprecated in favour of `IGRAPH_CALLOC`, `IGRAPH_REALLOC` and `IGRAPH_FREE` to simplify the API. The deprecated variants will be removed in 0.11. +- `igraph_sparsemat_copy()`, `igraph_sparsemat_diag()` and `igraph_sparsemat_eye()` have been renamed to `igraph_sparsemat_init_copy()`, `igraph_sparsemat_init_diag()` and `igraph_sparsemat_init_eye()` to indicate that they _initialize_ a new sparse matrix. The old names are deprecated and will be removed in 0.11. +- `igraph_strvector_add()` has been renamed to `igraph_strvector_push_back()` for sake of consistency with other vector-like data structures; the old name is deprecated and will be removed in 0.11. +- `igraph_strvector_copy()` has been renamed to `igraph_strvector_init_copy()` for sake of consistency with other vector-like data structures; the old name is deprecated and will be removed in 0.11. +- `igraph_strvector_get()` now returns a `const char*` and not a `char*` to indicate that you are not supposed to modify the string in the vector directly. If you do want to modify it and you are aware of the implications (i.e. the new string must not be longer than the original one), you can cast away the constness of the return value before modifying it. +- `igraph_strvector_set2()` has been renamed to `igraph_strvector_set_len()`; the old name is deprecated and will be removed in 0.11. +- `igraph_tree()` has been renamed to `igraph_kary_tree()`; the old name is deprecated and will be removed in 0.11. +- `igraph_vector_e()` and `igraph_vector_e_ptr()` have been renamed to `igraph_vector_get()` and `igraph_vector_get_ptr()`. The old names are deprecated and will be removed in 0.11. +- `igraph_vector_e_tol()` is now deprecated in favour of `igraph_vector_all_almost_e()`. +- `igraph_vector_copy()` is now deprecated; use `igraph_vector_init_copy()` instead. The new name emphasizes that the function _initializes_ the first argument instead of expecting an already-initialized target vector. The old name will be removed in 0.11. +- `igraph_vector_init_seq()` is now deprecated in favour of `igraph_vector_init_range()`, which uses C-style intervals (closed from the left and open from the right). +- `igraph_vs_seq()`, `igraph_vss_seq()`, `igraph_es_seq()` and `igraph_ess_seq()` are now deprecated in favour of `igraph_vs_range()`, `igraph_vss_range()`, `igraph_es_range()` and `igraph_ess_range()` because these use C-style intervals (closed from the left, open from the right). +- `igraph_write_graph_dimacs()` has been renamed to `igraph_write_graph_dimacs_flow()`; the old name is deprecated and might be re-used as a generic DIMACS writer in the future. Also, the function now uses `igraph_integer_t` as the source and target vertex IDs instead of a `long int`. +- `igraph_zeroin()` is deprecated and will be removed in 0.11, with no replacement. The function is not graph-related and was never part of the public API. +- The macros `igraph_Calloc`, `igraph_Realloc` and `igraph_Free` have been deprecated in favour of `IGRAPH_CALLOC`, `IGRAPH_REALLOC` and `IGRAPH_FREE` to simplify the API. The deprecated variants will be removed in 0.11. ### Other - - Documentation improvements. - - Support for Intel's LLVM-based compiler. +- Documentation improvements. +- Support for Intel's LLVM-based compiler. ## [0.9.10] - 2022-09-02 ### Added - - `igraph_reverse_edges()` reverses the specified edges in the graph while preserving all attributes. +- `igraph_reverse_edges()` reverses the specified edges in the graph while preserving all attributes. ### Changed - - The `IGRAPH_ARPACK_PROD` error code is no longer used. Instead, the specific error encountered while doing matrix multiplication is reported. - - XML external entities are not resolved any more when parsing GraphML files to prevent XML external entity injection (XXE) attacks. Standard XML entities like `<` or `"` still work. +- The `IGRAPH_ARPACK_PROD` error code is no longer used. Instead, the specific error encountered while doing matrix multiplication is reported. +- XML external entities are not resolved any more when parsing GraphML files to prevent XML external entity injection (XXE) attacks. Standard XML entities like `<` or `"` still work. ### Fixed - - Fixed incorrect results from `igraph_local_scan_1_ecount()` when the graph was directed but the mode was `IGRAPH_ALL` and some nodes had loop edges. See issue #2092. - - Fixed incorrect counting of self-loops in `igraph_local_scan_neighborhood_ecount()` when the graph was undirected. - - In some rare edge cases, `igraph_pagerank()` with the ARPACK method and `igraph_hub_score()` / `igraph_authority_score()` could return incorrect results. The problem could be detected by checking that the returned eigenvalue is not negative. See issue #2090. - - `igraph_permute_vertices()` now checks for out-of-range indices and duplicates in the permutation vector. - - `igraph_create()` now checks for non-finite vertex indices in the edges vector. - - `igraph_eigenvector_centrality()` would return incorrect scores when some weights were negative. - - `igraph_es_seq()` and `igraph_ess_seq()` did not include the `to` vertex in the sequence. - - `igraph_eit_create()` and `igraph_vit_create()` now check that all edge/vertex indices are in range when creating iterators from sequence-type selectors. - - `igraph_grg_game()` now validates its arguments. - - `igraph_layout_drl()` and its 3D version now validate their inputs. - - `igraph_layout_kamada_kawai()`, `igraph_layout_fruchterman_reingold()`, `igraph_layout_drl()`, as well as their 3D versions now check for non-positive weights. - - `igraph_asymmetric_preference_game()` interpreted its `type_dist_matrix` argument incorrectly. - - Fixed incorrect result of `igraph_community_spinglass()` for null and singleton graphs. - - `igraph_layout_gem()` does not crash any more for graphs with only a single vertex. - - `igraph_bridges()` no longer uses recursion and thus is no longer prone to stack overflow. - - Include paths of dependent packages would be specified incorrectly in some environments. +- Fixed incorrect results from `igraph_local_scan_1_ecount()` when the graph was directed but the mode was `IGRAPH_ALL` and some nodes had loop edges. See issue #2092. +- Fixed incorrect counting of self-loops in `igraph_local_scan_neighborhood_ecount()` when the graph was undirected. +- In some rare edge cases, `igraph_pagerank()` with the ARPACK method and `igraph_hub_score()` / `igraph_authority_score()` could return incorrect results. The problem could be detected by checking that the returned eigenvalue is not negative. See issue #2090. +- `igraph_permute_vertices()` now checks for out-of-range indices and duplicates in the permutation vector. +- `igraph_create()` now checks for non-finite vertex indices in the edges vector. +- `igraph_eigenvector_centrality()` would return incorrect scores when some weights were negative. +- `igraph_es_seq()` and `igraph_ess_seq()` did not include the `to` vertex in the sequence. +- `igraph_eit_create()` and `igraph_vit_create()` now check that all edge/vertex indices are in range when creating iterators from sequence-type selectors. +- `igraph_grg_game()` now validates its arguments. +- `igraph_layout_drl()` and its 3D version now validate their inputs. +- `igraph_layout_kamada_kawai()`, `igraph_layout_fruchterman_reingold()`, `igraph_layout_drl()`, as well as their 3D versions now check for non-positive weights. +- `igraph_asymmetric_preference_game()` interpreted its `type_dist_matrix` argument incorrectly. +- Fixed incorrect result of `igraph_community_spinglass()` for null and singleton graphs. +- `igraph_layout_gem()` does not crash any more for graphs with only a single vertex. +- `igraph_bridges()` no longer uses recursion and thus is no longer prone to stack overflow. +- Include paths of dependent packages would be specified incorrectly in some environments. ### Other - - Documentation improvements. +- Documentation improvements. ## [0.9.9] - 2022-06-04 ### Changed - - `igraph_community_walktrap()` now uses double precision floating point operations internally instead of single precision. - - In `igraph_community_leiden()`, the `nb_clusters` output parameter is now optional (i.e. it can be `NULL`). - - `igraph_read_graph_graphml()` no longer attempts to temporarily set the C locale, and will therefore not work correctly if the current locale uses a decimal comma. +- `igraph_community_walktrap()` now uses double precision floating point operations internally instead of single precision. +- In `igraph_community_leiden()`, the `nb_clusters` output parameter is now optional (i.e. it can be `NULL`). +- `igraph_read_graph_graphml()` no longer attempts to temporarily set the C locale, and will therefore not work correctly if the current locale uses a decimal comma. ### Fixed - - `igraph_community_walktrap()` would return an invalid `modularity` vector when the `merges` matrix was not requested. - - `igraph_community_walktrap()` would return a `modularity` vector that was too long for disconnected graphs. This would cause a failure in some weighted graphs when the `membership` vector was requested. - - `igraph_community_walktrap()` now checks the weight vector: only non-negative weights are accepted, and all vertices must have non-zero strength. - - `igraph_community_walktrap()` now returns a modularity score of NaN for graphs with no edges. - - `igraph_community_fast_greedy()` now returns a modularity score of NaN for graphs with no edges. - - `igraph_community_edge_betweenness()` now returns a modularity vector with a single NaN entry for graph with no edges. Previously it returned a zero-length vector. - - `igraph_community_leading_eigenvector()` does not ignore non-ARPACK-related errors from `igraph_arpack_rssolve()` any more. - - `igraph_preference_game()` now works correctly when `fixed_size` is true and +- `igraph_community_walktrap()` would return an invalid `modularity` vector when the `merges` matrix was not requested. +- `igraph_community_walktrap()` would return a `modularity` vector that was too long for disconnected graphs. This would cause a failure in some weighted graphs when the `membership` vector was requested. +- `igraph_community_walktrap()` now checks the weight vector: only non-negative weights are accepted, and all vertices must have non-zero strength. +- `igraph_community_walktrap()` now returns a modularity score of NaN for graphs with no edges. +- `igraph_community_fast_greedy()` now returns a modularity score of NaN for graphs with no edges. +- `igraph_community_edge_betweenness()` now returns a modularity vector with a single NaN entry for graph with no edges. Previously it returned a zero-length vector. +- `igraph_community_leading_eigenvector()` does not ignore non-ARPACK-related errors from `igraph_arpack_rssolve()` any more. +- `igraph_preference_game()` now works correctly when `fixed_size` is true and `type_dist` is not given; earlier versions had a bug where more than half of the vertices mistakenly ended up in group 0. - - Fixed a memory leak in `igraph_hrg_fit()` when using `start=1`. - - `igraph_write_graph_dot()` now outputs NaN values unchanged. - - `igraph_write_graph_dot()` no longer produces invalid DOT files when empty string attributes are present. - - `igraph_layout_fruchterman_reingold()` and `igraph_layout_kamada_kawai()`, as well as their 3D versions, did not respect vertex coordinate bounds (`xmin`, `xmax`, etc.) when minimum values were large or maximum values were small. This is now fixed. - - The initial coordinates of the Kamada-Kawai layout (`igraph_layout_kamada_kawai()` and `igraph_layout_kamada_kawai_3d()`) are chosen to be more in line with the original publication, improving the stability of the result. See isse #963. This changes the output of the function for the same graph, compared with previous versions. To obtain the same layout, initialize coordinates with `igraph_layout_circle()` (in 2D) or `igraph_layout_sphere()` (in 3D). - - Improved numerical stability in Kamada-Kawai layout. - - Corrected a problem in the calculation of displacements in `igraph_layout_fruchterman_reingold()` and its 3D version. This fixes using the "grid" variant of the algorithm on disconnected graphs. - - `igraph_sumtree_search()` would consider search intervals open on the left and closed on the right, contrary to the documentation. This is now corrected to closed on the left and open on the right. In some cases this lead to a zero-weight element being returned for a zero search value. See issue #2080. +- Fixed a memory leak in `igraph_hrg_fit()` when using `start=1`. +- `igraph_write_graph_dot()` now outputs NaN values unchanged. +- `igraph_write_graph_dot()` no longer produces invalid DOT files when empty string attributes are present. +- `igraph_layout_fruchterman_reingold()` and `igraph_layout_kamada_kawai()`, as well as their 3D versions, did not respect vertex coordinate bounds (`xmin`, `xmax`, etc.) when minimum values were large or maximum values were small. This is now fixed. +- The initial coordinates of the Kamada-Kawai layout (`igraph_layout_kamada_kawai()` and `igraph_layout_kamada_kawai_3d()`) are chosen to be more in line with the original publication, improving the stability of the result. See isse #963. This changes the output of the function for the same graph, compared with previous versions. To obtain the same layout, initialize coordinates with `igraph_layout_circle()` (in 2D) or `igraph_layout_sphere()` (in 3D). +- Improved numerical stability in Kamada-Kawai layout. +- Corrected a problem in the calculation of displacements in `igraph_layout_fruchterman_reingold()` and its 3D version. This fixes using the "grid" variant of the algorithm on disconnected graphs. +- `igraph_sumtree_search()` would consider search intervals open on the left and closed on the right, contrary to the documentation. This is now corrected to closed on the left and open on the right. In some cases this lead to a zero-weight element being returned for a zero search value. See issue #2080. ### Other - - Greatly improved error reporting from foregin format parsers. - - Documentation improvements. +- Greatly improved error reporting from foregin format parsers. +- Documentation improvements. ## [0.9.8] - 2022-04-08 ### Fixed - - Assertion failure in `igraph_bfs()` when an empty `roots` or `restricted` vector was provided. - - `igraph_diversity()` now returns 0 for degree-1 vertices. Previously it incorrectly returned NaN or +-Inf depending on roundoff errors. - - `igraph_community_walktrap()` does not crash any more when provided with +- Assertion failure in `igraph_bfs()` when an empty `roots` or `restricted` vector was provided. +- `igraph_diversity()` now returns 0 for degree-1 vertices. Previously it incorrectly returned NaN or +-Inf depending on roundoff errors. +- `igraph_community_walktrap()` does not crash any more when provided with `modularity=NULL` and `membership=NULL`. ### Other - - Documentation improvements. +- Documentation improvements. ## [0.9.7] - 2022-03-16 ### Changed - - `igraph_get_all_shortest_paths_dijsktra()` now uses tolerances when comparing path +- `igraph_get_all_shortest_paths_dijsktra()` now uses tolerances when comparing path lengths, and is thus robust to numerical roundoff errors. - - `igraph_vector_*_swap` and `igraph_matrix_swap` now take O(1) instead of O(n) and accept all sizes. +- `igraph_vector_*_swap` and `igraph_matrix_swap` now take O(1) instead of O(n) and accept all sizes. ### Fixed - - NCOL and LGL format writers no longer accept "name" and "weight" attributes +- NCOL and LGL format writers no longer accept "name" and "weight" attributes of invalid types. - - The LGL writer could not access numerical weight attributes, potentially leading +- The LGL writer could not access numerical weight attributes, potentially leading to crashes. - - External PLFIT libraries and their headers are now detected at their standard +- External PLFIT libraries and their headers are now detected at their standard installation location. - - `igraph_vector_init()` no longer accepts negative vector sizes. - - `igraph_assortativity_nominal()` crashed on the null graph. - - Label propagation now ensures that all labels are dominant. - - Fixed incorrect partition results for walktrap algorithm (issue #1927) - - Negative values returned by `igraph_rng_get_integer()` and `RNG_INTEGER()` were incorrect, +- `igraph_vector_init()` no longer accepts negative vector sizes. +- `igraph_assortativity_nominal()` crashed on the null graph. +- Label propagation now ensures that all labels are dominant. +- Fixed incorrect partition results for walktrap algorithm (issue #1927) +- Negative values returned by `igraph_rng_get_integer()` and `RNG_INTEGER()` were incorrect, one larger than they should have been. - - `igraph_community_walktrap()` now checks its `steps` input argument. - - The first modularity value reported by `igraph_community_walktrap()` was +- `igraph_community_walktrap()` now checks its `steps` input argument. +- The first modularity value reported by `igraph_community_walktrap()` was incorrect (it was always zero). This is now fixed. - - `igraph_correlated_game()` would return incorrect results, or exhaust the memory, +- `igraph_correlated_game()` would return incorrect results, or exhaust the memory, for most input graphs that were not generated with `igraph_erdos_renyi_game_gnp()`. - - `igraph_community_label_propagation` incorrectly did not result in all labels being dominant (issue #1963, fixed in PR #1966). +- `igraph_community_label_propagation` incorrectly did not result in all labels being dominant (issue #1963, fixed in PR #1966). ### Other - - The C attribute handler now verifies attribute types when retrieving attributes. - - Documentation improvements. +- The C attribute handler now verifies attribute types when retrieving attributes. +- Documentation improvements. ## [0.9.6] - 2022-01-05 - - Isomorphism class functions (`igraph_isoclass()`, `igraph_isoclass_subgraph()`, +- Isomorphism class functions (`igraph_isoclass()`, `igraph_isoclass_subgraph()`, `igraph_isoclass_create`) and motif finder functions (`igraph_motifs_randesu()`, `igraph_motifs_randesu_estimate()`, `igraph_motifs_randesu_callback()`) now support undirected (sub)graphs of sizes 5 and 6. Previsouly only sizes 3 and 4 @@ -1164,515 +1286,516 @@ Some of the highlights are: ### Fixed - - igraph would not build with MinGW when using the vendored GLPK and enabling TLS. - - Removed some uses of `abort()` from vendored libraries, which could unexpectedly +- igraph would not build with MinGW when using the vendored GLPK and enabling TLS. +- Removed some uses of `abort()` from vendored libraries, which could unexpectedly shut down the host language of igraph's high-level interfaces. - - `igraph_community_label_propagation()` no longer leaves any vertices unlabeled +- `igraph_community_label_propagation()` no longer leaves any vertices unlabeled when they were not reachable from any labeled ones, i.e. the returned membership vector is guaranteed not to contain negative values (#1853). - - The Kamada-Kawai layout is now interruptible. - - The Fruchterman-Reingold layout is now interruptible. - - Fixed a bug in `igraph_cmp_epsilon()` that resulted in incorrect results for +- The Kamada-Kawai layout is now interruptible. +- The Fruchterman-Reingold layout is now interruptible. +- Fixed a bug in `igraph_cmp_epsilon()` that resulted in incorrect results for edge betweenness calculations in certain rare cases with x87 floating point math when LTO was also enabled (#1894). - - Weighted clique related functions now fall back to the unweighted variants +- Weighted clique related functions now fall back to the unweighted variants when a null vertex weight vector is given to them. - - `igraph_erdos_renyi_game_(gnm|gnp)` would not produce self-loops for the singleton +- `igraph_erdos_renyi_game_(gnm|gnp)` would not produce self-loops for the singleton graph. - - Fixed a bug in `igraph_local_efficiency()` that sometimes erroneously +- Fixed a bug in `igraph_local_efficiency()` that sometimes erroneously reported zero as the local efficiency of a vertex in directed graphs. - - `igraph_vector_update()` (and its type-specific variants) did not check for +- `igraph_vector_update()` (and its type-specific variants) did not check for memory allocation failure. - - Fixed a potential crash in the GraphML reader that would be triggered by some +- Fixed a potential crash in the GraphML reader that would be triggered by some invalid GraphML files. ### Other - - `igraph_is_tree()` has improved performance and memory usage. - - `igraph_is_connected()` has improved performance when checking weak connectedness. - - Improved error handling in `igraph_maximal_cliques()` and related functions. - - The build system now checks that GLPK is of a compatible version (4.57 or later). - - The vendored `plfit` package was updated to 0.9.3. - - You can now build igraph with an external `plfit` instead of the vendored one. - - Documentation improvements. +- `igraph_is_tree()` has improved performance and memory usage. +- `igraph_is_connected()` has improved performance when checking weak connectedness. +- Improved error handling in `igraph_maximal_cliques()` and related functions. +- The build system now checks that GLPK is of a compatible version (4.57 or later). +- The vendored `plfit` package was updated to 0.9.3. +- You can now build igraph with an external `plfit` instead of the vendored one. +- Documentation improvements. ## [0.9.5] - 2021-11-11 ### Fixed - - `igraph_reindex_membership()` does not allow negative membership indices any more. +- `igraph_reindex_membership()` does not allow negative membership indices any more. - - `igraph_rewire_directed_edges()` now generates multigraphs when edge directions +- `igraph_rewire_directed_edges()` now generates multigraphs when edge directions are ignored, to make it consistent with the directed case. - - Fixed a bug in `igraph_gomory_hu_tree()` that returned only the equivalent flow +- Fixed a bug in `igraph_gomory_hu_tree()` that returned only the equivalent flow tree instead of the cut tree (#1810). - - Fixed a bug in the `IGRAPH_TO_UNDIRECTED_COLLAPSE` mode of +- Fixed a bug in the `IGRAPH_TO_UNDIRECTED_COLLAPSE` mode of `igraph_to_undirected()` that provided an incorrect merge vector to the attribute handler, leading to problems when edge attributes were merged using an attribute combination (#1814). - - Fixed the behaviour of the `IGRAPH_ENABLE_LTO` option when it was set to +- Fixed the behaviour of the `IGRAPH_ENABLE_LTO` option when it was set to `AUTO`; earlier versions had a bug where `AUTO` simply checked whether LTO is supported but then did not use LTO even if it was supported. - - When using igraph from a CMake project, it is now checked that the project has +- When using igraph from a CMake project, it is now checked that the project has the C++ language enabled. This is necessary for linking to igraph with CMake. ### Other - - Improved the root selection method for disconnected graphs in the +- Improved the root selection method for disconnected graphs in the Reingold-Tilford layout (#1836). The new root selection method provides niceer results if the graph is not a tree, although it is still recommended to use the Sugiyama layout instead, unless the input graph is _almost_ a tree, in which case Reingold-Tilfold may still be preferred. - - `igraph_decompose()` is now much faster for large graphs containing many +- `igraph_decompose()` is now much faster for large graphs containing many isolates or small components (#960). - - `igraph_largest_cliques()` and `igraph_clique_number()` were re-written to +- `igraph_largest_cliques()` and `igraph_clique_number()` were re-written to use `igraph_maximal_cliques_callback()` so they are much faster now (#804). - - The vendored GLPK has been upgraded to GLPK 5.0. +- The vendored GLPK has been upgraded to GLPK 5.0. - - Documentation improvements. +- Documentation improvements. ## [0.9.4] - 2021-05-31 ### Changed - - Unweighted transitivity (i.e. clustering coefficient) calculations now ignore multi-edges and edge directions instead of rejecting multigraphs and directed graphs. - - `igraph_transitivity_barrat()` now returns an error code if the input graph has multiple edges (which is not handled correctly by the implementation yet). +- Unweighted transitivity (i.e. clustering coefficient) calculations now ignore multi-edges and edge directions instead of rejecting multigraphs and directed graphs. +- `igraph_transitivity_barrat()` now returns an error code if the input graph has multiple edges (which is not handled correctly by the implementation yet). ### Fixed - - `igraph_local_scan_k_ecount()` now handles loops correctly. - - `igraph_transitivity_avglocal_undirected()` is no longer slower than `igraph_transitivity_local_undirected()`. - - Worked around an invalid warning issued by Clang 9.0 when compiling with OpenMP. +- `igraph_local_scan_k_ecount()` now handles loops correctly. +- `igraph_transitivity_avglocal_undirected()` is no longer slower than `igraph_transitivity_local_undirected()`. +- Worked around an invalid warning issued by Clang 9.0 when compiling with OpenMP. ### Other - - Documentation improvements. +- Documentation improvements. ## [0.9.3] - 2021-05-05 ### Added - - OpenMP is now enabled and used by certain functions (notably PageRank calculation) when the compiler supports it. Set `IGRAPH_OPENMP_SUPPORT=OFF` at configuration time to disable this. +- OpenMP is now enabled and used by certain functions (notably PageRank calculation) when the compiler supports it. Set `IGRAPH_OPENMP_SUPPORT=OFF` at configuration time to disable this. ### Fixed - - `igraph_get_incidence()` no longer reads and writes out of bounds when given a non-bipartite graph, but gives a warning and ignores edges within a part. - - `igraph_dyad_census()` no longer reports an overflow on singleton graphs, and handles loops and multigraphs correctly. Undirected graphs are handled consistently and will no longer give a warning. - - `igraph_vector_lex_cmp()` and `igraph_vector_colex_cmp()` dereferenced their arguments only once instead of twice, and therefore did not work with `igraph_vector_ptr_sort()`. - - `igraph_maximal_cliques_subset()` and `igraph_transitivity_barrat()` corrupted the error handling stack ("finally stack") under some circumstances. - - CMake package files did not respect `CMAKE_INSTALL_LIBDIR`. This only affected Linux distributions which install into `lib64` or other locations instead of `lib`. - - The parser sources could not be generated when igraph was in a location that contained spaces in its path. - - igraph no longer links to the math library (`libm`) when this is not necessary. - - `_CRT_SECURE_NO_WARNINGS` is now defined during compilation to enable compatibility with UWP. - - Fixed a compilation issue on MSYS / MinGW when link-time optimization was enabled and the `MSYS Makefiles` CMake generator was used. Some source files in igraph were renamed as a consequence, but these should not affect users of the library. +- `igraph_get_incidence()` no longer reads and writes out of bounds when given a non-bipartite graph, but gives a warning and ignores edges within a part. +- `igraph_dyad_census()` no longer reports an overflow on singleton graphs, and handles loops and multigraphs correctly. Undirected graphs are handled consistently and will no longer give a warning. +- `igraph_vector_lex_cmp()` and `igraph_vector_colex_cmp()` dereferenced their arguments only once instead of twice, and therefore did not work with `igraph_vector_ptr_sort()`. +- `igraph_maximal_cliques_subset()` and `igraph_transitivity_barrat()` corrupted the error handling stack ("finally stack") under some circumstances. +- CMake package files did not respect `CMAKE_INSTALL_LIBDIR`. This only affected Linux distributions which install into `lib64` or other locations instead of `lib`. +- The parser sources could not be generated when igraph was in a location that contained spaces in its path. +- igraph no longer links to the math library (`libm`) when this is not necessary. +- `_CRT_SECURE_NO_WARNINGS` is now defined during compilation to enable compatibility with UWP. +- Fixed a compilation issue on MSYS / MinGW when link-time optimization was enabled and the `MSYS Makefiles` CMake generator was used. Some source files in igraph were renamed as a consequence, but these should not affect users of the library. ### Deprecated - - `igraph_rng_min()` is now deprecated; assume a constant zero as its return value if you used this function in your own code. +- `igraph_rng_min()` is now deprecated; assume a constant zero as its return value if you used this function in your own code. ### Other - - Updated the vendored CXSparse library to version 3.2.0 +- Updated the vendored CXSparse library to version 3.2.0 ## [0.9.2] - 2021-04-14 ### Added - - CMake package files are now installed with igraph. This allows `find_package(igraph)` to find igraph and detect the appropriate compilation options for projects that link to it. +- CMake package files are now installed with igraph. This allows `find_package(igraph)` to find igraph and detect the appropriate compilation options for projects that link to it. ### Fixed - - igraph can now be used as a CMake subproject in other CMake-based projects. - - The documentaton can now be built from the release tarball. - - Configuration will no longer fail when the release tarball is extracted into a subdirectory of an unrelated git repository. - - The generated pkg-config file was incorrect when `CMAKE_INSTALL_` variables were absolute paths. - - On Unix-like systems, the library name is now `libigraph.so.0.0.0`, as it used to be for igraph 0.8 and earlier. - - Fixed a return type mismatch in parser sources, and fixed some warnings with recent versions of gcc. - - Fixed a bug in `igraph_get_shortest_paths_dijkstra()` and `igraph_get_shortest_paths_bellman_ford()` that returned incorrect results for unreachable vertices. +- igraph can now be used as a CMake subproject in other CMake-based projects. +- The documentaton can now be built from the release tarball. +- Configuration will no longer fail when the release tarball is extracted into a subdirectory of an unrelated git repository. +- The generated pkg-config file was incorrect when `CMAKE_INSTALL_` variables were absolute paths. +- On Unix-like systems, the library name is now `libigraph.so.0.0.0`, as it used to be for igraph 0.8 and earlier. +- Fixed a return type mismatch in parser sources, and fixed some warnings with recent versions of gcc. +- Fixed a bug in `igraph_get_shortest_paths_dijkstra()` and `igraph_get_shortest_paths_bellman_ford()` that returned incorrect results for unreachable vertices. ### Other - - Improved installation instructions and tutorial. +- Improved installation instructions and tutorial. ## [0.9.1] - 2021-03-23 ### Added - - `igraph_vector_lex_cmp()` and `igraph_vector_colex_cmp()` for lexicographic +- `igraph_vector_lex_cmp()` and `igraph_vector_colex_cmp()` for lexicographic and colexicographic comparison of vectors. These functions may also be used for sorting. ### Changed - - `igraph_community_multilevel()` is now randomized (PR #1696, thanks to Daniel Noom). +- `igraph_community_multilevel()` is now randomized (PR #1696, thanks to Daniel Noom). ### Fixed - - CMake settings that controlled the library installation directory name, such as `CMAKE_INSTALL_LIBDIR`, were not respected. - - Under some conditions, the generated pkg-config file contained an incorrect include directory path. - - The following functions were not exported from the shared library: `igraph_subcomponent()`, `igraph_stack_ptr_free_all()`, `igraph_stack_ptr_destroy_all()`, `igraph_status_handler_stderr()`, `igraph_progress_handler_stderr()`. - - Built-in random number generators (`igraph_rngtype_mt19937`, `igraph_rngtype_rand`, `igraph_rngtype_glibc2`) were not exported from the shared library. - - `igraph_layout_graphopt()` no longer rounds the `spring_length` parameter to an integer. - - `igraph_get_all_shortest_paths_dijkstra()` no longer modifies the `res` vector's item destructor. - - `igraph_get_shortest_path_bellman_ford()` did not work correctly when calculating paths to all vertices. - - `igraph_arpack_rnsolve()` checks its parameters more carefully. - - `igraph_community_to_membership()` does not crash anymore when `csize` is requested but `membership` is not. - - `igraph_citing_cited_type_game()`: fixed memory leaks (PR #1700, thanks to Daniel Noom). - - `igraph_transitivity_undirected()`, `igraph_transitivity_avglocal_undirected()` and `igraph_transitivity_barrat()` no longer trigger an assertion failure when used with the null graph (PRs #1709, #1710). - - `igraph_(personalized_)pagerank()` would return incorrect results for weighted multigraphs with fewer than 128 vertices when using `IGRAPH_PAGERANK_ALGO_PRPACK`. - - `igraph_diversity()` now checks its input more carefully, and throws an error when the input graph has multi-edges or is directed. - - `igraph_shortest_paths_johnson()` would return incorrect results when the `to` argument differed from `from` (thanks to Daniel Noom). - - `igraph_is_graphical()` would fail to set the result variable for certain special degree sequences in the undirected simple graph case. - - Non-maximal clique finding functions would sometimes return incomplete results when finding more than 2147483647 (i.e. 2^31 - 1) cliques. - - GLPK internal errors no longer crash igraph. - - Fixed some potential memory leaks that could happen on error conditions or when certain functions were interrupted. - - When testing a DLL build on Windows, the `PATH` was sometimes not set correctly, causing the tests to fail (PR #1692). - - When compiling from the git repository (as opposed to the release tarball), the build would fail with recent versions of `bison` and `flex`. +- CMake settings that controlled the library installation directory name, such as `CMAKE_INSTALL_LIBDIR`, were not respected. +- Under some conditions, the generated pkg-config file contained an incorrect include directory path. +- The following functions were not exported from the shared library: `igraph_subcomponent()`, `igraph_stack_ptr_free_all()`, `igraph_stack_ptr_destroy_all()`, `igraph_status_handler_stderr()`, `igraph_progress_handler_stderr()`. +- Built-in random number generators (`igraph_rngtype_mt19937`, `igraph_rngtype_rand`, `igraph_rngtype_glibc2`) were not exported from the shared library. +- `igraph_layout_graphopt()` no longer rounds the `spring_length` parameter to an integer. +- `igraph_get_all_shortest_paths_dijkstra()` no longer modifies the `res` vector's item destructor. +- `igraph_get_shortest_path_bellman_ford()` did not work correctly when calculating paths to all vertices. +- `igraph_arpack_rnsolve()` checks its parameters more carefully. +- `igraph_community_to_membership()` does not crash anymore when `csize` is requested but `membership` is not. +- `igraph_citing_cited_type_game()`: fixed memory leaks (PR #1700, thanks to Daniel Noom). +- `igraph_transitivity_undirected()`, `igraph_transitivity_avglocal_undirected()` and `igraph_transitivity_barrat()` no longer trigger an assertion failure when used with the null graph (PRs #1709, #1710). +- `igraph_(personalized_)pagerank()` would return incorrect results for weighted multigraphs with fewer than 128 vertices when using `IGRAPH_PAGERANK_ALGO_PRPACK`. +- `igraph_diversity()` now checks its input more carefully, and throws an error when the input graph has multi-edges or is directed. +- `igraph_shortest_paths_johnson()` would return incorrect results when the `to` argument differed from `from` (thanks to Daniel Noom). +- `igraph_is_graphical()` would fail to set the result variable for certain special degree sequences in the undirected simple graph case. +- Non-maximal clique finding functions would sometimes return incomplete results when finding more than 2147483647 (i.e. 2^31 - 1) cliques. +- GLPK internal errors no longer crash igraph. +- Fixed some potential memory leaks that could happen on error conditions or when certain functions were interrupted. +- When testing a DLL build on Windows, the `PATH` was sometimes not set correctly, causing the tests to fail (PR #1692). +- When compiling from the git repository (as opposed to the release tarball), the build would fail with recent versions of `bison` and `flex`. ### Other - - Documentation improvements. - - Much faster documentation builds. - - Allow using a pre-generated `arith.h` header for f2c when cross-compiling; see the Installation section of the documentation. - - The `IGRAPH_ENABLE_LTO` build option now supports the `AUTO` value, which uses LTO only if the compiler supports it. Warning: CMake may not always be able to detect that LTO is not fully supported. Therefore, the default setting is `OFF`. - - The following functions are now interruptible: `igraph_grg_game()`, `igraph_sbm_game()`, `igraph_barabasi_game()`, `igraph_barabasi_aging_game()`. - - Functions that use GLPK, such as `igraph_feedback_arc_set()` and `igraph_community_optimal_modularity()` are now interruptible. - - Add support for older versions of Clang that do not recognize the `-Wno-varargs` flag. +- Documentation improvements. +- Much faster documentation builds. +- Allow using a pre-generated `arith.h` header for f2c when cross-compiling; see the Installation section of the documentation. +- The `IGRAPH_ENABLE_LTO` build option now supports the `AUTO` value, which uses LTO only if the compiler supports it. Warning: CMake may not always be able to detect that LTO is not fully supported. Therefore, the default setting is `OFF`. +- The following functions are now interruptible: `igraph_grg_game()`, `igraph_sbm_game()`, `igraph_barabasi_game()`, `igraph_barabasi_aging_game()`. +- Functions that use GLPK, such as `igraph_feedback_arc_set()` and `igraph_community_optimal_modularity()` are now interruptible. +- Add support for older versions of Clang that do not recognize the `-Wno-varargs` flag. ### Acknowledgments - - Big thanks to Daniel Noom for continuing to expand the test suite and discovering and fixing several bugs in the process! +- Big thanks to Daniel Noom for continuing to expand the test suite and discovering and fixing several bugs in the process! ## [0.9.0] - 2021-02-16 ### Added - - Eulerian paths/cycles (PR #1346): - * `igraph_is_eulerian()` finds out whether an Eulerian path/cycle exists. - * `igraph_eulerian_path()` returns an Eulerian path. - * `igraph_eulerian_cycle()` returns an Eulerian cycle. - - Efficiency (PR #1344): - * `igraph_global_efficiency()` computes the global efficiency of a network. - * `igraph_local_efficiency()` computes the local efficiency around each vertex. - * `igraph_average_local_efficiency()` computes the mean local efficiency. - - Degree sequences (PR #1445): - * `igraph_is_graphical()` checks if a degree sequence has a realization as a simple or multigraph, with or without self-loops. - * `igraph_is_bigraphical()` checks if two degree sequences have a realization as a bipartite graph. - * `igraph_realize_degree_sequence()` now supports constructing non-simple graphs as well. - - There is a new fatal error handling mechanism (PR #1548): - * `igraph_set_fatal_handler()` sets the fatal error handler. It is the only function in this functionality group that is relevant to end users. - * The macro `IGRAPH_FATAL()` and the functions `igraph_fatal()` and `igraph_fatalf()` raise a fatal error. These are for internal use. - * `IGRAPH_ASSERT()` is a replacement for the `assert()` macro. It is for internal use. - * `igraph_fatal_handler_abort()` is the default fatal error handler. - - The new `IGRAPH_WARNINGF`, `IGRAPH_ERRORF` and `IGRAPH_FATALF` macros provide warning/error reporting with `printf`-like syntax. (PR #1627, thanks to Daniel Noom!) - - `igraph_average_path_length_dijkstra()` computes the mean shortest path length in weighted graphs (PR #1344). - - `igraph_get_shortest_paths_bellman_ford()` computes the shortest paths (including the vertex and edge IDs along the paths) using the Bellman-Ford algorithm (PR #1642, thanks to Guy Rozenberg). This makes it possible to calculate the shortest paths on graphs with negative edge weights, which was not possible before with Dijkstra's algorithm. - - `igraph_get_shortest_path_bellman_ford()` is a wrapper for `igraph_get_shortest_paths_bellman_ford()` for the single path case. - - `igraph_is_same_graph()` cheks that two labelled graphs are the same (PR #1604). - - Harmonic centrality (PR #1583): - * `igraph_harmonic_centrality()` computes the harmonic centrality of vertices. - * `igraph_harmonic_centrality_cutoff()` computes the range-limited harmonic centrality. - - Range-limited centralities, currently equivalent to the old functions with names ending in `_estimate` (PR #1583): - * `igraph_closeness_cutoff()`. - * `igraph_betweenness_cutoff()`. - * `igraph_edge_betweenness_cutoff()`. - - `igraph_vector_is_any_nan()` checks if any elements of an `igraph_vector_t` is NaN. - - `igraph_inclist_size()` returns the number of vertices in an incidence list. - - `igraph_lazy_adjlist_size()` returns the number of vertices in a lazy adjacency list. - - `igraph_lazy_inclist_size()` returns the number of vertices in a lazy incidence list. - - `igraph_bfs_simple()` now provides a simpler interface to the breadth-first search functionality. +- Eulerian paths/cycles (PR #1346): + - `igraph_is_eulerian()` finds out whether an Eulerian path/cycle exists. + - `igraph_eulerian_path()` returns an Eulerian path. + - `igraph_eulerian_cycle()` returns an Eulerian cycle. +- Efficiency (PR #1344): + - `igraph_global_efficiency()` computes the global efficiency of a network. + - `igraph_local_efficiency()` computes the local efficiency around each vertex. + - `igraph_average_local_efficiency()` computes the mean local efficiency. +- Degree sequences (PR #1445): + - `igraph_is_graphical()` checks if a degree sequence has a realization as a simple or multigraph, with or without self-loops. + - `igraph_is_bigraphical()` checks if two degree sequences have a realization as a bipartite graph. + - `igraph_realize_degree_sequence()` now supports constructing non-simple graphs as well. +- There is a new fatal error handling mechanism (PR #1548): + - `igraph_set_fatal_handler()` sets the fatal error handler. It is the only function in this functionality group that is relevant to end users. + - The macro `IGRAPH_FATAL()` and the functions `igraph_fatal()` and `igraph_fatalf()` raise a fatal error. These are for internal use. + - `IGRAPH_ASSERT()` is a replacement for the `assert()` macro. It is for internal use. + - `igraph_fatal_handler_abort()` is the default fatal error handler. +- The new `IGRAPH_WARNINGF`, `IGRAPH_ERRORF` and `IGRAPH_FATALF` macros provide warning/error reporting with `printf`-like syntax. (PR #1627, thanks to Daniel Noom!) +- `igraph_average_path_length_dijkstra()` computes the mean shortest path length in weighted graphs (PR #1344). +- `igraph_get_shortest_paths_bellman_ford()` computes the shortest paths (including the vertex and edge IDs along the paths) using the Bellman-Ford algorithm (PR #1642, thanks to Guy Rozenberg). This makes it possible to calculate the shortest paths on graphs with negative edge weights, which was not possible before with Dijkstra's algorithm. +- `igraph_get_shortest_path_bellman_ford()` is a wrapper for `igraph_get_shortest_paths_bellman_ford()` for the single path case. +- `igraph_is_same_graph()` cheks that two labelled graphs are the same (PR #1604). +- Harmonic centrality (PR #1583): + - `igraph_harmonic_centrality()` computes the harmonic centrality of vertices. + - `igraph_harmonic_centrality_cutoff()` computes the range-limited harmonic centrality. +- Range-limited centralities, currently equivalent to the old functions with names ending in `_estimate` (PR #1583): + - `igraph_closeness_cutoff()`. + - `igraph_betweenness_cutoff()`. + - `igraph_edge_betweenness_cutoff()`. +- `igraph_vector_is_any_nan()` checks if any elements of an `igraph_vector_t` is NaN. +- `igraph_inclist_size()` returns the number of vertices in an incidence list. +- `igraph_lazy_adjlist_size()` returns the number of vertices in a lazy adjacency list. +- `igraph_lazy_inclist_size()` returns the number of vertices in a lazy incidence list. +- `igraph_bfs_simple()` now provides a simpler interface to the breadth-first search functionality. ### Changed - - igraph now uses a CMake-based build sysyem. - - GMP support can no longer be disabled. When GMP is not present on the system, igraph will use an embedded copy of Mini-GMP (PR #1549). - - Bliss has been updated to version 0.75. Bliss functions are now interruptible. Thanks to Tommi Junttila for making this possible! - - Adjacency and incidence lists: - * `igraph_adjlist_init()` and `igraph_lazy_adjlist_init()` now require the caller to specify what to do with loop and multiple edges. - * `igraph_inclist_init()` and `igraph_lazy_inclist_init()` now require the caller to specify what to do with loop edges. - * Adjacency and incidence lists now use `igraph_vector_int_t` consistently. - - Community detection: - * `igraph_community_multilevel()`: added resolution parameter. - * `igraph_community_fluid_communities()`: graphs with no vertices or with one vertex only are now supported; they return a trivial partition. - - Modularity: - * `igraph_modularity()` and `igraph_modularity_matrix()`: added resolution parameter. - * `igraph_modularity()` and `igraph_modularity_matrix()` now support the directed version of modularity. - * `igraph_modularity()` returns NaN for graphs with no edges to indicate that the modularity is not well-defined for such graphs. - - Centralities: - * `cutoff=0` is no longer interpreted as infinity (i.e. no cutoff) in `betweenness`, `edge_betweenness` and `closeness`. If no cutoff is desired, use a negative value such as `cutoff=-1`. - * The `nobigint` argument has been removed from `igraph_betweenness()`, `igraph_betweenness_estimate()` and `igraph_centralization_betweenness()`, as it is not longer needed. The current implementation is more accurate than the old one using big integers. - * `igraph_closeness()` now considers only reachable vertices during the calculation (i.e. the closeness is calculated per-component in the undirected case) (PR #1630). - * `igraph_closeness()` gained two additional output parameters, `reachable_count` and `all_reachable`, returning the number of reached vertices from each vertex, as well as whether all vertices were reachable. This allows for computing various generalizations of closeness for disconnected graphs (PR #1630). - * `igraph_pagerank()`, `igraph_personalized_pagerank()` and `igraph_personalized_pagerank_vs()` no longer support the `IGRAPH_PAGERANK_ALGO_POWER` method. Their `options` argument now has type `igraph_arpack_options_t *` instead of `void *`. - - Shortest paths (PR #1344): - * `igraph_average_path_length()` now returns the number of disconnected vertex pairs in the new `unconn_pairs` output argument. - * `igraph_diameter()` now return the result as an `igraph_real_t` instead of an `igraph_integer_t`. - * `igraph_average_path_length()` and `igraph_diameter()` now return `IGRAPH_INFINITY` when `unconn=FALSE` and the graph is not connected. Previously they returned the number of vertices. - - Trait-based random graph generators: - * `igraph_callaway_traits_game()` and `igraph_establishment_game()` now have an optional output argument to retrieve the generated vertex types. - * `igraph_callaway_traits_game()` and `igraph_establishment_game()` now allow omitting the type distribution vector, in which case they assume a uniform distribution. - * `igraph_asymmetric_preference_game()` now accept a different number of in-types and out-types. - - `igraph_subisomorphic_lad()` now supports graphs with self-loops. - - `igraph_is_chordal()` and `igraph_maximum_cardinality_search()` now support non-simple graphs and directed graphs. - - `igraph_realize_degree_sequence()` has an additional argument controlling whether multi-edges or self-loops are allowed. - - `igraph_is_connected()` now returns false for the null graph; see https://github.com/igraph/igraph/issues/1538 for the reasoning behind this decision. - - `igraph_lapack_ddot()` is renamed to `igraph_blas_ddot()`. - - `igraph_to_directed()`: added RANDOM and ACYCLIC modes (PR #1511). - - `igraph_topological_sorting()` now issues an error if the input graph is not acyclic. Previously it issued a warning. - - `igraph_vector_(which_)(min|max|minmax)()` now handles NaN elements. - - `igraph_i_set_attribute_table()` is renamed to `igraph_set_attribute_table()`. - - `igraph_i_sparsemat_view()` is renamed to `igraph_sparsemat_view()`. +- igraph now uses a CMake-based build sysyem. +- GMP support can no longer be disabled. When GMP is not present on the system, igraph will use an embedded copy of Mini-GMP (PR #1549). +- Bliss has been updated to version 0.75. Bliss functions are now interruptible. Thanks to Tommi Junttila for making this possible! +- Adjacency and incidence lists: + - `igraph_adjlist_init()` and `igraph_lazy_adjlist_init()` now require the caller to specify what to do with loop and multiple edges. + - `igraph_inclist_init()` and `igraph_lazy_inclist_init()` now require the caller to specify what to do with loop edges. + - Adjacency and incidence lists now use `igraph_vector_int_t` consistently. +- Community detection: + - `igraph_community_multilevel()`: added resolution parameter. + - `igraph_community_fluid_communities()`: graphs with no vertices or with one vertex only are now supported; they return a trivial partition. +- Modularity: + - `igraph_modularity()` and `igraph_modularity_matrix()`: added resolution parameter. + - `igraph_modularity()` and `igraph_modularity_matrix()` now support the directed version of modularity. + - `igraph_modularity()` returns NaN for graphs with no edges to indicate that the modularity is not well-defined for such graphs. +- Centralities: + - `cutoff=0` is no longer interpreted as infinity (i.e. no cutoff) in `betweenness`, `edge_betweenness` and `closeness`. If no cutoff is desired, use a negative value such as `cutoff=-1`. + - The `nobigint` argument has been removed from `igraph_betweenness()`, `igraph_betweenness_estimate()` and `igraph_centralization_betweenness()`, as it is not longer needed. The current implementation is more accurate than the old one using big integers. + - `igraph_closeness()` now considers only reachable vertices during the calculation (i.e. the closeness is calculated per-component in the undirected case) (PR #1630). + - `igraph_closeness()` gained two additional output parameters, `reachable_count` and `all_reachable`, returning the number of reached vertices from each vertex, as well as whether all vertices were reachable. This allows for computing various generalizations of closeness for disconnected graphs (PR #1630). + - `igraph_pagerank()`, `igraph_personalized_pagerank()` and `igraph_personalized_pagerank_vs()` no longer support the `IGRAPH_PAGERANK_ALGO_POWER` method. Their `options` argument now has type `igraph_arpack_options_t *` instead of `void *`. +- Shortest paths (PR #1344): + - `igraph_average_path_length()` now returns the number of disconnected vertex pairs in the new `unconn_pairs` output argument. + - `igraph_diameter()` now return the result as an `igraph_real_t` instead of an `igraph_integer_t`. + - `igraph_average_path_length()` and `igraph_diameter()` now return `IGRAPH_INFINITY` when `unconn=FALSE` and the graph is not connected. Previously they returned the number of vertices. +- Trait-based random graph generators: + - `igraph_callaway_traits_game()` and `igraph_establishment_game()` now have an optional output argument to retrieve the generated vertex types. + - `igraph_callaway_traits_game()` and `igraph_establishment_game()` now allow omitting the type distribution vector, in which case they assume a uniform distribution. + - `igraph_asymmetric_preference_game()` now accept a different number of in-types and out-types. +- `igraph_subisomorphic_lad()` now supports graphs with self-loops. +- `igraph_is_chordal()` and `igraph_maximum_cardinality_search()` now support non-simple graphs and directed graphs. +- `igraph_realize_degree_sequence()` has an additional argument controlling whether multi-edges or self-loops are allowed. +- `igraph_is_connected()` now returns false for the null graph; see for the reasoning behind this decision. +- `igraph_lapack_ddot()` is renamed to `igraph_blas_ddot()`. +- `igraph_to_directed()`: added RANDOM and ACYCLIC modes (PR #1511). +- `igraph_topological_sorting()` now issues an error if the input graph is not acyclic. Previously it issued a warning. +- `igraph_vector_(which_)(min|max|minmax)()` now handles NaN elements. +- `igraph_i_set_attribute_table()` is renamed to `igraph_set_attribute_table()`. +- `igraph_i_sparsemat_view()` is renamed to `igraph_sparsemat_view()`. ### Deprecated - - `igraph_is_degree_sequence()` and `igraph_is_graphical_degree_sequence()` are deprecated in favour of the newly added `igraph_is_graphical()`. - - `igraph_closeness_estimate()` is deprecated in favour of the newly added `igraph_closeness_cutoff()`. - - `igraph_betweenness_estimate()` and `igraph_edge_betweenness_estimate()` are deprecated in favour of the newly added `igraph_betweenness_cutoff()` and `igraph_edge_betweenness_cutoff()`. - - `igraph_adjlist_remove_duplicate()` and `igraph_inclist_remove_duplicate()` are now deprecated in favour of the new constructor arguments in `igraph_adjlist_init()` and `igraph_inclist_init()`. +- `igraph_is_degree_sequence()` and `igraph_is_graphical_degree_sequence()` are deprecated in favour of the newly added `igraph_is_graphical()`. +- `igraph_closeness_estimate()` is deprecated in favour of the newly added `igraph_closeness_cutoff()`. +- `igraph_betweenness_estimate()` and `igraph_edge_betweenness_estimate()` are deprecated in favour of the newly added `igraph_betweenness_cutoff()` and `igraph_edge_betweenness_cutoff()`. +- `igraph_adjlist_remove_duplicate()` and `igraph_inclist_remove_duplicate()` are now deprecated in favour of the new constructor arguments in `igraph_adjlist_init()` and `igraph_inclist_init()`. ### Removed - - The following functions, all deprecated in igraph 0.6, have been removed (PR #1562): - * `igraph_adjedgelist_init()`, `igraph_adjedgelist_destroy()`, `igraph_adjedgelist_get()`, `igraph_adjedgelist_print()`, `igraph_adjedgelist_remove_duplicate()`. - * `igraph_lazy_adjedgelist_init()`, `igraph_lazy_adjedgelist_destroy()`, `igraph_lazy_adjedgelist_get()`, `igraph_lazy_adjedgelist_get_real()`. - * `igraph_adjacent()`. - * `igraph_es_adj()`. - * `igraph_subgraph()`. - - `igraph_pagerank_old()`, deprecated in 0.7, has been removed. - - `igraph_vector_bool` and `igraph_matrix_bool` functions that relied on inequality-comparing `igraph_bool_t` values are removed. +- The following functions, all deprecated in igraph 0.6, have been removed (PR #1562): + - `igraph_adjedgelist_init()`, `igraph_adjedgelist_destroy()`, `igraph_adjedgelist_get()`, `igraph_adjedgelist_print()`, `igraph_adjedgelist_remove_duplicate()`. + - `igraph_lazy_adjedgelist_init()`, `igraph_lazy_adjedgelist_destroy()`, `igraph_lazy_adjedgelist_get()`, `igraph_lazy_adjedgelist_get_real()`. + - `igraph_adjacent()`. + - `igraph_es_adj()`. + - `igraph_subgraph()`. +- `igraph_pagerank_old()`, deprecated in 0.7, has been removed. +- `igraph_vector_bool` and `igraph_matrix_bool` functions that relied on inequality-comparing `igraph_bool_t` values are removed. ### Fixed - - Betweenness calculations are no longer at risk from integer overflow. - - The actual cutoff distance used in closeness calculation was one smaller than the `cutoff` parameter. This is corrected (PR #1630). - - `igraph_layout_gem()` was not interruptible; now it is. - - `igraph_barabasi_aging_game()` now checks its parameters more carefully. - - `igraph_callaway_traits_game()` and `igraph_establishment_game()` now check their parameters. - - `igraph_lastcit_game()` checks its parameters more carefully, and no longer crashes with zero vertices (PR #1625). - - `igraph_cited_type_game()` incorrectly rounded the attractivity vector entries to integers. - - `igraph_residual_graph()` now returns the correct _residual_ capacities; previously it wrongly returned the original capacities (PR #1598). - - `igraph_psumtree_update()` now checks for negative values and NaN. - - `igraph_communities_spinglass()`: fixed several memory leaks in the `IGRAPH_SPINCOMM_IMP_NEG` implementation. - - `igraph_incident()` now returns edges in the same order as `igraph_neighbors()`. - - `igraph_modularity_matrix()` returned incorrect results for weighted graphs. This is now fixed. (PR #1649, thanks to Daniel Noom!) - - `igraph_lapack_dgetrf()` would crash when passing `NULL` for its `ipiv` argument (thanks for the fix to Daniel Noom). - - Some `igraph_matrix` functions would fail to report errors on out-of-memory conditions. - - `igraph_maxdegree()` now returns 0 for the null graph or empty vector set. Previously, it did not handle this case. - - `igraph_vector_bool_all_e()` now considers all nonzero (i.e. "true") values to be the same. - - PageRank (PR #1640): - * `igraph_(personalized_)pagerank(_vs)()` now check their parameters more carefully. - * `igraph_personalized_pagerank()` no longer modifies its `reset` parameter. - * `igraph_(personalized_)pagerank(_vs)`: the `IGRAPH_PAGERANK_ALGO_ARPACK` method now handles self-loops correctly. - * `igraph_personalized_pagerank(_vs)()`: the result retuned for edgeless or all-zero-weight graphs with the `IGRAPH_PAGERANK_ALGO_ARPACK` ignored the personalization vector. This is now corrected. - * `igraph_personalized_pagerank(_vs)()` with a non-uniform personalization vector, a disconnected graph and the `IGRAPH_PAGERANK_ALGO_PRPACK` method would return results that were inconsistent with `IGRAPH_PAGERANK_ALGO_ARPACK`. This happened because PRPACK always used a uniform reset distribution when the random walk got stuck in a sink vertex. Now it uses the user-specified reset distribution for this case as well. - - Fixed crashes in several functions when passing a weighted graph with zero edges (due to `vector_min` being called on the zero-length weight vector). - - Fixed problems in several functions when passing in a graph with zero vertices. - - Weighted betweenness, closeness, PageRank, shortest path calculations and random walk functions now check if any weights are NaN. - - Many functions now reject input arguments containing NaN values. - - Compatibility with the PGI compiler. +- Betweenness calculations are no longer at risk from integer overflow. +- The actual cutoff distance used in closeness calculation was one smaller than the `cutoff` parameter. This is corrected (PR #1630). +- `igraph_layout_gem()` was not interruptible; now it is. +- `igraph_barabasi_aging_game()` now checks its parameters more carefully. +- `igraph_callaway_traits_game()` and `igraph_establishment_game()` now check their parameters. +- `igraph_lastcit_game()` checks its parameters more carefully, and no longer crashes with zero vertices (PR #1625). +- `igraph_cited_type_game()` incorrectly rounded the attractivity vector entries to integers. +- `igraph_residual_graph()` now returns the correct _residual_ capacities; previously it wrongly returned the original capacities (PR #1598). +- `igraph_psumtree_update()` now checks for negative values and NaN. +- `igraph_communities_spinglass()`: fixed several memory leaks in the `IGRAPH_SPINCOMM_IMP_NEG` implementation. +- `igraph_incident()` now returns edges in the same order as `igraph_neighbors()`. +- `igraph_modularity_matrix()` returned incorrect results for weighted graphs. This is now fixed. (PR #1649, thanks to Daniel Noom!) +- `igraph_lapack_dgetrf()` would crash when passing `NULL` for its `ipiv` argument (thanks for the fix to Daniel Noom). +- Some `igraph_matrix` functions would fail to report errors on out-of-memory conditions. +- `igraph_maxdegree()` now returns 0 for the null graph or empty vector set. Previously, it did not handle this case. +- `igraph_vector_bool_all_e()` now considers all nonzero (i.e. "true") values to be the same. +- PageRank (PR #1640): + - `igraph_(personalized_)pagerank(_vs)()` now check their parameters more carefully. + - `igraph_personalized_pagerank()` no longer modifies its `reset` parameter. + - `igraph_(personalized_)pagerank(_vs)`: the `IGRAPH_PAGERANK_ALGO_ARPACK` method now handles self-loops correctly. + - `igraph_personalized_pagerank(_vs)()`: the result retuned for edgeless or all-zero-weight graphs with the `IGRAPH_PAGERANK_ALGO_ARPACK` ignored the personalization vector. This is now corrected. + - `igraph_personalized_pagerank(_vs)()` with a non-uniform personalization vector, a disconnected graph and the `IGRAPH_PAGERANK_ALGO_PRPACK` method would return results that were inconsistent with `IGRAPH_PAGERANK_ALGO_ARPACK`. This happened because PRPACK always used a uniform reset distribution when the random walk got stuck in a sink vertex. Now it uses the user-specified reset distribution for this case as well. +- Fixed crashes in several functions when passing a weighted graph with zero edges (due to `vector_min` being called on the zero-length weight vector). +- Fixed problems in several functions when passing in a graph with zero vertices. +- Weighted betweenness, closeness, PageRank, shortest path calculations and random walk functions now check if any weights are NaN. +- Many functions now reject input arguments containing NaN values. +- Compatibility with the PGI compiler. ### Other - - Documentation improvements. - - Improved error and warning messages. - - More robust error handling. - - General code cleanup to reduce the number of compiler warnings. - - igraph's source files have been re-organized for better maintainability. - - Debugging aid: When igraph is build with AddressSanitizer, the default error handler prints a stack trace before exiting. - - igraph can now be built with an external CXSparse library. - - The references to igraph source files in error and warning messages are now always relative to igraph's base directory. - - When igraph is built as a shared library, only public symbols are exported even on Linux and macOS. +- Documentation improvements. +- Improved error and warning messages. +- More robust error handling. +- General code cleanup to reduce the number of compiler warnings. +- igraph's source files have been re-organized for better maintainability. +- Debugging aid: When igraph is build with AddressSanitizer, the default error handler prints a stack trace before exiting. +- igraph can now be built with an external CXSparse library. +- The references to igraph source files in error and warning messages are now always relative to igraph's base directory. +- When igraph is built as a shared library, only public symbols are exported even on Linux and macOS. ### Acknowledgments - - Thanks to Daniel Noom for significantly expanding igraph's test coverage and exposing several issues in the process! +- Thanks to Daniel Noom for significantly expanding igraph's test coverage and exposing several issues in the process! ## [0.8.5] - 2020-12-07 ### Changed - - `igraph_write_graph_pajek()`: the function now always uses the platform-native line endings (CRLF on Windows, LF on Unix and macOS). Earlier versions tried to enforce Windows line endings, but this was error-prone, and since all recent versions of Pajek support both line endings, enforcing Windows line endings is not necessary any more. +- `igraph_write_graph_pajek()`: the function now always uses the platform-native line endings (CRLF on Windows, LF on Unix and macOS). Earlier versions tried to enforce Windows line endings, but this was error-prone, and since all recent versions of Pajek support both line endings, enforcing Windows line endings is not necessary any more. ### Fixed - - Fixed several compilation issues with MINGW32/64 (PR #1554) - - `igraph_layout_davidson_harel()` was not interruptible; now it is. - - Added a missing memory cleanup call in `igraph_i_cattribute_combine_vertices()`. - - Fixed a few memory leaks in test cases. +- Fixed several compilation issues with MINGW32/64 (PR #1554) +- `igraph_layout_davidson_harel()` was not interruptible; now it is. +- Added a missing memory cleanup call in `igraph_i_cattribute_combine_vertices()`. +- Fixed a few memory leaks in test cases. ## [0.8.4] - 2020-11-24 ### Fixed - - `igraph_i_cattribute_combine_vertices()`: fixed invalid cleanup code that eventually filled up the "finally" stack when combining vertices with attributes extensively. - - `igraph_hrg_sample()`: fixed incorrect function prototype - - `igraph_is_posinf()` and `igraph_is_neginf()`: fixed incorrect result on platforms where the sign of the result of `isinf()` is not indicative of the sign of the input. - - Fixed building with vendored LAPACK and external BLAS - - Fixed building with XCode 12.2 on macOS +- `igraph_i_cattribute_combine_vertices()`: fixed invalid cleanup code that eventually filled up the "finally" stack when combining vertices with attributes extensively. +- `igraph_hrg_sample()`: fixed incorrect function prototype +- `igraph_is_posinf()` and `igraph_is_neginf()`: fixed incorrect result on platforms where the sign of the result of `isinf()` is not indicative of the sign of the input. +- Fixed building with vendored LAPACK and external BLAS +- Fixed building with XCode 12.2 on macOS ### Other - - Documentation improvements - - General code cleanup to reduce the number of compiler warnings +- Documentation improvements +- General code cleanup to reduce the number of compiler warnings ## [0.8.3] - 2020-10-02 ### Added - - `igraph_vector_binsearch_slice()` performs binary search on a sorted slice of a vector. +- `igraph_vector_binsearch_slice()` performs binary search on a sorted slice of a vector. ### Changed - - `igraph_eigenvector_centrality()` assumes the adjacency matrix of undirected graphs to have twice the number of self-loops for each vertex on the diagonal. This makes the results consistent between an undirected graph and its directed equivalent when each edge is replaced by a mutual edge pair. +- `igraph_eigenvector_centrality()` assumes the adjacency matrix of undirected graphs to have twice the number of self-loops for each vertex on the diagonal. This makes the results consistent between an undirected graph and its directed equivalent when each edge is replaced by a mutual edge pair. ### Fixed - - `igraph_isomorphic()` now verifies that the input graphs have no multi-edges (PR #1464). - - `igraph_difference()` was creating superfluous self loops (#597). - - `igraph_count_multiple()` was giving incorrect results for self-loops in directed graph (PR #1399). - - `igraph_betweenness_estimate()`: fixed incorrect results with finite cutoff (PR #1392). - - `igraph_count_multiple()` was giving incorrect results for self-loops in directed graph (PR #1399). - - `igraph_eigen_matrix_symmetric()`: fixed incorrect matrix multiplication (PR #1379). - - Corrected several issues that could arise during an error condition (PRs #1405, #1406, #1438). - - `igraph_realize_degree_sequence()` did not correctly detect some non-graphical inputs. - - `igraph_is_graphical_degree_sequence()`: fixed incorrect results in undirected case (PR #1441). - - `igraph_community_leiden()`: fixed incorrect result when self-loops are present (PR #1476). - - `igraph_eigenvector_centrality()`: fixed incorrect value for isolated vertices in weighted graphs. - - `igraph_eigenvector_centrality()`: corrected the handling of self-loops. - - `igraph_layout_reingold_tilford()`: fixed an issue where branches of the tree would sometimes overlap. +- `igraph_isomorphic()` now verifies that the input graphs have no multi-edges (PR #1464). +- `igraph_difference()` was creating superfluous self loops (#597). +- `igraph_count_multiple()` was giving incorrect results for self-loops in directed graph (PR #1399). +- `igraph_betweenness_estimate()`: fixed incorrect results with finite cutoff (PR #1392). +- `igraph_count_multiple()` was giving incorrect results for self-loops in directed graph (PR #1399). +- `igraph_eigen_matrix_symmetric()`: fixed incorrect matrix multiplication (PR #1379). +- Corrected several issues that could arise during an error condition (PRs #1405, #1406, #1438). +- `igraph_realize_degree_sequence()` did not correctly detect some non-graphical inputs. +- `igraph_is_graphical_degree_sequence()`: fixed incorrect results in undirected case (PR #1441). +- `igraph_community_leiden()`: fixed incorrect result when self-loops are present (PR #1476). +- `igraph_eigenvector_centrality()`: fixed incorrect value for isolated vertices in weighted graphs. +- `igraph_eigenvector_centrality()`: corrected the handling of self-loops. +- `igraph_layout_reingold_tilford()`: fixed an issue where branches of the tree would sometimes overlap. ### Other - - `igraph_degree_sequence_game()`: improved performance with `IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE_UNIFORM` method. - - Improved the robustness of the test suite. - - Documentation improvements. - - Improved error and warning messages. - - Improved compatibility with recent versions of Microsoft Visual C. +- `igraph_degree_sequence_game()`: improved performance with `IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE_UNIFORM` method. +- Improved the robustness of the test suite. +- Documentation improvements. +- Improved error and warning messages. +- Improved compatibility with recent versions of Microsoft Visual C. ## [0.8.2] - 2020-04-28 ### Changed - - Improved argument checking: `igraph_all_st_mincuts()` and `igraph_sir()` - - Improved interruptibility: `igraph_sir()` +- Improved argument checking: `igraph_all_st_mincuts()` and `igraph_sir()` +- Improved interruptibility: `igraph_sir()` ### Fixed - - `igraph_community_leiden()`: fixed crash when interrupting - - The tests are now more robust. Some incorrect test failures were fixed when +- `igraph_community_leiden()`: fixed crash when interrupting +- The tests are now more robust. Some incorrect test failures were fixed when running on i386 architecture, or when using different versions of external dependencies. ### Other - - Improved error messages from `igraph_sir()`. - - Improved compatibility with more recent versions of Microsoft Visual C. +- Improved error messages from `igraph_sir()`. +- Improved compatibility with more recent versions of Microsoft Visual C. ## [0.8.1] - 2020-03-13 ### Changed - - Improved interruptability: `igraph_degree_sequence_game()` - - Improved argument checking: `igraph_forest_fire_game()` - - Updated the plfit library to version 0.8.1 +- Improved interruptability: `igraph_degree_sequence_game()` +- Improved argument checking: `igraph_forest_fire_game()` +- Updated the plfit library to version 0.8.1 ### Fixed - - `igraph_community_edge_betweenness()`: fix for graphs with no edges (PR #1312) - - `igraph_bridges()` now handles multigraphs correctly (PR #1335) - - `igraph_avg_nearest_neighbor_degree()`: fix for memory leak in weighted case (PR #1339) - - `igraph_community_leiden()`: fix crash bug (PR #1357) +- `igraph_community_edge_betweenness()`: fix for graphs with no edges (PR #1312) +- `igraph_bridges()` now handles multigraphs correctly (PR #1335) +- `igraph_avg_nearest_neighbor_degree()`: fix for memory leak in weighted case (PR #1339) +- `igraph_community_leiden()`: fix crash bug (PR #1357) ### Other - - Included `ACKOWLEDGEMENTS.md` - - Documentation improvements +- Included `ACKOWLEDGEMENTS.md` +- Documentation improvements ## [0.8.0] - 2020-01-29 ### Added - * Trees +- Trees - - `igraph_to_prufer()` and `igraph_from_prufer()` convert labelled trees to/from Prüfer sequences - - `igraph_tree_game()` samples uniformly from the set of labelled trees - - `igraph_is_tree()` checks if a graph is a tree - - `igraph_random_spanning_tree()` picks a spanning tree of a graph uniformly at random - - `igraph_random_edge_walk()` returns the indices of edges traversed by a random walk; useful for multigraphs + - `igraph_to_prufer()` and `igraph_from_prufer()` convert labelled trees to/from Prüfer sequences + - `igraph_tree_game()` samples uniformly from the set of labelled trees + - `igraph_is_tree()` checks if a graph is a tree + - `igraph_random_spanning_tree()` picks a spanning tree of a graph uniformly at random + - `igraph_random_edge_walk()` returns the indices of edges traversed by a random walk; useful for multigraphs - * Community detection +- Community detection - - `igraph_community_fluid_communities()` detects communities based on interacting fluids - - `igraph_community_leiden()` detects communities with the Leiden method + - `igraph_community_fluid_communities()` detects communities based on interacting fluids + - `igraph_community_leiden()` detects communities with the Leiden method - * Cliques +- Cliques - - `igraph_maximal_cliques_hist()` counts maximal cliques of each size - - `igraph_maximal_cliques_callback()` calls a function for each maximal clique - - `igraph_clique_size_hist()` counts cliques of each size - - `igraph_cliques_callback()` calls a function for each clique - - `igraph_weighted_cliques()` finds weighted cliques in graphs with integer vertex weights - - `igraph_weighted_clique_number()` computes the weighted clique number - - `igraph_largest_weighted_cliques()` finds the largest weighted cliques + - `igraph_maximal_cliques_hist()` counts maximal cliques of each size + - `igraph_maximal_cliques_callback()` calls a function for each maximal clique + - `igraph_clique_size_hist()` counts cliques of each size + - `igraph_cliques_callback()` calls a function for each clique + - `igraph_weighted_cliques()` finds weighted cliques in graphs with integer vertex weights + - `igraph_weighted_clique_number()` computes the weighted clique number + - `igraph_largest_weighted_cliques()` finds the largest weighted cliques - * Graph generators +- Graph generators - - `igraph_hsbm_game()` for a hierarchical stochastic block model - - `igraph_hsbm_list_game()` for a more general hierarchical stochastic block model - - `igraph_correlated_game()` generates pairs of correlated random graphs by perturbing existing adjacency matrix - - `igraph_correlated_pair_game()` generates pairs of correlated random graphs - - `igraph_tree_game()` samples uniformly from the set of labelled trees - - `igraph_dot_product_game()` generates a random dot product graph - - `igraph_realize_degree_sequence()` creates a single graph with a given degree sequence (Havel-Hakimi algorithm) + - `igraph_hsbm_game()` for a hierarchical stochastic block model + - `igraph_hsbm_list_game()` for a more general hierarchical stochastic block model + - `igraph_correlated_game()` generates pairs of correlated random graphs by perturbing existing adjacency matrix + - `igraph_correlated_pair_game()` generates pairs of correlated random graphs + - `igraph_tree_game()` samples uniformly from the set of labelled trees + - `igraph_dot_product_game()` generates a random dot product graph + - `igraph_realize_degree_sequence()` creates a single graph with a given degree sequence (Havel-Hakimi algorithm) - * Graph embeddings +- Graph embeddings - - `igraph_adjacency_spectral_embedding()` and `igraph_laplacian_spectral_embedding()` provide graph embedddings - - `igraph_dim_select()` provides dimensionality selection for singular values using profile likelihood + - `igraph_adjacency_spectral_embedding()` and `igraph_laplacian_spectral_embedding()` provide graph embedddings + - `igraph_dim_select()` provides dimensionality selection for singular values using profile likelihood - * Isomorphism +- Isomorphism - - `igraph_automorphism_group()` computes the generators of the automorphism group of a simple graph - - `igraph_simplify_and_colorize()` encodes edge and self-loop multiplicities into edge and vertex colors; use in conjunction with VF2 to test isomorphism of non-simple graphs + - `igraph_automorphism_group()` computes the generators of the automorphism group of a simple graph + - `igraph_simplify_and_colorize()` encodes edge and self-loop multiplicities into edge and vertex colors; use in conjunction with VF2 to test isomorphism of non-simple graphs - * Other +- Other - - `igraph_bridges()` finds edges whose removal would disconnect a graph - - `igraph_vertex_coloring_greedy()` computes a vertex coloring using a greedy algorithm - - `igraph_rewire_directed_edges()` randomly rewires only the starting points or only the endpoints of directed edges - - Various `igraph_local_scan_*` functions provide local counts and statistics of neighborhoods - - `igraph_sample_sphere_surface()` samples points uniformly from the surface of a sphere - - `igraph_sample_sphere_volume()` samples points uniformly from the volume of a sphere - - `igraph_sample_dirichlet()` samples points from a Dirichlet distribution - - `igraph_malloc()`, to be paired with the existing `igraph_free()` + - `igraph_bridges()` finds edges whose removal would disconnect a graph + - `igraph_vertex_coloring_greedy()` computes a vertex coloring using a greedy algorithm + - `igraph_rewire_directed_edges()` randomly rewires only the starting points or only the endpoints of directed edges + - Various `igraph_local_scan_*` functions provide local counts and statistics of neighborhoods + - `igraph_sample_sphere_surface()` samples points uniformly from the surface of a sphere + - `igraph_sample_sphere_volume()` samples points uniformly from the volume of a sphere + - `igraph_sample_dirichlet()` samples points from a Dirichlet distribution + - `igraph_malloc()`, to be paired with the existing `igraph_free()` ### Changed - - `igraph_degree_sequence_game()`: new method added for uniform sampling: `IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE_UNIFORM` - - `igraph_modularity_matrix()`: removed `membership` argument (PR #1194) - - `igraph_avg_nearest_neighbor_degree()`: added `mode` and `neighbor_degree_mode` arguments (PR #1214). - - `igraph_get_all_simple_paths()`: added `cutoff` argument (PR #1232). - - `igraph_unfold_tree()`: no longer preserves edge ordering of original graph - - `igraph_decompose()`: support strongly connected components - - `igraph_isomorphic_bliss()`, `igraph_canonical_permutation()`, `igraph_automorphisms()`: added additional arguments to support vertex colored graphs (PR #873) - - `igraph_extended_chordal_ring`: added argument to support direction (PR #1096), and fixed issue #1093. +- `igraph_degree_sequence_game()`: new method added for uniform sampling: `IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE_UNIFORM` +- `igraph_modularity_matrix()`: removed `membership` argument (PR #1194) +- `igraph_avg_nearest_neighbor_degree()`: added `mode` and `neighbor_degree_mode` arguments (PR #1214). +- `igraph_get_all_simple_paths()`: added `cutoff` argument (PR #1232). +- `igraph_unfold_tree()`: no longer preserves edge ordering of original graph +- `igraph_decompose()`: support strongly connected components +- `igraph_isomorphic_bliss()`, `igraph_canonical_permutation()`, `igraph_automorphisms()`: added additional arguments to support vertex colored graphs (PR #873) +- `igraph_extended_chordal_ring`: added argument to support direction (PR #1096), and fixed issue #1093. ### Other - - The [Bliss isomorphism library](http://www.tcs.hut.fi/Software/bliss/) was updated to version 0.73. This version adds support for vertex colored and directed graphs. - - igraph now uses the high-performance [Cliquer library](https://users.aalto.fi/~pat/cliquer.html) to find (non-maximal) cliques - - Provide proper support for Windows, using `__declspec(dllexport)` and `__declspec(dllimport)` for `DLL`s and static usage by using `#define IGRAPH_STATIC 1`. - - Provided integer versions of `dqueue` and `stack` data types. +- The [Bliss isomorphism library](http://www.tcs.hut.fi/Software/bliss/) was updated to version 0.73. This version adds support for vertex colored and directed graphs. +- igraph now uses the high-performance [Cliquer library](https://users.aalto.fi/~pat/cliquer.html) to find (non-maximal) cliques +- Provide proper support for Windows, using `__declspec(dllexport)` and `__declspec(dllimport)` for `DLL`s and static usage by using `#define IGRAPH_STATIC 1`. +- Provided integer versions of `dqueue` and `stack` data types. -[develop]: https://github.com/igraph/igraph/compare/master..develop -[master]: https://github.com/igraph/igraph/compare/0.10.16..master +[main]: https://github.com/igraph/igraph/compare/1.0.0..main +[1.0.0]: https://github.com/igraph/igraph/compare/0.10.17..1.0.0 +[0.10.17]: https://github.com/igraph/igraph/compare/0.10.16..0.10.17 [0.10.16]: https://github.com/igraph/igraph/compare/0.10.15..0.10.16 [0.10.15]: https://github.com/igraph/igraph/compare/0.10.13..0.10.15 [0.10.13]: https://github.com/igraph/igraph/compare/0.10.12..0.10.13 diff --git a/src/vendor/cigraph/CONTRIBUTING.md b/src/vendor/cigraph/CONTRIBUTING.md index 7894b2f9549..89336213f1d 100644 --- a/src/vendor/cigraph/CONTRIBUTING.md +++ b/src/vendor/cigraph/CONTRIBUTING.md @@ -32,6 +32,7 @@ experienced with C, you can contribute in a number of ways: adhere to our [Code of Conduct](https://igraph.org/code-of-conduct.html). + ## Bug reports A bug is a _demonstrable problem_ that is caused by the code in the repository. @@ -53,7 +54,7 @@ Guidelines for bug reports: reported. 3. **Check if the issue has been fixed** — try to reproduce it using the - latest `master` or development branch in the repository. + latest `main` or development branch in the repository. 4. **Isolate the problem** — create a [short, self-contained, correct example](http://sscce.org/). @@ -99,12 +100,12 @@ to convince the project's developers of the merits of this feature. _**Note:** The wiki has a lot of useful information for newcomers, as well as a [quick start guide](https://github.com/igraph/igraph/wiki/Quickstart-for-new-contributors)!_ -Good pull requests - patches, improvements, new features - are a fantastic help. +Good pull requests—patches, improvements, new features—are a fantastic help. They should remain focused in scope and avoid containing unrelated commits. Please also take a look at our [tips on writing igraph code](#tips) before getting your hands dirty. -**Please ask first** before embarking on any significant pull request (e.g. +**Please ask first before embarking on any significant pull request** (e.g. implementing features, refactoring code, porting to a different language), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project. @@ -127,7 +128,7 @@ Follow the following steps if you would like to make a new pull request: ``` 2. Please checkout the section on [branching](#branching) to see whether you - need to branch off from the `master` branch or the `develop` branch. + need to branch off from the `main` branch or the `develop` branch. If you cloned a while ago, get the latest changes from upstream: @@ -180,9 +181,10 @@ owner to license your work under the same license as that used by the project, see also [Legal Stuff](#legal). + ### Branching -In short, always ask whether your contribution should target the `master` or +In short, always ask whether your contribution should target the `main` or `develop` branch _before_ starting any work. Read on for more details on how this is decided. @@ -191,30 +193,30 @@ currently still in the development release (0.x), which in principle is a mark that the public API is not yet stable. Regardless, we try to maintain semantic versioning also for the development releases. We do so as follows. Any released minor version (0.x.z) will be API backwards-compatible with any previous release -of the *same* minor version (0.x.y, with y < z). This means that *if* there is +of the _same_ minor version (0.x.y, with y < z). This means that _if_ there is an API incompatible change, we will increase the minor version. For example, release 0.8.1 is API backwards-compatible with release 0.8.0, while release 0.9.0 might be API incompatible with version 0.8.1. Note that this only concerns -the *public* API, internal functions may change also within a minor version. +the _public_ API, internal functions may change also within a minor version. There will always be two versions of `igraph`: the most recent released version, and the next upcoming minor release, which is by definition not yet released. -The most recent release version is in the `master` branch, while the next +The most recent release version is in the `main` branch, while the next upcoming minor release is in the `develop` branch. If you make a change that is API incompatible with the most recent release, it **must** be merged to the `develop` branch. If the change is API backwards-compatible, it **can** be -merged to the `master` branch. It is possible that you build on recent +merged to the `main` branch. It is possible that you build on recent improvements in the `develop` branch, in which case your change should of course target the `develop` branch. If you only add new functionality, but do not change anything of the existing API, this should be backwards-compatible, and -can be merged in the `master` branch. +can be merged in the `main` branch. When you make a new pull request, please specify the correct target branch. The maintainers of `igraph` may decide to retarget your pull request to the correct branch. Retargeting you pull request may result in merge conflicts, so it is always good to decide **before** starting to work on something whether you -should start from the `master` branch or from the `develop` branch. In most -cases, changes in the `master` branch will also be merged to the `develop` +should start from the `main` branch or from the `develop` branch. In most +cases, changes in the `main` branch will also be merged to the `develop` branch by the maintainers. diff --git a/src/vendor/cigraph/CONTRIBUTORS.md b/src/vendor/cigraph/CONTRIBUTORS.md index fe9ef760b40..faec64de7a9 100644 --- a/src/vendor/cigraph/CONTRIBUTORS.md +++ b/src/vendor/cigraph/CONTRIBUTORS.md @@ -102,6 +102,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Sarah Rashidi
Sarah Rashidi

💻 Zara Zong
Zara Zong

💻 Arnór Friðriksson
Arnór Friðriksson

💻 + Varun Rajesh
Varun Rajesh

💻 + Steve Sajeev
Steve Sajeev

💻 + Rohith Sudheer
Rohith Sudheer

💻 + + + Grisha
Grisha

💻 + Michael Antonov
Michael Antonov

💻 diff --git a/src/vendor/cigraph/CONTRIBUTORS.txt b/src/vendor/cigraph/CONTRIBUTORS.txt index 70fd5644106..016f6a99c83 100644 --- a/src/vendor/cigraph/CONTRIBUTORS.txt +++ b/src/vendor/cigraph/CONTRIBUTORS.txt @@ -74,6 +74,11 @@ Lucas Lopes Felipe (@lucaslopes) Sarah Rashidi (@its-serah) Zara Zong (@minifinity) Arnór Friðriksson (@Zepeacedust) +Varun Rajesh (@VRajesh7649) +Steve Sajeev (@stevesajeev1) +Rohith Sudheer (@RohithS98) +Grisha (@GrishaVar) +Michael Antonov (@Antonov548) This project follows the [all-contributors][1] specification. Contributions of any kind welcome! diff --git a/src/vendor/cigraph/README.md b/src/vendor/cigraph/README.md index 185df33b5b0..8eadfd71388 100644 --- a/src/vendor/cigraph/README.md +++ b/src/vendor/cigraph/README.md @@ -1,6 +1,6 @@ -[![Build Status on Azure Pipelines](https://dev.azure.com/igraph-team/igraph/_apis/build/status/igraph.igraph?branchName=master)](https://dev.azure.com/igraph-team/igraph/_build/latest?definitionId=1&branchName=master) -![Build Status on Github Actions](https://github.com/igraph/igraph/workflows/MINGW/badge.svg?branch=master) -[![codecov](https://codecov.io/gh/igraph/igraph/branch/master/graph/badge.svg?token=xGFabHJE2I)](https://codecov.io/gh/igraph/igraph) +[![Build Status on Azure Pipelines](https://dev.azure.com/igraph-team/igraph/_apis/build/status/igraph.igraph?branchName=main)](https://dev.azure.com/igraph-team/igraph/_build/latest?definitionId=1&branchName=main) +![Build Status on Github Actions](https://github.com/igraph/igraph/workflows/MINGW/badge.svg?branch=main) +[![codecov](https://codecov.io/gh/igraph/igraph/branch/main/graph/badge.svg?token=xGFabHJE2I)](https://codecov.io/gh/igraph/igraph) [![DOI](https://zenodo.org/badge/8546198.svg)](https://zenodo.org/badge/latestdoi/8546198) The igraph library diff --git a/src/vendor/cigraph/VERSIONING.md b/src/vendor/cigraph/VERSIONING.md new file mode 100644 index 00000000000..b29b2333b1e --- /dev/null +++ b/src/vendor/cigraph/VERSIONING.md @@ -0,0 +1,58 @@ +# Versioning and stability + +This document is provided for informational purposes only, to help igraph users understand how igraph's programming interface is evolving, and what stability guaratees you can rely on. It concerns the igraph C library only. igraph's high level interfaces (R, Python, Mathematica) have their own separate versioning schemes and compatibility policies. + +## Versioning + +Starting with version 1.0, igraph follows the spirit of semantic versioning, with some differences, as described below. The version number consists of three parts in the `MAJOR.MINOR.PATCH` format. + +- `MAJOR` is incremented after making _incompatible changes_ to the stable programming interface. Major releases are intended to be infrequent, and are accompanied by release notes where we make the effort to provide detailed guidance on adapting to incompatible changes. +- `MINOR` is incremented after making _additions_ to the stable programming interface. Minor releases are issued regularly. +- `PATCH` is incremented when making changes that do not affect compatibility (usually bug fixes, documentation improvements, or build systems changes). + +The three version parts are available at compile time as the macros `IGRAPH_VERSION_MAJOR`, `IGRAPH_VERSION_MINOR` and `IGRAPH_VERSION_PATCH`, or at runtime through the `igraph_version()` function. + +The majority of public, documented functions are considered to be part of the _stable programming interface_, but there are some notable exceptions: + +- **Experimental functions** may change at any time without notice. These are clearly marked in their documentation ([example](https://igraph.org/c/html/0.10.13/igraph-Generators.html#igraph_chung_lu_game)). They are also marked in igraph's header files with the `IGRAPH_EXPERIMENTAL` macro ([example](https://github.com/igraph/igraph/blob/3629c46b2784cb10fc27fc6e9fab4404a13d031c/include/igraph_cycles.h#L49-L53)). Most newly added functions start out as _experimental_, and stay in this state until we are confident in their design, typically for one or two minor releases. User feedback about experimental functions is particularly welcome. We make the effort to avoid changes to experimental functions in patch releases, but do not guarantee this. +- **Internal and undocumented functions** are not part of the stable programming interface, not even if they are present in public headers. They may change at any time. The names of internal functions usually start with the prefix `igraph_i_` (capitalized for macros), while public functions start with `igraph_`. + +## Symbol lifecycle + +Most new symbols start out as _experimental_ in minor releases. Eventually, their API is declared stable, and the experimental marker is removed from their declaration and documentation in an upcoming minor release. + +Symbols go through a deprecation phase before they are removed. Deprecated symbols are marked in their documentation ([example](https://igraph.org/c/html/0.10.13/igraph-Structural.html#igraph_clusters)), and functions are prefixed with `IGRAPH_DEPRECATED` in the public headers ([example](https://github.com/igraph/igraph/blob/997f59ad742892fff199824a248fab382b40f526/include/igraph_components.h#L45-L47)). With GCC-compatible compilers, use the `-Wdeprecated` flag to get a warning for the use of deprecated functions, but keep in mind that deprecation warnings are not supported for all symbol types (e.g. macros) with all compilers. The ultimate reference for deprecations is the [changelog][1]. + +## Stability of behaviour + +Whether changes in function behaviour are considered breaking is somewhat subjective, and is decided on a case-by-case basis. Expect some changes within minor releases. For example, a function that ignored edge multiplicities may gain support for multigraphs in a new minor release. Do not rely on details of behaviour that are not explicitly documented. + +A notable case is stochastic functions: we do not guarantee that the same output is returned across different releases (even patch releases) for the same random seed. We only guarantee the same statistical properties. + +## Advice to users and package maintainers + +**Users:** + +For as long as you don't use _experimental_ functions, you can be confident that your code will continue to work with future releases having the same major version. If you do use _experimental_ functions, it is your responsibility to check the [release notes][1] of each igraph release and adapt accordingly. The use of _internal_ functions is completely unsupported: if you feel you need them, please talk to us. + +If you do use _experimental_ functions, make this clear in your README file for the benefit of package maintainers. + +While igraph comes with multiple header files, only `#include ` is supported. The rest of the headers exist for internal organizational purposes only, and may change without notice. + +**Package maintainers:** + +Software that does not use experimental functions from igraph can safely link to future igraph versions with the same major version. Ask the developer of any software you are packaging if they are using experimental igraph functions. + +The high-level interfaces of igraph do use both experimental and internal functions. Each high-level interface release is only guaranteed to be compatible with one specific release of C/igraph. As of this writing, this is a concern only for the Python interface, as the other interfaces (R and Mathematica) cannot link dynamically to C/igraph. + +We provide the `IGRAPH_WARN_EXPERIMENTAL` compile-time macro to help maintainers in determining whether a piece of software uses experimental igraph functions or not. Compilers that support `__attribute__((__warning(...)))` clauses will issue a warning when `IGRAPH_WARN_EXPERIMENTAL` is defined to a non-zero value at compile-time and an experimental function is used somewhere in the code. + +## Notes + +For the purposes of this document, "API compatibility" means that the same sources can be compiled using headers from different igraph versions. "ABI compatibility" means that a program that only uses stable API can be linked to a different version of the igraph shared library than what it was compiled with. + +We strive to maintain both API and ABI compatibility. + +However, it must be pointed out that we do not support manipulating the same in-memory igraph data structures with different igraph versions (for example, if two libraries that exchange data are each statically linked to different igraph versions). + + [1]: https://github.com/igraph/igraph/blob/main/CHANGELOG.md diff --git a/src/vendor/cigraph/azure-pipelines.yml b/src/vendor/cigraph/azure-pipelines.yml index 660db957c11..86ffc5cad9b 100644 --- a/src/vendor/cigraph/azure-pipelines.yml +++ b/src/vendor/cigraph/azure-pipelines.yml @@ -1,5 +1,5 @@ pool: - vmImage: 'ubuntu-latest' + vmImage: "ubuntu-latest" variables: CMAKE_COLOR_DIAGNOSTICS: ON @@ -9,7 +9,7 @@ variables: ASAN_OPTIONS: detect_stack_use_after_return=1:color=always UBSAN_OPTIONS: print_stacktrace=1:color=always OMP_NUM_THREADS: 1 - CTEST_PARALLEL_LEVEL: 0 # Since CMake 3.29, a setting of 0 will try to use all available resources + CTEST_PARALLEL_LEVEL: 4 jobs: # In this test we install and generate locales so that igraph_enter/exit_safelocale() can be tested @@ -52,7 +52,7 @@ jobs: int_arpack: false int_gmp: false int_glpk: false - extra_cmake_args: '-DBLA_VENDOR=OpenBLAS' + extra_cmake_args: "-DBLA_VENDOR=OpenBLAS" - job: linux_shared_vendored steps: @@ -75,22 +75,22 @@ jobs: int_arpack: false int_gmp: false int_glpk: false - extra_cmake_args: '-DBLA_VENDOR=OpenBLAS' + extra_cmake_args: "-DBLA_VENDOR=OpenBLAS" build_shared: true - - job: linux_clang_20 + - job: linux_clang_22 steps: - script: | sudo apt-get install ninja-build ccache -y wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 20 + sudo ./llvm.sh 22 displayName: Install dependencies - template: .azure/build.yml parameters: build_type: Debug - extra_cmake_args: '-DUSE_SANITIZER=Address\;Undefined -DCMAKE_C_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_CXX_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_C_COMPILER=clang-20 -DCMAKE_CXX_COMPILER=clang++-20' + extra_cmake_args: '-DUSE_SANITIZER=Address\;Undefined -DCMAKE_C_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_CXX_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_C_COMPILER=clang-22 -DCMAKE_CXX_COMPILER=clang++-22' - job: linux_x87 steps: @@ -99,7 +99,8 @@ jobs: - template: .azure/build.yml parameters: - extra_cmake_args: '-DCMAKE_C_FLAGS="-mfpmath=387" -DCMAKE_CXX_FLAGS="-mfpmath=387"' + build_type: Debug + extra_cmake_args: '-DUSE_SANITIZER=Address\;Undefined -DCMAKE_C_FLAGS="-mfpmath=387" -DCMAKE_CXX_FLAGS="-mfpmath=387"' - job: linux_alpine steps: @@ -129,20 +130,20 @@ jobs: - job: windows_static pool: - vmImage: windows-latest + vmImage: windows-latest steps: - template: .azure/build-win.yml - job: windows_shared pool: - vmImage: windows-latest + vmImage: windows-latest steps: - template: .azure/build-win.yml parameters: build_shared: true - vsver: '14.4' # latest VS2022 + vsver: "14.4" # latest VS2022 vcpkg_target_triplet: x64-windows - job: documentation @@ -155,9 +156,9 @@ jobs: - task: CMake@1 displayName: CMake inputs: - cmakeArgs: '..' + cmakeArgs: ".." - task: CMake@1 displayName: Doc build inputs: - cmakeArgs: '--build . --target doc' + cmakeArgs: "--build . --target doc" diff --git a/src/vendor/cigraph/etc/cmake/packaging.cmake b/src/vendor/cigraph/etc/cmake/packaging.cmake index a45497400e6..ec52c93d289 100644 --- a/src/vendor/cigraph/etc/cmake/packaging.cmake +++ b/src/vendor/cigraph/etc/cmake/packaging.cmake @@ -31,7 +31,7 @@ endif() ############################################################################# # Set source package name and format -set(CPACK_SOURCE_PACKAGE_FILE_NAME "igraph-${CMAKE_PROJECT_VERSION}") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "igraph-${PACKAGE_VERSION}") set(CPACK_SOURCE_GENERATOR "TGZ") # Declare what to include in the source tarball. Unfortunately we can only diff --git a/src/vendor/cigraph/etc/cmake/summary.cmake b/src/vendor/cigraph/etc/cmake/summary.cmake index 4c189f1395b..348b7d31e72 100644 --- a/src/vendor/cigraph/etc/cmake/summary.cmake +++ b/src/vendor/cigraph/etc/cmake/summary.cmake @@ -35,13 +35,13 @@ else() message(STATUS "Library type: static") endif() if(${IGRAPH_INTEGER_SIZE} STREQUAL "AUTO") - print_str("igraph_integer_t size" "auto") + print_str("igraph_int_t size" "auto") elseif(${IGRAPH_INTEGER_SIZE} STREQUAL 64) - print_str("igraph_integer_t size" "64 bits") + print_str("igraph_int_t size" "64 bits") elseif(${IGRAPH_INTEGER_SIZE} STREQUAL 32) - print_str("igraph_integer_t size" "32 bits") + print_str("igraph_int_t size" "32 bits") else() - print_str("igraph_integer_t size" "INVALID") + print_str("igraph_int_t size" "INVALID") endif() if(USE_CCACHE) if(CCACHE_PROGRAM) @@ -54,6 +54,7 @@ endif() message(STATUS " ") message(STATUS "----------[ Features ]----------") print_bool("GLPK for optimization" IGRAPH_GLPK_SUPPORT) +print_bool("Infomap community detection" IGRAPH_INFOMAP_SUPPORT) print_bool("Reading GraphML files" IGRAPH_GRAPHML_SUPPORT) print_bool("Thread-local storage" IGRAPH_ENABLE_TLS) print_bool("Link-time optimization" IGRAPH_ENABLE_LTO) @@ -64,7 +65,9 @@ foreach(DEPENDENCY ${ALL_DEPENDENCIES}) list(FIND VENDORED_DEPENDENCIES "${DEPENDENCY}" INDEX) if(INDEX EQUAL -1) print_bool("${DEPENDENCY}" ${DEPENDENCY}_FOUND) - else() + # This is a hack to skip printing Infomap, until + # support for linking to an external version is added + elseif(NOT "${DEPENDENCY}" STREQUAL "INFOMAP") print_str("${DEPENDENCY}" "vendored") endif() endforeach() diff --git a/src/vendor/cigraph/include/igraph.h b/src/vendor/cigraph/include/igraph.h index e50df3de8a0..72b827cc133 100644 --- a/src/vendor/cigraph/include/igraph.h +++ b/src/vendor/cigraph/include/igraph.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_adjlist.h b/src/vendor/cigraph/include/igraph_adjlist.h index 0a9885ac9a0..175de6dfb00 100644 --- a/src/vendor/cigraph/include/igraph_adjlist.h +++ b/src/vendor/cigraph/include/igraph_adjlist.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,20 +28,20 @@ IGRAPH_BEGIN_C_DECLS typedef struct igraph_adjlist_t { - igraph_integer_t length; + igraph_int_t length; igraph_vector_int_t *adjs; } igraph_adjlist_t; typedef struct igraph_inclist_t { - igraph_integer_t length; + igraph_int_t length; igraph_vector_int_t *incs; } igraph_inclist_t; IGRAPH_EXPORT igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple); -IGRAPH_EXPORT igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_integer_t no_of_nodes); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_adjlist_size(const igraph_adjlist_t *al); +IGRAPH_EXPORT igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_int_t no_of_nodes); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_adjlist_size(const igraph_adjlist_t *al); IGRAPH_EXPORT igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, @@ -54,8 +54,8 @@ IGRAPH_EXPORT void igraph_adjlist_sort(igraph_adjlist_t *al); IGRAPH_EXPORT igraph_error_t igraph_adjlist_simplify(igraph_adjlist_t *al); IGRAPH_EXPORT igraph_error_t igraph_adjlist_print(const igraph_adjlist_t *al); IGRAPH_EXPORT igraph_error_t igraph_adjlist_fprint(const igraph_adjlist_t *al, FILE *outfile); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_adjlist_has_edge(igraph_adjlist_t* al, igraph_integer_t from, igraph_integer_t to, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_adjlist_replace_edge(igraph_adjlist_t* al, igraph_integer_t from, igraph_integer_t oldto, igraph_integer_t newto, igraph_bool_t directed); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_adjlist_has_edge(igraph_adjlist_t* al, igraph_int_t from, igraph_int_t to, igraph_bool_t directed); +IGRAPH_EXPORT igraph_error_t igraph_adjlist_replace_edge(igraph_adjlist_t* al, igraph_int_t from, igraph_int_t oldto, igraph_int_t newto, igraph_bool_t directed); /** * \define igraph_adjlist_get @@ -70,7 +70,7 @@ IGRAPH_EXPORT igraph_error_t igraph_adjlist_replace_edge(igraph_adjlist_t* al, i * * Time complexity: O(1). */ -#define igraph_adjlist_get(al,no) (&(al)->adjs[(igraph_integer_t)(no)]) +#define igraph_adjlist_get(al,no) (&(al)->adjs[(igraph_int_t)(no)]) IGRAPH_EXPORT igraph_error_t igraph_adjlist(igraph_t *graph, const igraph_adjlist_t *adjlist, igraph_neimode_t mode, igraph_bool_t duplicate); @@ -79,8 +79,8 @@ IGRAPH_EXPORT igraph_error_t igraph_inclist_init(const igraph_t *graph, igraph_inclist_t *il, igraph_neimode_t mode, igraph_loops_t loops); -IGRAPH_EXPORT igraph_error_t igraph_inclist_init_empty(igraph_inclist_t *il, igraph_integer_t n); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_inclist_size(const igraph_inclist_t *al); +IGRAPH_EXPORT igraph_error_t igraph_inclist_init_empty(igraph_inclist_t *il, igraph_int_t n); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_inclist_size(const igraph_inclist_t *al); IGRAPH_EXPORT void igraph_inclist_destroy(igraph_inclist_t *il); IGRAPH_EXPORT void igraph_inclist_clear(igraph_inclist_t *il); IGRAPH_EXPORT igraph_error_t igraph_inclist_print(const igraph_inclist_t *il); @@ -99,11 +99,11 @@ IGRAPH_EXPORT igraph_error_t igraph_inclist_fprint(const igraph_inclist_t *il, F * * Time complexity: O(1). */ -#define igraph_inclist_get(il,no) (&(il)->incs[(igraph_integer_t)(no)]) +#define igraph_inclist_get(il,no) (&(il)->incs[(igraph_int_t)(no)]) typedef struct igraph_lazy_adjlist_t { const igraph_t *graph; - igraph_integer_t length; + igraph_int_t length; igraph_vector_int_t **adjs; igraph_neimode_t mode; igraph_loops_t loops; @@ -117,7 +117,7 @@ IGRAPH_EXPORT igraph_error_t igraph_lazy_adjlist_init(const igraph_t *graph, igraph_bool_t multiple); IGRAPH_EXPORT void igraph_lazy_adjlist_destroy(igraph_lazy_adjlist_t *al); IGRAPH_EXPORT void igraph_lazy_adjlist_clear(igraph_lazy_adjlist_t *al); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_adjlist_size(const igraph_lazy_adjlist_t *al); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_lazy_adjlist_size(const igraph_lazy_adjlist_t *al); /** * \define igraph_lazy_adjlist_has @@ -130,7 +130,7 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_adjlist_size(con * * Time complexity: O(1). */ -#define igraph_lazy_adjlist_has(al,no) ((al)->adjs[(igraph_integer_t)(no)] != NULL) +#define igraph_lazy_adjlist_has(al,no) ((al)->adjs[(igraph_int_t)(no)] != NULL) /** * \define igraph_lazy_adjlist_get @@ -155,13 +155,13 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_adjlist_size(con * first time, O(1) for subsequent calls. */ #define igraph_lazy_adjlist_get(al,no) \ - (igraph_lazy_adjlist_has(al,no) ? ((al)->adjs[(igraph_integer_t)(no)]) \ + (igraph_lazy_adjlist_has(al,no) ? ((al)->adjs[(igraph_int_t)(no)]) \ : (igraph_i_lazy_adjlist_get_real(al, no))) -IGRAPH_EXPORT igraph_vector_int_t *igraph_i_lazy_adjlist_get_real(igraph_lazy_adjlist_t *al, igraph_integer_t no); +IGRAPH_EXPORT igraph_vector_int_t *igraph_i_lazy_adjlist_get_real(igraph_lazy_adjlist_t *al, igraph_int_t no); typedef struct igraph_lazy_inclist_t { const igraph_t *graph; - igraph_integer_t length; + igraph_int_t length; igraph_vector_int_t **incs; igraph_neimode_t mode; igraph_loops_t loops; @@ -173,7 +173,7 @@ IGRAPH_EXPORT igraph_error_t igraph_lazy_inclist_init(const igraph_t *graph, igraph_loops_t loops); IGRAPH_EXPORT void igraph_lazy_inclist_destroy(igraph_lazy_inclist_t *il); IGRAPH_EXPORT void igraph_lazy_inclist_clear(igraph_lazy_inclist_t *il); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_inclist_size(const igraph_lazy_inclist_t *il); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_lazy_inclist_size(const igraph_lazy_inclist_t *il); /** * \define igraph_lazy_inclist_has @@ -186,7 +186,7 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_inclist_size(con * * Time complexity: O(1). */ -#define igraph_lazy_inclist_has(il,no) ((il)->incs[(igraph_integer_t)(no)] != NULL) +#define igraph_lazy_inclist_has(il,no) ((il)->incs[(igraph_int_t)(no)] != NULL) /** * \define igraph_lazy_inclist_get @@ -211,9 +211,9 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_lazy_inclist_size(con * time, O(1) for subsequent calls with the same \p no argument. */ #define igraph_lazy_inclist_get(il,no) \ - (igraph_lazy_inclist_has(il,no) ? ((il)->incs[(igraph_integer_t)(no)]) \ + (igraph_lazy_inclist_has(il,no) ? ((il)->incs[(igraph_int_t)(no)]) \ : (igraph_i_lazy_inclist_get_real(il,no))) -IGRAPH_EXPORT igraph_vector_int_t *igraph_i_lazy_inclist_get_real(igraph_lazy_inclist_t *il, igraph_integer_t no); +IGRAPH_EXPORT igraph_vector_int_t *igraph_i_lazy_inclist_get_real(igraph_lazy_inclist_t *il, igraph_int_t no); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_arpack.h b/src/vendor/cigraph/include/igraph_arpack.h index 9f1d2adb6fd..5912a66229b 100644 --- a/src/vendor/cigraph/include/igraph_arpack.h +++ b/src/vendor/cigraph/include/igraph_arpack.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -350,8 +350,8 @@ typedef enum { IGRAPH_EXPORT void igraph_arpack_options_init(igraph_arpack_options_t *o); IGRAPH_EXPORT igraph_arpack_options_t* igraph_arpack_options_get_default(void); -IGRAPH_EXPORT igraph_error_t igraph_arpack_storage_init(igraph_arpack_storage_t *s, igraph_integer_t maxn, - igraph_integer_t maxncv, igraph_integer_t maxldv, igraph_bool_t symm); +IGRAPH_EXPORT igraph_error_t igraph_arpack_storage_init(igraph_arpack_storage_t *s, igraph_int_t maxn, + igraph_int_t maxncv, igraph_int_t maxldv, igraph_bool_t symm); IGRAPH_EXPORT void igraph_arpack_storage_destroy(igraph_arpack_storage_t *s); /** @@ -385,7 +385,7 @@ IGRAPH_EXPORT igraph_error_t igraph_arpack_rnsolve(igraph_arpack_function_t *fun igraph_matrix_t *values, igraph_matrix_t *vectors); IGRAPH_EXPORT igraph_error_t igraph_arpack_unpack_complex(igraph_matrix_t *vectors, igraph_matrix_t *values, - igraph_integer_t nev); + igraph_int_t nev); IGRAPH_EXPORT const char* igraph_arpack_error_to_string(igraph_arpack_error_t error); IGRAPH_EXPORT igraph_arpack_error_t igraph_arpack_get_last_error(void); diff --git a/src/vendor/cigraph/include/igraph_attributes.h b/src/vendor/cigraph/include/igraph_attributes.h index de9c5343357..db0a3e64341 100644 --- a/src/vendor/cigraph/include/igraph_attributes.h +++ b/src/vendor/cigraph/include/igraph_attributes.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -137,11 +137,11 @@ IGRAPH_EXPORT igraph_error_t igraph_attribute_record_init_copy( 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( +IGRAPH_EXPORT igraph_int_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_attribute_record_t *attr, igraph_int_t new_size ); IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_name( igraph_attribute_record_t *attr, const char* name @@ -383,7 +383,7 @@ typedef struct igraph_attribute_table_t { 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_t *graph, igraph_int_t nv, const igraph_attribute_record_list_t *attr ); igraph_error_t (*permute_vertices)(const igraph_t *graph, @@ -449,17 +449,17 @@ IGRAPH_EXPORT igraph_real_t igraph_cattribute_GAN(const igraph_t *graph, const c IGRAPH_EXPORT igraph_bool_t igraph_cattribute_GAB(const igraph_t *graph, const char *name); IGRAPH_EXPORT const char* igraph_cattribute_GAS(const igraph_t *graph, const char *name); IGRAPH_EXPORT igraph_real_t igraph_cattribute_VAN(const igraph_t *graph, const char *name, - igraph_integer_t vid); + igraph_int_t vid); IGRAPH_EXPORT igraph_bool_t igraph_cattribute_VAB(const igraph_t *graph, const char *name, - igraph_integer_t vid); + igraph_int_t vid); IGRAPH_EXPORT const char* igraph_cattribute_VAS(const igraph_t *graph, const char *name, - igraph_integer_t vid); + igraph_int_t vid); IGRAPH_EXPORT igraph_real_t igraph_cattribute_EAN(const igraph_t *graph, const char *name, - igraph_integer_t eid); + igraph_int_t eid); IGRAPH_EXPORT igraph_bool_t igraph_cattribute_EAB(const igraph_t *graph, const char *name, - igraph_integer_t eid); + igraph_int_t eid); IGRAPH_EXPORT const char* igraph_cattribute_EAS(const igraph_t *graph, const char *name, - igraph_integer_t eid); + igraph_int_t eid); IGRAPH_EXPORT igraph_error_t igraph_cattribute_VANV(const igraph_t *graph, const char *name, igraph_vs_t vids, igraph_vector_t *result); @@ -489,17 +489,17 @@ IGRAPH_EXPORT igraph_error_t igraph_cattribute_GAB_set(igraph_t *graph, const ch IGRAPH_EXPORT igraph_error_t igraph_cattribute_GAS_set(igraph_t *graph, const char *name, const char *value); IGRAPH_EXPORT igraph_error_t igraph_cattribute_VAN_set(igraph_t *graph, const char *name, - igraph_integer_t vid, igraph_real_t value); + igraph_int_t vid, igraph_real_t value); IGRAPH_EXPORT igraph_error_t igraph_cattribute_VAB_set(igraph_t *graph, const char *name, - igraph_integer_t vid, igraph_bool_t value); + igraph_int_t vid, igraph_bool_t value); IGRAPH_EXPORT igraph_error_t igraph_cattribute_VAS_set(igraph_t *graph, const char *name, - igraph_integer_t vid, const char *value); + igraph_int_t vid, const char *value); IGRAPH_EXPORT igraph_error_t igraph_cattribute_EAN_set(igraph_t *graph, const char *name, - igraph_integer_t eid, igraph_real_t value); + igraph_int_t eid, igraph_real_t value); IGRAPH_EXPORT igraph_error_t igraph_cattribute_EAB_set(igraph_t *graph, const char *name, - igraph_integer_t eid, igraph_bool_t value); + igraph_int_t eid, igraph_bool_t value); IGRAPH_EXPORT igraph_error_t igraph_cattribute_EAS_set(igraph_t *graph, const char *name, - igraph_integer_t eid, const char *value); + igraph_int_t eid, const char *value); IGRAPH_EXPORT igraph_error_t igraph_cattribute_VAN_setv(igraph_t *graph, const char *name, const igraph_vector_t *v); diff --git a/src/vendor/cigraph/include/igraph_bipartite.h b/src/vendor/cigraph/include/igraph_bipartite.h index 923951a27fb..d1a0ee4d375 100644 --- a/src/vendor/cigraph/include/igraph_bipartite.h +++ b/src/vendor/cigraph/include/igraph_bipartite.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include "igraph_datatype.h" #include "igraph_constants.h" #include "igraph_error.h" +#include "igraph_graphicality.h" #include "igraph_types.h" #include "igraph_vector.h" #include "igraph_matrix.h" @@ -35,7 +36,7 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_full_bipartite(igraph_t *graph, igraph_vector_bool_t *types, - igraph_integer_t n1, igraph_integer_t n2, + igraph_int_t n1, igraph_int_t n2, igraph_bool_t directed, igraph_neimode_t mode); @@ -45,10 +46,10 @@ IGRAPH_EXPORT igraph_error_t igraph_create_bipartite(igraph_t *g, const igraph_v IGRAPH_EXPORT igraph_error_t igraph_bipartite_projection_size(const igraph_t *graph, const igraph_vector_bool_t *types, - igraph_integer_t *vcount1, - igraph_integer_t *ecount1, - igraph_integer_t *vcount2, - igraph_integer_t *ecount2); + igraph_int_t *vcount1, + igraph_int_t *ecount1, + igraph_int_t *vcount2, + igraph_int_t *ecount2); IGRAPH_EXPORT igraph_error_t igraph_bipartite_projection(const igraph_t *graph, const igraph_vector_bool_t *types, @@ -56,7 +57,7 @@ IGRAPH_EXPORT igraph_error_t igraph_bipartite_projection(const igraph_t *graph, igraph_t *proj2, igraph_vector_int_t *multiplicity1, igraph_vector_int_t *multiplicity2, - igraph_integer_t probe1); + igraph_int_t probe1); IGRAPH_EXPORT igraph_error_t igraph_biadjacency( igraph_t *graph, @@ -85,19 +86,25 @@ IGRAPH_EXPORT igraph_error_t igraph_is_bipartite(const igraph_t *graph, igraph_bool_t *res, igraph_vector_bool_t *types); -IGRAPH_EXPORT igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t *types, - igraph_integer_t n1, igraph_integer_t n2, - igraph_real_t p, igraph_bool_t directed, - igraph_neimode_t mode); - -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_bool_t multiple); - -IGRAPH_EXPORT igraph_error_t igraph_bipartite_iea_game( +IGRAPH_EXPORT igraph_error_t igraph_bipartite_game_gnp( + igraph_t *graph, + igraph_vector_bool_t *types, + igraph_int_t n1, igraph_int_t n2, igraph_real_t p, + igraph_bool_t directed, igraph_neimode_t mode, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled); + +IGRAPH_EXPORT igraph_error_t igraph_bipartite_game_gnm( + igraph_t *graph, + igraph_vector_bool_t *types, + igraph_int_t n1, igraph_int_t n2, igraph_int_t m, + igraph_bool_t directed, igraph_neimode_t mode, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_bipartite_iea_game( igraph_t *graph, igraph_vector_bool_t *types, - igraph_integer_t n1, igraph_integer_t n2, igraph_integer_t m, + igraph_int_t n1, igraph_int_t n2, igraph_int_t m, igraph_bool_t directed, igraph_neimode_t mode); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_bitset.h b/src/vendor/cigraph/include/igraph_bitset.h index 0d847730856..26962435132 100644 --- a/src/vendor/cigraph/include/igraph_bitset.h +++ b/src/vendor/cigraph/include/igraph_bitset.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -158,7 +158,7 @@ IGRAPH_BEGIN_C_DECLS * * Time complexity: O(1). */ -#define IGRAPH_BIT_NSLOTS(nbits) ((nbits + IGRAPH_INTEGER_SIZE - (igraph_integer_t)(1)) / IGRAPH_INTEGER_SIZE) +#define IGRAPH_BIT_NSLOTS(nbits) ((nbits + IGRAPH_INTEGER_SIZE - (igraph_int_t)(1)) / IGRAPH_INTEGER_SIZE) #if defined(__GNUC__) @@ -183,24 +183,24 @@ IGRAPH_BEGIN_C_DECLS #ifdef HAVE__POPCNT #define IGRAPH_I_POPCOUNT32(x) __popcnt(x) #else - igraph_integer_t igraph_i_popcnt(igraph_uint_t x); + igraph_int_t igraph_i_popcnt(igraph_uint_t x); #define IGRAPH_I_POPCOUNT32(x) igraph_i_popcnt(x) #endif #elif IGRAPH_INTEGER_SIZE == 64 #ifdef HAVE__POPCNT64 #define IGRAPH_I_POPCOUNT64(x) __popcnt64(x) #else - igraph_integer_t igraph_i_popcnt(igraph_uint_t x); + igraph_int_t igraph_i_popcnt(igraph_uint_t x); #define IGRAPH_I_POPCOUNT64(x) igraph_i_popcnt(x) #endif #else #error "Unexpected IGRAPH_INTEGER_SIZE value." #endif - igraph_integer_t igraph_i_ctz32(igraph_uint_t x); - igraph_integer_t igraph_i_ctz64(igraph_uint_t x); - igraph_integer_t igraph_i_clz32(igraph_uint_t x); - igraph_integer_t igraph_i_clz64(igraph_uint_t x); + igraph_int_t igraph_i_ctz32(igraph_uint_t x); + igraph_int_t igraph_i_ctz64(igraph_uint_t x); + igraph_int_t igraph_i_clz32(igraph_uint_t x); + igraph_int_t igraph_i_clz64(igraph_uint_t x); #define IGRAPH_I_CTZ32(x) igraph_i_ctz32(x) #define IGRAPH_I_CTZ64(x) igraph_i_ctz64(x) #define IGRAPH_I_CLZ32(x) igraph_i_clz32(x) @@ -225,24 +225,24 @@ IGRAPH_BEGIN_C_DECLS #define IGRAPH_CTO(x) IGRAPH_CTZ(~(x)) typedef struct { - igraph_integer_t size; + igraph_int_t size; igraph_uint_t *stor_begin; igraph_uint_t *stor_end; } igraph_bitset_t; -IGRAPH_EXPORT igraph_error_t igraph_bitset_init(igraph_bitset_t *bitset, igraph_integer_t size); +IGRAPH_EXPORT igraph_error_t igraph_bitset_init(igraph_bitset_t *bitset, igraph_int_t size); IGRAPH_EXPORT void igraph_bitset_destroy(igraph_bitset_t *bitset); IGRAPH_EXPORT igraph_error_t igraph_bitset_init_copy(igraph_bitset_t *dest, const igraph_bitset_t *src); IGRAPH_EXPORT igraph_error_t igraph_bitset_update(igraph_bitset_t *dest, const igraph_bitset_t *src); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_bitset_capacity(const igraph_bitset_t *bitset); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_bitset_size(const igraph_bitset_t *bitset); -IGRAPH_EXPORT igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_integer_t capacity); -IGRAPH_EXPORT igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_integer_t new_size); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_bitset_popcount(const igraph_bitset_t *bitset); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_bitset_countl_one(const igraph_bitset_t *bitset); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_bitset_countr_one(const igraph_bitset_t *bitset); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_capacity(const igraph_bitset_t *bitset); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_size(const igraph_bitset_t *bitset); +IGRAPH_EXPORT igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_int_t capacity); +IGRAPH_EXPORT igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_int_t new_size); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_popcount(const igraph_bitset_t *bitset); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countl_one(const igraph_bitset_t *bitset); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countr_one(const igraph_bitset_t *bitset); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_bitset_is_all_zero(const igraph_bitset_t *bitset); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_bitset_is_all_one(const igraph_bitset_t *bitset); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_bitset_is_any_zero(const igraph_bitset_t *bitset); diff --git a/src/vendor/cigraph/include/igraph_bitset_list.h b/src/vendor/cigraph/include/igraph_bitset_list.h index c837dc8c4fc..dd97dda28ff 100644 --- a/src/vendor/cigraph/include/igraph_bitset_list.h +++ b/src/vendor/cigraph/include/igraph_bitset_list.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_blas.h b/src/vendor/cigraph/include/igraph_blas.h index 40de616bf19..f10a2ca0e0d 100644 --- a/src/vendor/cigraph/include/igraph_blas.h +++ b/src/vendor/cigraph/include/igraph_blas.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_centrality.h b/src/vendor/cigraph/include/igraph_centrality.h index 13891b7eaf8..04fe3251c5b 100644 --- a/src/vendor/cigraph/include/igraph_centrality.h +++ b/src/vendor/cigraph/include/igraph_centrality.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -54,26 +54,43 @@ IGRAPH_EXPORT igraph_error_t igraph_harmonic_centrality_cutoff(const igraph_t *g igraph_bool_t normalized, igraph_real_t cutoff); -IGRAPH_EXPORT igraph_error_t igraph_betweenness(const igraph_t *graph, igraph_vector_t *res, - igraph_vs_t vids, igraph_bool_t directed, - const igraph_vector_t *weights); -IGRAPH_EXPORT igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t *res, - igraph_vs_t vids, igraph_bool_t directed, - const igraph_vector_t *weights, igraph_real_t cutoff); -IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness(const igraph_t *graph, igraph_vector_t *result, - igraph_bool_t directed, - const igraph_vector_t *weights); -IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vector_t *result, - igraph_bool_t directed, - const igraph_vector_t *weights, igraph_real_t cutoff); -IGRAPH_EXPORT igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t *res, - igraph_vs_t vids, igraph_bool_t directed, - igraph_vs_t sources, igraph_vs_t targets, - const igraph_vector_t *weights); -IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vector_t *res, - igraph_es_t eids, igraph_bool_t directed, - igraph_vs_t sources, igraph_vs_t targets, - const igraph_vector_t *weights); +IGRAPH_EXPORT igraph_error_t igraph_betweenness( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_vs_t vids, + igraph_bool_t directed, igraph_bool_t normalized); + +IGRAPH_EXPORT igraph_error_t igraph_betweenness_cutoff( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_vs_t vids, + igraph_bool_t directed, igraph_bool_t normalized, + igraph_real_t cutoff); + +IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, igraph_es_t eids, + igraph_bool_t directed, igraph_bool_t normalized); + +IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness_cutoff( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, igraph_es_t eids, + igraph_bool_t directed, igraph_bool_t normalized, + igraph_real_t cutoff); + +IGRAPH_EXPORT igraph_error_t igraph_betweenness_subset( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_vs_t sources, igraph_vs_t targets, + igraph_vs_t vids, + igraph_bool_t directed, igraph_bool_t normalized); + +IGRAPH_EXPORT igraph_error_t igraph_edge_betweenness_subset( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_vs_t sources, igraph_vs_t targets, + igraph_es_t eids, + igraph_bool_t directed, igraph_bool_t normalized); /** * \typedef igraph_pagerank_algo_t @@ -92,24 +109,30 @@ typedef enum { IGRAPH_PAGERANK_ALGO_PRPACK = 2 } igraph_pagerank_algo_t; -IGRAPH_EXPORT igraph_error_t igraph_pagerank(const igraph_t *graph, igraph_pagerank_algo_t algo, - igraph_vector_t *vector, - igraph_real_t *value, igraph_vs_t vids, - igraph_bool_t directed, igraph_real_t damping, - const igraph_vector_t *weights, igraph_arpack_options_t *options); -IGRAPH_EXPORT igraph_error_t igraph_personalized_pagerank(const igraph_t *graph, - igraph_pagerank_algo_t algo, igraph_vector_t *vector, - igraph_real_t *value, igraph_vs_t vids, - igraph_bool_t directed, igraph_real_t damping, - const igraph_vector_t *reset, - const igraph_vector_t *weights, igraph_arpack_options_t *options); -IGRAPH_EXPORT igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph, - igraph_pagerank_algo_t algo, - igraph_vector_t *vector, - igraph_real_t *value, igraph_vs_t vids, - igraph_bool_t directed, igraph_real_t damping, - igraph_vs_t reset_vids, - const igraph_vector_t *weights, igraph_arpack_options_t *options); +IGRAPH_EXPORT igraph_error_t igraph_pagerank( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *vector, igraph_real_t *value, + igraph_real_t damping, igraph_bool_t directed, + igraph_vs_t vids, + igraph_pagerank_algo_t algo, + igraph_arpack_options_t *options); + +IGRAPH_EXPORT igraph_error_t igraph_personalized_pagerank( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *vector, igraph_real_t *value, + const igraph_vector_t *reset, + igraph_real_t damping, igraph_bool_t directed, + igraph_vs_t vids, + igraph_pagerank_algo_t algo, + igraph_arpack_options_t *options); + +IGRAPH_EXPORT igraph_error_t igraph_personalized_pagerank_vs( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *vector, igraph_real_t *value, + igraph_vs_t reset_vids, igraph_real_t damping, + igraph_bool_t directed, igraph_vs_t vids, + igraph_pagerank_algo_t algo, + igraph_arpack_options_t *options); IGRAPH_EXPORT igraph_error_t igraph_eigenvector_centrality(const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, @@ -139,7 +162,7 @@ IGRAPH_EXPORT igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_real_t *theoretical_max, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_centralization_degree_tmax(const igraph_t *graph, - igraph_integer_t nodes, + igraph_int_t nodes, igraph_neimode_t mode, igraph_loops_t loops, igraph_real_t *res); @@ -151,7 +174,7 @@ IGRAPH_EXPORT igraph_error_t igraph_centralization_betweenness(const igraph_t *g igraph_real_t *theoretical_max, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_centralization_betweenness_tmax(const igraph_t *graph, - igraph_integer_t nodes, + igraph_int_t nodes, igraph_bool_t directed, igraph_real_t *res); @@ -162,7 +185,7 @@ IGRAPH_EXPORT igraph_error_t igraph_centralization_closeness(const igraph_t *gra igraph_real_t *theoretical_max, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_centralization_closeness_tmax(const igraph_t *graph, - igraph_integer_t nodes, + igraph_int_t nodes, igraph_neimode_t mode, igraph_real_t *res); @@ -175,7 +198,7 @@ IGRAPH_EXPORT igraph_error_t igraph_centralization_eigenvector_centrality(const igraph_real_t *theoretical_max, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_centralization_eigenvector_centrality_tmax(const igraph_t *graph, - igraph_integer_t nodes, + igraph_int_t nodes, igraph_neimode_t mode, igraph_real_t *res); diff --git a/src/vendor/cigraph/include/igraph_cliques.h b/src/vendor/cigraph/include/igraph_cliques.h index 019f6ffb1cf..c76ebd147bb 100644 --- a/src/vendor/cigraph/include/igraph_cliques.h +++ b/src/vendor/cigraph/include/igraph_cliques.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -32,50 +32,79 @@ IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques( - const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t min_size, igraph_integer_t max_size -); -IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_file(const igraph_t *graph, - FILE *outfile, - igraph_integer_t min_size, - igraph_integer_t max_size); -IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_count(const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t min_size, - igraph_integer_t max_size); + const igraph_t *graph, igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_file( + const igraph_t *graph, + FILE *outfile, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_count( + const igraph_t *graph, + igraph_int_t *res, + igraph_int_t min_size, igraph_int_t max_size); + IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_subset( - const igraph_t *graph, const igraph_vector_int_t *subset, - igraph_vector_int_list_t *res, igraph_integer_t *no, - FILE *outfile, igraph_integer_t min_size, igraph_integer_t max_size -); -IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_hist(const igraph_t *graph, - igraph_vector_t *hist, - igraph_integer_t min_size, - igraph_integer_t max_size); - -IGRAPH_EXPORT igraph_error_t igraph_cliques(const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t min_size, igraph_integer_t max_size); -IGRAPH_EXPORT igraph_error_t igraph_clique_size_hist(const igraph_t *graph, igraph_vector_t *hist, - igraph_integer_t min_size, igraph_integer_t max_size); -IGRAPH_EXPORT igraph_error_t igraph_largest_cliques(const igraph_t *graph, - igraph_vector_int_list_t *cliques); -IGRAPH_EXPORT igraph_error_t igraph_clique_number(const igraph_t *graph, igraph_integer_t *no); -IGRAPH_EXPORT igraph_error_t igraph_weighted_cliques(const igraph_t *graph, - const igraph_vector_t *vertex_weights, igraph_vector_int_list_t *res, - igraph_real_t min_weight, igraph_real_t max_weight, igraph_bool_t maximal); -IGRAPH_EXPORT igraph_error_t igraph_largest_weighted_cliques(const igraph_t *graph, - const igraph_vector_t *vertex_weights, igraph_vector_int_list_t *res); -IGRAPH_EXPORT igraph_error_t igraph_weighted_clique_number(const igraph_t *graph, - const igraph_vector_t *vertex_weights, igraph_real_t *res); -IGRAPH_EXPORT igraph_error_t igraph_independent_vertex_sets(const igraph_t *graph, - igraph_vector_int_list_t *res, - igraph_integer_t min_size, - igraph_integer_t max_size); -IGRAPH_EXPORT igraph_error_t igraph_largest_independent_vertex_sets(const igraph_t *graph, - igraph_vector_int_list_t *res); -IGRAPH_EXPORT igraph_error_t igraph_maximal_independent_vertex_sets(const igraph_t *graph, - igraph_vector_int_list_t *res); -IGRAPH_EXPORT igraph_error_t igraph_independence_number(const igraph_t *graph, igraph_integer_t *no); + const igraph_t *graph, const igraph_vector_int_t *subset, + igraph_vector_int_list_t *res, igraph_int_t *no, FILE *outfile, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_hist( + const igraph_t *graph, + igraph_vector_t *hist, + igraph_int_t min_size, igraph_int_t max_size); + +IGRAPH_EXPORT igraph_error_t igraph_cliques( + const igraph_t *graph, igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_clique_size_hist( + const igraph_t *graph, igraph_vector_t *hist, + igraph_int_t min_size, igraph_int_t max_size); + +IGRAPH_EXPORT igraph_error_t igraph_largest_cliques( + const igraph_t *graph, + igraph_vector_int_list_t *cliques); + +IGRAPH_EXPORT igraph_error_t igraph_clique_number(const igraph_t *graph, igraph_int_t *no); + +IGRAPH_EXPORT igraph_error_t igraph_weighted_cliques( + const igraph_t *graph, const igraph_vector_t *vertex_weights, + igraph_vector_int_list_t *res, + igraph_bool_t maximal, + igraph_real_t min_weight, igraph_real_t max_weight, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_largest_weighted_cliques( + const igraph_t *graph, const igraph_vector_t *vertex_weights, + igraph_vector_int_list_t *res); + +IGRAPH_EXPORT igraph_error_t igraph_weighted_clique_number( + const igraph_t *graph, const igraph_vector_t *vertex_weights, + igraph_real_t *res); + +IGRAPH_EXPORT igraph_error_t igraph_independent_vertex_sets( + const igraph_t *graph, + igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_largest_independent_vertex_sets( + const igraph_t *graph, + igraph_vector_int_list_t *res); + +IGRAPH_EXPORT igraph_error_t igraph_maximal_independent_vertex_sets( + const igraph_t *graph, + igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_independence_number(const igraph_t *graph, igraph_int_t *no); /** * \typedef igraph_clique_handler_t @@ -97,14 +126,15 @@ IGRAPH_EXPORT igraph_error_t igraph_independence_number(const igraph_t *graph, i */ typedef igraph_error_t igraph_clique_handler_t(const igraph_vector_int_t *clique, void *arg); -IGRAPH_EXPORT igraph_error_t igraph_cliques_callback(const igraph_t *graph, - igraph_integer_t min_size, igraph_integer_t max_size, - igraph_clique_handler_t *cliquehandler_fn, void *arg); - -IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_callback(const igraph_t *graph, - igraph_clique_handler_t *cliquehandler_fn, void *arg, - igraph_integer_t min_size, igraph_integer_t max_size); +IGRAPH_EXPORT igraph_error_t igraph_cliques_callback( + const igraph_t *graph, + igraph_int_t min_size, igraph_int_t max_size, + igraph_clique_handler_t *cliquehandler_fn, void *arg); +IGRAPH_EXPORT igraph_error_t igraph_maximal_cliques_callback( + const igraph_t *graph, + igraph_int_t min_size, igraph_int_t max_size, + igraph_clique_handler_t *cliquehandler_fn, void *arg); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_cocitation.h b/src/vendor/cigraph/include/igraph_cocitation.h index 23baa8607b1..706ca9a8828 100644 --- a/src/vendor/cigraph/include/igraph_cocitation.h +++ b/src/vendor/cigraph/include/igraph_cocitation.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_cohesive_blocks.h b/src/vendor/cigraph/include/igraph_cohesive_blocks.h index 372a4a476e3..924da037a62 100644 --- a/src/vendor/cigraph/include/igraph_cohesive_blocks.h +++ b/src/vendor/cigraph/include/igraph_cohesive_blocks.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_coloring.h b/src/vendor/cigraph/include/igraph_coloring.h index c64423b3cca..1831ad61fa1 100644 --- a/src/vendor/cigraph/include/igraph_coloring.h +++ b/src/vendor/cigraph/include/igraph_coloring.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2017-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_community.h b/src/vendor/cigraph/include/igraph_community.h index 1e8be0aa9f3..c8cab386534 100644 --- a/src/vendor/cigraph/include/igraph_community.h +++ b/src/vendor/cigraph/include/igraph_community.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -59,7 +59,7 @@ IGRAPH_EXPORT igraph_error_t igraph_community_spinglass(const igraph_t *graph, igraph_real_t *temperature, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t spins, + igraph_int_t spins, igraph_bool_t parupdate, igraph_real_t starttemp, igraph_real_t stoptemp, @@ -71,19 +71,19 @@ IGRAPH_EXPORT igraph_error_t igraph_community_spinglass(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_community_spinglass_single(const igraph_t *graph, const igraph_vector_t *weights, - igraph_integer_t vertex, + igraph_int_t vertex, igraph_vector_int_t *community, igraph_real_t *cohesion, igraph_real_t *adhesion, igraph_real_t *inner_links, igraph_real_t *outer_links, - igraph_integer_t spins, + igraph_int_t spins, igraph_spincomm_update_t update_rule, igraph_real_t gamma); IGRAPH_EXPORT igraph_error_t igraph_community_walktrap(const igraph_t *graph, const igraph_vector_t *weights, - igraph_integer_t steps, + igraph_int_t steps, igraph_matrix_int_t *merges, igraph_vector_t *modularity, igraph_vector_int_t *membership); @@ -91,7 +91,9 @@ IGRAPH_EXPORT igraph_error_t igraph_community_walktrap(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_community_infomap(const igraph_t *graph, const igraph_vector_t *edge_weights, const igraph_vector_t *vertex_weights, - igraph_integer_t nb_trials, + igraph_int_t nb_trials, + igraph_bool_t is_regularized, + igraph_real_t regularization_strength, igraph_vector_int_t *membership, igraph_real_t *codelength); @@ -121,16 +123,16 @@ IGRAPH_EXPORT igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, igraph_vector_int_t *membership); IGRAPH_EXPORT igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, - igraph_integer_t nodes, - igraph_integer_t steps, + igraph_int_t nodes, + igraph_int_t steps, igraph_vector_int_t *membership, igraph_vector_int_t *csize); IGRAPH_EXPORT igraph_error_t igraph_le_community_to_membership(const igraph_matrix_int_t *merges, - igraph_integer_t steps, + igraph_int_t steps, igraph_vector_int_t *membership, igraph_vector_int_t *csize); -IGRAPH_EXPORT igraph_error_t igraph_community_voronoi( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_community_voronoi( const igraph_t *graph, igraph_vector_int_t *membership, igraph_vector_int_t *generators, igraph_real_t *modularity, const igraph_vector_t *lengths, const igraph_vector_t *weights, @@ -151,7 +153,7 @@ IGRAPH_EXPORT igraph_error_t igraph_modularity_matrix(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_reindex_membership(igraph_vector_int_t *membership, igraph_vector_int_t *new_to_old, - igraph_integer_t *nb_clusters); + igraph_int_t *nb_clusters); typedef enum { IGRAPH_LEVC_HIST_SPLIT = 1, IGRAPH_LEVC_HIST_FAILED, @@ -189,7 +191,7 @@ typedef enum { IGRAPH_LEVC_HIST_SPLIT = 1, typedef igraph_error_t igraph_community_leading_eigenvector_callback_t( const igraph_vector_int_t *membership, - igraph_integer_t comm, + igraph_int_t comm, igraph_real_t eigenvalue, const igraph_vector_t *eigenvector, igraph_arpack_function_t *arpack_multiplier, @@ -200,7 +202,7 @@ IGRAPH_EXPORT igraph_error_t igraph_community_leading_eigenvector(const igraph_t const igraph_vector_t *weights, igraph_matrix_int_t *merges, igraph_vector_int_t *membership, - igraph_integer_t steps, + igraph_int_t steps, igraph_arpack_options_t *options, igraph_real_t *modularity, igraph_bool_t start, @@ -211,7 +213,7 @@ IGRAPH_EXPORT igraph_error_t igraph_community_leading_eigenvector(const igraph_t void *callback_extra); IGRAPH_EXPORT igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, - igraph_integer_t no_of_communities, + igraph_int_t no_of_communities, igraph_vector_int_t *membership); @@ -230,6 +232,12 @@ IGRAPH_EXPORT igraph_error_t igraph_community_multilevel(const igraph_t *graph, igraph_matrix_int_t *memberships, igraph_vector_t *modularity); +typedef enum { + IGRAPH_LEIDEN_OBJECTIVE_MODULARITY = 0, + IGRAPH_LEIDEN_OBJECTIVE_CPM, + IGRAPH_LEIDEN_OBJECTIVE_ER +} igraph_leiden_objective_t; + IGRAPH_EXPORT igraph_error_t igraph_community_leiden( const igraph_t *graph, const igraph_vector_t *edge_weights, @@ -238,9 +246,21 @@ IGRAPH_EXPORT igraph_error_t igraph_community_leiden( igraph_real_t resolution, igraph_real_t beta, igraph_bool_t start, - igraph_integer_t n_iterations, + igraph_int_t n_iterations, + igraph_vector_int_t *membership, + igraph_int_t *nb_clusters, igraph_real_t *quality); + +IGRAPH_EXPORT igraph_error_t igraph_community_leiden_simple( + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_leiden_objective_t objective, + igraph_real_t resolution, + igraph_real_t beta, + igraph_bool_t start, + igraph_int_t n_iterations, igraph_vector_int_t *membership, - igraph_integer_t *nb_clusters, igraph_real_t *quality); + igraph_int_t *nb_clusters, + igraph_real_t *quality); /* -------------------------------------------------- */ /* Community Structure Comparison */ @@ -252,8 +272,8 @@ IGRAPH_EXPORT igraph_error_t igraph_compare_communities(const igraph_vector_int_ igraph_community_comparison_t method); IGRAPH_EXPORT igraph_error_t igraph_split_join_distance(const igraph_vector_int_t *comm1, const igraph_vector_int_t *comm2, - igraph_integer_t* distance12, - igraph_integer_t* distance21); + igraph_int_t* distance12, + igraph_int_t* distance21); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_complex.h b/src/vendor/cigraph/include/igraph_complex.h index 4295bc8dda6..36d3f2b572b 100644 --- a/src/vendor/cigraph/include/igraph_complex.h +++ b/src/vendor/cigraph/include/igraph_complex.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_components.h b/src/vendor/cigraph/include/igraph_components.h index 79fffa8dc33..e784c04f921 100644 --- a/src/vendor/cigraph/include/igraph_components.h +++ b/src/vendor/cigraph/include/igraph_components.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -36,17 +36,17 @@ IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ IGRAPH_EXPORT igraph_error_t igraph_connected_components(const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no, + igraph_vector_int_t *csize, igraph_int_t *no, igraph_connectedness_t mode); IGRAPH_EXPORT igraph_error_t igraph_is_connected(const igraph_t *graph, igraph_bool_t *res, igraph_connectedness_t mode); IGRAPH_EXPORT igraph_error_t igraph_decompose(const igraph_t *graph, igraph_graph_list_t *components, igraph_connectedness_t mode, - igraph_integer_t maxcompno, igraph_integer_t minelements); + igraph_int_t maxcompno, igraph_int_t minelements); IGRAPH_EXPORT igraph_error_t igraph_articulation_points(const igraph_t *graph, igraph_vector_int_t *res); IGRAPH_EXPORT igraph_error_t igraph_biconnected_components(const igraph_t *graph, - igraph_integer_t *no, + igraph_int_t *no, igraph_vector_int_list_t *tree_edges, igraph_vector_int_list_t *component_edges, igraph_vector_int_list_t *components, @@ -54,17 +54,17 @@ 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); -IGRAPH_EXPORT igraph_error_t igraph_bond_percolation( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_bond_percolation( const igraph_t *graph, igraph_vector_int_t *giant_size, igraph_vector_int_t *vertex_count, const igraph_vector_int_t *edge_order); -IGRAPH_EXPORT igraph_error_t igraph_site_percolation( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_site_percolation( const igraph_t *graph, igraph_vector_int_t *giant_size, igraph_vector_int_t *edge_count, const igraph_vector_int_t *vertex_order); -IGRAPH_EXPORT igraph_error_t igraph_edgelist_percolation( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_edgelist_percolation( const igraph_vector_int_t *edges, igraph_vector_int_t *giant_size, igraph_vector_int_t *vertex_count); diff --git a/src/vendor/cigraph/include/igraph_config.h.in b/src/vendor/cigraph/include/igraph_config.h.in index 697dbfebc37..d8c910cdd2c 100644 --- a/src/vendor/cigraph/include/igraph_config.h.in +++ b/src/vendor/cigraph/include/igraph_config.h.in @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_constants.h b/src/vendor/cigraph/include/igraph_constants.h index 2205ee1fbdc..a9381ab7c40 100644 --- a/src/vendor/cigraph/include/igraph_constants.h +++ b/src/vendor/cigraph/include/igraph_constants.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,21 +27,83 @@ IGRAPH_BEGIN_C_DECLS /* Constants */ /* -------------------------------------------------- */ +/** + * \define IGRAPH_UNLIMITED + * \brief Constant for "do not limit results". + * + * A constant signifying that no limitation should be used with various cutoff, + * size limit or result set size parameters, such as minimum or maximum clique + * size, number of results returned, cutoff for path lengths, etc. Currently + * defined to -1. + */ +#define IGRAPH_UNLIMITED (-1) +/* Note to maintainers: IGRAPH_UNLIMITED is intended to support readability + * when *negative* parameter values indicate "no limit". Do not test + * directly against IGRAPH_UNLIMITED in implementations, test for negative + * values instead. */ + /* These constants are meant to be used for sake of readability */ enum { IGRAPH_UNDIRECTED = 0, IGRAPH_DIRECTED = 1 }; enum { IGRAPH_NO_MULTIPLE = 0, IGRAPH_MULTIPLE = 1 }; +enum { IGRAPH_EDGE_UNLABELED = 0, IGRAPH_EDGE_LABELED = 1 }; -/* Note for the enum below: yes, IGRAPH_LOOPS_TWICE is 1, and IGRAPH_LOOPS_ONCE +/** + * \typedef igraph_loops_t + * \brief How to interpret self-loops in undirected graphs? + * + * Controls the interpretation of self-loops in undirected graphs, typically + * in the context of adjacency matrices or degrees. + * + * These constants are also used to improve readability in + * boolean contexts, with \c IGRAPH_NO_LOOPS, equivalent to \c false, + * signifying that loops should be ignored and \c IGRAPH_LOOPS, equivalent + * to \c true, that loops should be considered. + * + * \enumval IGRAPH_NO_LOOPS Self-loops are ignored. + * \enumval IGRAPH_LOOPS_TWICE Self-loops are considered, and counted twice + * in undirected graphs. For example, a self-loop contributes two to the + * degree of a vertex and to diagonal entries of adjacency matrices. This + * is the standard interpretation in graph theory, thus \c IGRAPH_LOOPS + * serves as an alias for this option. + * \enumval IGRAPH_LOOPS_ONCE Self-loops are considered, and counted only + * once in undirected graphs. + */ +typedef enum { + IGRAPH_NO_LOOPS = 0, + IGRAPH_LOOPS_TWICE = 1, + IGRAPH_LOOPS_ONCE = 2, + IGRAPH_LOOPS = IGRAPH_LOOPS_TWICE +} igraph_loops_t; +/* Note for the enum above: yes, IGRAPH_LOOPS_TWICE is 1, and IGRAPH_LOOPS_ONCE * is 2. This is intentional, for the sake of backwards compatibility with * earlier versions where we only had IGRAPH_LOOPS and it meant * IGRAPH_LOOPS_TWICE */ -typedef enum { IGRAPH_NO_LOOPS = 0, IGRAPH_LOOPS = 1, IGRAPH_LOOPS_TWICE = 1, IGRAPH_LOOPS_ONCE = 2 } igraph_loops_t; typedef enum { IGRAPH_ASCENDING = 0, IGRAPH_DESCENDING = 1 } igraph_order_t; -/* Do not renumber the following values! Some internal code treats them as bitmasks +/** + * \typedef igraph_neimode_t + * \brief How to interpret edge directions in directed graphs? + * + * These "neighbor mode" constants are typically used to specify the treatment + * of edge directions in directed graphs, or which vertices to consider as + * adjacent to (i.e. neighbor of) a vertex. It is typically ignored in undirected + * graphs. + * + * \enumval IGRAPH_OUT Follow edge directions in directed graphs, or consider + * out-neighbors of vertices. + * \enumval IGRAPH_IN Follow edges in the reverse direction in directed graphs, + * or consider in-neighbors of vertices. + * \enumval IGRAPH_ALL Ignore edge directions in directed graphs, or consider + * all neighbours (both out and in-neighbors) of vertices. + */ +typedef enum { + IGRAPH_OUT = 1, + IGRAPH_IN = 2, + IGRAPH_ALL = 3 +} igraph_neimode_t; +/* Do not renumber the vaues above! Some internal code treats them as bitmasks * and assumes that IGRAPH_ALL == IGRAPH_IN | IGRAPH_OUT and IGRAPH_IN & IGRAPH_OUT == 0. */ -typedef enum { IGRAPH_OUT = 1, IGRAPH_IN = 2, IGRAPH_ALL = 3 } igraph_neimode_t; /* Reverse IGRAPH_OUT to IGRAPH_IN and vice versa. Leave other values alone. */ #define IGRAPH_REVERSE_MODE(mode) \ @@ -206,9 +268,9 @@ typedef enum { IGRAPH_PRODUCT_CARTESIAN = 0, * \enumval IGRAPH_LPA_FAST Sample from dominant labels, only check neighbors */ typedef enum { - IGRAPH_LPA_DOMINANCE = 0, // Sample from dominant labels, check for dominance after each iteration - IGRAPH_LPA_RETENTION, // Keep current label if among dominant labels, only check if labels changed - IGRAPH_LPA_FAST // Sample from dominant labels, only check neighbors + IGRAPH_LPA_DOMINANCE = 0, /* Sample from dominant labels, check for dominance after each iteration. */ + IGRAPH_LPA_RETENTION, /* Keep current label if among dominant labels, only check if labels changed. */ + IGRAPH_LPA_FAST /* Sample from dominant labels, only check neighbors. */ } igraph_lpa_variant_t; IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_constructors.h b/src/vendor/cigraph/include/igraph_constructors.h index c42907523e4..f2a22ecfbf6 100644 --- a/src/vendor/cigraph/include/igraph_constructors.h +++ b/src/vendor/cigraph/include/igraph_constructors.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -34,9 +34,9 @@ IGRAPH_BEGIN_C_DECLS /* Constructors, deterministic */ /* -------------------------------------------------- */ -IGRAPH_EXPORT igraph_error_t igraph_create(igraph_t *graph, const igraph_vector_int_t *edges, igraph_integer_t n, +IGRAPH_EXPORT igraph_error_t igraph_create(igraph_t *graph, const igraph_vector_int_t *edges, igraph_int_t n, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_small(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, +IGRAPH_EXPORT igraph_error_t igraph_small(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, int first, ...); IGRAPH_EXPORT igraph_error_t igraph_adjacency( igraph_t *graph, const igraph_matrix_t *adjmatrix, igraph_adjacency_t mode, @@ -46,51 +46,51 @@ IGRAPH_EXPORT igraph_error_t igraph_weighted_adjacency( igraph_vector_t *weights, igraph_loops_t loops); IGRAPH_EXPORT igraph_error_t igraph_sparse_adjacency(igraph_t *graph, igraph_sparsemat_t *adjmatrix, igraph_adjacency_t mode, igraph_loops_t loops); IGRAPH_EXPORT igraph_error_t igraph_sparse_weighted_adjacency(igraph_t *graph, igraph_sparsemat_t *adjmatrix, igraph_adjacency_t mode, igraph_vector_t *weights, igraph_loops_t loops); -IGRAPH_EXPORT igraph_error_t igraph_star(igraph_t *graph, igraph_integer_t n, igraph_star_mode_t mode, - igraph_integer_t center); -IGRAPH_EXPORT igraph_error_t igraph_wheel(igraph_t *graph, igraph_integer_t n, igraph_wheel_mode_t mode, - igraph_integer_t center); +IGRAPH_EXPORT igraph_error_t igraph_star(igraph_t *graph, igraph_int_t n, igraph_star_mode_t mode, + igraph_int_t center); +IGRAPH_EXPORT igraph_error_t igraph_wheel(igraph_t *graph, igraph_int_t n, igraph_wheel_mode_t mode, + igraph_int_t center); IGRAPH_EXPORT igraph_error_t igraph_hypercube(igraph_t *graph, - igraph_integer_t n, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_square_lattice(igraph_t *graph, const igraph_vector_int_t *dimvector, igraph_integer_t nei, + igraph_int_t n, igraph_bool_t directed); +IGRAPH_EXPORT igraph_error_t igraph_square_lattice(igraph_t *graph, const igraph_vector_int_t *dimvector, igraph_int_t nei, igraph_bool_t directed, igraph_bool_t mutual, const igraph_vector_bool_t *circular); -IGRAPH_EXPORT igraph_error_t igraph_ring(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, +IGRAPH_EXPORT igraph_error_t igraph_ring(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t mutual, igraph_bool_t circular); IGRAPH_EXPORT igraph_error_t igraph_path_graph( - igraph_t *graph, igraph_integer_t n, + igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t mutual); IGRAPH_EXPORT igraph_error_t igraph_cycle_graph( - igraph_t *graph, igraph_integer_t n, + igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t mutual); -IGRAPH_EXPORT igraph_error_t igraph_kary_tree(igraph_t *graph, igraph_integer_t n, igraph_integer_t children, +IGRAPH_EXPORT igraph_error_t igraph_kary_tree(igraph_t *graph, igraph_int_t n, igraph_int_t children, igraph_tree_mode_t type); IGRAPH_EXPORT igraph_error_t igraph_symmetric_tree(igraph_t *graph, const igraph_vector_int_t *branches, igraph_tree_mode_t type); -IGRAPH_EXPORT igraph_error_t igraph_regular_tree(igraph_t *graph, igraph_integer_t h, igraph_integer_t k, +IGRAPH_EXPORT igraph_error_t igraph_regular_tree(igraph_t *graph, igraph_int_t h, igraph_int_t k, igraph_tree_mode_t type); IGRAPH_EXPORT igraph_error_t igraph_tree_from_parent_vector(igraph_t *graph, const igraph_vector_int_t *parents, igraph_tree_mode_t mode); IGRAPH_EXPORT igraph_error_t igraph_from_prufer(igraph_t *graph, const igraph_vector_int_t *prufer); -IGRAPH_EXPORT igraph_error_t igraph_full(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, igraph_bool_t loops); +IGRAPH_EXPORT igraph_error_t igraph_full(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_full_multipartite(igraph_t *graph, igraph_vector_int_t *types, const igraph_vector_int_t *n, igraph_bool_t directed, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_turan(igraph_t *graph, igraph_vector_int_t *types, igraph_integer_t n, igraph_integer_t r); -IGRAPH_EXPORT igraph_error_t igraph_full_citation(igraph_t *graph, igraph_integer_t n, +IGRAPH_EXPORT igraph_error_t igraph_turan(igraph_t *graph, igraph_vector_int_t *types, igraph_int_t n, igraph_int_t r); +IGRAPH_EXPORT igraph_error_t igraph_full_citation(igraph_t *graph, igraph_int_t n, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_atlas(igraph_t *graph, igraph_integer_t number); -IGRAPH_EXPORT igraph_error_t igraph_extended_chordal_ring(igraph_t *graph, igraph_integer_t nodes, +IGRAPH_EXPORT igraph_error_t igraph_atlas(igraph_t *graph, igraph_int_t number); +IGRAPH_EXPORT igraph_error_t igraph_extended_chordal_ring(igraph_t *graph, igraph_int_t nodes, const igraph_matrix_int_t *W, igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_linegraph(const igraph_t *graph, igraph_t *linegraph); -IGRAPH_EXPORT igraph_error_t igraph_de_bruijn(igraph_t *graph, igraph_integer_t m, igraph_integer_t n); -IGRAPH_EXPORT igraph_error_t igraph_circulant(igraph_t *graph, igraph_integer_t n, const igraph_vector_int_t *l, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_generalized_petersen(igraph_t *graph, igraph_integer_t n, igraph_integer_t k); -IGRAPH_EXPORT igraph_error_t igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_t n); +IGRAPH_EXPORT igraph_error_t igraph_de_bruijn(igraph_t *graph, igraph_int_t m, igraph_int_t n); +IGRAPH_EXPORT igraph_error_t igraph_circulant(igraph_t *graph, igraph_int_t n, const igraph_vector_int_t *l, igraph_bool_t directed); +IGRAPH_EXPORT igraph_error_t igraph_generalized_petersen(igraph_t *graph, igraph_int_t n, igraph_int_t k); +IGRAPH_EXPORT igraph_error_t igraph_kautz(igraph_t *graph, igraph_int_t m, igraph_int_t n); IGRAPH_EXPORT igraph_error_t igraph_famous(igraph_t *graph, const char *name); -IGRAPH_EXPORT igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, +IGRAPH_EXPORT igraph_error_t igraph_lcf(igraph_t *graph, igraph_int_t n, const igraph_vector_int_t *shifts, - igraph_integer_t repeats); -IGRAPH_EXPORT igraph_error_t igraph_lcf_small(igraph_t *graph, igraph_integer_t n, ...); + igraph_int_t repeats); +IGRAPH_EXPORT igraph_error_t igraph_lcf_small(igraph_t *graph, igraph_int_t n, ...); IGRAPH_EXPORT igraph_error_t igraph_realize_degree_sequence(igraph_t *graph, const igraph_vector_int_t *outdeg, const igraph_vector_int_t *indeg, igraph_edge_type_sw_t allowed_edge_types, @@ -98,8 +98,7 @@ IGRAPH_EXPORT igraph_error_t igraph_realize_degree_sequence(igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_triangular_lattice(igraph_t *graph, const igraph_vector_int_t *dims, igraph_bool_t directed, igraph_bool_t mutual); IGRAPH_EXPORT igraph_error_t igraph_hexagonal_lattice(igraph_t *graph, const igraph_vector_int_t *dims, igraph_bool_t directed, igraph_bool_t mutual); IGRAPH_EXPORT igraph_error_t igraph_realize_bipartite_degree_sequence(igraph_t *graph, const igraph_vector_int_t *deg1, const igraph_vector_int_t *deg2, igraph_edge_type_sw_t allowed_edge_types, igraph_realize_degseq_t method); -IGRAPH_EXPORT igraph_error_t igraph_realize_bipartite_degree_sequence(igraph_t *graph, const igraph_vector_int_t *deg1, const igraph_vector_int_t *deg2, const igraph_edge_type_sw_t allowed_edge_types, const igraph_realize_degseq_t method); -IGRAPH_EXPORT igraph_error_t igraph_mycielski_graph(igraph_t *graph, igraph_integer_t k); +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_mycielski_graph(igraph_t *graph, igraph_int_t k); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_conversion.h b/src/vendor/cigraph/include/igraph_conversion.h index 8915dc9d69f..54a93f77ff8 100644 --- a/src/vendor/cigraph/include/igraph_conversion.h +++ b/src/vendor/cigraph/include/igraph_conversion.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_cycles.h b/src/vendor/cigraph/include/igraph_cycles.h index 94d4d7568ec..93e9f5ec73e 100644 --- a/src/vendor/cigraph/include/igraph_cycles.h +++ b/src/vendor/cigraph/include/igraph_cycles.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -41,20 +41,16 @@ IGRAPH_EXPORT igraph_error_t igraph_is_dag(const igraph_t *graph, igraph_bool_t /* Cycle bases */ /* -------------------------------------------------- */ -IGRAPH_EXPORT igraph_error_t igraph_fundamental_cycles( - const igraph_t *graph, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_fundamental_cycles( + const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *result, - igraph_integer_t start_vid, - igraph_integer_t bfs_cutoff, - const igraph_vector_t *weights); + igraph_int_t start_vid, igraph_real_t bfs_cutoff); -IGRAPH_EXPORT igraph_error_t igraph_minimum_cycle_basis( - const igraph_t *graph, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_minimum_cycle_basis( + const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *result, - igraph_integer_t bfs_cutoff, - igraph_bool_t complete, - igraph_bool_t use_cycle_order, - const igraph_vector_t *weights); + igraph_real_t bfs_cutoff, + igraph_bool_t complete, igraph_bool_t use_cycle_order); IGRAPH_EXPORT igraph_error_t igraph_find_cycle( const igraph_t *graph, @@ -80,20 +76,27 @@ typedef igraph_error_t igraph_cycle_handler_t( const igraph_vector_int_t *edges, void *arg); -IGRAPH_EXPORT igraph_error_t igraph_simple_cycles_callback( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_simple_cycles_callback( const igraph_t *graph, igraph_neimode_t mode, - igraph_integer_t min_cycle_length, - igraph_integer_t max_cycle_length, + igraph_int_t min_cycle_length, + igraph_int_t max_cycle_length, igraph_cycle_handler_t *callback, void *arg); -IGRAPH_EXPORT igraph_error_t igraph_simple_cycles( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_simple_cycles( const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, + igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, igraph_neimode_t mode, - igraph_integer_t min_cycle_length, - igraph_integer_t max_cycle_length); + igraph_int_t min_cycle_length, igraph_int_t max_cycle_length, + igraph_int_t max_results); + +IGRAPH_EXPORT igraph_error_t igraph_feedback_arc_set( + const igraph_t *graph, igraph_vector_int_t *result, + const igraph_vector_t *weights, igraph_fas_algorithm_t algo); + +IGRAPH_EXPORT igraph_error_t igraph_feedback_vertex_set( + const igraph_t *graph, igraph_vector_int_t *result, + const igraph_vector_t *vertex_weights, igraph_fvs_algorithm_t algo); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_datatype.h b/src/vendor/cigraph/include/igraph_datatype.h index 50617599c89..1c36d1d46c7 100644 --- a/src/vendor/cigraph/include/igraph_datatype.h +++ b/src/vendor/cigraph/include/igraph_datatype.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -103,7 +103,7 @@ typedef enum { * and \c |E| edges is \c O(|E|+|V|). */ typedef struct { - igraph_integer_t n; + igraph_int_t n; igraph_bool_t directed; igraph_vector_int_t from; igraph_vector_int_t to; diff --git a/src/vendor/cigraph/include/igraph_decls.h b/src/vendor/cigraph/include/igraph_decls.h index ee39fed2c55..1c63c1f869f 100644 --- a/src/vendor/cigraph/include/igraph_decls.h +++ b/src/vendor/cigraph/include/igraph_decls.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2016-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -76,3 +76,12 @@ /* Used instead of IGRAPH_EXPORT with functions that need to be tested, * but are not part of the public API. */ #define IGRAPH_PRIVATE_EXPORT IGRAPH_EXPORT + +/* Marks experimental functions. If IGRAPH_WARN_EXPERIMENTAL is defined to a + * nonzero value, supported compilers will emit a warning when these functions + * are used. */ +#if defined(__GNUC__) && IGRAPH_WARN_EXPERIMENTAL +#define IGRAPH_EXPERIMENTAL __attribute__((__warning__("Experimental function."))) +#else +#define IGRAPH_EXPERIMENTAL /* empty */ +#endif diff --git a/src/vendor/cigraph/include/igraph_dqueue.h b/src/vendor/cigraph/include/igraph_dqueue.h index 571152eaad8..d96bc94199f 100644 --- a/src/vendor/cigraph/include/igraph_dqueue.h +++ b/src/vendor/cigraph/include/igraph_dqueue.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_dqueue_pmt.h b/src/vendor/cigraph/include/igraph_dqueue_pmt.h index 6f2224b9472..d547cd892bf 100644 --- a/src/vendor/cigraph/include/igraph_dqueue_pmt.h +++ b/src/vendor/cigraph/include/igraph_dqueue_pmt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,12 +28,12 @@ typedef struct TYPE(igraph_dqueue) { BASE *stor_end; } TYPE(igraph_dqueue); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, init)(TYPE(igraph_dqueue)* q, igraph_integer_t capacity); +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, init)(TYPE(igraph_dqueue)* q, igraph_int_t capacity); IGRAPH_EXPORT void FUNCTION(igraph_dqueue, destroy)(TYPE(igraph_dqueue)* q); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_dqueue, empty)(const TYPE(igraph_dqueue)* q); IGRAPH_EXPORT void FUNCTION(igraph_dqueue, clear)(TYPE(igraph_dqueue)* q); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_dqueue, full)(TYPE(igraph_dqueue)* q); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_dqueue, size)(const TYPE(igraph_dqueue)* q); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_dqueue, size)(const TYPE(igraph_dqueue)* q); IGRAPH_EXPORT BASE FUNCTION(igraph_dqueue, pop)(TYPE(igraph_dqueue)* q); IGRAPH_EXPORT BASE FUNCTION(igraph_dqueue, pop_back)(TYPE(igraph_dqueue)* q); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_dqueue, head)(const TYPE(igraph_dqueue)* q); @@ -41,4 +41,4 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_dqueue, back)(const TYPE IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, push)(TYPE(igraph_dqueue)* q, BASE elem); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, print)(const TYPE(igraph_dqueue)* q); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_dqueue, fprint)(const TYPE(igraph_dqueue)* q, FILE *file); -IGRAPH_EXPORT BASE FUNCTION(igraph_dqueue, get)(const TYPE(igraph_dqueue) *q, igraph_integer_t idx); +IGRAPH_EXPORT BASE FUNCTION(igraph_dqueue, get)(const TYPE(igraph_dqueue) *q, igraph_int_t idx); diff --git a/src/vendor/cigraph/include/igraph_eigen.h b/src/vendor/cigraph/include/igraph_eigen.h index 935200cd4b8..281b83a9020 100644 --- a/src/vendor/cigraph/include/igraph_eigen.h +++ b/src/vendor/cigraph/include/igraph_eigen.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -20,6 +20,7 @@ #define IGRAPH_EIGEN_H #include "igraph_decls.h" +#include "igraph_datatype.h" #include "igraph_arpack.h" #include "igraph_error.h" #include "igraph_lapack.h" @@ -27,28 +28,29 @@ IGRAPH_BEGIN_C_DECLS -typedef enum { IGRAPH_EIGEN_AUTO = 0, - IGRAPH_EIGEN_LAPACK, - IGRAPH_EIGEN_ARPACK, - IGRAPH_EIGEN_COMP_AUTO, - IGRAPH_EIGEN_COMP_LAPACK, - IGRAPH_EIGEN_COMP_ARPACK - } igraph_eigen_algorithm_t; +typedef enum { + IGRAPH_EIGEN_AUTO = 0, + IGRAPH_EIGEN_LAPACK, + IGRAPH_EIGEN_ARPACK, + IGRAPH_EIGEN_COMP_AUTO, + IGRAPH_EIGEN_COMP_LAPACK, + IGRAPH_EIGEN_COMP_ARPACK +} igraph_eigen_algorithm_t; -typedef enum { IGRAPH_EIGEN_LM = 0, - IGRAPH_EIGEN_SM, /* 1 */ - IGRAPH_EIGEN_LA, /* 2 */ - IGRAPH_EIGEN_SA, /* 3 */ - IGRAPH_EIGEN_BE, /* 4 */ - IGRAPH_EIGEN_LR, /* 5 */ - IGRAPH_EIGEN_SR, /* 6 */ - IGRAPH_EIGEN_LI, /* 7 */ - IGRAPH_EIGEN_SI, /* 8 */ - IGRAPH_EIGEN_ALL, /* 9 */ - IGRAPH_EIGEN_INTERVAL, /* 10 */ - IGRAPH_EIGEN_SELECT - } /* 11 */ -igraph_eigen_which_position_t; +typedef enum { + IGRAPH_EIGEN_LM = 0, + IGRAPH_EIGEN_SM, /* 1 */ + IGRAPH_EIGEN_LA, /* 2 */ + IGRAPH_EIGEN_SA, /* 3 */ + IGRAPH_EIGEN_BE, /* 4 */ + IGRAPH_EIGEN_LR, /* 5 */ + IGRAPH_EIGEN_SR, /* 6 */ + IGRAPH_EIGEN_LI, /* 7 */ + IGRAPH_EIGEN_SI, /* 8 */ + IGRAPH_EIGEN_ALL, /* 9 */ + IGRAPH_EIGEN_INTERVAL, /* 10 */ + IGRAPH_EIGEN_SELECT /* 11 */ +} igraph_eigen_which_position_t; typedef struct igraph_eigen_which_t { igraph_eigen_which_position_t pos; diff --git a/src/vendor/cigraph/include/igraph_embedding.h b/src/vendor/cigraph/include/igraph_embedding.h index 7312b584c4f..2fa8ff6f462 100644 --- a/src/vendor/cigraph/include/igraph_embedding.h +++ b/src/vendor/cigraph/include/igraph_embedding.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_adjacency_spectral_embedding(const igraph_t *graph, - igraph_integer_t no, + igraph_int_t no, const igraph_vector_t *weights, igraph_eigen_which_position_t which, igraph_bool_t scaled, @@ -46,7 +46,7 @@ typedef enum { } igraph_laplacian_spectral_embedding_type_t; IGRAPH_EXPORT igraph_error_t igraph_laplacian_spectral_embedding(const igraph_t *graph, - igraph_integer_t no, + igraph_int_t no, const igraph_vector_t *weights, igraph_eigen_which_position_t which, igraph_laplacian_spectral_embedding_type_t type, @@ -56,7 +56,7 @@ IGRAPH_EXPORT igraph_error_t igraph_laplacian_spectral_embedding(const igraph_t igraph_vector_t *D, igraph_arpack_options_t *options); -IGRAPH_EXPORT igraph_error_t igraph_dim_select(const igraph_vector_t *sv, igraph_integer_t *dim); +IGRAPH_EXPORT igraph_error_t igraph_dim_select(const igraph_vector_t *sv, igraph_int_t *dim); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_epidemics.h b/src/vendor/cigraph/include/igraph_epidemics.h index c86efeea010..361f38cf5de 100644 --- a/src/vendor/cigraph/include/igraph_epidemics.h +++ b/src/vendor/cigraph/include/igraph_epidemics.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2014-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -55,7 +55,7 @@ IGRAPH_EXPORT igraph_error_t igraph_sir_init(igraph_sir_t *sir); IGRAPH_EXPORT void igraph_sir_destroy(igraph_sir_t *sir); IGRAPH_EXPORT igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, - igraph_real_t gamma, igraph_integer_t no_sim, + igraph_real_t gamma, igraph_int_t no_sim, igraph_vector_ptr_t *result); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_error.h b/src/vendor/cigraph/include/igraph_error.h index 4ccbb44e773..33ecdb66ac6 100644 --- a/src/vendor/cigraph/include/igraph_error.h +++ b/src/vendor/cigraph/include/igraph_error.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -260,7 +260,7 @@ IGRAPH_BEGIN_C_DECLS * \enumval IGRAPH_ARPACK An error happened inside a calculation implemented * in ARPACK. The calculation involved is most likely an eigenvector-related * calculation. - * \enumval IGRAPH_ENEGLOOP Negative loop detected while calculating shortest paths. + * \enumval IGRAPH_ENEGCYCLE Negative cycle detected while calculating shortest paths. * \enumval IGRAPH_EINTERNAL Internal error, likely a bug in igraph. * \enumval IGRAPH_EATTRCOMBINE Unimplemented attribute combination * method for the given attribute type. @@ -288,7 +288,7 @@ typedef enum { IGRAPH_DIVERGED = 14, IGRAPH_EARPACK = 15, /* ARPACK error codes from 15 to 36 were moved to igraph_arpack_error_t in 1.0 */ - IGRAPH_ENEGLOOP = 37, + IGRAPH_ENEGCYCLE = 37, IGRAPH_EINTERNAL = 38, /* ARPACK error codes from 39 to 41 were moved to igraph_arpack_error_t in 1.0 */ /* IGRAPH_EDIVZERO = 42, */ /* removed in 1.0 */ diff --git a/src/vendor/cigraph/include/igraph_eulerian.h b/src/vendor/cigraph/include/igraph_eulerian.h index e5f5e4ec5fb..07eafa232f2 100644 --- a/src/vendor/cigraph/include/igraph_eulerian.h +++ b/src/vendor/cigraph/include/igraph_eulerian.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2020-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_flow.h b/src/vendor/cigraph/include/igraph_flow.h index 143890a6a04..8b5e59fe44e 100644 --- a/src/vendor/cigraph/include/igraph_flow.h +++ b/src/vendor/cigraph/include/igraph_flow.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -49,27 +49,27 @@ IGRAPH_BEGIN_C_DECLS */ typedef struct { - igraph_integer_t nopush, norelabel, nogap, nogapnodes, nobfs; + igraph_int_t nopush, norelabel, nogap, nogapnodes, nobfs; } igraph_maxflow_stats_t; IGRAPH_EXPORT igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, igraph_vector_t *flow, igraph_vector_int_t *cut, igraph_vector_int_t *partition, igraph_vector_int_t *partition2, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity, igraph_maxflow_stats_t *stats); IGRAPH_EXPORT igraph_error_t igraph_maxflow_value(const igraph_t *graph, igraph_real_t *value, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity, igraph_maxflow_stats_t *stats); IGRAPH_EXPORT igraph_error_t igraph_st_mincut(const igraph_t *graph, igraph_real_t *value, igraph_vector_int_t *cut, igraph_vector_int_t *partition, igraph_vector_int_t *partition2, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity); IGRAPH_EXPORT igraph_error_t igraph_st_mincut_value(const igraph_t *graph, igraph_real_t *res, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity); IGRAPH_EXPORT igraph_error_t igraph_mincut_value(const igraph_t *graph, igraph_real_t *res, @@ -82,29 +82,29 @@ IGRAPH_EXPORT igraph_error_t igraph_mincut(const igraph_t *graph, const igraph_vector_t *capacity); IGRAPH_EXPORT igraph_error_t igraph_st_vertex_connectivity(const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target, igraph_vconn_nei_t neighbors); -IGRAPH_EXPORT igraph_error_t igraph_vertex_connectivity(const igraph_t *graph, igraph_integer_t *res, +IGRAPH_EXPORT igraph_error_t igraph_vertex_connectivity(const igraph_t *graph, igraph_int_t *res, igraph_bool_t checks); -IGRAPH_EXPORT igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph, igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target); -IGRAPH_EXPORT igraph_error_t igraph_edge_connectivity(const igraph_t *graph, igraph_integer_t *res, +IGRAPH_EXPORT igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph, igraph_int_t *res, + igraph_int_t source, + igraph_int_t target); +IGRAPH_EXPORT igraph_error_t igraph_edge_connectivity(const igraph_t *graph, igraph_int_t *res, igraph_bool_t checks); -IGRAPH_EXPORT igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph, igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target); -IGRAPH_EXPORT igraph_error_t igraph_vertex_disjoint_paths(const igraph_t *graph, igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target); +IGRAPH_EXPORT igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph, igraph_int_t *res, + igraph_int_t source, + igraph_int_t target); +IGRAPH_EXPORT igraph_error_t igraph_vertex_disjoint_paths(const igraph_t *graph, igraph_int_t *res, + igraph_int_t source, + igraph_int_t target); -IGRAPH_EXPORT igraph_error_t igraph_adhesion(const igraph_t *graph, igraph_integer_t *res, +IGRAPH_EXPORT igraph_error_t igraph_adhesion(const igraph_t *graph, igraph_int_t *res, igraph_bool_t checks); -IGRAPH_EXPORT igraph_error_t igraph_cohesion(const igraph_t *graph, igraph_integer_t *res, +IGRAPH_EXPORT igraph_error_t igraph_cohesion(const igraph_t *graph, igraph_int_t *res, igraph_bool_t checks); /* s-t cut listing related stuff */ @@ -124,7 +124,7 @@ IGRAPH_EXPORT igraph_error_t igraph_reverse_residual_graph(const igraph_t *graph const igraph_vector_t *flow); IGRAPH_EXPORT igraph_error_t igraph_dominator_tree(const igraph_t *graph, - igraph_integer_t root, + igraph_int_t root, igraph_vector_int_t *dom, igraph_t *domtree, igraph_vector_int_t *leftout, @@ -133,14 +133,14 @@ IGRAPH_EXPORT igraph_error_t igraph_dominator_tree(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_all_st_cuts(const igraph_t *graph, igraph_vector_int_list_t *cuts, igraph_vector_int_list_t *partition1s, - igraph_integer_t source, - igraph_integer_t target); + igraph_int_t source, + igraph_int_t target); IGRAPH_EXPORT igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value, igraph_vector_int_list_t *cuts, igraph_vector_int_list_t *partition1s, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t source, + igraph_int_t target, const igraph_vector_t *capacity); IGRAPH_EXPORT igraph_error_t igraph_gomory_hu_tree(const igraph_t *graph, diff --git a/src/vendor/cigraph/include/igraph_foreign.h b/src/vendor/cigraph/include/igraph_foreign.h index 790679d7ba5..0c9a0a25725 100644 --- a/src/vendor/cigraph/include/igraph_foreign.h +++ b/src/vendor/cigraph/include/igraph_foreign.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,7 +35,7 @@ IGRAPH_BEGIN_C_DECLS /* -------------------------------------------------- */ IGRAPH_EXPORT igraph_error_t igraph_read_graph_edgelist(igraph_t *graph, FILE *instream, - igraph_integer_t n, igraph_bool_t directed); + igraph_int_t n, igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_read_graph_ncol(igraph_t *graph, FILE *instream, const igraph_strvector_t *predefnames, igraph_bool_t names, igraph_add_weights_t weights, igraph_bool_t directed); @@ -44,12 +44,12 @@ IGRAPH_EXPORT igraph_error_t igraph_read_graph_lgl(igraph_t *graph, FILE *instre igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream); IGRAPH_EXPORT igraph_error_t igraph_read_graph_graphml(igraph_t *graph, FILE *instream, - igraph_integer_t index); + igraph_int_t index); IGRAPH_EXPORT igraph_error_t igraph_read_graph_dimacs_flow(igraph_t *graph, FILE *instream, igraph_strvector_t *problem, igraph_vector_int_t *label, - igraph_integer_t *source, - igraph_integer_t *target, + igraph_int_t *source, + igraph_int_t *target, igraph_vector_t *capacity, igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_read_graph_graphdb(igraph_t *graph, FILE *instream, @@ -75,7 +75,7 @@ IGRAPH_EXPORT igraph_error_t igraph_write_graph_graphml(const igraph_t *graph, F igraph_bool_t prefixattr); IGRAPH_EXPORT igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream); IGRAPH_EXPORT igraph_error_t igraph_write_graph_dimacs_flow(const igraph_t *graph, FILE *outstream, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity); IGRAPH_EXPORT igraph_error_t igraph_write_graph_gml(const igraph_t *graph, FILE *outstream, igraph_write_gml_sw_t options, diff --git a/src/vendor/cigraph/include/igraph_games.h b/src/vendor/cigraph/include/igraph_games.h index 72bfc8a3a1c..2ba1bbb8bcf 100644 --- a/src/vendor/cigraph/include/igraph_games.h +++ b/src/vendor/cigraph/include/igraph_games.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -23,9 +23,9 @@ #include "igraph_constants.h" #include "igraph_datatype.h" #include "igraph_error.h" +#include "igraph_graphicality.h" #include "igraph_matrix.h" #include "igraph_matrix_list.h" -#include "igraph_random.h" #include "igraph_types.h" #include "igraph_vector.h" #include "igraph_vector_list.h" @@ -36,84 +36,97 @@ IGRAPH_BEGIN_C_DECLS /* Constructors, games (=stochastic) */ /* -------------------------------------------------- */ -IGRAPH_EXPORT igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_integer_t n, +IGRAPH_EXPORT igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_int_t n, igraph_real_t power, - igraph_integer_t m, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t A, igraph_bool_t directed, igraph_barabasi_algorithm_t algo, const igraph_t *start_from); -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 multiple); -IGRAPH_EXPORT igraph_error_t igraph_iea_game(igraph_t *graph, - igraph_integer_t n, igraph_integer_t m, - igraph_bool_t directed, igraph_bool_t loops); + +IGRAPH_EXPORT igraph_error_t igraph_erdos_renyi_game_gnp( + igraph_t *graph, + igraph_int_t n, igraph_real_t p, + igraph_bool_t directed, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled); + +IGRAPH_EXPORT igraph_error_t igraph_erdos_renyi_game_gnm( + igraph_t *graph, + igraph_int_t n, igraph_int_t m, + igraph_bool_t directed, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_iea_game( + igraph_t *graph, + igraph_int_t n, igraph_int_t m, + igraph_bool_t directed, igraph_bool_t loops); + 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); -IGRAPH_EXPORT igraph_error_t igraph_growing_random_game(igraph_t *graph, igraph_integer_t n, - igraph_integer_t m, igraph_bool_t directed, igraph_bool_t citation); +IGRAPH_EXPORT igraph_error_t igraph_growing_random_game(igraph_t *graph, igraph_int_t n, + igraph_int_t m, igraph_bool_t directed, igraph_bool_t citation); IGRAPH_EXPORT igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, - igraph_integer_t nodes, - igraph_integer_t m, + igraph_int_t nodes, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t pa_exp, igraph_real_t aging_exp, - igraph_integer_t aging_bin, + igraph_int_t aging_bin, igraph_real_t zero_deg_appeal, igraph_real_t zero_age_appeal, igraph_real_t deg_coef, igraph_real_t age_coef, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t n, +IGRAPH_EXPORT igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_int_t n, igraph_real_t power, - igraph_integer_t window, - igraph_integer_t m, + igraph_int_t window, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t zero_appeal, igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, - igraph_integer_t nodes, - igraph_integer_t m, + igraph_int_t nodes, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t pa_exp, igraph_real_t aging_exp, - igraph_integer_t aging_bin, - igraph_integer_t window, + igraph_int_t aging_bin, + igraph_int_t window, igraph_real_t zero_appeal, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_callaway_traits_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t types, igraph_integer_t edges_per_step, +IGRAPH_EXPORT igraph_error_t igraph_callaway_traits_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t types, igraph_int_t edges_per_step, const igraph_vector_t *type_dist, const igraph_matrix_t *pref_matrix, igraph_bool_t directed, igraph_vector_int_t *node_type_vec); -IGRAPH_EXPORT igraph_error_t igraph_establishment_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t types, igraph_integer_t k, +IGRAPH_EXPORT igraph_error_t igraph_establishment_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t types, igraph_int_t k, const igraph_vector_t *type_dist, const igraph_matrix_t *pref_matrix, igraph_bool_t directed, igraph_vector_int_t *node_type_vec); -IGRAPH_EXPORT igraph_error_t igraph_grg_game(igraph_t *graph, igraph_integer_t nodes, +IGRAPH_EXPORT igraph_error_t igraph_grg_game(igraph_t *graph, igraph_int_t nodes, igraph_real_t radius, igraph_bool_t torus, igraph_vector_t *x, igraph_vector_t *y); -IGRAPH_EXPORT igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t types, +IGRAPH_EXPORT igraph_error_t igraph_preference_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t types, const igraph_vector_t *type_dist, igraph_bool_t fixed_sizes, const igraph_matrix_t *pref_matrix, igraph_vector_int_t *node_type_vec, igraph_bool_t directed, igraph_bool_t loops); -IGRAPH_EXPORT igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t out_types, - igraph_integer_t in_types, +IGRAPH_EXPORT igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t out_types, + igraph_int_t in_types, const igraph_matrix_t *type_dist_matrix, const igraph_matrix_t *pref_matrix, igraph_vector_int_t *node_type_out_vec, @@ -121,89 +134,91 @@ IGRAPH_EXPORT igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_rewire_edges(igraph_t *graph, igraph_real_t prob, - igraph_bool_t loops, igraph_bool_t multiple); + igraph_edge_type_sw_t allowed_edge_types); IGRAPH_EXPORT igraph_error_t igraph_rewire_directed_edges(igraph_t *graph, igraph_real_t prob, igraph_bool_t loops, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_watts_strogatz_game(igraph_t *graph, igraph_integer_t dim, - igraph_integer_t size, igraph_integer_t nei, - igraph_real_t p, igraph_bool_t loops, - igraph_bool_t multiple); +IGRAPH_EXPORT igraph_error_t igraph_watts_strogatz_game(igraph_t *graph, igraph_int_t dim, + igraph_int_t size, igraph_int_t nei, + igraph_real_t p, + igraph_edge_type_sw_t allowed_edge_types); IGRAPH_EXPORT igraph_error_t igraph_lastcit_game(igraph_t *graph, - igraph_integer_t nodes, igraph_integer_t edges_per_node, - igraph_integer_t agebins, + igraph_int_t nodes, igraph_int_t edges_per_node, + igraph_int_t agebins, const igraph_vector_t *preference, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_cited_type_game(igraph_t *graph, igraph_integer_t nodes, +IGRAPH_EXPORT igraph_error_t igraph_cited_type_game(igraph_t *graph, igraph_int_t nodes, const igraph_vector_int_t *types, const igraph_vector_t *pref, - igraph_integer_t edges_per_step, + igraph_int_t edges_per_step, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_integer_t nodes, +IGRAPH_EXPORT igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_int_t nodes, const igraph_vector_int_t *types, const igraph_matrix_t *pref, - igraph_integer_t edges_per_step, + igraph_int_t edges_per_step, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes, +IGRAPH_EXPORT igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_int_t nodes, igraph_real_t fw_prob, igraph_real_t bw_factor, - igraph_integer_t ambs, igraph_bool_t directed); + igraph_int_t ambs, igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_simple_interconnected_islands_game( igraph_t *graph, - igraph_integer_t islands_n, - igraph_integer_t islands_size, + igraph_int_t islands_n, + igraph_int_t islands_size, igraph_real_t islands_pin, - igraph_integer_t n_inter); + igraph_int_t n_inter); -IGRAPH_EXPORT igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_of_edges, +IGRAPH_EXPORT igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_int_t no_of_edges, const igraph_vector_t *fitness_out, const igraph_vector_t *fitness_in, - igraph_bool_t loops, igraph_bool_t multiple); + igraph_edge_type_sw_t allowed_edge_types); IGRAPH_EXPORT igraph_error_t igraph_static_power_law_game(igraph_t *graph, - igraph_integer_t no_of_nodes, igraph_integer_t no_of_edges, + igraph_int_t no_of_nodes, igraph_int_t no_of_edges, igraph_real_t exponent_out, igraph_real_t exponent_in, - igraph_bool_t loops, igraph_bool_t multiple, + igraph_edge_type_sw_t allowed_edge_types, igraph_bool_t finite_size_correction); -IGRAPH_EXPORT igraph_error_t igraph_chung_lu_game(igraph_t *graph, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_chung_lu_game(igraph_t *graph, const igraph_vector_t *expected_out_deg, const igraph_vector_t *expected_in_deg, igraph_bool_t loops, igraph_chung_lu_t variant); IGRAPH_EXPORT igraph_error_t igraph_k_regular_game(igraph_t *graph, - igraph_integer_t no_of_nodes, igraph_integer_t k, + igraph_int_t no_of_nodes, igraph_int_t k, igraph_bool_t directed, igraph_bool_t multiple); -IGRAPH_EXPORT igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, - const igraph_matrix_t *pref_matrix, - const igraph_vector_int_t *block_sizes, - igraph_bool_t directed, igraph_bool_t loops); +IGRAPH_EXPORT igraph_error_t igraph_sbm_game( + igraph_t *graph, + const igraph_matrix_t *pref_matrix, + const igraph_vector_int_t *block_sizes, + igraph_bool_t directed, + igraph_edge_type_sw_t allowed_edge_types); -IGRAPH_EXPORT igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, - igraph_integer_t m, const igraph_vector_t *rho, +IGRAPH_EXPORT igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_int_t n, + igraph_int_t m, const igraph_vector_t *rho, const igraph_matrix_t *C, igraph_real_t p); -IGRAPH_EXPORT igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, +IGRAPH_EXPORT igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_int_t n, const igraph_vector_int_t *mlist, const igraph_vector_list_t *rholist, const igraph_matrix_list_t *Clist, igraph_real_t p); -IGRAPH_EXPORT igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_graph, +IGRAPH_EXPORT igraph_error_t igraph_correlated_game(igraph_t *new_graph, const igraph_t *old_graph, igraph_real_t corr, igraph_real_t p, const igraph_vector_int_t *permutation); IGRAPH_EXPORT igraph_error_t igraph_correlated_pair_game(igraph_t *graph1, igraph_t *graph2, - igraph_integer_t n, igraph_real_t corr, igraph_real_t p, + igraph_int_t n, igraph_real_t corr, igraph_real_t p, igraph_bool_t directed, const igraph_vector_int_t *permutation); -IGRAPH_EXPORT igraph_error_t igraph_tree_game(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, +IGRAPH_EXPORT igraph_error_t igraph_tree_game(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_random_tree_t method); IGRAPH_EXPORT igraph_error_t igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *vecs, diff --git a/src/vendor/cigraph/include/igraph_graph_list.h b/src/vendor/cigraph/include/igraph_graph_list.h index fea672a14f3..ec0f5adb7b7 100644 --- a/src/vendor/cigraph/include/igraph_graph_list.h +++ b/src/vendor/cigraph/include/igraph_graph_list.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_graphicality.h b/src/vendor/cigraph/include/igraph_graphicality.h index 2a4c04a9831..6890b690f08 100644 --- a/src/vendor/cigraph/include/igraph_graphicality.h +++ b/src/vendor/cigraph/include/igraph_graphicality.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2020-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -25,6 +25,24 @@ IGRAPH_BEGIN_C_DECLS +/** + * \typedef igraph_edge_type_sw_t + * \brief What types of non-simple edges to allow? + * + * This type is used with multiple functions to specify what types of non-simple + * edges to allow, create or consider a graph. The constants below are treated + * as "switches" that can be turned on individually and combined using the + * bitwise-or operator. For example, + * IGRAPH_LOOPS_SW + * allows only self-loops but not multi-edges, while + * IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW + * allows both. + * + * \enumval IGRAPH_SIMPLE_SW A shorthand for simple graphs only, which is the default + * assumption. + * \enumval IGRAPH_LOOPS_SW Allow or consider self-loops. + * \enumval IGRAPH_MULTI_SW Allow or consider multi-edges. + */ typedef unsigned int igraph_edge_type_sw_t; /* diff --git a/src/vendor/cigraph/include/igraph_graphlets.h b/src/vendor/cigraph/include/igraph_graphlets.h index 3639dfad701..64b39274903 100644 --- a/src/vendor/cigraph/include/igraph_graphlets.h +++ b/src/vendor/cigraph/include/igraph_graphlets.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -36,12 +36,12 @@ IGRAPH_EXPORT igraph_error_t igraph_graphlets_project(const igraph_t *graph, const igraph_vector_t *weights, const igraph_vector_int_list_t *cliques, igraph_vector_t *Mu, igraph_bool_t startMu, - igraph_integer_t niter); + igraph_int_t niter); IGRAPH_EXPORT igraph_error_t igraph_graphlets(const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *cliques, - igraph_vector_t *Mu, igraph_integer_t niter); + igraph_vector_t *Mu, igraph_int_t niter); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_heap.h b/src/vendor/cigraph/include/igraph_heap.h index e5b57a112f4..12093279a31 100644 --- a/src/vendor/cigraph/include/igraph_heap.h +++ b/src/vendor/cigraph/include/igraph_heap.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_heap_pmt.h b/src/vendor/cigraph/include/igraph_heap_pmt.h index 8f8106ee30a..3d6f77a7b4f 100644 --- a/src/vendor/cigraph/include/igraph_heap_pmt.h +++ b/src/vendor/cigraph/include/igraph_heap_pmt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -22,13 +22,13 @@ typedef struct TYPE(igraph_heap) { BASE* end; } TYPE(igraph_heap); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, init)(TYPE(igraph_heap)* h, igraph_integer_t capacity); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, init_array)(TYPE(igraph_heap) *t, const BASE *data, igraph_integer_t len); +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, init)(TYPE(igraph_heap)* h, igraph_int_t capacity); +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, init_array)(TYPE(igraph_heap) *t, const BASE *data, igraph_int_t len); IGRAPH_EXPORT void FUNCTION(igraph_heap, destroy)(TYPE(igraph_heap)* h); IGRAPH_EXPORT void FUNCTION(igraph_heap, clear)(TYPE(igraph_heap)* h); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_heap, empty)(const TYPE(igraph_heap)* h); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, push)(TYPE(igraph_heap)* h, BASE elem); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_heap, top)(const TYPE(igraph_heap)* h); IGRAPH_EXPORT BASE FUNCTION(igraph_heap, delete_top)(TYPE(igraph_heap)* h); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_heap, size)(const TYPE(igraph_heap)* h); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, reserve)(TYPE(igraph_heap)* h, igraph_integer_t capacity); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_heap, size)(const TYPE(igraph_heap)* h); +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, reserve)(TYPE(igraph_heap)* h, igraph_int_t capacity); diff --git a/src/vendor/cigraph/include/igraph_hrg.h b/src/vendor/cigraph/include/igraph_hrg.h index 87abfbd5258..ce9cd7e0c77 100644 --- a/src/vendor/cigraph/include/igraph_hrg.h +++ b/src/vendor/cigraph/include/igraph_hrg.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -20,7 +20,6 @@ #define IGRAPH_HRG_H #include "igraph_decls.h" - #include "igraph_datatype.h" #include "igraph_error.h" #include "igraph_graph_list.h" @@ -70,14 +69,14 @@ typedef struct igraph_hrg_t { igraph_vector_int_t edges; } igraph_hrg_t; -IGRAPH_EXPORT igraph_error_t igraph_hrg_init(igraph_hrg_t *hrg, igraph_integer_t n); +IGRAPH_EXPORT igraph_error_t igraph_hrg_init(igraph_hrg_t *hrg, igraph_int_t n); IGRAPH_EXPORT void igraph_hrg_destroy(igraph_hrg_t *hrg); -IGRAPH_EXPORT igraph_integer_t igraph_hrg_size(const igraph_hrg_t *hrg); -IGRAPH_EXPORT igraph_error_t igraph_hrg_resize(igraph_hrg_t *hrg, igraph_integer_t newsize); +IGRAPH_EXPORT igraph_int_t igraph_hrg_size(const igraph_hrg_t *hrg); +IGRAPH_EXPORT igraph_error_t igraph_hrg_resize(igraph_hrg_t *hrg, igraph_int_t newsize); IGRAPH_EXPORT igraph_error_t igraph_hrg_fit( const igraph_t *graph, igraph_hrg_t *hrg, igraph_bool_t start, - igraph_integer_t steps + igraph_int_t steps ); IGRAPH_EXPORT igraph_error_t igraph_hrg_sample( @@ -86,7 +85,7 @@ IGRAPH_EXPORT igraph_error_t igraph_hrg_sample( IGRAPH_EXPORT igraph_error_t igraph_hrg_sample_many( const igraph_hrg_t *hrg, igraph_graph_list_t *samples, - igraph_integer_t num_samples + igraph_int_t num_samples ); IGRAPH_EXPORT igraph_error_t igraph_hrg_game( @@ -102,15 +101,15 @@ IGRAPH_EXPORT igraph_error_t igraph_hrg_consensus(const igraph_t *graph, igraph_vector_t *weights, igraph_hrg_t *hrg, igraph_bool_t start, - igraph_integer_t num_samples); + igraph_int_t num_samples); IGRAPH_EXPORT igraph_error_t igraph_hrg_predict(const igraph_t *graph, igraph_vector_int_t *edges, igraph_vector_t *prob, igraph_hrg_t *hrg, igraph_bool_t start, - igraph_integer_t num_samples, - igraph_integer_t num_bins); + igraph_int_t num_samples, + igraph_int_t num_bins); IGRAPH_EXPORT igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, const igraph_t *graph, diff --git a/src/vendor/cigraph/include/igraph_interface.h b/src/vendor/cigraph/include/igraph_interface.h index 6efae000c27..25b19ccc63e 100644 --- a/src/vendor/cigraph/include/igraph_interface.h +++ b/src/vendor/cigraph/include/igraph_interface.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -32,9 +32,9 @@ IGRAPH_BEGIN_C_DECLS /* Interface */ /* -------------------------------------------------- */ -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(igraph_t *graph, igraph_int_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, + igraph_t *graph, igraph_int_t n, igraph_bool_t directed, const igraph_attribute_record_list_t* attr ); IGRAPH_EXPORT void igraph_destroy(igraph_t *graph); @@ -44,7 +44,7 @@ IGRAPH_EXPORT igraph_error_t igraph_add_edges( const igraph_attribute_record_list_t* attr ); IGRAPH_EXPORT igraph_error_t igraph_add_vertices( - igraph_t *graph, igraph_integer_t nv, + igraph_t *graph, igraph_int_t nv, const igraph_attribute_record_list_t* attr ); IGRAPH_EXPORT igraph_error_t igraph_delete_edges(igraph_t *graph, igraph_es_t edges); @@ -53,35 +53,35 @@ IGRAPH_EXPORT igraph_error_t igraph_delete_vertices_map( igraph_t *graph, 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_FUNCATTR_PURE igraph_int_t igraph_vcount(const igraph_t *graph); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_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, + const igraph_t *graph, igraph_vector_int_t *neis, igraph_int_t vid, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple ); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_is_directed(const igraph_t *graph); IGRAPH_EXPORT igraph_error_t igraph_degree_1( - const igraph_t *graph, igraph_integer_t *deg, igraph_integer_t vid, + const igraph_t *graph, igraph_int_t *deg, igraph_int_t vid, igraph_neimode_t mode, igraph_loops_t loops ); IGRAPH_EXPORT igraph_error_t igraph_degree( const igraph_t *graph, igraph_vector_int_t *res, igraph_vs_t vids, igraph_neimode_t mode, igraph_loops_t loops ); -IGRAPH_EXPORT igraph_error_t igraph_edge(const igraph_t *graph, igraph_integer_t eid, - igraph_integer_t *from, igraph_integer_t *to); +IGRAPH_EXPORT igraph_error_t igraph_edge(const igraph_t *graph, igraph_int_t eid, + igraph_int_t *from, igraph_int_t *to); IGRAPH_EXPORT igraph_error_t igraph_edges(const igraph_t *graph, igraph_es_t eids, igraph_vector_int_t *edges, igraph_bool_t bycol); -IGRAPH_EXPORT igraph_error_t igraph_get_eid(const igraph_t *graph, igraph_integer_t *eid, - igraph_integer_t from, igraph_integer_t to, +IGRAPH_EXPORT igraph_error_t igraph_get_eid(const igraph_t *graph, igraph_int_t *eid, + igraph_int_t from, igraph_int_t to, igraph_bool_t directed, igraph_bool_t error); IGRAPH_EXPORT igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, const igraph_vector_int_t *pairs, igraph_bool_t directed, igraph_bool_t error); IGRAPH_EXPORT igraph_error_t igraph_get_all_eids_between(const igraph_t *graph, igraph_vector_int_t *eids, - igraph_integer_t source, igraph_integer_t target, igraph_bool_t directed); + igraph_int_t source, igraph_int_t target, igraph_bool_t directed); IGRAPH_EXPORT igraph_error_t igraph_incident( - const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t pnode, + const igraph_t *graph, igraph_vector_int_t *eids, igraph_int_t pnode, igraph_neimode_t mode, igraph_loops_t loops ); IGRAPH_EXPORT igraph_error_t igraph_is_same_graph(const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *res); @@ -112,7 +112,7 @@ IGRAPH_EXPORT void igraph_i_property_cache_invalidate_all(const igraph_t *graph) * \return The source vertex of the edge. * \sa \ref igraph_edge() if error checking is desired. */ -#define IGRAPH_FROM(graph,eid) ((igraph_integer_t)(VECTOR((graph)->from)[(igraph_integer_t)(eid)])) +#define IGRAPH_FROM(graph,eid) ((igraph_int_t)(VECTOR((graph)->from)[(igraph_int_t)(eid)])) /** * \define IGRAPH_TO @@ -125,7 +125,7 @@ IGRAPH_EXPORT void igraph_i_property_cache_invalidate_all(const igraph_t *graph) * \return The target vertex of the edge. * \sa \ref igraph_edge() if error checking is desired. */ -#define IGRAPH_TO(graph,eid) ((igraph_integer_t)(VECTOR((graph)->to) [(igraph_integer_t)(eid)])) +#define IGRAPH_TO(graph,eid) ((igraph_int_t)(VECTOR((graph)->to) [(igraph_int_t)(eid)])) /** * \define IGRAPH_OTHER @@ -143,7 +143,7 @@ IGRAPH_EXPORT void igraph_i_property_cache_invalidate_all(const igraph_t *graph) * of directed edges. */ #define IGRAPH_OTHER(graph,eid,vid) \ - ((igraph_integer_t)(IGRAPH_TO(graph,(eid))==(vid) ? IGRAPH_FROM((graph),(eid)) : IGRAPH_TO((graph),(eid)))) + ((igraph_int_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, igraph_vs_t vertices, igraph_vector_int_t *idx, diff --git a/src/vendor/cigraph/include/igraph_interrupt.h b/src/vendor/cigraph/include/igraph_interrupt.h index 239b9741603..f1bf1977283 100644 --- a/src/vendor/cigraph/include/igraph_interrupt.h +++ b/src/vendor/cigraph/include/igraph_interrupt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_isomorphism.h b/src/vendor/cigraph/include/igraph_isomorphism.h index 0c581f197bd..32f1eb74896 100644 --- a/src/vendor/cigraph/include/igraph_isomorphism.h +++ b/src/vendor/cigraph/include/igraph_isomorphism.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -22,6 +22,7 @@ #include "igraph_decls.h" #include "igraph_datatype.h" #include "igraph_error.h" +#include "igraph_iterators.h" #include "igraph_types.h" #include "igraph_vector_list.h" @@ -111,8 +112,8 @@ typedef igraph_error_t igraph_isohandler_t(const igraph_vector_int_t *map12, typedef igraph_bool_t igraph_isocompat_t(const igraph_t *graph1, const igraph_t *graph2, - const igraph_integer_t g1_num, - const igraph_integer_t g2_num, + const igraph_int_t g1_num, + const igraph_int_t g2_num, void *arg); IGRAPH_EXPORT igraph_error_t igraph_isomorphic_vf2(const igraph_t *graph1, const igraph_t *graph2, @@ -131,7 +132,7 @@ IGRAPH_EXPORT igraph_error_t igraph_count_isomorphisms_vf2(const igraph_t *graph const igraph_vector_int_t *vertex_color2, const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_integer_t *count, + igraph_int_t *count, igraph_isocompat_t *node_compat_fn, igraph_isocompat_t *edge_compat_fn, void *arg); @@ -169,7 +170,7 @@ IGRAPH_EXPORT igraph_error_t igraph_count_subisomorphisms_vf2(const igraph_t *gr const igraph_vector_int_t *vertex_color2, const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_integer_t *count, + igraph_int_t *count, igraph_isocompat_t *node_compat_fn, igraph_isocompat_t *edge_compat_fn, void *arg); @@ -268,13 +269,13 @@ IGRAPH_EXPORT igraph_error_t igraph_automorphism_group_bliss( ); /* Functions for small graphs (<= 4 vertices for directed graphs, <= 6 for undirected graphs) */ -IGRAPH_EXPORT igraph_error_t igraph_isoclass(const igraph_t *graph, igraph_integer_t *isoclass); -IGRAPH_EXPORT igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, const igraph_vector_int_t *vids, - igraph_integer_t *isoclass); -IGRAPH_EXPORT igraph_error_t igraph_isoclass_create(igraph_t *graph, igraph_integer_t size, - igraph_integer_t number, igraph_bool_t directed); +IGRAPH_EXPORT igraph_error_t igraph_isoclass(const igraph_t *graph, igraph_int_t *isoclass); +IGRAPH_EXPORT igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, igraph_vs_t vids, + igraph_int_t *isoclass); +IGRAPH_EXPORT igraph_error_t igraph_isoclass_create(igraph_t *graph, igraph_int_t size, + igraph_int_t number, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_graph_count(igraph_integer_t n, igraph_bool_t directed, igraph_integer_t *count); +IGRAPH_EXPORT igraph_error_t igraph_graph_count(igraph_int_t n, igraph_bool_t directed, igraph_int_t *count); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_iterators.h b/src/vendor/cigraph/include/igraph_iterators.h index 48ffdf74d0f..c43e34ade7d 100644 --- a/src/vendor/cigraph/include/igraph_iterators.h +++ b/src/vendor/cigraph/include/igraph_iterators.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -46,17 +46,17 @@ typedef enum { typedef struct igraph_vs_t { igraph_vs_type_t type; union { - igraph_integer_t vid; /* single vertex */ + igraph_int_t vid; /* single vertex */ const igraph_vector_int_t *vecptr; /* vector of vertices */ struct { - igraph_integer_t vid; + igraph_int_t vid; igraph_neimode_t mode; igraph_loops_t loops; igraph_bool_t multiple; } adj; /* adjacent vertices */ struct { - igraph_integer_t start; /* first index (inclusive) */ - igraph_integer_t end; /* last index (exclusive) */ + igraph_int_t start; /* first index (inclusive) */ + igraph_int_t end; /* last index (exclusive) */ } range; /* range of vertices */ } data; } igraph_vs_t; @@ -65,18 +65,18 @@ IGRAPH_EXPORT igraph_error_t igraph_vs_all(igraph_vs_t *vs); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_all(void); IGRAPH_EXPORT igraph_error_t igraph_vs_adj( - igraph_vs_t *vs, igraph_integer_t vid, igraph_neimode_t mode, + igraph_vs_t *vs, igraph_int_t vid, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple ); -IGRAPH_EXPORT igraph_error_t igraph_vs_nonadj(igraph_vs_t *vs, igraph_integer_t vid, +IGRAPH_EXPORT igraph_error_t igraph_vs_nonadj(igraph_vs_t *vs, igraph_int_t vid, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_vs_none(igraph_vs_t *vs); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_none(void); -IGRAPH_EXPORT igraph_error_t igraph_vs_1(igraph_vs_t *vs, igraph_integer_t vid); -IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_1(igraph_integer_t vid); +IGRAPH_EXPORT igraph_error_t igraph_vs_1(igraph_vs_t *vs, igraph_int_t vid); +IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_1(igraph_int_t vid); IGRAPH_EXPORT igraph_error_t igraph_vs_vector(igraph_vs_t *vs, const igraph_vector_int_t *v); @@ -87,8 +87,8 @@ IGRAPH_EXPORT igraph_error_t igraph_vs_vector_small(igraph_vs_t *vs, ...); IGRAPH_EXPORT igraph_error_t igraph_vs_vector_copy(igraph_vs_t *vs, const igraph_vector_int_t *v); -IGRAPH_EXPORT igraph_error_t igraph_vs_range(igraph_vs_t *vs, igraph_integer_t start, igraph_integer_t end); -IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_range(igraph_integer_t start, igraph_integer_t end); +IGRAPH_EXPORT igraph_error_t igraph_vs_range(igraph_vs_t *vs, igraph_int_t start, igraph_int_t end); +IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_vs_t igraph_vss_range(igraph_int_t start, igraph_int_t end); IGRAPH_EXPORT void igraph_vs_destroy(igraph_vs_t *vs); @@ -99,7 +99,7 @@ IGRAPH_EXPORT igraph_error_t igraph_vs_copy(igraph_vs_t* dest, const igraph_vs_t IGRAPH_EXPORT igraph_error_t igraph_vs_as_vector(const igraph_t *graph, igraph_vs_t vs, igraph_vector_int_t *v); IGRAPH_EXPORT igraph_error_t igraph_vs_size(const igraph_t *graph, const igraph_vs_t *vs, - igraph_integer_t *result); + igraph_int_t *result); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_vs_type_t igraph_vs_type(const igraph_vs_t *vs); /* -------------------------------------------------- */ @@ -114,9 +114,9 @@ typedef enum { typedef struct igraph_vit_t { igraph_vit_type_t type; - igraph_integer_t pos; - igraph_integer_t start; /* first index */ - igraph_integer_t end; /* one past last index */ + igraph_int_t pos; + igraph_int_t start; /* first index */ + igraph_int_t end; /* one past last index */ const igraph_vector_int_t *vec; } igraph_vit_t; @@ -211,7 +211,7 @@ typedef struct igraph_vit_t { * Time complexity: O(1). */ #define IGRAPH_VIT_GET(vit) \ - ((igraph_integer_t)(((vit).type == IGRAPH_VIT_RANGE) ? (vit).pos : \ + ((igraph_int_t)(((vit).type == IGRAPH_VIT_RANGE) ? (vit).pos : \ VECTOR(*(vit).vec)[(vit).pos])) IGRAPH_EXPORT igraph_error_t igraph_vit_create(const igraph_t *graph, @@ -242,25 +242,25 @@ typedef enum { typedef struct igraph_es_t { igraph_es_type_t type; union { - igraph_integer_t vid; - igraph_integer_t eid; + igraph_int_t vid; + igraph_int_t eid; const igraph_vector_int_t *vecptr; struct { - igraph_integer_t vid; + igraph_int_t vid; igraph_neimode_t mode; igraph_loops_t loops; } incident; struct { - igraph_integer_t start; /* first index (inclusive) */ - igraph_integer_t end; /* last index (exclusive) */ + igraph_int_t start; /* first index (inclusive) */ + igraph_int_t end; /* last index (exclusive) */ } range; struct { const igraph_vector_int_t *ptr; igraph_bool_t mode; } path; struct { - igraph_integer_t from; - igraph_integer_t to; + igraph_int_t from; + igraph_int_t to; igraph_bool_t directed; } between; } data; @@ -271,22 +271,22 @@ IGRAPH_EXPORT igraph_error_t igraph_es_all(igraph_es_t *es, IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_all(igraph_edgeorder_type_t order); IGRAPH_EXPORT igraph_error_t igraph_es_incident( - igraph_es_t *es, igraph_integer_t vid, igraph_neimode_t mode, + igraph_es_t *es, igraph_int_t vid, igraph_neimode_t mode, igraph_loops_t loops ); IGRAPH_EXPORT igraph_error_t igraph_es_none(igraph_es_t *es); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_none(void); -IGRAPH_EXPORT igraph_error_t igraph_es_1(igraph_es_t *es, igraph_integer_t eid); -IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_1(igraph_integer_t eid); +IGRAPH_EXPORT igraph_error_t igraph_es_1(igraph_es_t *es, igraph_int_t eid); +IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_1(igraph_int_t eid); IGRAPH_EXPORT igraph_error_t igraph_es_vector(igraph_es_t *es, const igraph_vector_int_t *v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_es_t igraph_ess_vector(const igraph_vector_int_t *v); -IGRAPH_EXPORT igraph_error_t igraph_es_range(igraph_es_t *es, igraph_integer_t from, igraph_integer_t to); -IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_range(igraph_integer_t from, igraph_integer_t to); +IGRAPH_EXPORT igraph_error_t igraph_es_range(igraph_es_t *es, igraph_int_t from, igraph_int_t to); +IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_es_t igraph_ess_range(igraph_int_t from, igraph_int_t to); IGRAPH_EXPORT igraph_error_t igraph_es_vector_copy(igraph_es_t *es, const igraph_vector_int_t *v); @@ -299,7 +299,7 @@ IGRAPH_EXPORT igraph_error_t igraph_es_path(igraph_es_t *es, const igraph_vector IGRAPH_EXPORT igraph_error_t igraph_es_path_small(igraph_es_t *es, igraph_bool_t directed, int first, ...); IGRAPH_EXPORT igraph_error_t igraph_es_all_between( - igraph_es_t *es, igraph_integer_t from, igraph_integer_t to, + igraph_es_t *es, igraph_int_t from, igraph_int_t to, igraph_bool_t directed ); @@ -312,7 +312,7 @@ IGRAPH_EXPORT igraph_error_t igraph_es_copy(igraph_es_t* dest, const igraph_es_t IGRAPH_EXPORT igraph_error_t igraph_es_as_vector(const igraph_t *graph, igraph_es_t es, igraph_vector_int_t *v); IGRAPH_EXPORT igraph_error_t igraph_es_size(const igraph_t *graph, const igraph_es_t *es, - igraph_integer_t *result); + igraph_int_t *result); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_es_type_t igraph_es_type(const igraph_es_t *es); @@ -328,9 +328,9 @@ typedef enum { typedef struct igraph_eit_t { igraph_eit_type_t type; - igraph_integer_t pos; - igraph_integer_t start; /* first index */ - igraph_integer_t end; /* one past last index */ + igraph_int_t pos; + igraph_int_t start; /* first index */ + igraph_int_t end; /* one past last index */ const igraph_vector_int_t *vec; } igraph_eit_t; @@ -402,7 +402,7 @@ typedef struct igraph_eit_t { * Time complexity: O(1). */ #define IGRAPH_EIT_GET(eit) \ - (igraph_integer_t)((((eit).type == IGRAPH_EIT_RANGE) ? (eit).pos : \ + (igraph_int_t)((((eit).type == IGRAPH_EIT_RANGE) ? (eit).pos : \ VECTOR(*(eit).vec)[(eit).pos])) IGRAPH_EXPORT igraph_error_t igraph_eit_create(const igraph_t *graph, diff --git a/src/vendor/cigraph/include/igraph_lapack.h b/src/vendor/cigraph/include/igraph_lapack.h index 7b2f8dbfaed..aa712f2a3d7 100644 --- a/src/vendor/cigraph/include/igraph_lapack.h +++ b/src/vendor/cigraph/include/igraph_lapack.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_layout.h b/src/vendor/cigraph/include/igraph_layout.h index 912744e9dfa..00812f02f4d 100644 --- a/src/vendor/cigraph/include/igraph_layout.h +++ b/src/vendor/cigraph/include/igraph_layout.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -20,16 +20,15 @@ #define IGRAPH_LAYOUT_H #include "igraph_decls.h" - #include "igraph_constants.h" #include "igraph_datatype.h" #include "igraph_error.h" #include "igraph_iterators.h" +#include "igraph_matrix.h" #include "igraph_matrix_list.h" #include "igraph_types.h" #include "igraph_vector.h" #include "igraph_vector_ptr.h" -#include "igraph_matrix.h" IGRAPH_BEGIN_C_DECLS @@ -53,12 +52,12 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_random(const igraph_t *graph, igraph_ IGRAPH_EXPORT igraph_error_t igraph_layout_circle(const igraph_t *graph, igraph_matrix_t *res, igraph_vs_t order); IGRAPH_EXPORT igraph_error_t igraph_layout_star(const igraph_t *graph, igraph_matrix_t *res, - igraph_integer_t center, const igraph_vector_int_t *order); -IGRAPH_EXPORT igraph_error_t igraph_layout_grid(const igraph_t *graph, igraph_matrix_t *res, igraph_integer_t width); + igraph_int_t center, const igraph_vector_int_t *order); +IGRAPH_EXPORT igraph_error_t igraph_layout_grid(const igraph_t *graph, igraph_matrix_t *res, igraph_int_t width); IGRAPH_EXPORT igraph_error_t igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, - igraph_integer_t niter, + igraph_int_t niter, igraph_real_t start_temp, igraph_layout_grid_t grid, const igraph_vector_t *weights, @@ -68,16 +67,16 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_fruchterman_reingold(const igraph_t * const igraph_vector_t *maxy); IGRAPH_EXPORT igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, + igraph_bool_t use_seed, igraph_int_t maxiter, igraph_real_t epsilon, igraph_real_t kkconst, const igraph_vector_t *weights, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy); IGRAPH_EXPORT igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, - igraph_integer_t maxiter, igraph_real_t maxdelta, + igraph_int_t maxiter, igraph_real_t maxdelta, igraph_real_t area, igraph_real_t coolexp, - igraph_real_t repulserad, igraph_real_t cellsize, igraph_integer_t root); + igraph_real_t repulserad, igraph_real_t cellsize, igraph_int_t root); IGRAPH_EXPORT igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, igraph_matrix_t *res, igraph_neimode_t mode, const igraph_vector_int_t *roots, @@ -87,19 +86,19 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_reingold_tilford_circular(const igrap igraph_neimode_t mode, const igraph_vector_int_t *roots, const igraph_vector_int_t *rootlevel); -IGRAPH_EXPORT igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *res, - igraph_t *extd_graph, igraph_vector_int_t *extd_to_orig_eids, - const igraph_vector_int_t* layers, igraph_real_t hgap, - igraph_real_t vgap, igraph_integer_t maxiter, const igraph_vector_t *weights); +IGRAPH_EXPORT igraph_error_t igraph_layout_sugiyama( + const igraph_t *graph, igraph_matrix_t *res, igraph_matrix_list_t *routing, + const igraph_vector_int_t* layers, igraph_real_t hgap, + igraph_real_t vgap, igraph_int_t maxiter, const igraph_vector_t *weights); IGRAPH_EXPORT igraph_error_t igraph_layout_random_3d(const igraph_t *graph, igraph_matrix_t *res); IGRAPH_EXPORT igraph_error_t igraph_layout_sphere(const igraph_t *graph, igraph_matrix_t *res); IGRAPH_EXPORT igraph_error_t igraph_layout_grid_3d(const igraph_t *graph, igraph_matrix_t *res, - igraph_integer_t width, igraph_integer_t height); + igraph_int_t width, igraph_int_t height); IGRAPH_EXPORT igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, - igraph_integer_t niter, + igraph_int_t niter, igraph_real_t start_temp, const igraph_vector_t *weights, const igraph_vector_t *minx, @@ -110,7 +109,7 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_ const igraph_vector_t *maxz); IGRAPH_EXPORT igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, + igraph_bool_t use_seed, igraph_int_t maxiter, igraph_real_t epsilon, igraph_real_t kkconst, const igraph_vector_t *weights, const igraph_vector_t *minx, const igraph_vector_t *maxx, @@ -118,7 +117,7 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph const igraph_vector_t *minz, const igraph_vector_t *maxz); IGRAPH_EXPORT igraph_error_t igraph_layout_graphopt(const igraph_t *graph, - igraph_matrix_t *res, igraph_integer_t niter, + igraph_matrix_t *res, igraph_int_t niter, igraph_real_t node_charge, igraph_real_t node_mass, igraph_real_t spring_length, igraph_real_t spring_constant, @@ -126,30 +125,30 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_graphopt(const igraph_t *graph, igraph_bool_t use_seed); IGRAPH_EXPORT igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, - const igraph_matrix_t *dist, igraph_integer_t dim); + const igraph_matrix_t *dist, igraph_int_t dim); IGRAPH_EXPORT igraph_error_t igraph_layout_bipartite(const igraph_t *graph, const igraph_vector_bool_t *types, igraph_matrix_t *res, igraph_real_t hgap, - igraph_real_t vgap, igraph_integer_t maxiter); + igraph_real_t vgap, igraph_int_t maxiter); -IGRAPH_EXPORT igraph_error_t igraph_layout_umap(const igraph_t *graph, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_layout_umap(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, const igraph_vector_t *distances, igraph_real_t min_dist, - igraph_integer_t epochs, + igraph_int_t epochs, igraph_bool_t distances_are_weights); -IGRAPH_EXPORT igraph_error_t igraph_layout_umap_3d(const igraph_t *graph, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_layout_umap_3d(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, const igraph_vector_t *distances, igraph_real_t min_dist, - igraph_integer_t epochs, + igraph_int_t epochs, igraph_bool_t distances_are_weights); -IGRAPH_EXPORT igraph_error_t igraph_layout_umap_compute_weights(const igraph_t *graph, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_layout_umap_compute_weights(const igraph_t *graph, const igraph_vector_t *distances, igraph_vector_t *weights); @@ -193,27 +192,27 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_umap_compute_weights(const igraph_t * typedef struct igraph_layout_drl_options_t { igraph_real_t edge_cut; - igraph_integer_t init_iterations; + igraph_int_t init_iterations; igraph_real_t init_temperature; igraph_real_t init_attraction; igraph_real_t init_damping_mult; - igraph_integer_t liquid_iterations; + igraph_int_t liquid_iterations; igraph_real_t liquid_temperature; igraph_real_t liquid_attraction; igraph_real_t liquid_damping_mult; - igraph_integer_t expansion_iterations; + igraph_int_t expansion_iterations; igraph_real_t expansion_temperature; igraph_real_t expansion_attraction; igraph_real_t expansion_damping_mult; - igraph_integer_t cooldown_iterations; + igraph_int_t cooldown_iterations; igraph_real_t cooldown_temperature; igraph_real_t cooldown_attraction; igraph_real_t cooldown_damping_mult; - igraph_integer_t crunch_iterations; + igraph_int_t crunch_iterations; igraph_real_t crunch_temperature; igraph_real_t crunch_attraction; igraph_real_t crunch_damping_mult; - igraph_integer_t simmer_iterations; + igraph_int_t simmer_iterations; igraph_real_t simmer_temperature; igraph_real_t simmer_attraction; igraph_real_t simmer_damping_mult; @@ -257,13 +256,13 @@ IGRAPH_EXPORT igraph_error_t igraph_layout_merge_dla(const igraph_vector_ptr_t * igraph_matrix_t *res); IGRAPH_EXPORT igraph_error_t igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, + igraph_bool_t use_seed, igraph_int_t maxiter, igraph_real_t temp_max, igraph_real_t temp_min, igraph_real_t temp_init); IGRAPH_EXPORT igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, - igraph_integer_t fineiter, igraph_real_t cool_fact, + igraph_bool_t use_seed, igraph_int_t maxiter, + igraph_int_t fineiter, igraph_real_t cool_fact, igraph_real_t weight_node_dist, igraph_real_t weight_border, igraph_real_t weight_edge_lengths, igraph_real_t weight_edge_crossings, diff --git a/src/vendor/cigraph/include/igraph_lsap.h b/src/vendor/cigraph/include/igraph_lsap.h index 80bce0aedfe..64a7fdf8623 100644 --- a/src/vendor/cigraph/include/igraph_lsap.h +++ b/src/vendor/cigraph/include/igraph_lsap.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2014-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,7 +27,7 @@ IGRAPH_BEGIN_C_DECLS -IGRAPH_EXPORT igraph_error_t igraph_solve_lsap(const igraph_matrix_t *c, igraph_integer_t n, +IGRAPH_EXPORT igraph_error_t igraph_solve_lsap(const igraph_matrix_t *c, igraph_int_t n, igraph_vector_int_t *p); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_matching.h b/src/vendor/cigraph/include/igraph_matching.h index dbce7b02ecf..bd9ad0a5424 100644 --- a/src/vendor/cigraph/include/igraph_matching.h +++ b/src/vendor/cigraph/include/igraph_matching.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2012-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -39,7 +39,7 @@ IGRAPH_EXPORT igraph_error_t igraph_is_maximal_matching(const igraph_t* graph, igraph_bool_t* result); IGRAPH_EXPORT igraph_error_t igraph_maximum_bipartite_matching(const igraph_t* graph, - const igraph_vector_bool_t* types, igraph_integer_t* matching_size, + const igraph_vector_bool_t* types, igraph_int_t* matching_size, igraph_real_t* matching_weight, igraph_vector_int_t* matching, const igraph_vector_t* weights, igraph_real_t eps); diff --git a/src/vendor/cigraph/include/igraph_matrix.h b/src/vendor/cigraph/include/igraph_matrix.h index 8ce91346b84..0644c4876ff 100644 --- a/src/vendor/cigraph/include/igraph_matrix.h +++ b/src/vendor/cigraph/include/igraph_matrix.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_matrix_list.h b/src/vendor/cigraph/include/igraph_matrix_list.h index 34a8b85548b..e2f1dd1e422 100644 --- a/src/vendor/cigraph/include/igraph_matrix_list.h +++ b/src/vendor/cigraph/include/igraph_matrix_list.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_matrix_pmt.h b/src/vendor/cigraph/include/igraph_matrix_pmt.h index 4ceb157d605..6ca4c452738 100644 --- a/src/vendor/cigraph/include/igraph_matrix_pmt.h +++ b/src/vendor/cigraph/include/igraph_matrix_pmt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -18,7 +18,7 @@ typedef struct TYPE(igraph_matrix) { TYPE(igraph_vector) data; - igraph_integer_t nrow, ncol; + igraph_int_t nrow, ncol; } TYPE(igraph_matrix); /*---------------*/ @@ -26,13 +26,13 @@ typedef struct TYPE(igraph_matrix) { /*---------------*/ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, init)( - TYPE(igraph_matrix) *m, igraph_integer_t nrow, igraph_integer_t ncol); + TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, init_array)( - TYPE(igraph_matrix)* m, const BASE* data, igraph_integer_t nrow, igraph_integer_t ncol, igraph_matrix_storage_t storage); + TYPE(igraph_matrix)* m, const BASE* data, igraph_int_t nrow, igraph_int_t ncol, igraph_matrix_storage_t storage); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, init_copy)( TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from); IGRAPH_EXPORT void FUNCTION(igraph_matrix, destroy)(TYPE(igraph_matrix) *m); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_matrix, capacity)(const TYPE(igraph_matrix) *m); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_matrix, capacity)(const TYPE(igraph_matrix) *m); /*--------------------*/ /* Accessing elements */ @@ -40,11 +40,11 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_matrix, capa /* MATRIX */ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_matrix, get)( - const TYPE(igraph_matrix) *m, igraph_integer_t row, igraph_integer_t col); + const TYPE(igraph_matrix) *m, igraph_int_t row, igraph_int_t col); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE* FUNCTION(igraph_matrix, get_ptr)( - const TYPE(igraph_matrix) *m, igraph_integer_t row, igraph_integer_t col); + const TYPE(igraph_matrix) *m, igraph_int_t row, igraph_int_t col); IGRAPH_EXPORT void FUNCTION(igraph_matrix, set)( - TYPE(igraph_matrix)* m, igraph_integer_t row, igraph_integer_t col, BASE value); + TYPE(igraph_matrix)* m, igraph_int_t row, igraph_int_t col, BASE value); /*------------------------------*/ /* Initializing matrix elements */ @@ -57,19 +57,19 @@ IGRAPH_EXPORT void FUNCTION(igraph_matrix, fill)(TYPE(igraph_matrix) *m, BASE e) /* Matrix views */ /*-----------------------*/ -IGRAPH_EXPORT const TYPE(igraph_matrix) *FUNCTION(igraph_matrix, view)( - const TYPE(igraph_matrix) *m, const BASE *data, - igraph_integer_t nrow, igraph_integer_t ncol); -IGRAPH_EXPORT const TYPE(igraph_matrix) *FUNCTION(igraph_matrix, view_from_vector)( - const TYPE(igraph_matrix) *m, const TYPE(igraph_vector) *v, - igraph_integer_t ncol +IGRAPH_EXPORT TYPE(igraph_matrix) FUNCTION(igraph_matrix, view)( + const BASE *data, + igraph_int_t nrow, igraph_int_t ncol); +IGRAPH_EXPORT TYPE(igraph_matrix) FUNCTION(igraph_matrix, view_from_vector)( + const TYPE(igraph_vector) *v, + igraph_int_t ncol ); /*------------------*/ /* Copying matrices */ /*------------------*/ -IGRAPH_EXPORT void FUNCTION(igraph_matrix, copy_to)(const TYPE(igraph_matrix) *m, BASE *to); +IGRAPH_EXPORT void FUNCTION(igraph_matrix, copy_to)(const TYPE(igraph_matrix) *m, BASE *to, igraph_matrix_storage_t storage); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, update)(TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, rbind)(TYPE(igraph_matrix) *to, @@ -83,13 +83,13 @@ IGRAPH_EXPORT void FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(i /*--------------------------*/ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, get_row)( - const TYPE(igraph_matrix) *m, TYPE(igraph_vector) *res, igraph_integer_t index); + const TYPE(igraph_matrix) *m, TYPE(igraph_vector) *res, igraph_int_t index); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, get_col)( - const TYPE(igraph_matrix) *m, TYPE(igraph_vector) *res, igraph_integer_t index); + const TYPE(igraph_matrix) *m, TYPE(igraph_vector) *res, igraph_int_t index); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, set_row)( - TYPE(igraph_matrix) *m, const TYPE(igraph_vector) *v, igraph_integer_t index); + TYPE(igraph_matrix) *m, const TYPE(igraph_vector) *v, igraph_int_t index); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, set_col)( - TYPE(igraph_matrix) *m, const TYPE(igraph_vector) *v, igraph_integer_t index); + TYPE(igraph_matrix) *m, const TYPE(igraph_vector) *v, igraph_int_t index); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, select_rows)( const TYPE(igraph_matrix) *m, TYPE(igraph_matrix) *res, const igraph_vector_int_t *rows); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, select_cols)( @@ -103,11 +103,11 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, select_rows_cols)( /*-----------------------------*/ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, swap_rows)( - TYPE(igraph_matrix) *m, igraph_integer_t i, igraph_integer_t j); + TYPE(igraph_matrix) *m, igraph_int_t i, igraph_int_t j); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, swap_cols)( - TYPE(igraph_matrix) *m, igraph_integer_t i, igraph_integer_t j); + TYPE(igraph_matrix) *m, igraph_int_t i, igraph_int_t j); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, swap_rowcol)( - TYPE(igraph_matrix) *m, igraph_integer_t i, igraph_integer_t j); + TYPE(igraph_matrix) *m, igraph_int_t i, igraph_int_t j); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, transpose)(TYPE(igraph_matrix) *m); /*-----------------------------*/ @@ -133,14 +133,14 @@ IGRAPH_EXPORT void FUNCTION(igraph_matrix, add_constant)(TYPE(igraph_matrix) *m, IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t FUNCTION(igraph_matrix, min)(const TYPE(igraph_matrix) *m); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t FUNCTION(igraph_matrix, max)(const TYPE(igraph_matrix) *m); IGRAPH_EXPORT void FUNCTION(igraph_matrix, which_min)( - const TYPE(igraph_matrix) *m, igraph_integer_t *i, igraph_integer_t *j); + const TYPE(igraph_matrix) *m, igraph_int_t *i, igraph_int_t *j); IGRAPH_EXPORT void FUNCTION(igraph_matrix, which_max)( - const TYPE(igraph_matrix) *m, igraph_integer_t *i, igraph_integer_t *j); + const TYPE(igraph_matrix) *m, igraph_int_t *i, igraph_int_t *j); IGRAPH_EXPORT void FUNCTION(igraph_matrix, minmax)( const TYPE(igraph_matrix) *m, BASE *min, BASE *max); IGRAPH_EXPORT void FUNCTION(igraph_matrix, which_minmax)( - const TYPE(igraph_matrix) *m, igraph_integer_t *imin, igraph_integer_t *jmin, - igraph_integer_t *imax, igraph_integer_t *jmax); + const TYPE(igraph_matrix) *m, igraph_int_t *imin, igraph_int_t *jmin, + igraph_int_t *imax, igraph_int_t *jmax); #endif /*------------------------------*/ @@ -166,9 +166,9 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_matrix, all_ge) IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_matrix, isnull)(const TYPE(igraph_matrix) *m); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_matrix, empty)(const TYPE(igraph_matrix) *m); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_matrix, size)(const TYPE(igraph_matrix) *m); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_matrix, ncol)(const TYPE(igraph_matrix) *m); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_matrix, size)(const TYPE(igraph_matrix) *m); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_matrix, ncol)(const TYPE(igraph_matrix) *m); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_matrix, is_symmetric)(const TYPE(igraph_matrix) *m); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_matrix, sum)(const TYPE(igraph_matrix) *m); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_matrix, prod)(const TYPE(igraph_matrix) *m); @@ -190,25 +190,25 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t FUNCTION(igraph_matrix, maxdiff IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_matrix, contains)( const TYPE(igraph_matrix) *m, BASE e); IGRAPH_EXPORT igraph_bool_t FUNCTION(igraph_matrix, search)( - const TYPE(igraph_matrix) *m, igraph_integer_t from, BASE what, - igraph_integer_t *pos, igraph_integer_t *row, igraph_integer_t *col); + const TYPE(igraph_matrix) *m, igraph_int_t from, BASE what, + igraph_int_t *pos, igraph_int_t *row, igraph_int_t *col); /*------------------------*/ /* Resizing operations */ /*------------------------*/ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, resize)( - TYPE(igraph_matrix) *m, igraph_integer_t nrow, igraph_integer_t ncol); + TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol); IGRAPH_EXPORT void FUNCTION(igraph_matrix, resize_min)( TYPE(igraph_matrix) *m); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, add_cols)( - TYPE(igraph_matrix) *m, igraph_integer_t n); + TYPE(igraph_matrix) *m, igraph_int_t n); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, add_rows)( - TYPE(igraph_matrix) *m, igraph_integer_t n); + TYPE(igraph_matrix) *m, igraph_int_t n); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, remove_col)( - TYPE(igraph_matrix) *m, igraph_integer_t col); + TYPE(igraph_matrix) *m, igraph_int_t col); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, remove_row)( - TYPE(igraph_matrix) *m, igraph_integer_t row); + TYPE(igraph_matrix) *m, igraph_int_t row); /*------------------------*/ /* Print as text */ @@ -248,4 +248,4 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_matrix_complex_all_almos #endif /* BASE_COMPLEX */ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, permdelete_rows)( - TYPE(igraph_matrix) *m, igraph_integer_t *index, igraph_integer_t nremove); + TYPE(igraph_matrix) *m, igraph_int_t *index, igraph_int_t nremove); diff --git a/src/vendor/cigraph/include/igraph_memory.h b/src/vendor/cigraph/include/igraph_memory.h index 90c5e7fd09e..81bdf6cd9de 100644 --- a/src/vendor/cigraph/include/igraph_memory.h +++ b/src/vendor/cigraph/include/igraph_memory.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_mixing.h b/src/vendor/cigraph/include/igraph_mixing.h index 7317caa892b..c0028a6f1c5 100644 --- a/src/vendor/cigraph/include/igraph_mixing.h +++ b/src/vendor/cigraph/include/igraph_mixing.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,18 +28,17 @@ IGRAPH_BEGIN_C_DECLS -IGRAPH_EXPORT igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, - const igraph_vector_int_t *types, - igraph_real_t *res, - igraph_bool_t directed, - igraph_bool_t normalized); +IGRAPH_EXPORT igraph_error_t igraph_assortativity_nominal( + const igraph_t *graph, const igraph_vector_t *weights, + const igraph_vector_int_t *types, + igraph_real_t *res, + igraph_bool_t directed, igraph_bool_t normalized); -IGRAPH_EXPORT igraph_error_t igraph_assortativity(const igraph_t *graph, - const igraph_vector_t *values, - const igraph_vector_t *values_in, - igraph_real_t *res, - igraph_bool_t directed, - igraph_bool_t normalized); +IGRAPH_EXPORT igraph_error_t igraph_assortativity( + const igraph_t *graph, const igraph_vector_t *weights, + const igraph_vector_t *values, const igraph_vector_t *values_in, + igraph_real_t *res, + igraph_bool_t directed, igraph_bool_t normalized); IGRAPH_EXPORT igraph_error_t igraph_assortativity_degree(const igraph_t *graph, igraph_real_t *res, @@ -48,14 +47,14 @@ IGRAPH_EXPORT igraph_error_t igraph_assortativity_degree(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_joint_degree_matrix( const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *jdm, - igraph_integer_t dout, igraph_integer_t din); + igraph_int_t dout, igraph_int_t din); IGRAPH_EXPORT igraph_error_t igraph_joint_degree_distribution( const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *p, igraph_neimode_t from_mode, igraph_neimode_t to_mode, igraph_bool_t directed_neighbors, igraph_bool_t normalized, - igraph_integer_t max_from_degree, igraph_integer_t max_to_degree); + igraph_int_t max_from_degree, igraph_int_t max_to_degree); IGRAPH_EXPORT igraph_error_t igraph_joint_type_distribution( const igraph_t *graph, const igraph_vector_t *weights, diff --git a/src/vendor/cigraph/include/igraph_motifs.h b/src/vendor/cigraph/include/igraph_motifs.h index 754abd540ae..c46d3546521 100644 --- a/src/vendor/cigraph/include/igraph_motifs.h +++ b/src/vendor/cigraph/include/igraph_motifs.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -61,24 +61,24 @@ IGRAPH_BEGIN_C_DECLS */ typedef igraph_error_t igraph_motifs_handler_t(const igraph_t *graph, - igraph_vector_int_t *vids, - igraph_integer_t isoclass, - void* extra); + const igraph_vector_int_t *vids, + igraph_int_t isoclass, + void *extra); IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu(const igraph_t *graph, igraph_vector_t *hist, - igraph_integer_t size, const igraph_vector_t *cut_prob); + igraph_int_t size, const igraph_vector_t *cut_prob); -IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_integer_t size, +IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_int_t size, const igraph_vector_t *cut_prob, igraph_motifs_handler_t *callback, void* extra); IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real_t *est, - igraph_integer_t size, const igraph_vector_t *cut_prob, - igraph_integer_t sample_size, + igraph_int_t size, const igraph_vector_t *cut_prob, + igraph_int_t sample_size, const igraph_vector_int_t *sample); IGRAPH_EXPORT igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_real_t *no, - igraph_integer_t size, const igraph_vector_t *cut_prob); + igraph_int_t size, const igraph_vector_t *cut_prob); IGRAPH_EXPORT igraph_error_t igraph_dyad_census(const igraph_t *graph, igraph_real_t *mut, igraph_real_t *asym, igraph_real_t *null); diff --git a/src/vendor/cigraph/include/igraph_neighborhood.h b/src/vendor/cigraph/include/igraph_neighborhood.h index 35a0a9b204a..da5e089a630 100644 --- a/src/vendor/cigraph/include/igraph_neighborhood.h +++ b/src/vendor/cigraph/include/igraph_neighborhood.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,15 +29,15 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int_t *res, - igraph_vs_t vids, igraph_integer_t order, - igraph_neimode_t mode, igraph_integer_t mindist); + igraph_vs_t vids, igraph_int_t order, + igraph_neimode_t mode, igraph_int_t mindist); IGRAPH_EXPORT igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_vs_t vids, igraph_integer_t order, - igraph_neimode_t mode, igraph_integer_t mindist); + igraph_vs_t vids, igraph_int_t order, + igraph_neimode_t mode, igraph_int_t mindist); IGRAPH_EXPORT igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_list_t *res, - igraph_vs_t vids, igraph_integer_t order, + igraph_vs_t vids, igraph_int_t order, igraph_neimode_t mode, - igraph_integer_t mindist); + igraph_int_t mindist); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_nongraph.h b/src/vendor/cigraph/include/igraph_nongraph.h index 226bbaa7b90..2be9cef3e8b 100644 --- a/src/vendor/cigraph/include/igraph_nongraph.h +++ b/src/vendor/cigraph/include/igraph_nongraph.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -21,7 +21,6 @@ #include "igraph_decls.h" #include "igraph_error.h" -#include "igraph_matrix.h" #include "igraph_types.h" #include "igraph_vector.h" @@ -77,11 +76,9 @@ typedef struct igraph_plfit_result_t { } igraph_plfit_result_t; IGRAPH_EXPORT igraph_error_t igraph_running_mean(const igraph_vector_t *data, igraph_vector_t *res, - igraph_integer_t binwidth); -IGRAPH_EXPORT igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_integer_t l, igraph_integer_t h, - igraph_integer_t length); -IGRAPH_EXPORT igraph_error_t igraph_convex_hull(const igraph_matrix_t *data, igraph_vector_int_t *resverts, - igraph_matrix_t *rescoords); + igraph_int_t binwidth); +IGRAPH_EXPORT igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_int_t l, igraph_int_t h, + igraph_int_t length); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST igraph_bool_t igraph_almost_equals(double a, double b, double eps); IGRAPH_EXPORT IGRAPH_FUNCATTR_CONST int igraph_cmp_epsilon(double a, double b, double eps); diff --git a/src/vendor/cigraph/include/igraph_operators.h b/src/vendor/cigraph/include/igraph_operators.h index a50ee07b920..5e6100f8d95 100644 --- a/src/vendor/cigraph/include/igraph_operators.h +++ b/src/vendor/cigraph/include/igraph_operators.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -20,7 +20,6 @@ #define IGRAPH_OPERATORS_H #include "igraph_decls.h" - #include "igraph_attributes.h" #include "igraph_constants.h" #include "igraph_datatype.h" @@ -36,7 +35,25 @@ IGRAPH_BEGIN_C_DECLS /* Graph operators */ /* -------------------------------------------------- */ -IGRAPH_EXPORT igraph_error_t igraph_add_edge(igraph_t *graph, igraph_integer_t from, igraph_integer_t to); +/** + * \typedef igraph_rewiring_stats_t + * \brief Data structure holding statistics from graph rewiring. + * + * \param successful_swaps Number of successful rewiring trials (successful swaps). + */ + +typedef struct { + igraph_int_t successful_swaps; + + /* unused members added at the end to allow us to extend the stats in the future + * without breaking ABI compatibility. Do not use these fields in your own code */ + + igraph_int_t unused1_; + igraph_int_t unused2_; + igraph_int_t unused3_; +} igraph_rewiring_stats_t; + +IGRAPH_EXPORT igraph_error_t igraph_add_edge(igraph_t *graph, igraph_int_t from, igraph_int_t to); IGRAPH_EXPORT igraph_error_t igraph_disjoint_union(igraph_t *res, const igraph_t *left, const igraph_t *right); IGRAPH_EXPORT igraph_error_t igraph_disjoint_union_many(igraph_t *res, @@ -65,11 +82,12 @@ IGRAPH_EXPORT igraph_error_t igraph_contract_vertices(igraph_t *graph, const igraph_attribute_combination_t *vertex_comb); IGRAPH_EXPORT igraph_error_t igraph_permute_vertices(const igraph_t *graph, igraph_t *res, const igraph_vector_int_t *permutation); -IGRAPH_EXPORT igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t order, +IGRAPH_EXPORT igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_int_t order, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_graph_power(const igraph_t *graph, igraph_t *res, - igraph_integer_t order, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_edge_type_sw_t allowed_edge_types); + igraph_int_t order, igraph_bool_t directed); +IGRAPH_EXPORT igraph_error_t igraph_rewire(igraph_t *graph, igraph_int_t n, igraph_edge_type_sw_t allowed_edge_types, + igraph_rewiring_stats_t *stats); IGRAPH_EXPORT igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t remove_multiple, igraph_bool_t remove_loops, const igraph_attribute_combination_t *edge_comb); @@ -85,15 +103,15 @@ IGRAPH_EXPORT igraph_error_t igraph_induced_subgraph_edges( IGRAPH_EXPORT igraph_error_t igraph_subgraph_from_edges(const igraph_t *graph, igraph_t *res, igraph_es_t eids, igraph_bool_t delete_vertices); IGRAPH_EXPORT igraph_error_t igraph_reverse_edges(igraph_t *graph, igraph_es_t eids); -IGRAPH_EXPORT igraph_error_t igraph_product(igraph_t *res, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_product(igraph_t *res, const igraph_t *g1, const igraph_t *g2, igraph_product_t type); -IGRAPH_EXPORT igraph_error_t igraph_rooted_product(igraph_t *res, +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_rooted_product(igraph_t *res, const igraph_t *g1, const igraph_t *g2, - const igraph_integer_t root); -IGRAPH_EXPORT igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_integer_t k); + igraph_int_t root); +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_int_t k); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_paths.h b/src/vendor/cigraph/include/igraph_paths.h index f047777f083..d15d274c97b 100644 --- a/src/vendor/cigraph/include/igraph_paths.h +++ b/src/vendor/cigraph/include/igraph_paths.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -59,7 +59,7 @@ IGRAPH_BEGIN_C_DECLS */ typedef igraph_error_t igraph_astar_heuristic_func_t( igraph_real_t *result, - igraph_integer_t from, igraph_integer_t to, + igraph_int_t from, igraph_int_t to, void *extra); typedef enum { @@ -70,7 +70,7 @@ typedef enum { IGRAPH_EXPORT igraph_error_t igraph_diameter( const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, - igraph_integer_t *from, igraph_integer_t *to, + igraph_int_t *from, igraph_int_t *to, igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path, igraph_bool_t directed, igraph_bool_t unconn ); @@ -117,13 +117,13 @@ IGRAPH_EXPORT igraph_error_t igraph_distances_dijkstra_cutoff( IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths( const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, igraph_vs_t to, igraph_neimode_t mode, + igraph_int_t from, igraph_vs_t to, igraph_neimode_t mode, igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges ); IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, + igraph_int_t from, igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode, @@ -132,7 +132,7 @@ IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, + igraph_int_t from, igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode, @@ -142,28 +142,28 @@ IGRAPH_EXPORT igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t * IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path( const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, igraph_integer_t to, igraph_neimode_t mode + igraph_int_t from, igraph_int_t to, igraph_neimode_t mode ); IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path_bellman_ford(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path_dijkstra(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode, igraph_astar_heuristic_func_t *heuristic, @@ -172,14 +172,14 @@ IGRAPH_EXPORT igraph_error_t igraph_get_shortest_path_astar(const igraph_t *grap IGRAPH_EXPORT igraph_error_t igraph_get_all_shortest_paths( const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_vector_int_t *nrgeo, igraph_integer_t from, igraph_vs_t to, + igraph_vector_int_t *nrgeo, igraph_int_t from, igraph_vs_t to, igraph_neimode_t mode ); IGRAPH_EXPORT igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, igraph_vector_int_t *nrgeo, - igraph_integer_t from, igraph_vs_t to, + igraph_int_t from, igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode); @@ -213,42 +213,39 @@ IGRAPH_EXPORT igraph_error_t igraph_radius( igraph_neimode_t mode ); -IGRAPH_EXPORT igraph_error_t igraph_graph_center( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_graph_center( const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_t *res, igraph_neimode_t mode ); IGRAPH_EXPORT igraph_error_t igraph_pseudo_diameter( const igraph_t *graph, const igraph_vector_t *weights, - igraph_real_t *diameter, igraph_integer_t vid_start, - igraph_integer_t *from, igraph_integer_t *to, + igraph_real_t *diameter, igraph_int_t vid_start, + igraph_int_t *from, igraph_int_t *to, igraph_bool_t directed, igraph_bool_t unconn ); -IGRAPH_EXPORT igraph_error_t igraph_get_all_simple_paths(const igraph_t *graph, - igraph_vector_int_list_t *res, - igraph_integer_t from, - igraph_vs_t to, - igraph_integer_t minlen, - igraph_integer_t maxlen, - igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t +igraph_get_all_simple_paths(const igraph_t *graph, igraph_vector_int_list_t *res, igraph_int_t from, + const igraph_vs_t to, igraph_neimode_t mode, igraph_int_t minlen, + igraph_int_t maxlen, igraph_int_t max_results); IGRAPH_EXPORT igraph_error_t igraph_random_walk(const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t start, + igraph_int_t start, igraph_neimode_t mode, - igraph_integer_t steps, + igraph_int_t steps, igraph_random_walk_stuck_t stuck); IGRAPH_EXPORT igraph_error_t igraph_get_k_shortest_paths(const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *vertex_paths, igraph_vector_int_list_t *edge_paths, - igraph_integer_t k, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t k, + igraph_int_t from, + igraph_int_t to, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_spanner(const igraph_t *graph, @@ -259,7 +256,7 @@ IGRAPH_EXPORT igraph_error_t igraph_spanner(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_get_widest_paths(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, + igraph_int_t from, igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode, @@ -268,8 +265,8 @@ IGRAPH_EXPORT igraph_error_t igraph_get_widest_paths(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_get_widest_path(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph, @@ -295,7 +292,7 @@ IGRAPH_EXPORT igraph_error_t igraph_voronoi(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_expand_path_to_pairs(igraph_vector_int_t *path); IGRAPH_EXPORT igraph_error_t igraph_vertex_path_from_edge_path( - const igraph_t *graph, igraph_integer_t start, + const igraph_t *graph, igraph_int_t start, const igraph_vector_int_t *edge_path, igraph_vector_int_t *vertex_path, igraph_neimode_t mode); diff --git a/src/vendor/cigraph/include/igraph_pmt.h b/src/vendor/cigraph/include/igraph_pmt.h index bcdee2a11c2..1032cce93f6 100644 --- a/src/vendor/cigraph/include/igraph_pmt.h +++ b/src/vendor/cigraph/include/igraph_pmt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -63,7 +63,7 @@ #define EQ(a,b) ((a && b) || (!a && !b)) #elif defined(BASE_INT) - #define BASE igraph_integer_t + #define BASE igraph_int_t #define BASE_VECTOR igraph_vector_int_t #define BASE_MATRIX igraph_matrix_int_t #define SHORT int diff --git a/src/vendor/cigraph/include/igraph_pmt_off.h b/src/vendor/cigraph/include/igraph_pmt_off.h index f0ed85fdad8..14be2b8d39a 100644 --- a/src/vendor/cigraph/include/igraph_pmt_off.h +++ b/src/vendor/cigraph/include/igraph_pmt_off.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_progress.h b/src/vendor/cigraph/include/igraph_progress.h index 19bc2fb4aa6..48055af0c69 100644 --- a/src/vendor/cigraph/include/igraph_progress.h +++ b/src/vendor/cigraph/include/igraph_progress.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_psumtree.h b/src/vendor/cigraph/include/igraph_psumtree.h index 3811c203cc7..5e3d5e731bf 100644 --- a/src/vendor/cigraph/include/igraph_psumtree.h +++ b/src/vendor/cigraph/include/igraph_psumtree.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,18 +27,18 @@ IGRAPH_BEGIN_C_DECLS typedef struct { igraph_vector_t v; - igraph_integer_t size; - igraph_integer_t offset; + igraph_int_t size; + igraph_int_t offset; } igraph_psumtree_t; -IGRAPH_EXPORT igraph_error_t igraph_psumtree_init(igraph_psumtree_t *t, igraph_integer_t size); +IGRAPH_EXPORT igraph_error_t igraph_psumtree_init(igraph_psumtree_t *t, igraph_int_t size); IGRAPH_EXPORT void igraph_psumtree_reset(igraph_psumtree_t *t); IGRAPH_EXPORT void igraph_psumtree_destroy(igraph_psumtree_t *t); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_psumtree_get(const igraph_psumtree_t *t, igraph_integer_t idx); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_psumtree_size(const igraph_psumtree_t *t); -IGRAPH_EXPORT igraph_error_t igraph_psumtree_search(const igraph_psumtree_t *t, igraph_integer_t *idx, +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_psumtree_get(const igraph_psumtree_t *t, igraph_int_t idx); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_psumtree_size(const igraph_psumtree_t *t); +IGRAPH_EXPORT igraph_error_t igraph_psumtree_search(const igraph_psumtree_t *t, igraph_int_t *idx, igraph_real_t elem); -IGRAPH_EXPORT igraph_error_t igraph_psumtree_update(igraph_psumtree_t *t, igraph_integer_t idx, +IGRAPH_EXPORT igraph_error_t igraph_psumtree_update(igraph_psumtree_t *t, igraph_int_t idx, igraph_real_t new_value); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_psumtree_sum(const igraph_psumtree_t *t); diff --git a/src/vendor/cigraph/include/igraph_qsort.h b/src/vendor/cigraph/include/igraph_qsort.h index e32362a3215..9992727e029 100644 --- a/src/vendor/cigraph/include/igraph_qsort.h +++ b/src/vendor/cigraph/include/igraph_qsort.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_random.h b/src/vendor/cigraph/include/igraph_random.h index ff60b1eacd6..c3efc387447 100644 --- a/src/vendor/cigraph/include/igraph_random.h +++ b/src/vendor/cigraph/include/igraph_random.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -25,7 +25,6 @@ #include #include -#include IGRAPH_BEGIN_C_DECLS @@ -68,7 +67,7 @@ IGRAPH_BEGIN_C_DECLS * the caller is responsible for ensuring that this is the case. You can always * assume that hi > lo. Note that both endpoints are _inclusive_, and you must * make sure that your generation scheme works for both 32-bit and 64-bit - * versions of igraph_integer_t as igraph can be compiled for both cases. If + * versions of igraph_int_t as igraph can be compiled for both cases. If * you are unsure, leave get_int() unimplemented and igraph will provide its * own implementation based on get(). */ @@ -89,11 +88,11 @@ typedef struct igraph_rng_type_t { /* Optional generators; defaults are provided by igraph that rely solely * on get() */ - igraph_integer_t (*get_int)(void *state, igraph_integer_t l, igraph_integer_t h); + igraph_int_t (*get_int)(void *state, igraph_int_t l, igraph_int_t h); igraph_real_t (*get_real)(void *state); igraph_real_t (*get_norm)(void *state); igraph_real_t (*get_geom)(void *state, igraph_real_t p); - igraph_real_t (*get_binom)(void *state, igraph_integer_t n, igraph_real_t p); + igraph_real_t (*get_binom)(void *state, igraph_int_t n, igraph_real_t p); igraph_real_t (*get_exp)(void *state, igraph_real_t rate); igraph_real_t (*get_gamma)(void *state, igraph_real_t shape, igraph_real_t scale); @@ -112,13 +111,13 @@ IGRAPH_EXPORT igraph_error_t igraph_rng_init(igraph_rng_t *rng, const igraph_rng IGRAPH_EXPORT void igraph_rng_destroy(igraph_rng_t *rng); IGRAPH_EXPORT igraph_error_t igraph_rng_seed(igraph_rng_t *rng, igraph_uint_t seed); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_rng_bits(const igraph_rng_t* rng); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_rng_bits(const igraph_rng_t* rng); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_uint_t igraph_rng_max(const igraph_rng_t *rng); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE const char *igraph_rng_name(const igraph_rng_t *rng); IGRAPH_EXPORT igraph_bool_t igraph_rng_get_bool(igraph_rng_t *rng) ; -IGRAPH_EXPORT igraph_integer_t igraph_rng_get_integer( - igraph_rng_t *rng, igraph_integer_t l, igraph_integer_t h +IGRAPH_EXPORT igraph_int_t igraph_rng_get_integer( + igraph_rng_t *rng, igraph_int_t l, igraph_int_t h ); IGRAPH_EXPORT igraph_real_t igraph_rng_get_normal( igraph_rng_t *rng, igraph_real_t m, igraph_real_t s @@ -129,7 +128,7 @@ IGRAPH_EXPORT igraph_real_t igraph_rng_get_unif( IGRAPH_EXPORT igraph_real_t igraph_rng_get_unif01(igraph_rng_t *rng); IGRAPH_EXPORT igraph_real_t igraph_rng_get_geom(igraph_rng_t *rng, igraph_real_t p); IGRAPH_EXPORT igraph_real_t igraph_rng_get_binom( - igraph_rng_t *rng, igraph_integer_t n, igraph_real_t p + igraph_rng_t *rng, igraph_int_t n, igraph_real_t p ); IGRAPH_EXPORT igraph_real_t igraph_rng_get_exp(igraph_rng_t *rng, igraph_real_t rate); IGRAPH_EXPORT igraph_real_t igraph_rng_get_gamma( diff --git a/src/vendor/cigraph/include/igraph_reachability.h b/src/vendor/cigraph/include/igraph_reachability.h index 8c99fd8502c..b51f99888f5 100644 --- a/src/vendor/cigraph/include/igraph_reachability.h +++ b/src/vendor/cigraph/include/igraph_reachability.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -31,7 +31,7 @@ IGRAPH_EXPORT igraph_error_t igraph_reachability( const igraph_t *graph, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t *no_of_components, + igraph_int_t *no_of_components, igraph_bitset_list_t *reach, igraph_neimode_t mode); diff --git a/src/vendor/cigraph/include/igraph_sampling.h b/src/vendor/cigraph/include/igraph_sampling.h index a9a5725ccbd..322e7ced09c 100644 --- a/src/vendor/cigraph/include/igraph_sampling.h +++ b/src/vendor/cigraph/include/igraph_sampling.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,17 +27,17 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT igraph_error_t igraph_rng_sample_sphere_surface( - igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_rng_t* rng, igraph_int_t dim, igraph_int_t n, igraph_real_t radius, igraph_bool_t positive, igraph_matrix_t *res ); IGRAPH_EXPORT igraph_error_t igraph_rng_sample_sphere_volume( - igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_rng_t* rng, igraph_int_t dim, igraph_int_t n, igraph_real_t radius, igraph_bool_t positive, igraph_matrix_t *res ); IGRAPH_EXPORT igraph_error_t igraph_rng_sample_dirichlet( - igraph_rng_t* rng, igraph_integer_t n, const igraph_vector_t *alpha, igraph_matrix_t *res + igraph_rng_t* rng, igraph_int_t n, const igraph_vector_t *alpha, igraph_matrix_t *res ); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_scan.h b/src/vendor/cigraph/include/igraph_scan.h index 60199f05d7e..c3eb73c4ca0 100644 --- a/src/vendor/cigraph/include/igraph_scan.h +++ b/src/vendor/cigraph/include/igraph_scan.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -44,13 +44,13 @@ IGRAPH_EXPORT igraph_error_t igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_vector_t *weights, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_local_scan_k_ecount(const igraph_t *graph, igraph_integer_t k, +IGRAPH_EXPORT igraph_error_t igraph_local_scan_k_ecount(const igraph_t *graph, igraph_int_t k, igraph_vector_t *res, const igraph_vector_t *weights, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_local_scan_k_ecount_them(const igraph_t *us, const igraph_t *them, - igraph_integer_t k, igraph_vector_t *res, + igraph_int_t k, igraph_vector_t *res, const igraph_vector_t *weights_them, igraph_neimode_t mode); diff --git a/src/vendor/cigraph/include/igraph_separators.h b/src/vendor/cigraph/include/igraph_separators.h index 5e2a16abe37..1108a01c973 100644 --- a/src/vendor/cigraph/include/igraph_separators.h +++ b/src/vendor/cigraph/include/igraph_separators.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -20,7 +20,6 @@ #define IGRAPH_SEPARATORS_H #include "igraph_decls.h" - #include "igraph_datatype.h" #include "igraph_error.h" #include "igraph_iterators.h" diff --git a/src/vendor/cigraph/include/igraph_setup.h b/src/vendor/cigraph/include/igraph_setup.h index 58e2ab41da2..90532d146f8 100644 --- a/src/vendor/cigraph/include/igraph_setup.h +++ b/src/vendor/cigraph/include/igraph_setup.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_sparsemat.h b/src/vendor/cigraph/include/igraph_sparsemat.h index b390fa1d78b..1ea5778ecb6 100644 --- a/src/vendor/cigraph/include/igraph_sparsemat.h +++ b/src/vendor/cigraph/include/igraph_sparsemat.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -23,7 +23,6 @@ #include "igraph_error.h" #include "igraph_types.h" #include "igraph_vector.h" -#include "igraph_datatype.h" #include "igraph_arpack.h" #include @@ -31,7 +30,7 @@ IGRAPH_BEGIN_C_DECLS /* - * These types are private to igraph, and customized to use igraph_integer_t. + * These types are private to igraph, and customized to use igraph_int_t. * Do not attempt to access them using a separate copy of the CXSparse library. * Use the public igraph_sparsemat_... types instead. */ @@ -57,29 +56,29 @@ typedef enum { IGRAPH_SPARSEMAT_TRIPLET, typedef struct { const igraph_sparsemat_t *mat; - igraph_integer_t pos; - igraph_integer_t col; + igraph_int_t pos; + igraph_int_t col; } igraph_sparsemat_iterator_t; IGRAPH_EXPORT igraph_error_t igraph_sparsemat_init( - igraph_sparsemat_t *A, igraph_integer_t rows, igraph_integer_t cols, - igraph_integer_t nzmax + igraph_sparsemat_t *A, igraph_int_t rows, igraph_int_t cols, + igraph_int_t nzmax ); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_init_copy( igraph_sparsemat_t *to, const igraph_sparsemat_t *from); IGRAPH_EXPORT void igraph_sparsemat_destroy(igraph_sparsemat_t *A); -IGRAPH_EXPORT igraph_error_t igraph_sparsemat_realloc(igraph_sparsemat_t *A, igraph_integer_t nzmax); +IGRAPH_EXPORT igraph_error_t igraph_sparsemat_realloc(igraph_sparsemat_t *A, igraph_int_t nzmax); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_init_eye(igraph_sparsemat_t *A, - igraph_integer_t n, igraph_integer_t nzmax, + igraph_int_t n, igraph_int_t nzmax, igraph_real_t value, igraph_bool_t compress); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_init_diag(igraph_sparsemat_t *A, - igraph_integer_t nzmax, const igraph_vector_t *values, + igraph_int_t nzmax, const igraph_vector_t *values, igraph_bool_t compress); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_nrow(const igraph_sparsemat_t *A); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_ncol(const igraph_sparsemat_t *B); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_nrow(const igraph_sparsemat_t *A); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_ncol(const igraph_sparsemat_t *B); IGRAPH_EXPORT igraph_sparsemat_type_t igraph_sparsemat_type(const igraph_sparsemat_t *A); IGRAPH_EXPORT igraph_bool_t igraph_sparsemat_is_triplet(const igraph_sparsemat_t *A); IGRAPH_EXPORT igraph_bool_t igraph_sparsemat_is_cc(const igraph_sparsemat_t *A); @@ -90,7 +89,7 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_permute(const igraph_sparsemat_t * igraph_sparsemat_t *res); IGRAPH_EXPORT igraph_real_t igraph_sparsemat_get( - const igraph_sparsemat_t *A, igraph_integer_t row, igraph_integer_t col + const igraph_sparsemat_t *A, igraph_int_t row, igraph_int_t col ); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_index(const igraph_sparsemat_t *A, const igraph_vector_int_t *p, @@ -99,7 +98,7 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_index(const igraph_sparsemat_t *A, igraph_real_t *constres); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_entry(igraph_sparsemat_t *A, - igraph_integer_t row, igraph_integer_t col, igraph_real_t elem); + igraph_int_t row, igraph_int_t col, igraph_real_t elem); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_compress(const igraph_sparsemat_t *A, igraph_sparsemat_t *res); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_transpose( @@ -108,7 +107,7 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_transpose( IGRAPH_EXPORT igraph_error_t igraph_sparsemat_is_symmetric(const igraph_sparsemat_t *A, igraph_bool_t *result); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_dupl(igraph_sparsemat_t *A); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_fkeep(igraph_sparsemat_t *A, - igraph_integer_t (*fkeep)(igraph_integer_t, igraph_integer_t, igraph_real_t, void*), + igraph_int_t (*fkeep)(igraph_int_t, igraph_int_t, igraph_real_t, void*), void *other); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_dropzeros(igraph_sparsemat_t *A); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_droptol(igraph_sparsemat_t *A, igraph_real_t tol); @@ -140,12 +139,12 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_utsolve(const igraph_sparsemat_t * IGRAPH_EXPORT igraph_error_t igraph_sparsemat_cholsol(const igraph_sparsemat_t *A, const igraph_vector_t *b, igraph_vector_t *res, - igraph_integer_t order); + igraph_int_t order); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_lusol(const igraph_sparsemat_t *A, const igraph_vector_t *b, igraph_vector_t *res, - igraph_integer_t order, + igraph_int_t order, igraph_real_t tol); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_print(const igraph_sparsemat_t *A, @@ -193,10 +192,10 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_qrresol(const igraph_sparsemat_sym const igraph_vector_t *b, igraph_vector_t *res); -IGRAPH_EXPORT igraph_error_t igraph_sparsemat_symbqr(igraph_integer_t order, const igraph_sparsemat_t *A, +IGRAPH_EXPORT igraph_error_t igraph_sparsemat_symbqr(igraph_int_t order, const igraph_sparsemat_t *A, igraph_sparsemat_symbolic_t *dis); -IGRAPH_EXPORT igraph_error_t igraph_sparsemat_symblu(igraph_integer_t order, const igraph_sparsemat_t *A, +IGRAPH_EXPORT igraph_error_t igraph_sparsemat_symblu(igraph_int_t order, const igraph_sparsemat_t *A, igraph_sparsemat_symbolic_t *dis); @@ -208,8 +207,8 @@ IGRAPH_EXPORT igraph_real_t igraph_sparsemat_min(igraph_sparsemat_t *A); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_minmax(igraph_sparsemat_t *A, igraph_real_t *min, igraph_real_t *max); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_count_nonzero(igraph_sparsemat_t *A); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_count_nonzerotol(igraph_sparsemat_t *A, +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_count_nonzero(igraph_sparsemat_t *A); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_count_nonzerotol(igraph_sparsemat_t *A, igraph_real_t tol); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_rowsums(const igraph_sparsemat_t *A, igraph_vector_t *res); @@ -236,11 +235,11 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_which_min_cols(igraph_sparsemat_t IGRAPH_EXPORT igraph_error_t igraph_sparsemat_scale(igraph_sparsemat_t *A, igraph_real_t by); -IGRAPH_EXPORT igraph_error_t igraph_sparsemat_add_rows(igraph_sparsemat_t *A, igraph_integer_t n); -IGRAPH_EXPORT igraph_error_t igraph_sparsemat_add_cols(igraph_sparsemat_t *A, igraph_integer_t n); +IGRAPH_EXPORT igraph_error_t igraph_sparsemat_add_rows(igraph_sparsemat_t *A, igraph_int_t n); +IGRAPH_EXPORT igraph_error_t igraph_sparsemat_add_cols(igraph_sparsemat_t *A, igraph_int_t n); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_resize(igraph_sparsemat_t *A, - igraph_integer_t nrow, igraph_integer_t ncol, igraph_integer_t nzmax); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_nonzero_storage(const igraph_sparsemat_t *A); + igraph_int_t nrow, igraph_int_t ncol, igraph_int_t nzmax); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_nonzero_storage(const igraph_sparsemat_t *A); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_getelements(const igraph_sparsemat_t *A, igraph_vector_int_t *i, igraph_vector_int_t *j, @@ -260,13 +259,10 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_dense_multiply(const igraph_matrix const igraph_sparsemat_t *B, igraph_matrix_t *res); -IGRAPH_EXPORT igraph_error_t igraph_sparsemat_view(igraph_sparsemat_t *A, igraph_integer_t nzmax, igraph_integer_t m, igraph_integer_t n, - igraph_integer_t *p, igraph_integer_t *i, igraph_real_t *x, igraph_integer_t nz); - IGRAPH_EXPORT igraph_error_t igraph_sparsemat_sort(const igraph_sparsemat_t *A, igraph_sparsemat_t *sorted); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_nzmax(const igraph_sparsemat_t *A); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_nzmax(const igraph_sparsemat_t *A); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_neg(igraph_sparsemat_t *A); @@ -280,11 +276,11 @@ IGRAPH_EXPORT igraph_error_t igraph_sparsemat_iterator_init( ); IGRAPH_EXPORT igraph_error_t igraph_sparsemat_iterator_reset(igraph_sparsemat_iterator_t *it); IGRAPH_EXPORT igraph_bool_t igraph_sparsemat_iterator_end(const igraph_sparsemat_iterator_t *it); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_iterator_row(const igraph_sparsemat_iterator_t *it); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_iterator_col(const igraph_sparsemat_iterator_t *it); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_iterator_idx(const igraph_sparsemat_iterator_t *it); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_iterator_row(const igraph_sparsemat_iterator_t *it); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_iterator_col(const igraph_sparsemat_iterator_t *it); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_iterator_idx(const igraph_sparsemat_iterator_t *it); IGRAPH_EXPORT igraph_real_t igraph_sparsemat_iterator_get(const igraph_sparsemat_iterator_t *it); -IGRAPH_EXPORT igraph_integer_t igraph_sparsemat_iterator_next(igraph_sparsemat_iterator_t *it); +IGRAPH_EXPORT igraph_int_t igraph_sparsemat_iterator_next(igraph_sparsemat_iterator_t *it); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_spatial.h b/src/vendor/cigraph/include/igraph_spatial.h index a4eeb0b1a08..1e1ad35abbb 100644 --- a/src/vendor/cigraph/include/igraph_spatial.h +++ b/src/vendor/cigraph/include/igraph_spatial.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,6 +27,32 @@ IGRAPH_BEGIN_C_DECLS +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_delaunay_graph( + igraph_t *graph, + const igraph_matrix_t *points); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_lune_beta_skeleton( + igraph_t *graph, + const igraph_matrix_t *points, + igraph_real_t beta); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_circle_beta_skeleton( + igraph_t *graph, + const igraph_matrix_t *points, + igraph_real_t beta); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_beta_weighted_gabriel_graph( + igraph_t *graph, + igraph_vector_t *weights, + const igraph_matrix_t *points, + igraph_real_t max_beta); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_gabriel_graph( + igraph_t *graph, const igraph_matrix_t *points); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_relative_neighborhood_graph( + igraph_t *graph, const igraph_matrix_t *points); + /** * \typedef igraph_metric_t * \brief Metric functions for use with spatial computation. @@ -41,14 +67,24 @@ typedef enum { IGRAPH_METRIC_L1 = IGRAPH_METRIC_MANHATTAN } igraph_metric_t; -IGRAPH_EXPORT igraph_error_t igraph_nearest_neighbor_graph( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_nearest_neighbor_graph( igraph_t *graph, const igraph_matrix_t *points, igraph_metric_t metric, - igraph_integer_t neighbors, + igraph_int_t neighbors, igraph_real_t cutoff, - igraph_bool_t directed -); + igraph_bool_t directed); + +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_spatial_edge_lengths( + const igraph_t *graph, + igraph_vector_t *lengths, + const igraph_matrix_t *points, + igraph_metric_t metric); + +IGRAPH_EXPORT igraph_error_t igraph_convex_hull_2d( + const igraph_matrix_t *data, + igraph_vector_int_t *resverts, + igraph_matrix_t *rescoords); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_stack.h b/src/vendor/cigraph/include/igraph_stack.h index 616231b245f..0b84a0a080c 100644 --- a/src/vendor/cigraph/include/igraph_stack.h +++ b/src/vendor/cigraph/include/igraph_stack.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_stack_pmt.h b/src/vendor/cigraph/include/igraph_stack_pmt.h index fc0fcfbd516..4d1c320af4a 100644 --- a/src/vendor/cigraph/include/igraph_stack_pmt.h +++ b/src/vendor/cigraph/include/igraph_stack_pmt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,12 +29,12 @@ typedef struct TYPE(igraph_stack) { BASE* end; } TYPE(igraph_stack); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_stack, init)(TYPE(igraph_stack)* s, igraph_integer_t capacity); +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_stack, init)(TYPE(igraph_stack)* s, igraph_int_t capacity); IGRAPH_EXPORT void FUNCTION(igraph_stack, destroy)(TYPE(igraph_stack)* s); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_stack, reserve)(TYPE(igraph_stack)* s, igraph_integer_t capacity); +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_stack, reserve)(TYPE(igraph_stack)* s, igraph_int_t capacity); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_stack, empty)(TYPE(igraph_stack)* s); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_stack, size)(const TYPE(igraph_stack)* s); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_stack, capacity)(const TYPE(igraph_stack)* s); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_stack, size)(const TYPE(igraph_stack)* s); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_stack, capacity)(const TYPE(igraph_stack)* s); IGRAPH_EXPORT void FUNCTION(igraph_stack, clear)(TYPE(igraph_stack)* s); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_stack, push)(TYPE(igraph_stack)* s, BASE elem); IGRAPH_EXPORT BASE FUNCTION(igraph_stack, pop)(TYPE(igraph_stack)* s); diff --git a/src/vendor/cigraph/include/igraph_statusbar.h b/src/vendor/cigraph/include/igraph_statusbar.h index d9b1e532640..d8c1bae2dbc 100644 --- a/src/vendor/cigraph/include/igraph_statusbar.h +++ b/src/vendor/cigraph/include/igraph_statusbar.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_structural.h b/src/vendor/cigraph/include/igraph_structural.h index 5508a111f12..b568422fbee 100644 --- a/src/vendor/cigraph/include/igraph_structural.h +++ b/src/vendor/cigraph/include/igraph_structural.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,18 +35,18 @@ IGRAPH_BEGIN_C_DECLS /* Basic query functions */ /* -------------------------------------------------- */ -IGRAPH_EXPORT igraph_error_t igraph_are_adjacent(const igraph_t *graph, igraph_integer_t v1, igraph_integer_t v2, igraph_bool_t *res); +IGRAPH_EXPORT igraph_error_t igraph_are_adjacent(const igraph_t *graph, igraph_int_t v1, igraph_int_t v2, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_count_multiple(const igraph_t *graph, igraph_vector_int_t *res, igraph_es_t es); -IGRAPH_EXPORT igraph_error_t igraph_count_multiple_1(const igraph_t *graph, igraph_integer_t *res, igraph_integer_t eid); -IGRAPH_EXPORT igraph_error_t igraph_density(const igraph_t *graph, igraph_real_t *res, - igraph_bool_t loops); +IGRAPH_EXPORT igraph_error_t igraph_count_multiple_1(const igraph_t *graph, igraph_int_t *res, igraph_int_t eid); +IGRAPH_EXPORT igraph_error_t igraph_density(const igraph_t *graph, const igraph_vector_t *weights, + igraph_real_t *res, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_diversity(const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, igraph_vs_t vs); IGRAPH_EXPORT igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth, igraph_vector_int_t *circle); IGRAPH_EXPORT igraph_error_t igraph_has_loop(const igraph_t *graph, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_has_multiple(const igraph_t *graph, igraph_bool_t *res); -IGRAPH_EXPORT igraph_error_t igraph_count_loops(const igraph_t *graph, igraph_integer_t *loop_count); +IGRAPH_EXPORT igraph_error_t igraph_count_loops(const igraph_t *graph, igraph_int_t *loop_count); IGRAPH_EXPORT igraph_error_t igraph_is_loop(const igraph_t *graph, igraph_vector_bool_t *res, igraph_es_t es); IGRAPH_EXPORT igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *res, @@ -54,11 +54,11 @@ IGRAPH_EXPORT igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_ve IGRAPH_EXPORT igraph_error_t igraph_is_mutual(const igraph_t *graph, igraph_vector_bool_t *res, igraph_es_t es, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_has_mutual(const igraph_t *graph, igraph_bool_t *res, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_integer_t *root, igraph_neimode_t mode); +IGRAPH_EXPORT igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_int_t *root, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_is_acyclic(const igraph_t *graph, igraph_bool_t *res); IGRAPH_EXPORT igraph_error_t igraph_is_forest(const igraph_t *graph, igraph_bool_t *res, igraph_vector_int_t *roots, igraph_neimode_t mode); -IGRAPH_EXPORT igraph_error_t igraph_maxdegree(const igraph_t *graph, igraph_integer_t *res, +IGRAPH_EXPORT igraph_error_t igraph_maxdegree(const igraph_t *graph, igraph_int_t *res, igraph_vs_t vids, igraph_neimode_t mode, igraph_loops_t loops); IGRAPH_EXPORT igraph_error_t igraph_mean_degree(const igraph_t *graph, igraph_real_t *res, @@ -90,9 +90,9 @@ IGRAPH_EXPORT igraph_error_t igraph_minimum_spanning_tree( const igraph_t *graph, igraph_vector_int_t *res, const igraph_vector_t *weights, igraph_mst_algorithm_t method); IGRAPH_EXPORT igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_int_t *res, - igraph_integer_t vid); + igraph_int_t vid); -IGRAPH_EXPORT igraph_error_t igraph_subcomponent(const igraph_t *graph, igraph_vector_int_t *res, igraph_integer_t vid, +IGRAPH_EXPORT igraph_error_t igraph_subcomponent(const igraph_t *graph, igraph_vector_int_t *res, igraph_int_t vid, igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_unfold_tree(const igraph_t *graph, igraph_t *tree, @@ -121,15 +121,7 @@ IGRAPH_EXPORT igraph_error_t igraph_degree_correlation_vector( igraph_neimode_t from_mode, igraph_neimode_t to_mode, igraph_bool_t directed_neighbors); -IGRAPH_EXPORT igraph_error_t igraph_feedback_arc_set( - const igraph_t *graph, igraph_vector_int_t *result, - const igraph_vector_t *weights, igraph_fas_algorithm_t algo); - -IGRAPH_EXPORT igraph_error_t igraph_feedback_vertex_set( - const igraph_t *graph, igraph_vector_int_t *result, - const igraph_vector_t *vertex_weights, igraph_fvs_algorithm_t algo); - -IGRAPH_EXPORT igraph_error_t igraph_rich_club_sequence( +IGRAPH_EXPERIMENTAL IGRAPH_EXPORT igraph_error_t igraph_rich_club_sequence( const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, diff --git a/src/vendor/cigraph/include/igraph_strvector.h b/src/vendor/cigraph/include/igraph_strvector.h index bbd7f03160a..cf671d4f5bf 100644 --- a/src/vendor/cigraph/include/igraph_strvector.h +++ b/src/vendor/cigraph/include/igraph_strvector.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -62,20 +62,20 @@ typedef struct s_igraph_strvector { do { IGRAPH_CHECK(igraph_strvector_init(sv, size)); \ IGRAPH_FINALLY( igraph_strvector_destroy, sv); } while (0) -IGRAPH_EXPORT igraph_error_t igraph_strvector_init(igraph_strvector_t *sv, igraph_integer_t len); +IGRAPH_EXPORT igraph_error_t igraph_strvector_init(igraph_strvector_t *sv, igraph_int_t len); IGRAPH_EXPORT void igraph_strvector_destroy(igraph_strvector_t *sv); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_strvector_size(const igraph_strvector_t *sv); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_strvector_capacity(const igraph_strvector_t *sv); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE const char *igraph_strvector_get(const igraph_strvector_t *sv, igraph_integer_t idx); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_strvector_size(const igraph_strvector_t *sv); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_strvector_capacity(const igraph_strvector_t *sv); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE const char *igraph_strvector_get(const igraph_strvector_t *sv, igraph_int_t idx); IGRAPH_EXPORT igraph_error_t igraph_strvector_set( - igraph_strvector_t *sv, igraph_integer_t idx, const char *value); + igraph_strvector_t *sv, igraph_int_t idx, const char *value); IGRAPH_EXPORT igraph_error_t igraph_strvector_set_len( - igraph_strvector_t *sv, igraph_integer_t idx, const char *value, size_t len); + igraph_strvector_t *sv, igraph_int_t idx, const char *value, size_t len); IGRAPH_EXPORT void igraph_strvector_clear(igraph_strvector_t *sv); IGRAPH_EXPORT void igraph_strvector_remove_section( - igraph_strvector_t *v, igraph_integer_t from, igraph_integer_t to); + igraph_strvector_t *v, igraph_int_t from, igraph_int_t to); IGRAPH_EXPORT void igraph_strvector_remove( - igraph_strvector_t *v, igraph_integer_t elem); + igraph_strvector_t *v, igraph_int_t elem); IGRAPH_EXPORT igraph_error_t igraph_strvector_init_copy( igraph_strvector_t *to, const igraph_strvector_t *from); IGRAPH_EXPORT igraph_error_t igraph_strvector_append( @@ -86,7 +86,7 @@ IGRAPH_EXPORT void igraph_strvector_swap(igraph_strvector_t *v1, igraph_strvecto 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_strvector_t* v, igraph_int_t newsize); IGRAPH_EXPORT void igraph_strvector_resize_min(igraph_strvector_t *sv); IGRAPH_EXPORT igraph_error_t igraph_strvector_push_back(igraph_strvector_t *v, const char *value); @@ -102,10 +102,10 @@ IGRAPH_EXPORT igraph_error_t igraph_strvector_index(const igraph_strvector_t *v, const igraph_vector_int_t *idx); IGRAPH_EXPORT igraph_error_t igraph_strvector_reserve(igraph_strvector_t *sv, - igraph_integer_t capacity); + igraph_int_t capacity); IGRAPH_EXPORT void igraph_strvector_swap_elements(igraph_strvector_t *sv, - igraph_integer_t i, igraph_integer_t j); + igraph_int_t i, igraph_int_t j); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_threading.h.in b/src/vendor/cigraph/include/igraph_threading.h.in index 555b7ff39e9..06f4d2b9921 100644 --- a/src/vendor/cigraph/include/igraph_threading.h.in +++ b/src/vendor/cigraph/include/igraph_threading.h.in @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_transitivity.h b/src/vendor/cigraph/include/igraph_transitivity.h index d830171f70f..b2cd6f3dc49 100644 --- a/src/vendor/cigraph/include/igraph_transitivity.h +++ b/src/vendor/cigraph/include/igraph_transitivity.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -45,7 +45,7 @@ IGRAPH_EXPORT igraph_error_t igraph_transitivity_barrat(const igraph_t *graph, IGRAPH_EXPORT igraph_error_t igraph_ecc(const igraph_t *graph, igraph_vector_t *res, igraph_es_t eids, - igraph_integer_t k, + igraph_int_t k, igraph_bool_t offset, igraph_bool_t normalize); diff --git a/src/vendor/cigraph/include/igraph_typed_list_pmt.h b/src/vendor/cigraph/include/igraph_typed_list_pmt.h index a4036907a69..679fabf774e 100644 --- a/src/vendor/cigraph/include/igraph_typed_list_pmt.h +++ b/src/vendor/cigraph/include/igraph_typed_list_pmt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -46,7 +46,7 @@ typedef struct { /* Allocation */ /*--------------------*/ -IGRAPH_EXPORT igraph_error_t FUNCTION(init)(TYPE* v, igraph_integer_t size); +IGRAPH_EXPORT igraph_error_t FUNCTION(init)(TYPE* v, igraph_int_t size); IGRAPH_EXPORT igraph_error_t FUNCTION(init_copy)(TYPE* to, const TYPE* from); IGRAPH_EXPORT void FUNCTION(destroy)(TYPE* v); @@ -54,43 +54,43 @@ IGRAPH_EXPORT void FUNCTION(destroy)(TYPE* v); /* Accessing elements */ /*--------------------*/ -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE ITEM_TYPE* FUNCTION(get_ptr)(const TYPE* v, igraph_integer_t pos); -IGRAPH_EXPORT void FUNCTION(set)(TYPE* v, igraph_integer_t pos, ITEM_TYPE* e); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE ITEM_TYPE* FUNCTION(get_ptr)(const TYPE* v, igraph_int_t pos); +IGRAPH_EXPORT void FUNCTION(set)(TYPE* v, igraph_int_t pos, ITEM_TYPE* e); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE ITEM_TYPE* FUNCTION(tail_ptr)(const TYPE *v); /*-----------------*/ /* List properties */ /*-----------------*/ -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(capacity)(const TYPE* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(capacity)(const TYPE* v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(empty)(const TYPE* v); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(size)(const TYPE* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(size)(const TYPE* v); /*------------------------*/ /* Resizing operations */ /*------------------------*/ IGRAPH_EXPORT void FUNCTION(clear)(TYPE* v); -IGRAPH_EXPORT igraph_error_t FUNCTION(reserve)(TYPE* v, igraph_integer_t capacity); -IGRAPH_EXPORT igraph_error_t FUNCTION(resize)(TYPE* v, igraph_integer_t new_size); +IGRAPH_EXPORT igraph_error_t FUNCTION(reserve)(TYPE* v, igraph_int_t capacity); +IGRAPH_EXPORT igraph_error_t FUNCTION(resize)(TYPE* v, igraph_int_t new_size); /*------------------------*/ /* Adding/removing items */ /*------------------------*/ -IGRAPH_EXPORT void FUNCTION(discard)(TYPE* v, igraph_integer_t index); +IGRAPH_EXPORT void FUNCTION(discard)(TYPE* v, igraph_int_t index); IGRAPH_EXPORT void FUNCTION(discard_back)(TYPE* v); -IGRAPH_EXPORT void FUNCTION(discard_fast)(TYPE* v, igraph_integer_t index); -IGRAPH_EXPORT igraph_error_t FUNCTION(insert)(TYPE* v, igraph_integer_t pos, ITEM_TYPE* e); -IGRAPH_EXPORT igraph_error_t FUNCTION(insert_copy)(TYPE* v, igraph_integer_t pos, const ITEM_TYPE* e); -IGRAPH_EXPORT igraph_error_t FUNCTION(insert_new)(TYPE* v, igraph_integer_t pos, ITEM_TYPE** result); +IGRAPH_EXPORT void FUNCTION(discard_fast)(TYPE* v, igraph_int_t index); +IGRAPH_EXPORT igraph_error_t FUNCTION(insert)(TYPE* v, igraph_int_t pos, ITEM_TYPE* e); +IGRAPH_EXPORT igraph_error_t FUNCTION(insert_copy)(TYPE* v, igraph_int_t pos, const ITEM_TYPE* e); +IGRAPH_EXPORT igraph_error_t FUNCTION(insert_new)(TYPE* v, igraph_int_t pos, ITEM_TYPE** result); IGRAPH_EXPORT igraph_error_t FUNCTION(push_back)(TYPE* v, ITEM_TYPE* e); IGRAPH_EXPORT igraph_error_t FUNCTION(push_back_copy)(TYPE* v, const ITEM_TYPE* e); IGRAPH_EXPORT igraph_error_t FUNCTION(push_back_new)(TYPE* v, ITEM_TYPE** result); IGRAPH_EXPORT ITEM_TYPE FUNCTION(pop_back)(TYPE* v); -IGRAPH_EXPORT igraph_error_t FUNCTION(remove)(TYPE* v, igraph_integer_t index, ITEM_TYPE* e); -IGRAPH_EXPORT igraph_error_t FUNCTION(remove_fast)(TYPE* v, igraph_integer_t index, ITEM_TYPE* e); -IGRAPH_EXPORT void FUNCTION(replace)(TYPE* v, igraph_integer_t pos, ITEM_TYPE* e); +IGRAPH_EXPORT igraph_error_t FUNCTION(remove)(TYPE* v, igraph_int_t index, ITEM_TYPE* e); +IGRAPH_EXPORT igraph_error_t FUNCTION(remove_fast)(TYPE* v, igraph_int_t index, ITEM_TYPE* e); +IGRAPH_EXPORT void FUNCTION(replace)(TYPE* v, igraph_int_t pos, ITEM_TYPE* e); IGRAPH_EXPORT void FUNCTION(remove_consecutive_duplicates)(TYPE *v, igraph_bool_t (*eq)(const ITEM_TYPE*, const ITEM_TYPE*)); /*------------------*/ @@ -100,7 +100,7 @@ IGRAPH_EXPORT void FUNCTION(remove_consecutive_duplicates)(TYPE *v, igraph_bool_ IGRAPH_EXPORT igraph_error_t FUNCTION(permute)(TYPE *v, const igraph_vector_int_t *index); IGRAPH_EXPORT igraph_error_t FUNCTION(reverse)(TYPE *v); IGRAPH_EXPORT void FUNCTION(swap)(TYPE *v1, TYPE *v2); -IGRAPH_EXPORT void FUNCTION(swap_elements)(TYPE* v, igraph_integer_t i, igraph_integer_t j); +IGRAPH_EXPORT void FUNCTION(swap_elements)(TYPE* v, igraph_int_t i, igraph_int_t j); /*-----------*/ /* Sorting */ diff --git a/src/vendor/cigraph/include/igraph_types.h b/src/vendor/cigraph/include/igraph_types.h index 19e93338b35..5acd293150f 100644 --- a/src/vendor/cigraph/include/igraph_types.h +++ b/src/vendor/cigraph/include/igraph_types.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -40,16 +40,16 @@ IGRAPH_BEGIN_C_DECLS #if !defined(IGRAPH_INTEGER_SIZE) # error "igraph integer size not defined; check the value of IGRAPH_INTEGER_SIZE when compiling" #elif IGRAPH_INTEGER_SIZE == 64 -typedef int64_t igraph_integer_t; +typedef int64_t igraph_int_t; typedef uint64_t igraph_uint_t; #elif IGRAPH_INTEGER_SIZE == 32 -typedef int32_t igraph_integer_t; +typedef int32_t igraph_int_t; typedef uint32_t igraph_uint_t; #else # error "Invalid igraph integer size; check the value of IGRAPH_INTEGER_SIZE when compiling" #endif -typedef igraph_integer_t igraph_int_t; +typedef igraph_int_t igraph_integer_t; typedef double igraph_real_t; @@ -58,7 +58,7 @@ typedef double igraph_real_t; * See igraph_config.h for more info */ typedef IGRAPH_BOOL_TYPE igraph_bool_t; -/* printf format specifier for igraph_integer_t */ +/* printf format specifier for igraph_int_t */ #if IGRAPH_INTEGER_SIZE == 64 # define IGRAPH_PRId PRId64 # define IGRAPH_PRIu PRIu64 @@ -67,7 +67,7 @@ typedef IGRAPH_BOOL_TYPE igraph_bool_t; # define IGRAPH_PRIu PRIu32 #endif -/* maximum and minimum allowed values for igraph_integer_t */ +/* maximum and minimum allowed values for igraph_int_t */ #if IGRAPH_INTEGER_SIZE == 64 # define IGRAPH_INTEGER_MAX INT64_MAX # define IGRAPH_INTEGER_MIN INT64_MIN diff --git a/src/vendor/cigraph/include/igraph_vector.h b/src/vendor/cigraph/include/igraph_vector.h index 463b79ec632..16d7a9d0b64 100644 --- a/src/vendor/cigraph/include/igraph_vector.h +++ b/src/vendor/cigraph/include/igraph_vector.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -140,18 +140,18 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_vector_is_any_nan(const IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_vector_is_all_finite(const igraph_vector_t *v); IGRAPH_EXPORT igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, const igraph_vector_int_t *v2, - igraph_vector_int_t* res, igraph_integer_t maxval); + igraph_vector_int_t* res, igraph_int_t maxval); /* For internal use only: */ IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_vector_int_order( const igraph_vector_int_t* v, igraph_vector_int_t* res, - igraph_integer_t maxval); + igraph_int_t maxval); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_vector_int_rank( const igraph_vector_int_t *v, igraph_vector_int_t *res, - igraph_integer_t maxval); + igraph_int_t maxval); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_vector_list.h b/src/vendor/cigraph/include/igraph_vector_list.h index 8fff22fd509..20b7c02da6a 100644 --- a/src/vendor/cigraph/include/igraph_vector_list.h +++ b/src/vendor/cigraph/include/igraph_vector_list.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_vector_pmt.h b/src/vendor/cigraph/include/igraph_vector_pmt.h index 43a708b8043..9548af4efdd 100644 --- a/src/vendor/cigraph/include/igraph_vector_pmt.h +++ b/src/vendor/cigraph/include/igraph_vector_pmt.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -21,9 +21,9 @@ /*--------------------*/ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init)( - TYPE(igraph_vector) *v, igraph_integer_t size); + TYPE(igraph_vector) *v, igraph_int_t size); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_array)( - TYPE(igraph_vector) *v, const BASE *data, igraph_integer_t length); + TYPE(igraph_vector) *v, const BASE *data, igraph_int_t length); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_copy)( TYPE(igraph_vector) *to, const TYPE(igraph_vector) *from); @@ -33,7 +33,7 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_range)(TYPE(igraph_vec IGRAPH_EXPORT void FUNCTION(igraph_vector, destroy)(TYPE(igraph_vector) *v); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, capacity)(const TYPE(igraph_vector)*v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_vector, capacity)(const TYPE(igraph_vector)*v); /*--------------------*/ /* Accessing elements */ @@ -60,9 +60,9 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, capa #define VECTOR(v) ((v).stor_begin) #endif -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_vector, get)(const TYPE(igraph_vector) *v, igraph_integer_t pos); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE* FUNCTION(igraph_vector, get_ptr)(const TYPE(igraph_vector) *v, igraph_integer_t pos); -IGRAPH_EXPORT void FUNCTION(igraph_vector, set)(TYPE(igraph_vector) *v, igraph_integer_t pos, BASE value); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_vector, get)(const TYPE(igraph_vector) *v, igraph_int_t pos); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE* FUNCTION(igraph_vector, get_ptr)(const TYPE(igraph_vector) *v, igraph_int_t pos); +IGRAPH_EXPORT void FUNCTION(igraph_vector, set)(TYPE(igraph_vector) *v, igraph_int_t pos, BASE value); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_vector, tail)(const TYPE(igraph_vector) *v); /*-----------------------*/ @@ -80,9 +80,8 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, range)(TYPE(igraph_vector) /* Vector views */ /*-----------------------*/ -IGRAPH_EXPORT const TYPE(igraph_vector) *FUNCTION(igraph_vector, view)(const TYPE(igraph_vector) *v, - const BASE *data, - igraph_integer_t length); +IGRAPH_EXPORT TYPE(igraph_vector) FUNCTION(igraph_vector, view)(const BASE *data, + igraph_int_t length); /*-----------------------*/ /* Copying vectors */ @@ -100,12 +99,12 @@ IGRAPH_EXPORT void FUNCTION(igraph_vector, swap)(TYPE(igraph_vector) *v1, TYPE(i /*-----------------------*/ IGRAPH_EXPORT void FUNCTION(igraph_vector, swap_elements)( - TYPE(igraph_vector) *v, igraph_integer_t i, igraph_integer_t j); + TYPE(igraph_vector) *v, igraph_int_t i, igraph_int_t j); IGRAPH_EXPORT void FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v); IGRAPH_EXPORT void FUNCTION(igraph_vector, reverse_section)( - TYPE(igraph_vector) *v, igraph_integer_t from, igraph_integer_t to); + TYPE(igraph_vector) *v, igraph_int_t from, igraph_int_t to); IGRAPH_EXPORT void FUNCTION(igraph_vector, rotate_left)( - TYPE(igraph_vector) *v, igraph_integer_t n); + TYPE(igraph_vector) *v, igraph_int_t n); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, permute)(TYPE(igraph_vector) *v, const igraph_vector_int_t *ind); IGRAPH_EXPORT void FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v); @@ -161,12 +160,12 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE int FUNCTION(igraph_vector, colex_cmp_untyped #ifndef NOTORDERED IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_vector, min)(const TYPE(igraph_vector)* v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_vector, max)(const TYPE(igraph_vector)* v); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, which_min)(const TYPE(igraph_vector)* v); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, which_max)(const TYPE(igraph_vector)* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_vector, which_min)(const TYPE(igraph_vector)* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_vector, which_max)(const TYPE(igraph_vector)* v); IGRAPH_EXPORT void FUNCTION(igraph_vector, minmax)( const TYPE(igraph_vector) *v, BASE *min, BASE *max); IGRAPH_EXPORT void FUNCTION(igraph_vector, which_minmax)( - const TYPE(igraph_vector) *v, igraph_integer_t *which_min, igraph_integer_t *which_max); + const TYPE(igraph_vector) *v, igraph_int_t *which_min, igraph_int_t *which_max); #endif /*-------------------*/ @@ -174,7 +173,7 @@ IGRAPH_EXPORT void FUNCTION(igraph_vector, which_minmax)( /*-------------------*/ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_vector, empty)(const TYPE(igraph_vector)* v); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, size)(const TYPE(igraph_vector)* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_vector, size)(const TYPE(igraph_vector)* v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_vector, isnull)(const TYPE(igraph_vector) *v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE BASE FUNCTION(igraph_vector, sum)(const TYPE(igraph_vector) *v); IGRAPH_DEPRECATED IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t FUNCTION(igraph_vector, sumsq)(const TYPE(igraph_vector) *v); @@ -198,13 +197,13 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t FUNCTION(igraph_vector, maxdiff IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_vector, contains)(const TYPE(igraph_vector) *v, BASE e); IGRAPH_EXPORT igraph_bool_t FUNCTION(igraph_vector, search)( - const TYPE(igraph_vector) *v, igraph_integer_t from, BASE what, igraph_integer_t *pos); + const TYPE(igraph_vector) *v, igraph_int_t from, BASE what, igraph_int_t *pos); #ifndef NOTORDERED IGRAPH_EXPORT igraph_bool_t FUNCTION(igraph_vector, binsearch_slice)( - const TYPE(igraph_vector) *v, BASE what, igraph_integer_t *pos, - igraph_integer_t start, igraph_integer_t end); + const TYPE(igraph_vector) *v, BASE what, igraph_int_t *pos, + igraph_int_t start, igraph_int_t end); IGRAPH_EXPORT igraph_bool_t FUNCTION(igraph_vector, binsearch)( - const TYPE(igraph_vector) *v, BASE what, igraph_integer_t *pos); + const TYPE(igraph_vector) *v, BASE what, igraph_int_t *pos); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_vector, contains_sorted)( const TYPE(igraph_vector) *v, BASE what); #endif @@ -215,20 +214,20 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t FUNCTION(igraph_vector, contain IGRAPH_EXPORT void FUNCTION(igraph_vector, clear)(TYPE(igraph_vector)* v); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, resize)( - TYPE(igraph_vector)* v, igraph_integer_t new_size); + TYPE(igraph_vector)* v, igraph_int_t new_size); IGRAPH_EXPORT void FUNCTION(igraph_vector, resize_min)(TYPE(igraph_vector)*v); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, reserve)( - TYPE(igraph_vector)* v, igraph_integer_t capacity); + TYPE(igraph_vector)* v, igraph_int_t capacity); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, push_back)(TYPE(igraph_vector)* v, BASE e); IGRAPH_EXPORT BASE FUNCTION(igraph_vector, pop_back)(TYPE(igraph_vector)* v); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, insert)( - TYPE(igraph_vector) *v, igraph_integer_t pos, BASE value); + TYPE(igraph_vector) *v, igraph_int_t pos, BASE value); IGRAPH_EXPORT void FUNCTION(igraph_vector, remove)( - TYPE(igraph_vector) *v, igraph_integer_t elem); + TYPE(igraph_vector) *v, igraph_int_t elem); IGRAPH_EXPORT void FUNCTION(igraph_vector, remove_fast)( - TYPE(igraph_vector) *v, igraph_integer_t elem); + TYPE(igraph_vector) *v, igraph_int_t elem); IGRAPH_EXPORT void FUNCTION(igraph_vector, remove_section)( - TYPE(igraph_vector) *v, igraph_integer_t from, igraph_integer_t to); + TYPE(igraph_vector) *v, igraph_int_t from, igraph_int_t to); /*-----------*/ /* Sorting */ @@ -286,20 +285,24 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_real_end)(TYPE(igraph_ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, init_int_end)(TYPE(igraph_vector)*v, int endmark, ...); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, move_interval)( - TYPE(igraph_vector) *v, igraph_integer_t begin, igraph_integer_t end, - igraph_integer_t to); + TYPE(igraph_vector) *v, igraph_int_t begin, igraph_int_t end, + igraph_int_t to); #ifndef NOTORDERED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, filter_smaller)(TYPE(igraph_vector) *v, BASE elem); #endif IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, get_interval)( const TYPE(igraph_vector) *v, TYPE(igraph_vector) *res, - igraph_integer_t from, igraph_integer_t to); + igraph_int_t from, igraph_int_t to); #ifndef NOTORDERED IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, difference_sorted)(const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2, TYPE(igraph_vector) *result); +IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, difference_and_intersection_sorted)( + const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2, + TYPE(igraph_vector) *vdiff12, TYPE(igraph_vector) *vdiff21, + TYPE(igraph_vector) *vinter); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, intersect_sorted)(const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2, TYPE(igraph_vector) *result); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t FUNCTION(igraph_vector, intersection_size_sorted)( +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t FUNCTION(igraph_vector, intersection_size_sorted)( const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2); #endif diff --git a/src/vendor/cigraph/include/igraph_vector_ptr.h b/src/vendor/cigraph/include/igraph_vector_ptr.h index 9bd4b6d3105..90a89ba57e8 100644 --- a/src/vendor/cigraph/include/igraph_vector_ptr.h +++ b/src/vendor/cigraph/include/igraph_vector_ptr.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -46,32 +46,31 @@ typedef struct s_vector_ptr { do { IGRAPH_CHECK(igraph_vector_ptr_init(v, size)); \ IGRAPH_FINALLY(igraph_vector_ptr_destroy, v); } while (0) -IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_init(igraph_vector_ptr_t* v, igraph_integer_t size); -IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_init_array(igraph_vector_ptr_t* v, void *const *data, igraph_integer_t length); +IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_init(igraph_vector_ptr_t* v, igraph_int_t size); +IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_init_array(igraph_vector_ptr_t* v, void *const *data, igraph_int_t length); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_init_copy(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from); -IGRAPH_EXPORT const igraph_vector_ptr_t *igraph_vector_ptr_view (const igraph_vector_ptr_t *v, - void *const *data, igraph_integer_t length); +IGRAPH_EXPORT igraph_vector_ptr_t igraph_vector_ptr_view (void *const *data, igraph_int_t length); IGRAPH_EXPORT void igraph_vector_ptr_destroy(igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_free_all(igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_destroy_all(igraph_vector_ptr_t* v); -IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_integer_t capacity); +IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_int_t capacity); IGRAPH_EXPORT void igraph_vector_ptr_resize_min(igraph_vector_ptr_t* v); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_vector_ptr_empty(const igraph_vector_ptr_t* v); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_vector_ptr_capacity(const igraph_vector_ptr_t* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_vector_ptr_capacity(const igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_clear(igraph_vector_ptr_t* v); IGRAPH_EXPORT void igraph_vector_ptr_null(igraph_vector_ptr_t* v); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_push_back(igraph_vector_ptr_t* v, void* e); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_append(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from); IGRAPH_EXPORT void *igraph_vector_ptr_pop_back(igraph_vector_ptr_t *v); -IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_insert(igraph_vector_ptr_t *v, igraph_integer_t pos, void* e); -IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_integer_t pos); -IGRAPH_EXPORT void igraph_vector_ptr_set(igraph_vector_ptr_t* v, igraph_integer_t pos, void* value); -IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_resize(igraph_vector_ptr_t* v, igraph_integer_t newsize); +IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_insert(igraph_vector_ptr_t *v, igraph_int_t pos, void* e); +IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_int_t pos); +IGRAPH_EXPORT void igraph_vector_ptr_set(igraph_vector_ptr_t* v, igraph_int_t pos, void* value); +IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_resize(igraph_vector_ptr_t* v, igraph_int_t newsize); IGRAPH_EXPORT void igraph_vector_ptr_copy_to(const igraph_vector_ptr_t *v, void** to); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_permute(igraph_vector_ptr_t* v, const igraph_vector_int_t* index); -IGRAPH_EXPORT void igraph_vector_ptr_remove(igraph_vector_ptr_t *v, igraph_integer_t pos); +IGRAPH_EXPORT void igraph_vector_ptr_remove(igraph_vector_ptr_t *v, igraph_int_t pos); IGRAPH_EXPORT void igraph_vector_ptr_sort(igraph_vector_ptr_t *v, int(*compar)(const void*, const void*)); IGRAPH_EXPORT igraph_error_t igraph_vector_ptr_sort_ind( igraph_vector_ptr_t *v, igraph_vector_int_t *inds, int(*compar)(const void*, const void*)); diff --git a/src/vendor/cigraph/include/igraph_vector_type.h b/src/vendor/cigraph/include/igraph_vector_type.h index 05a77855a8d..95c39aefe12 100644 --- a/src/vendor/cigraph/include/igraph_vector_type.h +++ b/src/vendor/cigraph/include/igraph_vector_type.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013-2025 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/include/igraph_version.h.in b/src/vendor/cigraph/include/igraph_version.h.in index 477b390d4c3..74bfc5e55a3 100644 --- a/src/vendor/cigraph/include/igraph_version.h.in +++ b/src/vendor/cigraph/include/igraph_version.h.in @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -32,7 +32,7 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_EXPORT void igraph_version(const char **version_string, int *major, int *minor, - int *subminor); + int *patch); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/include/igraph_visitor.h b/src/vendor/cigraph/include/igraph_visitor.h index 9f5f931a714..7edd3feab69 100644 --- a/src/vendor/cigraph/include/igraph_visitor.h +++ b/src/vendor/cigraph/include/igraph_visitor.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -67,15 +67,15 @@ IGRAPH_BEGIN_C_DECLS */ typedef igraph_error_t igraph_bfshandler_t(const igraph_t *graph, - igraph_integer_t vid, - igraph_integer_t pred, - igraph_integer_t succ, - igraph_integer_t rank, - igraph_integer_t dist, + igraph_int_t vid, + igraph_int_t pred, + igraph_int_t succ, + igraph_int_t rank, + igraph_int_t dist, void *extra); IGRAPH_EXPORT igraph_error_t igraph_bfs(const igraph_t *graph, - igraph_integer_t root, const igraph_vector_int_t *roots, + igraph_int_t root, const igraph_vector_int_t *roots, igraph_neimode_t mode, igraph_bool_t unreachable, const igraph_vector_int_t *restricted, igraph_vector_int_t *order, igraph_vector_int_t *rank, @@ -84,7 +84,7 @@ IGRAPH_EXPORT igraph_error_t igraph_bfs(const igraph_t *graph, igraph_vector_int_t *dist, igraph_bfshandler_t *callback, void *extra); -IGRAPH_EXPORT igraph_error_t igraph_bfs_simple(const igraph_t *graph, igraph_integer_t root, igraph_neimode_t mode, +IGRAPH_EXPORT igraph_error_t igraph_bfs_simple(const igraph_t *graph, igraph_int_t root, igraph_neimode_t mode, igraph_vector_int_t *order, igraph_vector_int_t *layers, igraph_vector_int_t *parents); @@ -117,11 +117,11 @@ IGRAPH_EXPORT igraph_error_t igraph_bfs_simple(const igraph_t *graph, igraph_int */ typedef igraph_error_t igraph_dfshandler_t(const igraph_t *graph, - igraph_integer_t vid, - igraph_integer_t dist, + igraph_int_t vid, + igraph_int_t dist, void *extra); -IGRAPH_EXPORT igraph_error_t igraph_dfs(const igraph_t *graph, igraph_integer_t root, +IGRAPH_EXPORT igraph_error_t igraph_dfs(const igraph_t *graph, igraph_int_t root, igraph_neimode_t mode, igraph_bool_t unreachable, igraph_vector_int_t *order, igraph_vector_int_t *order_out, igraph_vector_int_t *parents, diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml index 560bf6157d4..17d0ba25fe2 100644 --- a/src/vendor/cigraph/interfaces/functions.yaml +++ b/src/vendor/cigraph/interfaces/functions.yaml @@ -63,7 +63,7 @@ igraph_neighbors: PARAMS: |- GRAPH graph, OUT VERTEX_INDICES neis, VERTEX vid, NEIMODE mode=ALL, LOOPS loops=TWICE, BOOLEAN multiple=True - DEPS: neis ON graph, vid ON graph + DEPS: vid ON graph, neis ON graph FLAGS: no_rng igraph_is_directed: @@ -91,19 +91,21 @@ igraph_get_eid: PARAMS: |- GRAPH graph, OUT EDGE eid, VERTEX from, VERTEX to, BOOLEAN directed=True, BOOLEAN error=True + DEPS: eid ON graph, from ON graph, to ON graph FLAGS: no_rng igraph_get_eids: PARAMS: |- GRAPH graph, OUT EDGE_INDICES eids, VERTEX_INDEX_PAIRS pairs, BOOLEAN directed=True, BOOLEAN error=True - DEPS: pairs ON graph + DEPS: eids ON graph, pairs ON graph FLAGS: no_rng igraph_get_all_eids_between: PARAMS: |- GRAPH graph, OUT EDGE_INDICES eids, VERTEX from, VERTEX to, BOOLEAN directed=True + DEPS: eids ON graph, from ON graph, to ON graph FLAGS: no_rng igraph_incident: @@ -139,11 +141,13 @@ igraph_sparse_weighted_adjacency: PARAMS: |- OUT GRAPH graph, INOUT SPARSEMAT adjmatrix, ADJACENCY_MODE mode=DIRECTED, OUT EDGE_WEIGHTS weights, LOOPS loops=ONCE + DEPS: weights ON graph igraph_weighted_adjacency: PARAMS: |- OUT GRAPH graph, MATRIX adjmatrix, ADJACENCY_MODE mode=DIRECTED, OUT EDGE_WEIGHTS weights, LOOPS loops=ONCE + DEPS: weights ON graph igraph_star: PARAMS: OUT GRAPH graph, INTEGER n, STAR_MODE mode=OUT, INTEGER center=0 @@ -232,9 +236,8 @@ igraph_adjlist: igraph_full_bipartite: PARAMS: |- - OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, INTEGER n1, + OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, INTEGER n1, INTEGER n2, BOOLEAN directed=False, NEIMODE mode=ALL - DEPS: types ON graph igraph_full_multipartite: PARAMS: |- @@ -273,10 +276,16 @@ igraph_barabasi_game: OPTIONAL GRAPH start_from igraph_erdos_renyi_game_gnp: - PARAMS: OUT GRAPH graph, INTEGER n, REAL p, BOOLEAN directed=False, BOOLEAN loops=False + PARAMS: |- + OUT GRAPH graph, INTEGER n, REAL p, BOOLEAN directed=False, + EDGE_TYPE_SW allowed_edge_types=SIMPLE, + BOOLEAN edge_labeled=False igraph_erdos_renyi_game_gnm: - PARAMS: OUT GRAPH graph, INTEGER n, INTEGER m, BOOLEAN directed=False, BOOLEAN loops=False, BOOLEAN multiple=False + PARAMS: |- + OUT GRAPH graph, INTEGER n, INTEGER m, BOOLEAN directed=False, + EDGE_TYPE_SW allowed_edge_types=SIMPLE, + BOOLEAN edge_labeled=False igraph_iea_game: PARAMS: OUT GRAPH graph, INTEGER n, INTEGER m, BOOLEAN directed=False, BOOLEAN loops=False @@ -343,8 +352,8 @@ igraph_asymmetric_preference_game: igraph_rewire_edges: PARAMS: |- - INOUT GRAPH graph, REAL prob, BOOLEAN loops=False, - BOOLEAN multiple=False + INOUT GRAPH graph, REAL prob, + EDGE_TYPE_SW allowed_edge_types=SIMPLE igraph_rewire_directed_edges: PARAMS: |- @@ -354,7 +363,7 @@ igraph_rewire_directed_edges: igraph_watts_strogatz_game: PARAMS: |- OUT GRAPH graph, INTEGER dim, INTEGER size, INTEGER nei, - REAL p, BOOLEAN loops=False, BOOLEAN multiple=False + REAL p, EDGE_TYPE_SW allowed_edge_types=SIMPLE igraph_lastcit_game: PARAMS: |- @@ -390,14 +399,14 @@ igraph_chung_lu_game: igraph_static_fitness_game: PARAMS: |- OUT GRAPH graph, INTEGER no_of_edges, VECTOR fitness_out, - OPTIONAL VECTOR fitness_in, BOOLEAN loops=False, - BOOLEAN multiple=False + OPTIONAL VECTOR fitness_in, + EDGE_TYPE_SW allowed_edge_types=SIMPLE igraph_static_power_law_game: PARAMS: |- OUT GRAPH graph, INTEGER no_of_nodes, INTEGER no_of_edges, REAL exponent_out, REAL exponent_in=-1, - BOOLEAN loops=False, BOOLEAN multiple=False, + EDGE_TYPE_SW allowed_edge_types=SIMPLE, BOOLEAN finite_size_correction=True igraph_k_regular_game: @@ -407,9 +416,9 @@ igraph_k_regular_game: igraph_sbm_game: PARAMS: |- - OUT GRAPH graph, INTEGER n, MATRIX pref_matrix, + OUT GRAPH graph, MATRIX pref_matrix, VECTOR_INT block_sizes, BOOLEAN directed=False, - BOOLEAN loops=False + EDGE_TYPE_SW allowed_edge_types=SIMPLE igraph_hsbm_game: INTERNAL: true @@ -425,7 +434,7 @@ igraph_hsbm_list_game: igraph_correlated_game: PARAMS: |- - GRAPH old_graph, OUT GRAPH new_graph, + OUT GRAPH new_graph, GRAPH old_graph, REAL corr, REAL p=edge_density(old.graph), OPTIONAL INDEX_VECTOR permutation igraph_correlated_pair_game: @@ -475,7 +484,7 @@ igraph_closeness_cutoff: OPTIONAL OUT BOOLEAN all_reachable, VERTEX_SELECTOR vids=ALL, NEIMODE mode=OUT, OPTIONAL EDGE_WEIGHTS weights, - BOOLEAN normalized=False, REAL cutoff=-1 + BOOLEAN normalized=False, REAL cutoff=UNLIMITED DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_distances: @@ -487,7 +496,7 @@ igraph_distances: igraph_distances_cutoff: PARAMS: |- GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX res, - VERTEX_SELECTOR from=ALL, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, REAL cutoff=-1 + VERTEX_SELECTOR from=ALL, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, REAL cutoff=UNLIMITED DEPS: weights ON graph, from ON graph, to ON graph igraph_get_shortest_path: @@ -526,14 +535,14 @@ igraph_get_shortest_paths: VERTEX from, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents, OPTIONAL OUT VECTOR_INT inbound_edges - DEPS: weights ON graph, vertices ON graph, edges ON graph, from ON graph, to ON graph + DEPS: weights ON graph, edges ON graph, from ON graph, to ON graph igraph_get_all_shortest_paths: PARAMS: |- GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, 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: weights ON graph, vertices ON graph, edges ON graph, from ON graph, to ON graph + DEPS: weights ON graph, edges ON graph, from ON graph, to ON graph igraph_distances_dijkstra: PARAMS: |- @@ -544,7 +553,7 @@ igraph_distances_dijkstra: igraph_distances_dijkstra_cutoff: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, REAL cutoff=-1 + VERTEX_SELECTOR to=ALL, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, REAL cutoff=UNLIMITED DEPS: from ON graph, to ON graph, weights ON graph igraph_get_shortest_paths_dijkstra: @@ -606,7 +615,9 @@ igraph_voronoi: igraph_get_all_simple_paths: PARAMS: |- GRAPH graph, OUT VERTEX_INDICES_LIST res, VERTEX from, - VERTEX_SELECTOR to=ALL, INTEGER minlen=-1, INTEGER maxlen=-1, NEIMODE mode=OUT + VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, + INTEGER minlen=UNLIMITED, INTEGER maxlen=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: from ON graph, to ON graph, res ON graph igraph_get_k_shortest_paths: @@ -660,44 +671,44 @@ igraph_subcomponent: igraph_betweenness: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - BOOLEAN directed=True, OPTIONAL EDGE_WEIGHTS weights + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY res, + VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, BOOLEAN normalized=False 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, OPTIONAL EDGE_WEIGHTS weights, - REAL cutoff=-1 + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY res, + VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, BOOLEAN normalized=False, + REAL cutoff=UNLIMITED 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, - BOOLEAN directed=True, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, - OPTIONAL EDGE_WEIGHTS weights + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY res, + VERTEX_SELECTOR vids=ALL, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, + BOOLEAN directed=True, BOOLEAN normalized=False DEPS: |- vids ON graph, weights ON graph, res ON graph vids, sources ON graph, targets ON graph igraph_edge_betweenness: PARAMS: |- - GRAPH graph, OUT VECTOR res, BOOLEAN directed=True, - OPTIONAL EDGE_WEIGHTS weights - DEPS: weights ON graph + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VECTOR res, EDGE_SELECTOR eids=ALL, + BOOLEAN directed=True, BOOLEAN normalized=False + DEPS: eids ON graph, weights ON graph, res ON graph eids igraph_edge_betweenness_cutoff: PARAMS: |- - GRAPH graph, OUT VECTOR res, BOOLEAN directed=True, - OPTIONAL EDGE_WEIGHTS weights, REAL cutoff=-1 - DEPS: weights ON graph + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VECTOR res, EDGE_SELECTOR eids=ALL, + BOOLEAN directed=True, BOOLEAN normalized=False, REAL cutoff=UNLIMITED + DEPS: eids ON graph, weights ON graph, res ON graph eids igraph_edge_betweenness_subset: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, EDGE_SELECTOR eids=ALL, - BOOLEAN directed=True, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, - OPTIONAL EDGE_WEIGHTS weights + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VECTOR res, + VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, EDGE_SELECTOR eids=ALL, + BOOLEAN directed=True, BOOLEAN normalized=False DEPS: |- - res ON graph eids, eids ON graph, sources ON graph, targets ON graph, weights ON graph + eids ON graph, weights ON graph, res ON graph eids, sources ON graph, targets ON graph igraph_harmonic_centrality: PARAMS: |- @@ -709,15 +720,16 @@ igraph_harmonic_centrality_cutoff: PARAMS: |- GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=OUT, OPTIONAL EDGE_WEIGHTS weights, BOOLEAN normalized=False, - REAL cutoff=-1 + REAL cutoff=UNLIMITED DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_pagerank: PARAMS: |- - GRAPH graph, PAGERANKALGO algo=PRPACK, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY vector, OUT REAL value, - VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, - REAL damping=0.85, OPTIONAL EDGE_WEIGHTS weights, + REAL damping=0.85, BOOLEAN directed=True, + VERTEX_SELECTOR vids=ALL, + PAGERANKALGO algo=PRPACK, OPTIONAL INOUT PAGERANKOPT options DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, @@ -725,11 +737,12 @@ igraph_pagerank: igraph_personalized_pagerank: PARAMS: |- - GRAPH graph, PAGERANKALGO algo=PRPACK, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT VERTEX_QTY vector, OUT REAL value, - VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, - REAL damping=0.85, OPTIONAL VECTOR personalized, - OPTIONAL EDGE_WEIGHTS weights, + OPTIONAL VECTOR reset, + REAL damping=0.85, BOOLEAN directed=True, + VERTEX_SELECTOR vids=ALL, + PAGERANKALGO algo=PRPACK, OPTIONAL INOUT PAGERANKOPT options DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, @@ -737,19 +750,19 @@ igraph_personalized_pagerank: igraph_personalized_pagerank_vs: PARAMS: |- - GRAPH graph, PAGERANKALGO algo=PRPACK, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, PRIMARY OUT VERTEX_QTY vector, OUT REAL value, - VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, - REAL damping=0.85, VERTEX_SELECTOR reset_vids, - OPTIONAL EDGE_WEIGHTS weights, + REAL damping=0.85, BOOLEAN directed=True, + VERTEX_SELECTOR vids=ALL, + PAGERANKALGO algo=PRPACK, OPTIONAL INOUT PAGERANKOPT options DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, options ON algo igraph_rewire: - PARAMS: INOUT GRAPH rewire, INTEGER n, EDGE_TYPE_SW allowed_edge_types=SIMPLE + PARAMS: INOUT GRAPH rewire, INTEGER n, EDGE_TYPE_SW allowed_edge_types=SIMPLE, OPTIONAL OUT REWIRING_STATS stats igraph_induced_subgraph: PARAMS: GRAPH graph, OUT GRAPH res, VERTEX_SELECTOR vids, SUBGRAPH_IMPL impl=AUTO @@ -817,7 +830,8 @@ igraph_maxdegree: DEPS: vids ON graph igraph_density: - PARAMS: GRAPH graph, OUT REAL res, BOOLEAN loops=False + PARAMS: GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT REAL res, BOOLEAN loops=False + DEPS: weights ON graph igraph_mean_degree: PARAMS: GRAPH graph, OUT REAL res, BOOLEAN loops=True @@ -886,8 +900,8 @@ igraph_count_multiple: DEPS: es ON graph igraph_girth: - PARAMS: GRAPH graph, OUT REAL girth, OUT VERTEX_INDICES circle - DEPS: circle ON graph + PARAMS: GRAPH graph, OUT REAL girth, OUT VERTEX_INDICES cycle + DEPS: cycle ON graph igraph_is_perfect: PARAMS: GRAPH graph, OUT BOOLEAN res @@ -1025,13 +1039,18 @@ igraph_centralization_eigenvector_centrality_tmax: igraph_assortativity_nominal: PARAMS: |- - GRAPH graph, INDEX_VECTOR types, OUT REAL res, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + INDEX_VECTOR types, + OUT REAL res, BOOLEAN directed=True, BOOLEAN normalized=True + DEPS: weights ON graph, types ON graph igraph_assortativity: PARAMS: |- - GRAPH graph, VECTOR values, OPTIONAL VECTOR values_in, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + VECTOR values, OPTIONAL VECTOR values_in, OUT REAL res, BOOLEAN directed=True, BOOLEAN normalized=True + DEPS: weights ON graph, values ON graph, values_in ON graph igraph_assortativity_degree: PARAMS: GRAPH graph, OUT REAL res, BOOLEAN directed=True @@ -1040,7 +1059,7 @@ igraph_joint_degree_matrix: PARAMS: |- GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX jdm, - INTEGER max_out_degree=-1, INTEGER max_in_degree=-1 + INTEGER max_out_degree=UNLIMITED, INTEGER max_in_degree=UNLIMITED DEPS: weights ON graph igraph_joint_degree_distribution: @@ -1050,7 +1069,7 @@ igraph_joint_degree_distribution: NEIMODE from_mode=OUT, NEIMODE to_mode=IN, BOOLEAN directed_neighbors=True, BOOLEAN normalized=True, - INTEGER max_from_degree=-1, INTEGER max_to_degree=-1 + INTEGER max_from_degree=UNLIMITED, INTEGER max_to_degree=UNLIMITED DEPS: weights ON graph igraph_joint_type_distribution: @@ -1089,7 +1108,7 @@ igraph_pseudo_diameter: OUT REAL diameter, VERTEX start_vid, OPTIONAL OUT INTEGER from, OPTIONAL OUT INTEGER to, BOOLEAN directed=True, BOOLEAN unconnected=True - DEPS: weights ON graph + DEPS: weights ON graph, start_vid ON graph igraph_diversity: PARAMS: |- @@ -1152,6 +1171,7 @@ igraph_bfs: OUT VECTOR_INT parents, OUT VECTOR_INT pred, OUT VECTOR_INT succ, OUT VECTOR_INT dist, OPTIONAL BFS_FUNC callback, OPTIONAL EXTRA extra + DEPS: root ON graph, roots ON graph, restricted ON graph, order ON graph igraph_bfs_simple: PARAMS: |- @@ -1160,6 +1180,7 @@ igraph_bfs_simple: OUT VERTEX_INDICES order, OUT VECTOR_INT layers, OUT VECTOR_INT parents + DEPS: root ON graph, order ON graph igraph_dfs: PARAMS: |- @@ -1167,6 +1188,7 @@ igraph_dfs: OUT VERTEX_INDICES order, OUT VERTEX_INDICES order_out, OUT VECTOR_INT father, OUT VECTOR_INT dist, OPTIONAL DFS_FUNC in_callback, OPTIONAL DFS_FUNC out_callback, OPTIONAL EXTRA extra + DEPS: root ON graph, order ON graph, order_out ON graph ####################################### # Bipartite graphs @@ -1191,7 +1213,6 @@ igraph_create_bipartite: PARAMS: |- OUT GRAPH graph, IN BIPARTITE_TYPES types, VECTOR_INT edges, BOOLEAN directed=False - DEPS: types ON graph, edges ON graph igraph_biadjacency: PARAMS: |- @@ -1202,7 +1223,7 @@ igraph_biadjacency: igraph_weighted_biadjacency: PARAMS: |- OUT GRAPH graph, - OUT ALL_BIPARTITE_TYPES types, OUT EDGE_WEIGHTS weights, + OUT BIPARTITE_TYPES types, OUT EDGE_WEIGHTS weights, MATRIX biadjmatrix, BOOLEAN directed=False, NEIMODE mode=ALL DEPS: |- @@ -1221,22 +1242,24 @@ igraph_is_bipartite: igraph_bipartite_game_gnp: PARAMS: |- OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, - INTEGER n1, INTEGER n2, REAL p, BOOLEAN directed=False, - NEIMODE mode=ALL + INTEGER n1, INTEGER n2, REAL p, + BOOLEAN directed=False, NEIMODE mode=ALL, + EDGE_TYPE_SW allowed_edge_types=SIMPLE, BOOLEAN edge_labeled=False igraph_bipartite_game_gnm: PARAMS: |- - OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, - INTEGER n1, INTEGER n2, INTEGER m, BOOLEAN directed=False, - NEIMODE mode=ALL, BOOLEAN multiple=False - DEPS: types ON graph + OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, + INTEGER n1, INTEGER n2, INTEGER m, + BOOLEAN directed=False, NEIMODE mode=ALL, + EDGE_TYPE_SW allowed_edge_types=SIMPLE, BOOLEAN edge_labeled=False igraph_bipartite_iea_game: PARAMS: |- - OUT GRAPH graph, OPTIONAL OUT ALL_BIPARTITE_TYPES types, + OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, INTEGER n1, INTEGER n2, INTEGER m, BOOLEAN directed=False, NEIMODE mode=ALL - DEPS: types ON graph + DEPS: |- + types ON graph ####################################### # Spectral properties @@ -1269,7 +1292,7 @@ igraph_is_connected: igraph_decompose: PARAMS: |- GRAPH graph, OUT GRAPH_LIST components, CONNECTEDNESS mode=WEAK, - INTEGER maxcompno=-1, INTEGER minelements=1 + INTEGER maxcompno=UNLIMITED, INTEGER minelements=1 igraph_articulation_points: PARAMS: GRAPH graph, OUT VERTEX_INDICES res @@ -1294,7 +1317,7 @@ igraph_is_biconnected: PARAMS: GRAPH graph, OUT BOOLEAN res igraph_count_reachable: - PARAMS: GRAPH graph, OUT VECTOR_INT counts, NEIMODE mode + PARAMS: GRAPH graph, OUT VECTOR_INT counts, NEIMODE mode=OUT ####################################### # Percolation @@ -1323,8 +1346,9 @@ igraph_is_clique: igraph_cliques: PARAMS: |- - GRAPH graph, OUT VERTEX_INDICES_LIST res, INTEGER min_size=0, - INTEGER max_size=0 + GRAPH graph, OUT VERTEX_INDICES_LIST res, + INTEGER min_size=UNLIMITED, INTEGER max_size=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: res ON graph igraph_cliques_callback: @@ -1341,19 +1365,25 @@ igraph_largest_cliques: DEPS: res ON graph igraph_maximal_cliques: - PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST res, INTEGER min_size=0, INTEGER max_size=0 + PARAMS: |- + GRAPH graph, OUT VERTEX_INDICES_LIST res, + INTEGER min_size=UNLIMITED, INTEGER max_size=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: res ON graph igraph_maximal_cliques_subset: PARAMS: |- GRAPH graph, VERTEX_INDICES subset, PRIMARY OUT VERTEX_INDICES_LIST res, - OUT INTEGER no, OPTIONAL OUTFILE outfile, INTEGER min_size=0, INTEGER max_size=0 + OUT INTEGER no, OPTIONAL OUTFILE outfile, + INTEGER min_size=UNLIMITED, INTEGER max_size=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: subset ON graph, res ON graph igraph_maximal_cliques_callback: PARAMS: |- - GRAPH graph, CLIQUE_FUNC cliquehandler_fn, OPTIONAL EXTRA arg, - INTEGER min_size=0, INTEGER max_size=0 + GRAPH graph, + INTEGER min_size=0, INTEGER max_size=0, + CLIQUE_FUNC cliquehandler_fn, OPTIONAL EXTRA arg igraph_maximal_cliques_count: PARAMS: |- @@ -1361,7 +1391,9 @@ igraph_maximal_cliques_count: igraph_maximal_cliques_file: PARAMS: |- - GRAPH graph, OUTFILE res, INTEGER min_size=0, INTEGER max_size=0 + GRAPH graph, OUTFILE res, + INTEGER min_size=UNLIMITED, INTEGER max_size=UNLIMITED, + INTEGER max_results=UNLIMITED igraph_maximal_cliques_hist: PARAMS: |- @@ -1373,7 +1405,9 @@ igraph_clique_number: igraph_weighted_cliques: PARAMS: |- GRAPH graph, OPTIONAL VERTEX_WEIGHTS vertex_weights, OUT VERTEX_INDICES_LIST res, - REAL min_weight=0, REAL max_weight=0, BOOLEAN maximal=False + BOOLEAN maximal=False, + REAL min_weight=UNLIMITED, REAL max_weight=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: vertex_weights ON graph, res ON graph igraph_largest_weighted_cliques: @@ -1391,8 +1425,9 @@ igraph_is_independent_vertex_set: igraph_independent_vertex_sets: PARAMS: |- - GRAPH graph, OUT VERTEX_INDICES_LIST res, INTEGER min_size=0, - INTEGER max_size=0 + GRAPH graph, OUT VERTEX_INDICES_LIST res, + INTEGER min_size=UNLIMITED, INTEGER max_size=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: res ON graph igraph_largest_independent_vertex_sets: @@ -1400,7 +1435,10 @@ igraph_largest_independent_vertex_sets: DEPS: res ON graph igraph_maximal_independent_vertex_sets: - PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST res + PARAMS: |- + GRAPH graph, OUT VERTEX_INDICES_LIST res, + INTEGER min_size=UNLIMITED, INTEGER max_size=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: res ON graph igraph_independence_number: @@ -1460,11 +1498,13 @@ igraph_layout_reingold_tilford: PARAMS: |- GRAPH graph, OUT MATRIX res, NEIMODE mode=OUT, OPTIONAL VERTEX_INDICES roots, OPTIONAL VECTOR_INT rootlevel + DEPS: roots ON graph igraph_layout_reingold_tilford_circular: PARAMS: |- GRAPH graph, OUT MATRIX res, NEIMODE mode=OUT, OPTIONAL VERTEX_INDICES roots, OPTIONAL VECTOR_INT rootlevel + DEPS: roots ON graph igraph_roots_for_tree_layout: PARAMS: |- @@ -1524,8 +1564,7 @@ igraph_layout_merge_dla: igraph_layout_sugiyama: PARAMS: |- - GRAPH graph, OUT MATRIX res, OPTIONAL OUT GRAPH extd_graph, - OPTIONAL OUT INDEX_VECTOR extd_to_orig_eids, + GRAPH graph, OUT MATRIX res, OPTIONAL OUT MATRIX_LIST routing, OPTIONAL INDEX_VECTOR layers, REAL hgap=1, REAL vgap=1, INTEGER maxiter=100, OPTIONAL EDGE_WEIGHTS weights @@ -1592,9 +1631,9 @@ igraph_bibcoupling: igraph_similarity_dice: PARAMS: |- - GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR vit_from=ALL, VERTEX_SELECTOR vit_to=ALL, NEIMODE mode=ALL, + GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, VERTEX_SELECTOR to=ALL, NEIMODE mode=ALL, BOOLEAN loops=False - DEPS: vit_from ON graph, vit_to ON graph, res ON vit_from, res ON vit_to + DEPS: from ON graph, to ON graph, res ON from, res ON to igraph_similarity_dice_es: PARAMS: |- @@ -1614,9 +1653,9 @@ igraph_similarity_inverse_log_weighted: igraph_similarity_jaccard: PARAMS: |- - GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR vit_from=ALL, VERTEX_SELECTOR vit_to=ALL, NEIMODE mode=ALL, + GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, VERTEX_SELECTOR to=ALL, NEIMODE mode=ALL, BOOLEAN loops=False - DEPS: vit_from ON graph, vit_to ON graph, res ON vit_from, res ON vit_to + DEPS: from ON graph, to ON graph, res ON from, res ON to igraph_similarity_jaccard_es: PARAMS: |- @@ -1728,6 +1767,7 @@ igraph_community_leading_eigenvector: OPTIONAL OUT VECTOR_INT history, OPTIONAL LEVC_FUNC callback, OPTIONAL EXTRA callback_extra + DEPS: weights ON graph igraph_community_fluid_communities: PARAMS: |- @@ -1737,7 +1777,7 @@ igraph_community_label_propagation: PARAMS: |- GRAPH graph, OUT VECTOR_INT membership, NEIMODE mode=ALL, OPTIONAL EDGE_WEIGHTS weights, OPTIONAL INDEX_VECTOR initial, - OPTIONAL VECTOR_BOOL fixed, IN LPA_VARIANT lpa_variant + OPTIONAL VECTOR_BOOL fixed, LPA_VARIANT lpa_variant=DOMINANCE DEPS: weights ON graph igraph_community_multilevel: @@ -1758,11 +1798,20 @@ igraph_community_leiden: GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OPTIONAL VERTEX_WEIGHTS vertex_out_weights, OPTIONAL VERTEX_WEIGHTS vertex_in_weights, - REAL resolution, REAL beta=0.01, BOOLEAN start, INTEGER n_iterations=2, + REAL resolution, REAL beta=0.01, BOOLEAN start=False, INTEGER n_iterations=2, OPTIONAL INOUT VECTOR_INT membership, OUT INTEGER nb_clusters, OUT REAL quality DEPS: weights ON graph, vertex_out_weights ON graph, vertex_in_weights ON graph +igraph_community_leiden_simple: + PARAMS: |- + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + LEIDEN_OBJECTIVE objective, + REAL resolution, REAL beta=0.01, BOOLEAN start=False, INTEGER n_iterations=2, + OPTIONAL INOUT VECTOR_INT membership, + OUT INTEGER nb_clusters, OUT REAL quality + DEPS: weights ON graph + igraph_split_join_distance: PARAMS: |- VECTOR_INT comm1, VECTOR_INT comm2, OUT INTEGER distance12, @@ -1772,6 +1821,7 @@ igraph_community_infomap: PARAMS: |- GRAPH graph, OPTIONAL EDGE_WEIGHTS edge_weights, OPTIONAL VERTEX_WEIGHTS vertex_weights, INTEGER nb_trials=10, + BOOLEAN is_regularized=False, REAL regularization_strength=1, OPTIONAL OUT VECTOR_INT membership, OPTIONAL OUT REAL codelength DEPS: edge_weights ON graph, vertex_weights ON graph @@ -2089,7 +2139,7 @@ igraph_compose: igraph_induced_subgraph_map: PARAMS: |- - GRAPH graph, OUT GRAPH res, VERTEX_SELECTOR vids, SUBGRAPH_IMPL impl, + GRAPH graph, OUT GRAPH res, VERTEX_SELECTOR vids, SUBGRAPH_IMPL impl=AUTO, OPTIONAL OUT INDEX_VECTOR map, OPTIONAL OUT INDEX_VECTOR invmap DEPS: vids ON graph @@ -2286,7 +2336,7 @@ igraph_count_automorphisms: DEPS: colors ON graph igraph_isoclass_subgraph: - PARAMS: GRAPH graph, VECTOR_INT vids, OUT INTEGER isoclass + PARAMS: GRAPH graph, VERTEX_SELECTOR vids, OUT INTEGER isoclass DEPS: vids ON graph igraph_isoclass_create: @@ -2479,7 +2529,7 @@ igraph_maximum_bipartite_matching: OPTIONAL OUT REAL matching_weight, OUT INDEX_VECTOR matching, OPTIONAL EDGE_WEIGHTS weights, REAL eps=.Machine$double.eps - DEPS: types ON graph matching, weights ON graph + DEPS: types ON graph, weights ON graph ####################################### # Embedding @@ -2543,7 +2593,7 @@ igraph_running_mean: igraph_random_sample: PARAMS: OUT VECTOR_INT res, INTEGER l, INTEGER h, INTEGER length -igraph_convex_hull: +igraph_convex_hull_2d: PARAMS: MATRIX data, OUT INDEX_VECTOR resverts, OUT MATRIX rescoords igraph_dim_select: @@ -2586,13 +2636,14 @@ igraph_simple_cycles: PARAMS: |- GRAPH graph, OPTIONAL OUT VERTEX_INDICES_LIST vertices, OPTIONAL OUT EDGE_INDICES_LIST edges, - NEIMODE mode=OUT, INTEGER min_cycle_length=-1, INTEGER max_cycle_length=-1 + NEIMODE mode=OUT, INTEGER min_cycle_length=UNLIMITED, INTEGER max_cycle_length=UNLIMITED, + INTEGER max_results=UNLIMITED DEPS: vertices ON graph, edges ON graph igraph_simple_cycles_callback: PARAMS: |- GRAPH graph, - NEIMODE mode=OUT, INTEGER min_cycle_length=-1, INTEGER max_cycle_length=-1, + NEIMODE mode=OUT, INTEGER min_cycle_length=UNLIMITED, INTEGER max_cycle_length=UNLIMITED, CYCLE_FUNC cycle_handler, OPTIONAL EXTRA arg ####################################### @@ -2616,15 +2667,18 @@ igraph_eulerian_cycle: igraph_fundamental_cycles: PARAMS: |- - GRAPH graph, OUT EDGE_INDICES_LIST basis, OPTIONAL VERTEX start=-1, - INTEGER bfs_cutoff=-1, OPTIONAL EDGE_WEIGHTS weights + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + OUT EDGE_INDICES_LIST basis, + OPTIONAL VERTEX start, + REAL bfs_cutoff=UNLIMITED DEPS: weights ON graph, basis ON graph, start ON graph igraph_minimum_cycle_basis: PARAMS: |- - GRAPH graph, OUT EDGE_INDICES_LIST basis, INTEGER bfs_cutoff=-1, - BOOLEAN complete=True, BOOLEAN use_cycle_order=True, - OPTIONAL EDGE_WEIGHTS weights + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + OUT EDGE_INDICES_LIST basis, + REAL bfs_cutoff=UNLIMITED, + BOOLEAN complete=True, BOOLEAN use_cycle_order=True DEPS: weights ON graph, basis ON graph ####################################### @@ -2656,7 +2710,7 @@ igraph_minimum_spanning_tree: DEPS: res ON graph, weights ON graph igraph_random_spanning_tree: - PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid=-1 + PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid DEPS: res ON graph, vid ON graph igraph_tree_game: @@ -2665,9 +2719,33 @@ igraph_tree_game: ####################################### # Spatial ####################################### + igraph_nearest_neighbor_graph: PARAMS: OUT GRAPH graph, MATRIX points, METRIC metric, INTEGER neighbors, REAL cutoff, BOOLEAN directed +igraph_delaunay_graph: + PARAMS: OUT GRAPH graph, MATRIX points + +igraph_gabriel_graph: + PARAMS: OUT GRAPH graph, MATRIX points + +igraph_relative_neighborhood_graph: + PARAMS: OUT GRAPH graph, MATRIX points + +igraph_lune_beta_skeleton: + PARAMS: OUT GRAPH graph, MATRIX points, REAL beta=1 + +igraph_circle_beta_skeleton: + PARAMS: OUT GRAPH graph, MATRIX points, REAL beta=1 + +igraph_beta_weighted_gabriel_graph: + PARAMS: OUT GRAPH graph, OUT EDGE_WEIGHTS weights, MATRIX points, REAL max_beta=UNLIMITED + DEPS: weights ON graph + +igraph_spatial_edge_lengths: + PARAMS: GRAPH graph, OUT EDGE_LENGTHS lengths, MATRIX points, METRIC METRIC + DEPS: lengths ON graph + ####################################### # Coloring ####################################### @@ -2727,7 +2805,6 @@ igraph_vertex_path_from_edge_path: PARAMS: |- GRAPH graph, OPTIONAL VERTEX start, EDGE_INDICES edge_path, OUT VERTEX_INDICES vertex_path, NEIMODE mode=OUT - DEPS: start ON graph, edge_path ON graph, vertex_path ON graph ####################################### # Meta info diff --git a/src/vendor/cigraph/interfaces/types.yaml b/src/vendor/cigraph/interfaces/types.yaml index 3d4819fe2dc..eda9572ec81 100644 --- a/src/vendor/cigraph/interfaces/types.yaml +++ b/src/vendor/cigraph/interfaces/types.yaml @@ -12,7 +12,7 @@ INTEGER: # An ordinary igraph integer - CTYPE: igraph_integer_t + CTYPE: igraph_int_t REAL: # An ordinary igraph floating-point number @@ -133,7 +133,7 @@ SPARSEMAT: EDGE: # A single edge index - CTYPE: igraph_integer_t + CTYPE: igraph_int_t EDGE_INDICES: # An integer vector containing edge indices. @@ -146,7 +146,7 @@ EDGE_SELECTOR: VERTEX: # A single vertex index - CTYPE: igraph_integer_t + CTYPE: igraph_int_t VERTEX_INDICES: # An integer vector containing vertex indices. @@ -169,12 +169,7 @@ VERTEX_SELECTOR: BIPARTITE_TYPES: # A vector containing Booleans that define the two partitions of a - # bipartite graph, for a set of vertices - CTYPE: igraph_vector_bool_t - FLAGS: BY_REF - -ALL_BIPARTITE_TYPES: - # Same as BIPARTITE_TYPES, for all vertices of a graph + # bipartite graph CTYPE: igraph_vector_bool_t FLAGS: BY_REF @@ -367,6 +362,12 @@ LAYOUT_GRID: CTYPE: igraph_layout_grid_t FLAGS: ENUM +LEIDEN_OBJECTIVE: + # The objective function to maximize with the Leiden community detection + # method. + CTYPE: igraph_leiden_objective_t + FLAGS: ENUM + LOOPS: # Enum that describes how loop edges should be handled in undirected graphs # in functions that support it. Possible options are: no loops, loops @@ -639,6 +640,11 @@ PLFIT: CTYPE: igraph_plfit_result_t FLAGS: BY_REF +REWIRING_STATS: + # Structure storing statistics about degree-preserving edge rewiring + CTYPE: igraph_rewiring_stats_t + FLAGS: BY_REF + VERTEX_ATTRIBUTE_COMBINATION: # Structure specifying how the attributes of vertices should be combined # during graph operations that may merge multiple vertices into a single one diff --git a/src/vendor/cigraph/src/CMakeLists.txt b/src/vendor/cigraph/src/CMakeLists.txt index f2032db3e8f..c1b345435a6 100644 --- a/src/vendor/cigraph/src/CMakeLists.txt +++ b/src/vendor/cigraph/src/CMakeLists.txt @@ -183,6 +183,9 @@ add_library( connectivity/separators.c connectivity/reachability.c + cycles/cycle_bases.c + cycles/feedback_sets.c + cycles/order_cycle.cpp cycles/simple_cycles.c flow/flow.c @@ -296,21 +299,22 @@ add_library( misc/cocitation.c misc/coloring.c misc/conversion.c - misc/cycle_bases.c misc/degree_sequence.cpp misc/embedding.c - misc/feedback_arc_set.c misc/graphicality.c misc/matching.c misc/mixing.c misc/motifs.c - misc/order_cycle.cpp misc/other.c misc/power_law_fit.c misc/scan.c misc/sir.c misc/spanning_trees.c + spatial/beta_skeleton.cpp + spatial/delaunay.c + spatial/convex_hull.c + spatial/edge_lengths.c spatial/nearest_neighbor.cpp internal/glpk_support.c @@ -337,8 +341,8 @@ add_library( add_dependencies(igraph parsersources) # Set soname for the library -set_target_properties(igraph PROPERTIES VERSION "3.1.10") -set_target_properties(igraph PROPERTIES SOVERSION 3) +set_target_properties(igraph PROPERTIES VERSION "4.0.0") +set_target_properties(igraph PROPERTIES SOVERSION 4) # Add extra compiler definitions if needed target_compile_definitions( @@ -424,7 +428,7 @@ endif() target_link_libraries( igraph PRIVATE - bliss cliquer cxsparse_vendored pcg prpack + bliss cliquer cxsparse_vendored pcg prpack qhull_vendored ) if (NOT BUILD_SHARED_LIBS) @@ -473,7 +477,7 @@ write_basic_package_version_file( # Define how to install the library install( - TARGETS igraph bliss cliquer cxsparse_vendored pcg prpack + TARGETS igraph bliss cliquer cxsparse_vendored pcg prpack qhull_vendored EXPORT igraph_targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/vendor/cigraph/src/centrality/betweenness.c b/src/vendor/cigraph/src/centrality/betweenness.c index 4971da8c193..03f7948161b 100644 --- a/src/vendor/cigraph/src/centrality/betweenness.c +++ b/src/vendor/cigraph/src/centrality/betweenness.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -59,8 +59,8 @@ * \param adjlist the adjacency list of the graph * \param cutoff cutoff length of shortest paths */ -static igraph_error_t igraph_i_sspf( - igraph_integer_t source, +static igraph_error_t sspf( + igraph_int_t source, igraph_vector_t *dist, igraph_real_t *nrgeo, igraph_stack_int_t *stack, @@ -71,7 +71,7 @@ static igraph_error_t igraph_i_sspf( igraph_dqueue_int_t queue; const igraph_vector_int_t *neis; igraph_vector_int_t *v; - igraph_integer_t nlen; + igraph_int_t nlen; IGRAPH_DQUEUE_INT_INIT_FINALLY(&queue, 100); @@ -80,7 +80,7 @@ static igraph_error_t igraph_i_sspf( nrgeo[source] = 1; while (!igraph_dqueue_int_empty(&queue)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&queue); + igraph_int_t actnode = igraph_dqueue_int_pop(&queue); /* Ignore vertices that are more distant than the cutoff */ if (cutoff >= 0 && VECTOR(*dist)[actnode] > cutoff + 1) { @@ -97,8 +97,8 @@ static igraph_error_t igraph_i_sspf( /* Examine the neighbors of this node */ neis = igraph_adjlist_get(adjlist, actnode); nlen = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nlen; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < nlen; j++) { + igraph_int_t neighbor = VECTOR(*neis)[j]; if (VECTOR(*dist)[neighbor] == 0) { /* We have found 'neighbor' for the first time */ @@ -139,9 +139,9 @@ static igraph_error_t igraph_i_sspf( * \param inclist the incidence list of the graph * \param cutoff cutoff length of shortest paths */ -static igraph_error_t igraph_i_sspf_edge( +static igraph_error_t sspf_edge( const igraph_t *graph, - igraph_integer_t source, + igraph_int_t source, igraph_vector_t *dist, igraph_real_t *nrgeo, igraph_stack_int_t *stack, @@ -152,7 +152,7 @@ static igraph_error_t igraph_i_sspf_edge( igraph_dqueue_int_t queue; const igraph_vector_int_t *neis; igraph_vector_int_t *v; - igraph_integer_t nlen; + igraph_int_t nlen; IGRAPH_DQUEUE_INT_INIT_FINALLY(&queue, 100); @@ -161,7 +161,7 @@ static igraph_error_t igraph_i_sspf_edge( nrgeo[source] = 1; while (!igraph_dqueue_int_empty(&queue)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&queue); + igraph_int_t actnode = igraph_dqueue_int_pop(&queue); /* Ignore vertices that are more distant than the cutoff */ if (cutoff >= 0 && VECTOR(*dist)[actnode] > cutoff + 1) { @@ -178,9 +178,9 @@ static igraph_error_t igraph_i_sspf_edge( /* Examine the neighbors of this node */ neis = igraph_inclist_get(inclist, actnode); nlen = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, edge, actnode); + for (igraph_int_t j = 0; j < nlen; j++) { + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, edge, actnode); if (VECTOR(*dist)[neighbor] == 0) { /* We have found 'neighbor' for the first time */ @@ -222,9 +222,9 @@ static igraph_error_t igraph_i_sspf_edge( * \param inclist the incidence list of the graph * \param cutoff cutoff length of shortest paths */ -static igraph_error_t igraph_i_sspf_weighted( +static igraph_error_t sspf_weighted( const igraph_t *graph, - igraph_integer_t source, + igraph_int_t source, igraph_vector_t *dist, igraph_real_t *nrgeo, const igraph_vector_t *weights, @@ -239,19 +239,19 @@ static igraph_error_t igraph_i_sspf_weighted( igraph_2wheap_t queue; const igraph_vector_int_t *neis; igraph_vector_int_t *v; - igraph_integer_t nlen; + igraph_int_t nlen; /* TODO: this is an O|V| step here. We could save some time by pre-allocating * the two-way heap in the caller and re-using it here */ IGRAPH_CHECK(igraph_2wheap_init(&queue, igraph_vcount(graph))); IGRAPH_FINALLY(igraph_2wheap_destroy, &queue); - igraph_2wheap_push_with_index(&queue, source, -1.0); + igraph_2wheap_push_with_index(&queue, source, -1.0); /* reserved */ VECTOR(*dist)[source] = 1.0; nrgeo[source] = 1; while (!igraph_2wheap_empty(&queue)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&queue); + igraph_int_t minnei = igraph_2wheap_max_index(&queue); igraph_real_t mindist = -igraph_2wheap_delete_max(&queue); /* Ignore vertices that are more distant than the cutoff */ @@ -269,9 +269,9 @@ static igraph_error_t igraph_i_sspf_weighted( /* Now check all neighbors of 'minnei' for a shorter path */ neis = igraph_inclist_get(inclist, minnei); nlen = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t to = IGRAPH_OTHER(graph, edge, minnei); + for (igraph_int_t j = 0; j < nlen; j++) { + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t to = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_real_t curdist = VECTOR(*dist)[to]; @@ -331,9 +331,9 @@ static igraph_error_t igraph_i_sspf_weighted( * \param inclist the incidence list of the graph * \param cutoff cutoff length of shortest paths */ -static igraph_error_t igraph_i_sspf_weighted_edge( +static igraph_error_t sspf_weighted_edge( const igraph_t *graph, - igraph_integer_t source, + igraph_int_t source, igraph_vector_t *dist, igraph_real_t *nrgeo, const igraph_vector_t *weights, @@ -348,19 +348,19 @@ static igraph_error_t igraph_i_sspf_weighted_edge( igraph_2wheap_t queue; const igraph_vector_int_t *neis; igraph_vector_int_t *v; - igraph_integer_t nlen; + igraph_int_t nlen; /* TODO: this is an O|V| step here. We could save some time by pre-allocating * the two-way heap in the caller and re-using it here */ IGRAPH_CHECK(igraph_2wheap_init(&queue, igraph_vcount(graph))); IGRAPH_FINALLY(igraph_2wheap_destroy, &queue); - igraph_2wheap_push_with_index(&queue, source, -1.0); + igraph_2wheap_push_with_index(&queue, source, -1.0); /* reserved */ VECTOR(*dist)[source] = 1.0; nrgeo[source] = 1; while (!igraph_2wheap_empty(&queue)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&queue); + igraph_int_t minnei = igraph_2wheap_max_index(&queue); igraph_real_t mindist = -igraph_2wheap_delete_max(&queue); /* Ignore vertices that are more distant than the cutoff */ @@ -378,9 +378,9 @@ static igraph_error_t igraph_i_sspf_weighted_edge( /* Now check all neighbors of 'minnei' for a shorter path */ neis = igraph_inclist_get(inclist, minnei); nlen = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t to = IGRAPH_OTHER(graph, edge, minnei); + for (igraph_int_t j = 0; j < nlen; j++) { + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t to = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_real_t curdist = VECTOR(*dist)[to]; @@ -422,25 +422,26 @@ static igraph_error_t igraph_i_sspf_weighted_edge( return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_betweenness_check_weights( - const igraph_vector_t* weights, igraph_integer_t no_of_edges +static igraph_error_t betweenness_check_weights( + const igraph_vector_t *weights, igraph_int_t no_of_edges ) { igraph_real_t minweight; if (weights) { if (igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERROR("Weight vector length must match the number of edges.", IGRAPH_EINVAL); + IGRAPH_ERROR("Edge weight vector length must match the number of edges.", IGRAPH_EINVAL); } if (no_of_edges > 0) { minweight = igraph_vector_min(weights); if (minweight <= 0) { - IGRAPH_ERROR("Weight vector must be positive.", IGRAPH_EINVAL); + IGRAPH_ERROR("Edge weights must be positive for betweenness.", IGRAPH_EINVAL); } else if (isnan(minweight)) { - IGRAPH_ERROR("Weight vector must not contain NaN values.", IGRAPH_EINVAL); + IGRAPH_ERROR("Edge weights must not contain NaN values.", IGRAPH_EINVAL); } else if (minweight <= IGRAPH_SHORTEST_PATH_EPSILON) { - IGRAPH_WARNING( - "Some weights are smaller than epsilon, calculations may " - "suffer from numerical precision issues." + IGRAPH_WARNINGF( + "Some weights are smaller than the path length comparison tolerance (%g), " + "betweenness calculations may suffer from numerical precision issues.", + IGRAPH_SHORTEST_PATH_EPSILON ); } } @@ -456,10 +457,9 @@ static igraph_error_t igraph_i_betweenness_check_weights( * \function igraph_betweenness * \brief Betweenness centrality of some vertices. * - * The betweenness centrality of a vertex is the number of geodesics - * going through it. If there are more than one geodesic between two - * vertices, the value of these geodesics are weighted by one over the - * number of geodesics. + * The betweenness centrality of a vertex \c v is the number of shortest paths + * passing through it. If there is more than one shortest path between two + * vertices, the fraction of these passing through \c v is counted. * * * Reference: @@ -470,15 +470,20 @@ static igraph_error_t igraph_i_betweenness_check_weights( * https://doi.org/10.1080/0022250X.2001.9990249 * * \param graph The graph object. + * \param weights An optional vector containing edge weights for + * calculating weighted betweenness. No edge weight may be NaN. + * Supply a null pointer here for unweighted betweenness. * \param res The result of the computation, a vector containing the * betweenness scores for the specified vertices. - * \param vids The vertices of which the betweenness centrality scores - * will be calculated. + * \param vids The vertices for which the range-limited betweenness centrality + * scores will be returned. This paramerer is for convenience only and + * does not affect performance. Internally, the betewenness of all + * vertices is calculated. * \param directed If true directed paths will be considered * for directed graphs. It is ignored for undirected graphs. - * \param weights An optional vector containing edge weights for - * calculating weighted betweenness. No edge weight may be NaN. - * Supply a null pointer here for unweighted betweenness. + * \param normalized Whether to normalize betweenness scores by the number of + * vertex pairs. In directed graphs, the number of ordered vertex pairs, + * in undirected graphs the number of unordered vertex pairs is used. * \return Error code: * \c IGRAPH_ENOMEM, not enough memory for temporary data. * \c IGRAPH_EINVVID, invalid vertex ID passed in \p vids. @@ -490,15 +495,17 @@ static igraph_error_t igraph_i_betweenness_check_weights( * Note that the time complexity is independent of the number of * vertices for which the score is calculated. * - * \sa Other centrality types: \ref igraph_degree(), \ref igraph_closeness(). - * See \ref igraph_edge_betweenness() for calculating the betweenness score - * of the edges in a graph. See \ref igraph_betweenness_cutoff() to - * calculate the range-limited betweenness of the vertices in a graph. + * \sa \ref igraph_edge_betweenness() for calculating the betweenness score + * of the edges in a graph; \ref igraph_betweenness_cutoff() to + * calculate the range-limited betweenness of the vertices in a graph; + * \ref igraph_betweenness_subset() to consider shortest paths only between + * two vertex subsets for calculating betweenness. */ -igraph_error_t igraph_betweenness(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_bool_t directed, - const igraph_vector_t* weights) { - return igraph_betweenness_cutoff(graph, res, vids, directed, weights, -1); +igraph_error_t igraph_betweenness( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, igraph_vs_t vids, + igraph_bool_t directed, igraph_bool_t normalized) { + return igraph_betweenness_cutoff(graph, weights, res, vids, directed, normalized, -1); } /** @@ -511,18 +518,23 @@ igraph_error_t igraph_betweenness(const igraph_t *graph, igraph_vector_t *res, * then the given cutoff value. * * \param graph The graph object. + * \param weights An optional vector containing edge weights for + * calculating weighted betweenness. No edge weight may be NaN. + * Supply a null pointer here for unweighted betweenness. * \param res The result of the computation, a vector containing the * range-limited betweenness scores for the specified vertices. * \param vids The vertices for which the range-limited betweenness centrality - * scores will be computed. + * scores will be returned. This paramerer is for convenience only and + * does not affect performance. Internally, the betewenness of all + * vertices is calculated. * \param directed If true directed paths will be considered * for directed graphs. It is ignored for undirected graphs. - * \param weights An optional vector containing edge weights for - * calculating weighted betweenness. No edge weight may be NaN. - * Supply a null pointer here for unweighted betweenness. + * \param normalized Whether to normalize betweenness scores by the number of + * vertex pairs. In directed graphs, the number of ordered vertex pairs, + * in undirected graphs the number of unordered vertex pairs is used. * \param cutoff The maximal length of paths that will be considered. - * If negative, the exact betweenness will be calculated, and - * there will be no upper limit on path lengths. + * If negative or \ref IGRAPH_UNLIMITED, 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. @@ -538,17 +550,20 @@ igraph_error_t igraph_betweenness(const igraph_t *graph, igraph_vector_t *res, * \ref igraph_edge_betweenness_cutoff() to calculate the range-limited * edge betweenness. */ -igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_bool_t directed, - const igraph_vector_t *weights, igraph_real_t cutoff) { +igraph_error_t igraph_betweenness_cutoff( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_vs_t vids, + igraph_bool_t directed, igraph_bool_t normalized, + igraph_real_t cutoff) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_adjlist_t adjlist, parents; igraph_inclist_t inclist; - igraph_integer_t source, j, neighbor; + igraph_int_t source, j, neighbor; igraph_stack_int_t S; - igraph_neimode_t mode = directed ? IGRAPH_OUT : IGRAPH_ALL; + igraph_neimode_t mode; igraph_vector_t dist; /* Note: nrgeo holds the number of shortest paths, which may be very large in some cases, * e.g. in a grid graph. If using an integer type, this results in overflow. @@ -562,8 +577,14 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t igraph_real_t *tmpscore; igraph_vector_t v_tmpres, *tmpres = &v_tmpres; igraph_vit_t vit; + igraph_real_t normalization_factor; - IGRAPH_CHECK(igraph_i_betweenness_check_weights(weights, no_of_edges)); + if (!igraph_is_directed(graph)) { + directed = false; + } + mode = directed ? IGRAPH_OUT : IGRAPH_ALL; + + IGRAPH_CHECK(betweenness_check_weights(weights, no_of_edges)); if (weights) { IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, mode, IGRAPH_NO_LOOPS)); @@ -615,17 +636,17 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t /* Conduct a single-source shortest path search from the source node */ if (weights) { - IGRAPH_CHECK(igraph_i_sspf_weighted(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, cutoff)); + IGRAPH_CHECK(sspf_weighted(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, cutoff)); } else { - IGRAPH_CHECK(igraph_i_sspf(source, &dist, nrgeo, &S, &parents, &adjlist, cutoff)); + IGRAPH_CHECK(sspf(source, &dist, nrgeo, &S, &parents, &adjlist, cutoff)); } /* Aggregate betweenness scores for the nodes we have reached in this * traversal */ while (!igraph_stack_int_empty(&S)) { - igraph_integer_t actnode = igraph_stack_int_pop(&S); + igraph_int_t actnode = igraph_stack_int_pop(&S); igraph_vector_int_t *neis = igraph_adjlist_get(&parents, actnode); - igraph_integer_t nneis = igraph_vector_int_size(neis); + igraph_int_t nneis = igraph_vector_int_size(neis); igraph_real_t coeff = (1 + tmpscore[actnode]) / nrgeo[actnode]; for (j = 0; j < nneis; j++) { @@ -656,7 +677,7 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t for (j = 0, IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), j++) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); + igraph_int_t node = IGRAPH_VIT_GET(vit); VECTOR(*res)[j] = VECTOR(*tmpres)[node]; } @@ -665,10 +686,16 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t IGRAPH_FINALLY_CLEAN(2); } - if (!directed || !igraph_is_directed(graph)) { - igraph_vector_scale(res, 0.5); + /* The betweenness calculation is always done for all _ordered_ vertex pairs. + * We only need to correct for this in undirected graphs when normalized=false. */ + if (normalized) { + normalization_factor = 1.0 / (no_of_nodes * (no_of_nodes - 1.0)); + } else { + normalization_factor = directed ? 1.0 : 0.5; } + igraph_vector_scale(res, normalization_factor); + IGRAPH_PROGRESS("Betweenness centrality: ", 100.0, 0); IGRAPH_FREE(nrgeo); @@ -694,10 +721,9 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t * \function igraph_edge_betweenness * \brief Betweenness centrality of the edges. * - * The betweenness centrality of an edge is the number of geodesics - * going through it. If there are more than one geodesics between two - * vertices, the value of these geodesics are weighted by one over the - * number of geodesics. + * The betweenness centrality of an edge \c e is the number of shortest paths + * passing through it. If there is more than one shortest path between two + * vertices, the fraction of these passing through \c e is counted. * * * Reference: @@ -708,13 +734,20 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t * https://doi.org/10.1080/0022250X.2001.9990249 * * \param graph The graph object. - * \param result The result of the computation, vector containing the - * betweenness scores for the edges. - * \param directed If true directed paths will be considered - * for directed graphs. It is ignored for undirected graphs. * \param weights An optional weight vector for weighted edge * betweenness. No edge weight may be NaN. Supply a null * pointer here for the unweighted version. + * \param res The result of the computation, vector containing the + * betweenness scores for the edges. + * \param eids The edges for which the betweenness centrality will be returned. + * This parameter is for convenience only, and does not affect + * performance. Internally, the betweenness is be calculated for all + * edges. + * \param directed If true directed paths will be considered + * for directed graphs. It is ignored for undirected graphs. + * \param normalized Whether to normalize betweenness scores by the number of + * vertex pairs. In directed graphs, the number of ordered vertex pairs, + * in undirected graphs the number of unordered vertex pairs is used. * \return Error code: * \c IGRAPH_ENOMEM, not enough memory for * temporary data. @@ -724,16 +757,21 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t * |E| are the number of vertices and * edges in the graph. * - * \sa Other centrality types: \ref igraph_degree(), \ref igraph_closeness(). - * See \ref igraph_edge_betweenness() for calculating the betweenness score - * of the edges in a graph. See \ref igraph_edge_betweenness_cutoff() to - * compute the range-limited betweenness score of the edges in a graph. + * \sa \ref igraph_betweenness() for calculating the betweenness score of the + * vertices in a graph; \ref igraph_edge_betweenness_cutoff() to compute the + * range-limited betweenness score of the edges in a graph; + * \ref igraph_edge_betweenness_subset() to consider shortest paths only between + * two vertex subsets for calculating betweenness. */ -igraph_error_t igraph_edge_betweenness(const igraph_t *graph, igraph_vector_t *result, - igraph_bool_t directed, - const igraph_vector_t *weights) { - return igraph_edge_betweenness_cutoff(graph, result, directed, - weights, -1); +igraph_error_t igraph_edge_betweenness( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, igraph_es_t eids, + igraph_bool_t directed, igraph_bool_t normalized) { + + return igraph_edge_betweenness_cutoff( + graph, weights, + res, eids, + directed, normalized, -1); } /** @@ -746,16 +784,23 @@ igraph_error_t igraph_edge_betweenness(const igraph_t *graph, igraph_vector_t *r * then the given cutoff value. * * \param graph The graph object. - * \param result The result of the computation, vector containing the - * betweenness scores for the edges. - * \param directed If true directed paths will be considered - * for directed graphs. It is ignored for undirected graphs. * \param weights An optional weight vector for weighted * betweenness. No edge weight may be NaN. Supply a null * pointer here for unweighted betweenness. + * \param res The result of the computation, vector containing the + * betweenness scores for the edges. + * \param eids The edges for which the betweenness centrality will be returned. + * This parameter is for convenience only, and does not affect + * performance. Internally, the betweenness is be calculated for all + * edges. + * \param directed If true directed paths will be considered + * for directed graphs. It is ignored for undirected graphs. + * \param normalized Whether to normalize betweenness scores by the number of + * vertex pairs. In directed graphs, the number of ordered vertex pairs, + * in undirected graphs the number of unordered vertex pairs is used. * \param cutoff The maximal length of paths that will be considered. - * If negative, the exact betweenness will be calculated (no - * upper limit on path lengths). + * If negative of \ref IGRAPH_UNLIMITED, the exact betweenness will be + * calculated (no upper limit on path lengths). * \return Error code: * \c IGRAPH_ENOMEM, not enough memory for * temporary data. @@ -768,20 +813,31 @@ igraph_error_t igraph_edge_betweenness(const igraph_t *graph, igraph_vector_t *r * \sa \ref igraph_edge_betweenness() to compute the exact edge betweenness and * \ref igraph_betweenness_cutoff() to compute the range-limited vertex betweenness. */ -igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vector_t *result, - igraph_bool_t directed, - const igraph_vector_t *weights, igraph_real_t cutoff) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); +igraph_error_t igraph_edge_betweenness_cutoff( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_es_t eids, + igraph_bool_t directed, igraph_bool_t normalized, + igraph_real_t cutoff) { + + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_inclist_t inclist, parents; - igraph_neimode_t mode = directed ? IGRAPH_OUT : IGRAPH_ALL; + igraph_neimode_t mode; igraph_vector_t dist; + igraph_vector_t v_tmpres, *tmpres = &v_tmpres; igraph_real_t *nrgeo; igraph_real_t *tmpscore; - igraph_integer_t source, j; + igraph_int_t source, j; igraph_stack_int_t S; + igraph_real_t normalization_factor; + + if (!igraph_is_directed(graph)) { + directed = false; + } + mode = directed ? IGRAPH_OUT : IGRAPH_ALL; - IGRAPH_CHECK(igraph_i_betweenness_check_weights(weights, no_of_edges)); + IGRAPH_CHECK(betweenness_check_weights(weights, no_of_edges)); IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, mode, IGRAPH_NO_LOOPS)); IGRAPH_FINALLY(igraph_inclist_destroy, &inclist); @@ -804,8 +860,15 @@ igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vect IGRAPH_CHECK(igraph_stack_int_init(&S, no_of_nodes)); IGRAPH_FINALLY(igraph_stack_int_destroy, &S); - IGRAPH_CHECK(igraph_vector_resize(result, no_of_edges)); - igraph_vector_null(result); + if (!igraph_es_is_all(&eids)) { + /* result needed only for a subset of the vertices */ + IGRAPH_VECTOR_INIT_FINALLY(tmpres, no_of_edges); + } else { + /* result covers all vertices */ + IGRAPH_CHECK(igraph_vector_resize(res, no_of_edges)); + igraph_vector_null(res); + tmpres = res; + } for (source = 0; source < no_of_nodes; source++) { @@ -823,24 +886,24 @@ igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vect /* Conduct a single-source shortest path search from the source node */ if (weights) { - IGRAPH_CHECK(igraph_i_sspf_weighted_edge(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, cutoff)); + IGRAPH_CHECK(sspf_weighted_edge(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, cutoff)); } else { - IGRAPH_CHECK(igraph_i_sspf_edge(graph, source, &dist, nrgeo, &S, &parents, &inclist, cutoff)); + IGRAPH_CHECK(sspf_edge(graph, source, &dist, nrgeo, &S, &parents, &inclist, cutoff)); } /* Aggregate betweenness scores for the edges we have reached in this * traversal */ while (!igraph_stack_int_empty(&S)) { - igraph_integer_t actnode = igraph_stack_int_pop(&S); - igraph_vector_int_t *fatv = igraph_inclist_get(&parents, actnode); - igraph_integer_t fatv_len = igraph_vector_int_size(fatv); + igraph_int_t actnode = igraph_stack_int_pop(&S); + igraph_vector_int_t *parentv = igraph_inclist_get(&parents, actnode); + igraph_int_t parentv_len = igraph_vector_int_size(parentv); igraph_real_t coeff = (1 + tmpscore[actnode]) / nrgeo[actnode]; - for (j = 0; j < fatv_len; j++) { - igraph_integer_t fedge = VECTOR(*fatv)[j]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, fedge, actnode); + for (j = 0; j < parentv_len; j++) { + igraph_int_t fedge = VECTOR(*parentv)[j]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, fedge, actnode); tmpscore[neighbor] += nrgeo[neighbor] * coeff; - VECTOR(*result)[fedge] += nrgeo[neighbor] * coeff; + VECTOR(*tmpres)[fedge] += nrgeo[neighbor] * coeff; } /* Reset variables to ensure that the 'for' loop invariant will @@ -849,14 +912,40 @@ igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vect VECTOR(dist)[actnode] = 0; nrgeo[actnode] = 0; tmpscore[actnode] = 0; - igraph_vector_int_clear(fatv); + igraph_vector_int_clear(parentv); } } /* source < no_of_nodes */ - if (!directed || !igraph_is_directed(graph)) { - igraph_vector_scale(result, 0.5); + /* Keep only the requested edges */ + if (!igraph_es_is_all(&eids)) { + igraph_eit_t eit; + + IGRAPH_CHECK(igraph_eit_create(graph, eids, &eit)); + IGRAPH_FINALLY(igraph_eit_destroy, &eit); + + IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_EIT_SIZE(eit))); + + for (j = 0, IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); + IGRAPH_EIT_NEXT(eit), j++) { + igraph_int_t edge = IGRAPH_EIT_GET(eit); + VECTOR(*res)[j] = VECTOR(*tmpres)[edge]; + } + + igraph_eit_destroy(&eit); + igraph_vector_destroy(tmpres); + IGRAPH_FINALLY_CLEAN(2); } + /* The betweenness calculation is always done for all _ordered_ vertex pairs. + * We only need to correct for this in undirected graphs when normalized=false. */ + if (normalized) { + normalization_factor = 1.0 / (no_of_nodes * (no_of_nodes - 1.0)); + } else { + normalization_factor = directed ? 1.0 : 0.5; + } + + igraph_vector_scale(res, normalization_factor); + IGRAPH_PROGRESS("Edge betweenness centrality: ", 100.0, 0); igraph_stack_int_destroy(&S); @@ -880,19 +969,21 @@ igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vect * source and target subset. * * \param graph The graph object. + * \param weights An optional vector containing edge weights for + * calculating weighted betweenness. No edge weight may be NaN. + * Supply a null pointer here for unweighted betweenness. * \param res The result of the computation, a vector containing the * betweenness score for the subset of vertices. - * \param vids The vertices for which the subset-limited betweenness centrality - * scores will be computed. - * \param directed If true directed paths will be considered - * for directed graphs. It is ignored for undirected graphs. * \param sources A vertex selector for the sources of the shortest paths taken * into considuration in the betweenness calculation. * \param targets A vertex selector for the targets of the shortest paths taken * into considuration in the betweenness calculation. - * \param weights An optional vector containing edge weights for - * calculating weighted betweenness. No edge weight may be NaN. - * Supply a null pointer here for unweighted betweenness. + * \param vids The vertices for which the subset-limited betweenness centrality + * scores will be computed. + * \param directed If true directed paths will be considered + * for directed graphs. It is ignored for undirected graphs. + * \param normalized Whether to normalize betweenness scores. Normalization is + * currently unimplemented, and setting this to \c true raises an error. * \return Error code: * \c IGRAPH_ENOMEM, not enough memory for temporary data. * \c IGRAPH_EINVVID, invalid vertex ID passed in \p vids, @@ -906,29 +997,35 @@ igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vect * \ref igraph_betweenness_cutoff() to calculate the range-limited vertex * betweenness. */ -igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t *res, - const igraph_vs_t vids, igraph_bool_t directed, - const igraph_vs_t sources, const igraph_vs_t targets, - const igraph_vector_t *weights) { - - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_sources; - igraph_integer_t no_of_processed_sources; +igraph_error_t igraph_betweenness_subset( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_vs_t sources, igraph_vs_t targets, + igraph_vs_t vids, + igraph_bool_t directed, igraph_bool_t normalized) { + + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_sources; + igraph_int_t no_of_processed_sources; igraph_adjlist_t adjlist, parents; igraph_inclist_t inclist; - igraph_integer_t source, j; + igraph_int_t source, j; igraph_stack_int_t S; igraph_vector_t v_tmpres, *tmpres = &v_tmpres; igraph_neimode_t mode = directed ? IGRAPH_OUT : IGRAPH_ALL; - igraph_integer_t father; + igraph_int_t parent; igraph_vector_t dist; igraph_real_t *nrgeo; igraph_real_t *tmpscore; igraph_vit_t vit; bool *is_target; - IGRAPH_CHECK(igraph_i_betweenness_check_weights(weights, no_of_edges)); + if (normalized) { + IGRAPH_ERROR("Normalization is not yet implemented for subset betweenness.", IGRAPH_UNIMPLEMENTED); + } + + IGRAPH_CHECK(betweenness_check_weights(weights, no_of_edges)); IGRAPH_CHECK(igraph_vs_size(graph, &sources, &no_of_sources)); @@ -1012,17 +1109,17 @@ igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t /* Conduct a single-source shortest path search from the source node */ if (weights) { - IGRAPH_CHECK(igraph_i_sspf_weighted(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, -1)); + IGRAPH_CHECK(sspf_weighted(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, -1)); } else { - IGRAPH_CHECK(igraph_i_sspf(source, &dist, nrgeo, &S, &parents, &adjlist, -1)); + IGRAPH_CHECK(sspf(source, &dist, nrgeo, &S, &parents, &adjlist, -1)); } /* Aggregate betweenness scores for the nodes we have reached in this * traversal */ while (!igraph_stack_int_empty(&S)) { - igraph_integer_t actnode = igraph_stack_int_pop(&S); - igraph_vector_int_t *fatv = igraph_adjlist_get(&parents, actnode); - igraph_integer_t fatv_len = igraph_vector_int_size(fatv); + igraph_int_t actnode = igraph_stack_int_pop(&S); + igraph_vector_int_t *parentv = igraph_adjlist_get(&parents, actnode); + igraph_int_t parentv_len = igraph_vector_int_size(parentv); igraph_real_t coeff; if (is_target[actnode]) { @@ -1031,9 +1128,9 @@ igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t coeff = tmpscore[actnode] / nrgeo[actnode]; } - for (j = 0; j < fatv_len; j++) { - father = VECTOR(*fatv)[j]; - tmpscore[father] += nrgeo[father] * coeff; + for (j = 0; j < parentv_len; j++) { + parent = VECTOR(*parentv)[j]; + tmpscore[parent] += nrgeo[parent] * coeff; } if (actnode != source) { @@ -1046,7 +1143,7 @@ igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t VECTOR(dist)[actnode] = 0; nrgeo[actnode] = 0; tmpscore[actnode] = 0; - igraph_vector_int_clear(fatv); + igraph_vector_int_clear(parentv); } } @@ -1061,7 +1158,7 @@ igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_VIT_SIZE(vit))); for (j = 0, IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), j++) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); + igraph_int_t node = IGRAPH_VIT_GET(vit); VECTOR(*res)[j] = VECTOR(*tmpres)[node]; } @@ -1100,19 +1197,22 @@ igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t * source and target subset. * * \param graph The graph object. + * \param weights An optional weight vector for weighted + * betweenness. No edge weight may be NaN. Supply a null + * pointer here for unweighted betweenness. * \param res The result of the computation, vector containing the * betweenness scores for the edges. - * \param eids The edges for which the subset-limited betweenness centrality - * scores will be computed. - * \param directed If true directed paths will be considered - * for directed graphs. It is ignored for undirected graphs. * \param sources A vertex selector for the sources of the shortest paths taken * into considuration in the betweenness calculation. * \param targets A vertex selector for the targets of the shortest paths taken * into considuration in the betweenness calculation. - * \param weights An optional weight vector for weighted - * betweenness. No edge weight may be NaN. Supply a null - * pointer here for unweighted betweenness. + * \param eids The edges for which the subset-limited betweenness centrality + * scores will be returned. This parameter is for convenience only. + * Internally, the betweenness will be calculated for all edges. + * \param directed If true directed paths will be considered + * for directed graphs. It is ignored for undirected graphs. + * \param normalized Whether to normalize betweenness scores. Normalization is + * currently unimplemented, and setting this to \c true raises an error. * \return Error code: * \c IGRAPH_ENOMEM, not enough memory for temporary data. * \c IGRAPH_EINVVID, invalid vertex ID passed in \p sources or \p targets @@ -1124,14 +1224,17 @@ igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t * \sa \ref igraph_edge_betweenness() to compute the exact edge betweenness and * \ref igraph_edge_betweenness_cutoff() to compute the range-limited edge betweenness. */ -igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vector_t *res, - const igraph_es_t eids, igraph_bool_t directed, - const igraph_vs_t sources, const igraph_vs_t targets, - const igraph_vector_t *weights) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_sources; - igraph_integer_t no_of_processed_sources; +igraph_error_t igraph_edge_betweenness_subset( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *res, + igraph_vs_t sources, igraph_vs_t targets, + igraph_es_t eids, + igraph_bool_t directed, igraph_bool_t normalized) { + + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_sources; + igraph_int_t no_of_processed_sources; igraph_inclist_t inclist, parents; igraph_vit_t vit; igraph_eit_t eit; @@ -1140,11 +1243,15 @@ igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vect igraph_vector_t v_tmpres, *tmpres = &v_tmpres; igraph_real_t *nrgeo; igraph_real_t *tmpscore; - igraph_integer_t source, j; + igraph_int_t source, j; bool *is_target; igraph_stack_int_t S; - IGRAPH_CHECK(igraph_i_betweenness_check_weights(weights, no_of_edges)); + if (normalized) { + IGRAPH_ERROR("Normalization is not yet implemented for subset edge betweenness.", IGRAPH_UNIMPLEMENTED); + } + + IGRAPH_CHECK(betweenness_check_weights(weights, no_of_edges)); IGRAPH_CHECK(igraph_vs_size(graph, &sources, &no_of_sources)); @@ -1222,17 +1329,17 @@ igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vect /* Conduct a single-source shortest path search from the source node */ if (weights) { - IGRAPH_CHECK(igraph_i_sspf_weighted_edge(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, -1)); + IGRAPH_CHECK(sspf_weighted_edge(graph, source, &dist, nrgeo, weights, &S, &parents, &inclist, -1)); } else { - IGRAPH_CHECK(igraph_i_sspf_edge(graph, source, &dist, nrgeo, &S, &parents, &inclist, -1)); + IGRAPH_CHECK(sspf_edge(graph, source, &dist, nrgeo, &S, &parents, &inclist, -1)); } /* Aggregate betweenness scores for the nodes we have reached in this * traversal */ while (!igraph_stack_int_empty(&S)) { - igraph_integer_t actnode = igraph_stack_int_pop(&S); - igraph_vector_int_t *fatv = igraph_inclist_get(&parents, actnode); - igraph_integer_t fatv_len = igraph_vector_int_size(fatv); + igraph_int_t actnode = igraph_stack_int_pop(&S); + igraph_vector_int_t *parentv = igraph_inclist_get(&parents, actnode); + igraph_int_t parentv_len = igraph_vector_int_size(parentv); igraph_real_t coeff; if (is_target[actnode]) { @@ -1241,11 +1348,11 @@ igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vect coeff = tmpscore[actnode] / nrgeo[actnode]; } - for (j = 0; j < fatv_len; j++) { - igraph_integer_t father_edge = VECTOR(*fatv)[j]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, father_edge, actnode); + for (j = 0; j < parentv_len; j++) { + igraph_int_t parent_edge = VECTOR(*parentv)[j]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, parent_edge, actnode); tmpscore[neighbor] += nrgeo[neighbor] * coeff; - VECTOR(*tmpres)[father_edge] += nrgeo[neighbor] * coeff; + VECTOR(*tmpres)[parent_edge] += nrgeo[neighbor] * coeff; } /* Reset variables to ensure that the 'for' loop invariant will @@ -1254,7 +1361,7 @@ igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vect VECTOR(dist)[actnode] = 0; nrgeo[actnode] = 0; tmpscore[actnode] = 0; - igraph_vector_int_clear(fatv); + igraph_vector_int_clear(parentv); } } @@ -1270,7 +1377,7 @@ igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vect for (j = 0, IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit), j++) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t edge = IGRAPH_EIT_GET(eit); VECTOR(*res)[j] = VECTOR(*tmpres)[edge]; } diff --git a/src/vendor/cigraph/src/centrality/centrality_internal.h b/src/vendor/cigraph/src/centrality/centrality_internal.h index 6afb24687ef..10e4bc69d9c 100644 --- a/src/vendor/cigraph/src/centrality/centrality_internal.h +++ b/src/vendor/cigraph/src/centrality/centrality_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/centrality/centrality_other.c b/src/vendor/cigraph/src/centrality/centrality_other.c index 71d7ec2617e..5865d8b8bf2 100644 --- a/src/vendor/cigraph/src/centrality/centrality_other.c +++ b/src/vendor/cigraph/src/centrality/centrality_other.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ igraph_bool_t igraph_i_vector_mostly_negative(const igraph_vector_t *vector) { * the values are relatively large negative numbers, in which case we should * negate the eigenvector. */ - igraph_integer_t n = igraph_vector_size(vector); + igraph_int_t n = igraph_vector_size(vector); igraph_real_t mi, ma; if (n == 0) { @@ -54,11 +54,11 @@ igraph_bool_t igraph_i_vector_mostly_negative(const igraph_vector_t *vector) { * produce eigenvector-like centrality values, scaling the largest centrality * to 1.0. */ void igraph_i_vector_scale_by_max_abs(igraph_vector_t *vec) { - const igraph_integer_t n = igraph_vector_size(vec); + const igraph_int_t n = igraph_vector_size(vec); igraph_real_t amax = 0; - igraph_integer_t which = 0; + igraph_int_t which = 0; - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { igraph_real_t tmp; tmp = fabs(VECTOR(*vec)[i]); if (tmp > amax) { diff --git a/src/vendor/cigraph/src/centrality/centralization.c b/src/vendor/cigraph/src/centrality/centralization.c index 75cc5f304ef..976a151a282 100644 --- a/src/vendor/cigraph/src/centrality/centralization.c +++ b/src/vendor/cigraph/src/centrality/centralization.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -81,7 +81,7 @@ igraph_real_t igraph_centralization(const igraph_vector_t *scores, igraph_real_t theoretical_max, igraph_bool_t normalized) { - igraph_integer_t no_of_nodes = igraph_vector_size(scores); + igraph_int_t no_of_nodes = igraph_vector_size(scores); igraph_real_t cent; if (no_of_nodes != 0) { @@ -216,7 +216,7 @@ igraph_error_t igraph_centralization_degree( */ igraph_error_t igraph_centralization_degree_tmax( - const igraph_t *graph, igraph_integer_t nodes, igraph_neimode_t mode, + const igraph_t *graph, igraph_int_t nodes, igraph_neimode_t mode, igraph_loops_t loops, igraph_real_t *res ) { @@ -322,7 +322,7 @@ igraph_error_t igraph_centralization_betweenness(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(scores, 0); } - IGRAPH_CHECK(igraph_betweenness(graph, scores, igraph_vss_all(), directed, /*weights=*/ 0)); + IGRAPH_CHECK(igraph_betweenness(graph, /*weights=*/ 0, scores, igraph_vss_all(), directed, false)); IGRAPH_CHECK(igraph_centralization_betweenness_tmax(graph, 0, directed, tmax)); @@ -376,7 +376,7 @@ igraph_error_t igraph_centralization_betweenness(const igraph_t *graph, */ igraph_error_t igraph_centralization_betweenness_tmax(const igraph_t *graph, - igraph_integer_t nodes, + igraph_int_t nodes, igraph_bool_t directed, igraph_real_t *res) { igraph_real_t real_nodes; @@ -517,7 +517,7 @@ igraph_error_t igraph_centralization_closeness(const igraph_t *graph, */ igraph_error_t igraph_centralization_closeness_tmax(const igraph_t *graph, - igraph_integer_t nodes, + igraph_int_t nodes, igraph_neimode_t mode, igraph_real_t *res) { igraph_real_t real_nodes; @@ -688,7 +688,7 @@ igraph_error_t igraph_centralization_eigenvector_centrality( igraph_error_t igraph_centralization_eigenvector_centrality_tmax( const igraph_t *graph, - igraph_integer_t nodes, + igraph_int_t nodes, igraph_neimode_t mode, igraph_real_t *res) { diff --git a/src/vendor/cigraph/src/centrality/closeness.c b/src/vendor/cigraph/src/centrality/closeness.c index 0e176a5821a..96a7b9fb410 100644 --- a/src/vendor/cigraph/src/centrality/closeness.c +++ b/src/vendor/cigraph/src/centrality/closeness.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -133,19 +133,19 @@ static igraph_error_t igraph_i_closeness_cutoff_weighted(const igraph_t *graph, /* See igraph_distances_dijkstra() for the implementation details and the dirty tricks. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_2wheap_t Q; igraph_vit_t vit; - igraph_integer_t nodes_to_calc; + igraph_int_t nodes_to_calc; igraph_lazy_inclist_t inclist; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_vector_t dist; igraph_vector_int_t which; - igraph_integer_t nodes_reached; + igraph_int_t nodes_reached; igraph_real_t mindist = 0; @@ -188,18 +188,18 @@ static igraph_error_t igraph_i_closeness_cutoff_weighted(const igraph_t *graph, for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t source = IGRAPH_VIT_GET(vit); + igraph_int_t source = IGRAPH_VIT_GET(vit); igraph_2wheap_clear(&Q); - igraph_2wheap_push_with_index(&Q, source, -1.0); + igraph_2wheap_push_with_index(&Q, source, -1.0); /* reserved */ VECTOR(which)[source] = i + 1; VECTOR(dist)[source] = 1.0; /* actual distance is zero but we need to store distance + 1 */ nodes_reached = 0; while (!igraph_2wheap_empty(&Q)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&Q); + igraph_int_t minnei = igraph_2wheap_max_index(&Q); /* Now check all neighbors of minnei for a shorter path */ igraph_vector_int_t *neis = igraph_lazy_inclist_get(&inclist, minnei); - igraph_integer_t nlen; + igraph_int_t nlen; IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); @@ -214,8 +214,8 @@ static igraph_error_t igraph_i_closeness_cutoff_weighted(const igraph_t *graph, nodes_reached++; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t to = IGRAPH_OTHER(graph, edge, minnei); + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t to = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_real_t curdist = VECTOR(dist)[to]; @@ -300,8 +300,8 @@ static igraph_error_t igraph_i_closeness_cutoff_weighted(const igraph_t *graph, * reachable within the cutoff is returned. If false, the inverse * of the sum of distances is returned. * \param cutoff The maximal length of paths that will be considered. - * If negative, the exact closeness will be calculated (no upper - * limit on path lengths). + * If negative or \ref IGRAPH_UNLIMITED, the exact closeness will be + * calculated (no upper limit on path lengths). * \return Error code: * \clist * \cli IGRAPH_ENOMEM @@ -328,18 +328,18 @@ igraph_error_t igraph_closeness_cutoff(const igraph_t *graph, igraph_vector_t *r igraph_bool_t normalized, igraph_real_t cutoff) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t already_counted; igraph_vector_int_t *neis; - igraph_integer_t i, j; - igraph_integer_t nodes_reached; + igraph_int_t i, j; + igraph_int_t nodes_reached; igraph_adjlist_t allneis; - igraph_integer_t actdist = 0; + igraph_int_t actdist = 0; igraph_dqueue_int_t q; - igraph_integer_t nodes_to_calc; + igraph_int_t nodes_to_calc; igraph_vit_t vit; if (weights) { @@ -387,7 +387,7 @@ igraph_error_t igraph_closeness_cutoff(const igraph_t *graph, igraph_vector_t *r IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t act = igraph_dqueue_int_pop(&q); + igraph_int_t act = igraph_dqueue_int_pop(&q); actdist = igraph_dqueue_int_pop(&q); if (cutoff >= 0 && actdist > cutoff) { @@ -399,9 +399,9 @@ igraph_error_t igraph_closeness_cutoff(const igraph_t *graph, igraph_vector_t *r /* check the neighbors */ neis = igraph_adjlist_get(&allneis, act); - igraph_integer_t nei_count = igraph_vector_int_size(neis); + igraph_int_t nei_count = igraph_vector_int_size(neis); for (j = 0; j < nei_count; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + igraph_int_t neighbor = VECTOR(*neis)[j]; if (VECTOR(already_counted)[neighbor] == i + 1) { continue; } @@ -450,17 +450,17 @@ static igraph_error_t igraph_i_harmonic_centrality_unweighted(const igraph_t *gr igraph_bool_t normalized, igraph_real_t cutoff) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t already_counted; igraph_vector_int_t *neis; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_adjlist_t allneis; - igraph_integer_t actdist = 0; + igraph_int_t actdist = 0; igraph_dqueue_int_t q; - igraph_integer_t nodes_to_calc; + igraph_int_t nodes_to_calc; igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); @@ -486,7 +486,7 @@ static igraph_error_t igraph_i_harmonic_centrality_unweighted(const igraph_t *gr !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t source = IGRAPH_VIT_GET(vit); + igraph_int_t source = IGRAPH_VIT_GET(vit); igraph_dqueue_int_clear(&q); IGRAPH_CHECK(igraph_dqueue_int_push(&q, source)); @@ -497,7 +497,7 @@ static igraph_error_t igraph_i_harmonic_centrality_unweighted(const igraph_t *gr IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t act = igraph_dqueue_int_pop(&q); + igraph_int_t act = igraph_dqueue_int_pop(&q); actdist = igraph_dqueue_int_pop(&q); if (cutoff >= 0 && actdist > cutoff) { @@ -511,9 +511,9 @@ static igraph_error_t igraph_i_harmonic_centrality_unweighted(const igraph_t *gr /* check the neighbors */ neis = igraph_adjlist_get(&allneis, act); - igraph_integer_t nei_count = igraph_vector_int_size(neis); + igraph_int_t nei_count = igraph_vector_int_size(neis); for (j = 0; j < nei_count; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + igraph_int_t neighbor = VECTOR(*neis)[j]; if (VECTOR(already_counted)[neighbor] == i + 1) { continue; } @@ -552,15 +552,15 @@ static igraph_error_t igraph_i_harmonic_centrality_weighted(const igraph_t *grap /* See igraph_distances_dijkstra() for the implementation details and the dirty tricks. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_2wheap_t Q; igraph_vit_t vit; - igraph_integer_t nodes_to_calc; + igraph_int_t nodes_to_calc; igraph_lazy_inclist_t inclist; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_vector_t dist; igraph_vector_int_t which; @@ -598,17 +598,17 @@ static igraph_error_t igraph_i_harmonic_centrality_weighted(const igraph_t *grap for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t source = IGRAPH_VIT_GET(vit); + igraph_int_t source = IGRAPH_VIT_GET(vit); igraph_2wheap_clear(&Q); - igraph_2wheap_push_with_index(&Q, source, -1.0); + igraph_2wheap_push_with_index(&Q, source, -1.0); /* reserved */ VECTOR(which)[source] = i + 1; VECTOR(dist)[source] = 1.0; /* actual distance is zero but we need to store distance + 1 */ while (!igraph_2wheap_empty(&Q)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&Q); + igraph_int_t minnei = igraph_2wheap_max_index(&Q); /* Now check all neighbors of minnei for a shorter path */ igraph_vector_int_t *neis = igraph_lazy_inclist_get(&inclist, minnei); - igraph_integer_t nlen; + igraph_int_t nlen; IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); @@ -625,8 +625,8 @@ static igraph_error_t igraph_i_harmonic_centrality_weighted(const igraph_t *grap } for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t to = IGRAPH_OTHER(graph, edge, minnei); + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t to = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_real_t curdist = VECTOR(dist)[to]; diff --git a/src/vendor/cigraph/src/centrality/coreness.c b/src/vendor/cigraph/src/centrality/coreness.c index 324cea3cbac..9c383d8bb1a 100644 --- a/src/vendor/cigraph/src/centrality/coreness.c +++ b/src/vendor/cigraph/src/centrality/coreness.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -55,9 +55,9 @@ igraph_error_t igraph_coreness(const igraph_t *graph, igraph_vector_int_t *cores, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t *bin, *vert, *pos; - igraph_integer_t maxdeg; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t *bin, *vert, *pos; + igraph_int_t maxdeg; igraph_vector_int_t neis; igraph_neimode_t omode; @@ -75,11 +75,11 @@ igraph_error_t igraph_coreness(const igraph_t *graph, return IGRAPH_SUCCESS; } - vert = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + vert = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(vert, "Insufficient memory for k-cores."); IGRAPH_FINALLY(igraph_free, vert); - pos = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + pos = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(pos, "Insufficient memory for k-cores."); IGRAPH_FINALLY(igraph_free, pos); @@ -89,50 +89,50 @@ igraph_error_t igraph_coreness(const igraph_t *graph, /* null graph was already handled earlier, 'cores' is not empty */ maxdeg = igraph_vector_int_max(cores); - bin = IGRAPH_CALLOC(maxdeg + 1, igraph_integer_t); + bin = IGRAPH_CALLOC(maxdeg + 1, igraph_int_t); IGRAPH_CHECK_OOM(bin, "Insufficient memory for k-cores."); IGRAPH_FINALLY(igraph_free, bin); /* degree histogram */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { bin[ VECTOR(*cores)[i] ] += 1; } /* start pointers */ - for (igraph_integer_t d = 0, start = 0; d <= maxdeg; d++) { - igraph_integer_t k = bin[d]; + for (igraph_int_t d = 0, start = 0; d <= maxdeg; d++) { + igraph_int_t k = bin[d]; bin[d] = start; start += k; } /* sort in vert (and corrupt bin) */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { pos[i] = bin[VECTOR(*cores)[i]]; vert[pos[i]] = i; bin[VECTOR(*cores)[i]] += 1; } /* correct bin */ - for (igraph_integer_t d = maxdeg; d > 0; d--) { + for (igraph_int_t d = maxdeg; d > 0; d--) { bin[d] = bin[d - 1]; } bin[0] = 0; /* this is the main algorithm */ IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, maxdeg); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t v = vert[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t v = vert[i]; IGRAPH_CHECK(igraph_neighbors( graph, &neis, v, omode, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); - igraph_integer_t nei_count = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < nei_count; j++) { - igraph_integer_t u = VECTOR(neis)[j]; + igraph_int_t nei_count = igraph_vector_int_size(&neis); + for (igraph_int_t j = 0; j < nei_count; j++) { + igraph_int_t u = VECTOR(neis)[j]; if (VECTOR(*cores)[u] > VECTOR(*cores)[v]) { - igraph_integer_t du = VECTOR(*cores)[u]; - igraph_integer_t pu = pos[u]; - igraph_integer_t pw = bin[du]; - igraph_integer_t w = vert[pw]; + igraph_int_t du = VECTOR(*cores)[u]; + igraph_int_t pu = pos[u]; + igraph_int_t pw = bin[du]; + igraph_int_t w = vert[pw]; if (u != w) { pos[u] = pw; pos[w] = pu; diff --git a/src/vendor/cigraph/src/centrality/eigenvector.c b/src/vendor/cigraph/src/centrality/eigenvector.c index 3154614ea96..0cafd771df1 100644 --- a/src/vendor/cigraph/src/centrality/eigenvector.c +++ b/src/vendor/cigraph/src/centrality/eigenvector.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,14 +35,14 @@ static igraph_error_t adjmat_mul_unweighted(igraph_real_t *to, const igraph_real int n, void *extra) { igraph_adjlist_t *adjlist = extra; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; for (i = 0; i < n; i++) { neis = igraph_adjlist_get(adjlist, i); nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += from[nei]; } } @@ -65,15 +65,15 @@ static igraph_error_t adjmat_mul_weighted(igraph_real_t *to, const igraph_real_t const igraph_inclist_t *inclist = data->inclist; const igraph_vector_t *weights = data->weights; igraph_vector_int_t *edges; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; for (i = 0; i < n; i++) { edges = igraph_inclist_get(inclist, i); nlen = igraph_vector_int_size(edges); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*edges)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*edges)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; to[i] += w * from[nei]; } @@ -94,9 +94,9 @@ static void warn_zero_entries(const igraph_vector_t *evcent) { * nonzero values. * See https://github.com/igraph/igraph/pull/2592 */ const igraph_real_t tol = 10 * DBL_EPSILON; - const igraph_integer_t n = igraph_vector_size(evcent); + const igraph_int_t n = igraph_vector_size(evcent); - for (igraph_integer_t i=0; i < n; i++) { + for (igraph_int_t i=0; i < n; i++) { igraph_real_t x = VECTOR(*evcent)[i]; if (-tol < x && x < tol) { IGRAPH_WARNING("Some eigenvector centralities are nearly zero, indicating that the graph may not be (strongly) connected. " @@ -114,9 +114,9 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t igraph_vector_t values; igraph_matrix_t vectors; igraph_vector_t degree; - igraph_integer_t i; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t i; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t negative_weights = false; if (no_of_nodes > INT_MAX) { @@ -192,7 +192,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_undirected(const igraph_t } else { /* When negative weights are present, a zero strength may occur even * if the degree is not zero, and some edges have non-zero weight. */ - igraph_integer_t deg; + igraph_int_t deg; IGRAPH_CHECK(igraph_degree_1(graph, °, i, IGRAPH_ALL, IGRAPH_LOOPS)); MATRIX(vectors, i, 0) = deg == 0 ? 0.0 : 1.0; } @@ -291,8 +291,8 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g igraph_matrix_t vectors; igraph_vector_t indegree; igraph_bool_t dag; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t negative_weights = false; mode = IGRAPH_REVERSE_MODE(mode); @@ -382,7 +382,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g graph, vector, igraph_vss_all(), IGRAPH_REVERSE_MODE(mode), IGRAPH_LOOPS, weights )); - for (igraph_integer_t i=0; i < no_of_nodes; i++) { + for (igraph_int_t i=0; i < no_of_nodes; i++) { if (VECTOR(*vector)[i] == 0) { VECTOR(*vector)[i] = 1; } else { @@ -416,7 +416,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g IGRAPH_CHECK(igraph_strength(graph, &indegree, igraph_vss_all(), mode, IGRAPH_LOOPS, weights)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(indegree)[i]) { /* Note: Keep random perturbation non-negative. */ MATRIX(vectors, i, 0) = VECTOR(indegree)[i] + RNG_UNIF(0, 1e-4); @@ -426,7 +426,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g } else { /* When negative weights are present, a zero in-strength may occur even * if the in-degree is not zero, and some in-edges have non-zero weight. */ - igraph_integer_t deg; + igraph_int_t deg; IGRAPH_CHECK(igraph_degree_1(graph, °, i, mode, IGRAPH_LOOPS)); MATRIX(vectors, i, 0) = deg == 0 ? 0.0 : 1.0; } @@ -476,7 +476,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g igraph_vector_fill(vector, 0); MATRIX(values, 0, 0) = 0; } else { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(*vector)[i] = MATRIX(vectors, i, 0); } @@ -486,7 +486,7 @@ static igraph_error_t igraph_i_eigenvector_centrality_directed(const igraph_t *g /* Correction for numeric inaccuracies (eliminating -0.0) */ if (! negative_weights) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(*vector)[i] < 0) { VECTOR(*vector)[i] = 0; } diff --git a/src/vendor/cigraph/src/centrality/hub_authority.c b/src/vendor/cigraph/src/centrality/hub_authority.c index 4587cee7673..f74da43ecf0 100644 --- a/src/vendor/cigraph/src/centrality/hub_authority.c +++ b/src/vendor/cigraph/src/centrality/hub_authority.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -60,17 +60,17 @@ typedef struct igraph_i_kleinberg_data2_t { static void warn_zero_entries(const igraph_vector_t *cent) { const igraph_real_t tol = 10 * DBL_EPSILON; const igraph_real_t frac = 0.3; /* warn if at least this fraction of centralities is zero */ - const igraph_integer_t n = igraph_vector_size(cent); + const igraph_int_t n = igraph_vector_size(cent); /* Skip check for small graphs */ if (n < 10) { return; } - const igraph_integer_t max_zero_cnt = (igraph_integer_t) frac*n; - igraph_integer_t zero_cnt = 0; + const igraph_int_t max_zero_cnt = ((igraph_int_t) (frac*n)); + igraph_int_t zero_cnt = 0; - for (igraph_integer_t i=0; i < n; i++) { + for (igraph_int_t i=0; i < n; i++) { igraph_real_t x = VECTOR(*cent)[i]; if (-tol < x && x < tol) { if (++zero_cnt > max_zero_cnt) { @@ -86,17 +86,17 @@ static void warn_zero_entries(const igraph_vector_t *cent) { } static igraph_error_t igraph_i_kleinberg_unweighted_hub_to_auth( - igraph_integer_t n, igraph_vector_t *to, const igraph_real_t *from, + igraph_int_t n, igraph_vector_t *to, const igraph_real_t *from, igraph_adjlist_t *in) { igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; for (i = 0; i < n; i++) { neis = igraph_adjlist_get(in, i); nlen = igraph_vector_int_size(neis); VECTOR(*to)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; VECTOR(*to)[i] += from[nei]; } } @@ -111,7 +111,7 @@ static igraph_error_t igraph_i_kleinberg_unweighted(igraph_real_t *to, igraph_adjlist_t *out = data->out; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; igraph_i_kleinberg_unweighted_hub_to_auth(n, tmp, from, data->in); @@ -120,7 +120,7 @@ static igraph_error_t igraph_i_kleinberg_unweighted(igraph_real_t *to, nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += VECTOR(*tmp)[nei]; } } @@ -128,18 +128,18 @@ static igraph_error_t igraph_i_kleinberg_unweighted(igraph_real_t *to, return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_kleinberg_weighted_hub_to_auth(igraph_integer_t n, +static igraph_error_t igraph_i_kleinberg_weighted_hub_to_auth(igraph_int_t n, igraph_vector_t *to, const igraph_real_t *from, igraph_inclist_t *in, const igraph_t *g, const igraph_vector_t *weights) { igraph_vector_int_t *neis; - igraph_integer_t nlen, i, j; + igraph_int_t nlen, i, j; for (i = 0; i < n; i++) { neis = igraph_inclist_get(in, i); nlen = igraph_vector_int_size(neis); VECTOR(*to)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei_edge = VECTOR(*neis)[j]; - igraph_integer_t nei = IGRAPH_OTHER(g, nei_edge, i); + igraph_int_t nei_edge = VECTOR(*neis)[j]; + igraph_int_t nei = IGRAPH_OTHER(g, nei_edge, i); VECTOR(*to)[i] += from[nei] * VECTOR(*weights)[nei_edge]; } } @@ -157,7 +157,7 @@ static igraph_error_t igraph_i_kleinberg_weighted(igraph_real_t *to, const igraph_vector_t *weights = data->weights; const igraph_t *g = data->graph; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; igraph_i_kleinberg_weighted_hub_to_auth(n, tmp, from, data->in, g, weights); @@ -166,8 +166,8 @@ static igraph_error_t igraph_i_kleinberg_weighted(igraph_real_t *to, nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei_edge = VECTOR(*neis)[j]; - igraph_integer_t nei = IGRAPH_OTHER(g, nei_edge, i); + igraph_int_t nei_edge = VECTOR(*neis)[j]; + igraph_int_t nei = IGRAPH_OTHER(g, nei_edge, i); to[i] += VECTOR(*tmp)[nei] * VECTOR(*weights)[nei_edge]; } } @@ -268,7 +268,7 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, igraph_adjlist_t inadjlist, outadjlist; igraph_inclist_t ininclist, outinclist; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_t tmp; igraph_vector_t values; igraph_matrix_t vectors; @@ -404,7 +404,7 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, * Thus we use out-strengths as starting values. */ IGRAPH_CHECK(igraph_strength(graph, &tmp, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, weights)); - for (igraph_integer_t i = 0; i < options->n; i++) { + for (igraph_int_t i = 0; i < options->n; i++) { if (VECTOR(tmp)[i] != 0) { /* Note: Keep random perturbation non-negative. */ MATRIX(vectors, i, 0) = VECTOR(tmp)[i] + RNG_UNIF(0, 1e-4); @@ -414,7 +414,7 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, } else { /* When negative weights are present, a zero out-strength may occur even * if the out-degree is not zero, and some out-edges have non-zero weight. */ - igraph_integer_t deg; + igraph_int_t deg; IGRAPH_CHECK(igraph_degree_1(graph, °, i, IGRAPH_OUT, /* loops */ true)); MATRIX(vectors, i, 0) = deg == 0 ? 0.0 : 1.0; } @@ -449,7 +449,7 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, } IGRAPH_CHECK(igraph_vector_resize(my_hub_vector_p, options->n)); - for (igraph_integer_t i = 0; i < options->n; i++) { + for (igraph_int_t i = 0; i < options->n; i++) { VECTOR(*my_hub_vector_p)[i] = MATRIX(vectors, i, 0); } @@ -457,7 +457,7 @@ igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph, /* Correction for numeric inaccuracies (eliminating -0.0) */ if (! negative_weights) { - for (igraph_integer_t i = 0; i < options->n; i++) { + for (igraph_int_t i = 0; i < options->n; i++) { if (VECTOR(*my_hub_vector_p)[i] < 0) { VECTOR(*my_hub_vector_p)[i] = 0; } diff --git a/src/vendor/cigraph/src/centrality/pagerank.c b/src/vendor/cigraph/src/centrality/pagerank.c index e0511edf88f..d216c582dde 100644 --- a/src/vendor/cigraph/src/centrality/pagerank.c +++ b/src/vendor/cigraph/src/centrality/pagerank.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -66,7 +66,7 @@ static igraph_error_t pagerank_operator_unweighted(igraph_real_t *to, const igra igraph_vector_t *tmp = data->tmp; igraph_vector_t *reset = data->reset; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; igraph_real_t sumfrom = 0.0; igraph_real_t fact = 1 - data->damping; @@ -92,7 +92,7 @@ static igraph_error_t pagerank_operator_unweighted(igraph_real_t *to, const igra nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += VECTOR(*tmp)[nei]; } to[i] *= data->damping; @@ -129,7 +129,7 @@ static igraph_error_t pagerank_operator_weighted(igraph_real_t *to, const igraph igraph_vector_t *outdegree = data->outdegree; igraph_vector_t *tmp = data->tmp; igraph_vector_t *reset = data->reset; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; igraph_real_t sumfrom = 0.0; igraph_vector_int_t *neis; igraph_real_t fact = 1 - data->damping; @@ -159,8 +159,8 @@ static igraph_error_t pagerank_operator_weighted(igraph_real_t *to, const igraph nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); to[i] += VECTOR(*weights)[edge] * VECTOR(*tmp)[nei]; } to[i] *= data->damping; @@ -235,8 +235,9 @@ static igraph_error_t pagerank_operator_weighted(igraph_real_t *to, const igraph * https://doi.org/10.1016/S0169-7552(98)00110-X * * \param graph The graph object. - * \param algo The PageRank implementation to use. Possible values: - * \c IGRAPH_PAGERANK_ALGO_ARPACK, \c IGRAPH_PAGERANK_ALGO_PRPACK. + * \param weights Optional edge weights. May be a \c NULL pointer, + * meaning unweighted edges, or a vector of non-negative values + * of the same length as the number of edges. * \param vector Pointer to an initialized vector, the result is * stored here. It is resized as needed. * \param value Pointer to a real variable. When using \c IGRAPH_PAGERANK_ALGO_ARPACK, @@ -244,16 +245,15 @@ static igraph_error_t pagerank_operator_weighted(igraph_real_t *to, const igraph * expected to be exactly one. Checking this value can be used to diagnose cases * when ARPACK failed to converge to the leading eigenvector. * When using \c IGRAPH_PAGERANK_ALGO_PRPACK, this is always set to 1.0. + * \param damping The damping factor ("d" in the original paper). + * Must be a probability in the range [0, 1]. A commonly used value is 0.85. + * \param directed Boolean, whether to consider the directedness of + * the edges. This is ignored for undirected graphs. * \param vids The vertex IDs for which the PageRank is returned. This parameter * is only for convenience. Computing PageRank for fewer than all vertices will * not speed up the calculation. - * \param directed Boolean, whether to consider the directedness of - * the edges. This is ignored for undirected graphs. - * \param damping The damping factor ("d" in the original paper). - * Must be a probability in the range [0, 1]. A commonly used value is 0.85. - * \param weights Optional edge weights. May be a \c NULL pointer, - * meaning unweighted edges, or a vector of non-negative values - * of the same length as the number of edges. + * \param algo The PageRank implementation to use. Possible values: + * \c IGRAPH_PAGERANK_ALGO_ARPACK, \c IGRAPH_PAGERANK_ALGO_PRPACK. * \param options Options for the ARPACK method. See \ref igraph_arpack_options_t * for details. Supply \c NULL here to use the defaults. Note that the function * overwrites the n (number of vertices), nev (1), @@ -274,15 +274,21 @@ static igraph_error_t pagerank_operator_weighted(igraph_real_t *to, const igraph * * \example examples/simple/igraph_pagerank.c */ - -igraph_error_t igraph_pagerank(const igraph_t *graph, igraph_pagerank_algo_t algo, - igraph_vector_t *vector, - igraph_real_t *value, const igraph_vs_t vids, - igraph_bool_t directed, igraph_real_t damping, - const igraph_vector_t *weights, igraph_arpack_options_t *options) { - return igraph_personalized_pagerank(graph, algo, vector, value, vids, - directed, damping, NULL, weights, - options); +igraph_error_t igraph_pagerank( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *vector, igraph_real_t *value, + igraph_real_t damping, igraph_bool_t directed, + igraph_vs_t vids, + igraph_pagerank_algo_t algo, + igraph_arpack_options_t *options) { + return igraph_personalized_pagerank( + graph, weights, + vector, value, + NULL, + damping, directed, + vids, + algo, + options); } /** @@ -311,8 +317,9 @@ igraph_error_t igraph_pagerank(const igraph_t *graph, igraph_pagerank_algo_t alg * does not result in any performance increase at all. * * \param graph The graph object. - * \param algo The PageRank implementation to use. Possible values: - * \c IGRAPH_PAGERANK_ALGO_ARPACK, \c IGRAPH_PAGERANK_ALGO_PRPACK. + * \param weights Optional edge weights, it is either a null pointer, + * then the edges are not weighted, or a vector of the same length + * as the number of edges. * \param vector Pointer to an initialized vector, the result is * stored here. It is resized as needed. * \param value Pointer to a real variable. When using \c IGRAPH_PAGERANK_ALGO_ARPACK, @@ -320,19 +327,18 @@ igraph_error_t igraph_pagerank(const igraph_t *graph, igraph_pagerank_algo_t alg * expected to be exactly one. Checking this value can be used to diagnose cases * when ARPACK failed to converge to the leading eigenvector. * When using \c IGRAPH_PAGERANK_ALGO_PRPACK, this is always set to 1.0. - * \param vids The vertex IDs for which the PageRank is returned. This parameter - * is only for convenience. Computing PageRank for fewer than all vertices will - * not speed up the calculation. - * \param directed Boolean, whether to consider the directedness of - * the edges. This is ignored for undirected graphs. - * \param damping The damping factor ("d" in the original paper). - * Must be a probability in the range [0, 1]. A commonly used value is 0.85. * \param reset_vids IDs of the vertices used when resetting the random walk. * The walk will be restarted from a vertex in this set, chosen uniformly at * random. Duplicate vertices are allowed. - * \param weights Optional edge weights, it is either a null pointer, - * then the edges are not weighted, or a vector of the same length - * as the number of edges. + * \param damping The damping factor ("d" in the original paper). + * Must be a probability in the range [0, 1]. A commonly used value is 0.85. + * \param directed Boolean, whether to consider the directedness of + * the edges. This is ignored for undirected graphs. + * \param vids The vertex IDs for which the PageRank is returned. This parameter + * is only for convenience. Computing PageRank for fewer than all vertices will + * not speed up the calculation. + * \param algo The PageRank implementation to use. Possible values: + * \c IGRAPH_PAGERANK_ALGO_ARPACK, \c IGRAPH_PAGERANK_ALGO_PRPACK. * \param options Options for the ARPACK method. See \ref igraph_arpack_options_t * for details. Supply \c NULL here to use the defaults. Note that the function * overwrites the n (number of vertices), nev (1), @@ -351,14 +357,15 @@ igraph_error_t igraph_pagerank(const igraph_t *graph, igraph_pagerank_algo_t alg * * \sa \ref igraph_pagerank() for the non-personalized implementation. */ +igraph_error_t igraph_personalized_pagerank_vs( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *vector, igraph_real_t *value, + igraph_vs_t reset_vids, + igraph_real_t damping, igraph_bool_t directed, + igraph_vs_t vids, + igraph_pagerank_algo_t algo, + igraph_arpack_options_t *options) { -igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph, - igraph_pagerank_algo_t algo, igraph_vector_t *vector, - igraph_real_t *value, const igraph_vs_t vids, - igraph_bool_t directed, igraph_real_t damping, - igraph_vs_t reset_vids, - const igraph_vector_t *weights, - igraph_arpack_options_t *options) { igraph_vector_t reset; igraph_vit_t vit; @@ -375,9 +382,9 @@ igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph, IGRAPH_FINALLY_CLEAN(1); IGRAPH_CHECK(igraph_personalized_pagerank( - graph, algo, vector, - value, vids, directed, - damping, &reset, weights, + graph, weights, vector, + value, &reset, + damping, directed, vids, algo, options)); igraph_vector_destroy(&reset); @@ -406,8 +413,9 @@ igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph, * does not result in any performance increase at all. * * \param graph The graph object. - * \param algo The PageRank implementation to use. Possible values: - * \c IGRAPH_PAGERANK_ALGO_ARPACK, \c IGRAPH_PAGERANK_ALGO_PRPACK. + * \param weights Optional edge weights. May be a \c NULL pointer, + * meaning unweighted edges, or a vector of non-negative values + * of the same length as the number of edges. * \param vector Pointer to an initialized vector, the result is * stored here. It is resized as needed. * \param value Pointer to a real variable. When using \c IGRAPH_PAGERANK_ALGO_ARPACK, @@ -415,20 +423,19 @@ igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph, * expected to be exactly one. Checking this value can be used to diagnose cases * when ARPACK failed to converge to the leading eigenvector. * When using \c IGRAPH_PAGERANK_ALGO_PRPACK, this is always set to 1.0. - * \param vids The vertex IDs for which the PageRank is returned. This parameter - * is only for convenience. Computing PageRank for fewer than all vertices will - * not speed up the calculation. - * \param directed Boolean, whether to consider the directedness of - * the edges. This is ignored for undirected graphs. - * \param damping The damping factor ("d" in the original paper). - * Must be a probability in the range [0, 1]. A commonly used value is 0.85. * \param reset The probability distribution over the vertices used when * resetting the random walk. It is either a \c NULL pointer (denoting * a uniform choice that results in the original PageRank measure) * or a vector of the same length as the number of vertices. - * \param weights Optional edge weights. May be a \c NULL pointer, - * meaning unweighted edges, or a vector of non-negative values - * of the same length as the number of edges. + * \param damping The damping factor ("d" in the original paper). + * Must be a probability in the range [0, 1]. A commonly used value is 0.85. + * \param directed Boolean, whether to consider the directedness of + * the edges. This is ignored for undirected graphs. + * \param vids The vertex IDs for which the PageRank is returned. This parameter + * is only for convenience. Computing PageRank for fewer than all vertices will + * not speed up the calculation. + * \param algo The PageRank implementation to use. Possible values: + * \c IGRAPH_PAGERANK_ALGO_ARPACK, \c IGRAPH_PAGERANK_ALGO_PRPACK. * \param options Options for the ARPACK method. See \ref igraph_arpack_options_t * for details. Supply \c NULL here to use the defaults. Note that the function * overwrites the n (number of vertices), nev (1), @@ -448,13 +455,14 @@ igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph, * \ref igraph_personalized_pagerank_vs() for a personalized implementation * with resetting to specific vertices. */ -igraph_error_t igraph_personalized_pagerank(const igraph_t *graph, - igraph_pagerank_algo_t algo, igraph_vector_t *vector, - igraph_real_t *value, const igraph_vs_t vids, - igraph_bool_t directed, igraph_real_t damping, - const igraph_vector_t *reset, - const igraph_vector_t *weights, - igraph_arpack_options_t *options) { +igraph_error_t igraph_personalized_pagerank( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_t *vector, igraph_real_t *value, + const igraph_vector_t *reset, + igraph_real_t damping, igraph_bool_t directed, + igraph_vs_t vids, + igraph_pagerank_algo_t algo, + igraph_arpack_options_t *options) { if (damping < 0.0 || damping > 1.0) { IGRAPH_ERROR("The PageRank damping factor must be in the range [0,1].", IGRAPH_EINVAL); @@ -493,9 +501,9 @@ static igraph_error_t igraph_i_personalized_pagerank_arpack(const igraph_t *grap igraph_vector_t tmp; igraph_vector_t normalized_reset; - igraph_integer_t i; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t i; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_real_t reset_sum; /* used only when reset != NULL */ @@ -679,7 +687,7 @@ static igraph_error_t igraph_i_personalized_pagerank_arpack(const igraph_t *grap if (vector) { igraph_vit_t vit; - igraph_integer_t nodes_to_calc; + igraph_int_t nodes_to_calc; igraph_real_t sum = 0; for (i = 0; i < no_of_nodes; i++) { diff --git a/src/vendor/cigraph/src/centrality/prpack.cpp b/src/vendor/cigraph/src/centrality/prpack.cpp index 2ba52f362e4..1391b28908f 100644 --- a/src/vendor/cigraph/src/centrality/prpack.cpp +++ b/src/vendor/cigraph/src/centrality/prpack.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -40,7 +40,7 @@ igraph_error_t igraph_i_personalized_pagerank_prpack(const igraph_t *graph, igra const igraph_vector_t *weights) { IGRAPH_HANDLE_EXCEPTIONS_BEGIN; - igraph_integer_t i, no_of_nodes = igraph_vcount(graph); + igraph_int_t i, no_of_nodes = igraph_vcount(graph); double *u = nullptr; std::unique_ptr v; @@ -112,7 +112,7 @@ igraph_error_t igraph_i_personalized_pagerank_prpack(const igraph_t *graph, igra igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); - igraph_integer_t nodes_to_calc = IGRAPH_VIT_SIZE(vit); + igraph_int_t nodes_to_calc = IGRAPH_VIT_SIZE(vit); IGRAPH_CHECK(igraph_vector_resize(vector, nodes_to_calc)); for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { diff --git a/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp b/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp index 622213e4f29..35cd85a7006 100644 --- a/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp +++ b/src/vendor/cigraph/src/centrality/prpack/prpack_igraph_graph.cpp @@ -14,8 +14,8 @@ igraph_error_t prpack_igraph_graph::convert_from_igraph( const igraph_t *g, const igraph_vector_t *weights, bool directed) { const bool treat_as_directed = igraph_is_directed(g) && directed; - const igraph_integer_t vcount = igraph_vcount(g); - const igraph_integer_t ecount = igraph_ecount(g); + const igraph_int_t vcount = igraph_vcount(g); + const igraph_int_t ecount = igraph_ecount(g); double *p_weight; int *p_head; @@ -62,7 +62,7 @@ igraph_error_t prpack_igraph_graph::convert_from_igraph( IGRAPH_CHECK(igraph_eit_create(g, igraph_ess_all(IGRAPH_EDGEORDER_TO), &eit)); IGRAPH_FINALLY(igraph_eit_destroy, &eit); while (!IGRAPH_EIT_END(eit)) { - igraph_integer_t eid = IGRAPH_EIT_GET(eit); + igraph_int_t eid = IGRAPH_EIT_GET(eit); IGRAPH_EIT_NEXT(eit); // Handle the weight diff --git a/src/vendor/cigraph/src/centrality/prpack_internal.h b/src/vendor/cigraph/src/centrality/prpack_internal.h index 50a240f7373..28b4b52296f 100644 --- a/src/vendor/cigraph/src/centrality/prpack_internal.h +++ b/src/vendor/cigraph/src/centrality/prpack_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/centrality/truss.cpp b/src/vendor/cigraph/src/centrality/truss.cpp index 76e96478c32..13e1024a71e 100644 --- a/src/vendor/cigraph/src/centrality/truss.cpp +++ b/src/vendor/cigraph/src/centrality/truss.cpp @@ -47,11 +47,11 @@ using std::unordered_set; // So, instead of the triangle specified as vertices [1, 2, 3], return the // edges as [1, 2, 1, 3, 2, 3] so that the support can be computed. static igraph_error_t igraph_truss_i_unpack(const igraph_vector_int_t *tri, igraph_vector_int_t *unpacked_tri) { - igraph_integer_t num_triangles = igraph_vector_int_size(tri); + igraph_int_t num_triangles = igraph_vector_int_size(tri); IGRAPH_CHECK(igraph_vector_int_resize(unpacked_tri, 2 * num_triangles)); - for (igraph_integer_t i = 0, j = 0; i < num_triangles; i += 3, j += 6) { + for (igraph_int_t i = 0, j = 0; i < num_triangles; i += 3, j += 6) { VECTOR(*unpacked_tri)[j] = VECTOR(*unpacked_tri)[j+2] = VECTOR(*tri)[i]; VECTOR(*unpacked_tri)[j+1] = VECTOR(*unpacked_tri)[j+4] = VECTOR(*tri)[i+1]; VECTOR(*unpacked_tri)[j+3] = VECTOR(*unpacked_tri)[j+5] = VECTOR(*tri)[i+2]; @@ -64,8 +64,8 @@ static igraph_error_t igraph_truss_i_unpack(const igraph_vector_int_t *tri, igra // Compute the edge support, i.e. number of triangles each edge occurs in. // Time complexity: O(m), where m is the number of edges listed in eid. static void igraph_truss_i_compute_support(const igraph_vector_int_t *eid, igraph_vector_int_t *support) { - igraph_integer_t m = igraph_vector_int_size(eid); - for (igraph_integer_t i = 0; i < m; ++i) { + igraph_int_t m = igraph_vector_int_size(eid); + for (igraph_int_t i = 0; i < m; ++i) { VECTOR(*support)[VECTOR(*eid)[i]] += 1; } } @@ -81,10 +81,10 @@ static igraph_error_t igraph_i_trussness(const igraph_t *graph, igraph_vector_in igraph_vector_bool_t completed; // C++ data structures - vector< unordered_set > vec; + vector< unordered_set > vec; // Allocate memory for result - igraph_integer_t no_of_edges = igraph_vector_int_size(support); + igraph_int_t no_of_edges = igraph_vector_int_size(support); IGRAPH_CHECK(igraph_vector_int_resize(trussness, no_of_edges)); if (no_of_edges == 0) { return IGRAPH_SUCCESS; @@ -92,7 +92,7 @@ static igraph_error_t igraph_i_trussness(const igraph_t *graph, igraph_vector_in // Get max possible value = max entry in support. // This cannot be computed if there are no edges, hence the above check - igraph_integer_t max = igraph_vector_int_max(support); + igraph_int_t max = igraph_vector_int_max(support); // Initialize completed edges. IGRAPH_VECTOR_BOOL_INIT_FINALLY(&completed, no_of_edges); @@ -102,7 +102,7 @@ static igraph_error_t igraph_i_trussness(const igraph_t *graph, igraph_vector_in vec.resize(max + 1); // Add each edge to its appropriate level of support. - for (igraph_integer_t i = 0; i < no_of_edges; ++i) { + for (igraph_int_t i = 0; i < no_of_edges; ++i) { vec[VECTOR(*support)[i]].insert(i); // insert edge i into its support level } @@ -119,18 +119,18 @@ static igraph_error_t igraph_i_trussness(const igraph_t *graph, igraph_vector_in IGRAPH_VECTOR_INT_INIT_FINALLY(&commonNeighbors, 0); // Move through the levels, one level at a time, starting at first level. - for (igraph_integer_t level = 1; level <= max; ++level) { + for (igraph_int_t level = 1; level <= max; ++level) { /* Track down edges one at a time */ while (!vec[level].empty()) { IGRAPH_ALLOW_INTERRUPTION(); - igraph_integer_t seed = *vec[level].begin(); // pull out the first edge + igraph_int_t seed = *vec[level].begin(); // pull out the first edge vec[level].erase(seed); // remove the first element /* Find the vertices of this edge */ - igraph_integer_t fromVertex = IGRAPH_FROM(graph, seed); - igraph_integer_t toVertex = IGRAPH_TO(graph, seed); + igraph_int_t fromVertex = IGRAPH_FROM(graph, seed); + igraph_int_t toVertex = IGRAPH_TO(graph, seed); /* Find neighbors of both vertices. If they run into each other, * there is a triangle. We rely on the neighbor lists being sorted, @@ -150,10 +150,10 @@ static igraph_error_t igraph_i_trussness(const igraph_t *graph, igraph_vector_in IGRAPH_CHECK(igraph_vector_int_intersect_sorted(q1, q2, &commonNeighbors)); /* Go over the overlapping neighbors and check each */ - igraph_integer_t ncommon = igraph_vector_int_size(&commonNeighbors); - for (igraph_integer_t j = 0; j < ncommon; j++) { - igraph_integer_t n = VECTOR(commonNeighbors)[j]; // the common neighbor - igraph_integer_t e1, e2; + igraph_int_t ncommon = igraph_vector_int_size(&commonNeighbors); + for (igraph_int_t j = 0; j < ncommon; j++) { + igraph_int_t n = VECTOR(commonNeighbors)[j]; // the common neighbor + igraph_int_t e1, e2; IGRAPH_CHECK(igraph_get_eid(graph, &e1, fromVertex, n, IGRAPH_UNDIRECTED, /* error= */ true)); IGRAPH_CHECK(igraph_get_eid(graph, &e2, toVertex, n, IGRAPH_UNDIRECTED, /* error= */ true)); @@ -161,7 +161,7 @@ static igraph_error_t igraph_i_trussness(const igraph_t *graph, igraph_vector_in bool e2_complete = VECTOR(completed)[e2]; if (!e1_complete && !e2_complete) { - igraph_integer_t newLevel; + igraph_int_t newLevel; // Demote this edge, if higher than current level. if (VECTOR(*support)[e1] > level) { diff --git a/src/vendor/cigraph/src/cliques/cliquer/cliquer.c b/src/vendor/cigraph/src/cliques/cliquer/cliquer.c index 01baed27e4f..dd7cb92078d 100644 --- a/src/vendor/cigraph/src/cliques/cliquer/cliquer.c +++ b/src/vendor/cigraph/src/cliques/cliquer/cliquer.c @@ -376,9 +376,14 @@ static igraph_error_t unweighted_clique_search_all( maximal,g,opts,&r); SET_DEL_ELEMENT(current_clique,v); count+=r; - if (retval) { - /* Abort. */ - break; + if (retval != IGRAPH_SUCCESS) { + /* Abort. */ + /* This is from a top-level call to sub_unweighted_all(), + * transform IGRAPH_STOP to success. */ + if (retval == IGRAPH_STOP) { + retval = IGRAPH_SUCCESS; + } + break; } #if 0 @@ -453,9 +458,9 @@ static igraph_error_t sub_unweighted_all(int *table, int size, int min_size, int /* We've found one. Store it. */ count++; retval = store_clique(current_clique, g, opts); - if (retval) { + if (retval != IGRAPH_SUCCESS) { *num_found = count; - return retval == IGRAPH_STOP ? IGRAPH_SUCCESS : retval; + return retval; } } if (max_size <= 0) { @@ -506,11 +511,12 @@ static igraph_error_t sub_unweighted_all(int *table, int size, int min_size, int retval = sub_unweighted_all(newtable,p1-newtable, min_size-1,max_size-1,maximal,g,opts,&n); SET_DEL_ELEMENT(current_clique,v); - count += n; - if (retval || n < 0) { + count += n; + if (retval != IGRAPH_SUCCESS || n < 0) { + /* This is from a recursive call to sub_unweighted_all(), + * pass through IGRAPH_STOP unaltered. */ break; } - count+=n; } temp_list[temp_count++]=newtable; @@ -650,7 +656,12 @@ static igraph_error_t weighted_clique_search_single(int *table, int min_weight, min_w,max_weight,FALSE, g,&localopts, &search_weight); SET_DEL_ELEMENT(current_clique,v); - if (retval || search_weight < 0) { + if (retval != IGRAPH_SUCCESS || search_weight < 0) { + /* This is from a top-level call to sub_weighted_all(), + * transform IGRAPH_STOP to success. */ + if (retval == IGRAPH_STOP) { + retval = IGRAPH_SUCCESS; + } break; } @@ -761,8 +772,13 @@ static igraph_error_t weighted_clique_search_all(int *table, int start, min_weight,max_weight,maximal,g,opts,&j); SET_DEL_ELEMENT(current_clique,v); - if (retval || j < 0) { + if (retval != IGRAPH_SUCCESS || j < 0) { /* Abort. */ + /* This is from a top-level call to sub_weighted_all(), + * transform IGRAPH_STOP to success. */ + if (retval == IGRAPH_STOP) { + retval = IGRAPH_SUCCESS; + } break; } @@ -854,7 +870,7 @@ static igraph_error_t sub_weighted_all(int *table, int size, int weight, retval = store_clique(current_clique,g,opts); if (retval) { *weight_found = -1; - return retval == IGRAPH_STOP ? IGRAPH_SUCCESS : retval; + return retval; } } if (current_weight >= max_weight) { @@ -929,8 +945,10 @@ static igraph_error_t sub_weighted_all(int *table, int size, int weight, min_weight,max_weight,maximal, g,opts, &prune_low); SET_DEL_ELEMENT(current_clique,v); - if (retval || (prune_low<0) || (prune_low>=prune_high)) { + if (retval != IGRAPH_SUCCESS || (prune_low<0) || (prune_low>=prune_high)) { /* Impossible to find larger clique. */ + /* This is from a recursive call to sub_weighted_all(), + * pass through IGRAPH_STOP unaltered. */ break; } } diff --git a/src/vendor/cigraph/src/cliques/cliquer_internal.h b/src/vendor/cigraph/src/cliques/cliquer_internal.h index ecd440a8a2f..009f24eb761 100644 --- a/src/vendor/cigraph/src/cliques/cliquer_internal.h +++ b/src/vendor/cigraph/src/cliques/cliquer_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2016-2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -25,18 +25,20 @@ IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_cliquer_cliques(const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t min_size, igraph_integer_t max_size); + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); igraph_error_t igraph_i_cliquer_histogram(const igraph_t *graph, igraph_vector_t *hist, - igraph_integer_t min_size, igraph_integer_t max_size); + igraph_int_t min_size, igraph_int_t max_size); igraph_error_t igraph_i_cliquer_callback(const igraph_t *graph, - igraph_integer_t min_size, igraph_integer_t max_size, + igraph_int_t min_size, igraph_int_t max_size, igraph_clique_handler_t *cliquehandler_fn, void *arg); igraph_error_t igraph_i_weighted_cliques(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_vector_int_list_t *res, - igraph_real_t min_weight, igraph_real_t max_weight, igraph_bool_t maximal); + igraph_real_t min_weight, igraph_real_t max_weight, igraph_bool_t maximal, + igraph_int_t max_results); igraph_error_t igraph_i_largest_weighted_cliques(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_vector_int_list_t *res); diff --git a/src/vendor/cigraph/src/cliques/cliquer_wrapper.c b/src/vendor/cigraph/src/cliques/cliquer_wrapper.c index 25002f2ecaa..e01370db38f 100644 --- a/src/vendor/cigraph/src/cliques/cliquer_wrapper.c +++ b/src/vendor/cigraph/src/cliques/cliquer_wrapper.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2016-2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,8 +35,8 @@ static IGRAPH_THREAD_LOCAL clique_options igraph_cliquer_opt = { /* Convert an igraph graph to a Cliquer graph */ static igraph_error_t igraph_to_cliquer(const igraph_t *ig, graph_t **cg) { - igraph_integer_t vcount, ecount; - igraph_integer_t i; + igraph_int_t vcount, ecount; + igraph_int_t i; if (igraph_is_directed(ig)) { IGRAPH_WARNING("Edge directions are ignored for clique calculations."); @@ -52,7 +52,7 @@ static igraph_error_t igraph_to_cliquer(const igraph_t *ig, graph_t **cg) { *cg = graph_new((int) vcount); for (i = 0; i < ecount; ++i) { - igraph_integer_t s, t; + igraph_int_t s, t; s = IGRAPH_FROM(ig, i); t = IGRAPH_TO(ig, i); if (s != t) { @@ -66,7 +66,7 @@ static igraph_error_t igraph_to_cliquer(const igraph_t *ig, graph_t **cg) { /* Copy weights to a Cliquer graph */ static igraph_error_t set_weights(const igraph_vector_t *vertex_weights, graph_t *g) { - igraph_integer_t i; + igraph_int_t i; IGRAPH_ASSERT(vertex_weights != NULL); @@ -93,6 +93,7 @@ static igraph_error_t set_weights(const igraph_vector_t *vertex_weights, graph_t typedef struct { igraph_vector_int_t clique; igraph_vector_int_list_t* result; + igraph_int_t max_results; } igraph_i_cliquer_cliques_user_data_t; static igraph_error_t igraph_i_cliquer_cliques_user_data_init( @@ -100,6 +101,7 @@ static igraph_error_t igraph_i_cliquer_cliques_user_data_init( igraph_vector_int_list_t* result ) { data->result = result; + data->max_results = IGRAPH_UNLIMITED; igraph_vector_int_list_clear(result); return igraph_vector_int_init(&data->clique, 0); } @@ -113,7 +115,7 @@ static void igraph_i_cliquer_cliques_user_data_destroy( static igraph_error_t collect_cliques_callback(set_t s, graph_t *g, clique_options *opt) { int i; - igraph_integer_t j; + igraph_int_t j; igraph_i_cliquer_cliques_user_data_t* data = (igraph_i_cliquer_cliques_user_data_t *) opt->user_data; IGRAPH_UNUSED(g); @@ -129,16 +131,23 @@ static igraph_error_t collect_cliques_callback(set_t s, graph_t *g, clique_optio IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(data->result, &data->clique)); - return IGRAPH_SUCCESS; + if (data->max_results > 0 && igraph_vector_int_list_size(data->result) == data->max_results) { + return IGRAPH_STOP; + } else { + return IGRAPH_SUCCESS; + } } -igraph_error_t igraph_i_cliquer_cliques(const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t min_size, igraph_integer_t max_size) { +igraph_error_t igraph_i_cliquer_cliques( + const igraph_t *graph, igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results) { + graph_t *g; - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t vcount = igraph_vcount(graph); igraph_i_cliquer_cliques_user_data_t data; - if (vcount == 0) { + if (vcount == 0 || max_results == 0) { igraph_vector_int_list_clear(res); return IGRAPH_SUCCESS; } @@ -162,6 +171,8 @@ igraph_error_t igraph_i_cliquer_cliques(const igraph_t *graph, igraph_vector_int IGRAPH_CHECK(igraph_i_cliquer_cliques_user_data_init(&data, res)); IGRAPH_FINALLY(igraph_i_cliquer_cliques_user_data_destroy, &data); + data.max_results = max_results; + IGRAPH_CHECK(igraph_to_cliquer(graph, &g)); IGRAPH_FINALLY(graph_free, g); @@ -194,10 +205,10 @@ static igraph_error_t count_cliques_callback(set_t s, graph_t *g, clique_options } igraph_error_t igraph_i_cliquer_histogram(const igraph_t *graph, igraph_vector_t *hist, - igraph_integer_t min_size, igraph_integer_t max_size) { + igraph_int_t min_size, igraph_int_t max_size) { graph_t *g; - igraph_integer_t i; - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t i; + igraph_int_t vcount = igraph_vcount(graph); if (vcount == 0) { igraph_vector_clear(hist); @@ -257,7 +268,7 @@ struct callback_data { static igraph_error_t callback_callback(set_t s, graph_t *g, clique_options *opt) { struct callback_data *cd; int i; - igraph_integer_t j; + igraph_int_t j; igraph_error_t retval; IGRAPH_UNUSED(g); @@ -279,12 +290,12 @@ static igraph_error_t callback_callback(set_t s, graph_t *g, clique_options *opt } igraph_error_t igraph_i_cliquer_callback(const igraph_t *graph, - igraph_integer_t min_size, igraph_integer_t max_size, + igraph_int_t min_size, igraph_int_t max_size, igraph_clique_handler_t *cliquehandler_fn, void *arg) { graph_t *g; igraph_vector_int_t current_clique; struct callback_data cd; - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t vcount = igraph_vcount(graph); if (vcount == 0) { return IGRAPH_SUCCESS; @@ -331,12 +342,13 @@ igraph_error_t igraph_i_cliquer_callback(const igraph_t *graph, igraph_error_t igraph_i_weighted_cliques(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_vector_int_list_t *res, - igraph_real_t min_weight, igraph_real_t max_weight, igraph_bool_t maximal) { + igraph_real_t min_weight, igraph_real_t max_weight, igraph_bool_t maximal, + igraph_int_t max_results) { graph_t *g; - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t vcount = igraph_vcount(graph); igraph_i_cliquer_cliques_user_data_t data; - if (vcount == 0) { + if (vcount == 0 || max_results == 0) { igraph_vector_int_list_clear(res); return IGRAPH_SUCCESS; } @@ -365,6 +377,7 @@ igraph_error_t igraph_i_weighted_cliques(const igraph_t *graph, IGRAPH_CHECK(igraph_i_cliquer_cliques_user_data_init(&data, res)); IGRAPH_FINALLY(igraph_i_cliquer_cliques_user_data_destroy, &data); + data.max_results = max_results; IGRAPH_CHECK(igraph_to_cliquer(graph, &g)); IGRAPH_FINALLY(graph_free, g); @@ -389,7 +402,7 @@ igraph_error_t igraph_i_weighted_cliques(const igraph_t *graph, igraph_error_t igraph_i_largest_weighted_cliques(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_vector_int_list_t *res) { graph_t *g; - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t vcount = igraph_vcount(graph); igraph_i_cliquer_cliques_user_data_t data; if (vcount == 0) { @@ -429,7 +442,7 @@ static igraph_error_t check_interruption_callback(set_t s, graph_t *g, clique_op igraph_error_t igraph_i_weighted_clique_number(const igraph_t *graph, const igraph_vector_t *vertex_weights, igraph_real_t *res) { graph_t *g; - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t vcount = igraph_vcount(graph); int res_int; if (vcount == 0) { @@ -444,7 +457,7 @@ igraph_error_t igraph_i_weighted_clique_number(const igraph_t *graph, IGRAPH_CHECK(set_weights(vertex_weights, g)); - igraph_cliquer_opt.user_function = check_interruption_callback; + igraph_cliquer_opt.user_function = &check_interruption_callback; IGRAPH_CHECK(clique_max_weight(g, &igraph_cliquer_opt, &res_int)); diff --git a/src/vendor/cigraph/src/cliques/cliques.c b/src/vendor/cigraph/src/cliques/cliques.c index 216d22c517d..83c29418465 100644 --- a/src/vendor/cigraph/src/cliques/cliques.c +++ b/src/vendor/cigraph/src/cliques/cliques.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,23 +28,23 @@ #include "core/set.h" static igraph_error_t igraph_i_find_k_indsets( - igraph_integer_t size, - const igraph_integer_t *member_storage, - igraph_integer_t **new_member_storage, - igraph_integer_t old_count, - igraph_integer_t *new_count, + igraph_int_t size, + const igraph_int_t *member_storage, + igraph_int_t **new_member_storage, + igraph_int_t old_count, + igraph_int_t *new_count, igraph_lazy_adjlist_t *al) { - igraph_integer_t l, m, n, new_member_storage_size; - const igraph_integer_t *c1, *c2; + igraph_int_t l, m, n, new_member_storage_size; + const igraph_int_t *c1, *c2; const igraph_vector_int_t *neis; - igraph_integer_t v1, v2; + igraph_int_t v1, v2; igraph_bool_t ok; /* Allocate the storage */ *new_member_storage = IGRAPH_REALLOC(*new_member_storage, (size_t) (size * old_count), - igraph_integer_t); + igraph_int_t); IGRAPH_CHECK_OOM(*new_member_storage, "Insufficient memory for independent vertex sets."); new_member_storage_size = size * old_count; @@ -53,8 +53,8 @@ static igraph_error_t igraph_i_find_k_indsets( m = n = 0; /* Now consider all pairs of i-1-indsets and see if they can be merged */ - for (igraph_integer_t j = 0; j < old_count; j++) { - for (igraph_integer_t k = j + 1; k < old_count; k++) { + for (igraph_int_t j = 0; j < old_count; j++) { + for (igraph_int_t k = j + 1; k < old_count; k++) { IGRAPH_ALLOW_INTERRUPTION(); /* Since indsets are represented by their vertex indices in increasing @@ -137,7 +137,7 @@ static igraph_error_t igraph_i_find_k_indsets( IGRAPH_FINALLY_CLEAN(1); *new_member_storage = IGRAPH_REALLOC(*new_member_storage, (size_t) new_member_storage_size * 2, - igraph_integer_t); + igraph_int_t); IGRAPH_CHECK_OOM(*new_member_storage, "Insufficient memory to find independent vertex sets."); new_member_storage_size *= 2; IGRAPH_FINALLY(igraph_free, *new_member_storage); @@ -174,6 +174,8 @@ static igraph_error_t igraph_i_find_k_indsets( * returned. If negative or zero, no lower bound will be used. * \param max_size Integer specifying the maximum size of the cliques to be * returned. If negative or zero, no upper bound will be used. + * \param max_results At most this many cliques will be recorded. If + * negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_largest_cliques() and \ref igraph_clique_number(). @@ -182,9 +184,11 @@ static igraph_error_t igraph_i_find_k_indsets( * * \example examples/simple/igraph_cliques.c */ -igraph_error_t igraph_cliques(const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t min_size, igraph_integer_t max_size) { - return igraph_i_cliquer_cliques(graph, res, min_size, max_size); +igraph_error_t igraph_cliques( + const igraph_t *graph, igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results) { + return igraph_i_cliquer_cliques(graph, res, min_size, max_size, max_results); } @@ -216,7 +220,7 @@ igraph_error_t igraph_cliques(const igraph_t *graph, igraph_vector_int_list_t *r * */ igraph_error_t igraph_clique_size_hist(const igraph_t *graph, igraph_vector_t *hist, - igraph_integer_t min_size, igraph_integer_t max_size) { + igraph_int_t min_size, igraph_int_t max_size) { return igraph_i_cliquer_histogram(graph, hist, min_size, max_size); } @@ -253,7 +257,7 @@ igraph_error_t igraph_clique_size_hist(const igraph_t *graph, igraph_vector_t *h * */ igraph_error_t igraph_cliques_callback(const igraph_t *graph, - igraph_integer_t min_size, igraph_integer_t max_size, + igraph_int_t min_size, igraph_int_t max_size, igraph_clique_handler_t *cliquehandler_fn, void *arg) { return igraph_i_cliquer_callback(graph, min_size, max_size, cliquehandler_fn, arg); } @@ -282,11 +286,13 @@ igraph_error_t igraph_cliques_callback(const igraph_t *graph, * here to make each vertex have a weight of 1. * \param res Pointer to an initialized list of integer vectors. The cliques * will be stored here as vectors of vertex IDs. + * \param maximal If true, only maximal cliques will be returned * \param min_weight Integer specifying the minimum weight of the cliques to be * returned. If negative or zero, no lower bound will be used. * \param max_weight Integer specifying the maximum weight of the cliques to be * returned. If negative or zero, no upper bound will be used. - * \param maximal If true, only maximal cliques will be returned + * \param max_results At most this many cliques will be recorded. If + * negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_cliques(), \ref igraph_maximal_cliques() @@ -294,15 +300,19 @@ igraph_error_t igraph_cliques_callback(const igraph_t *graph, * Time complexity: Exponential * */ -igraph_error_t igraph_weighted_cliques(const igraph_t *graph, - const igraph_vector_t *vertex_weights, igraph_vector_int_list_t *res, - igraph_real_t min_weight, igraph_real_t max_weight, igraph_bool_t maximal) { +igraph_error_t igraph_weighted_cliques( + const igraph_t *graph, const igraph_vector_t *vertex_weights, + igraph_vector_int_list_t *res, + igraph_bool_t maximal, + igraph_real_t min_weight, igraph_real_t max_weight, + igraph_int_t max_results) { + if (vertex_weights) { - return igraph_i_weighted_cliques(graph, vertex_weights, res, min_weight, max_weight, maximal); + return igraph_i_weighted_cliques(graph, vertex_weights, res, min_weight, max_weight, maximal, max_results); } else if (maximal) { - return igraph_maximal_cliques(graph, res, min_weight, max_weight); + return igraph_maximal_cliques(graph, res, min_weight, max_weight, max_results); } else { - return igraph_cliques(graph, res, min_weight, max_weight); + return igraph_cliques(graph, res, min_weight, max_weight, max_results); } } @@ -377,7 +387,7 @@ igraph_error_t igraph_weighted_clique_number(const igraph_t *graph, if (vertex_weights) { return igraph_i_weighted_clique_number(graph, vertex_weights, res); } else { - igraph_integer_t res_int; + igraph_int_t res_int; IGRAPH_CHECK(igraph_clique_number(graph, &res_int)); if (res) { *res = res_int; @@ -389,7 +399,7 @@ igraph_error_t igraph_weighted_clique_number(const igraph_t *graph, static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets( const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t *clique_number, + igraph_int_t *clique_number, igraph_bool_t keep_only_largest, igraph_bool_t complementer); @@ -419,6 +429,8 @@ static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets( * returned. If negative or zero, no lower bound will be used. * \param max_size Integer specifying the maximum size of the sets to be * returned. If negative or zero, no upper bound will be used. + * \param max_results At most this many independent vertex sets will be recorded. + * If negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_largest_independent_vertex_sets(), @@ -428,15 +440,16 @@ static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets( * * \example examples/simple/igraph_independent_sets.c */ -igraph_error_t igraph_independent_vertex_sets(const igraph_t *graph, - igraph_vector_int_list_t *res, - igraph_integer_t min_size, - igraph_integer_t max_size) { - igraph_integer_t no_of_nodes; +igraph_error_t igraph_independent_vertex_sets( + const igraph_t *graph, + igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results) { + + igraph_int_t no_of_nodes; igraph_vector_int_t *indset; - igraph_integer_t *member_storage, *new_member_storage, *c1; - igraph_vector_int_t new_member_storage_view; - igraph_integer_t indset_count, old_indset_count; + igraph_int_t *member_storage, *new_member_storage, *c1; + igraph_int_t indset_count, old_indset_count; igraph_lazy_adjlist_t al; if (igraph_is_directed(graph)) { @@ -451,38 +464,48 @@ igraph_error_t igraph_independent_vertex_sets(const igraph_t *graph, if (max_size > no_of_nodes || max_size <= 0) { max_size = no_of_nodes; } + if (max_results < 0) { + max_results = IGRAPH_INTEGER_MAX; + } igraph_vector_int_list_clear(res); + /* Add size-1 indsets if requested */ + if (min_size <= 1) { + igraph_int_t max_singletons_to_add = + (max_results > no_of_nodes) ? no_of_nodes : max_results; + IGRAPH_CHECK(igraph_vector_int_list_resize(res, max_singletons_to_add)); + for (igraph_int_t i = 0; i < max_singletons_to_add; i++) { + indset = igraph_vector_int_list_get_ptr(res, i); + IGRAPH_CHECK(igraph_vector_int_push_back(indset, i)); + --max_results; + } + } + + if (max_results == 0) { + return IGRAPH_SUCCESS; + } + IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &al, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &al); /* Will be resized later, if needed. */ - member_storage = IGRAPH_CALLOC(1, igraph_integer_t); + member_storage = IGRAPH_CALLOC(1, igraph_int_t); IGRAPH_CHECK_OOM(member_storage, "Insufficient memory for independent vertex set calculation."); IGRAPH_FINALLY(igraph_free, member_storage); /* Find all 1-cliques: every vertex will be a clique */ - new_member_storage = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + new_member_storage = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(new_member_storage, "Insufficient memory for independent vertex set calculation."); IGRAPH_FINALLY(igraph_free, new_member_storage); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { new_member_storage[i] = i; } indset_count = no_of_nodes; old_indset_count = 0; - /* Add size 1 indsets if requested */ - if (min_size <= 1) { - IGRAPH_CHECK(igraph_vector_int_list_resize(res, no_of_nodes)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - indset = igraph_vector_int_list_get_ptr(res, i); - IGRAPH_CHECK(igraph_vector_int_push_back(indset, i)); - } - } - - for (igraph_integer_t i = 2; i <= max_size && indset_count > 1; i++) { + for (igraph_int_t i = 2; i <= max_size && indset_count > 1; i++) { /* Here new_member_storage contains the independent vertex sets found in the previous iteration. Save this into member_storage, might be needed later */ @@ -507,14 +530,20 @@ igraph_error_t igraph_independent_vertex_sets(const igraph_t *graph, /* Add the cliques just found to the result if requested */ if (i >= min_size && i <= max_size) { - for (igraph_integer_t j = 0, k = 0; j < indset_count; j++, k += i) { - igraph_vector_int_view(&new_member_storage_view, new_member_storage + k, i); + for (igraph_int_t j = 0, k = 0; j < indset_count; j++, k += i) { + const igraph_vector_int_t new_member_storage_view = + igraph_vector_int_view(new_member_storage + k, i); + IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(res, &new_member_storage_view)); + if (--max_results == 0) { + goto done; + } } } } /* i <= max_size && clique_count != 0 */ +done: IGRAPH_FREE(new_member_storage); IGRAPH_FREE(member_storage); igraph_lazy_adjlist_destroy(&al); @@ -555,31 +584,37 @@ igraph_error_t igraph_largest_independent_vertex_sets(const igraph_t *graph, } typedef struct igraph_i_max_ind_vsets_data_t { - igraph_integer_t matrix_size; + igraph_int_t matrix_size; igraph_adjlist_t adj_list; /* Adjacency list of the graph */ igraph_vector_int_t deg; /* Degrees of individual nodes */ igraph_set_t* buckets; /* Bucket array */ /* The IS value for each node. Still to be explained :) */ - igraph_integer_t* IS; - igraph_integer_t largest_set_size; /* Size of the largest set encountered */ + igraph_int_t* IS; + igraph_int_t largest_set_size; /* Size of the largest set encountered */ igraph_bool_t keep_only_largest; /* True if we keep only the largest sets */ + igraph_int_t min_size, max_size; + igraph_int_t max_results; } igraph_i_max_ind_vsets_data_t; static igraph_error_t igraph_i_maximal_independent_vertex_sets_backtrack( const igraph_t *graph, igraph_vector_int_list_t *res, igraph_i_max_ind_vsets_data_t *clqdata, - igraph_integer_t level) { + igraph_int_t level) { - igraph_integer_t v1, v2, v3, c, j, k; + igraph_int_t v1, v2, v3, c, j, k; igraph_vector_int_t *neis1, *neis2; igraph_bool_t f; - igraph_integer_t it_state; + igraph_int_t it_state; + + if (clqdata->max_results == 0) { + return IGRAPH_SUCCESS; + } IGRAPH_ALLOW_INTERRUPTION(); if (level >= clqdata->matrix_size - 1) { - igraph_integer_t size = 0; + igraph_int_t size = 0; if (res) { igraph_vector_int_t vec, *newvec; @@ -597,8 +632,11 @@ static igraph_error_t igraph_i_maximal_independent_vertex_sets_backtrack( * Instead of copying the vector contents, we add an empty vector to * the list, then swap it with the vector to-be-added in O(1) time. */ if (!clqdata->keep_only_largest) { - IGRAPH_CHECK(igraph_vector_int_list_push_back_new(res, &newvec)); - igraph_vector_int_swap(newvec, &vec); + if (clqdata->min_size <= size && size <= clqdata->max_size) { + IGRAPH_CHECK(igraph_vector_int_list_push_back_new(res, &newvec)); + igraph_vector_int_swap(newvec, &vec); + if (clqdata->max_results >= 0) --(clqdata->max_results); + } } else { if (size > clqdata->largest_set_size) { /* We are keeping only the largest sets, and we've found one that's @@ -721,7 +759,7 @@ static igraph_error_t igraph_i_maximal_independent_vertex_sets_backtrack( * Should probably be replaced with a proper igraph_vector_ptr_t. */ static void free_set_array_incomplete(igraph_set_t *array) { - igraph_integer_t i = 0; + igraph_int_t i = 0; while (igraph_set_inited(array + i)) { igraph_set_destroy(array + i); i++; @@ -729,8 +767,8 @@ static void free_set_array_incomplete(igraph_set_t *array) { IGRAPH_FREE(array); } -static void free_set_array(igraph_set_t *array, igraph_integer_t n) { - for (igraph_integer_t i=0; i < n; i++) { +static void free_set_array(igraph_set_t *array, igraph_int_t n) { + for (igraph_int_t i=0; i < n; i++) { igraph_set_destroy(&array[i]); } IGRAPH_FREE(array); @@ -762,6 +800,12 @@ static void free_set_array(igraph_set_t *array, igraph_integer_t n) { * \param graph The input graph. * \param res Pointer to an initialized list of integer vectors. The cliques * will be stored here as vectors of vertex IDs. + * \param min_size Integer specifying the minimum size of the sets to be + * returned. If negative or zero, no lower bound will be used. + * \param max_size Integer specifying the maximum size of the sets to be + * returned. If negative or zero, no upper bound will be used. + * \param max_results At most this many independent vertex sets will be recorded. + * If negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_maximal_cliques(), \ref @@ -769,10 +813,14 @@ static void free_set_array(igraph_set_t *array, igraph_integer_t n) { * * Time complexity: TODO. */ -igraph_error_t igraph_maximal_independent_vertex_sets(const igraph_t *graph, - igraph_vector_int_list_t *res) { +igraph_error_t igraph_maximal_independent_vertex_sets( + const igraph_t *graph, + igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results) { + igraph_i_max_ind_vsets_data_t clqdata; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (igraph_is_directed(graph)) { IGRAPH_WARNING("Edge directions are ignored during independent vertex set calculations."); @@ -781,17 +829,29 @@ igraph_error_t igraph_maximal_independent_vertex_sets(const igraph_t *graph, clqdata.matrix_size = no_of_nodes; clqdata.keep_only_largest = false; + if (max_size <= 0) { + max_size = IGRAPH_INTEGER_MAX; + } + + if (max_results < 0) { + max_results = IGRAPH_INTEGER_MAX; + } + + clqdata.min_size = min_size; + clqdata.max_size = max_size; + clqdata.max_results = max_results; + IGRAPH_CHECK(igraph_adjlist_init( graph, &clqdata.adj_list, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE )); IGRAPH_FINALLY(igraph_adjlist_destroy, &clqdata.adj_list); - clqdata.IS = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + clqdata.IS = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(clqdata.IS, "Insufficient memory for maximal independent vertex sets."); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INT_INIT_FINALLY(&clqdata.deg, no_of_nodes); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(clqdata.deg)[i] = igraph_vector_int_size(igraph_adjlist_get(&clqdata.adj_list, i)); } @@ -799,7 +859,7 @@ igraph_error_t igraph_maximal_independent_vertex_sets(const igraph_t *graph, IGRAPH_CHECK_OOM(clqdata.buckets, "Insufficient memory for maximal independent vertex sets."); IGRAPH_FINALLY(free_set_array_incomplete, clqdata.buckets); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_set_init(&clqdata.buckets[i], 0)); } @@ -836,16 +896,16 @@ igraph_error_t igraph_maximal_independent_vertex_sets(const igraph_t *graph, * * \param graph The input graph. * \param no The independence number will be returned to the \c - * igraph_integer_t pointed by this variable. + * igraph_int_t pointed by this variable. * \return Error code. * * \sa \ref igraph_independent_vertex_sets(). * * Time complexity: TODO. */ -igraph_error_t igraph_independence_number(const igraph_t *graph, igraph_integer_t *no) { +igraph_error_t igraph_independence_number(const igraph_t *graph, igraph_int_t *no) { igraph_i_max_ind_vsets_data_t clqdata; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (igraph_is_directed(graph)) { IGRAPH_WARNING("Edge directions are ignored during independence number calculations."); @@ -853,18 +913,19 @@ igraph_error_t igraph_independence_number(const igraph_t *graph, igraph_integer_ clqdata.matrix_size = no_of_nodes; clqdata.keep_only_largest = false; + clqdata.max_results = IGRAPH_INTEGER_MAX; IGRAPH_CHECK(igraph_adjlist_init( graph, &clqdata.adj_list, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE )); IGRAPH_FINALLY(igraph_adjlist_destroy, &clqdata.adj_list); - clqdata.IS = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + clqdata.IS = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(clqdata.IS, "Insufficient memory for independence number calculation."); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INT_INIT_FINALLY(&clqdata.deg, no_of_nodes); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(clqdata.deg)[i] = igraph_vector_int_size(igraph_adjlist_get(&clqdata.adj_list, i)); } @@ -872,7 +933,7 @@ igraph_error_t igraph_independence_number(const igraph_t *graph, igraph_integer_ IGRAPH_CHECK_OOM(clqdata.buckets, "Insufficient memory for independence number calculation."); IGRAPH_FINALLY(free_set_array_incomplete, clqdata.buckets); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_set_init(&clqdata.buckets[i], 0)); } @@ -896,7 +957,7 @@ igraph_error_t igraph_independence_number(const igraph_t *graph, igraph_integer_ /*************************************************************************/ static igraph_error_t igraph_i_maximal_cliques_store_max_size(const igraph_vector_int_t* clique, void* data) { - igraph_integer_t* result = (igraph_integer_t*)data; + igraph_int_t* result = (igraph_int_t*)data; if (*result < igraph_vector_int_size(clique)) { *result = igraph_vector_int_size(clique); } @@ -905,7 +966,7 @@ static igraph_error_t igraph_i_maximal_cliques_store_max_size(const igraph_vecto static igraph_error_t igraph_i_largest_cliques_store(const igraph_vector_int_t* clique, void* data) { igraph_vector_int_list_t* result = (igraph_vector_int_list_t*)data; - igraph_integer_t n; + igraph_int_t n; /* Is the current clique at least as large as the others that we have found? */ if (!igraph_vector_int_list_empty(result)) { @@ -961,7 +1022,7 @@ static igraph_error_t igraph_i_largest_cliques_store(const igraph_vector_int_t* igraph_error_t igraph_largest_cliques(const igraph_t *graph, igraph_vector_int_list_t *res) { igraph_vector_int_list_clear(res); - IGRAPH_CHECK(igraph_maximal_cliques_callback(graph, &igraph_i_largest_cliques_store, (void*)res, 0, 0)); + IGRAPH_CHECK(igraph_maximal_cliques_callback(graph, 0, 0, &igraph_i_largest_cliques_store, (void *) res)); return IGRAPH_SUCCESS; } @@ -977,7 +1038,7 @@ igraph_error_t igraph_largest_cliques(const igraph_t *graph, igraph_vector_int_l * track of the size of the largest clique that was found. * * \param graph The input graph. - * \param no The clique number will be returned to the \c igraph_integer_t + * \param no The clique number will be returned to the \c igraph_int_t * pointed by this variable. * \return Error code. * @@ -985,19 +1046,19 @@ igraph_error_t igraph_largest_cliques(const igraph_t *graph, igraph_vector_int_l * * Time complexity: O(3^(|V|/3)) worst case. */ -igraph_error_t igraph_clique_number(const igraph_t *graph, igraph_integer_t *no) { +igraph_error_t igraph_clique_number(const igraph_t *graph, igraph_int_t *no) { *no = 0; - return igraph_maximal_cliques_callback(graph, &igraph_i_maximal_cliques_store_max_size, (void*)no, 0, 0); + return igraph_maximal_cliques_callback(graph, 0, 0, &igraph_i_maximal_cliques_store_max_size, (void *) no); } static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets(const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t *clique_number, + igraph_int_t *clique_number, igraph_bool_t keep_only_largest, igraph_bool_t complementer) { igraph_i_max_ind_vsets_data_t clqdata; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (igraph_is_directed(graph)) { IGRAPH_WARNING("Edge directions are ignored for largest independent vertex set or clique calculations."); @@ -1005,6 +1066,9 @@ static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets(const igrap clqdata.matrix_size = no_of_nodes; clqdata.keep_only_largest = keep_only_largest; + clqdata.min_size = 0; + clqdata.max_size = IGRAPH_INTEGER_MAX; + clqdata.max_results = IGRAPH_INTEGER_MAX; if (complementer) { IGRAPH_CHECK(igraph_adjlist_init_complementer(graph, &clqdata.adj_list, IGRAPH_ALL, IGRAPH_NO_LOOPS)); @@ -1015,12 +1079,12 @@ static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets(const igrap } IGRAPH_FINALLY(igraph_adjlist_destroy, &clqdata.adj_list); - clqdata.IS = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + clqdata.IS = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(clqdata.IS, "Insufficient memory for largest independent sets or cliques."); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INT_INIT_FINALLY(&clqdata.deg, no_of_nodes); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(clqdata.deg)[i] = igraph_vector_int_size(igraph_adjlist_get(&clqdata.adj_list, i)); } @@ -1028,7 +1092,7 @@ static igraph_error_t igraph_i_maximal_or_largest_cliques_or_indsets(const igrap IGRAPH_CHECK_OOM(clqdata.buckets, "Insufficient memory for largest independent sets or cliques."); IGRAPH_FINALLY(free_set_array_incomplete, clqdata.buckets); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_set_init(&clqdata.buckets[i], 0)); } diff --git a/src/vendor/cigraph/src/cliques/glet.c b/src/vendor/cigraph/src/cliques/glet.c index a87a62e5ec1..3e9092aff29 100644 --- a/src/vendor/cigraph/src/cliques/glet.c +++ b/src/vendor/cigraph/src/cliques/glet.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -74,12 +74,12 @@ typedef struct { igraph_vector_int_t *resultids; igraph_t *result; igraph_vector_t *resultweights; - igraph_integer_t nc; + igraph_int_t nc; } igraph_i_subclique_next_free_t; static void igraph_i_subclique_next_free(void *ptr) { igraph_i_subclique_next_free_t *data = ptr; - igraph_integer_t i; + igraph_int_t i; if (data->resultids) { for (i = 0; i < data->nc; i++) { igraph_vector_int_destroy(&data->resultids[i]); @@ -136,9 +136,9 @@ static igraph_error_t igraph_i_subclique_next(const igraph_t *graph, igraph_vector_int_t mark, map; igraph_vector_int_t edges; igraph_vector_int_t neis, newedges; - igraph_integer_t c, nc = igraph_vector_int_list_size(cliques); - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t c, nc = igraph_vector_int_list_size(cliques); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_i_subclique_next_free_t freedata = { NULL, NULL, NULL, nc }; if (igraph_vector_size(weights) != no_of_edges) { @@ -182,8 +182,8 @@ static igraph_error_t igraph_i_subclique_next(const igraph_t *graph, for (c = 0; c < nc; c++) { igraph_vector_int_t *clique = igraph_vector_int_list_get_ptr(cliques, c); igraph_real_t minweight = IGRAPH_INFINITY, nextweight = IGRAPH_INFINITY; - igraph_integer_t e, v, clsize = igraph_vector_int_size(clique); - igraph_integer_t noe, nov = 0; + igraph_int_t e, v, clsize = igraph_vector_int_size(clique); + igraph_int_t noe, nov = 0; igraph_vector_int_t *newids = (*resultids) + c; igraph_vector_t *neww = (*resultweights) + c; igraph_t *newgraph = (*result) + c; @@ -199,13 +199,13 @@ static igraph_error_t igraph_i_subclique_next(const igraph_t *graph, the clique and the next edge weight if any. */ for (v = 0; v < clsize; v++) { - igraph_integer_t i, neilen, node = VECTOR(*clique)[v]; + igraph_int_t i, neilen, node = VECTOR(*clique)[v]; IGRAPH_CHECK(igraph_incident(graph, &neis, node, IGRAPH_ALL, IGRAPH_LOOPS)); neilen = igraph_vector_int_size(&neis); VECTOR(mark)[node] = c + 1; for (i = 0; i < neilen; i++) { - igraph_integer_t edge = VECTOR(neis)[i]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, node); + igraph_int_t edge = VECTOR(neis)[i]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, node); if (VECTOR(mark)[nei] == c + 1) { igraph_real_t w = VECTOR(*weights)[edge]; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, edge)); @@ -246,8 +246,8 @@ static igraph_error_t igraph_i_subclique_next(const igraph_t *graph, noe = igraph_vector_int_size(&edges); for (e = 0; e < noe; e++) { - igraph_integer_t edge = VECTOR(edges)[e]; - igraph_integer_t from, to; + igraph_int_t edge = VECTOR(edges)[e]; + igraph_int_t from, to; igraph_real_t w = VECTOR(*weights)[edge]; IGRAPH_CHECK(igraph_edge(graph, edge, &from, &to)); if (w >= nextweight) { @@ -284,7 +284,7 @@ static igraph_error_t igraph_i_subclique_next(const igraph_t *graph, } static void igraph_i_graphlets_destroy_clique_list(igraph_vector_ptr_t *vl) { - igraph_integer_t i, n = igraph_vector_ptr_size(vl); + igraph_int_t i, n = igraph_vector_ptr_size(vl); for (i = 0; i < n; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*) VECTOR(*vl)[i]; if (v) { @@ -308,7 +308,7 @@ static igraph_error_t igraph_i_graphlets(const igraph_t *graph, 'startthr' */ igraph_vector_int_list_t mycliques; - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t subv; igraph_t subg; igraph_t *newgraphs = NULL; @@ -321,19 +321,19 @@ static igraph_error_t igraph_i_graphlets(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&subv, 0); /* We start by finding cliques at the lowest threshold */ - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { if (VECTOR(*weights)[i] >= startthr) { IGRAPH_CHECK(igraph_vector_int_push_back(&subv, i)); } } IGRAPH_CHECK(igraph_subgraph_from_edges(graph, &subg, igraph_ess_vector(&subv), /*delete_vertices=*/ 0)); IGRAPH_FINALLY(igraph_destroy, &subg); - IGRAPH_CHECK(igraph_maximal_cliques(&subg, &mycliques, /*min_size=*/ 0, /*max_size=*/ 0)); + IGRAPH_CHECK(igraph_maximal_cliques(&subg, &mycliques, /*min_size=*/ 0, /*max_size=*/ 0, IGRAPH_UNLIMITED)); igraph_destroy(&subg); igraph_vector_int_destroy(&subv); IGRAPH_FINALLY_CLEAN(2); - const igraph_integer_t nocliques = igraph_vector_int_list_size(&mycliques); + const igraph_int_t nocliques = igraph_vector_int_list_size(&mycliques); /* Get the next cliques and thresholds */ IGRAPH_VECTOR_INIT_FINALLY(&next_thr, 0); @@ -358,7 +358,7 @@ static igraph_error_t igraph_i_graphlets(const igraph_t *graph, IGRAPH_FINALLY_CLEAN(1); IGRAPH_CHECK(igraph_vector_ptr_resize(cliques, igraph_vector_ptr_size(cliques) + nocliques)); - for (igraph_integer_t i = 0, j = igraph_vector_ptr_size(cliques) - 1; i < nocliques; i++, j--) { + for (igraph_int_t i = 0, j = igraph_vector_ptr_size(cliques) - 1; i < nocliques; i++, j--) { igraph_vector_int_t *cl = IGRAPH_CALLOC(1, igraph_vector_int_t); IGRAPH_CHECK_OOM(cl, "Cannot find graphlets."); IGRAPH_FINALLY(igraph_free, cl); @@ -370,9 +370,9 @@ static igraph_error_t igraph_i_graphlets(const igraph_t *graph, VECTOR(*cliques)[j] = cl; IGRAPH_FINALLY_CLEAN(1); - const igraph_integer_t n = igraph_vector_int_size(cl); - for (igraph_integer_t k = 0; k < n; k++) { - igraph_integer_t node = VECTOR(*cl)[k]; + const igraph_int_t n = igraph_vector_int_size(cl); + for (igraph_int_t k = 0; k < n; k++) { + igraph_int_t node = VECTOR(*cl)[k]; VECTOR(*cl)[k] = VECTOR(*ids)[node]; } igraph_vector_int_sort(cl); @@ -382,7 +382,7 @@ static igraph_error_t igraph_i_graphlets(const igraph_t *graph, IGRAPH_FINALLY_CLEAN(1); /* Recursive calls for cliques found */ - for (igraph_integer_t i = 0; i < nocliques; i++) { + for (igraph_int_t i = 0; i < nocliques; i++) { igraph_t *g = newgraphs + i; if (igraph_vcount(g) > 1) { igraph_vector_t *w_sub = newweights + i; @@ -405,12 +405,12 @@ typedef struct { static int igraph_i_graphlets_filter_cmp(void *data, const void *a, const void *b) { igraph_i_graphlets_filter_t *ddata = (igraph_i_graphlets_filter_t *) data; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t t_a = VECTOR(*ddata->thresholds)[*aa]; igraph_real_t t_b = VECTOR(*ddata->thresholds)[*bb]; igraph_vector_int_t *v_a, *v_b; - igraph_integer_t s_a, s_b; + igraph_int_t s_a, s_b; if (t_a < t_b) { return -1; @@ -443,7 +443,7 @@ static igraph_error_t igraph_i_graphlets_filter(igraph_vector_ptr_t *cliques, superset, we only need to check the cliques next in the list, until their threshold is different. */ - igraph_integer_t i, iptr, nocliques = igraph_vector_ptr_size(cliques); + igraph_int_t i, iptr, nocliques = igraph_vector_ptr_size(cliques); igraph_vector_int_t order; igraph_i_graphlets_filter_t sortdata = { cliques, thresholds }; @@ -454,16 +454,16 @@ static igraph_error_t igraph_i_graphlets_filter(igraph_vector_ptr_t *cliques, igraph_i_graphlets_filter_cmp); for (i = 0; i < nocliques - 1; i++) { - igraph_integer_t ri = VECTOR(order)[i]; + igraph_int_t ri = VECTOR(order)[i]; igraph_vector_int_t *needle = VECTOR(*cliques)[ri]; igraph_real_t thr_i = VECTOR(*thresholds)[ri]; - igraph_integer_t n_i = igraph_vector_int_size(needle); + igraph_int_t n_i = igraph_vector_int_size(needle); - for (igraph_integer_t j = i + 1; j < nocliques; j++) { - igraph_integer_t rj = VECTOR(order)[j]; + for (igraph_int_t j = i + 1; j < nocliques; j++) { + igraph_int_t rj = VECTOR(order)[j]; igraph_real_t thr_j = VECTOR(*thresholds)[rj]; igraph_vector_int_t *hay; - igraph_integer_t n_j, pi = 0, pj = 0; + igraph_int_t n_j, pi = 0, pj = 0; /* Done, not found */ if (thr_j != thr_i) { @@ -479,8 +479,8 @@ static igraph_error_t igraph_i_graphlets_filter(igraph_vector_ptr_t *cliques, /* Check if hay is a superset */ while (pi < n_i && pj < n_j && n_i - pi <= n_j - pj) { - igraph_integer_t ei = VECTOR(*needle)[pi]; - igraph_integer_t ej = VECTOR(*hay)[pj]; + igraph_int_t ei = VECTOR(*needle)[pi]; + igraph_int_t ej = VECTOR(*hay)[pj]; if (ei < ej) { break; } else if (ei > ej) { @@ -540,12 +540,12 @@ igraph_error_t igraph_graphlets_candidate_basis(const igraph_t *graph, igraph_vector_int_list_t *cliques, igraph_vector_t *thresholds) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_real_t minthr; igraph_vector_int_t ids; igraph_bool_t simple; - igraph_integer_t i, no_of_cliques; + igraph_int_t i, no_of_cliques; igraph_vector_ptr_t mycliques; /* Some checks */ @@ -606,16 +606,16 @@ igraph_error_t igraph_graphlets_candidate_basis(const igraph_t *graph, igraph_error_t igraph_i_graphlets_project( const igraph_t *graph, const igraph_vector_t *weights, const igraph_vector_int_list_t *cliques, igraph_vector_t *Mu, igraph_bool_t startMu, - igraph_integer_t niter, igraph_integer_t vid1 + igraph_int_t niter, igraph_int_t vid1 ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_cliques = igraph_vector_int_list_size(cliques); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_cliques = igraph_vector_int_list_size(cliques); igraph_vector_int_t vcl, vclidx, ecl, eclidx, cel, celidx; igraph_vector_int_t edgelist; igraph_vector_t newweights, normfact; - igraph_integer_t i, total_vertices, e, ptr, total_edges; + igraph_int_t i, total_vertices, e, ptr, total_edges; igraph_bool_t simple; /* Check arguments */ @@ -647,12 +647,12 @@ igraph_error_t igraph_i_graphlets_project( IGRAPH_VECTOR_INT_INIT_FINALLY(&celidx, no_cliques + 3); for (i = 0, total_vertices = 0, total_edges = 0; i < no_cliques; i++) { igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(cliques, i); - igraph_integer_t j, n = igraph_vector_int_size(v); + igraph_int_t j, n = igraph_vector_int_size(v); total_vertices += n; total_edges += n * (n - 1) / 2; VECTOR(celidx)[i + 2] = total_edges; for (j = 0; j < n; j++) { - igraph_integer_t vv = VECTOR(*v)[j] - vid1; + igraph_int_t vv = VECTOR(*v)[j] - vid1; VECTOR(vclidx)[vv + 2] += 1; } } @@ -667,10 +667,10 @@ igraph_error_t igraph_i_graphlets_project( IGRAPH_VECTOR_INT_INIT_FINALLY(&vcl, total_vertices); for (i = 0; i < no_cliques; i++) { igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(cliques, i); - igraph_integer_t j, n = igraph_vector_int_size(v); + igraph_int_t j, n = igraph_vector_int_size(v); for (j = 0; j < n; j++) { - igraph_integer_t vv = VECTOR(*v)[j] - vid1; - igraph_integer_t p = VECTOR(vclidx)[vv + 1]; + igraph_int_t vv = VECTOR(*v)[j] - vid1; + igraph_int_t p = VECTOR(vclidx)[vv + 1]; VECTOR(vcl)[p] = i; VECTOR(vclidx)[vv + 1] += 1; } @@ -682,16 +682,16 @@ igraph_error_t igraph_i_graphlets_project( IGRAPH_VECTOR_INT_INIT_FINALLY(&edgelist, no_of_edges * 2); IGRAPH_CHECK(igraph_get_edgelist(graph, &edgelist, /*by_col=*/ 0)); for (i = 0, e = 0, ptr = 0; e < no_of_edges; e++) { - igraph_integer_t from = VECTOR(edgelist)[i++]; - igraph_integer_t to = VECTOR(edgelist)[i++]; - igraph_integer_t from_s = VECTOR(vclidx)[from]; - igraph_integer_t from_e = VECTOR(vclidx)[from + 1]; - igraph_integer_t to_s = VECTOR(vclidx)[to]; - igraph_integer_t to_e = VECTOR(vclidx)[to + 1]; + igraph_int_t from = VECTOR(edgelist)[i++]; + igraph_int_t to = VECTOR(edgelist)[i++]; + igraph_int_t from_s = VECTOR(vclidx)[from]; + igraph_int_t from_e = VECTOR(vclidx)[from + 1]; + igraph_int_t to_s = VECTOR(vclidx)[to]; + igraph_int_t to_e = VECTOR(vclidx)[to + 1]; VECTOR(eclidx)[e] = ptr; while (from_s < from_e && to_s < to_e) { - igraph_integer_t from_v = VECTOR(vcl)[from_s]; - igraph_integer_t to_v = VECTOR(vcl)[to_s]; + igraph_int_t from_v = VECTOR(vcl)[from_s]; + igraph_int_t to_v = VECTOR(vcl)[to_s]; if (from_v == to_v) { VECTOR(ecl)[ptr++] = from_v; from_s++; to_s++; @@ -710,10 +710,10 @@ igraph_error_t igraph_i_graphlets_project( /* Convert the edge-clique list to a clique-edge list */ IGRAPH_VECTOR_INT_INIT_FINALLY(&cel, total_edges); for (i = 0; i < no_of_edges; i++) { - igraph_integer_t ecl_s = VECTOR(eclidx)[i], ecl_e = VECTOR(eclidx)[i + 1], j; + igraph_int_t ecl_s = VECTOR(eclidx)[i], ecl_e = VECTOR(eclidx)[i + 1], j; for (j = ecl_s; j < ecl_e; j++) { - igraph_integer_t cl = VECTOR(ecl)[j]; - igraph_integer_t epos = VECTOR(celidx)[cl + 1]; + igraph_int_t cl = VECTOR(ecl)[j]; + igraph_int_t epos = VECTOR(celidx)[cl + 1]; VECTOR(cel)[epos] = i; VECTOR(celidx)[cl + 1] += 1; } @@ -723,7 +723,7 @@ igraph_error_t igraph_i_graphlets_project( IGRAPH_VECTOR_INIT_FINALLY(&normfact, no_cliques); for (i = 0; i < no_cliques; i++) { igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(cliques, i); - igraph_integer_t n = igraph_vector_int_size(v); + igraph_int_t n = igraph_vector_int_size(v); VECTOR(normfact)[i] = n * (n + 1) / 2; } @@ -731,20 +731,20 @@ igraph_error_t igraph_i_graphlets_project( IGRAPH_VECTOR_INIT_FINALLY(&newweights, no_of_edges); for (i = 0; i < niter; i++) { for (e = 0; e < no_of_edges; e++) { - igraph_integer_t start = VECTOR(eclidx)[e]; - igraph_integer_t end = VECTOR(eclidx)[e + 1]; + igraph_int_t start = VECTOR(eclidx)[e]; + igraph_int_t end = VECTOR(eclidx)[e + 1]; VECTOR(newweights)[e] = 0.0001; while (start < end) { - igraph_integer_t clique = VECTOR(ecl)[start++]; + igraph_int_t clique = VECTOR(ecl)[start++]; VECTOR(newweights)[e] += VECTOR(*Mu)[clique]; } } for (e = 0; e < no_cliques; e++) { igraph_real_t sumratio = 0; - igraph_integer_t start = VECTOR(celidx)[e]; - igraph_integer_t end = VECTOR(celidx)[e + 1]; + igraph_int_t start = VECTOR(celidx)[e]; + igraph_int_t end = VECTOR(celidx)[e + 1]; while (start < end) { - igraph_integer_t edge = VECTOR(cel)[start++]; + igraph_int_t edge = VECTOR(cel)[start++]; sumratio += VECTOR(*weights)[edge] / VECTOR(newweights)[edge]; } VECTOR(*Mu)[e] *= sumratio / VECTOR(normfact)[e]; @@ -797,7 +797,7 @@ igraph_error_t igraph_graphlets_project(const igraph_t *graph, const igraph_vector_t *weights, const igraph_vector_int_list_t *cliques, igraph_vector_t *Mu, igraph_bool_t startMu, - igraph_integer_t niter) { + igraph_int_t niter) { return igraph_i_graphlets_project(graph, weights, cliques, Mu, startMu, niter, /*vid1=*/ 0); @@ -810,8 +810,8 @@ typedef struct igraph_i_graphlets_order_t { static int igraph_i_graphlets_order_cmp(void *data, const void *a, const void *b) { igraph_i_graphlets_order_t *ddata = (igraph_i_graphlets_order_t*) data; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t Mu_a = VECTOR(*ddata->Mu)[*aa]; igraph_real_t Mu_b = VECTOR(*ddata->Mu)[*bb]; @@ -850,9 +850,9 @@ static int igraph_i_graphlets_order_cmp(void *data, const void *a, const void *b igraph_error_t igraph_graphlets(const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *cliques, - igraph_vector_t *Mu, igraph_integer_t niter) { + igraph_vector_t *Mu, igraph_int_t niter) { - igraph_integer_t nocliques; + igraph_int_t nocliques; igraph_vector_t thresholds; igraph_vector_int_t order; igraph_i_graphlets_order_t sortdata = { cliques, Mu }; diff --git a/src/vendor/cigraph/src/cliques/maximal_cliques.c b/src/vendor/cigraph/src/cliques/maximal_cliques.c index d392465e3e9..c841cde924c 100644 --- a/src/vendor/cigraph/src/cliques/maximal_cliques.c +++ b/src/vendor/cigraph/src/cliques/maximal_cliques.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -37,42 +37,42 @@ static igraph_error_t igraph_i_maximal_cliques_reorder_adjlists( const igraph_vector_int_t *PX, - igraph_integer_t PS, igraph_integer_t PE, igraph_integer_t XS, igraph_integer_t XE, + igraph_int_t PS, igraph_int_t PE, igraph_int_t XS, igraph_int_t XE, const igraph_vector_int_t *pos, igraph_adjlist_t *adjlist); static igraph_error_t igraph_i_maximal_cliques_select_pivot( const igraph_vector_int_t *PX, - igraph_integer_t PS, igraph_integer_t PE, igraph_integer_t XS, igraph_integer_t XE, + igraph_int_t PS, igraph_int_t PE, igraph_int_t XS, igraph_int_t XE, const igraph_vector_int_t *pos, const igraph_adjlist_t *adjlist, - igraph_integer_t *pivot, + igraph_int_t *pivot, igraph_vector_int_t *nextv, - igraph_integer_t oldPS, igraph_integer_t oldXE); + igraph_int_t oldPS, igraph_int_t oldXE); static igraph_error_t igraph_i_maximal_cliques_down( igraph_vector_int_t *PX, - igraph_integer_t PS, igraph_integer_t PE, igraph_integer_t XS, igraph_integer_t XE, + igraph_int_t PS, igraph_int_t PE, igraph_int_t XS, igraph_int_t XE, igraph_vector_int_t *pos, - igraph_adjlist_t *adjlist, igraph_integer_t mynextv, + igraph_adjlist_t *adjlist, igraph_int_t mynextv, igraph_vector_int_t *R, - igraph_integer_t *newPS, igraph_integer_t *newXE); + igraph_int_t *newPS, igraph_int_t *newXE); static igraph_error_t igraph_i_maximal_cliques_PX( - igraph_vector_int_t *PX, igraph_integer_t PS, igraph_integer_t *PE, - igraph_integer_t *XS, igraph_integer_t XE, igraph_vector_int_t *pos, - igraph_adjlist_t *adjlist, igraph_integer_t v, + igraph_vector_int_t *PX, igraph_int_t PS, igraph_int_t *PE, + igraph_int_t *XS, igraph_int_t XE, igraph_vector_int_t *pos, + igraph_adjlist_t *adjlist, igraph_int_t v, igraph_vector_int_t *H); static igraph_error_t igraph_i_maximal_cliques_up( - igraph_vector_int_t *PX, igraph_integer_t PS, igraph_integer_t PE, - igraph_integer_t XS, igraph_integer_t XE, igraph_vector_int_t *pos, + igraph_vector_int_t *PX, igraph_int_t PS, igraph_int_t PE, + igraph_int_t XS, igraph_int_t XE, igraph_vector_int_t *pos, igraph_adjlist_t *adjlist, igraph_vector_int_t *R, igraph_vector_int_t *H); #define PRINT_PX do { \ - igraph_integer_t j; \ + igraph_int_t j; \ printf("PX="); \ for (j=0; j= sPS && avneipos <= sPE) { if (pp != avnei) { - igraph_integer_t tmp = *avnei; + igraph_int_t tmp = *avnei; *avnei = *pp; *pp = tmp; } @@ -150,37 +150,37 @@ static igraph_error_t igraph_i_maximal_cliques_reorder_adjlists( static igraph_error_t igraph_i_maximal_cliques_select_pivot( const igraph_vector_int_t *PX, - igraph_integer_t PS, igraph_integer_t PE, - igraph_integer_t XS, igraph_integer_t XE, + igraph_int_t PS, igraph_int_t PE, + igraph_int_t XS, igraph_int_t XE, const igraph_vector_int_t *pos, const igraph_adjlist_t *adjlist, - igraph_integer_t *pivot, + igraph_int_t *pivot, igraph_vector_int_t *nextv, - igraph_integer_t oldPS, igraph_integer_t oldXE) { + igraph_int_t oldPS, igraph_int_t oldXE) { igraph_vector_int_t *pivotvectneis; - igraph_integer_t j, pivotvectlen; - igraph_integer_t i, usize = -1; - igraph_integer_t soldPS = oldPS + 1, soldXE = oldXE + 1, sPS = PS + 1, sPE = PE + 1; + igraph_int_t j, pivotvectlen; + igraph_int_t i, usize = -1; + igraph_int_t soldPS = oldPS + 1, soldXE = oldXE + 1, sPS = PS + 1, sPE = PE + 1; IGRAPH_UNUSED(XS); /* Choose a pivotvect, and bring up P vertices at the same time */ for (i = PS; i <= XE; i++) { - igraph_integer_t av = VECTOR(*PX)[i]; + igraph_int_t av = VECTOR(*PX)[i]; igraph_vector_int_t *avneis = igraph_adjlist_get(adjlist, av); - igraph_integer_t *avp = VECTOR(*avneis); - igraph_integer_t avlen = igraph_vector_int_size(avneis); - igraph_integer_t *ave = avp + avlen; - igraph_integer_t *avnei = avp, *pp = avp; + igraph_int_t *avp = VECTOR(*avneis); + igraph_int_t avlen = igraph_vector_int_size(avneis); + igraph_int_t *ave = avp + avlen; + igraph_int_t *avnei = avp, *pp = avp; for (; avnei < ave; avnei++) { - igraph_integer_t avneipos = VECTOR(*pos)[(*avnei)]; + igraph_int_t avneipos = VECTOR(*pos)[(*avnei)]; if (avneipos < soldPS || avneipos > soldXE) { break; } if (avneipos >= sPS && avneipos <= sPE) { if (pp != avnei) { - igraph_integer_t tmp = *avnei; + igraph_int_t tmp = *avnei; *avnei = *pp; *pp = tmp; } @@ -198,12 +198,12 @@ static igraph_error_t igraph_i_maximal_cliques_select_pivot( pivotvectlen = igraph_vector_int_size(pivotvectneis); for (j = PS; j <= PE; j++) { - igraph_integer_t vcand = VECTOR(*PX)[j]; + igraph_int_t vcand = VECTOR(*PX)[j]; igraph_bool_t nei = false; - igraph_integer_t k = 0; + igraph_int_t k = 0; for (k = 0; k < pivotvectlen; k++) { - igraph_integer_t unv = VECTOR(*pivotvectneis)[k]; - igraph_integer_t unvpos = VECTOR(*pos)[unv]; + igraph_int_t unv = VECTOR(*pivotvectneis)[k]; + igraph_int_t unvpos = VECTOR(*pos)[unv]; if (unvpos < sPS || unvpos > sPE) { break; } @@ -221,8 +221,8 @@ static igraph_error_t igraph_i_maximal_cliques_select_pivot( } #define SWAP(p1,p2) do { \ - igraph_integer_t v1=VECTOR(*PX)[p1]; \ - igraph_integer_t v2=VECTOR(*PX)[p2]; \ + igraph_int_t v1=VECTOR(*PX)[p1]; \ + igraph_int_t v2=VECTOR(*PX)[p2]; \ VECTOR(*PX)[p1] = v2; \ VECTOR(*PX)[p2] = v1; \ VECTOR(*pos)[v1] = (p2)+1; \ @@ -230,21 +230,21 @@ static igraph_error_t igraph_i_maximal_cliques_select_pivot( } while (0) static igraph_error_t igraph_i_maximal_cliques_down(igraph_vector_int_t *PX, - igraph_integer_t PS, igraph_integer_t PE, - igraph_integer_t XS, igraph_integer_t XE, + igraph_int_t PS, igraph_int_t PE, + igraph_int_t XS, igraph_int_t XE, igraph_vector_int_t *pos, - igraph_adjlist_t *adjlist, igraph_integer_t mynextv, + igraph_adjlist_t *adjlist, igraph_int_t mynextv, igraph_vector_int_t *R, - igraph_integer_t *newPS, igraph_integer_t *newXE) { + igraph_int_t *newPS, igraph_int_t *newXE) { igraph_vector_int_t *vneis = igraph_adjlist_get(adjlist, mynextv); - igraph_integer_t j, vneislen = igraph_vector_int_size(vneis); - igraph_integer_t sPS = PS + 1, sPE = PE + 1, sXS = XS + 1, sXE = XE + 1; + igraph_int_t j, vneislen = igraph_vector_int_size(vneis); + igraph_int_t sPS = PS + 1, sPE = PE + 1, sXS = XS + 1, sXE = XE + 1; *newPS = PE + 1; *newXE = XS - 1; for (j = 0; j < vneislen; j++) { - igraph_integer_t vnei = VECTOR(*vneis)[j]; - igraph_integer_t vneipos = VECTOR(*pos)[vnei]; + igraph_int_t vnei = VECTOR(*vneis)[j]; + igraph_int_t vneipos = VECTOR(*pos)[vnei]; if (vneipos >= sPS && vneipos <= sPE) { (*newPS)--; SWAP(vneipos - 1, *newPS); @@ -262,13 +262,13 @@ static igraph_error_t igraph_i_maximal_cliques_down(igraph_vector_int_t *PX, #undef SWAP static igraph_error_t igraph_i_maximal_cliques_PX(igraph_vector_int_t *PX, - igraph_integer_t PS, igraph_integer_t *PE, igraph_integer_t *XS, igraph_integer_t XE, - igraph_vector_int_t *pos, igraph_adjlist_t *adjlist, igraph_integer_t v, + igraph_int_t PS, igraph_int_t *PE, igraph_int_t *XS, igraph_int_t XE, + igraph_vector_int_t *pos, igraph_adjlist_t *adjlist, igraph_int_t v, igraph_vector_int_t *H ) { - igraph_integer_t vpos = VECTOR(*pos)[v] - 1; - igraph_integer_t tmp = VECTOR(*PX)[*PE]; + igraph_int_t vpos = VECTOR(*pos)[v] - 1; + igraph_int_t tmp = VECTOR(*PX)[*PE]; IGRAPH_UNUSED(PS); IGRAPH_UNUSED(XE); @@ -285,13 +285,13 @@ static igraph_error_t igraph_i_maximal_cliques_PX(igraph_vector_int_t *PX, } static igraph_error_t igraph_i_maximal_cliques_up( - igraph_vector_int_t *PX, igraph_integer_t PS, igraph_integer_t PE, - igraph_integer_t XS, igraph_integer_t XE, igraph_vector_int_t *pos, + igraph_vector_int_t *PX, igraph_int_t PS, igraph_int_t PE, + igraph_int_t XS, igraph_int_t XE, igraph_vector_int_t *pos, igraph_adjlist_t *adjlist, igraph_vector_int_t *R, igraph_vector_int_t *H ) { - igraph_integer_t vv; + igraph_int_t vv; IGRAPH_UNUSED(PS); IGRAPH_UNUSED(PE); @@ -301,8 +301,8 @@ static igraph_error_t igraph_i_maximal_cliques_up( igraph_vector_int_pop_back(R); while ((vv = igraph_vector_int_pop_back(H)) != -1) { - igraph_integer_t vvpos = VECTOR(*pos)[vv]; - igraph_integer_t tmp = VECTOR(*PX)[XS]; + igraph_int_t vvpos = VECTOR(*pos)[vv]; + igraph_int_t tmp = VECTOR(*PX)[XS]; VECTOR(*PX)[XS] = vv; VECTOR(*PX)[vvpos - 1] = tmp; VECTOR(*pos)[vv] = XS + 1; @@ -313,6 +313,19 @@ static igraph_error_t igraph_i_maximal_cliques_up( return IGRAPH_SUCCESS; } + +/* igraph_maximal_cliques */ + +igraph_error_t igraph_i_maximal_cliques( + const igraph_t *graph, + igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +#define IGRAPH_MC_ORIG +#include "maximal_cliques_template.h" +#undef IGRAPH_MC_ORIG + /** * \function igraph_maximal_cliques * \brief Finds all maximal cliques in a graph. @@ -348,6 +361,8 @@ static igraph_error_t igraph_i_maximal_cliques_up( * returned. If negative or zero, no lower bound will be used. * \param max_size Integer giving the maximum size of the cliques to be * returned. If negative or zero, no upper bound will be used. + * \param max_results At most this many cliques will be recorded. If + * negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_maximal_independent_vertex_sets() to find maximal @@ -362,13 +377,25 @@ static igraph_error_t igraph_i_maximal_cliques_up( */ igraph_error_t igraph_maximal_cliques( - const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t min_size, igraph_integer_t max_size -); + const igraph_t *graph, + igraph_vector_int_list_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results) { + return igraph_i_maximal_cliques(graph, res, min_size, max_size, max_results); +} -#define IGRAPH_MC_ORIG + +/* igraph_maximal_cliques_count */ + +igraph_error_t igraph_i_maximal_cliques_count( + const igraph_t *graph, + igraph_int_t *res, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +#define IGRAPH_MC_COUNT #include "maximal_cliques_template.h" -#undef IGRAPH_MC_ORIG +#undef IGRAPH_MC_COUNT /** * \function igraph_maximal_cliques_count @@ -377,7 +404,7 @@ igraph_error_t igraph_maximal_cliques( * See \ref igraph_maximal_cliques() for details. * * \param graph The input graph. Edge directions are ignored. - * \param res Pointer to an \c igraph_integer_t; the number of maximal + * \param res Pointer to an \c igraph_int_t; the number of maximal * cliques will be stored here. * \param min_size Integer giving the minimum size of the cliques to be * returned. If negative or zero, no lower bound will be used. @@ -393,14 +420,24 @@ igraph_error_t igraph_maximal_cliques( * \example examples/simple/igraph_maximal_cliques.c */ -igraph_error_t igraph_maximal_cliques_count(const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t min_size, - igraph_integer_t max_size); +igraph_error_t igraph_maximal_cliques_count( + const igraph_t *graph, + igraph_int_t *res, + igraph_int_t min_size, igraph_int_t max_size) { + return igraph_i_maximal_cliques_count(graph, res, min_size, max_size, IGRAPH_UNLIMITED); +} + +/* igraph_maximal_cliques_file */ -#define IGRAPH_MC_COUNT +igraph_error_t igraph_i_maximal_cliques_file( + const igraph_t *graph, + FILE *outfile, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +#define IGRAPH_MC_FILE #include "maximal_cliques_template.h" -#undef IGRAPH_MC_COUNT +#undef IGRAPH_MC_FILE /** * \function igraph_maximal_cliques_file @@ -416,6 +453,8 @@ igraph_error_t igraph_maximal_cliques_count(const igraph_t *graph, * returned. If negative or zero, no lower bound will be used. * \param max_size Integer giving the maximum size of the cliques to be * returned. If negative or zero, no upper bound will be used. + * \param max_results At most this many cliques will be output. If + * negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_maximal_cliques(). @@ -425,14 +464,26 @@ igraph_error_t igraph_maximal_cliques_count(const igraph_t *graph, * */ -igraph_error_t igraph_maximal_cliques_file(const igraph_t *graph, - FILE *outfile, - igraph_integer_t min_size, - igraph_integer_t max_size); +igraph_error_t igraph_maximal_cliques_file( + const igraph_t *graph, + FILE *outfile, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results) { + return igraph_i_maximal_cliques_file(graph, outfile, min_size, max_size, max_results); +} -#define IGRAPH_MC_FILE + +/* igraph_maximal_cliques_subset */ + +igraph_error_t igraph_i_maximal_cliques_subset( + const igraph_t *graph, const igraph_vector_int_t *subset, + igraph_vector_int_list_t *res, igraph_int_t *no, + FILE *outfile, igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +#define IGRAPH_MC_FULL #include "maximal_cliques_template.h" -#undef IGRAPH_MC_FILE +#undef IGRAPH_MC_FULL /** * \function igraph_maximal_cliques_subset @@ -447,7 +498,7 @@ igraph_error_t igraph_maximal_cliques_file(const igraph_t *graph, * subset of initial vertices. * \param res Pointer to a list of integer vectors; the cliques will be * stored here. - * \param no Pointer to an \c igraph_integer_t; the number of maximal + * \param no Pointer to an \c igraph_int_t; the number of maximal * cliques will be stored here. * \param outfile Pointer to an output file or \c NULL. * When not \c NULL, the file should be writable. @@ -455,6 +506,8 @@ igraph_error_t igraph_maximal_cliques_file(const igraph_t *graph, * returned. If negative or zero, no lower bound will be used. * \param max_size Integer giving the maximum size of the cliques to be * returned. If negative or zero, no upper bound will be used. + * \param max_results At most this many cliques will be recorded. If + * negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_maximal_cliques(). @@ -465,15 +518,25 @@ igraph_error_t igraph_maximal_cliques_file(const igraph_t *graph, */ igraph_error_t igraph_maximal_cliques_subset( - const igraph_t *graph, const igraph_vector_int_t *subset, - igraph_vector_int_list_t *res, igraph_integer_t *no, - FILE *outfile, igraph_integer_t min_size, igraph_integer_t max_size -); + const igraph_t *graph, const igraph_vector_int_t *subset, + igraph_vector_int_list_t *res, igraph_int_t *no, FILE *outfile, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results) { + return igraph_i_maximal_cliques_subset(graph, subset, res, no, outfile, min_size, max_size, max_results); +} -#define IGRAPH_MC_FULL -#include "maximal_cliques_template.h" -#undef IGRAPH_MC_FULL +/* igraph_maximal_cliques_callback */ + +igraph_error_t igraph_i_maximal_cliques_callback( + const igraph_t *graph, + igraph_clique_handler_t *cliquehandler_fn, void *arg, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +#define IGRAPH_MC_CALLBACK +#include "maximal_cliques_template.h" +#undef IGRAPH_MC_CALLBACK /** * \function igraph_maximal_cliques_callback @@ -503,14 +566,25 @@ igraph_error_t igraph_maximal_cliques_subset( * */ -igraph_error_t igraph_maximal_cliques_callback(const igraph_t *graph, - igraph_clique_handler_t *cliquehandler_fn, void *arg, - igraph_integer_t min_size, igraph_integer_t max_size); +igraph_error_t igraph_maximal_cliques_callback( + const igraph_t *graph, + igraph_int_t min_size, igraph_int_t max_size, + igraph_clique_handler_t *cliquehandler_fn, void *arg) { + return igraph_i_maximal_cliques_callback(graph, cliquehandler_fn, arg, min_size, max_size, IGRAPH_UNLIMITED); +} + -#define IGRAPH_MC_CALLBACK -#include "maximal_cliques_template.h" -#undef IGRAPH_MC_CALLBACK +/* igraph_maximal_cliques_hist */ +igraph_error_t igraph_i_maximal_cliques_hist( + const igraph_t *graph, + igraph_vector_t *hist, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results); + +#define IGRAPH_MC_HIST +#include "maximal_cliques_template.h" +#undef IGRAPH_MC_HIST /** * \function igraph_maximal_cliques_hist @@ -537,11 +611,9 @@ igraph_error_t igraph_maximal_cliques_callback(const igraph_t *graph, * */ -igraph_error_t igraph_maximal_cliques_hist(const igraph_t *graph, - igraph_vector_t *hist, - igraph_integer_t min_size, - igraph_integer_t max_size); - -#define IGRAPH_MC_HIST -#include "maximal_cliques_template.h" -#undef IGRAPH_MC_HIST +igraph_error_t igraph_maximal_cliques_hist( + const igraph_t *graph, + igraph_vector_t *hist, + igraph_int_t min_size, igraph_int_t max_size) { + return igraph_i_maximal_cliques_hist(graph, hist, min_size, max_size, IGRAPH_UNLIMITED); +} diff --git a/src/vendor/cigraph/src/cliques/maximal_cliques_template.h b/src/vendor/cigraph/src/cliques/maximal_cliques_template.h index 63d18c17c79..cfc5cb83d98 100644 --- a/src/vendor/cigraph/src/cliques/maximal_cliques_template.h +++ b/src/vendor/cigraph/src/cliques/maximal_cliques_template.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -36,7 +36,7 @@ #endif #ifdef IGRAPH_MC_COUNT - #define RESTYPE igraph_integer_t *res + #define RESTYPE igraph_int_t *res #define RESNAME res #define SUFFIX _count #define RECORD (*res)++ @@ -61,7 +61,7 @@ #define RESTYPE \ const igraph_vector_int_t *subset, \ igraph_vector_int_list_t *res, \ - igraph_integer_t *no, \ + igraph_int_t *no, \ FILE *outfile #define RESNAME subset, res, no, outfile #define SUFFIX _subset @@ -113,10 +113,10 @@ #define RESNAME hist #define SUFFIX _hist #define RECORD do { \ - igraph_integer_t hsize = igraph_vector_size(hist); \ + igraph_int_t hsize = igraph_vector_size(hist); \ if (clsize > hsize) { \ - igraph_integer_t hcapacity = igraph_vector_capacity(hist); \ - igraph_integer_t j; \ + igraph_int_t hcapacity = igraph_vector_capacity(hist); \ + igraph_int_t j; \ igraph_error_t err; \ if (hcapacity < clsize && clsize < 2*hcapacity) \ err = igraph_vector_reserve(hist, 2*hcapacity); \ @@ -137,15 +137,16 @@ #endif static igraph_error_t FUNCTION(igraph_i_maximal_cliques_bk, SUFFIX)( - igraph_vector_int_t *PX, igraph_integer_t PS, igraph_integer_t PE, - igraph_integer_t XS, igraph_integer_t XE, igraph_integer_t oldPS, igraph_integer_t oldXE, - igraph_vector_int_t *R, - igraph_vector_int_t *pos, - igraph_adjlist_t *adjlist, - RESTYPE, - igraph_vector_int_t *nextv, - igraph_vector_int_t *H, - igraph_integer_t min_size, igraph_integer_t max_size) { + igraph_vector_int_t *PX, igraph_int_t PS, igraph_int_t PE, + igraph_int_t XS, igraph_int_t XE, igraph_int_t oldPS, igraph_int_t oldXE, + igraph_vector_int_t *R, + igraph_vector_int_t *pos, + igraph_adjlist_t *adjlist, + RESTYPE, + igraph_vector_int_t *nextv, + igraph_vector_int_t *H, + igraph_int_t min_size, igraph_int_t max_size, + igraph_int_t max_results, igraph_int_t *result_count) { igraph_error_t err; @@ -153,18 +154,22 @@ static igraph_error_t FUNCTION(igraph_i_maximal_cliques_bk, SUFFIX)( if (PS > PE && XS > XE) { /* Found a maximum clique, report it */ - igraph_integer_t clsize = igraph_vector_int_size(R); + igraph_int_t clsize = igraph_vector_int_size(R); if (min_size <= clsize && (clsize <= max_size || max_size <= 0)) { RECORD; + *result_count += 1; + if (max_results >= 0 && *result_count == max_results) { + return IGRAPH_STOP; + } } } else if (PS <= PE) { /* Select a pivot element */ - igraph_integer_t pivot, mynextv; + igraph_int_t pivot, mynextv; IGRAPH_CHECK(igraph_i_maximal_cliques_select_pivot( PX, PS, PE, XS, XE, pos, adjlist, &pivot, nextv, oldPS, oldXE )); while ((mynextv = igraph_vector_int_pop_back(nextv)) != -1) { - igraph_integer_t newPS, newXE; + igraph_int_t newPS, newXE; /* Going down, prepare */ IGRAPH_CHECK(igraph_i_maximal_cliques_down( @@ -174,7 +179,8 @@ static igraph_error_t FUNCTION(igraph_i_maximal_cliques_bk, SUFFIX)( err = FUNCTION(igraph_i_maximal_cliques_bk, SUFFIX)( PX, newPS, PE, XS, newXE, PS, XE, R, pos, adjlist, RESNAME, nextv, H, - min_size, max_size); + min_size, max_size, + max_results, result_count); if (err == IGRAPH_STOP) { return err; @@ -196,21 +202,23 @@ static igraph_error_t FUNCTION(igraph_i_maximal_cliques_bk, SUFFIX)( return IGRAPH_SUCCESS; } -igraph_error_t FUNCTION(igraph_maximal_cliques, SUFFIX)( +igraph_error_t FUNCTION(igraph_i_maximal_cliques, SUFFIX)( const igraph_t *graph, RESTYPE, - igraph_integer_t min_size, - igraph_integer_t max_size) { + igraph_int_t min_size, + igraph_int_t max_size, + igraph_int_t max_results) { /* Implementation details. TODO */ - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t PX, R, H, pos, nextv; igraph_vector_int_t coreness; igraph_vector_int_t order; igraph_vector_int_t rank; /* TODO: this is not needed */ - igraph_integer_t i, ii, nn; + igraph_int_t i, ii, nn; igraph_adjlist_t adjlist, fulladjlist; + igraph_int_t result_count = 0; igraph_real_t pgreset = round(no_of_nodes / 100.0), pg = pgreset, pgc = 0; igraph_error_t err; @@ -220,13 +228,19 @@ igraph_error_t FUNCTION(igraph_maximal_cliques, SUFFIX)( IGRAPH_WARNING("Edge directions are ignored for maximal clique calculations."); } + PREPARE; + + if (max_results == 0) { + return IGRAPH_SUCCESS; + } + IGRAPH_VECTOR_INT_INIT_FINALLY(&order, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&rank, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&coreness, no_of_nodes); IGRAPH_CHECK(igraph_coreness(graph, &coreness, /*mode=*/ IGRAPH_ALL)); IGRAPH_CHECK(igraph_vector_int_sort_ind(&coreness, &order, IGRAPH_ASCENDING)); for (ii = 0; ii < no_of_nodes; ii++) { - igraph_integer_t v = VECTOR(order)[ii]; + igraph_int_t v = VECTOR(order)[ii]; VECTOR(rank)[v] = ii; } @@ -245,15 +259,13 @@ igraph_error_t FUNCTION(igraph_maximal_cliques, SUFFIX)( IGRAPH_VECTOR_INT_INIT_FINALLY(&pos, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&nextv, 100); - PREPARE; - FOR_LOOP_OVER_VERTICES { - igraph_integer_t v; - igraph_integer_t vrank; + igraph_int_t v; + igraph_int_t vrank; igraph_vector_int_t *vneis; - igraph_integer_t vdeg; - igraph_integer_t Pptr, Xptr, PS, PE, XS, XE; - igraph_integer_t j; + igraph_int_t vdeg; + igraph_int_t Pptr, Xptr, PS, PE, XS, XE; + igraph_int_t j; FOR_LOOP_OVER_VERTICES_PREPARE; @@ -286,7 +298,7 @@ igraph_error_t FUNCTION(igraph_maximal_cliques, SUFFIX)( VECTOR(R)[0] = v; for (j = 0; j < vdeg; j++) { - igraph_integer_t vx = VECTOR(*vneis)[j]; + igraph_int_t vx = VECTOR(*vneis)[j]; if (VECTOR(rank)[vx] > vrank) { VECTOR(PX)[Pptr] = vx; VECTOR(pos)[vx] = Pptr + 1; @@ -308,14 +320,14 @@ igraph_error_t FUNCTION(igraph_maximal_cliques, SUFFIX)( igraph_adjlist_get(&fulladjlist, v) )); for (j = 0; j <= vdeg - 1; j++) { - igraph_integer_t vv = VECTOR(PX)[j]; + igraph_int_t vv = VECTOR(PX)[j]; igraph_vector_int_t *fadj = igraph_adjlist_get(&fulladjlist, vv); igraph_vector_int_t *radj = igraph_adjlist_get(&adjlist, vv); - igraph_integer_t k, fn = igraph_vector_int_size(fadj); + igraph_int_t k, fn = igraph_vector_int_size(fadj); igraph_vector_int_clear(radj); for (k = 0; k < fn; k++) { - igraph_integer_t nei = VECTOR(*fadj)[k]; - igraph_integer_t neipos = VECTOR(pos)[nei] - 1; + igraph_int_t nei = VECTOR(*fadj)[k]; + igraph_int_t neipos = VECTOR(pos)[nei] - 1; if (neipos >= PS && neipos <= XE) { IGRAPH_CHECK(igraph_vector_int_push_back(radj, nei)); } @@ -329,8 +341,8 @@ igraph_error_t FUNCTION(igraph_maximal_cliques, SUFFIX)( err = FUNCTION(igraph_i_maximal_cliques_bk, SUFFIX)( &PX, PS, PE, XS, XE, PS, XE, &R, &pos, - &adjlist, RESNAME, &nextv, &H, min_size, - max_size); + &adjlist, RESNAME, &nextv, &H, + min_size, max_size, max_results, &result_count); if (err == IGRAPH_STOP) { break; } else { diff --git a/src/vendor/cigraph/src/community/community_internal.h b/src/vendor/cigraph/src/community/community_internal.h new file mode 100644 index 00000000000..4282547f674 --- /dev/null +++ b/src/vendor/cigraph/src/community/community_internal.h @@ -0,0 +1,34 @@ +/* + igraph library. + Copyright (C) 2025 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 . +*/ + +#ifndef IGRAPH_COMMUNITY_INTERNAL_H +#define IGRAPH_COMMUNITY_INTERNAL_H + +#include "igraph_decls.h" +#include "igraph_vector.h" + +IGRAPH_BEGIN_C_DECLS + +igraph_error_t igraph_i_reindex_membership_large( + igraph_vector_int_t *membership, + igraph_vector_int_t *new_to_old, + igraph_int_t *nb_clusters); + +IGRAPH_END_C_DECLS + +#endif /* IGRAPH_COMMUNITY_INTERNAL_H */ diff --git a/src/vendor/cigraph/src/community/community_misc.c b/src/vendor/cigraph/src/community/community_misc.c index c2319f03a68..6072da658a9 100644 --- a/src/vendor/cigraph/src/community/community_misc.c +++ b/src/vendor/cigraph/src/community/community_misc.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -20,6 +20,8 @@ #include "igraph_memory.h" #include "igraph_sparsemat.h" +#include "community/community_internal.h" + #include #include @@ -49,42 +51,44 @@ /** * \function igraph_community_to_membership - * \brief Creates a membership vector from a community structure dendrogram. + * \brief Cut a dendrogram after a given number of merges. * - * This function creates a membership vector from a community - * structure dendrogram. A membership vector contains for each vertex - * the id of its graph component, the graph components are numbered - * from zero, see the same argument of \ref igraph_connected_components() - * for an example of a membership vector. + * This function creates a membership vector from a dendrogram whose leaves + * are individual vertices by cutting it at the specified level. It produces + * a membership vector that contains for each vertex its cluster ID, numbered + * from zero. This is the same membership vector format that is produced by + * \ref igraph_connected_components(), as well as all community detection + * functions in igraph. * * - * Many community detection algorithms return with a \em merges - * matrix, \ref igraph_community_walktrap() and \ref - * igraph_community_edge_betweenness() are two examples. The matrix - * contains the merge operations performed while mapping the - * hierarchical structure of a network. If the matrix has \c n-1 rows, - * where \c n is the number of vertices in the graph, then it contains - * the hierarchical structure of the whole network and it is called a - * dendrogram. + * It takes as input the number of vertices \p n, and a \p merges matrix + * encoding the dendrogram, in the format produced by hierarchical clustering + * functions such as \ref igraph_community_edge_betweenness(), + * \ref igraph_community_walktrap() or \ref igraph_community_fastgreedy(). + * The matrix must have two columns and up to n - 1 rows. + * Each row represents merging two dendrogram nodes into their parent node. + * The leaf nodes of the dendrogram are indexed from 0 to n - 1 + * and are identical to the vertices of the graph that is being partitioned + * into communities. Row \c i contains the children of dendrogram node + * with index n + i. * * * This function performs \p steps merge operations as prescribed by - * the \p merges matrix and returns the current state of the network. + * the \p merges matrix and returns the resulting partitioning into + * n - steps communities. * * * If \p merges is not a complete dendrogram, it is possible to * take \p steps steps if \p steps is not bigger than the number * lines in \p merges. * - * \param merges The two-column matrix containing the merge - * operations. See \ref igraph_community_walktrap() for the - * detailed syntax. + * \param merges The two-column matrix containing the merge operations. * \param nodes The number of leaf nodes in the dendrogram. * \param steps Integer constant, the number of steps to take. * \param membership Pointer to an initialized vector, the membership - * results will be stored here, if not NULL. The vector will be + * results will be stored here, if not \c NULL. The vector will be * resized as needed. - * \param csize Pointer to an initialized vector, or NULL. If not NULL + * \param csize Pointer to an initialized vector, or \c NULL. If not \c NULL * then the sizes of the components will be stored here, the vector * will be resized as needed. * \return Error code. @@ -92,19 +96,21 @@ * \sa \ref igraph_community_walktrap(), \ref * igraph_community_edge_betweenness(), \ref * igraph_community_fastgreedy() for community structure detection - * algorithms. + * algorithms producing merge matrices in this format; + * \ref igraph_le_community_to_membership() to perform merges + * starting from a given cluster assignment. * * Time complexity: O(|V|), the number of vertices in the graph. */ igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, - igraph_integer_t nodes, - igraph_integer_t steps, + igraph_int_t nodes, + igraph_int_t steps, igraph_vector_int_t *membership, igraph_vector_int_t *csize) { - const igraph_integer_t no_of_nodes = nodes; - const igraph_integer_t components = no_of_nodes - steps; - igraph_integer_t found = 0; + const igraph_int_t no_of_nodes = nodes; + const igraph_int_t components = no_of_nodes - steps; + igraph_int_t found = 0; igraph_vector_int_t tmp; igraph_vector_bool_t already_merged; igraph_vector_int_t own_membership; @@ -143,9 +149,9 @@ igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, IGRAPH_VECTOR_BOOL_INIT_FINALLY(&already_merged, steps + no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, steps); - for (igraph_integer_t i = steps - 1; i >= 0; i--) { - const igraph_integer_t c1 = MATRIX(*merges, i, 0); - const igraph_integer_t c2 = MATRIX(*merges, i, 1); + for (igraph_int_t i = steps - 1; i >= 0; i--) { + const igraph_int_t c1 = MATRIX(*merges, i, 0); + const igraph_int_t c2 = MATRIX(*merges, i, 1); if (VECTOR(already_merged)[c1] == 0) { VECTOR(already_merged)[c1] = true; @@ -165,7 +171,7 @@ igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, } if (c1 < no_of_nodes) { - const igraph_integer_t cid = VECTOR(tmp)[i] - 1; + const igraph_int_t cid = VECTOR(tmp)[i] - 1; if (membership) { VECTOR(*membership)[c1] = cid + 1; } @@ -177,7 +183,7 @@ igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, } if (c2 < no_of_nodes) { - const igraph_integer_t cid = VECTOR(tmp)[i] - 1; + const igraph_int_t cid = VECTOR(tmp)[i] - 1; if (membership) { VECTOR(*membership)[c2] = cid + 1; } @@ -191,21 +197,18 @@ igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, } if (membership || csize) { - /* it can never happen that csize != NULL and membership == NULL; we have - * handled that case above */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - const igraph_integer_t c = VECTOR(*membership)[i]; + /* It can never happen that csize != NULL and membership == NULL; we have + * handled that case above. Thus we skip if (membership) checks, which + * would confuse static analysers in this context. */ + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + const igraph_int_t c = VECTOR(*membership)[i]; if (c != 0) { - if (membership) { - VECTOR(*membership)[i] = c - 1; - } + VECTOR(*membership)[i] = c - 1; } else { if (csize) { VECTOR(*csize)[found] += 1; } - if (membership) { - VECTOR(*membership)[i] = found; - } + VECTOR(*membership)[i] = found; found++; } } @@ -224,21 +227,37 @@ igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, } -/* This slower implementation is used when cluster indices are not within - * the range 0..vcount-1. +/** + * This slower implementation of igraph_reindex_membership() is used when + * cluster indices are not within the range 0..vcount-1. + * + * \param membership Vector encoding the membership of each vertex. + * Elements may be arbitrary integers, however, its length must not be zero. + * \param new_to_old If not \c NULL, a mapping from new to old cluster + * indices will be stored here. + * \param nb_clusters If not \c NULL, the number of clusters will be stored here. + * + * Time complexity: O(n log(n)) where n is the membership vector length. */ -static igraph_error_t reindex_membership_large( +igraph_error_t igraph_i_reindex_membership_large( igraph_vector_int_t *membership, igraph_vector_int_t *new_to_old, - igraph_integer_t *nb_clusters) { + igraph_int_t *nb_clusters) { - const igraph_integer_t vcount = igraph_vector_int_size(membership); + const igraph_int_t vcount = igraph_vector_int_size(membership); igraph_vector_int_t permutation; - /* This implementation cannot currently handle vcount == 0, and is not - * called with such input. Assert that the input is valid as a safety - * measure. */ - IGRAPH_ASSERT(vcount > 0); + /* The vcount == 0 case requires special handling because the main + * algorithm of this function cannot handle it. */ + if (vcount == 0) { + if (new_to_old) { + igraph_vector_int_clear(new_to_old); + } + if (nb_clusters) { + *nb_clusters = 0; + } + return IGRAPH_SUCCESS; + } IGRAPH_VECTOR_INT_INIT_FINALLY(&permutation, vcount); @@ -248,16 +267,16 @@ static igraph_error_t reindex_membership_large( igraph_vector_int_clear(new_to_old); } - igraph_integer_t j = VECTOR(permutation)[0]; - igraph_integer_t c_old = VECTOR(*membership)[j]; - igraph_integer_t c_old_prev = c_old; - igraph_integer_t c_new = 0; + igraph_int_t j = VECTOR(permutation)[0]; + igraph_int_t c_old = VECTOR(*membership)[j]; + igraph_int_t c_old_prev = c_old; + igraph_int_t c_new = 0; if (new_to_old) { IGRAPH_CHECK(igraph_vector_int_push_back(new_to_old, c_old)); } VECTOR(*membership)[j] = c_new; - for (igraph_integer_t i=1; i < vcount; i++) { + for (igraph_int_t i=1; i < vcount; i++) { j = VECTOR(permutation)[i]; c_old = VECTOR(*membership)[j]; if (c_old != c_old_prev) { @@ -307,11 +326,11 @@ static igraph_error_t reindex_membership_large( igraph_error_t igraph_reindex_membership( igraph_vector_int_t *membership, igraph_vector_int_t *new_to_old, - igraph_integer_t *nb_clusters) { + igraph_int_t *nb_clusters) { - const igraph_integer_t vcount = igraph_vector_int_size(membership); + const igraph_int_t vcount = igraph_vector_int_size(membership); igraph_vector_int_t new_cluster; - igraph_integer_t i_nb_clusters; + igraph_int_t i_nb_clusters; /* First, we assume cluster indices in the range 0..vcount-1, * and attempt to use a performant implementation. If indices @@ -326,15 +345,15 @@ igraph_error_t igraph_reindex_membership( /* Clean clusters. We will store the new cluster + 1 so that membership == 0 * indicates that no cluster was assigned yet. */ i_nb_clusters = 1; - for (igraph_integer_t i = 0; i < vcount; i++) { - igraph_integer_t c = VECTOR(*membership)[i]; + for (igraph_int_t i = 0; i < vcount; i++) { + igraph_int_t c = VECTOR(*membership)[i]; if (c < 0 || c >= vcount) { /* Found cluster indices out of the 0..vcount-1 range. * Use alternative implementation that supports these. */ igraph_vector_int_destroy(&new_cluster); IGRAPH_FINALLY_CLEAN(1); - return reindex_membership_large(membership, new_to_old, nb_clusters); + return igraph_i_reindex_membership_large(membership, new_to_old, nb_clusters); } if (VECTOR(new_cluster)[c] == 0) { @@ -347,8 +366,8 @@ igraph_error_t igraph_reindex_membership( } /* Assign new membership */ - for (igraph_integer_t i = 0; i < vcount; i++) { - igraph_integer_t c = VECTOR(*membership)[i]; + for (igraph_int_t i = 0; i < vcount; i++) { + igraph_int_t c = VECTOR(*membership)[i]; VECTOR(*membership)[i] = VECTOR(new_cluster)[c] - 1; } @@ -370,8 +389,8 @@ static igraph_error_t igraph_i_compare_communities_nmi(const igraph_vector_int_t static igraph_error_t igraph_i_compare_communities_rand(const igraph_vector_int_t *v1, const igraph_vector_int_t *v2, igraph_real_t* result, igraph_bool_t adjust); static igraph_error_t igraph_i_split_join_distance(const igraph_vector_int_t *v1, - const igraph_vector_int_t *v2, igraph_integer_t* distance12, - igraph_integer_t* distance21); + const igraph_vector_int_t *v2, igraph_int_t* distance12, + igraph_int_t* distance21); /** * \ingroup communities @@ -527,7 +546,7 @@ igraph_error_t igraph_compare_communities(const igraph_vector_int_t *comm1, break; case IGRAPH_COMMCMP_SPLIT_JOIN: { - igraph_integer_t d12, d21; + igraph_int_t d12, d21; IGRAPH_CHECK(igraph_i_split_join_distance(&c1, &c2, &d12, &d21)); *result = d12 + d21; } @@ -587,10 +606,10 @@ igraph_error_t igraph_compare_communities(const igraph_vector_int_t *comm1, * * \param comm1 the membership vector of the first community structure * \param comm2 the membership vector of the second community structure - * \param distance12 pointer to an \c igraph_integer_t, the projection distance + * \param distance12 pointer to an \c igraph_int_t, the projection distance * of the first community structure from the second one will be * returned here. - * \param distance21 pointer to an \c igraph_integer_t, the projection distance + * \param distance21 pointer to an \c igraph_int_t, the projection distance * of the second community structure from the first one will be * returned here. * \return Error code. @@ -602,8 +621,8 @@ igraph_error_t igraph_compare_communities(const igraph_vector_int_t *comm1, * Time complexity: O(n log(n)). */ igraph_error_t igraph_split_join_distance(const igraph_vector_int_t *comm1, - const igraph_vector_int_t *comm2, igraph_integer_t *distance12, - igraph_integer_t *distance21) { + const igraph_vector_int_t *comm2, igraph_int_t *distance12, + igraph_int_t *distance21) { igraph_vector_int_t c1, c2; if (igraph_vector_int_size(comm1) != igraph_vector_int_size(comm2)) { @@ -638,9 +657,9 @@ igraph_error_t igraph_split_join_distance(const igraph_vector_int_t *comm1, */ static igraph_error_t igraph_i_entropy_and_mutual_information(const igraph_vector_int_t* v1, const igraph_vector_int_t* v2, double* h1, double* h2, double* mut_inf) { - igraph_integer_t i, n; - igraph_integer_t k1; - igraph_integer_t k2; + igraph_int_t i, n; + igraph_int_t k1; + igraph_int_t k2; igraph_real_t *p1, *p2; igraph_sparsemat_t m; igraph_sparsemat_t mu; /* uncompressed */ @@ -789,7 +808,7 @@ static igraph_error_t igraph_i_compare_communities_vi(const igraph_vector_int_t */ static igraph_error_t igraph_i_confusion_matrix(const igraph_vector_int_t *v1, const igraph_vector_int_t *v2, igraph_sparsemat_t *m) { - igraph_integer_t k1, k2, i, n; + igraph_int_t k1, k2, i, n; n = igraph_vector_int_size(v1); if (n == 0) { @@ -826,8 +845,8 @@ static igraph_error_t igraph_i_confusion_matrix(const igraph_vector_int_t *v1, c * and k2 are the number of clusters in each of the clusterings. */ static igraph_error_t igraph_i_split_join_distance(const igraph_vector_int_t *v1, const igraph_vector_int_t *v2, - igraph_integer_t* distance12, igraph_integer_t* distance21) { - igraph_integer_t n = igraph_vector_int_size(v1); + igraph_int_t* distance12, igraph_int_t* distance21) { + igraph_int_t n = igraph_vector_int_size(v1); igraph_vector_t rowmax, colmax; igraph_sparsemat_t m; igraph_sparsemat_t mu; /* uncompressed */ @@ -854,8 +873,8 @@ static igraph_error_t igraph_i_split_join_distance(const igraph_vector_int_t *v1 IGRAPH_CHECK(igraph_sparsemat_iterator_init(&mit, &m)); while (!igraph_sparsemat_iterator_end(&mit)) { igraph_real_t value = igraph_sparsemat_iterator_get(&mit); - igraph_integer_t row = igraph_sparsemat_iterator_row(&mit); - igraph_integer_t col = igraph_sparsemat_iterator_col(&mit); + igraph_int_t row = igraph_sparsemat_iterator_row(&mit); + igraph_int_t col = igraph_sparsemat_iterator_col(&mit); if (value > VECTOR(rowmax)[row]) { VECTOR(rowmax)[row] = value; } @@ -866,8 +885,8 @@ static igraph_error_t igraph_i_split_join_distance(const igraph_vector_int_t *v1 } /* Calculate the distances */ - *distance12 = (igraph_integer_t) (n - igraph_vector_sum(&rowmax)); - *distance21 = (igraph_integer_t) (n - igraph_vector_sum(&colmax)); + *distance12 = (igraph_int_t) (n - igraph_vector_sum(&rowmax)); + *distance21 = (igraph_int_t) (n - igraph_vector_sum(&colmax)); igraph_vector_destroy(&rowmax); igraph_vector_destroy(&colmax); @@ -907,7 +926,7 @@ static igraph_error_t igraph_i_compare_communities_rand( igraph_sparsemat_t mu; /* uncompressed */ igraph_sparsemat_iterator_t mit; igraph_vector_t rowsums, colsums; - igraph_integer_t i, nrow, ncol; + igraph_int_t i, nrow, ncol; igraph_real_t rand, n; igraph_real_t frac_pairs_in_1, frac_pairs_in_2; diff --git a/src/vendor/cigraph/src/community/edge_betweenness.c b/src/vendor/cigraph/src/community/edge_betweenness.c index 622cc705c14..d5982b3f4ad 100644 --- a/src/vendor/cigraph/src/community/edge_betweenness.c +++ b/src/vendor/cigraph/src/community/edge_betweenness.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -37,14 +37,14 @@ #include static igraph_error_t igraph_i_rewrite_membership_vector(igraph_vector_int_t *membership) { - const igraph_integer_t no = igraph_vector_int_max(membership) + 1; + const igraph_int_t no = igraph_vector_int_max(membership) + 1; igraph_vector_int_t idx; - igraph_integer_t realno = 0; - const igraph_integer_t len = igraph_vector_int_size(membership); + igraph_int_t realno = 0; + const igraph_int_t len = igraph_vector_int_size(membership); IGRAPH_VECTOR_INT_INIT_FINALLY(&idx, no); - for (igraph_integer_t i = 0; i < len; i++) { - const igraph_integer_t t = VECTOR(*membership)[i]; + for (igraph_int_t i = 0; i < len; i++) { + const igraph_int_t t = VECTOR(*membership)[i]; if (VECTOR(idx)[t]) { VECTOR(*membership)[i] = VECTOR(idx)[t] - 1; } else { @@ -68,12 +68,12 @@ static igraph_error_t igraph_i_community_eb_get_merges2(const igraph_t *graph, igraph_vector_int_t *membership) { igraph_vector_int_t mymembership; - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_real_t maxmod = -1; - igraph_integer_t midx = 0; - igraph_integer_t no_comps; + igraph_int_t midx = 0; + igraph_int_t no_comps; const igraph_bool_t use_directed = directed && igraph_is_directed(graph); - igraph_integer_t max_merges; + igraph_int_t max_merges; if (membership) { IGRAPH_CHECK(igraph_vector_int_resize(membership, no_of_nodes)); @@ -109,12 +109,12 @@ static igraph_error_t igraph_i_community_eb_get_merges2(const igraph_t *graph, VECTOR(*modularity)[0] = maxmod; } - for (igraph_integer_t i = igraph_vector_int_size(edges) - 1; i >= 0; i--) { - igraph_integer_t edge = VECTOR(*edges)[i]; - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); - igraph_integer_t c1 = VECTOR(mymembership)[from]; - igraph_integer_t c2 = VECTOR(mymembership)[to]; + for (igraph_int_t i = igraph_vector_int_size(edges) - 1; i >= 0; i--) { + igraph_int_t edge = VECTOR(*edges)[i]; + igraph_int_t from = IGRAPH_FROM(graph, edge); + igraph_int_t to = IGRAPH_TO(graph, edge); + igraph_int_t c1 = VECTOR(mymembership)[from]; + igraph_int_t c2 = VECTOR(mymembership)[to]; igraph_real_t actmod; if (c1 != c2) { /* this is a merge */ @@ -127,7 +127,7 @@ static igraph_error_t igraph_i_community_eb_get_merges2(const igraph_t *graph, } /* The new cluster has id no_of_nodes+midx+1 */ - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { if (VECTOR(mymembership)[j] == c1 || VECTOR(mymembership)[j] == c2) { VECTOR(mymembership)[j] = no_of_nodes + midx; @@ -224,13 +224,13 @@ igraph_error_t igraph_community_eb_get_merges(const igraph_t *graph, igraph_vector_t *modularity, igraph_vector_int_t *membership) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t ptr; - igraph_integer_t midx = 0; - igraph_integer_t no_comps; - const igraph_integer_t no_removed_edges = igraph_vector_int_size(edges); - igraph_integer_t max_merges; + igraph_int_t midx = 0; + igraph_int_t no_comps; + const igraph_int_t no_removed_edges = igraph_vector_int_size(edges); + igraph_int_t max_merges; if (! igraph_vector_int_isininterval(edges, 0, no_of_edges-1)) { IGRAPH_ERROR( @@ -280,9 +280,9 @@ igraph_error_t igraph_community_eb_get_merges(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(bridges, max_merges)); } - for (igraph_integer_t i = igraph_vector_int_size(edges) - 1; i >= 0; i--) { - igraph_integer_t edge = VECTOR(*edges)[i]; - igraph_integer_t from, to, c1, c2, idx; + for (igraph_int_t i = igraph_vector_int_size(edges) - 1; i >= 0; i--) { + igraph_int_t edge = VECTOR(*edges)[i]; + igraph_int_t from, to, c1, c2, idx; IGRAPH_CHECK(igraph_edge(graph, edge, &from, &to)); idx = from + 1; while (VECTOR(ptr)[idx - 1] != 0) { @@ -324,16 +324,16 @@ igraph_error_t igraph_community_eb_get_merges(const igraph_t *graph, * and the ranking is done solely based on v. * * This function requires that at least one element is active. */ -static igraph_integer_t igraph_i_which_max_active_ratio( +static igraph_int_t igraph_i_which_max_active_ratio( const igraph_vector_t *v, const igraph_vector_t *w, igraph_bitset_t *passive) { - const igraph_integer_t size = igraph_vector_size(v); - igraph_integer_t which = igraph_bitset_countr_one(passive); /* start with first active element */ + const igraph_int_t size = igraph_vector_size(v); + igraph_int_t which = igraph_bitset_countr_one(passive); /* start with first active element */ igraph_real_t max = VECTOR(*v)[which] / (w ? VECTOR(*w)[which] : 1.0); - for (igraph_integer_t i = which+1; i < size; i++) { + for (igraph_int_t i = which+1; i < size; i++) { igraph_real_t elem = VECTOR(*v)[i] / (w ? VECTOR(*w)[i] : 1.0); if (! IGRAPH_BIT_TEST(*passive, i) && elem > max) { max = elem; @@ -412,8 +412,8 @@ static igraph_integer_t igraph_i_which_max_active_ratio( * then merges performed by the algorithm are stored here. Even if * this is a divisive algorithm, we can replay it backwards and * note which two clusters were merged. Clusters are numbered from - * zero, see the \p merges argument of \ref igraph_community_walktrap() - * for details. The matrix will be resized as needed. + * zero. See \ref igraph_community_to_membership() for details. The + * matrix will be resized as needed. * \param bridges Pointer to an initialized vector of \c NULL. If not * \c NULL then the indices into \p result of all edges which caused * one of the \p merges will be put here. This is equivalent to all edge removals @@ -455,18 +455,18 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, const igraph_vector_t *weights, const igraph_vector_t *lengths) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); double *distance, *tmpscore; double *nrgeo; igraph_inclist_t elist_out, elist_in, parents; igraph_inclist_t *elist_out_p, *elist_in_p; igraph_vector_int_t *neip; - igraph_integer_t neino; + igraph_int_t neino; igraph_vector_t eb; - igraph_integer_t maxedge, pos; - igraph_integer_t from, to; + igraph_int_t maxedge, pos; + igraph_int_t from, to; igraph_bool_t result_owned = false; igraph_stack_int_t stack; igraph_real_t steps, steps_done; @@ -578,7 +578,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, steps = no_of_edges / 2.0 * (no_of_edges + 1); steps_done = 0; - for (igraph_integer_t e = 0; e < no_of_edges; steps_done += no_of_edges - e, e++) { + for (igraph_int_t e = 0; e < no_of_edges; steps_done += no_of_edges - e, e++) { IGRAPH_PROGRESS("Edge betweenness community detection: ", 100.0 * steps_done / steps, NULL); @@ -589,7 +589,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, /* The following for loop is copied almost intact from * igraph_edge_betweenness_cutoff */ - for (igraph_integer_t source = 0; source < no_of_nodes; source++) { + for (igraph_int_t source = 0; source < no_of_nodes; source++) { IGRAPH_ALLOW_INTERRUPTION(); @@ -604,13 +604,13 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, distance[source] = 0; while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); neip = igraph_inclist_get(elist_out_p, actnode); neino = igraph_vector_int_size(neip); - for (igraph_integer_t i = 0; i < neino; i++) { - igraph_integer_t edge = VECTOR(*neip)[i]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, edge, actnode); + for (igraph_int_t i = 0; i < neino; i++) { + igraph_int_t edge = VECTOR(*neip)[i]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, edge, actnode); if (nrgeo[neighbor] != 0) { /* we've already seen this node, another shortest path? */ if (distance[neighbor] == distance[actnode] + 1) { @@ -630,7 +630,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, shortest paths to them. Now we do an inverse search, starting with the farthest nodes. */ while (!igraph_stack_int_empty(&stack)) { - igraph_integer_t actnode = igraph_stack_int_pop(&stack); + igraph_int_t actnode = igraph_stack_int_pop(&stack); if (distance[actnode] < 1) { continue; /* skip source node */ } @@ -638,9 +638,9 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, /* set the temporary score of the friends */ neip = igraph_inclist_get(elist_in_p, actnode); neino = igraph_vector_int_size(neip); - for (igraph_integer_t i = 0; i < neino; i++) { - igraph_integer_t edge = VECTOR(*neip)[i]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, edge, actnode); + for (igraph_int_t i = 0; i < neino; i++) { + igraph_int_t edge = VECTOR(*neip)[i]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, edge, actnode); if (distance[neighbor] == distance[actnode] - 1 && nrgeo[neighbor] != 0) { tmpscore[neighbor] += @@ -660,7 +660,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, /* The following for loop is copied almost intact from * igraph_i_edge_betweenness_cutoff_weighted */ - for (igraph_integer_t source = 0; source < no_of_nodes; source++) { + for (igraph_int_t source = 0; source < no_of_nodes; source++) { /* This will contain the edge betweenness in the current step */ IGRAPH_ALLOW_INTERRUPTION(); @@ -673,7 +673,7 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, nrgeo[source] = 1; while (!igraph_2wheap_empty(&heap)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&heap); + igraph_int_t minnei = igraph_2wheap_max_index(&heap); igraph_real_t mindist = -igraph_2wheap_delete_max(&heap); IGRAPH_CHECK(igraph_stack_int_push(&stack, minnei)); @@ -681,9 +681,9 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, neip = igraph_inclist_get(elist_out_p, minnei); neino = igraph_vector_int_size(neip); - for (igraph_integer_t i = 0; i < neino; i++) { - igraph_integer_t edge = VECTOR(*neip)[i]; - igraph_integer_t to = IGRAPH_OTHER(graph, edge, minnei); + for (igraph_int_t i = 0; i < neino; i++) { + igraph_int_t edge = VECTOR(*neip)[i]; + igraph_int_t to = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*lengths)[edge]; igraph_real_t curdist = distance[to]; igraph_vector_int_t *v; @@ -719,13 +719,13 @@ igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, } /* igraph_2wheap_empty(&Q) */ while (!igraph_stack_int_empty(&stack)) { - igraph_integer_t w = igraph_stack_int_pop(&stack); + igraph_int_t w = igraph_stack_int_pop(&stack); igraph_vector_int_t *parv = igraph_inclist_get(&parents, w); - igraph_integer_t parv_len = igraph_vector_int_size(parv); + igraph_int_t parv_len = igraph_vector_int_size(parv); - for (igraph_integer_t i = 0; i < parv_len; i++) { - igraph_integer_t fedge = VECTOR(*parv)[i]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, fedge, w); + for (igraph_int_t i = 0; i < parv_len; i++) { + igraph_int_t fedge = VECTOR(*parv)[i]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, fedge, w); tmpscore[neighbor] += (tmpscore[w] + 1) * nrgeo[neighbor] / nrgeo[w]; VECTOR(eb)[fedge] += (tmpscore[w] + 1) * nrgeo[neighbor] / nrgeo[w]; } diff --git a/src/vendor/cigraph/src/community/fast_modularity.c b/src/vendor/cigraph/src/community/fast_modularity.c index b4b92ea7346..0b4c8a970ee 100644 --- a/src/vendor/cigraph/src/community/fast_modularity.c +++ b/src/vendor/cigraph/src/community/fast_modularity.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -70,8 +70,8 @@ /* Structure storing a pair of communities along with their dQ values */ typedef struct s_igraph_i_fastgreedy_commpair { - igraph_integer_t first; /* first member of the community pair */ - igraph_integer_t second; /* second member of the community pair */ + igraph_int_t first; /* first member of the community pair */ + igraph_int_t second; /* second member of the community pair */ igraph_real_t *dq; /* pointer to a member of the dq vector storing the */ /* increase in modularity achieved when joining */ struct s_igraph_i_fastgreedy_commpair *opposite; @@ -79,25 +79,25 @@ typedef struct s_igraph_i_fastgreedy_commpair { /* Structure storing a community */ typedef struct { - igraph_integer_t id; /* Identifier of the community (for merges matrix) */ - igraph_integer_t size; /* Size of the community */ + igraph_int_t id; /* Identifier of the community (for merges matrix) */ + igraph_int_t size; /* Size of the community */ igraph_vector_ptr_t neis; /* references to neighboring communities */ igraph_i_fastgreedy_commpair *maxdq; /* community pair with maximal dq */ } igraph_i_fastgreedy_community; /* Global community list structure */ typedef struct { - igraph_integer_t no_of_communities, n; /* number of communities, number of vertices */ + igraph_int_t no_of_communities, n; /* number of communities, number of vertices */ igraph_i_fastgreedy_community *e; /* list of communities */ igraph_i_fastgreedy_community **heap; /* heap of communities */ - igraph_integer_t *heapindex; /* heap index to speed up lookup by community idx */ + igraph_int_t *heapindex; /* heap index to speed up lookup by community idx */ } igraph_i_fastgreedy_community_list; /* Scans the community neighborhood list for the new maximal dq value. * Returns true if the maximum is different from the previous one, * false otherwise. */ static igraph_bool_t igraph_i_fastgreedy_community_rescan_max(igraph_i_fastgreedy_community *comm) { - igraph_integer_t i, n; + igraph_int_t i, n; igraph_i_fastgreedy_commpair *p, *best; igraph_real_t bestdq, currdq; @@ -129,7 +129,7 @@ static igraph_bool_t igraph_i_fastgreedy_community_rescan_max(igraph_i_fastgreed /* Destroys the global community list object */ static void igraph_i_fastgreedy_community_list_destroy( igraph_i_fastgreedy_community_list *list) { - igraph_integer_t i; + igraph_int_t i; for (i = 0; i < list->n; i++) { igraph_vector_ptr_destroy(&list->e[i].neis); } @@ -144,12 +144,12 @@ static void igraph_i_fastgreedy_community_list_destroy( /* Community list heap maintenance: sift down */ static void igraph_i_fastgreedy_community_list_sift_down( - igraph_i_fastgreedy_community_list *list, igraph_integer_t idx) { - igraph_integer_t root, child, c1, c2; + igraph_i_fastgreedy_community_list *list, igraph_int_t idx) { + igraph_int_t root, child, c1, c2; igraph_i_fastgreedy_community *dummy; - igraph_integer_t dummy2; + igraph_int_t dummy2; igraph_i_fastgreedy_community** heap = list->heap; - igraph_integer_t *heapindex = list->heapindex; + igraph_int_t *heapindex = list->heapindex; root = idx; while (root * 2 + 1 < list->no_of_communities) { @@ -179,12 +179,12 @@ static void igraph_i_fastgreedy_community_list_sift_down( /* Community list heap maintenance: sift up */ static void igraph_i_fastgreedy_community_list_sift_up( - igraph_i_fastgreedy_community_list *list, igraph_integer_t idx) { - igraph_integer_t root, parent, c1, c2; + igraph_i_fastgreedy_community_list *list, igraph_int_t idx) { + igraph_int_t root, parent, c1, c2; igraph_i_fastgreedy_community *dummy; - igraph_integer_t dummy2; + igraph_int_t dummy2; igraph_i_fastgreedy_community** heap = list->heap; - igraph_integer_t *heapindex = list->heapindex; + igraph_int_t *heapindex = list->heapindex; root = idx; while (root > 0) { @@ -211,7 +211,7 @@ static void igraph_i_fastgreedy_community_list_sift_up( /* Builds the community heap for the first time */ static void igraph_i_fastgreedy_community_list_build_heap( igraph_i_fastgreedy_community_list *list) { - igraph_integer_t i; + igraph_int_t i; for (i = list->no_of_communities / 2 - 1; i >= 0; i--) { igraph_i_fastgreedy_community_list_sift_down(list, i); } @@ -225,7 +225,7 @@ static void igraph_i_fastgreedy_community_list_build_heap( /* static void igraph_i_fastgreedy_community_list_dump_heap( igraph_i_fastgreedy_community_list *list) { - igraph_integer_t i; + igraph_int_t i; debug("Heap:\n"); for (i = 0; i < list->no_of_communities; i++) { debug("(%ld, %p, %p)", i, list->heap[i], @@ -249,7 +249,7 @@ static void igraph_i_fastgreedy_community_list_dump_heap( /* static void igraph_i_fastgreedy_community_list_check_heap( igraph_i_fastgreedy_community_list *list) { - igraph_integer_t i; + igraph_int_t i; for (i = 0; i < list->no_of_communities / 2; i++) { if ((2 * i + 1 < list->no_of_communities && *list->heap[i]->maxdq->dq < *list->heap[2 * i + 1]->maxdq->dq) || (2 * i + 2 < list->no_of_communities && *list->heap[i]->maxdq->dq < *list->heap[2 * i + 2]->maxdq->dq)) { @@ -263,9 +263,9 @@ static void igraph_i_fastgreedy_community_list_check_heap( /* Removes a given element from the heap */ static void igraph_i_fastgreedy_community_list_remove( - igraph_i_fastgreedy_community_list *list, igraph_integer_t idx) { + igraph_i_fastgreedy_community_list *list, igraph_int_t idx) { igraph_real_t old; - igraph_integer_t commidx; + igraph_int_t commidx; /* First adjust the index */ commidx = list->heap[list->no_of_communities - 1]->maxdq->first; @@ -289,8 +289,8 @@ static void igraph_i_fastgreedy_community_list_remove( /* Removes a given element from the heap when there are no more neighbors * for it (comm->maxdq is NULL) */ static void igraph_i_fastgreedy_community_list_remove2( - igraph_i_fastgreedy_community_list *list, igraph_integer_t idx, igraph_integer_t comm) { - igraph_integer_t i; + igraph_i_fastgreedy_community_list *list, igraph_int_t idx, igraph_int_t comm) { + igraph_int_t i; if (idx == list->no_of_communities - 1) { /* We removed the rightmost element on the bottom level, no problem, @@ -318,8 +318,8 @@ static void igraph_i_fastgreedy_community_list_remove2( /* Removes the pair belonging to community k from the neighborhood list * of community c (that is, clist[c]) and recalculates maxdq */ static void igraph_i_fastgreedy_community_remove_nei( - igraph_i_fastgreedy_community_list *list, igraph_integer_t c, igraph_integer_t k) { - igraph_integer_t i, n; + igraph_i_fastgreedy_community_list *list, igraph_int_t c, igraph_int_t k) { + igraph_int_t i, n; igraph_bool_t rescan = false; igraph_i_fastgreedy_commpair *p; igraph_i_fastgreedy_community *comm; @@ -363,7 +363,7 @@ static void igraph_i_fastgreedy_community_remove_nei( * `second` field */ static int igraph_i_fastgreedy_commpair_cmp(const void *p1, const void *p2) { igraph_i_fastgreedy_commpair *cp1, *cp2; - igraph_integer_t diff; + igraph_int_t diff; cp1 = *(igraph_i_fastgreedy_commpair**)p1; cp2 = *(igraph_i_fastgreedy_commpair**)p2; diff = cp1->second - cp2->second; @@ -374,10 +374,10 @@ static int igraph_i_fastgreedy_commpair_cmp(const void *p1, const void *p2) { * optimizing the process if we know that the list is nearly sorted and only * a given pair is in the wrong place. */ static void igraph_i_fastgreedy_community_sort_neighbors_of( - igraph_i_fastgreedy_community_list *list, igraph_integer_t index, + igraph_i_fastgreedy_community_list *list, igraph_int_t index, igraph_i_fastgreedy_commpair *changed_pair) { igraph_vector_ptr_t *vec; - igraph_integer_t i, n; + igraph_int_t i, n; igraph_bool_t can_skip_sort = false; igraph_i_fastgreedy_commpair *other_pair; @@ -444,7 +444,7 @@ static igraph_bool_t igraph_i_fastgreedy_community_update_dq( igraph_i_fastgreedy_community_list *list, igraph_i_fastgreedy_commpair *p, igraph_real_t newdq) { - igraph_integer_t i, j, to, from; + igraph_int_t i, j, to, from; igraph_real_t olddq; igraph_i_fastgreedy_community *comm_to, *comm_from; to = p->first; from = p->second; @@ -575,10 +575,10 @@ static igraph_bool_t igraph_i_fastgreedy_community_update_dq( * weights. Supply a null pointer here for unweighted graphs. The * weights are expected to be non-negative. * \param merges Pointer to an initialized matrix or \c NULL, the result of the - * computation is stored here. The matrix has two columns and each - * merge corresponds to one merge, the IDs of the two merged - * components are stored. The component IDs are numbered from zero and - * the first \c n components are the individual vertices, \c n is + * computation is stored here as a merges matrix representing a dendrogram. + * The matrix has two columns and each merge corresponds to one merge, the + * IDs of the two merged components are stored. The component IDs are numbered + * from zero and the first \c n components are the individual vertices, \c n is * the number of vertices in the graph. Component \c n is created * in the first merge, component n+1 in the second merge, etc. * The matrix will be resized as needed. If this argument is \c NULL @@ -592,10 +592,8 @@ static igraph_bool_t igraph_i_fastgreedy_community_update_dq( * of modularity) is stored here. * \return Error code. * - * \sa \ref igraph_community_walktrap(), \ref - * igraph_community_edge_betweenness() for other community detection - * algorithms, \ref igraph_community_to_membership() to convert the - * dendrogram to a membership vector. + * \sa \ref igraph_community_to_membership() to cut the dendrogram at + * an arbitrary number of steps. * * Time complexity: O(|E||V|log|V|) in the worst case, * O(|E|+|V|log^2|V|) typically, |V| is the number of vertices, |E| is @@ -608,8 +606,8 @@ igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, igraph_matrix_int_t *merges, igraph_vector_t *modularity, igraph_vector_int_t *membership) { - igraph_integer_t no_of_edges, no_of_nodes, no_of_joins, total_joins; - igraph_integer_t i, j, k, n, m, from, to, dummy, best_no_of_joins; + igraph_int_t no_of_edges, no_of_nodes, no_of_joins, total_joins; + igraph_int_t i, j, k, n, m, from, to, dummy, best_no_of_joins; igraph_eit_t edgeit; igraph_i_fastgreedy_commpair *pairs, *p1, *p2; igraph_i_fastgreedy_community_list communities; @@ -619,8 +617,8 @@ igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, igraph_bool_t has_multiple; igraph_matrix_int_t merges_local; - /*igraph_integer_t join_order[] = { 16,5, 5,6, 6,0, 4,0, 10,0, 26,29, 29,33, 23,33, 27,33, 25,24, 24,31, 12,3, 21,1, 30,8, 8,32, 9,2, 17,1, 11,0, 7,3, 3,2, 13,2, 1,2, 28,31, 31,33, 22,32, 18,32, 20,32, 32,33, 15,33, 14,33, 0,19, 19,2, -1,-1 };*/ - /*igraph_integer_t join_order[] = { 43,42, 42,41, 44,41, 41,36, 35,36, 37,36, 36,29, 38,29, 34,29, 39,29, 33,29, 40,29, 32,29, 14,29, 30,29, 31,29, 6,18, 18,4, 23,4, 21,4, 19,4, 27,4, 20,4, 22,4, 26,4, 25,4, 24,4, 17,4, 0,13, 13,2, 1,2, 11,2, 8,2, 5,2, 3,2, 10,2, 9,2, 7,2, 2,28, 28,15, 12,15, 29,16, 4,15, -1,-1 };*/ + /*igraph_int_t join_order[] = { 16,5, 5,6, 6,0, 4,0, 10,0, 26,29, 29,33, 23,33, 27,33, 25,24, 24,31, 12,3, 21,1, 30,8, 8,32, 9,2, 17,1, 11,0, 7,3, 3,2, 13,2, 1,2, 28,31, 31,33, 22,32, 18,32, 20,32, 32,33, 15,33, 14,33, 0,19, 19,2, -1,-1 };*/ + /*igraph_int_t join_order[] = { 43,42, 42,41, 44,41, 41,36, 35,36, 37,36, 36,29, 38,29, 34,29, 39,29, 33,29, 40,29, 32,29, 14,29, 30,29, 31,29, 6,18, 18,4, 23,4, 21,4, 19,4, 27,4, 20,4, 22,4, 26,4, 25,4, 24,4, 17,4, 0,13, 13,2, 1,2, 11,2, 8,2, 5,2, 3,2, 10,2, 9,2, 7,2, 2,28, 28,15, 12,15, 29,16, 4,15, -1,-1 };*/ no_of_nodes = igraph_vcount(graph); no_of_edges = igraph_ecount(graph); @@ -702,7 +700,7 @@ igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, IGRAPH_CHECK_OOM(communities.heap, "Insufficient memory for fast greedy community detection."); IGRAPH_FINALLY(igraph_free, communities.heap); - communities.heapindex = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + communities.heapindex = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(communities.heapindex, "Insufficient memory for fast greedy community detection."); IGRAPH_FINALLY_CLEAN(2); @@ -729,7 +727,7 @@ igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, loop_weight_sum = 0; for (i = 0, j = 0; !IGRAPH_EIT_END(edgeit); i += 2, j++, IGRAPH_EIT_NEXT(edgeit)) { - igraph_integer_t eidx = IGRAPH_EIT_GET(edgeit); + igraph_int_t eidx = IGRAPH_EIT_GET(edgeit); /* Create the pairs themselves */ from = IGRAPH_FROM(graph, eidx); to = IGRAPH_TO(graph, eidx); @@ -1014,10 +1012,10 @@ igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, * the excess rows from the merge matrix */ if (merges != NULL) { if (no_of_joins < total_joins) { - igraph_integer_t *ivec; - igraph_integer_t merges_nrow = igraph_matrix_int_nrow(merges); + igraph_int_t *ivec; + igraph_int_t merges_nrow = igraph_matrix_int_nrow(merges); - ivec = IGRAPH_CALLOC(merges_nrow, igraph_integer_t); + ivec = IGRAPH_CALLOC(merges_nrow, igraph_int_t); IGRAPH_CHECK_OOM(ivec, "Insufficient memory for fast greedy community detection."); IGRAPH_FINALLY(igraph_free, ivec); diff --git a/src/vendor/cigraph/src/community/fluid.c b/src/vendor/cigraph/src/community/fluid.c index c94800af9d6..25bbee53c85 100644 --- a/src/vendor/cigraph/src/community/fluid.c +++ b/src/vendor/cigraph/src/community/fluid.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -57,11 +57,11 @@ */ igraph_error_t igraph_community_fluid_communities( const igraph_t *graph, - igraph_integer_t no_of_communities, + igraph_int_t no_of_communities, igraph_vector_int_t *membership) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i, j, k, kv1; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i, j, k, kv1; igraph_adjlist_t al; igraph_real_t max_density; igraph_bool_t is_simple, is_connected, running; @@ -146,7 +146,7 @@ igraph_error_t igraph_community_fluid_communities( running = true; while (running) { /* Declarations of variables used inside main loop */ - igraph_integer_t v1, size, rand_idx; + igraph_int_t v1, size, rand_idx; igraph_real_t max_count, label_counter_diff; igraph_vector_int_t *neis; igraph_bool_t same_label_in_dominant; diff --git a/src/vendor/cigraph/src/community/infomap.cpp b/src/vendor/cigraph/src/community/infomap.cpp index 31d8370dc1e..4ae90e9cd72 100644 --- a/src/vendor/cigraph/src/community/infomap.cpp +++ b/src/vendor/cigraph/src/community/infomap.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -18,23 +18,22 @@ #include "igraph_community.h" -#include "igraph_error.h" +#include "config.h" + +#ifdef HAVE_INFOMAP + #include "igraph_interface.h" #include "igraph_interrupt.h" #include "core/exceptions.h" -#include "config.h" - -#ifdef HAVE_INFOMAP - #include "Infomap.h" -#endif - #include #include +#include "Infomap.h" + static igraph_error_t infomap_get_membership(infomap::InfomapBase &infomap, igraph_vector_int_t *membership) { - igraph_integer_t n = infomap.numLeafNodes(); + igraph_int_t n = infomap.numLeafNodes(); IGRAPH_CHECK(igraph_vector_int_resize(membership, n)); @@ -58,14 +57,14 @@ static igraph_error_t convert_igraph_to_infomap(const igraph_t *graph, const igraph_vector_t *vertex_weights, infomap::Network &network) { - igraph_integer_t vcount = igraph_vcount(graph); - igraph_integer_t ecount = igraph_ecount(graph); + igraph_int_t vcount = igraph_vcount(graph); + igraph_int_t ecount = igraph_ecount(graph); if (vcount > UINT_MAX) { IGRAPH_ERROR("Graph has too many vertices for Infomap.", IGRAPH_EINVAL); } - for (igraph_integer_t v = 0; v < vcount; v++) { + for (igraph_int_t v = 0; v < vcount; v++) { if (vertex_weights) { double weight = VECTOR(*vertex_weights)[v]; if (weight < 0) { @@ -82,9 +81,9 @@ static igraph_error_t convert_igraph_to_infomap(const igraph_t *graph, } } - for (igraph_integer_t e = 0; e < ecount; e++) { - igraph_integer_t v1 = IGRAPH_FROM(graph, e); - igraph_integer_t v2 = IGRAPH_TO(graph, e); + for (igraph_int_t e = 0; e < ecount; e++) { + igraph_int_t v1 = IGRAPH_FROM(graph, e); + igraph_int_t v2 = IGRAPH_TO(graph, e); if (edge_weights) { double weight = VECTOR(*edge_weights)[e]; @@ -110,6 +109,7 @@ static igraph_error_t convert_igraph_to_infomap(const igraph_t *graph, static bool infomap_allow_interruption() { return igraph_allow_interruption(); } +#endif // HAVE_INFOMAP /** * \function igraph_community_infomap @@ -125,7 +125,8 @@ static bool infomap_allow_interruption() { * either chooses out-edges to follow with probabilities proportional to edge * weights, or teleports to a random vertex with probability 0.15. Vertex weights * can be given to control the probability of choosing different vertices as - * the target of the teleportation. + * the target of the teleportation. In addition, Infomap can be regularized to + * account for potential missing links. * * * As of igraph 1.0, the Infomap library written by Daniel Edler, Anton Holmgren @@ -150,6 +151,11 @@ static bool infomap_allow_interruption() { * Eur. Phys. J. Special Topics 178, 13 (2009). * https://dx.doi.org/10.1140/epjst/e2010-01179-1, https://arxiv.org/abs/0906.1405 * + * + * Smiljanić, Jelena, Daniel Edler, and Martin Rosvall: Mapping Flows on + * Sparse Networks with Missing Links. Phys Rev E 102 (1–1): 012302 (2020). + * https://doi.org/10.1103/PhysRevE.102.012302, https://arxiv.org/abs/2106.14798 + * * \param graph The input graph. Edge directions are taken into account. * \param edge_weights Numeric vector giving the weights of the edges. * The random walker will favour edges with high weights over @@ -165,12 +171,19 @@ static bool infomap_allow_interruption() { * equal weights. Weights are expected to be positive. * \param nb_trials The number of attempts to partition the network * (can be any integer value equal to or larger than 1). + * \param is_regularized If true, adds a fully connected Bayesian prior network + * to avoid overfitting due to missing links. + * \param regularization_strength Adjust relative strength of the Bayesian prior + * network used for regularization. This multiplies the default strength, a + * parameter of 1 hence uses the default regularization strength. Ignored + * when \p is_regularized is set to \c false. * \param membership Pointer to a vector. The membership vector is * stored here. \c NULL means that the caller is not interested in the * membership vector. * \param codelength Pointer to a real. If not \c NULL the code length of the * partition is stored here. * \return Error code. + * When Infomap is not available, \c IGRAPH_UNIMPLEMENTED is returned. * * \sa \ref igraph_community_spinglass(), \ref * igraph_community_edge_betweenness(), \ref igraph_community_walktrap(). @@ -182,7 +195,9 @@ igraph_error_t igraph_community_infomap( const igraph_t *graph, const igraph_vector_t *edge_weights, const igraph_vector_t *vertex_weights, - igraph_integer_t nb_trials, + igraph_int_t nb_trials, + igraph_bool_t is_regularized, + igraph_real_t regularization_strength, igraph_vector_int_t *membership, igraph_real_t *codelength) { @@ -190,8 +205,8 @@ igraph_error_t igraph_community_infomap( IGRAPH_ERROR("Infomap is not available.", IGRAPH_UNIMPLEMENTED); #else - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); if (edge_weights) { if (igraph_vector_size(edge_weights) != ecount) { @@ -235,6 +250,8 @@ igraph_error_t igraph_community_infomap( conf.silent = true; conf.directed = igraph_is_directed(graph); conf.interruptionHandler = &infomap_allow_interruption; + conf.regularized = is_regularized; + conf.regularizationStrength = regularization_strength; infomap::InfomapBase infomap(conf); diff --git a/src/vendor/cigraph/src/community/label_propagation.c b/src/vendor/cigraph/src/community/label_propagation.c index 587b3d05cd9..a82984421e8 100644 --- a/src/vendor/cigraph/src/community/label_propagation.c +++ b/src/vendor/cigraph/src/community/label_propagation.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -34,9 +34,9 @@ static igraph_error_t community_label_propagation( const igraph_vector_bool_t *fixed, igraph_bool_t retention) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_not_fixed_nodes = 0; - igraph_integer_t i, j, k; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_not_fixed_nodes = 0; + igraph_int_t i, j, k; igraph_adjlist_t al; igraph_inclist_t il; igraph_bool_t running, control_iteration; @@ -98,7 +98,7 @@ static igraph_error_t community_label_propagation( control_iteration = true; running = true; while (running) { - igraph_integer_t v1, num_neis; + igraph_int_t v1, num_neis; igraph_real_t max_count; igraph_vector_int_t *neis; igraph_vector_int_t *ineis; @@ -259,9 +259,9 @@ static igraph_error_t community_fast_label_propagation( const igraph_vector_t *weights, const igraph_vector_bool_t *fixed) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_not_fixed_nodes = 0; - igraph_integer_t i, j, k; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_not_fixed_nodes = 0; + igraph_int_t i, j, k; igraph_inclist_t il; igraph_adjlist_t al; @@ -316,7 +316,7 @@ static igraph_error_t community_fast_label_propagation( IGRAPH_FINALLY_CLEAN(1); while (!igraph_dqueue_int_empty(&queue)) { - igraph_integer_t v1, v2, e = -1, num_neis; + igraph_int_t v1, v2, e = -1, num_neis; igraph_real_t max_count; igraph_vector_int_t *neis; igraph_bool_t was_zero; @@ -366,11 +366,11 @@ static igraph_error_t community_fast_label_propagation( } if (igraph_vector_int_size(&dominant_labels) > 0) { - igraph_integer_t current_label = VECTOR(*membership)[v1]; + igraph_int_t current_label = VECTOR(*membership)[v1]; /* Select randomly from the dominant labels */ k = RNG_INTEGER(0, igraph_vector_int_size(&dominant_labels) - 1); - igraph_integer_t new_label = VECTOR(dominant_labels)[k]; /* a dominant label */ + igraph_int_t new_label = VECTOR(dominant_labels)[k]; /* a dominant label */ /* Check if the _current_ label of the node is not the same */ if (new_label != current_label) { @@ -383,7 +383,7 @@ static igraph_error_t community_fast_label_propagation( v2 = VECTOR(*neis)[j]; } if (!VECTOR(in_queue)[v2]) { - igraph_integer_t neigh_label = VECTOR(*membership)[v2]; /* neighbor community */ + igraph_int_t neigh_label = VECTOR(*membership)[v2]; /* neighbor community */ if (neigh_label != new_label && /* not in new community */ (fixed == NULL || !VECTOR(*fixed)[v2]) ) { /* not fixed */ IGRAPH_CHECK(igraph_dqueue_int_push(&queue, v2)); @@ -553,10 +553,10 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, const igraph_vector_bool_t *fixed, igraph_lpa_variant_t lpa_variant) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_not_fixed_nodes = no_of_nodes; - igraph_integer_t i, j, k; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_not_fixed_nodes = no_of_nodes; + igraph_int_t i, j, k; igraph_bool_t unlabelled_left; /* We make a copy of 'fixed' as a pointer into 'fixed_copy' after casting @@ -719,7 +719,7 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, IGRAPH_FINALLY(igraph_dqueue_int_destroy, &q); for (i=0; i < no_of_not_fixed_nodes; ++i) { - igraph_integer_t v = VECTOR(node_order)[i]; + igraph_int_t v = VECTOR(node_order)[i]; /* Is this node unlabelled? */ if (IS_UNLABELLED(v)) { @@ -728,14 +728,14 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, IGRAPH_CHECK(igraph_dqueue_int_push(&q, v)); VECTOR(*membership)[v] = j; while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t ni, num_neis; - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t ni, num_neis; + igraph_int_t actnode = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); num_neis = igraph_vector_int_size(&neis); for (ni = 0; ni < num_neis; ++ni) { - igraph_integer_t neighbor = VECTOR(neis)[ni]; + igraph_int_t neighbor = VECTOR(neis)[ni]; if (IS_UNLABELLED(neighbor)) { VECTOR(*membership)[neighbor] = j; IGRAPH_CHECK(igraph_dqueue_int_push(&q, neighbor)); diff --git a/src/vendor/cigraph/src/community/leading_eigenvector.c b/src/vendor/cigraph/src/community/leading_eigenvector.c index 2d188a34b9c..f25b63a59d2 100644 --- a/src/vendor/cigraph/src/community/leading_eigenvector.c +++ b/src/vendor/cigraph/src/community/leading_eigenvector.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -82,9 +82,9 @@ typedef struct igraph_i_community_leading_eigenvector_data_t { igraph_adjlist_t *adjlist; igraph_inclist_t *inclist; igraph_vector_t *tmp; - igraph_integer_t no_of_edges; + igraph_int_t no_of_edges; igraph_vector_int_t *mymembership; - igraph_integer_t comm; + igraph_int_t comm; const igraph_vector_t *weights; const igraph_t *graph; igraph_vector_t *strength; @@ -97,26 +97,26 @@ static igraph_error_t igraph_i_community_leading_eigenvector( int n, void *extra) { igraph_i_community_leading_eigenvector_data_t *data = extra; - igraph_integer_t size = n; + igraph_int_t size = n; igraph_vector_int_t *idx = data->idx; igraph_vector_int_t *idx2 = data->idx2; igraph_vector_t *tmp = data->tmp; igraph_adjlist_t *adjlist = data->adjlist; igraph_real_t ktx, ktx2; - igraph_integer_t no_of_edges = data->no_of_edges; + igraph_int_t no_of_edges = data->no_of_edges; igraph_vector_int_t *mymembership = data->mymembership; - igraph_integer_t comm = data->comm; + igraph_int_t comm = data->comm; /* Ax */ - for (igraph_integer_t j = 0; j < size; j++) { - igraph_integer_t oldid = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < size; j++) { + igraph_int_t oldid = VECTOR(*idx)[j]; igraph_vector_int_t *neis = igraph_adjlist_get(adjlist, oldid); - igraph_integer_t nlen = igraph_vector_int_size(neis); + igraph_int_t nlen = igraph_vector_int_size(neis); to[j] = 0.0; VECTOR(*tmp)[j] = 0.0; - for (igraph_integer_t k = 0; k < nlen; k++) { - igraph_integer_t nei = VECTOR(*neis)[k]; - igraph_integer_t neimemb = VECTOR(*mymembership)[nei]; + for (igraph_int_t k = 0; k < nlen; k++) { + igraph_int_t nei = VECTOR(*neis)[k]; + igraph_int_t neimemb = VECTOR(*mymembership)[nei]; if (neimemb == comm) { to[j] += from[ VECTOR(*idx2)[nei] ]; VECTOR(*tmp)[j] += 1; @@ -126,10 +126,10 @@ static igraph_error_t igraph_i_community_leading_eigenvector( /* Now calculate k^Tx/2m */ ktx = 0.0; ktx2 = 0.0; - for (igraph_integer_t j = 0; j < size; j++) { - igraph_integer_t oldid = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < size; j++) { + igraph_int_t oldid = VECTOR(*idx)[j]; igraph_vector_int_t *neis = igraph_adjlist_get(adjlist, oldid); - igraph_integer_t degree = igraph_vector_int_size(neis); + igraph_int_t degree = igraph_vector_int_size(neis); ktx += from[j] * degree; ktx2 += degree; } @@ -137,8 +137,8 @@ static igraph_error_t igraph_i_community_leading_eigenvector( ktx2 = ktx2 / no_of_edges / 2.0; /* Now calculate Bx */ - for (igraph_integer_t j = 0; j < size; j++) { - igraph_integer_t oldid = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < size; j++) { + igraph_int_t oldid = VECTOR(*idx)[j]; igraph_vector_int_t *neis = igraph_adjlist_get(adjlist, oldid); igraph_real_t degree = igraph_vector_int_size(neis); to[j] = to[j] - ktx * degree; @@ -146,7 +146,7 @@ static igraph_error_t igraph_i_community_leading_eigenvector( } /* -d_ij summa l in G B_il */ - for (igraph_integer_t j = 0; j < size; j++) { + for (igraph_int_t j = 0; j < size; j++) { to[j] -= VECTOR(*tmp)[j] * from[j]; } @@ -159,31 +159,31 @@ static igraph_error_t igraph_i_community_leading_eigenvector_weighted( int n, void *extra) { igraph_i_community_leading_eigenvector_data_t *data = extra; - igraph_integer_t size = n; + igraph_int_t size = n; igraph_vector_int_t *idx = data->idx; igraph_vector_int_t *idx2 = data->idx2; igraph_vector_t *tmp = data->tmp; igraph_inclist_t *inclist = data->inclist; igraph_real_t ktx, ktx2; igraph_vector_int_t *mymembership = data->mymembership; - igraph_integer_t comm = data->comm; + igraph_int_t comm = data->comm; const igraph_vector_t *weights = data->weights; const igraph_t *graph = data->graph; igraph_vector_t *strength = data->strength; igraph_real_t sw = data->sumweights; /* Ax */ - for (igraph_integer_t j = 0; j < size; j++) { - igraph_integer_t oldid = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < size; j++) { + igraph_int_t oldid = VECTOR(*idx)[j]; igraph_vector_int_t *inc = igraph_inclist_get(inclist, oldid); - igraph_integer_t nlen = igraph_vector_int_size(inc); + igraph_int_t nlen = igraph_vector_int_size(inc); to[j] = 0.0; VECTOR(*tmp)[j] = 0.0; - for (igraph_integer_t k = 0; k < nlen; k++) { - igraph_integer_t edge = VECTOR(*inc)[k]; + for (igraph_int_t k = 0; k < nlen; k++) { + igraph_int_t edge = VECTOR(*inc)[k]; igraph_real_t w = VECTOR(*weights)[edge]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, oldid); - igraph_integer_t neimemb = VECTOR(*mymembership)[nei]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, oldid); + igraph_int_t neimemb = VECTOR(*mymembership)[nei]; if (neimemb == comm) { to[j] += from[ VECTOR(*idx2)[nei] ] * w; VECTOR(*tmp)[j] += w; @@ -193,8 +193,8 @@ static igraph_error_t igraph_i_community_leading_eigenvector_weighted( /* k^Tx/2m */ ktx = 0.0; ktx2 = 0.0; - for (igraph_integer_t j = 0; j < size; j++) { - igraph_integer_t oldid = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < size; j++) { + igraph_int_t oldid = VECTOR(*idx)[j]; igraph_real_t str = VECTOR(*strength)[oldid]; ktx += from[j] * str; ktx2 += str; @@ -203,15 +203,15 @@ static igraph_error_t igraph_i_community_leading_eigenvector_weighted( ktx2 = ktx2 / sw / 2.0; /* Bx */ - for (igraph_integer_t j = 0; j < size; j++) { - igraph_integer_t oldid = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < size; j++) { + igraph_int_t oldid = VECTOR(*idx)[j]; igraph_real_t str = VECTOR(*strength)[oldid]; to[j] = to[j] - ktx * str; VECTOR(*tmp)[j] = VECTOR(*tmp)[j] - ktx2 * str; } /* -d_ij summa l in G B_il */ - for (igraph_integer_t j = 0; j < size; j++) { + for (igraph_int_t j = 0; j < size; j++) { to[j] -= VECTOR(*tmp)[j] * from[j]; } @@ -333,7 +333,7 @@ igraph_error_t igraph_community_leading_eigenvector( const igraph_vector_t *weights, igraph_matrix_int_t *merges, igraph_vector_int_t *membership, - igraph_integer_t steps, + igraph_int_t steps, igraph_arpack_options_t *options, igraph_real_t *modularity, igraph_bool_t start, @@ -343,18 +343,18 @@ igraph_error_t igraph_community_leading_eigenvector( igraph_community_leading_eigenvector_callback_t *callback, void *callback_extra) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_dqueue_int_t tosplit; igraph_vector_int_t idx, idx2; igraph_vector_t mymerges; igraph_vector_t strength, tmp; igraph_vector_t start_vec; - igraph_integer_t staken = 0; + igraph_int_t staken = 0; igraph_adjlist_t adjlist; igraph_inclist_t inclist; - igraph_integer_t i, j, k, l; - igraph_integer_t communities; + igraph_int_t i, j, k, l; + igraph_int_t communities; igraph_vector_int_t vmembership, *mymembership = membership; igraph_i_community_leading_eigenvector_data_t extra; igraph_arpack_storage_t storage; @@ -429,7 +429,7 @@ igraph_error_t igraph_community_leading_eigenvector( IGRAPH_CHECK(igraph_vector_int_resize(&idx, communities)); igraph_vector_int_null(&idx); for (i = 0; i < no_of_nodes; i++) { - igraph_integer_t t = VECTOR(*mymembership)[i]; + igraph_int_t t = VECTOR(*mymembership)[i]; VECTOR(idx)[t] += 1; } } @@ -502,9 +502,9 @@ igraph_error_t igraph_community_leading_eigenvector( extra.mymembership = mymembership; while (!igraph_dqueue_int_empty(&tosplit) && staken < steps) { - igraph_integer_t comm = igraph_dqueue_int_pop_back(&tosplit); + igraph_int_t comm = igraph_dqueue_int_pop_back(&tosplit); /* depth first search */ - igraph_integer_t size = 0; + igraph_int_t size = 0; IGRAPH_ALLOW_INTERRUPTION(); @@ -543,7 +543,7 @@ igraph_error_t igraph_community_leading_eigenvector( storage.resid[i] = (i % 2 ? 1 : -1) + RNG_UNIF(-0.1, 0.1); } - igraph_vector_view(&start_vec, storage.resid, options->n); + start_vec = igraph_vector_view(storage.resid, options->n); igraph_vector_shuffle(&start_vec); { @@ -599,10 +599,9 @@ igraph_error_t igraph_community_leading_eigenvector( /* ---------------------------------------------------------------*/ if (callback) { - igraph_vector_t vv; + const igraph_vector_t vv = igraph_vector_view(storage.v, size);; igraph_error_t ret; - igraph_vector_view(&vv, storage.v, size); IGRAPH_CHECK_CALLBACK( callback( mymembership, comm, storage.d[0], &vv, arpcb1, @@ -677,7 +676,7 @@ igraph_error_t igraph_community_leading_eigenvector( /* Rewrite the mymembership vector */ for (j = 0; j < size; j++) { if (storage.v[j] < 0) { - igraph_integer_t oldid = VECTOR(idx)[j]; + igraph_int_t oldid = VECTOR(idx)[j]; VECTOR(*mymembership)[oldid] = communities - 1; } } @@ -723,8 +722,8 @@ igraph_error_t igraph_community_leading_eigenvector( j = 0; IGRAPH_CHECK(igraph_matrix_int_resize(merges, l / 2, 2)); for (i = l; i > 0; i -= 2) { - igraph_integer_t from = VECTOR(mymerges)[i - 1]; - igraph_integer_t to = VECTOR(mymerges)[i - 2]; + igraph_int_t from = VECTOR(mymerges)[i - 1]; + igraph_int_t to = VECTOR(mymerges)[i - 2]; MATRIX(*merges, j, 0) = VECTOR(mymerges)[i - 2]; MATRIX(*merges, j, 1) = VECTOR(mymerges)[i - 1]; if (VECTOR(idx)[from] != 0) { @@ -758,12 +757,32 @@ igraph_error_t igraph_community_leading_eigenvector( /** * \function igraph_le_community_to_membership - * \brief Vertex membership from the leading eigenvector community structure. + * \brief Cut an incomplete dendrogram after a given number of merges, starting with an initial cluster assignment. * - * This function creates a membership vector from the - * result of \ref igraph_community_leading_eigenvector(). - * It takes \c membership and performs \c steps merges, - * according to the supplied \c merges matrix. + * This function takes a dendrogram whose leaves are cluster IDs given in an + * initial cluster assignment provided in \p membership. Then it updates + * the cluster assignment by performing the specified number of mergers, + * as given by the dendrogram encoded in \p merges. It is a more general + * version of \ref igraph_community_to_membership(), which assumes that + * the dendrogram leaves are singleton clusters corresponding to individual + * vertices. + * + * + * This dendrogram format is suitable for divise hierarchical community + * detection algorithms that stop before dividing the graph into individual + * vertices, such as \ref igraph_community_leading_eigenvector(). + * + * + * Initially, \p membership is expected to contain \c m contiguous cluster + * indices, numbered from zero. These correspond to the leaf nodes of the + * dendrogram. Row \c i of the two-column \p merges matrix contains the IDs of + * clusters that are merged together into dendrogram node m + i. + * It may have up to m - 1 rows. + * + * + * This function performs \p steps merge operations as prescribed by the + * \p merges matrix and updates \p membership to the resulting partitioning + * into m - steps communities. * * \param merges The two-column matrix containing the merge operations. * See \ref igraph_community_leading_eigenvector() for the @@ -776,16 +795,19 @@ igraph_error_t igraph_community_leading_eigenvector( * if this is not a null pointer, but an initialized vector. * \return Error code. * + * \sa \ref igraph_community_to_membership() for a simpler interface that + * starts by merging individual vertices. + * * Time complexity: O(|V|), the number of vertices. */ igraph_error_t igraph_le_community_to_membership(const igraph_matrix_int_t *merges, - igraph_integer_t steps, + igraph_int_t steps, igraph_vector_int_t *membership, igraph_vector_int_t *csize) { - igraph_integer_t no_of_nodes = igraph_vector_int_size(membership); + igraph_int_t no_of_nodes = igraph_vector_int_size(membership); igraph_vector_int_t fake_memb; - igraph_integer_t components, i; + igraph_int_t components, i; if (no_of_nodes > 0) { components = igraph_vector_int_max(membership) + 1; diff --git a/src/vendor/cigraph/src/community/leiden.c b/src/vendor/cigraph/src/community/leiden.c index ed02fed9bec..8667b8b6b04 100644 --- a/src/vendor/cigraph/src/community/leiden.c +++ b/src/vendor/cigraph/src/community/leiden.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2020-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -26,6 +26,7 @@ #include "igraph_memory.h" #include "igraph_random.h" #include "igraph_stack.h" +#include "igraph_structural.h" #include "igraph_vector.h" #include "igraph_vector_list.h" @@ -53,11 +54,11 @@ static igraph_error_t leiden_fastmove_vertices( const igraph_vector_t *vertex_out_weights, const igraph_vector_t *vertex_in_weights, const igraph_real_t resolution, - igraph_integer_t *nb_clusters, + igraph_int_t *nb_clusters, igraph_vector_int_t *membership, igraph_bool_t *changed) { - const igraph_integer_t n = igraph_vcount(graph); + const igraph_int_t n = igraph_vcount(graph); const igraph_bool_t directed = (vertex_in_weights != NULL); igraph_dqueue_int_t unstable_vertices; igraph_real_t max_diff, diff; @@ -68,7 +69,7 @@ static igraph_error_t leiden_fastmove_vertices( igraph_vector_int_t vertex_order; igraph_vector_int_t nb_vertices_per_cluster; igraph_stack_int_t empty_clusters; - igraph_integer_t c, nb_neigh_clusters; + igraph_int_t c, nb_neigh_clusters; int iter = 0; /* Initialize queue of unstable vertices and whether vertex is stable. Only @@ -83,7 +84,7 @@ static igraph_error_t leiden_fastmove_vertices( igraph_vector_int_shuffle(&vertex_order); /* Add to the queue */ - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { IGRAPH_CHECK(igraph_dqueue_int_push(&unstable_vertices, VECTOR(vertex_order)[i])); } @@ -93,7 +94,7 @@ static igraph_error_t leiden_fastmove_vertices( IGRAPH_VECTOR_INIT_FINALLY(&cluster_in_weights, n); } IGRAPH_VECTOR_INT_INIT_FINALLY(&nb_vertices_per_cluster, n); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { c = VECTOR(*membership)[i]; VECTOR(cluster_out_weights)[c] += VECTOR(*vertex_out_weights)[i]; if (directed) { @@ -119,9 +120,9 @@ static igraph_error_t leiden_fastmove_vertices( /* Iterate while the queue is not empty */ while (!igraph_dqueue_int_empty(&unstable_vertices)) { - igraph_integer_t v = igraph_dqueue_int_pop(&unstable_vertices); - igraph_integer_t best_cluster, current_cluster = VECTOR(*membership)[v]; - igraph_integer_t degree; + igraph_int_t v = igraph_dqueue_int_pop(&unstable_vertices); + igraph_int_t best_cluster, current_cluster = VECTOR(*membership)[v]; + igraph_int_t degree; igraph_vector_int_t *edges; /* Remove vertex from current cluster */ @@ -143,9 +144,9 @@ static igraph_error_t leiden_fastmove_vertices( /* Determine the edge weight to each neighboring cluster */ edges = igraph_inclist_get(edges_per_vertex, v); degree = igraph_vector_int_size(edges); - for (igraph_integer_t i = 0; i < degree; i++) { - igraph_integer_t e = VECTOR(*edges)[i]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); + for (igraph_int_t i = 0; i < degree; i++) { + igraph_int_t e = VECTOR(*edges)[i]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); if (u != v) { c = VECTOR(*membership)[u]; if (!IGRAPH_BIT_TEST(neighbor_cluster_added, c)) { @@ -166,7 +167,7 @@ static igraph_error_t leiden_fastmove_vertices( } else { max_diff -= VECTOR(*vertex_out_weights)[v] * VECTOR(cluster_out_weights)[current_cluster] * resolution; } - for (igraph_integer_t i = 0; i < nb_neigh_clusters; i++) { + for (igraph_int_t i = 0; i < nb_neigh_clusters; i++) { c = VECTOR(neighbor_clusters)[i]; diff = VECTOR(edge_weights_per_cluster)[c]; if (directed) { @@ -204,9 +205,9 @@ static igraph_error_t leiden_fastmove_vertices( *changed = true; VECTOR(*membership)[v] = best_cluster; - for (igraph_integer_t i = 0; i < degree; i++) { - igraph_integer_t e = VECTOR(*edges)[i]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); + for (igraph_int_t i = 0; i < degree; i++) { + igraph_int_t e = VECTOR(*edges)[i]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); if (IGRAPH_BIT_TEST(vertex_is_stable, u) && VECTOR(*membership)[u] != best_cluster) { IGRAPH_CHECK(igraph_dqueue_int_push(&unstable_vertices, u)); IGRAPH_BIT_CLEAR(vertex_is_stable, u); @@ -250,9 +251,9 @@ static igraph_error_t leiden_fastmove_vertices( static igraph_error_t leiden_clean_refined_membership( const igraph_vector_int_t* vertex_subset, igraph_vector_int_t *refined_membership, - igraph_integer_t* nb_refined_clusters) { + igraph_int_t* nb_refined_clusters) { - const igraph_integer_t n = igraph_vector_int_size(vertex_subset); + const igraph_int_t n = igraph_vector_int_size(vertex_subset); igraph_vector_int_t new_cluster; IGRAPH_VECTOR_INT_INIT_FINALLY(&new_cluster, n); @@ -260,9 +261,9 @@ static igraph_error_t leiden_clean_refined_membership( /* Clean clusters. We will store the new cluster + 1 so that cluster == 0 * indicates that no membership was assigned yet. */ *nb_refined_clusters += 1; - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(*vertex_subset)[i]; - igraph_integer_t c = VECTOR(*refined_membership)[v]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t v = VECTOR(*vertex_subset)[i]; + igraph_int_t c = VECTOR(*refined_membership)[v]; if (VECTOR(new_cluster)[c] == 0) { VECTOR(new_cluster)[c] = *nb_refined_clusters; *nb_refined_clusters += 1; @@ -270,9 +271,9 @@ static igraph_error_t leiden_clean_refined_membership( } /* Assign new cluster */ - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(*vertex_subset)[i]; - igraph_integer_t c = VECTOR(*refined_membership)[v]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t v = VECTOR(*vertex_subset)[i]; + igraph_int_t c = VECTOR(*refined_membership)[v]; VECTOR(*refined_membership)[v] = VECTOR(new_cluster)[c] - 1; } /* We used the cluster + 1, so correct */ @@ -322,10 +323,10 @@ static igraph_error_t leiden_merge_vertices( const igraph_vector_t *vertex_in_weights, const igraph_vector_int_t *vertex_subset, const igraph_vector_int_t *membership, - const igraph_integer_t cluster_subset, + const igraph_int_t cluster_subset, const igraph_real_t resolution, const igraph_real_t beta, - igraph_integer_t *nb_refined_clusters, + igraph_int_t *nb_refined_clusters, igraph_vector_int_t *refined_membership) { const igraph_bool_t directed = (vertex_in_weights != NULL); @@ -333,12 +334,12 @@ static igraph_error_t leiden_merge_vertices( igraph_bitset_t non_singleton_cluster, neighbor_cluster_added; igraph_real_t max_diff, total_cum_trans_diff, diff; igraph_real_t total_vertex_out_weight = 0.0, total_vertex_in_weight = 0.0; - const igraph_integer_t n = igraph_vector_int_size(vertex_subset); + const igraph_int_t n = igraph_vector_int_size(vertex_subset); igraph_vector_t cluster_out_weights, cluster_in_weights; igraph_vector_t cum_trans_diff, edge_weights_per_cluster, external_edge_weight_per_cluster_in_subset; igraph_vector_int_t neighbor_clusters; igraph_vector_int_t *edges, nb_vertices_per_cluster; - igraph_integer_t degree, nb_neigh_clusters; + igraph_int_t degree, nb_neigh_clusters; /* Initialize cluster weights */ IGRAPH_VECTOR_INIT_FINALLY(&cluster_out_weights, n); @@ -353,8 +354,8 @@ static igraph_error_t leiden_merge_vertices( IGRAPH_VECTOR_INIT_FINALLY(&external_edge_weight_per_cluster_in_subset, n); /* Initialize administration for a singleton partition */ - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(*vertex_subset)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t v = VECTOR(*vertex_subset)[i]; VECTOR(*refined_membership)[v] = i; VECTOR(cluster_out_weights)[i] += VECTOR(*vertex_out_weights)[v]; total_vertex_out_weight += VECTOR(*vertex_out_weights)[v]; @@ -367,9 +368,9 @@ static igraph_error_t leiden_merge_vertices( /* Find out neighboring clusters */ edges = igraph_inclist_get(edges_per_vertex, v); degree = igraph_vector_int_size(edges); - for (igraph_integer_t j = 0; j < degree; j++) { - igraph_integer_t e = VECTOR(*edges)[j]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); + for (igraph_int_t j = 0; j < degree; j++) { + igraph_int_t e = VECTOR(*edges)[j]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); if (u != v && VECTOR(*membership)[u] == cluster_subset) { VECTOR(external_edge_weight_per_cluster_in_subset)[i] += VECTOR(*edge_weights)[e]; } @@ -394,9 +395,9 @@ static igraph_error_t leiden_merge_vertices( /* Initialize cumulative transformed difference */ IGRAPH_VECTOR_INIT_FINALLY(&cum_trans_diff, n); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(vertex_order)[i]; - igraph_integer_t chosen_cluster, best_cluster, current_cluster = VECTOR(*refined_membership)[v]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t v = VECTOR(vertex_order)[i]; + igraph_int_t chosen_cluster, best_cluster, current_cluster = VECTOR(*refined_membership)[v]; igraph_real_t vertex_weight_prod; if (directed) { @@ -426,11 +427,11 @@ static igraph_error_t leiden_merge_vertices( VECTOR(neighbor_clusters)[0] = current_cluster; IGRAPH_BIT_SET(neighbor_cluster_added, current_cluster); nb_neigh_clusters = 1; - for (igraph_integer_t j = 0; j < degree; j++) { - igraph_integer_t e = VECTOR(*edges)[j]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); + for (igraph_int_t j = 0; j < degree; j++) { + igraph_int_t e = VECTOR(*edges)[j]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); if (u != v && VECTOR(*membership)[u] == cluster_subset) { - igraph_integer_t c = VECTOR(*refined_membership)[u]; + igraph_int_t c = VECTOR(*refined_membership)[u]; if (!IGRAPH_BIT_TEST(neighbor_cluster_added, c)) { IGRAPH_BIT_SET(neighbor_cluster_added, c); VECTOR(neighbor_clusters)[nb_neigh_clusters++] = c; @@ -443,8 +444,8 @@ static igraph_error_t leiden_merge_vertices( best_cluster = current_cluster; max_diff = 0.0; total_cum_trans_diff = 0.0; - for (igraph_integer_t j = 0; j < nb_neigh_clusters; j++) { - igraph_integer_t c = VECTOR(neighbor_clusters)[j]; + for (igraph_int_t j = 0; j < nb_neigh_clusters; j++) { + igraph_int_t c = VECTOR(neighbor_clusters)[j]; if (directed) { vertex_weight_prod = @@ -486,7 +487,7 @@ static igraph_error_t leiden_merge_vertices( */ if (total_cum_trans_diff < IGRAPH_INFINITY) { igraph_real_t r = RNG_UNIF(0, total_cum_trans_diff); - igraph_integer_t chosen_idx; + igraph_int_t chosen_idx; igraph_vector_binsearch_slice(&cum_trans_diff, r, &chosen_idx, 0, nb_neigh_clusters); chosen_cluster = VECTOR(neighbor_clusters)[chosen_idx]; } else { @@ -500,9 +501,9 @@ static igraph_error_t leiden_merge_vertices( } VECTOR(nb_vertices_per_cluster)[chosen_cluster]++; - for (igraph_integer_t j = 0; j < degree; j++) { - igraph_integer_t e = VECTOR(*edges)[j]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); + for (igraph_int_t j = 0; j < degree; j++) { + igraph_int_t e = VECTOR(*edges)[j]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); if (VECTOR(*membership)[u] == cluster_subset) { if (VECTOR(*refined_membership)[u] == chosen_cluster) { VECTOR(external_edge_weight_per_cluster_in_subset)[chosen_cluster] -= VECTOR(*edge_weights)[e]; @@ -553,9 +554,9 @@ static igraph_error_t leiden_get_clusters( const igraph_vector_int_t *membership, igraph_vector_int_list_t *clusters) { - const igraph_integer_t n = igraph_vector_int_size(membership); + const igraph_int_t n = igraph_vector_int_size(membership); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { /* Get cluster for vertex i */ igraph_vector_int_t *cluster = igraph_vector_int_list_get_ptr(clusters, VECTOR(*membership)[i]); @@ -588,7 +589,7 @@ static igraph_error_t leiden_aggregate( const igraph_vector_t *vertex_in_weights, const igraph_vector_int_t *membership, const igraph_vector_int_t *refined_membership, - const igraph_integer_t nb_refined_clusters, + const igraph_int_t nb_refined_clusters, igraph_t *aggregated_graph, igraph_vector_t *aggregated_edge_weights, igraph_vector_t *aggregated_vertex_out_weights, @@ -602,7 +603,7 @@ static igraph_error_t leiden_aggregate( igraph_vector_int_t *incident_edges; igraph_vector_int_t neighbor_clusters; igraph_bitset_t neighbor_cluster_added; - igraph_integer_t c, degree, nb_neigh_clusters; + igraph_int_t c, degree, nb_neigh_clusters; /* Get refined clusters */ IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(&refined_clusters, nb_refined_clusters); @@ -629,8 +630,8 @@ static igraph_error_t leiden_aggregate( /* Check per cluster */ for (c = 0; c < nb_refined_clusters; c++) { igraph_vector_int_t* refined_cluster = igraph_vector_int_list_get_ptr(&refined_clusters, c); - igraph_integer_t n_c = igraph_vector_int_size(refined_cluster); - igraph_integer_t v = -1; + igraph_int_t n_c = igraph_vector_int_size(refined_cluster); + igraph_int_t v = -1; /* Calculate the total edge weight to other clusters */ VECTOR(*aggregated_vertex_out_weights)[c] = 0.0; @@ -638,15 +639,15 @@ static igraph_error_t leiden_aggregate( VECTOR(*aggregated_vertex_in_weights)[c] = 0.0; } nb_neigh_clusters = 0; - for (igraph_integer_t i = 0; i < n_c; i++) { + for (igraph_int_t i = 0; i < n_c; i++) { v = VECTOR(*refined_cluster)[i]; incident_edges = igraph_inclist_get(edges_per_vertex, v); degree = igraph_vector_int_size(incident_edges); - for (igraph_integer_t j = 0; j < degree; j++) { - igraph_integer_t e = VECTOR(*incident_edges)[j]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); - igraph_integer_t c2 = VECTOR(*refined_membership)[u]; + for (igraph_int_t j = 0; j < degree; j++) { + igraph_int_t e = VECTOR(*incident_edges)[j]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); + igraph_int_t c2 = VECTOR(*refined_membership)[u]; if (c2 > c) { if (!IGRAPH_BIT_TEST(neighbor_cluster_added, c2)) { @@ -664,8 +665,8 @@ static igraph_error_t leiden_aggregate( } /* Add actual edges from this cluster to the other clusters */ - for (igraph_integer_t i = 0; i < nb_neigh_clusters; i++) { - igraph_integer_t c2 = VECTOR(neighbor_clusters)[i]; + for (igraph_int_t i = 0; i < nb_neigh_clusters; i++) { + igraph_int_t c2 = VECTOR(neighbor_clusters)[i]; /* Add edge */ IGRAPH_CHECK(igraph_vector_int_push_back(&aggregated_edges, c)); @@ -731,12 +732,12 @@ static igraph_error_t leiden_quality( const igraph_vector_t *vertex_out_weights, const igraph_vector_t *vertex_in_weights, const igraph_vector_int_t *membership, - const igraph_integer_t nb_clusters, + const igraph_int_t nb_clusters, const igraph_real_t resolution, igraph_real_t *quality) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); const igraph_bool_t directed = (vertex_in_weights != NULL); const igraph_real_t directed_multiplier = directed ? 1.0 : 2.0; igraph_vector_t cluster_out_weights, cluster_in_weights; @@ -744,9 +745,9 @@ static igraph_error_t leiden_quality( *quality = 0.0; - for (igraph_integer_t e=0; e < ecount; e++) { - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); + for (igraph_int_t e=0; e < ecount; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); total_edge_weight += VECTOR(*edge_weights)[e]; /* We add the internal edge weights. */ @@ -762,8 +763,8 @@ static igraph_error_t leiden_quality( IGRAPH_VECTOR_INIT_FINALLY(&cluster_in_weights, vcount); } - for (igraph_integer_t i = 0; i < vcount; i++) { - igraph_integer_t c = VECTOR(*membership)[i]; + for (igraph_int_t i = 0; i < vcount; i++) { + igraph_int_t c = VECTOR(*membership)[i]; VECTOR(cluster_out_weights)[c] += VECTOR(*vertex_out_weights)[i]; if (directed) { VECTOR(cluster_in_weights)[c] += VECTOR(*vertex_in_weights)[i]; @@ -772,7 +773,7 @@ static igraph_error_t leiden_quality( /* We subtract gamma * N^out_c * N^in_c */ - for (igraph_integer_t c = 0; c < nb_clusters; c++) { + for (igraph_int_t c = 0; c < nb_clusters; c++) { if (directed) { *quality -= resolution * VECTOR(cluster_out_weights)[c] * VECTOR(cluster_in_weights)[c]; } else { @@ -807,14 +808,14 @@ static igraph_error_t community_leiden( igraph_real_t resolution, igraph_real_t beta, igraph_vector_int_t *membership, - igraph_integer_t *nb_clusters, + igraph_int_t *nb_clusters, igraph_real_t *quality, igraph_bool_t *changed) { - const igraph_integer_t n = igraph_vcount(graph); + const igraph_int_t n = igraph_vcount(graph); const igraph_bool_t directed = (vertex_in_weights != NULL); - igraph_integer_t nb_refined_clusters; - igraph_integer_t i, c; + igraph_int_t nb_refined_clusters; + igraph_int_t i, c; igraph_t aggregated_graph, *i_graph; igraph_vector_t aggregated_edge_weights; igraph_vector_t aggregated_vertex_out_weights, aggregated_vertex_in_weights; @@ -829,7 +830,7 @@ static igraph_error_t community_leiden( igraph_vector_int_list_t clusters; igraph_inclist_t edges_per_vertex; igraph_bool_t continue_clustering; - igraph_integer_t level = 0; + igraph_int_t level = 0; /* Initialize temporary weights and membership to be used in aggregation */ IGRAPH_VECTOR_INIT_FINALLY(&tmp_edge_weights, 0); @@ -903,7 +904,7 @@ static igraph_error_t community_leiden( /* Set original membership */ if (level > 0) { for (i = 0; i < n; i++) { - igraph_integer_t v_aggregate = VECTOR(aggregate_vertex)[i]; + igraph_int_t v_aggregate = VECTOR(aggregate_vertex)[i]; VECTOR(*membership)[i] = VECTOR(*i_membership)[v_aggregate]; } } @@ -939,7 +940,7 @@ static igraph_error_t community_leiden( /* Keep track of aggregate vertex. */ for (i = 0; i < n; i++) { /* Current aggregate vertex */ - igraph_integer_t v_aggregate = VECTOR(aggregate_vertex)[i]; + igraph_int_t v_aggregate = VECTOR(aggregate_vertex)[i]; /* New aggregate vertex */ VECTOR(aggregate_vertex)[i] = VECTOR(refined_membership)[v_aggregate]; } @@ -1078,12 +1079,17 @@ static igraph_error_t community_leiden( * is the vertex weight of vertex \c i (separate out- and in-weights are used * with directed graphs), s_i is the cluster of vertex * \c i and δ(x, y) = 1 if and only if x = y and 0 - * otherwise. By setting n_i = k_i, the degree of vertex \c i, and + * otherwise. + * + * + * By setting n_i = k_i, the degree of vertex \c i, and * dividing \c γ by 2m (by \c m in the directed case), we effectively * obtain an expression for modularity. Hence, the standard modularity will be * optimized when you supply the degrees (out- and in-degrees with directed graphs) * as the vertex weights and by supplying as a resolution parameter * 1/(2m) (1/m with directed graphs). + * Use the \ref igraph_community_leiden_simple() convenience function to + * compute vertex weights automatically for modularity maximization. * * * References: @@ -1110,9 +1116,10 @@ static igraph_error_t community_leiden( * directed graphs. If set to \c NULL, in-weights are assumed to be the same * as out-weights, which effectively ignores edge directions. * Must be \c NULL for undirected graphs. - * \param resolution The resolution parameter used, which is - * represented by γ in the objective function mentioned in the - * documentation. + * \param n_iterations Iterate the core Leiden algorithm the indicated number + * of times. If this is a negative number, it will continue iterating until + * an iteration did not change the clustering. Two iterations are often + * sufficient, thus 2 is a reasonable default. * \param beta The randomness used in the refinement step when merging. A small * amount of randomness (\c beta = 0.01) typically works well. * \param start Start from membership vector. If this is true, the optimization @@ -1135,6 +1142,10 @@ static igraph_error_t community_leiden( * * Time complexity: near linear on sparse graphs. * + * \sa \ref igraph_community_leiden_simple() for a simplified interface + * that allows specifying an objective function directly and does not require + * vertex weights. + * * \example examples/simple/igraph_community_leiden.c */ igraph_error_t igraph_community_leiden( @@ -1145,16 +1156,16 @@ igraph_error_t igraph_community_leiden( igraph_real_t resolution, igraph_real_t beta, igraph_bool_t start, - igraph_integer_t n_iterations, + igraph_int_t n_iterations, igraph_vector_int_t *membership, - igraph_integer_t *nb_clusters, + igraph_int_t *nb_clusters, igraph_real_t *quality) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); const igraph_bool_t directed = igraph_is_directed(graph); igraph_vector_t *i_edge_weights, *i_vertex_out_weights, *i_vertex_in_weights; - igraph_integer_t i_nb_clusters; + igraph_int_t i_nb_clusters; if (!nb_clusters) { nb_clusters = &i_nb_clusters; @@ -1240,7 +1251,7 @@ igraph_error_t igraph_community_leiden( * each iteration explores different subsets of vertices. */ igraph_bool_t changed = true; - for (igraph_integer_t itr = 0; + for (igraph_int_t itr = 0; n_iterations < 0 ? changed : itr < n_iterations; itr++) { IGRAPH_CHECK(community_leiden(graph, @@ -1263,3 +1274,230 @@ igraph_error_t igraph_community_leiden( return IGRAPH_SUCCESS; } + +/** + * \function igraph_community_leiden_simple + * \brief Finding community structure using the Leiden algorithm, simple interface. + * + * This is a simplified interface to \ref igraph_community_leiden() for + * convenience purposes. Instead of requiring vertex weights, it allows + * choosing from a set of objective functions to maximize. It implements + * these objective functions by passing suitable vertex weights to + * \ref igraph_community_leiden(), as explained in the documentation of + * that function. + * + * \param graph The input graph. May be directed or undirected. + * \param weights The edge weights. If \c NULL, all weights are assumed to be 1. + * \param objective The objective function to maximize. + * \clist + * \cli IGRAPH_LEIDEN_OBJECTIVE_MODULARITY + * Use the generalized modularity, defined as + * Q = 1/(2m) sum_ij (A_ij - γ k_i k_j / (2m)) δ(c_i, c_j) + * for undirected graphs and as + * Q = 1/m sum_ij (A_ij - γ k^out_i k^in_j / m) δ(c_i, c_j) + * for directed graphs. This effectively uses a multigraph configuration + * model as the null model. Edge weights must not be negative. + * \cli IGRAPH_LEIDEN_OBJECTIVE_CPM + * Use the constant Potts model, whose objective function is defined as + * Q = 1/(2m) sum_ij (A_ij - γ) δ(c_i, c_j) + * for undirected graphs and as + * Q = 1/m sum_ij (A_ij - γ) δ(c_i, c_j) + * for directed graphs. Edge weights are allowed to be negative. + * Edge directions have no impact on the result. + * \cli IGRAPH_LEIDEN_OBJECTIVE_ER + * Use an objective function based on the multigraph Erdős-Rényi G(n,p) + * null model, defined as + * Q = 1/(2m) sum_ij (A_ij - γ p) δ(c_i, c_j) + * for undirected graphs and as + * Q = 1/m sum_ij (A_ij - γ p) δ(c_i, c_j) + * for directed graphs. \c p is the weighted density, i.e. the average + * link strength between all vertex pairs (whether adjacent or not). + * Edge weights must not be negative. Edge directions have no impact on + * the result. + * \endclist + * In the above formulas, \c A is the adjacency matrix, \c m is the total + * edge weight, \c k are the (out- and in-) degrees, \c γ is the resolution + * parameter, and δ(c_i, c_j) is 1 if vertices \c i and \c j + * are in the same community and 0 otherwise. Edge directions are only + * relevant with \c IGRAPH_LEIDEN_OBJECTIVE_MODULARITY. The other two + * objective functions are equivalent between directed and undirected graphs: + * the formal difference is due to each edge being included twice in + * undirected (symmetric) adjacency matrices. + * \param resolution The resolution parameter, which is represented by γ in + * the objective functions detailed above. + * \param beta The randomness used in the refinement step when merging. A small + * amount of randomness (\c beta = 0.01) typically works well. + * \param start Start from membership vector. If this is true, the optimization + * will start from the provided membership vector. If this is false, the + * optimization will start from a singleton partition. + * \param n_iterations Iterate the core Leiden algorithm the indicated number + * of times. If this is a negative number, it will continue iterating until + * an iteration did not change the clustering. Two iterations are often + * sufficient, thus 2 is a reasonable default. + * \param membership The membership vector. If \p start is set to \c false, + * it will be resized appropriately. If \p start is \c true, it must be + * a valid membership vector for the given \p graph. + * \param nb_clusters The number of clusters contained in the final \p membership. + * If \c NULL, the number of clusters will not be returned. + * \param quality The quality of the partition, in terms of the objective + * function selected by \p objective. If \c NULL the quality will + * not be calculated. + * \return Error code. + * + * Time complexity: near linear on sparse graphs. + * + * \sa \ref igraph_community_leiden() for a more flexible interface that + * allows specifying raw vertex weights. + */ +igraph_error_t igraph_community_leiden_simple( + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_leiden_objective_t objective, + igraph_real_t resolution, + igraph_real_t beta, + igraph_bool_t start, + igraph_int_t n_iterations, + igraph_vector_int_t *membership, + igraph_int_t *nb_clusters, + igraph_real_t *quality) { + + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); + const igraph_bool_t directed = igraph_is_directed(graph); + igraph_vector_t vertex_out_weights, vertex_in_weights; + igraph_vector_int_t i_membership, *p_membership; + igraph_real_t min_weight = IGRAPH_INFINITY; + + /* Basic weight vector validation, calculate properties used for validation steps + * specific to different objective functions. */ + if (weights) { + if (igraph_vector_size(weights) != ecount) { + IGRAPH_ERROR("Edge weight vector length does not match number of edges.", IGRAPH_EINVAL); + } + for (igraph_int_t i=0; i < ecount; i++) { + igraph_real_t w = VECTOR(*weights)[i]; + if (w < min_weight) { + min_weight = w; + } + if (! isfinite(w)) { + IGRAPH_ERRORF("Edge weights must not be infinite or NaN, got %g.", + IGRAPH_EINVAL, w); + } + } + } + + IGRAPH_VECTOR_INIT_FINALLY(&vertex_out_weights, vcount); + if (directed) { + IGRAPH_VECTOR_INIT_FINALLY(&vertex_in_weights, vcount); + } + + /* igraph_community_leiden() always requires an initialized membership vector + * of the correct size to be given. We relax this requirement to the case + * when start = true. */ + if (start) { + if (!membership) { + IGRAPH_ERROR("Requesting to start the computation from a specific " + "community assignment, but no membership vector given.", + IGRAPH_EINVAL); + } + if (igraph_vector_int_size(membership) != vcount) { + IGRAPH_ERRORF("Requesting to start the computation from a specific " + "community assignment, but the given membership vector " + "has a different size (%" IGRAPH_PRId " than the vertex " + "count (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, + igraph_vector_int_size(membership), vcount); + } + p_membership = membership; + } else { + if (!membership) { + IGRAPH_VECTOR_INT_INIT_FINALLY(&i_membership, vcount); + p_membership = &i_membership; + } else { + IGRAPH_CHECK(igraph_vector_int_resize(membership, vcount)); + p_membership = membership; + } + } + + switch (objective) { + case IGRAPH_LEIDEN_OBJECTIVE_MODULARITY: + if (min_weight < 0) { + IGRAPH_ERRORF("Edge weights must not be negative for Leiden community " + "detection with modularity objective function, got %g.", + IGRAPH_EINVAL, + min_weight); + } + + IGRAPH_CHECK(igraph_strength( + graph, &vertex_out_weights, + igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, weights)); + if (directed) { + IGRAPH_CHECK(igraph_strength( + graph, &vertex_in_weights, + igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS, weights)); + } + + /* If directed, the sum of vertex_out_weights is the total edge weight. + * If undirected, it is twice the total edge weight. */ + resolution /= igraph_vector_sum(&vertex_out_weights); + + break; + + case IGRAPH_LEIDEN_OBJECTIVE_CPM: + /* TODO: Potential minor optimization is to use the same vector for both. */ + igraph_vector_fill(&vertex_out_weights, 1); + if (directed) { + igraph_vector_fill(&vertex_in_weights, 1); + } + + break; + + case IGRAPH_LEIDEN_OBJECTIVE_ER: + if (min_weight < 0) { + IGRAPH_ERRORF("Edge weights must not be negative for Leiden community " + "detection with ER objective function, got %g.", + IGRAPH_EINVAL, + min_weight); + } + + /* TODO: Potential minor optimization is to use the same vector for both. */ + igraph_vector_fill(&vertex_out_weights, 1); + if (directed) { + igraph_vector_fill(&vertex_in_weights, 1); + } + + { + igraph_real_t p; + /* Note: Loops must be allowed, as the aggregation step of the + * algorithm effectively creates them. */ + IGRAPH_CHECK(igraph_density(graph, weights, &p, /* loops */ true)); + resolution *= p; + } + + break; + + + default: + IGRAPH_ERROR("Invalid objective function for Leiden community detection.", + IGRAPH_EINVAL); + } + + IGRAPH_CHECK(igraph_community_leiden( + graph, weights, + &vertex_out_weights, directed ? &vertex_in_weights : NULL, + resolution, beta, start, n_iterations, p_membership, nb_clusters, quality)); + + if (!membership) { + igraph_vector_int_destroy(&i_membership); + IGRAPH_FINALLY_CLEAN(1); + } + + if (directed) { + igraph_vector_destroy(&vertex_in_weights); + IGRAPH_FINALLY_CLEAN(1); + } + igraph_vector_destroy(&vertex_out_weights); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/community/louvain.c b/src/vendor/cigraph/src/community/louvain.c index 94dbf82b26e..e76c79f98dd 100644 --- a/src/vendor/cigraph/src/community/louvain.c +++ b/src/vendor/cigraph/src/community/louvain.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -32,14 +32,14 @@ /* Structure storing a community */ typedef struct { - igraph_integer_t size; /* Size of the community */ + igraph_int_t size; /* Size of the community */ igraph_real_t weight_inside; /* Sum of edge weights inside community */ igraph_real_t weight_all; /* Sum of edge weights starting/ending in the community */ } igraph_i_multilevel_community; /* Global community list structure */ typedef struct { - igraph_integer_t communities_no, vertices_no; /* Number of communities, number of vertices */ + igraph_int_t communities_no, vertices_no; /* Number of communities, number of vertices */ igraph_real_t weight_sum; /* Sum of edges weight in the whole graph */ igraph_i_multilevel_community *item; /* List of communities */ igraph_vector_int_t *membership; /* Community IDs */ @@ -53,7 +53,7 @@ static igraph_real_t igraph_i_multilevel_community_modularity( igraph_real_t result = 0.0; igraph_real_t m = communities->weight_sum; - for (igraph_integer_t i = 0; i < communities->vertices_no; i++) { + for (igraph_int_t i = 0; i < communities->vertices_no; i++) { if (communities->item[i].size > 0) { result += (communities->item[i].weight_inside - resolution * communities->item[i].weight_all * communities->item[i].weight_all / m) / m; } @@ -63,13 +63,13 @@ static igraph_real_t igraph_i_multilevel_community_modularity( } typedef struct { - igraph_integer_t from; - igraph_integer_t to; - igraph_integer_t id; + igraph_int_t from; + igraph_int_t to; + igraph_int_t id; } igraph_i_multilevel_link; static int igraph_i_multilevel_link_cmp(const void *a, const void *b) { - igraph_integer_t diff; + igraph_int_t diff; diff = ((igraph_i_multilevel_link*)a)->from - ((igraph_i_multilevel_link*)b)->from; @@ -92,8 +92,8 @@ static int igraph_i_multilevel_link_cmp(const void *a, const void *b) { /* removes multiple edges and returns new edge IDs for each edge in |E|log|E| */ static igraph_error_t igraph_i_multilevel_simplify_multiple(igraph_t *graph, igraph_vector_int_t *eids) { - igraph_integer_t ecount = igraph_ecount(graph); - igraph_integer_t l = -1, last_from = -1, last_to = -1; + igraph_int_t ecount = igraph_ecount(graph); + igraph_int_t l = -1, last_from = -1, last_to = -1; igraph_bool_t directed = igraph_is_directed(graph); igraph_vector_int_t edges; igraph_i_multilevel_link *links; @@ -105,7 +105,7 @@ static igraph_error_t igraph_i_multilevel_simplify_multiple(igraph_t *graph, igr IGRAPH_CHECK_OOM(links, "Multi-level community structure detection failed."); IGRAPH_FINALLY(igraph_free, links); - for (igraph_integer_t i = 0; i < ecount; i++) { + for (igraph_int_t i = 0; i < ecount; i++) { links[i].from = IGRAPH_FROM(graph, i); links[i].to = IGRAPH_TO(graph, i); links[i].id = i; @@ -115,7 +115,7 @@ static igraph_error_t igraph_i_multilevel_simplify_multiple(igraph_t *graph, igr igraph_i_multilevel_link_cmp); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - for (igraph_integer_t i = 0; i < ecount; i++) { + for (igraph_int_t i = 0; i < ecount; i++) { if (links[i].from == last_from && links[i].to == last_to) { VECTOR(*eids)[links[i].id] = l; continue; @@ -124,8 +124,8 @@ static igraph_error_t igraph_i_multilevel_simplify_multiple(igraph_t *graph, igr last_from = links[i].from; last_to = links[i].to; - igraph_vector_int_push_back(&edges, last_from); - igraph_vector_int_push_back(&edges, last_to); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, last_from)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, last_to)); l++; @@ -145,12 +145,12 @@ static igraph_error_t igraph_i_multilevel_simplify_multiple(igraph_t *graph, igr } typedef struct { - igraph_integer_t community; + igraph_int_t community; igraph_real_t weight; } igraph_i_multilevel_community_link; static int igraph_i_multilevel_community_link_cmp(const void *a, const void *b) { - igraph_integer_t diff = ( + igraph_int_t diff = ( ((igraph_i_multilevel_community_link*)a)->community - ((igraph_i_multilevel_community_link*)b)->community ); @@ -173,14 +173,14 @@ static int igraph_i_multilevel_community_link_cmp(const void *a, const void *b) static igraph_error_t igraph_i_multilevel_community_links( const igraph_t *graph, const igraph_i_multilevel_community_list *communities, - igraph_integer_t vertex, igraph_vector_int_t *edges, + igraph_int_t vertex, igraph_vector_int_t *edges, igraph_real_t *weight_all, igraph_real_t *weight_inside, igraph_real_t *weight_loop, igraph_vector_int_t *links_community, igraph_vector_t *links_weight) { - igraph_integer_t n, last = -1, c = -1; + igraph_int_t n, last = -1, c = -1; igraph_real_t weight = 1; - igraph_integer_t to, to_community; - igraph_integer_t community = VECTOR(*(communities->membership))[vertex]; + igraph_int_t to, to_community; + igraph_int_t community = VECTOR(*(communities->membership))[vertex]; igraph_i_multilevel_community_link *links; *weight_all = *weight_inside = *weight_loop = 0; @@ -196,8 +196,8 @@ static igraph_error_t igraph_i_multilevel_community_links( IGRAPH_CHECK_OOM(links, "Multi-level community structure detection failed."); IGRAPH_FINALLY(igraph_free, links); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t eidx = VECTOR(*edges)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t eidx = VECTOR(*edges)[i]; weight = VECTOR(*communities->weights)[eidx]; to = IGRAPH_OTHER(graph, eidx, vertex); @@ -225,7 +225,7 @@ static igraph_error_t igraph_i_multilevel_community_links( /* Sort links by community ID and merge the same */ igraph_qsort((void*)links, (size_t) n, sizeof(igraph_i_multilevel_community_link), igraph_i_multilevel_community_link_cmp); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { to_community = links[i].community; if (to_community != last) { IGRAPH_CHECK(igraph_vector_int_push_back(links_community, to_community)); @@ -245,7 +245,7 @@ static igraph_error_t igraph_i_multilevel_community_links( static igraph_real_t igraph_i_multilevel_community_modularity_gain( const igraph_i_multilevel_community_list *communities, - igraph_integer_t community, igraph_integer_t vertex, + igraph_int_t community, igraph_int_t vertex, igraph_real_t weight_all, igraph_real_t weight_inside, const igraph_real_t resolution) { IGRAPH_UNUSED(vertex); @@ -261,8 +261,8 @@ static igraph_real_t igraph_i_multilevel_community_modularity_gain( * igraph_membership_reindex call */ static igraph_error_t igraph_i_multilevel_shrink(igraph_t *graph, igraph_vector_int_t *membership) { igraph_vector_int_t edges; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); IGRAPH_ASSERT(igraph_vector_int_size(membership) == no_of_nodes); @@ -277,7 +277,7 @@ static igraph_error_t igraph_i_multilevel_shrink(igraph_t *graph, igraph_vector_ /* Create the new edgelist */ IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, /* bycol= */ false)); - for (igraph_integer_t i=0; i < 2*no_of_edges; i++) { + for (igraph_int_t i=0; i < 2*no_of_edges; i++) { VECTOR(edges)[i] = VECTOR(*membership)[ VECTOR(edges)[i] ]; } @@ -326,8 +326,8 @@ static igraph_error_t igraph_i_community_multilevel_step( igraph_real_t *modularity, const igraph_real_t resolution) { - igraph_integer_t vcount = igraph_vcount(graph); - igraph_integer_t ecount = igraph_ecount(graph); + igraph_int_t vcount = igraph_vcount(graph); + igraph_int_t ecount = igraph_ecount(graph); igraph_real_t q, pass_q; /* int pass; // used only for debugging */ igraph_bool_t changed; @@ -360,7 +360,7 @@ static igraph_error_t igraph_i_community_multilevel_step( IGRAPH_FINALLY(igraph_free, communities.item); /* Still initializing the communities data structure */ - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { VECTOR(*communities.membership)[i] = i; communities.item[i].size = 1; communities.item[i].weight_inside = 0; @@ -368,8 +368,8 @@ static igraph_error_t igraph_i_community_multilevel_step( } /* Some more initialization :) */ - for (igraph_integer_t i = 0; i < ecount; i++) { - igraph_integer_t ffrom = IGRAPH_FROM(graph, i), fto = IGRAPH_TO(graph, i); + for (igraph_int_t i = 0; i < ecount; i++) { + igraph_int_t ffrom = IGRAPH_FROM(graph, i), fto = IGRAPH_TO(graph, i); igraph_real_t weight = 1; weight = VECTOR(*weights)[i]; @@ -384,7 +384,7 @@ static igraph_error_t igraph_i_community_multilevel_step( /* pass = 1; */ do { /* Pass begin */ - igraph_integer_t temp_communities_no = communities.communities_no; + igraph_int_t temp_communities_no = communities.communities_no; pass_q = q; changed = false; @@ -397,21 +397,21 @@ static igraph_error_t igraph_i_community_multilevel_step( * have a measurable performance impact, hence the single inversion. * See https://github.com/igraph/igraph/issues/2650 for details. */ if (vcount > 1) { - igraph_integer_t i1 = RNG_INTEGER(0, vcount-1); - igraph_integer_t i2 = RNG_INTEGER(0, vcount-1); - igraph_integer_t tmp = VECTOR(node_order)[i1]; + igraph_int_t i1 = RNG_INTEGER(0, vcount-1); + igraph_int_t i2 = RNG_INTEGER(0, vcount-1); + igraph_int_t tmp = VECTOR(node_order)[i1]; VECTOR(node_order)[i1] = VECTOR(node_order)[i2]; VECTOR(node_order)[i2] = tmp; } - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { /* Exclude vertex from its current community */ igraph_real_t weight_all = 0; igraph_real_t weight_inside = 0; igraph_real_t weight_loop = 0; igraph_real_t max_q_gain = 0; igraph_real_t max_weight; - igraph_integer_t old_id, new_id, n, ni; + igraph_int_t old_id, new_id, n, ni; ni = VECTOR(node_order)[i]; @@ -440,8 +440,8 @@ static igraph_error_t igraph_i_community_multilevel_step( max_weight = weight_inside; n = igraph_vector_int_size(&links_community); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t c = VECTOR(links_community)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t c = VECTOR(links_community)[j]; igraph_real_t w = VECTOR(links_weight)[j]; igraph_real_t q_gain = @@ -514,7 +514,7 @@ static igraph_error_t igraph_i_community_multilevel_step( IGRAPH_CHECK(igraph_vector_update(&links_weight, weights)); igraph_vector_null(weights); - for (igraph_integer_t i = 0; i < ecount; i++) { + for (igraph_int_t i = 0; i < ecount; i++) { VECTOR(*weights)[VECTOR(edges)[i]] += VECTOR(links_weight)[i]; } @@ -601,9 +601,9 @@ igraph_error_t igraph_community_multilevel(const igraph_t *graph, igraph_vector_int_t m; igraph_vector_int_t level_membership; igraph_real_t prev_q = -1, q = -1; - igraph_integer_t level = 1; - igraph_integer_t vcount = igraph_vcount(graph); - igraph_integer_t ecount = igraph_ecount(graph); + igraph_int_t level = 1; + igraph_int_t vcount = igraph_vcount(graph); + igraph_int_t ecount = igraph_ecount(graph); /* Initial sanity checks on the input parameters */ if (igraph_is_directed(graph)) { @@ -644,7 +644,7 @@ igraph_error_t igraph_community_multilevel(const igraph_t *graph, if (memberships || membership) { /* Put each vertex in its own community */ - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { VECTOR(level_membership)[i] = i; } } @@ -659,7 +659,7 @@ igraph_error_t igraph_community_multilevel(const igraph_t *graph, while (true) { /* Remember the previous modularity and vertex count, do a single step */ - igraph_integer_t step_vcount = igraph_vcount(&g); + igraph_int_t step_vcount = igraph_vcount(&g); prev_q = q; IGRAPH_CHECK(igraph_i_community_multilevel_step(&g, &w, &m, &q, resolution)); @@ -670,7 +670,7 @@ igraph_error_t igraph_community_multilevel(const igraph_t *graph, } if (memberships || membership) { - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { /* Readjust the membership vector */ VECTOR(level_membership)[i] = VECTOR(m)[ VECTOR(level_membership)[i] ]; } @@ -717,7 +717,7 @@ igraph_error_t igraph_community_multilevel(const igraph_t *graph, /* If we need the final membership vector, copy it to the output */ if (membership) { IGRAPH_CHECK(igraph_vector_int_resize(membership, vcount)); - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { VECTOR(*membership)[i] = VECTOR(level_membership)[i]; } } diff --git a/src/vendor/cigraph/src/community/modularity.c b/src/vendor/cigraph/src/community/modularity.c index 9c709113336..3541a3e3e26 100644 --- a/src/vendor/cigraph/src/community/modularity.c +++ b/src/vendor/cigraph/src/community/modularity.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -24,6 +24,8 @@ #include "igraph_interface.h" #include "igraph_structural.h" +#include "community/community_internal.h" + /** * \function igraph_modularity * \brief Calculates the modularity of a graph with respect to some clusters or vertex types. @@ -93,7 +95,9 @@ * \param membership Numeric vector of integer values which gives the type of each * vertex, i.e. the cluster to which it belongs. * It does not have to be consecutive, i.e. empty communities - * are allowed. + * are allowed. For better performance, ensure that community + * indices are nonnegative and smaller than the vertex count. + * This can be ensured using \ref igraph_reindex_membership(). * \param weights Weight vector or \c NULL if no weights are specified. * \param resolution The resolution parameter \c γ. Must not be negative. * Set it to 1 to use the classical definition of modularity. @@ -106,7 +110,8 @@ * \sa \ref igraph_modularity_matrix() * * Time complexity: O(|V|+|E|), the number of vertices plus the number - * of edges. + * of edges, assuming that community indices are nonnegative and smaller + * than the vertex count. Otherwise, O(|V| log |V| + |E|). */ igraph_error_t igraph_modularity(const igraph_t *graph, const igraph_vector_int_t *membership, @@ -115,17 +120,21 @@ igraph_error_t igraph_modularity(const igraph_t *graph, const igraph_bool_t directed, igraph_real_t *modularity) { + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); + const igraph_vector_int_t *p_membership; + igraph_vector_int_t i_membership; + igraph_bool_t using_i_membership = false; igraph_vector_t k_out, k_in; - igraph_integer_t no_of_partitions; - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t min_cluster_id, max_cluster_id, no_of_partitions; igraph_real_t e; /* count/fraction of edges/weights within partitions */ igraph_real_t m; /* edge count / weight sum */ - igraph_integer_t c1, c2; + igraph_int_t c1, c2; /* Only consider the graph as directed if it actually is directed */ igraph_bool_t use_directed = directed && igraph_is_directed(graph); igraph_real_t directed_multiplier = (use_directed ? 1 : 2); - if (igraph_vector_int_size(membership) != igraph_vcount(graph)) { + if (igraph_vector_int_size(membership) != vcount) { IGRAPH_ERROR("Membership vector size differs from number of vertices.", IGRAPH_EINVAL); } @@ -133,7 +142,7 @@ igraph_error_t igraph_modularity(const igraph_t *graph, IGRAPH_ERROR("The resolution parameter must not be negative.", IGRAPH_EINVAL); } - if (no_of_edges == 0) { + if (ecount == 0) { /* Special case: the modularity of graphs with no edges is not * well-defined */ *modularity = IGRAPH_NAN; @@ -141,12 +150,20 @@ igraph_error_t igraph_modularity(const igraph_t *graph, } /* At this point, the 'membership' vector does not have length zero, - thus it is safe to call igraph_vector_max() and min(). */ - - no_of_partitions = igraph_vector_int_max(membership) + 1; - - if (igraph_vector_int_min(membership) < 0) { - IGRAPH_ERROR("Invalid membership vector: negative entry.", IGRAPH_EINVAL); + thus it is safe to call igraph_vector_int_minmax(). */ + + /* If community indices are outside of the standard range, automatically + * reindex them. */ + igraph_vector_int_minmax(membership, &min_cluster_id, &max_cluster_id); + if (min_cluster_id < 0 || max_cluster_id >= vcount) { + IGRAPH_CHECK(igraph_vector_int_init_copy(&i_membership, membership)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &i_membership); + IGRAPH_CHECK(igraph_i_reindex_membership_large(&i_membership, NULL, &no_of_partitions)); + p_membership = &i_membership; + using_i_membership = true; + } else { + no_of_partitions = max_cluster_id + 1; + p_membership = membership; } IGRAPH_VECTOR_INIT_FINALLY(&k_out, no_of_partitions); @@ -154,17 +171,17 @@ igraph_error_t igraph_modularity(const igraph_t *graph, e = 0.0; if (weights) { - if (igraph_vector_size(weights) != no_of_edges) + if (igraph_vector_size(weights) != ecount) IGRAPH_ERROR("Weight vector size differs from number of edges.", IGRAPH_EINVAL); m = 0.0; - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < ecount; i++) { igraph_real_t w = VECTOR(*weights)[i]; if (w < 0) { IGRAPH_ERROR("Negative weight in weight vector.", IGRAPH_EINVAL); } - c1 = VECTOR(*membership)[ IGRAPH_FROM(graph, i) ]; - c2 = VECTOR(*membership)[ IGRAPH_TO(graph, i) ]; + c1 = VECTOR(*p_membership)[ IGRAPH_FROM(graph, i) ]; + c2 = VECTOR(*p_membership)[ IGRAPH_TO(graph, i) ]; if (c1 == c2) { e += directed_multiplier * w; } @@ -173,10 +190,10 @@ igraph_error_t igraph_modularity(const igraph_t *graph, m += w; } } else { - m = no_of_edges; - for (igraph_integer_t i = 0; i < no_of_edges; i++) { - c1 = VECTOR(*membership)[ IGRAPH_FROM(graph, i) ]; - c2 = VECTOR(*membership)[ IGRAPH_TO(graph, i) ]; + m = ecount; + for (igraph_int_t i = 0; i < ecount; i++) { + c1 = VECTOR(*p_membership)[ IGRAPH_FROM(graph, i) ]; + c2 = VECTOR(*p_membership)[ IGRAPH_TO(graph, i) ]; if (c1 == c2) { e += directed_multiplier; } @@ -198,7 +215,7 @@ igraph_error_t igraph_modularity(const igraph_t *graph, if (m > 0) { *modularity = e; - for (igraph_integer_t i = 0; i < no_of_partitions; i++) { + for (igraph_int_t i = 0; i < no_of_partitions; i++) { *modularity -= resolution * VECTOR(k_out)[i] * VECTOR(k_in)[i]; } } else { @@ -209,6 +226,11 @@ igraph_error_t igraph_modularity(const igraph_t *graph, igraph_vector_destroy(&k_in); IGRAPH_FINALLY_CLEAN(2); + if (using_i_membership) { + igraph_vector_int_destroy(&i_membership); + IGRAPH_FINALLY_CLEAN(1); + } + return IGRAPH_SUCCESS; } @@ -218,8 +240,8 @@ static igraph_error_t igraph_i_modularity_matrix_get_adjacency( /* Specifically used to handle weights and/or ignore direction */ igraph_eit_t edgeit; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t from, to; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t from, to; IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, no_of_nodes)); igraph_matrix_null(res); @@ -228,7 +250,7 @@ static igraph_error_t igraph_i_modularity_matrix_get_adjacency( if (weights) { for (; !IGRAPH_EIT_END(edgeit); IGRAPH_EIT_NEXT(edgeit)) { - igraph_integer_t edge = IGRAPH_EIT_GET(edgeit); + igraph_int_t edge = IGRAPH_EIT_GET(edgeit); from = IGRAPH_FROM(graph, edge); to = IGRAPH_TO(graph, edge); MATRIX(*res, from, to) += VECTOR(*weights)[edge]; @@ -238,7 +260,7 @@ static igraph_error_t igraph_i_modularity_matrix_get_adjacency( } } else { for (; !IGRAPH_EIT_END(edgeit); IGRAPH_EIT_NEXT(edgeit)) { - igraph_integer_t edge = IGRAPH_EIT_GET(edgeit); + igraph_int_t edge = IGRAPH_EIT_GET(edgeit); from = IGRAPH_FROM(graph, edge); to = IGRAPH_TO(graph, edge); MATRIX(*res, from, to) += 1; @@ -303,8 +325,8 @@ igraph_error_t igraph_modularity_matrix(const igraph_t *graph, igraph_matrix_t *modmat, igraph_bool_t directed) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); const igraph_real_t sw = weights ? igraph_vector_sum(weights) : no_of_edges; igraph_vector_t deg, in_deg, out_deg; igraph_real_t scaling_factor; @@ -342,8 +364,8 @@ igraph_error_t igraph_modularity_matrix(const igraph_t *graph, scaling_factor = resolution / sw; - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { MATRIX(*modmat, i, j) -= VECTOR(out_deg)[i] * VECTOR(in_deg)[j] * scaling_factor; } } @@ -358,8 +380,8 @@ igraph_error_t igraph_modularity_matrix(const igraph_t *graph, scaling_factor = resolution / 2.0 / sw; - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { MATRIX(*modmat, i, j) -= VECTOR(deg)[i] * VECTOR(deg)[j] * scaling_factor; } } diff --git a/src/vendor/cigraph/src/community/optimal_modularity.c b/src/vendor/cigraph/src/community/optimal_modularity.c index 9a530d82827..23aebf476c9 100644 --- a/src/vendor/cigraph/src/community/optimal_modularity.c +++ b/src/vendor/cigraph/src/community/optimal_modularity.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -89,11 +89,11 @@ igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, IGRAPH_ERROR("GLPK is not available.", IGRAPH_UNIMPLEMENTED); #else - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); const igraph_bool_t directed = igraph_is_directed(graph); - igraph_integer_t no_of_variables; - igraph_integer_t i, j, k, l; + igraph_int_t no_of_variables; + igraph_int_t i, j, k, l; int st; int idx[] = { 0, 0, 0, 0 }; double coef[] = { 0.0, 1.0, 1.0, -2.0 }; @@ -283,7 +283,7 @@ igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, } if (membership) { - igraph_integer_t comm = 0; /* id of the last community that was found */ + igraph_int_t comm = 0; /* id of the last community that was found */ IGRAPH_CHECK(igraph_vector_int_resize(membership, no_of_nodes)); for (i = 0; i < no_of_nodes; i++) { diff --git a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp index 8cb83deb39b..5f83300ba2f 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp +++ b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -82,7 +82,7 @@ NLink *NNode::Get_LinkToNeighbour(const NNode* neighbour) { } } -igraph_integer_t NNode::Disconnect_From(NNode* neighbour) { +igraph_int_t NNode::Disconnect_From(NNode* neighbour) { //sollen doppelte Links erlaubt sein?? s.o. neighbours.fDelete(neighbour); n_links.fDelete(Get_LinkToNeighbour(neighbour)); @@ -91,8 +91,8 @@ igraph_integer_t NNode::Disconnect_From(NNode* neighbour) { return 1; } -igraph_integer_t NNode::Disconnect_From_All() { - igraph_integer_t number_of_neighbours = 0; +igraph_int_t NNode::Disconnect_From_All() { + igraph_int_t number_of_neighbours = 0; while (neighbours.Size()) { Disconnect_From(neighbours.Pop()); number_of_neighbours++; diff --git a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h index 6a5222e46db..aa9432f894e 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h +++ b/src/vendor/cigraph/src/community/spinglass/NetDataTypes.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -56,15 +56,15 @@ struct HUGE_INDEX { unsigned int field_index; - igraph_integer_t in_field_index; + igraph_int_t in_field_index; }; template class HugeArray { - igraph_integer_t size = 2; + igraph_int_t size = 2; unsigned int highest_field_index = 0; - const igraph_integer_t max_bit_left = 1UL << 31; //wir setzen das 31. Bit auf 1 - igraph_integer_t max_index = 0; + const igraph_int_t max_bit_left = 1UL << 31; //wir setzen das 31. Bit auf 1 + igraph_int_t max_index = 0; DATA *data; DATA *fields[32]; public: @@ -72,11 +72,11 @@ class HugeArray { HugeArray(const HugeArray &) = delete; HugeArray & operator = (const HugeArray &) = delete; ~HugeArray(); - HUGE_INDEX get_huge_index(igraph_integer_t) const; - DATA &Set(igraph_integer_t index); - DATA Get(igraph_integer_t index) { return Set(index); } - DATA &operator[](igraph_integer_t index) { return Set(index); } - igraph_integer_t Size() const { return max_index; } + HUGE_INDEX get_huge_index(igraph_int_t) const; + DATA &Set(igraph_int_t index); + DATA Get(igraph_int_t index) { return Set(index); } + DATA &operator[](igraph_int_t index) { return Set(index); } + igraph_int_t Size() const { return max_index; } } ; //############################################################################################### @@ -92,11 +92,11 @@ class DLItem { friend class DLList_Iter; L_DATA item; - igraph_integer_t index; + igraph_int_t index; DLItem *previous; DLItem *next; - DLItem(L_DATA i, igraph_integer_t ind); - DLItem(L_DATA i, igraph_integer_t ind, DLItem *p, DLItem *n); + DLItem(L_DATA i, igraph_int_t ind); + DLItem(L_DATA i, igraph_int_t ind, DLItem *p, DLItem *n); public: void del() { delete item; @@ -109,7 +109,7 @@ class DLList { protected: DLItem *head; DLItem *tail; - igraph_integer_t number_of_items = 0; + igraph_int_t number_of_items = 0; virtual DLItem *pInsert(L_DATA, DLItem*); virtual L_DATA pDelete(DLItem*); public: @@ -117,14 +117,14 @@ class DLList { DLList(const DLList &) = delete; DLList & operator = (const DLList &) = delete; virtual ~DLList(); - igraph_integer_t Size() const { + igraph_int_t Size() const { return number_of_items; } int fDelete(L_DATA); virtual L_DATA Push(L_DATA); virtual L_DATA Pop(); - virtual L_DATA Get(igraph_integer_t); - igraph_integer_t Is_In_List(L_DATA); + virtual L_DATA Get(igraph_int_t); + igraph_int_t Is_In_List(L_DATA); void delete_items(); }; @@ -133,13 +133,13 @@ class DL_Indexed_List : public DLList { DLItem *pInsert(L_DATA, DLItem*) final; L_DATA pDelete(DLItem*) final; HugeArray*> array; - igraph_integer_t last_index = 0; + igraph_int_t last_index = 0; public: DL_Indexed_List() = default; L_DATA Push(L_DATA) final; L_DATA Pop() final; - L_DATA Get(igraph_integer_t) final; + L_DATA Get(igraph_int_t) final; }; //##################################################################################################### @@ -165,9 +165,9 @@ template class DLList_Iter { class NLink; class NNode { - igraph_integer_t index; - igraph_integer_t cluster_index; - igraph_integer_t marker = 0; + igraph_int_t index; + igraph_int_t cluster_index; + igraph_int_t marker = 0; double weight = 0.0; DLList neighbours; //list with pointers to neighbours @@ -175,7 +175,7 @@ class NNode { DLList *global_link_list; char name[SPINGLASS_MAX_NAME_LEN]; public : - NNode(igraph_integer_t ind, igraph_integer_t c_ind, DLList *ll, const char *n) : + NNode(igraph_int_t ind, igraph_int_t c_ind, DLList *ll, const char *n) : index(ind), cluster_index(c_ind), global_link_list(ll) { strcpy(name, n); @@ -184,22 +184,22 @@ public : NNode &operator=(const NNode &) = delete; ~NNode() { Disconnect_From_All(); } - igraph_integer_t Get_Index() const { + igraph_int_t Get_Index() const { return index; } - igraph_integer_t Get_ClusterIndex() const { + igraph_int_t Get_ClusterIndex() const { return cluster_index; } - igraph_integer_t Get_Marker() const { + igraph_int_t Get_Marker() const { return marker; } - void Set_Marker(igraph_integer_t m) { + void Set_Marker(igraph_int_t m) { marker = m; } - void Set_ClusterIndex(igraph_integer_t ci) { + void Set_ClusterIndex(igraph_int_t ci) { cluster_index = ci; } - igraph_integer_t Get_Degree() const { + igraph_int_t Get_Degree() const { return (neighbours.Size()); } const char *Get_Name() { @@ -221,8 +221,8 @@ public : const DLList *Get_Links() const { return &n_links; } - igraph_integer_t Disconnect_From(NNode*); - igraph_integer_t Disconnect_From_All(); + igraph_int_t Disconnect_From(NNode*); + igraph_int_t Disconnect_From_All(); NLink *Get_LinkToNeighbour(const NNode *neighbour); }; @@ -298,10 +298,10 @@ template HugeArray::~HugeArray() { } template -HUGE_INDEX HugeArray::get_huge_index(igraph_integer_t index) const { +HUGE_INDEX HugeArray::get_huge_index(igraph_int_t index) const { HUGE_INDEX h_index; unsigned int shift_index = 0; - igraph_integer_t help_index; + igraph_int_t help_index; help_index = index; if (index < 2) { h_index.field_index = 0; @@ -314,19 +314,19 @@ HUGE_INDEX HugeArray::get_huge_index(igraph_integer_t index) const { shift_index++; } h_index.field_index = 31 - shift_index; // das hoechste besetzte Bit im Index - help_index = igraph_integer_t(1) << h_index.field_index; // in help_index wird das hoechste besetzte Bit von Index gesetzt + help_index = igraph_int_t(1) << h_index.field_index; // in help_index wird das hoechste besetzte Bit von Index gesetzt h_index.in_field_index = (index ^ help_index); // index XOR help_index, womit alle bits unter dem hoechsten erhalten bleiben return h_index; } template -DATA &HugeArray::Set(igraph_integer_t index) { - igraph_integer_t data_size; +DATA &HugeArray::Set(igraph_int_t index) { + igraph_int_t data_size; while (size < index + 1) { highest_field_index++; - data_size = igraph_integer_t(1) << highest_field_index; + data_size = igraph_int_t(1) << highest_field_index; data = new DATA[data_size]; - for (igraph_integer_t i = 0; i < data_size; i++) { + for (igraph_int_t i = 0; i < data_size; i++) { data[i] = 0; } size = size + data_size; //overflow noch abfangen @@ -343,11 +343,11 @@ DATA &HugeArray::Set(igraph_integer_t index) { //############################################################################### template -DLItem::DLItem(L_DATA i, igraph_integer_t ind) : +DLItem::DLItem(L_DATA i, igraph_int_t ind) : item(i), index(ind), previous(nullptr), next(nullptr) { } template -DLItem::DLItem(L_DATA i, igraph_integer_t ind, DLItem *p, DLItem *n) : +DLItem::DLItem(L_DATA i, igraph_int_t ind, DLItem *p, DLItem *n) : item(i), index(ind), previous(p), next(n) { } //###################################################################################################################### @@ -434,7 +434,7 @@ L_DATA DLList::Pop() { template -L_DATA DLList::Get(igraph_integer_t pos) { +L_DATA DLList::Get(igraph_int_t pos) { if ((pos < 1) || (pos > (number_of_items + 1))) { return 0; } @@ -447,9 +447,9 @@ L_DATA DLList::Get(igraph_integer_t pos) { //gibt Index des gesuchte Listenelement zurueck, besser waere eigentlich zeiger template -igraph_integer_t DLList::Is_In_List(L_DATA data) { +igraph_int_t DLList::Is_In_List(L_DATA data) { DLItem *cur = head, *next; - igraph_integer_t pos = 0; + igraph_int_t pos = 0; while (cur) { next = cur->next; if (cur->item == data) { @@ -500,7 +500,7 @@ L_DATA DL_Indexed_List::Pop() { } template -L_DATA DL_Indexed_List::Get(igraph_integer_t pos) { +L_DATA DL_Indexed_List::Get(igraph_int_t pos) { if (pos > this->number_of_items - 1) { return 0; } diff --git a/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp b/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp index d4242f22b17..d25b9969a89 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp +++ b/src/vendor/cigraph/src/community/spinglass/NetRoutines.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -50,20 +50,20 @@ igraph_error_t igraph_i_read_network_spinglass( const igraph_t *graph, const igraph_vector_t *weights, network *net, igraph_bool_t use_weights) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); double sum_weight; - for (igraph_integer_t vid = 0; vid < no_of_nodes; vid++) { + for (igraph_int_t vid = 0; vid < no_of_nodes; vid++) { char name[SPINGLASS_MAX_NAME_LEN]; snprintf(name, sizeof(name) / sizeof(name[0]), "%" IGRAPH_PRId "", vid+1); net->node_list.Push(new NNode(vid, 0, &net->link_list, name)); } sum_weight = 0.0; - for (igraph_integer_t eid = 0; eid < no_of_edges; eid++) { - igraph_integer_t v1 = IGRAPH_FROM(graph, eid); - igraph_integer_t v2 = IGRAPH_TO(graph, eid); + for (igraph_int_t eid = 0; eid < no_of_edges; eid++) { + igraph_int_t v1 = IGRAPH_FROM(graph, eid); + igraph_int_t v2 = IGRAPH_TO(graph, eid); igraph_real_t w = use_weights ? VECTOR(*weights)[eid] : 1.0; NNode *node1 = net->node_list.Get(v1); diff --git a/src/vendor/cigraph/src/community/spinglass/NetRoutines.h b/src/vendor/cigraph/src/community/spinglass/NetRoutines.h index 6d042777a99..d36f7601bf6 100644 --- a/src/vendor/cigraph/src/community/spinglass/NetRoutines.h +++ b/src/vendor/cigraph/src/community/spinglass/NetRoutines.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/community/spinglass/clustertool.cpp b/src/vendor/cigraph/src/community/spinglass/clustertool.cpp index 64361496d14..37a8a828cc6 100644 --- a/src/vendor/cigraph/src/community/spinglass/clustertool.cpp +++ b/src/vendor/cigraph/src/community/spinglass/clustertool.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -60,7 +60,7 @@ static igraph_error_t igraph_i_community_spinglass_orig( igraph_real_t *temperature, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t spins, + igraph_int_t spins, igraph_bool_t parupdate, igraph_real_t starttemp, igraph_real_t stoptemp, @@ -75,7 +75,7 @@ static igraph_error_t igraph_i_community_spinglass_negative( igraph_real_t *temperature, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t spins, + igraph_int_t spins, igraph_bool_t parupdate, igraph_real_t starttemp, igraph_real_t stoptemp, @@ -170,7 +170,7 @@ igraph_error_t igraph_community_spinglass(const igraph_t *graph, igraph_real_t *temperature, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t spins, + igraph_int_t spins, igraph_bool_t parupdate, igraph_real_t starttemp, igraph_real_t stoptemp, @@ -211,7 +211,7 @@ static igraph_error_t igraph_i_community_spinglass_orig( igraph_real_t *temperature, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t spins, + igraph_int_t spins, igraph_bool_t parupdate, igraph_real_t starttemp, igraph_real_t stoptemp, @@ -219,8 +219,8 @@ static igraph_error_t igraph_i_community_spinglass_orig( igraph_spincomm_update_t update_rule, igraph_real_t gamma) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t changes, runs; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t changes, runs; igraph_bool_t use_weights = false; bool zeroT; double kT, acc, prob; @@ -417,13 +417,13 @@ static igraph_error_t igraph_i_community_spinglass_orig( igraph_error_t igraph_community_spinglass_single(const igraph_t *graph, const igraph_vector_t *weights, - igraph_integer_t vertex, + igraph_int_t vertex, igraph_vector_int_t *community, igraph_real_t *cohesion, igraph_real_t *adhesion, igraph_real_t *inner_links, igraph_real_t *outer_links, - igraph_integer_t spins, + igraph_int_t spins, igraph_spincomm_update_t update_rule, igraph_real_t gamma) { IGRAPH_HANDLE_EXCEPTIONS( @@ -486,7 +486,7 @@ static igraph_error_t igraph_i_community_spinglass_negative( igraph_real_t *temperature, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t spins, + igraph_int_t spins, igraph_bool_t parupdate, igraph_real_t starttemp, igraph_real_t stoptemp, @@ -495,8 +495,8 @@ static igraph_error_t igraph_i_community_spinglass_negative( igraph_real_t gamma, igraph_real_t gamma_minus) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t runs; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t runs; igraph_bool_t use_weights = false; bool zeroT; double kT, acc; diff --git a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp index 3707b7a9799..cdc12860c40 100644 --- a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp +++ b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -52,12 +52,12 @@ using namespace std; //################################################################################################# -PottsModel::PottsModel(network *n, igraph_integer_t qvalue, int m) : +PottsModel::PottsModel(network *n, igraph_int_t qvalue, int m) : net(n), q(qvalue), operation_mode(m), Qmatrix(qvalue+1) { DLList_Iter iter; const NNode *n_cur; - igraph_integer_t *i_ptr; + igraph_int_t *i_ptr; //needed in calculating modularity Qa = new double[q + 1]; //weights for each spin state needed in Monte Carlo process @@ -74,10 +74,10 @@ PottsModel::PottsModel(network *n, igraph_integer_t qvalue, int m) : if (k_max < n_cur->Get_Degree()) { k_max = n_cur->Get_Degree(); } - i_ptr = new igraph_integer_t; + i_ptr = new igraph_int_t; *i_ptr = 0; new_spins.Push(i_ptr); - i_ptr = new igraph_integer_t; + i_ptr = new igraph_int_t; *i_ptr = 0; previous_spins.Push(i_ptr); n_cur = iter.Next(); @@ -103,8 +103,8 @@ PottsModel::~PottsModel() { //when called with positve one. //This may be handy, if you want to warm up the network. //#################################################### -igraph_integer_t PottsModel::assign_initial_conf(igraph_integer_t spin) { - igraph_integer_t s; +igraph_int_t PottsModel::assign_initial_conf(igraph_int_t spin) { + igraph_int_t s; DLList_Iter iter; DLList_Iter l_iter; NNode *n_cur; @@ -112,7 +112,7 @@ igraph_integer_t PottsModel::assign_initial_conf(igraph_integer_t spin) { double sum_weight; // initialize colorfield - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { color_field[i] = 0.0; } // @@ -159,7 +159,7 @@ igraph_integer_t PottsModel::assign_initial_conf(igraph_integer_t spin) { double PottsModel::initialize_Qmatrix() { DLList_Iter l_iter; NLink *l_cur; - igraph_integer_t i, j; + igraph_int_t i, j; //initialize with zeros num_of_links = net->link_list.Size(); for (i = 0; i <= q; i++) { @@ -194,7 +194,7 @@ double PottsModel::initialize_Qmatrix() { //#################################################################### double PottsModel::calculate_Q() { double Q = 0.0; - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { Q += Qmatrix[i][i] - Qa[i] * Qa[i] / double(2.0 * net->sum_weights); } Q /= double(2.0 * net->sum_weights); @@ -230,15 +230,15 @@ double PottsModel::FindStartTemp(double gamma, double prob, double ts) { //max sweeps is the maximum number of sweeps it should perform, //if it does not converge earlier //############################################################## -igraph_integer_t PottsModel::HeatBathParallelLookupZeroTemp(double gamma, double prob, unsigned int max_sweeps) { +igraph_int_t PottsModel::HeatBathParallelLookupZeroTemp(double gamma, double prob, unsigned int max_sweeps) { DLList_Iter net_iter; DLList_Iter l_iter; - DLList_Iter i_iter, i_iter2; + DLList_Iter i_iter, i_iter2; NNode *node, *n_cur; NLink *l_cur; unsigned int sweep; - igraph_integer_t *SPIN, *P_SPIN, old_spin, new_spin, spin_opt; - igraph_integer_t changes; + igraph_int_t *SPIN, *P_SPIN, old_spin, new_spin, spin_opt; + igraph_int_t changes; double h, delta = 0, deltaE, deltaEmin, w, degree; bool cyclic = false; @@ -254,7 +254,7 @@ igraph_integer_t PottsModel::HeatBathParallelLookupZeroTemp(double gamma, double while (!net_iter.End()) { // How many neighbors of each type? // set them all zero - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { neighbours[i] = 0; } degree = node->Get_Weight(); @@ -289,7 +289,7 @@ igraph_integer_t PottsModel::HeatBathParallelLookupZeroTemp(double gamma, double spin_opt = old_spin; deltaEmin = 0.0; - for (igraph_integer_t spin = 1; spin <= q; spin++) { // all possible spin states + for (igraph_int_t spin = 1; spin <= q; spin++) { // all possible spin states if (spin != old_spin) { h = color_field[spin] + delta - color_field[old_spin]; deltaE = double(neighbours[old_spin] - neighbours[spin]) + gamma * prob * double(h); @@ -369,10 +369,10 @@ double PottsModel::HeatBathLookupZeroTemp(double gamma, double prob, unsigned in DLList_Iter l_iter; NNode *node, *n_cur; NLink *l_cur; - igraph_integer_t new_spin, spin_opt, old_spin; + igraph_int_t new_spin, spin_opt, old_spin; unsigned int sweep; - igraph_integer_t r; - igraph_integer_t changes; + igraph_int_t r; + igraph_int_t changes; double delta = 0, h, deltaE, deltaEmin, w, degree; sweep = 0; @@ -380,12 +380,12 @@ double PottsModel::HeatBathLookupZeroTemp(double gamma, double prob, unsigned in while (sweep < max_sweeps) { sweep++; //ueber alle Knoten im Netz - for (igraph_integer_t n = 0; n < num_of_nodes; n++) { + for (igraph_int_t n = 0; n < num_of_nodes; n++) { r = RNG_INTEGER(0, num_of_nodes - 1); node = net->node_list.Get(r); // Wir zaehlen, wieviele Nachbarn von jedem spin vorhanden sind // erst mal alles Null setzen - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { neighbours[i] = 0; } degree = node->Get_Weight(); @@ -420,7 +420,7 @@ double PottsModel::HeatBathLookupZeroTemp(double gamma, double prob, unsigned in spin_opt = old_spin; deltaEmin = 0.0; - for (igraph_integer_t spin = 1; spin <= q; spin++) { // alle moeglichen Spins + for (igraph_int_t spin = 1; spin <= q; spin++) { // alle moeglichen Spins if (spin != old_spin) { h = color_field[spin] + delta - color_field[old_spin]; deltaE = double(neighbours[old_spin] - neighbours[spin]) + gamma * prob * double(h); @@ -468,20 +468,20 @@ double PottsModel::HeatBathLookupZeroTemp(double gamma, double prob, unsigned in //##################################################################################### //This function performs a parallel update at Terperature T //##################################################################################### -igraph_integer_t PottsModel::HeatBathParallelLookup(double gamma, double prob, double kT, unsigned int max_sweeps) { +igraph_int_t PottsModel::HeatBathParallelLookup(double gamma, double prob, double kT, unsigned int max_sweeps) { DLList_Iter net_iter; DLList_Iter l_iter; - DLList_Iter i_iter, i_iter2; + DLList_Iter i_iter, i_iter2; NNode *node, *n_cur; NLink *l_cur; - igraph_integer_t new_spin, spin_opt, old_spin; - igraph_integer_t *SPIN, *P_SPIN; + igraph_int_t new_spin, spin_opt, old_spin; + igraph_int_t *SPIN, *P_SPIN; unsigned int sweep; - igraph_integer_t max_q; - igraph_integer_t changes; + igraph_int_t max_q; + igraph_int_t changes; double h, delta = 0, norm, r, beta, minweight, prefac = 0, w, degree; bool cyclic = false/*, found*/; - igraph_integer_t number_of_nodes; + igraph_int_t number_of_nodes; sweep = 0; changes = 1; @@ -495,7 +495,7 @@ igraph_integer_t PottsModel::HeatBathParallelLookup(double gamma, double prob, d SPIN = i_iter.First(&new_spins); while (!net_iter.End()) { // Initialize neighbours and weights - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { neighbours[i] = 0; weights[i] = 0; } @@ -534,7 +534,7 @@ igraph_integer_t PottsModel::HeatBathParallelLookup(double gamma, double prob, d beta = 1.0 / kT * prefac; minweight = 0.0; weights[old_spin] = 0.0; - for (igraph_integer_t spin = 1; spin <= q; spin++) { // loop over all possible new spins + for (igraph_int_t spin = 1; spin <= q; spin++) { // loop over all possible new spins if (spin != old_spin) { // only if we have a different than old spin! h = color_field[spin] + delta - color_field[old_spin]; weights[spin] = double(neighbours[old_spin] - neighbours[spin]) + gamma * prob * double(h); @@ -543,7 +543,7 @@ igraph_integer_t PottsModel::HeatBathParallelLookup(double gamma, double prob, d } } } // for spin - for (igraph_integer_t spin = 1; spin <= q; spin++) { // loop over all possibe spins + for (igraph_int_t spin = 1; spin <= q; spin++) { // loop over all possibe spins weights[spin] -= minweight; // subtract minweight // to avoid numerical problems with large exponents weights[spin] = exp(-beta * weights[spin]); @@ -613,8 +613,8 @@ igraph_integer_t PottsModel::HeatBathParallelLookup(double gamma, double prob, d } // while markov max_q = 0; - for (igraph_integer_t i = 1; i <= q; i++) if (color_field[i] > max_q) { - max_q = igraph_integer_t(color_field[i]); + for (igraph_int_t i = 1; i <= q; i++) if (color_field[i] > max_q) { + max_q = igraph_int_t(color_field[i]); } //again, we would not like to end up in cyclic attractors @@ -634,26 +634,26 @@ double PottsModel::HeatBathLookup(double gamma, double prob, double kT, unsigned DLList_Iter l_iter; NNode *node, *n_cur; NLink *l_cur; - igraph_integer_t new_spin, spin_opt, old_spin; + igraph_int_t new_spin, spin_opt, old_spin; unsigned int sweep; - igraph_integer_t max_q; - igraph_integer_t rn; - igraph_integer_t changes; + igraph_int_t max_q; + igraph_int_t rn; + igraph_int_t changes; double degree, w, delta = 0, h; double norm, r, beta, minweight, prefac = 0; - igraph_integer_t number_of_nodes; + igraph_int_t number_of_nodes; sweep = 0; changes = 0; number_of_nodes = net->node_list.Size(); while (sweep < max_sweeps) { sweep++; //loop over all nodes in network - for (igraph_integer_t n = 0; n < number_of_nodes; n++) { + for (igraph_int_t n = 0; n < number_of_nodes; n++) { rn = RNG_INTEGER(0, number_of_nodes - 1); node = net->node_list.Get(rn); // initialize the neighbours and the weights - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { neighbours[i] = 0.0; weights[i] = 0.0; } @@ -694,7 +694,7 @@ double PottsModel::HeatBathLookup(double gamma, double prob, double kT, unsigned beta = 1.0 / kT * prefac; minweight = 0.0; weights[old_spin] = 0.0; - for (igraph_integer_t spin = 1; spin <= q; spin++) { // all possible new spins + for (igraph_int_t spin = 1; spin <= q; spin++) { // all possible new spins if (spin != old_spin) { // except the old one! h = color_field[spin] - (color_field[old_spin] - delta); weights[spin] = neighbours[old_spin] - neighbours[spin] + gamma * prob * h; @@ -703,7 +703,7 @@ double PottsModel::HeatBathLookup(double gamma, double prob, double kT, unsigned } } } // for spin - for (igraph_integer_t spin = 1; spin <= q; spin++) { // all possible new spins + for (igraph_int_t spin = 1; spin <= q; spin++) { // all possible new spins weights[spin] -= minweight; // subtract minweigt // for numerical stability weights[spin] = exp(-beta * weights[spin]); @@ -755,8 +755,8 @@ double PottsModel::HeatBathLookup(double gamma, double prob, double kT, unsigned } // while markov max_q = 0; - for (igraph_integer_t i = 1; i <= q; i++) if (color_field[i] > max_q) { - max_q = igraph_integer_t(color_field[i] + 0.5); + for (igraph_int_t i = 1; i <= q; i++) if (color_field[i] > max_q) { + max_q = igraph_int_t(color_field[i] + 0.5); } acceptance = double(changes) / double(number_of_nodes) / double(sweep); @@ -782,8 +782,8 @@ double PottsModel::FindCommunityFromStart( NLink *l_cur; bool found = false, add = false, remove = false; double degree, delta_aff_add, delta_aff_rem, max_delta_aff, Ks = 0.0, Kr = 0, kis, kir, w; - igraph_integer_t community_marker = 5; - igraph_integer_t to_do_marker = 10; + igraph_int_t community_marker = 5; + igraph_int_t to_do_marker = 10; double inner_links = 0, outer_links = 0, aff_r, aff_s; // find the node in the network @@ -982,14 +982,14 @@ double PottsModel::FindCommunityFromStart( node = iter.Next(); } } - igraph_integer_t size = community.Size(); + igraph_int_t size = community.Size(); return size; } //################################################################################################ // this Function writes the clusters to disk //################################################################################################ -igraph_integer_t PottsModel::WriteClusters(igraph_real_t *modularity, +igraph_int_t PottsModel::WriteClusters(igraph_real_t *modularity, igraph_real_t *temperature, igraph_vector_int_t *csize, igraph_vector_int_t *membership, @@ -1006,7 +1006,7 @@ igraph_integer_t PottsModel::WriteClusters(igraph_real_t *modularity, if (csize || membership || modularity) { // TODO: count the number of clusters - for (igraph_integer_t spin = 1; spin <= q; spin++) { + for (igraph_int_t spin = 1; spin <= q; spin++) { inner_links[spin] = 0; outer_links[spin] = 0; nodes[spin] = 0; @@ -1030,7 +1030,7 @@ igraph_integer_t PottsModel::WriteClusters(igraph_real_t *modularity, } if (modularity) { *modularity = 0.0; - for (igraph_integer_t spin = 1; spin <= q; spin++) { + for (igraph_int_t spin = 1; spin <= q; spin++) { if (nodes[spin] > 0) { double t1 = inner_links[spin] / net->sum_weights / 2.0; double t2 = (inner_links[spin] + outer_links[spin]) / @@ -1042,7 +1042,7 @@ igraph_integer_t PottsModel::WriteClusters(igraph_real_t *modularity, } if (csize) { igraph_vector_int_clear(csize); - for (igraph_integer_t spin = 1; spin <= q; spin++) { + for (igraph_int_t spin = 1; spin <= q; spin++) { if (nodes[spin] > 0) { inner_links[spin] /= 2; IGRAPH_CHECK(igraph_vector_int_push_back(csize, nodes[spin])); @@ -1052,9 +1052,9 @@ igraph_integer_t PottsModel::WriteClusters(igraph_real_t *modularity, //die Elemente der Cluster if (membership) { - igraph_integer_t no = -1; + igraph_int_t no = -1; IGRAPH_CHECK(igraph_vector_int_resize(membership, num_of_nodes)); - for (igraph_integer_t spin = 1; spin <= q; spin++) { + for (igraph_int_t spin = 1; spin <= q; spin++) { if (nodes[spin] > 0) { no++; } @@ -1072,7 +1072,7 @@ igraph_integer_t PottsModel::WriteClusters(igraph_real_t *modularity, } //################################################################################################# -PottsModelN::PottsModelN(network *n, igraph_integer_t num_communities, bool directed) : +PottsModelN::PottsModelN(network *n, igraph_int_t num_communities, bool directed) : net(n), q(num_communities), num_nodes(net->node_list.Size()), is_directed(directed) { } //####################################################### @@ -1097,7 +1097,7 @@ PottsModelN::~PottsModelN() { } void PottsModelN::assign_initial_conf(bool init_spins) { - igraph_integer_t s; + igraph_int_t s; DLList_Iter l_iter; const NNode *n_cur; const NLink *l_cur; @@ -1118,7 +1118,7 @@ void PottsModelN::assign_initial_conf(bool init_spins) { degree_pos_out = new double[num_nodes]; //Postive outdegree of the nodes (or sum of weights) degree_neg_out = new double[num_nodes]; //Negative outdegree of the nodes (or sum of weights) - spin = new igraph_integer_t[num_nodes]; //The spin state of each node + spin = new igraph_int_t[num_nodes]; //The spin state of each node } if (is_init) { @@ -1143,11 +1143,11 @@ void PottsModelN::assign_initial_conf(bool init_spins) { //...and of weights and neighbours for in the HeathBathLookup weights = new double[q + 1]; //The weights for changing to another spin state neighbours = new double[q + 1]; //The number of neighbours (or weights) in different spin states - csize = new igraph_integer_t[q + 1]; //The number of nodes in each community + csize = new igraph_int_t[q + 1]; //The number of nodes in each community //Initialize communities - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { degree_community_pos_in[i] = 0.0; degree_community_neg_in[i] = 0.0; degree_community_pos_out[i] = 0.0; @@ -1158,7 +1158,7 @@ void PottsModelN::assign_initial_conf(bool init_spins) { //Initialize vectors if (init_spins) { - for (igraph_integer_t i = 0; i < num_nodes; i++) { + for (igraph_int_t i = 0; i < num_nodes; i++) { degree_pos_in[i] = 0.0; degree_neg_in[i] = 0.0; degree_pos_out[i] = 0.0; @@ -1177,7 +1177,7 @@ void PottsModelN::assign_initial_conf(bool init_spins) { double sum_weight_pos_in, sum_weight_pos_out, sum_weight_neg_in, sum_weight_neg_out; - for (igraph_integer_t v = 0; v < num_nodes; v++) { + for (igraph_int_t v = 0; v < num_nodes; v++) { if (init_spins) { s = RNG_INTEGER(1, q); //The new spin s spin[v] = s; @@ -1265,13 +1265,13 @@ double PottsModelN::HeatBathLookup(double gamma, double lambda, double t, unsign * the old_spin is the spin of the node we are currently * changing. */ - igraph_integer_t new_spin, spin_opt, old_spin; + igraph_int_t new_spin, spin_opt, old_spin; unsigned int sweep; //current sweep - igraph_integer_t changes/*, problemcount*/; //Number of changes and number of problems encountered + igraph_int_t changes/*, problemcount*/; //Number of changes and number of problems encountered double exp_old_spin; //The expectation value for the old spin double exp_spin; //The expectation value for the other spin(s) - igraph_integer_t v; //The node we will be investigating + igraph_int_t v; //The node we will be investigating //The variables required for the calculations double delta_pos_out, delta_pos_in, delta_neg_out, delta_neg_in; @@ -1302,7 +1302,7 @@ double PottsModelN::HeatBathLookup(double gamma, double lambda, double t, unsign while (sweep < max_sweeps) { sweep++; //loop over all nodes in network - for (igraph_integer_t n = 0; n < num_nodes; n++) { + for (igraph_int_t n = 0; n < num_nodes; n++) { //Look for a random node v = RNG_INTEGER(0, num_nodes - 1); //We will be investigating node v @@ -1312,7 +1312,7 @@ double PottsModelN::HeatBathLookup(double gamma, double lambda, double t, unsign /*******************************************/ // initialize the neighbours and the weights // problemcount = 0; - for (igraph_integer_t i = 0; i <= q; i++) { + for (igraph_int_t i = 0; i <= q; i++) { neighbours[i] = 0.0; weights[i] = 0.0; } @@ -1470,7 +1470,7 @@ double PottsModelN::FindStartTemp(double gamma, double lambda, double ts) { return kT; } -igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, +igraph_int_t PottsModelN::WriteClusters(igraph_real_t *modularity, igraph_real_t *temperature, igraph_vector_int_t *community_size, igraph_vector_int_t *membership, @@ -1485,16 +1485,16 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, printf("Start writing clusters.\n"); #endif //Reassign each community so that we retrieve a community assignment 1 through num_communities - auto *cluster_assign = new igraph_integer_t[q + 1]; - for (igraph_integer_t i = 0; i <= q; i++) { + auto *cluster_assign = new igraph_int_t[q + 1]; + for (igraph_int_t i = 0; i <= q; i++) { cluster_assign[i] = 0; } - igraph_integer_t num_clusters = 0; + igraph_int_t num_clusters = 0; //Find out what the new communities will be - for (igraph_integer_t i = 0; i < num_nodes; i++) { - igraph_integer_t s = spin[i]; + for (igraph_int_t i = 0; i < num_nodes; i++) { + igraph_int_t s = spin[i]; if (cluster_assign[s] == 0) { num_clusters++; cluster_assign[s] = num_clusters; @@ -1506,11 +1506,11 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, //And now assign each node to its new community q = num_clusters; - for (igraph_integer_t i = 0; i < num_nodes; i++) { + for (igraph_int_t i = 0; i < num_nodes; i++) { #ifdef SPINGLASS_DEBUG printf("Setting node %d to %d.\n", i, cluster_assign[spin[i]]); #endif - igraph_integer_t s = cluster_assign[spin[i]]; + igraph_int_t s = cluster_assign[spin[i]]; spin[i] = s; #ifdef SPINGLASS_DEBUG printf("Have set node %d to %d.\n", i, s); @@ -1527,7 +1527,7 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, if (community_size) { //Initialize the vector IGRAPH_CHECK(igraph_vector_int_resize(community_size, q)); - for (igraph_integer_t spin_opt = 1; spin_opt <= q; spin_opt++) { + for (igraph_int_t spin_opt = 1; spin_opt <= q; spin_opt++) { //Set the community size VECTOR(*community_size)[spin_opt - 1] = csize[spin_opt]; } @@ -1536,7 +1536,7 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, //Set the membership if (membership) { IGRAPH_CHECK(igraph_vector_int_resize(membership, num_nodes)); - for (igraph_integer_t i = 0; i < num_nodes; i++) { + for (igraph_int_t i = 0; i < num_nodes; i++) { VECTOR(*membership)[ i ] = spin[i] - 1; } } @@ -1553,7 +1553,7 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, num_links_neg = new double *[q + 1] ; //memory allocated for elements of each column. - for ( igraph_integer_t i = 0 ; i < q + 1 ; i++) { + for ( igraph_int_t i = 0 ; i < q + 1 ; i++) { num_links_pos[i] = new double[q + 1]; num_links_neg[i] = new double[q + 1]; } @@ -1561,8 +1561,8 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, //Init num_links - for (igraph_integer_t i = 0; i <= q; i++) { - for (igraph_integer_t j = 0; j <= q; j++) { + for (igraph_int_t i = 0; i <= q; i++) { + for (igraph_int_t j = 0; j <= q; j++) { num_links_pos[i][j] = 0.0; num_links_neg[i][j] = 0.0; } @@ -1575,8 +1575,8 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, while (!iter_l.End()) { w = l_cur->Get_Weight(); - igraph_integer_t a = spin[l_cur->Get_Start()->Get_Index()]; - igraph_integer_t b = spin[l_cur->Get_End()->Get_Index()]; + igraph_int_t a = spin[l_cur->Get_Start()->Get_Index()]; + igraph_int_t b = spin[l_cur->Get_End()->Get_Index()]; if (w > 0) { num_links_pos[a][b] += w; if (!is_directed && a != b) { //Only one edge is defined in case it is undirected @@ -1607,8 +1607,8 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, //We don't take into account the lambda or gamma for //computing the modularity and adhesion, since they //are then incomparable to other definitions. - for (igraph_integer_t i = 1; i <= q; i++) { - for (igraph_integer_t j = 1; j <= q; j++) { + for (igraph_int_t i = 1; i <= q; i++) { + for (igraph_int_t j = 1; j <= q; j++) { if (!is_directed && i == j) expected = degree_community_pos_out[i] * degree_community_pos_in[j] / (m_p == 0 ? 1 : 2 * m_p) - degree_community_neg_out[i] * degree_community_neg_in[j] / (m_n == 0 ? 1 : 2 * m_n); @@ -1673,7 +1673,7 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, } //for i //free the allocated memory - for ( igraph_integer_t i = 0 ; i < q + 1 ; i++ ) { + for ( igraph_int_t i = 0 ; i < q + 1 ; i++ ) { delete [] num_links_pos[i] ; delete [] num_links_neg[i]; } @@ -1692,8 +1692,8 @@ igraph_integer_t PottsModelN::WriteClusters(igraph_real_t *modularity, if (polarization) { double sum_ad = 0.0; - for (igraph_integer_t i = 0; i < q; i++) { - for (igraph_integer_t j = 0; j < q; j++) { + for (igraph_int_t i = 0; i < q; i++) { + for (igraph_int_t j = 0; j < q; j++) { if (i != j) { sum_ad -= MATRIX(*normalised_adhesion, i, j); } diff --git a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h index 1b742ed01e2..a92861f94b4 100644 --- a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h +++ b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -68,39 +68,39 @@ class SimpleMatrix { class PottsModel { private: //these lists are needed to keep track of spin states for parallel update mode - DL_Indexed_List new_spins; - DL_Indexed_List previous_spins; + DL_Indexed_List new_spins; + DL_Indexed_List previous_spins; HugeArray*> correlation; network *net; - igraph_integer_t q; + igraph_int_t q; unsigned int operation_mode; SimpleMatrix Qmatrix; double* Qa; double* weights; double total_degree_sum; - igraph_integer_t num_of_nodes; - igraph_integer_t num_of_links; - igraph_integer_t k_max = 0; + igraph_int_t num_of_nodes; + igraph_int_t num_of_links; + igraph_int_t k_max = 0; double acceptance = 0; double* neighbours; double* color_field; public: - PottsModel(network *net, igraph_integer_t q, int norm_by_degree); + PottsModel(network *net, igraph_int_t q, int norm_by_degree); ~PottsModel(); - igraph_integer_t assign_initial_conf(igraph_integer_t spin); + igraph_int_t assign_initial_conf(igraph_int_t spin); double initialize_Qmatrix(); double calculate_Q(); double FindStartTemp(double gamma, double prob, double ts); - igraph_integer_t HeatBathParallelLookupZeroTemp(double gamma, double prob, unsigned int max_sweeps); + igraph_int_t HeatBathParallelLookupZeroTemp(double gamma, double prob, unsigned int max_sweeps); double HeatBathLookupZeroTemp(double gamma, double prob, unsigned int max_sweeps); - igraph_integer_t HeatBathParallelLookup(double gamma, double prob, double kT, unsigned int max_sweeps); + igraph_int_t HeatBathParallelLookup(double gamma, double prob, double kT, unsigned int max_sweeps); double HeatBathLookup(double gamma, double prob, double kT, unsigned int max_sweeps); - igraph_integer_t WriteClusters(igraph_real_t *modularity, + igraph_int_t WriteClusters(igraph_real_t *modularity, igraph_real_t *temperature, igraph_vector_int_t *csize, igraph_vector_int_t *membership, double kT, double gamma) const; @@ -119,10 +119,10 @@ class PottsModelN { HugeArray*> correlation; network *net; - igraph_integer_t q; //number of communities + igraph_int_t q; //number of communities double m_p; //number of positive ties (or sum of degrees), this equals the number of edges only if it is undirected and each edge has a weight of 1 double m_n; //number of negative ties (or sum of degrees) - igraph_integer_t num_nodes; //number of nodes + igraph_int_t num_nodes; //number of nodes bool is_directed; bool is_init = false; @@ -137,19 +137,19 @@ class PottsModelN { double *degree_community_pos_out = nullptr; //Positive sum of outegree for communities double *degree_community_neg_out = nullptr; //Negative sum of outdegree for communities - igraph_integer_t *csize = nullptr; //The number of nodes in each community - igraph_integer_t *spin = nullptr; //The membership of each node + igraph_int_t *csize = nullptr; //The number of nodes in each community + igraph_int_t *spin = nullptr; //The membership of each node double *neighbours = nullptr; //Array of neighbours of a vertex in each community double *weights = nullptr; //Weights of all possible transitions to another community public: - PottsModelN(network *n, igraph_integer_t num_communities, bool directed); + PottsModelN(network *n, igraph_int_t num_communities, bool directed); ~PottsModelN(); void assign_initial_conf(bool init_spins); double FindStartTemp(double gamma, double lambda, double ts); double HeatBathLookup(double gamma, double lambda, double t, unsigned int max_sweeps); - igraph_integer_t WriteClusters(igraph_real_t *modularity, + igraph_int_t WriteClusters(igraph_real_t *modularity, igraph_real_t *temperature, igraph_vector_int_t *community_size, igraph_vector_int_t *membership, diff --git a/src/vendor/cigraph/src/community/voronoi.c b/src/vendor/cigraph/src/community/voronoi.c index fa3ba2df57a..fc3d0d71486 100644 --- a/src/vendor/cigraph/src/community/voronoi.c +++ b/src/vendor/cigraph/src/community/voronoi.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -43,8 +43,8 @@ * Time complexity: TODO. */ static igraph_error_t igraph_i_local_relative_density(const igraph_t *graph, igraph_vector_t *res, igraph_vs_t vs) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t vs_size; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t vs_size; igraph_vector_int_t nei_mask; /* which nodes are in the local neighbourhood? */ igraph_vector_int_t nei_done; /* which local nodes have already been processed? -- avoids duplicate processing in multigraphs */ igraph_lazy_adjlist_t al; @@ -63,17 +63,17 @@ static igraph_error_t igraph_i_local_relative_density(const igraph_t *graph, igr IGRAPH_CHECK(igraph_vector_resize(res, vs_size)); - for (igraph_integer_t i=0; ! IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t w = IGRAPH_VIT_GET(vit); - igraph_integer_t int_count = 0, ext_count = 0; + for (igraph_int_t i=0; ! IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + igraph_int_t w = IGRAPH_VIT_GET(vit); + igraph_int_t int_count = 0, ext_count = 0; igraph_vector_int_t *w_neis = igraph_lazy_adjlist_get(&al, w); IGRAPH_CHECK_OOM(w_neis, "Cannot calculate local relative density."); - igraph_integer_t dw = igraph_vector_int_size(w_neis); + igraph_int_t dw = igraph_vector_int_size(w_neis); /* mark neighbours of w, as well as w itself */ - for (igraph_integer_t j=0; j < dw; ++j) { + for (igraph_int_t j=0; j < dw; ++j) { VECTOR(nei_mask)[ VECTOR(*w_neis)[j] ] = i + 1; } VECTOR(nei_mask)[w] = i + 1; @@ -82,8 +82,8 @@ static igraph_error_t igraph_i_local_relative_density(const igraph_t *graph, igr int_count += dw; VECTOR(nei_done)[w] = i + 1; - for (igraph_integer_t j=0; j < dw; ++j) { - igraph_integer_t v = VECTOR(*w_neis)[j]; + for (igraph_int_t j=0; j < dw; ++j) { + igraph_int_t v = VECTOR(*w_neis)[j]; if (VECTOR(nei_done)[v] == i + 1) { continue; @@ -94,10 +94,10 @@ static igraph_error_t igraph_i_local_relative_density(const igraph_t *graph, igr igraph_vector_int_t *v_neis = igraph_lazy_adjlist_get(&al, v); IGRAPH_CHECK_OOM(v_neis, "Cannot calculate local relative density."); - igraph_integer_t dv = igraph_vector_int_size(v_neis); + igraph_int_t dv = igraph_vector_int_size(v_neis); - for (igraph_integer_t k=0; k < dv; ++k) { - igraph_integer_t u = VECTOR(*v_neis)[k]; + for (igraph_int_t k=0; k < dv; ++k) { + igraph_int_t u = VECTOR(*v_neis)[k]; if (VECTOR(nei_mask)[u] == i + 1) { int_count += 1; @@ -160,10 +160,10 @@ static igraph_error_t choose_generators( igraph_neimode_t mode, igraph_real_t r) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t ord; igraph_bitset_t excluded; - igraph_integer_t excluded_count; + igraph_int_t excluded_count; igraph_inclist_t il; igraph_2wheap_t q; igraph_real_t radius_max; @@ -186,8 +186,8 @@ static igraph_error_t choose_generators( radius_max = -IGRAPH_INFINITY; igraph_vector_int_clear(generators); - for (igraph_integer_t i=0; i < no_of_nodes; i++) { - igraph_integer_t g = VECTOR(ord)[i]; + for (igraph_int_t i=0; i < no_of_nodes; i++) { + igraph_int_t g = VECTOR(ord)[i]; if (IGRAPH_BIT_TEST(excluded, g)) continue; @@ -196,7 +196,7 @@ static igraph_error_t choose_generators( igraph_2wheap_clear(&q); IGRAPH_CHECK(igraph_2wheap_push_with_index(&q, g, -0.0)); while (!igraph_2wheap_empty(&q)) { - igraph_integer_t vid = igraph_2wheap_max_index(&q); + igraph_int_t vid = igraph_2wheap_max_index(&q); igraph_real_t mindist = -igraph_2wheap_deactivate_max(&q); /* Exceeded cutoff distance, do not search further along this path. */ @@ -215,9 +215,9 @@ static igraph_error_t choose_generators( } igraph_vector_int_t *inc_edges = igraph_inclist_get(&il, vid); - igraph_integer_t inc_count = igraph_vector_int_size(inc_edges); - for (igraph_integer_t j=0; j < inc_count; j++) { - igraph_integer_t edge = VECTOR(*inc_edges)[j]; + igraph_int_t inc_count = igraph_vector_int_size(inc_edges); + for (igraph_int_t j=0; j < inc_count; j++) { + igraph_int_t edge = VECTOR(*inc_edges)[j]; igraph_real_t weight = VECTOR(*lengths)[edge]; /* Optimization: do not follow infinite-length edges. */ @@ -225,7 +225,7 @@ static igraph_error_t choose_generators( continue; } - igraph_integer_t to = IGRAPH_OTHER(graph, edge, vid); + igraph_int_t to = IGRAPH_OTHER(graph, edge, vid); igraph_real_t altdist = mindist + weight; if (!igraph_2wheap_has_elem(&q, to)) { @@ -516,8 +516,8 @@ igraph_error_t igraph_community_voronoi( const igraph_vector_t *lengths, const igraph_vector_t *weights, igraph_neimode_t mode, igraph_real_t r) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_t local_rel_dens; igraph_vector_t lengths2; /* lengths2 = lengths / ecc */ igraph_vector_int_t imembership, igenerators; @@ -594,7 +594,7 @@ igraph_error_t igraph_community_voronoi( IGRAPH_CHECK(igraph_ecc(graph, &lengths2, igraph_ess_all(IGRAPH_EDGEORDER_ID), 3, true, true)); /* Note: ECC is never NaN but it may be Inf */ - for (igraph_integer_t i=0; i < no_of_edges; i++) { + for (igraph_int_t i=0; i < no_of_edges; i++) { VECTOR(lengths2)[i] = 1 / (VECTOR(lengths2)[i]); } if (lengths) { diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap.cpp index 69c2d457b3e..bd419e4ed27 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -130,14 +130,14 @@ using namespace igraph::walktrap; igraph_error_t igraph_community_walktrap(const igraph_t *graph, const igraph_vector_t *weights, - igraph_integer_t steps, + igraph_int_t steps, igraph_matrix_int_t *merges, igraph_vector_t *modularity, igraph_vector_int_t *membership) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t comp_count; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t comp_count; igraph_matrix_int_t imerges, *pmerges = merges; igraph_vector_t imodularity, *pmodularity = modularity; @@ -205,7 +205,7 @@ igraph_error_t igraph_community_walktrap(const igraph_t *graph, ); if (membership) { - igraph_integer_t m; + igraph_int_t m; m = no_of_nodes > 0 ? igraph_vector_which_max(pmodularity) : 0; IGRAPH_CHECK(igraph_community_to_membership(pmerges, no_of_nodes, /*steps=*/ m, diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp index 93cdb9fedd8..4435351738e 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h index ce9426c462b..fc37fac84ad 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_communities.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -123,7 +123,7 @@ class Community { class Communities { private: igraph_matrix_int_t *merges; - igraph_integer_t mergeidx; + igraph_int_t mergeidx; igraph_vector_t *modularity; public: diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp index be02efc53c6..eede1490454 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -145,8 +145,8 @@ igraph_error_t Graph::convert_from_igraph(const igraph_t *graph, const igraph_vector_t *weights) { Graph &G = *this; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); // Avoid warnings with GCC when compiling with LTO. IGRAPH_ASSUME(no_of_nodes >= 0); @@ -160,7 +160,7 @@ igraph_error_t Graph::convert_from_igraph(const igraph_t *graph, Edge_list EL; - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { igraph_real_t w = weights ? VECTOR(*weights)[i] : 1.0; EL.add(IGRAPH_FROM(graph, i), IGRAPH_TO(graph, i), w); } diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h index 43a480673e5..1c66ceef61b 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp index e165b219ea5..df17d07573b 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h index b55f7f1c9f5..675bbe1bee5 100644 --- a/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h +++ b/src/vendor/cigraph/src/community/walktrap/walktrap_heap.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA diff --git a/src/vendor/cigraph/src/connectivity/cohesive_blocks.c b/src/vendor/cigraph/src/connectivity/cohesive_blocks.c index d11e93a709e..f84e5d5283a 100644 --- a/src/vendor/cigraph/src/connectivity/cohesive_blocks.c +++ b/src/vendor/cigraph/src/connectivity/cohesive_blocks.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -35,7 +35,7 @@ #include "core/interruption.h" static void igraph_i_cohesive_blocks_free_graphs(igraph_vector_ptr_t *ptr) { - igraph_integer_t i, n = igraph_vector_ptr_size(ptr); + igraph_int_t i, n = igraph_vector_ptr_size(ptr); for (i = 0; i < n; i++) { igraph_t *g = VECTOR(*ptr)[i]; @@ -55,15 +55,15 @@ static void igraph_i_cohesive_blocks_free_graphs(igraph_vector_ptr_t *ptr) { static igraph_error_t igraph_i_cb_components(igraph_t *graph, const igraph_vector_bool_t *excluded, igraph_vector_int_t *components, - igraph_integer_t *no, + igraph_int_t *no, /* working area follows */ igraph_vector_int_t *compid, igraph_dqueue_int_t *Q, igraph_vector_int_t *neis) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i; - igraph_integer_t cno = 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i; + igraph_int_t cno = 0; igraph_vector_int_clear(components); igraph_dqueue_int_clear(Q); @@ -84,14 +84,14 @@ static igraph_error_t igraph_i_cb_components(igraph_t *graph, VECTOR(*compid)[i] = ++cno; while (!igraph_dqueue_int_empty(Q)) { - igraph_integer_t node = igraph_dqueue_int_pop(Q); - igraph_integer_t j, n; + igraph_int_t node = igraph_dqueue_int_pop(Q); + igraph_int_t j, n; IGRAPH_CHECK(igraph_neighbors( graph, neis, node, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); n = igraph_vector_int_size(neis); for (j = 0; j < n; j++) { - igraph_integer_t v = VECTOR(*neis)[j]; + igraph_int_t v = VECTOR(*neis)[j]; if (VECTOR(*excluded)[v]) { if (VECTOR(*compid)[v] != cno) { VECTOR(*compid)[v] = cno; @@ -118,9 +118,9 @@ static igraph_error_t igraph_i_cb_components(igraph_t *graph, static igraph_bool_t igraph_i_cb_isin(const igraph_vector_int_t *needle, const igraph_vector_int_t *haystack) { - igraph_integer_t nlen = igraph_vector_int_size(needle); - igraph_integer_t hlen = igraph_vector_int_size(haystack); - igraph_integer_t np = 0, hp = 0; + igraph_int_t nlen = igraph_vector_int_size(needle); + igraph_int_t hlen = igraph_vector_int_size(haystack); + igraph_int_t np = 0, hp = 0; if (hlen < nlen) { return false; @@ -223,8 +223,8 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, igraph_vector_int_t Qparent; igraph_vector_int_t Qcohesion; igraph_vector_bool_t Qcheck; - igraph_integer_t Qptr = 0; - igraph_integer_t conn; + igraph_int_t Qptr = 0; + igraph_int_t conn; igraph_bool_t is_simple; igraph_t *graph_copy; @@ -296,11 +296,11 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, while (Qptr < igraph_vector_ptr_size(&Q)) { igraph_t *mygraph = VECTOR(Q)[Qptr]; igraph_bool_t mycheck = VECTOR(Qcheck)[Qptr]; - igraph_integer_t mynodes = igraph_vcount(mygraph); - igraph_integer_t i, nsep; - igraph_integer_t no, kept = 0; - igraph_integer_t cptr = 0; - igraph_integer_t nsepv = 0; + igraph_int_t mynodes = igraph_vcount(mygraph); + igraph_int_t i, nsep; + igraph_int_t no, kept = 0; + igraph_int_t cptr = 0; + igraph_int_t nsepv = 0; igraph_bool_t addedsep = false; IGRAPH_ALLOW_INTERRUPTION(); @@ -314,9 +314,9 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, igraph_vector_bool_null(&marked); for (i = 0; i < nsep; i++) { igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(&separators, i); - igraph_integer_t j, n = igraph_vector_int_size(v); + igraph_int_t j, n = igraph_vector_int_size(v); for (j = 0; j < n; j++) { - igraph_integer_t vv = VECTOR(*v)[j]; + igraph_int_t vv = VECTOR(*v)[j]; if (!VECTOR(marked)[vv]) { nsepv++; VECTOR(marked)[vv] = true; @@ -347,12 +347,12 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, for (i = 0; i < no; i++) { igraph_t *newgraph; - igraph_integer_t maxdeg; + igraph_int_t maxdeg; igraph_vector_int_clear(&compvertices); while (true) { - igraph_integer_t v = VECTOR(components)[cptr++]; + igraph_int_t v = VECTOR(components)[cptr++]; if (v < 0) { break; } @@ -373,7 +373,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, IGRAPH_CHECK(igraph_maxdegree(newgraph, &maxdeg, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); if (maxdeg > VECTOR(Qcohesion)[Qptr]) { - igraph_integer_t newconn; + igraph_int_t newconn; kept++; IGRAPH_CHECK(igraph_vector_ptr_push_back(&Q, newgraph)); IGRAPH_FINALLY_CLEAN(2); @@ -409,9 +409,9 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, IGRAPH_FINALLY_CLEAN(8); if (blocks || cohesion || parent || block_tree) { - igraph_integer_t noblocks = Qptr, badblocks = 0; + igraph_int_t noblocks = Qptr, badblocks = 0; igraph_vector_bool_t removed; - igraph_integer_t i, resptr = 0; + igraph_int_t i, resptr = 0; igraph_vector_int_t rewritemap; IGRAPH_CHECK(igraph_vector_bool_init(&removed, noblocks)); @@ -420,7 +420,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, IGRAPH_FINALLY(igraph_vector_int_destroy, &rewritemap); for (i = 1; i < noblocks; i++) { - igraph_integer_t p = VECTOR(Qparent)[i]; + igraph_int_t p = VECTOR(Qparent)[i]; while (VECTOR(removed)[p]) { p = VECTOR(Qparent)[p]; } @@ -432,7 +432,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, /* Rewrite the mappings */ for (i = 1; i < Qptr; i++) { - igraph_integer_t j, n, p = VECTOR(Qparent)[i]; + igraph_int_t j, n, p = VECTOR(Qparent)[i]; igraph_vector_int_t *mapping, *pmapping; if (p == 0) { @@ -444,7 +444,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, n = igraph_vector_int_size(mapping); for (j = 0; j < n; j++) { - igraph_integer_t v = VECTOR(*mapping)[j]; + igraph_int_t v = VECTOR(*mapping)[j]; VECTOR(*mapping)[j] = VECTOR(*pmapping)[v]; } } @@ -453,7 +453,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, not ensured that the found blocks are not subsets of each other. We check this now. */ for (i = 1; i < noblocks; i++) { - igraph_integer_t j, ic; + igraph_int_t j, ic; igraph_vector_int_t *ivec; if (!VECTOR(Qcheck)[i] || VECTOR(removed)[i]) { continue; @@ -462,7 +462,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, ic = VECTOR(Qcohesion)[i]; for (j = 1; j < noblocks; j++) { igraph_vector_int_t *jvec; - igraph_integer_t jc; + igraph_int_t jc; if (j == i || !VECTOR(Qcheck)[j] || VECTOR(removed)[j]) { continue; } @@ -497,7 +497,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, VECTOR(*cohesion)[resptr] = VECTOR(Qcohesion)[i]; } if (parent || block_tree) { - igraph_integer_t p = VECTOR(Qparent)[i]; + igraph_int_t p = VECTOR(Qparent)[i]; while (p >= 0 && VECTOR(removed)[p]) { p = VECTOR(Qparent)[p]; } @@ -523,7 +523,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, /* Plus the original graph */ if (blocks) { - igraph_integer_t num_vertices = igraph_vcount(graph); + igraph_int_t num_vertices = igraph_vcount(graph); igraph_vector_int_t *orig = igraph_vector_int_list_get_ptr(blocks, 0); IGRAPH_CHECK(igraph_vector_int_resize(orig, num_vertices)); for (i = 0; i < num_vertices; i++) { @@ -533,7 +533,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph, if (block_tree) { igraph_vector_int_t edges; - igraph_integer_t eptr = 0; + igraph_int_t eptr = 0; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, noblocks * 2 - 2); for (i = 1; i < Qptr; i++) { if (VECTOR(removed)[i]) { diff --git a/src/vendor/cigraph/src/connectivity/components.c b/src/vendor/cigraph/src/connectivity/components.c index 459b286856b..4c8da280315 100644 --- a/src/vendor/cigraph/src/connectivity/components.c +++ b/src/vendor/cigraph/src/connectivity/components.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -36,11 +36,11 @@ static igraph_error_t igraph_i_connected_components_weak( const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no + igraph_vector_int_t *csize, igraph_int_t *no ); static igraph_error_t igraph_i_connected_components_strong( const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no + igraph_vector_int_t *csize, igraph_int_t *no ); /** @@ -81,7 +81,7 @@ static igraph_error_t igraph_i_connected_components_strong( igraph_error_t igraph_connected_components( const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no, igraph_connectedness_t mode + igraph_vector_int_t *csize, igraph_int_t *no, igraph_connectedness_t mode ) { if (mode == IGRAPH_WEAK || !igraph_is_directed(graph)) { return igraph_i_connected_components_weak(graph, membership, csize, no); @@ -94,11 +94,11 @@ igraph_error_t igraph_connected_components( static igraph_error_t igraph_i_connected_components_weak( const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no + igraph_vector_int_t *csize, igraph_int_t *no ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_components; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_components; igraph_bitset_t already_added; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; igraph_vector_int_t neis = IGRAPH_VECTOR_NULL; @@ -141,8 +141,8 @@ static igraph_error_t igraph_i_connected_components_weak( /* The algorithm */ no_of_components = 0; - for (igraph_integer_t first_node = 0; first_node < no_of_nodes; ++first_node) { - igraph_integer_t act_component_size; + for (igraph_int_t first_node = 0; first_node < no_of_nodes; ++first_node) { + igraph_int_t act_component_size; if (IGRAPH_BIT_TEST(already_added, first_node)) { continue; @@ -157,13 +157,13 @@ static igraph_error_t igraph_i_connected_components_weak( IGRAPH_CHECK(igraph_dqueue_int_push(&q, first_node)); while ( !igraph_dqueue_int_empty(&q) ) { - igraph_integer_t act_node = igraph_dqueue_int_pop(&q); + igraph_int_t act_node = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_neighbors( graph, &neis, act_node, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE )); - igraph_integer_t nei_count = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < nei_count; i++) { - igraph_integer_t neighbor = VECTOR(neis)[i]; + igraph_int_t nei_count = igraph_vector_int_size(&neis); + for (igraph_int_t i = 0; i < nei_count; i++) { + igraph_int_t neighbor = VECTOR(neis)[i]; if (IGRAPH_BIT_TEST(already_added, neighbor)) { continue; } @@ -202,13 +202,13 @@ static igraph_error_t igraph_i_connected_components_weak( static igraph_error_t igraph_i_connected_components_strong( const igraph_t *graph, igraph_vector_int_t *membership, - igraph_vector_int_t *csize, igraph_integer_t *no + igraph_vector_int_t *csize, igraph_int_t *no ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t next_nei = IGRAPH_VECTOR_NULL; - igraph_integer_t num_seen; + igraph_int_t num_seen; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; - igraph_integer_t no_of_components = 0; + igraph_int_t no_of_components = 0; igraph_vector_int_t out = IGRAPH_VECTOR_NULL; igraph_adjlist_t adjlist; @@ -255,7 +255,7 @@ static igraph_error_t igraph_i_connected_components_strong( IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); num_seen = 0; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { const igraph_vector_int_t *tmp; IGRAPH_ALLOW_INTERRUPTION(); @@ -267,14 +267,14 @@ static igraph_error_t igraph_i_connected_components_strong( IGRAPH_CHECK(igraph_dqueue_int_push(&q, i)); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t act_node = igraph_dqueue_int_back(&q); + igraph_int_t act_node = igraph_dqueue_int_back(&q); tmp = igraph_adjlist_get(&adjlist, act_node); if (VECTOR(next_nei)[act_node] == 0) { /* this is the first time we've met this vertex */ VECTOR(next_nei)[act_node]++; } else if (VECTOR(next_nei)[act_node] <= igraph_vector_int_size(tmp)) { /* we've already met this vertex but it has more children */ - igraph_integer_t neighbor = VECTOR(*tmp)[VECTOR(next_nei)[act_node] - 1]; + igraph_int_t neighbor = VECTOR(*tmp)[VECTOR(next_nei)[act_node] - 1]; if (VECTOR(next_nei)[neighbor] == 0) { IGRAPH_CHECK(igraph_dqueue_int_push(&q, neighbor)); } @@ -310,8 +310,8 @@ static igraph_error_t igraph_i_connected_components_strong( num_seen = 0; while (!igraph_vector_int_empty(&out)) { - igraph_integer_t act_component_size; - igraph_integer_t grandfather = igraph_vector_int_pop_back(&out); + igraph_int_t act_component_size; + igraph_int_t grandfather = igraph_vector_int_pop_back(&out); if (VECTOR(next_nei)[grandfather] != 0) { continue; @@ -332,11 +332,11 @@ static igraph_error_t igraph_i_connected_components_strong( } while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t act_node = igraph_dqueue_int_pop_back(&q); + igraph_int_t act_node = igraph_dqueue_int_pop_back(&q); const igraph_vector_int_t *tmp = igraph_adjlist_get(&adjlist, act_node); - const igraph_integer_t n = igraph_vector_int_size(tmp); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t neighbor = VECTOR(*tmp)[i]; + const igraph_int_t n = igraph_vector_int_size(tmp); + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t neighbor = VECTOR(*tmp)[i]; if (VECTOR(next_nei)[neighbor] != 0) { continue; } @@ -433,8 +433,8 @@ igraph_error_t igraph_is_connected(const igraph_t *graph, igraph_bool_t *res, igraph_connectedness_t mode) { igraph_cached_property_t prop; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no; if (!igraph_is_directed(graph)) { mode = IGRAPH_WEAK; @@ -482,9 +482,9 @@ igraph_error_t igraph_is_connected(const igraph_t *graph, igraph_bool_t *res, } static igraph_error_t igraph_i_is_connected_weak(const igraph_t *graph, igraph_bool_t *res) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t added_count; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t added_count; igraph_bitset_t already_added; igraph_vector_int_t neis; igraph_dqueue_int_t q; @@ -514,15 +514,15 @@ static igraph_error_t igraph_i_is_connected_weak(const igraph_t *graph, igraph_b while (! igraph_dqueue_int_empty(&q)) { IGRAPH_ALLOW_INTERRUPTION(); - const igraph_integer_t actnode = igraph_dqueue_int_pop(&q); + const igraph_int_t actnode = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_neighbors( graph, &neis, actnode, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE )); - const igraph_integer_t nei_count = igraph_vector_int_size(&neis); + const igraph_int_t nei_count = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < nei_count; i++) { - const igraph_integer_t neighbor = VECTOR(neis)[i]; + for (igraph_int_t i = 0; i < nei_count; i++) { + const igraph_int_t neighbor = VECTOR(neis)[i]; if (IGRAPH_BIT_TEST(already_added, neighbor)) { continue; } @@ -561,11 +561,11 @@ static igraph_error_t igraph_i_is_connected_weak(const igraph_t *graph, igraph_b 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); + igraph_int_t maxcompno, igraph_int_t minelements); static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, igraph_graph_list_t *components, - igraph_integer_t maxcompno, igraph_integer_t minelements); + igraph_int_t maxcompno, igraph_int_t minelements); /** * \function igraph_decompose @@ -602,7 +602,7 @@ static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, igraph_error_t igraph_decompose(const igraph_t *graph, igraph_graph_list_t *components, igraph_connectedness_t mode, - igraph_integer_t maxcompno, igraph_integer_t minelements) { + igraph_int_t maxcompno, igraph_int_t minelements) { if (!igraph_is_directed(graph)) { mode = IGRAPH_WEAK; } @@ -619,17 +619,17 @@ igraph_error_t igraph_decompose(const igraph_t *graph, igraph_graph_list_t *comp 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) { + igraph_int_t maxcompno, igraph_int_t minelements) { - igraph_integer_t actstart; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t resco = 0; /* number of graphs created so far */ + igraph_int_t actstart; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t resco = 0; /* number of graphs created so far */ igraph_bitset_t already_added; igraph_dqueue_int_t q; igraph_vector_int_t verts; igraph_vector_int_t neis; igraph_vector_int_t vids_old2new; - igraph_integer_t i; + igraph_int_t i; igraph_t newg; @@ -670,14 +670,14 @@ static igraph_error_t igraph_i_decompose_weak(const igraph_t *graph, /* add the neighbors, recursively */ while (!igraph_dqueue_int_empty(&q) ) { /* pop from the queue of this component */ - igraph_integer_t actvert = igraph_dqueue_int_pop(&q); + igraph_int_t actvert = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_neighbors( graph, &neis, actvert, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE )); - igraph_integer_t nei_count = igraph_vector_int_size(&neis); + igraph_int_t nei_count = igraph_vector_int_size(&neis); /* iterate over the neighbors */ for (i = 0; i < nei_count; i++) { - igraph_integer_t neighbor = VECTOR(neis)[i]; + igraph_int_t neighbor = VECTOR(neis)[i]; if (IGRAPH_BIT_TEST(already_added, neighbor)) { continue; } @@ -724,19 +724,19 @@ static igraph_error_t igraph_i_decompose_weak(const igraph_t *graph, static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, igraph_graph_list_t *components, - igraph_integer_t maxcompno, igraph_integer_t minelements) { + igraph_int_t maxcompno, igraph_int_t minelements) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); /* this is a heap used twice for checking what nodes have * been counted already */ igraph_vector_int_t next_nei = IGRAPH_VECTOR_NULL; - igraph_integer_t i, n, num_seen; + igraph_int_t i, n, num_seen; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; - igraph_integer_t no_of_components = 0; + igraph_int_t no_of_components = 0; igraph_vector_int_t out = IGRAPH_VECTOR_NULL; const igraph_vector_int_t* tmp; @@ -795,7 +795,7 @@ static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, * until there is no more */ while (!igraph_dqueue_int_empty(&q)) { /* this looks up but does NOT consume the queue */ - igraph_integer_t act_node = igraph_dqueue_int_back(&q); + igraph_int_t act_node = igraph_dqueue_int_back(&q); /* get all neighbors of this node */ tmp = igraph_adjlist_get(&adjlist, act_node); @@ -807,7 +807,7 @@ static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, } else if (VECTOR(next_nei)[act_node] <= igraph_vector_int_size(tmp)) { /* we've already met this vertex but it has more children */ - igraph_integer_t neighbor = VECTOR(*tmp)[VECTOR(next_nei)[act_node] - 1]; + igraph_int_t neighbor = VECTOR(*tmp)[VECTOR(next_nei)[act_node] - 1]; if (VECTOR(next_nei)[neighbor] == 0) { /* add the root of the other children to the queue */ IGRAPH_CHECK(igraph_dqueue_int_push(&q, neighbor)); @@ -847,7 +847,7 @@ static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, num_seen = 0; while (!igraph_vector_int_empty(&out) && no_of_components < maxcompno) { /* consume the vector from the last element */ - igraph_integer_t grandfather = igraph_vector_int_pop_back(&out); + igraph_int_t grandfather = igraph_vector_int_pop_back(&out); /* been here, done that * NOTE: next_nei is initialized as [0, 0, ...] */ @@ -875,11 +875,11 @@ static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, while (!igraph_dqueue_int_empty(&q)) { /* consume the queue from this node */ - igraph_integer_t act_node = igraph_dqueue_int_pop_back(&q); + igraph_int_t act_node = igraph_dqueue_int_pop_back(&q); tmp = igraph_adjlist_get(&adjlist, act_node); n = igraph_vector_int_size(tmp); for (i = 0; i < n; i++) { - igraph_integer_t neighbor = VECTOR(*tmp)[i]; + igraph_int_t neighbor = VECTOR(*tmp)[i]; if (VECTOR(next_nei)[neighbor] != 0) { continue; } @@ -1030,13 +1030,13 @@ igraph_error_t igraph_articulation_points(const igraph_t *graph, igraph_vector_i */ igraph_error_t igraph_biconnected_components(const igraph_t *graph, - igraph_integer_t *no, + igraph_int_t *no, igraph_vector_int_list_t *tree_edges, igraph_vector_int_list_t *component_edges, igraph_vector_int_list_t *components, igraph_vector_int_t *articulation_points) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t nextptr; igraph_vector_int_t num, low; igraph_bitset_t found; @@ -1044,9 +1044,9 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, igraph_stack_int_t path; igraph_stack_int_t edgestack; igraph_inclist_t inclist; - igraph_integer_t counter, rootdfs = 0; + igraph_int_t counter, rootdfs = 0; igraph_vector_int_t vertex_added; - igraph_integer_t comps = 0; + igraph_int_t comps = 0; igraph_vector_int_list_t *mycomponents = components, vcomponents; IGRAPH_VECTOR_INT_INIT_FINALLY(&nextptr, no_of_nodes); @@ -1082,7 +1082,7 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(mycomponents, 0); } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(low)[i] != 0) { continue; /* already visited */ @@ -1095,16 +1095,16 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, rootdfs = 0; VECTOR(low)[i] = VECTOR(num)[i] = counter++; while (!igraph_stack_int_empty(&path)) { - igraph_integer_t n; - igraph_integer_t act = igraph_stack_int_top(&path); - igraph_integer_t actnext = VECTOR(nextptr)[act]; + igraph_int_t n; + igraph_int_t act = igraph_stack_int_top(&path); + igraph_int_t actnext = VECTOR(nextptr)[act]; adjedges = igraph_inclist_get(&inclist, act); n = igraph_vector_int_size(adjedges); if (actnext < n) { /* Step down (maybe) */ - igraph_integer_t edge = VECTOR(*adjedges)[actnext]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, act); + igraph_int_t edge = VECTOR(*adjedges)[actnext]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, act); if (VECTOR(low)[nei] == 0) { if (act == i) { rootdfs++; @@ -1123,7 +1123,7 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, /* Step up */ igraph_stack_int_pop(&path); if (!igraph_stack_int_empty(&path)) { - igraph_integer_t prev = igraph_stack_int_top(&path); + igraph_int_t prev = igraph_stack_int_top(&path); /* Update LOW value if needed */ if (VECTOR(low)[act] < VECTOR(low)[prev]) { VECTOR(low)[prev] = VECTOR(low)[act]; @@ -1152,9 +1152,9 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, } while (!igraph_stack_int_empty(&edgestack)) { - igraph_integer_t e = igraph_stack_int_pop(&edgestack); - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); + igraph_int_t e = igraph_stack_int_pop(&edgestack); + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); if (tree_edges) { IGRAPH_CHECK(igraph_vector_int_push_back(v, e)); } @@ -1175,18 +1175,18 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, if (component_edges) { igraph_vector_int_t *nodes = igraph_vector_int_list_get_ptr(mycomponents, comps - 1); - igraph_integer_t ii, no_vert = igraph_vector_int_size(nodes); + igraph_int_t ii, no_vert = igraph_vector_int_size(nodes); igraph_vector_int_t *vv; IGRAPH_CHECK(igraph_vector_int_list_push_back_new(component_edges, &vv)); for (ii = 0; ii < no_vert; ii++) { - igraph_integer_t vert = VECTOR(*nodes)[ii]; + igraph_int_t vert = VECTOR(*nodes)[ii]; igraph_vector_int_t *edges = igraph_inclist_get(&inclist, vert); - igraph_integer_t j, nn = igraph_vector_int_size(edges); + igraph_int_t j, nn = igraph_vector_int_size(edges); for (j = 0; j < nn; j++) { - igraph_integer_t e = VECTOR(*edges)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, e, vert); + igraph_int_t e = VECTOR(*edges)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, e, vert); if (VECTOR(vertex_added)[nei] == comps && nei < vert) { IGRAPH_CHECK(igraph_vector_int_push_back(vv, e)); } @@ -1253,7 +1253,7 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, igraph_error_t igraph_is_biconnected(const igraph_t *graph, igraph_bool_t *res) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t nextptr; igraph_vector_int_t num, low; igraph_stack_int_t path; @@ -1292,20 +1292,20 @@ igraph_error_t igraph_is_biconnected(const igraph_t *graph, igraph_bool_t *res) IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &inclist, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &inclist); - const igraph_integer_t root = 0; /* start DFS from vertex 0 */ - igraph_integer_t counter = 1; - igraph_integer_t rootdfs = 0; + const igraph_int_t root = 0; /* start DFS from vertex 0 */ + igraph_int_t counter = 1; + igraph_int_t rootdfs = 0; IGRAPH_CHECK(igraph_stack_int_push(&path, root)); VECTOR(low)[root] = VECTOR(num)[root] = counter++; while (!igraph_stack_int_empty(&path)) { - igraph_integer_t act = igraph_stack_int_top(&path); - igraph_integer_t actnext = VECTOR(nextptr)[act]; + igraph_int_t act = igraph_stack_int_top(&path); + igraph_int_t actnext = VECTOR(nextptr)[act]; const igraph_vector_int_t *neis = igraph_lazy_adjlist_get(&inclist, act); - const igraph_integer_t n = igraph_vector_int_size(neis); + const igraph_int_t n = igraph_vector_int_size(neis); if (actnext < n) { /* Step down (maybe) */ - igraph_integer_t nei = VECTOR(*neis)[actnext]; + igraph_int_t nei = VECTOR(*neis)[actnext]; if (VECTOR(low)[nei] == 0) { if (act == root) { rootdfs++; @@ -1323,7 +1323,7 @@ igraph_error_t igraph_is_biconnected(const igraph_t *graph, igraph_bool_t *res) /* Step up */ igraph_stack_int_pop(&path); if (!igraph_stack_int_empty(&path)) { - igraph_integer_t prev = igraph_stack_int_top(&path); + igraph_int_t prev = igraph_stack_int_top(&path); /* Update LOW value if needed */ if (VECTOR(low)[act] < VECTOR(low)[prev]) { VECTOR(low)[prev] = VECTOR(low)[act]; @@ -1405,14 +1405,14 @@ igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridge Additionally, we use explicit stacks instead of recursion to avoid stack overflow. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_inclist_t il; igraph_bitset_t visited; igraph_vector_int_t vis; /* vis[u] time when vertex u was first visited */ igraph_vector_int_t low; /* low[u] is the lowest visit time of vertices reachable from u */ igraph_vector_int_t incoming_edge; igraph_stack_int_t su, si; - igraph_integer_t time; + igraph_int_t time; IGRAPH_CHECK(igraph_inclist_init(graph, &il, IGRAPH_ALL, IGRAPH_LOOPS_TWICE)); IGRAPH_FINALLY(igraph_inclist_destroy, &il); @@ -1431,7 +1431,7 @@ igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridge igraph_vector_int_clear(bridges); time = 0; - for (igraph_integer_t start = 0; start < no_of_nodes; ++start) { + for (igraph_int_t start = 0; start < no_of_nodes; ++start) { if (! IGRAPH_BIT_TEST(visited, start)) { /* Perform a DFS from 'start'. * The top of the su stack is u, the vertex currently being visited. @@ -1442,8 +1442,8 @@ igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridge IGRAPH_CHECK(igraph_stack_int_push(&si, 0)); while (! igraph_stack_int_empty(&su)) { - igraph_integer_t u = igraph_stack_int_pop(&su); - igraph_integer_t i = igraph_stack_int_pop(&si); + igraph_int_t u = igraph_stack_int_pop(&su); + igraph_int_t i = igraph_stack_int_pop(&si); if (i == 0) { /* We are at the first step of visiting vertex u. */ @@ -1462,8 +1462,8 @@ igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridge IGRAPH_CHECK(igraph_stack_int_push(&su, u)); IGRAPH_CHECK(igraph_stack_int_push(&si, i+1)); - igraph_integer_t edge = VECTOR(*incedges)[i]; - igraph_integer_t v = IGRAPH_OTHER(graph, edge, u); + igraph_int_t edge = VECTOR(*incedges)[i]; + igraph_int_t v = IGRAPH_OTHER(graph, edge, u); if (! IGRAPH_BIT_TEST(visited, v)) { VECTOR(incoming_edge)[v] = edge; @@ -1478,9 +1478,9 @@ igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridge * We are ready to update the 'low' value of its parent w, and decide * whether its incoming edge is a bridge. */ - igraph_integer_t edge = VECTOR(incoming_edge)[u]; + igraph_int_t edge = VECTOR(incoming_edge)[u]; if (edge >= 0) { - igraph_integer_t w = IGRAPH_OTHER(graph, edge, u); /* parent of u in DFS tree */ + igraph_int_t w = IGRAPH_OTHER(graph, edge, u); /* parent of u in DFS tree */ VECTOR(low)[w] = VECTOR(low)[w] < VECTOR(low)[u] ? VECTOR(low)[w] : VECTOR(low)[u]; if (VECTOR(low)[u] > VECTOR(vis)[w]) { IGRAPH_CHECK(igraph_vector_int_push_back(bridges, edge)); @@ -1552,14 +1552,14 @@ igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridge * vertices; \ref igraph_neighborhood() to find vertices within a given distance. */ igraph_error_t igraph_subcomponent( - const igraph_t *graph, igraph_vector_int_t *res, igraph_integer_t vertex, + const igraph_t *graph, igraph_vector_int_t *res, igraph_int_t vertex, igraph_neimode_t mode ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; igraph_bitset_t already_added; - igraph_integer_t i, vsize; + igraph_int_t i, vsize; igraph_vector_int_t tmp = IGRAPH_VECTOR_NULL; if (vertex < 0 || vertex >= no_of_nodes) { @@ -1581,14 +1581,14 @@ igraph_error_t igraph_subcomponent( IGRAPH_BIT_SET(already_added, vertex); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_neighbors(graph, &tmp, actnode, mode, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE)); vsize = igraph_vector_int_size(&tmp); for (i = 0; i < vsize; i++) { - igraph_integer_t neighbor = VECTOR(tmp)[i]; + igraph_int_t neighbor = VECTOR(tmp)[i]; if (IGRAPH_BIT_TEST(already_added, neighbor)) { continue; diff --git a/src/vendor/cigraph/src/connectivity/percolation.c b/src/vendor/cigraph/src/connectivity/percolation.c index cdadd960e87..7534a97392d 100644 --- a/src/vendor/cigraph/src/connectivity/percolation.c +++ b/src/vendor/cigraph/src/connectivity/percolation.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -40,9 +40,9 @@ static void percolate_edge(igraph_vector_int_t *links, igraph_vector_int_t *sizes, - igraph_integer_t *biggest, - igraph_integer_t a, - igraph_integer_t b) { + igraph_int_t *biggest, + igraph_int_t a, + igraph_int_t b) { // Find head of each tree while (VECTOR(*links)[a] != a) { @@ -60,7 +60,7 @@ static void percolate_edge(igraph_vector_int_t *links, } // Make smaller child of larger - igraph_integer_t parent, child; + igraph_int_t parent, child; if (VECTOR(*sizes)[a] < VECTOR(*sizes)[b]) { parent = b; child = a; @@ -107,12 +107,12 @@ igraph_error_t igraph_edgelist_percolation( igraph_vector_int_t *giant_size, igraph_vector_int_t *vertex_count) { - igraph_integer_t biggest = 1; - igraph_integer_t vertices_added = 0; - igraph_integer_t lower, upper; + igraph_int_t biggest = 1; + igraph_int_t vertices_added = 0; + igraph_int_t lower, upper; int iter = 0; - igraph_integer_t ecount = igraph_vector_int_size(edges); + igraph_int_t ecount = igraph_vector_int_size(edges); if (ecount % 2 == 1) { IGRAPH_ERROR("Invalid edge list, odd number of elements.", IGRAPH_EINVAL); @@ -137,7 +137,7 @@ igraph_error_t igraph_edgelist_percolation( IGRAPH_ERROR("Invalid vertex ID.", IGRAPH_EINVVID); } - const igraph_integer_t vcount = upper + 1; + const igraph_int_t vcount = upper + 1; igraph_vector_int_t sizes; IGRAPH_VECTOR_INT_INIT_FINALLY(&sizes, vcount); @@ -145,14 +145,14 @@ igraph_error_t igraph_edgelist_percolation( igraph_vector_int_t links; IGRAPH_VECTOR_INT_INIT_FINALLY(&links, vcount); - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { VECTOR(sizes)[i] = -1; VECTOR(links)[i] = i; } - for (igraph_integer_t i = 0; i < ecount; i++) { - const igraph_integer_t from = VECTOR(*edges)[2*i]; - const igraph_integer_t to = VECTOR(*edges)[2*i + 1]; + for (igraph_int_t i = 0; i < ecount; i++) { + const igraph_int_t from = VECTOR(*edges)[2*i]; + const igraph_int_t to = VECTOR(*edges)[2*i + 1]; if (VECTOR(sizes)[from] == -1) { vertices_added++; VECTOR(sizes)[from] = 1; @@ -229,12 +229,12 @@ igraph_error_t igraph_bond_percolation( p_edge_order = &i_edge_order; } else { // Verify that there are no duplicates. - const igraph_integer_t no_of_added_edges = igraph_vector_int_size(edge_order); + const igraph_int_t no_of_added_edges = igraph_vector_int_size(edge_order); igraph_bitset_t present_edges; IGRAPH_BITSET_INIT_FINALLY(&present_edges, no_of_added_edges); - for (igraph_integer_t i = 0; i < no_of_added_edges; i++) { + for (igraph_int_t i = 0; i < no_of_added_edges; i++) { if (IGRAPH_BIT_TEST(present_edges, VECTOR(*edge_order)[i])) { IGRAPH_ERROR("Duplicate edges in edge order vector.", IGRAPH_EINVAL); } @@ -267,9 +267,9 @@ igraph_error_t igraph_bond_percolation( static igraph_error_t percolate_site(const igraph_t *graph, igraph_vector_int_t *links, igraph_vector_int_t *sizes, - igraph_integer_t *biggest, - igraph_integer_t *edges_added, - igraph_integer_t vertex, + igraph_int_t *biggest, + igraph_int_t *edges_added, + igraph_int_t vertex, igraph_vector_int_t *neighbors) { if (VECTOR(*sizes)[vertex] != 0) { @@ -280,8 +280,8 @@ static igraph_error_t percolate_site(const igraph_t *graph, IGRAPH_CHECK(igraph_neighbors(graph, neighbors, vertex, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); - igraph_integer_t neighbor_count = igraph_vector_int_size(neighbors); - for (igraph_integer_t i = 0; i < neighbor_count; i++) { + igraph_int_t neighbor_count = igraph_vector_int_size(neighbors); + for (igraph_int_t i = 0; i < neighbor_count; i++) { // Do not add edges to vertices that have not been added. if (VECTOR(*sizes)[VECTOR(*neighbors)[i]] == 0) { continue; @@ -331,7 +331,7 @@ igraph_error_t igraph_site_percolation( igraph_vector_int_t *edge_count, const igraph_vector_int_t *vertex_order) { - const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_int_t vcount = igraph_vcount(graph); const igraph_vector_int_t *p_vertex_order; igraph_vector_int_t i_vertex_order; int iter = 0; @@ -347,9 +347,9 @@ igraph_error_t igraph_site_percolation( } // Initialize variables - igraph_integer_t number_percolated = igraph_vector_int_size(p_vertex_order); - igraph_integer_t biggest = 1; // largest component size so far - igraph_integer_t edges_added = 0; // no. of edges added so far + igraph_int_t number_percolated = igraph_vector_int_size(p_vertex_order); + igraph_int_t biggest = 1; // largest component size so far + igraph_int_t edges_added = 0; // no. of edges added so far igraph_vector_int_t sizes; IGRAPH_VECTOR_INT_INIT_FINALLY(&sizes, vcount); @@ -357,7 +357,7 @@ igraph_error_t igraph_site_percolation( igraph_vector_int_t links; IGRAPH_VECTOR_INT_INIT_FINALLY(&links, vcount); - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { VECTOR(sizes)[i] = 0; VECTOR(links)[i] = i; } @@ -373,8 +373,8 @@ igraph_error_t igraph_site_percolation( } // Percolation - for (igraph_integer_t i = 0; i < number_percolated; i++) { - const igraph_integer_t vid = VECTOR(*p_vertex_order)[i]; + for (igraph_int_t i = 0; i < number_percolated; i++) { + const igraph_int_t vid = VECTOR(*p_vertex_order)[i]; if (vid < 0 || vid >= vcount) { IGRAPH_ERROR("Invalid vertex ID.", IGRAPH_EINVVID); } diff --git a/src/vendor/cigraph/src/connectivity/reachability.c b/src/vendor/cigraph/src/connectivity/reachability.c index 9fa4e51c247..06c2aa1b9a3 100644 --- a/src/vendor/cigraph/src/connectivity/reachability.c +++ b/src/vendor/cigraph/src/connectivity/reachability.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -30,8 +30,6 @@ * \function igraph_reachability * \brief Calculates which vertices are reachable from each vertex in the graph. * - * \experimental - * * The resulting list will contain one bitset for each strongly connected component. * The bitset for component i will have its j-th bit set, if vertex j is reachable * from some vertex in component i in 0 or more steps. @@ -67,7 +65,7 @@ * |C| is the number of strongly connected components (at most |V|), * |V| is the number of vertices, and * |E| is the number of edges respectively, - * and w is the bit width of \type igraph_integer_t, typically the + * and w is the bit width of \type igraph_int_t, typically the * word size of the machine (32 or 64). */ @@ -75,12 +73,12 @@ igraph_error_t igraph_reachability( const igraph_t *graph, igraph_vector_int_t *membership, igraph_vector_int_t *csize, - igraph_integer_t *no_of_components, + igraph_int_t *no_of_components, igraph_bitset_list_t *reach, igraph_neimode_t mode) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_comps; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_comps; igraph_adjlist_t adjlist, dag; if (mode != IGRAPH_ALL && mode != IGRAPH_OUT && mode != IGRAPH_IN) { @@ -101,10 +99,10 @@ igraph_error_t igraph_reachability( IGRAPH_CHECK(igraph_bitset_list_resize(reach, no_of_comps)); - for (igraph_integer_t comp = 0; comp < no_of_comps; comp++) { + for (igraph_int_t comp = 0; comp < no_of_comps; comp++) { IGRAPH_CHECK(igraph_bitset_resize(igraph_bitset_list_get_ptr(reach, comp), no_of_nodes)); } - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { IGRAPH_BIT_SET(*igraph_bitset_list_get_ptr(reach, VECTOR(*membership)[v]), v); } @@ -118,12 +116,12 @@ igraph_error_t igraph_reachability( IGRAPH_CHECK(igraph_adjlist_init_empty(&dag, no_of_comps)); IGRAPH_FINALLY(igraph_adjlist_destroy, &dag); - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { const igraph_vector_int_t *neighbours = igraph_adjlist_get(&adjlist, v); igraph_vector_int_t *dag_neighbours = igraph_adjlist_get(&dag, VECTOR(*membership)[v]); - const igraph_integer_t n = igraph_vector_int_size(neighbours); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t w = VECTOR(*neighbours)[i]; + const igraph_int_t n = igraph_vector_int_size(neighbours); + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t w = VECTOR(*neighbours)[i]; if (VECTOR(*membership)[v] != VECTOR(*membership)[w]) { IGRAPH_CHECK(igraph_vector_int_push_back(dag_neighbours, VECTOR(*membership)[w])); } @@ -132,12 +130,12 @@ igraph_error_t igraph_reachability( /* Iterate through strongly connected components in reverser topological order, * exploiting the fact that they are indexed in topological order. */ - for (igraph_integer_t i = 0; i < no_of_comps; i++) { - const igraph_integer_t comp = mode == IGRAPH_IN ? i : no_of_comps - i - 1; + for (igraph_int_t i = 0; i < no_of_comps; i++) { + const igraph_int_t comp = mode == IGRAPH_IN ? i : no_of_comps - i - 1; const igraph_vector_int_t *dag_neighbours = igraph_adjlist_get(&dag, comp); igraph_bitset_t *from_bitset = igraph_bitset_list_get_ptr(reach, comp); - const igraph_integer_t n = igraph_vector_int_size(dag_neighbours); - for (igraph_integer_t j = 0; j < n; j++) { + const igraph_int_t n = igraph_vector_int_size(dag_neighbours); + for (igraph_int_t j = 0; j < n; j++) { const igraph_bitset_t *to_bitset = igraph_bitset_list_get_ptr(reach, VECTOR(*dag_neighbours)[j]); igraph_bitset_or(from_bitset, from_bitset, to_bitset); } @@ -156,8 +154,6 @@ igraph_error_t igraph_reachability( * \function igraph_count_reachable * \brief The number of vertices reachable from each vertex in the graph. * - * \experimental - * * \param graph The graph object to analyze. * \param counts Integer vector. counts[v] will store the number * of vertices reachable from vertex \c v, including \c v itself. @@ -176,7 +172,7 @@ igraph_error_t igraph_reachability( * |C| is the number of strongly connected components (at most |V|), * |V| is the number of vertices, and * |E| is the number of edges respectively, - * and w is the bit width of \type igraph_integer_t, typically the + * and w is the bit width of \type igraph_int_t, typically the * word size of the machine (32 or 64). */ @@ -185,7 +181,7 @@ igraph_error_t igraph_count_reachable(const igraph_t *graph, igraph_neimode_t mode) { igraph_vector_int_t membership; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_bitset_list_t reach; IGRAPH_VECTOR_INT_INIT_FINALLY(&membership, 0); @@ -194,7 +190,7 @@ igraph_error_t igraph_count_reachable(const igraph_t *graph, IGRAPH_CHECK(igraph_reachability(graph, &membership, NULL, NULL, &reach, mode)); IGRAPH_CHECK(igraph_vector_int_resize(counts, igraph_vcount(graph))); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(*counts)[i] = igraph_bitset_popcount(igraph_bitset_list_get_ptr(&reach, VECTOR(membership)[i])); } @@ -227,7 +223,7 @@ igraph_error_t igraph_count_reachable(const igraph_t *graph, * |E| is the number of edges, respectively. */ igraph_error_t igraph_transitive_closure(const igraph_t *graph, igraph_t *closure) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); const igraph_bool_t directed = igraph_is_directed(graph); igraph_vector_int_t membership, edges; igraph_bitset_list_t reach; @@ -238,9 +234,9 @@ igraph_error_t igraph_transitive_closure(const igraph_t *graph, igraph_t *closur IGRAPH_CHECK(igraph_reachability(graph, &membership, NULL, NULL, &reach, IGRAPH_OUT)); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - for (igraph_integer_t u = 0; u < no_of_nodes; u++) { + for (igraph_int_t u = 0; u < no_of_nodes; u++) { const igraph_bitset_t *row = igraph_bitset_list_get_ptr(&reach, VECTOR(membership)[u]); - for (igraph_integer_t v = directed ? 0 : u + 1; v < no_of_nodes; v++) { + for (igraph_int_t v = directed ? 0 : u + 1; v < no_of_nodes; v++) { if (u != v && IGRAPH_BIT_TEST(*row, v)) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, u)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, v)); diff --git a/src/vendor/cigraph/src/connectivity/separators.c b/src/vendor/cigraph/src/connectivity/separators.c index 8f22b5ca8ae..5c52d217a94 100644 --- a/src/vendor/cigraph/src/connectivity/separators.c +++ b/src/vendor/cigraph/src/connectivity/separators.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -54,7 +54,7 @@ static igraph_error_t igraph_i_is_separator( igraph_bool_t *is_minimal ) { - const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_int_t vcount = igraph_vcount(graph); /* mark[v] means: * @@ -68,7 +68,7 @@ static igraph_error_t igraph_i_is_separator( igraph_vector_int_t neis; igraph_dqueue_int_t Q; igraph_vit_t vit; - igraph_integer_t S_size = 0, S_visited_count = 0; + igraph_int_t S_size = 0, S_visited_count = 0; IGRAPH_CHECK(igraph_vit_create(graph, S, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); @@ -85,7 +85,7 @@ static igraph_error_t igraph_i_is_separator( /* Mark and count vertices in S, taking care not to double-count * when duplicate vertices were passed in. */ for (; ! IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { - const igraph_integer_t u = IGRAPH_VIT_GET(vit); + const igraph_int_t u = IGRAPH_VIT_GET(vit); if (! IN_S(u)) { SET_IN_S(u); S_size++; @@ -103,7 +103,7 @@ static igraph_error_t igraph_i_is_separator( for (IGRAPH_VIT_RESET(vit); ! IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { - const igraph_integer_t u = IGRAPH_VIT_GET(vit); + const igraph_int_t u = IGRAPH_VIT_GET(vit); if (VISITED(u)) { continue; } @@ -132,10 +132,10 @@ static igraph_error_t igraph_i_is_separator( */ /* Sum of in-degrees of visited vertices in S. */ - igraph_integer_t degsum = 0; + igraph_int_t degsum = 0; /* Number of in-edges of vertices in S that were traversed. */ - igraph_integer_t edgecount = 0; + igraph_int_t edgecount = 0; /* Have we already traversed an edge leaving S? */ igraph_bool_t exited = false; @@ -143,7 +143,7 @@ static igraph_error_t igraph_i_is_separator( IGRAPH_CHECK(igraph_dqueue_int_push(&Q, u)); while (! igraph_dqueue_int_empty(&Q)) { - const igraph_integer_t v = igraph_dqueue_int_pop(&Q); + const igraph_int_t v = igraph_dqueue_int_pop(&Q); if (VISITED(v)) { continue; } @@ -153,15 +153,15 @@ static igraph_error_t igraph_i_is_separator( graph, &neis, v, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); - const igraph_integer_t dv = igraph_vector_int_size(&neis); + const igraph_int_t dv = igraph_vector_int_size(&neis); if (IN_S(v)) { degsum += dv; S_visited_count++; } - for (igraph_integer_t i=0; i < dv; i++) { - const igraph_integer_t w = VECTOR(neis)[i]; + for (igraph_int_t i=0; i < dv; i++) { + const igraph_int_t w = VECTOR(neis)[i]; /* Decide whether to traverse the v -> w edge. */ if (!exited || !IN_S(v) || IN_S(w)) { @@ -231,20 +231,20 @@ static igraph_error_t igraph_i_is_separator( #define FLIP_REACHED(x) (VECTOR(mark)[x] ^= 4) /* Flip the reachability status of x in S. */ for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { - const igraph_integer_t u = IGRAPH_VIT_GET(vit); + const igraph_int_t u = IGRAPH_VIT_GET(vit); IGRAPH_CHECK(igraph_neighbors( graph, &Sneis, u, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); - const igraph_integer_t du = igraph_vector_int_size(&Sneis); - for (igraph_integer_t i=0; i < du; i++) { + const igraph_int_t du = igraph_vector_int_size(&Sneis); + for (igraph_int_t i=0; i < du; i++) { - igraph_integer_t v = VECTOR(Sneis)[i]; + igraph_int_t v = VECTOR(Sneis)[i]; if (VISITED(v)) { continue; } /* How many vertices in S were reachable from u? */ - igraph_integer_t S_reached = 0; + igraph_int_t S_reached = 0; IGRAPH_CHECK(igraph_dqueue_int_push(&Q, v)); while (! igraph_dqueue_int_empty(&Q)) { v = igraph_dqueue_int_pop(&Q); @@ -257,10 +257,10 @@ static igraph_error_t igraph_i_is_separator( graph, &neis, v, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); - const igraph_integer_t dv = igraph_vector_int_size(&neis); + const igraph_int_t dv = igraph_vector_int_size(&neis); - for (igraph_integer_t j=0; j < dv; j++) { - const igraph_integer_t w = VECTOR(neis)[j]; + for (igraph_int_t j=0; j < dv; j++) { + const igraph_int_t w = VECTOR(neis)[j]; if (! VISITED(w)) { IGRAPH_CHECK(igraph_dqueue_int_push(&Q, w)); @@ -372,14 +372,14 @@ igraph_error_t igraph_is_minimal_separator(const igraph_t *graph, static igraph_error_t igraph_i_connected_components_leaveout(const igraph_adjlist_t *adjlist, igraph_vector_int_t *components, igraph_vector_int_t *leaveout, - igraph_integer_t *mark, + igraph_int_t *mark, igraph_dqueue_int_t *Q) { /* Another trick: we use the same 'leaveout' vector to mark the * vertices that were already found in the BFS */ - igraph_integer_t i, no_of_nodes = igraph_adjlist_size(adjlist); + igraph_int_t i, no_of_nodes = igraph_adjlist_size(adjlist); igraph_dqueue_int_clear(Q); igraph_vector_int_clear(components); @@ -395,11 +395,11 @@ static igraph_error_t igraph_i_connected_components_leaveout(const igraph_adjlis IGRAPH_CHECK(igraph_vector_int_push_back(components, i)); while (!igraph_dqueue_int_empty(Q)) { - igraph_integer_t act_node = igraph_dqueue_int_pop(Q); + igraph_int_t act_node = igraph_dqueue_int_pop(Q); igraph_vector_int_t *neis = igraph_adjlist_get(adjlist, act_node); - igraph_integer_t j, n = igraph_vector_int_size(neis); + igraph_int_t j, n = igraph_vector_int_size(neis); for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; if (VECTOR(*leaveout)[nei] == *mark) { continue; } @@ -421,7 +421,7 @@ static igraph_bool_t igraph_i_separators_is_not_seen_yet( const igraph_vector_int_list_t *comps, const igraph_vector_int_t *newc ) { - igraph_integer_t co, nocomps = igraph_vector_int_list_size(comps); + igraph_int_t co, nocomps = igraph_vector_int_list_size(comps); for (co = 0; co < nocomps; co++) { igraph_vector_int_t *act = igraph_vector_int_list_get_ptr(comps, co); @@ -438,17 +438,17 @@ static igraph_error_t igraph_i_separators_store(igraph_vector_int_list_t *separa const igraph_adjlist_t *adjlist, igraph_vector_int_t *components, igraph_vector_int_t *leaveout, - igraph_integer_t *mark, + igraph_int_t *mark, igraph_vector_int_t *sorter) { /* We need to store N(C), the neighborhood of C, but only if it is * not already stored among the separators. */ - igraph_integer_t cptr = 0, next, complen = igraph_vector_int_size(components); + igraph_int_t cptr = 0, next, complen = igraph_vector_int_size(components); while (cptr < complen) { - igraph_integer_t saved = cptr; + igraph_int_t saved = cptr; igraph_vector_int_clear(sorter); /* Calculate N(C) for the next C */ @@ -460,9 +460,9 @@ static igraph_error_t igraph_i_separators_store(igraph_vector_int_list_t *separa while ( (next = VECTOR(*components)[cptr++]) != -1) { igraph_vector_int_t *neis = igraph_adjlist_get(adjlist, next); - igraph_integer_t j, nn = igraph_vector_int_size(neis); + igraph_int_t j, nn = igraph_vector_int_size(neis); for (j = 0; j < nn; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; if (VECTOR(*leaveout)[nei] != *mark) { IGRAPH_CHECK(igraph_vector_int_push_back(sorter, nei)); VECTOR(*leaveout)[nei] = *mark; @@ -547,11 +547,11 @@ igraph_error_t igraph_all_minimal_st_separators( * The try_next pointer show the next separator to try as a basis. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t leaveout; - igraph_integer_t try_next = 0; - igraph_integer_t mark = 1; - igraph_integer_t v; + igraph_int_t try_next = 0; + igraph_int_t mark = 1; + igraph_int_t v; igraph_adjlist_t adjlist; igraph_vector_int_t components; @@ -580,10 +580,10 @@ igraph_error_t igraph_all_minimal_st_separators( /* Mark v and its neighbors */ igraph_vector_int_t *neis = igraph_adjlist_get(&adjlist, v); - igraph_integer_t i, n = igraph_vector_int_size(neis); + igraph_int_t i, n = igraph_vector_int_size(neis); VECTOR(leaveout)[v] = mark; for (i = 0; i < n; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; + igraph_int_t nei = VECTOR(*neis)[i]; VECTOR(leaveout)[nei] = mark; } @@ -607,19 +607,19 @@ igraph_error_t igraph_all_minimal_st_separators( * mutate the vector_list later, and this can potentially invalidate * the pointer */ igraph_vector_int_t basis = *(igraph_vector_int_list_get_ptr(separators, try_next)); - igraph_integer_t b, basislen = igraph_vector_int_size(&basis); + igraph_int_t b, basislen = igraph_vector_int_size(&basis); for (b = 0; b < basislen; b++) { /* Remove N(x) U basis */ - igraph_integer_t x = VECTOR(basis)[b]; + igraph_int_t x = VECTOR(basis)[b]; igraph_vector_int_t *neis = igraph_adjlist_get(&adjlist, x); - igraph_integer_t i, n = igraph_vector_int_size(neis); + igraph_int_t i, n = igraph_vector_int_size(neis); for (i = 0; i < basislen; i++) { - igraph_integer_t sn = VECTOR(basis)[i]; + igraph_int_t sn = VECTOR(basis)[i]; VECTOR(leaveout)[sn] = mark; } for (i = 0; i < n; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; + igraph_int_t nei = VECTOR(*neis)[i]; VECTOR(leaveout)[nei] = mark; } @@ -654,8 +654,8 @@ static igraph_error_t igraph_i_minimum_size_separators_append( igraph_vector_int_list_t *old, igraph_vector_int_list_t *new ) { - igraph_integer_t olen = igraph_vector_int_list_size(old); - igraph_integer_t j; + igraph_int_t olen = igraph_vector_int_list_size(old); + igraph_int_t j; while (!igraph_vector_int_list_empty(new)) { igraph_vector_int_t *newvec = igraph_vector_int_list_tail_ptr(new); @@ -688,9 +688,9 @@ static igraph_error_t igraph_i_minimum_size_separators_append( * Finds the k largest degree vertices. */ static igraph_error_t igraph_i_minimum_size_separators_topkdeg( - const igraph_t *graph, igraph_vector_int_t *res, const igraph_integer_t k + const igraph_t *graph, igraph_vector_int_t *res, const igraph_int_t k ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t deg, order; IGRAPH_VECTOR_INT_INIT_FINALLY(°, no_of_nodes); @@ -702,7 +702,7 @@ static igraph_error_t igraph_i_minimum_size_separators_topkdeg( IGRAPH_CHECK(igraph_i_vector_int_order(°, &order, no_of_nodes)); IGRAPH_CHECK(igraph_vector_int_resize(res, k)); - for (igraph_integer_t i = 0; i < k; i++) { + for (igraph_int_t i = 0; i < k; i++) { VECTOR(*res)[i] = VECTOR(order)[no_of_nodes - 1 - i]; } @@ -750,11 +750,11 @@ igraph_error_t igraph_minimum_size_separators( const igraph_t *graph, igraph_vector_int_list_t *separators ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t conn; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t conn; igraph_vector_int_t X; - igraph_integer_t k, n; + igraph_int_t k, n; igraph_bool_t issepX; igraph_t Gbar; igraph_vector_t phi; @@ -785,7 +785,7 @@ igraph_error_t igraph_minimum_size_separators( IGRAPH_CHECK(igraph_articulation_points(graph, &ap)); n = igraph_vector_int_size(&ap); IGRAPH_CHECK(igraph_vector_int_list_resize(separators, n)); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(separators, i); IGRAPH_CHECK(igraph_vector_int_push_back(v, VECTOR(ap)[i])); } @@ -820,12 +820,12 @@ igraph_error_t igraph_minimum_size_separators( /* ---------------------------------------------------------------- */ /* 3 If v[j] != x[i] and v[j] is not adjacent to x[i] then */ - for (igraph_integer_t i = 0; i < k; i++) { + for (igraph_int_t i = 0; i < k; i++) { IGRAPH_ALLOW_INTERRUPTION(); - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { - igraph_integer_t xi = VECTOR(X)[i]; + for (igraph_int_t j = 0; j < no_of_nodes; j++) { + igraph_int_t xi = VECTOR(X)[i]; igraph_real_t phivalue; igraph_bool_t conn; diff --git a/src/vendor/cigraph/src/constructors/adjacency.c b/src/vendor/cigraph/src/constructors/adjacency.c index 694425dbc0f..7043e000237 100644 --- a/src/vendor/cigraph/src/constructors/adjacency.c +++ b/src/vendor/cigraph/src/constructors/adjacency.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -51,7 +51,7 @@ static igraph_error_t igraph_i_adjacency_min( ); static igraph_error_t igraph_i_adjust_loop_edge_count( - igraph_integer_t* count, igraph_loops_t loops + igraph_int_t* count, igraph_loops_t loops ) { /* The compiler should be smart enough to figure out that this can be * inlined */ @@ -77,7 +77,7 @@ static igraph_error_t igraph_i_adjacency_directed_or_plus( const igraph_matrix_t *adjmatrix, igraph_vector_int_t *edges, igraph_adjacency_t mode, igraph_loops_t loops ) { - const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + const igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); /* For sake of consistency with the rest of the library, IGRAPH_LOOPS_TWICE * is treated as IGRAPH_LOOPS_ONCE for directed graphs */ @@ -85,13 +85,13 @@ static igraph_error_t igraph_i_adjacency_directed_or_plus( loops = IGRAPH_LOOPS_ONCE; } - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t M = MATRIX(*adjmatrix, i, j); + for (igraph_int_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t M = MATRIX(*adjmatrix, i, j); if (i == j) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); } - for (igraph_integer_t k = 0; k < M; k++) { + for (igraph_int_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } @@ -106,8 +106,8 @@ static igraph_error_t igraph_i_adjacency_max( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j, k, M1, M2; + igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t i, j, k, M1, M2; for (i = 0; i < no_of_nodes; i++) { /* do the loops first */ @@ -155,8 +155,8 @@ static igraph_error_t igraph_i_adjacency_upper( igraph_loops_t loops ) { - const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t M; + const igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t M; /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense * for loops to appear twice in the adjacency matrix when the lower triangle @@ -169,10 +169,10 @@ static igraph_error_t igraph_i_adjacency_upper( loops = IGRAPH_LOOPS_ONCE; } - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { - for (igraph_integer_t i = 0; i < j; i++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t i = 0; i < j; i++) { M = MATRIX(*adjmatrix, i, j); - for (igraph_integer_t k = 0; k < M; k++) { + for (igraph_int_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } @@ -182,7 +182,7 @@ static igraph_error_t igraph_i_adjacency_upper( M = MATRIX(*adjmatrix, j, j); if (M) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); - for (igraph_integer_t k = 0; k < M; k++) { + for (igraph_int_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } @@ -196,8 +196,8 @@ static igraph_error_t igraph_i_adjacency_lower( igraph_loops_t loops ) { - const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t M; + const igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t M; /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense * for loops to appear twice in the adjacency matrix when the lower triangle @@ -210,20 +210,20 @@ static igraph_error_t igraph_i_adjacency_lower( loops = IGRAPH_LOOPS_ONCE; } - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { /* do the loops first */ M = MATRIX(*adjmatrix, j, j); if (M) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&M, loops)); - for (igraph_integer_t k = 0; k < M; k++) { + for (igraph_int_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } } - for (igraph_integer_t i = j+1; i < no_of_nodes; i++) { + for (igraph_int_t i = j+1; i < no_of_nodes; i++) { M = MATRIX(*adjmatrix, i, j); - for (igraph_integer_t k = 0; k < M; k++) { + for (igraph_int_t k = 0; k < M; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, j)); } @@ -237,8 +237,8 @@ static igraph_error_t igraph_i_adjacency_min( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j, k, M1, M2; + igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t i, j, k, M1, M2; for (i = 0; i < no_of_nodes; i++) { /* do the loops first */ @@ -310,9 +310,9 @@ static igraph_error_t igraph_i_adjacency_min( * An undirected graph will be created. Only the lower left triangle * (including the diagonal) is used for the number of edges. * \endclist - * \param loops Constant to specify how the diagonal of the matrix should be - * treated when creating loop edges. Ignored for modes - * \c IGRAPH_ADJ_DIRECTED, \c IGRAPH_ADJ_UPPER and \c IGRAPH_ADJ_LOWER. + * \param loops Constant of type \ref igraph_loops_t to specify how the diagonal + * of the matrix should be treated when creating loop edges. Ignored for + * modes \c IGRAPH_ADJ_DIRECTED, \c IGRAPH_ADJ_UPPER and \c IGRAPH_ADJ_LOWER. * \clist * \cli IGRAPH_NO_LOOPS * Ignore the diagonal of the input matrix and do not create loops. @@ -331,8 +331,6 @@ static igraph_error_t igraph_i_adjacency_min( * * Time complexity: O(|V||V|), * |V| is the number of vertices in the graph. - * - * \example examples/simple/igraph_adjacency.c */ igraph_error_t igraph_adjacency( igraph_t *graph, const igraph_matrix_t *adjmatrix, igraph_adjacency_t mode, @@ -340,7 +338,7 @@ igraph_error_t igraph_adjacency( ) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); /* Some checks */ if (igraph_matrix_nrow(adjmatrix) != igraph_matrix_ncol(adjmatrix)) { @@ -447,7 +445,7 @@ static igraph_error_t igraph_i_weighted_adjacency_directed( igraph_loops_t loops ) { - const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + const igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); /* For sake of consistency with the rest of the library, IGRAPH_LOOPS_TWICE * is treated as IGRAPH_LOOPS_ONCE for directed graphs */ @@ -455,8 +453,8 @@ static igraph_error_t igraph_i_weighted_adjacency_directed( loops = IGRAPH_LOOPS_ONCE; } - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_real_t M = MATRIX(*adjmatrix, i, j); if (M != 0.0) { if (i == j) { @@ -482,8 +480,8 @@ static igraph_error_t igraph_i_weighted_adjacency_plus( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j; + igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t i, j; igraph_real_t M; for (i = 0; i < no_of_nodes; i++) { @@ -517,8 +515,8 @@ static igraph_error_t igraph_i_weighted_adjacency_max( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j; + igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t i, j; igraph_real_t M1, M2; for (i = 0; i < no_of_nodes; i++) { @@ -559,8 +557,8 @@ static igraph_error_t igraph_i_weighted_adjacency_undirected( /* We do not use igraph_matrix_is_symmetric() for this check, as we need to * allow symmetric matrices with NaN values. igraph_matrix_is_symmetric() * returns false for these as NaN != NaN. */ - const igraph_integer_t n = igraph_matrix_nrow(adjmatrix); - for (igraph_integer_t i=0; i < n; i++) { + const igraph_int_t n = igraph_matrix_nrow(adjmatrix); + for (igraph_int_t i=0; i < n; i++) { /* do the loops first */ if (loops) { igraph_real_t M = MATRIX(*adjmatrix, i, i); @@ -572,7 +570,7 @@ static igraph_error_t igraph_i_weighted_adjacency_undirected( } } - for (igraph_integer_t j=0; j < i; j++) { + for (igraph_int_t j=0; j < i; j++) { igraph_real_t M1 = MATRIX(*adjmatrix, i, j); igraph_real_t M2 = MATRIX(*adjmatrix, j, i); if (IGRAPH_UNLIKELY(M1 != M2 && ! (isnan(M1) && isnan(M2)))) { @@ -598,7 +596,7 @@ static igraph_error_t igraph_i_weighted_adjacency_upper( igraph_loops_t loops ) { - const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + const igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); igraph_real_t M; /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense @@ -612,8 +610,8 @@ static igraph_error_t igraph_i_weighted_adjacency_upper( loops = IGRAPH_LOOPS_ONCE; } - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { - for (igraph_integer_t i = 0; i < j; i++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t i = 0; i < j; i++) { igraph_real_t M = MATRIX(*adjmatrix, i, j); if (M != 0.0) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); @@ -643,7 +641,7 @@ static igraph_error_t igraph_i_weighted_adjacency_lower( igraph_loops_t loops ) { - const igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + const igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); igraph_real_t M; /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense @@ -657,7 +655,7 @@ static igraph_error_t igraph_i_weighted_adjacency_lower( loops = IGRAPH_LOOPS_ONCE; } - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { /* do the loops first */ if (loops) { M = MATRIX(*adjmatrix, j, j); @@ -669,7 +667,7 @@ static igraph_error_t igraph_i_weighted_adjacency_lower( } } - for (igraph_integer_t i = j+1; i < no_of_nodes; i++) { + for (igraph_int_t i = j+1; i < no_of_nodes; i++) { M = MATRIX(*adjmatrix, i, j); if (M != 0.0) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, i)); @@ -688,8 +686,8 @@ static igraph_error_t igraph_i_weighted_adjacency_min( igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(adjmatrix); - igraph_integer_t i, j; + igraph_int_t no_of_nodes = igraph_matrix_nrow(adjmatrix); + igraph_int_t i, j; igraph_real_t M1, M2; for (i = 0; i < no_of_nodes; i++) { @@ -790,7 +788,7 @@ igraph_error_t igraph_weighted_adjacency( ) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t no_of_nodes; + igraph_int_t no_of_nodes; /* Some checks */ if (igraph_matrix_nrow(adjmatrix) != igraph_matrix_ncol(adjmatrix)) { @@ -884,15 +882,15 @@ igraph_error_t igraph_weighted_adjacency( igraph_error_t igraph_adjlist(igraph_t *graph, const igraph_adjlist_t *adjlist, igraph_neimode_t mode, igraph_bool_t duplicate) { - const igraph_integer_t no_of_nodes = igraph_adjlist_size(adjlist); - igraph_integer_t no_of_edges = 0; + const igraph_int_t no_of_nodes = igraph_adjlist_size(adjlist); + igraph_int_t no_of_edges = 0; igraph_vector_int_t edges; - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; duplicate = duplicate && (mode == IGRAPH_ALL); /* only duplicate if undirected */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { no_of_edges += igraph_vector_int_size(igraph_adjlist_get(adjlist, i)); } @@ -902,13 +900,13 @@ igraph_error_t igraph_adjlist(igraph_t *graph, const igraph_adjlist_t *adjlist, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2 * no_of_edges); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_vector_int_t *neis = igraph_adjlist_get(adjlist, i); - const igraph_integer_t n = igraph_vector_int_size(neis); - igraph_integer_t loops = 0; + const igraph_int_t n = igraph_vector_int_size(neis); + igraph_int_t loops = 0; - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t nei = VECTOR(*neis)[j]; if (nei == i) { loops++; } else { @@ -935,7 +933,7 @@ igraph_error_t igraph_adjlist(igraph_t *graph, const igraph_adjlist_t *adjlist, IGRAPH_ERROR("Invalid adjacency list, most probably not correctly" " duplicated edges for an undirected graph.", IGRAPH_EINVAL); } - for (igraph_integer_t j = 0; j < loops; j++) { + for (igraph_int_t j = 0; j < loops; j++) { VECTOR(edges)[edgeptr++] = i; VECTOR(edges)[edgeptr++] = i; } @@ -967,13 +965,13 @@ static igraph_error_t igraph_i_sparse_adjacency_directed_or_plus( } for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); - igraph_integer_t multi = igraph_sparsemat_iterator_get(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t multi = igraph_sparsemat_iterator_get(&it); if (to == from) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&multi, loops)); } - for (igraph_integer_t count = 0; count < multi; count++) { + for (igraph_int_t count = 0; count < multi; count++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, to)); } @@ -990,19 +988,19 @@ static igraph_error_t igraph_i_sparse_adjacency_max( igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); if (to < from) { continue; } - igraph_integer_t multi = igraph_sparsemat_iterator_get(&it); + igraph_int_t multi = igraph_sparsemat_iterator_get(&it); if (to == from) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&multi, loops)); } else { other = igraph_sparsemat_get(adjmatrix, to, from); multi = multi > other ? multi : other; } - for (igraph_integer_t count = 0; count < multi; count++) { + for (igraph_int_t count = 0; count < multi; count++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, to)); } @@ -1020,19 +1018,19 @@ static igraph_error_t igraph_i_sparse_adjacency_min( igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); if (to < from) { continue; } - igraph_integer_t multi = igraph_sparsemat_iterator_get(&it); + igraph_int_t multi = igraph_sparsemat_iterator_get(&it); if (to == from) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&multi, loops)); } else { other = igraph_sparsemat_get(adjmatrix, to, from); multi = multi < other ? multi : other; } - for (igraph_integer_t count = 0; count < multi; count++) { + for (igraph_int_t count = 0; count < multi; count++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, to)); } @@ -1060,16 +1058,16 @@ static igraph_error_t igraph_i_sparse_adjacency_upper( igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); if (to < from) { continue; } - igraph_integer_t multi = igraph_sparsemat_iterator_get(&it); + igraph_int_t multi = igraph_sparsemat_iterator_get(&it); if (to == from) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&multi, loops)); } - for (igraph_integer_t count = 0; count < multi; count++) { + for (igraph_int_t count = 0; count < multi; count++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, to)); } @@ -1097,16 +1095,16 @@ static igraph_error_t igraph_i_sparse_adjacency_lower( igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); if (to > from) { continue; } - igraph_integer_t multi = igraph_sparsemat_iterator_get(&it); + igraph_int_t multi = igraph_sparsemat_iterator_get(&it); if (to == from) { IGRAPH_CHECK(igraph_i_adjust_loop_edge_count(&multi, loops)); } - for (igraph_integer_t count = 0; count < multi; count++) { + for (igraph_int_t count = 0; count < multi; count++) { IGRAPH_CHECK(igraph_vector_int_push_back(edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(edges, to)); } @@ -1147,9 +1145,9 @@ igraph_error_t igraph_sparse_adjacency(igraph_t *graph, igraph_sparsemat_t *adjm igraph_adjacency_t mode, igraph_loops_t loops) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t no_of_nodes = igraph_sparsemat_nrow(adjmatrix); - igraph_integer_t no_of_nonzeros = igraph_sparsemat_count_nonzero(adjmatrix); - igraph_integer_t approx_no_of_edges; + igraph_int_t no_of_nodes = igraph_sparsemat_nrow(adjmatrix); + igraph_int_t no_of_nonzeros = igraph_sparsemat_count_nonzero(adjmatrix); + igraph_int_t approx_no_of_edges; if (!igraph_sparsemat_is_cc(adjmatrix)) { IGRAPH_ERROR("Sparse adjacency matrix should be in column-compressed " @@ -1225,12 +1223,12 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_max ( ) { igraph_sparsemat_iterator_t it; igraph_sparsemat_iterator_init(&it, adjmatrix); - igraph_integer_t e = 0; + igraph_int_t e = 0; igraph_real_t other; for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); if (to < from) { continue; } @@ -1258,13 +1256,13 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_min ( igraph_vector_t *weights, igraph_loops_t loops ) { igraph_sparsemat_iterator_t it; - igraph_integer_t e = 0; + igraph_int_t e = 0; igraph_real_t other; igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); if (to < from) { continue; } @@ -1292,13 +1290,13 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_plus ( igraph_vector_t *weights, igraph_loops_t loops ) { igraph_sparsemat_iterator_t it; - igraph_integer_t e = 0; + igraph_int_t e = 0; igraph_real_t other; igraph_sparsemat_iterator_init(&it, adjmatrix); for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); if (to < from) { continue; } @@ -1327,7 +1325,7 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_upper( ) { igraph_sparsemat_iterator_t it; igraph_sparsemat_iterator_init(&it, adjmatrix); - igraph_integer_t e = 0; + igraph_int_t e = 0; /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense * for loops to appear twice in the adjacency matrix when the lower triangle @@ -1341,8 +1339,8 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_upper( } for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); igraph_real_t weight = igraph_sparsemat_iterator_get(&it); if (to < from) { continue; @@ -1368,7 +1366,7 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_lower( ) { igraph_sparsemat_iterator_t it; igraph_sparsemat_iterator_init(&it, adjmatrix); - igraph_integer_t e = 0; + igraph_int_t e = 0; /* IGRAPH_LOOPS_TWICE is treated as IGRAPH_LOOPS_ONCE -- it makes no sense * for loops to appear twice in the adjacency matrix when the lower triangle @@ -1382,8 +1380,8 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_lower( } for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); igraph_real_t weight = igraph_sparsemat_iterator_get(&it); if (to > from) { continue; @@ -1426,7 +1424,7 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_directed( ) { igraph_sparsemat_iterator_t it; igraph_sparsemat_iterator_init(&it, adjmatrix); - igraph_integer_t e = 0; + igraph_int_t e = 0; /* For sake of consistency with the rest of the library, IGRAPH_LOOPS_TWICE * is treated as IGRAPH_LOOPS_ONCE for directed graphs */ @@ -1435,8 +1433,8 @@ static igraph_error_t igraph_i_sparse_weighted_adjacency_directed( } for (; !igraph_sparsemat_iterator_end(&it); igraph_sparsemat_iterator_next(&it)) { - igraph_integer_t from = igraph_sparsemat_iterator_row(&it); - igraph_integer_t to = igraph_sparsemat_iterator_col(&it); + igraph_int_t from = igraph_sparsemat_iterator_row(&it); + igraph_int_t to = igraph_sparsemat_iterator_col(&it); igraph_real_t weight = igraph_sparsemat_iterator_get(&it); if (to == from) { igraph_i_adjust_loop_edge_weight(&weight, loops); @@ -1472,8 +1470,8 @@ igraph_error_t igraph_sparse_weighted_adjacency( igraph_vector_t *weights, igraph_loops_t loops ) { igraph_vector_int_t edges; - igraph_integer_t no_of_nodes = igraph_sparsemat_nrow(adjmatrix); - igraph_integer_t no_of_edges = igraph_sparsemat_count_nonzero(adjmatrix); + igraph_int_t no_of_nodes = igraph_sparsemat_nrow(adjmatrix); + igraph_int_t no_of_edges = igraph_sparsemat_count_nonzero(adjmatrix); if (!igraph_sparsemat_is_cc(adjmatrix)) { IGRAPH_ERROR("Sparse adjacency matrix should be in column-compressed form.", IGRAPH_EINVAL); diff --git a/src/vendor/cigraph/src/constructors/atlas-edges.h b/src/vendor/cigraph/src/constructors/atlas-edges.h index c22560b58de..accc395f728 100644 --- a/src/vendor/cigraph/src/constructors/atlas-edges.h +++ b/src/vendor/cigraph/src/constructors/atlas-edges.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -28,7 +28,7 @@ IGRAPH_BEGIN_C_DECLS -const igraph_integer_t igraph_i_atlas_edges[] = { +const igraph_int_t igraph_i_atlas_edges[] = { 0, 0, 1, 0, 2, 0, @@ -1284,7 +1284,7 @@ const igraph_integer_t igraph_i_atlas_edges[] = { 7, 21, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 2, 3, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6, 4, 5, 4, 6, 5, 6, }; -const igraph_integer_t igraph_i_atlas_edges_pos[] = {0, 2, 4, 6, 10, 12, 16, 22, 30, 32, 36, 42, 48, 56, 64, 72, 82, 92, 104, 118, 120, 124, 130, 136, 144, 152, 160, 168, 178, 188, 198, 208, 218, 228, 240, 252, 264, 276, 288, 300, 314, 328, 342, 356, 370, 384, 400, 416, 432, 448, 466, 484, 504, 526, 528, 532, 538, 544, 552, 560, 568, 576, 584, 594, 604, 614, 624, 634, 644, 654, 664, 674, 686, 698, 710, 722, 734, 746, 758, 770, 782, 794, 806, 818, 830, 842, 854, 868, 882, 896, 910, 924, 938, 952, 966, 980, 994, 1008, 1022, 1036, 1050, 1064, 1078, 1092, 1106, 1120, 1134, 1148, 1164, 1180, 1196, 1212, 1228, 1244, 1260, 1276, 1292, 1308, 1324, 1340, 1356, 1372, 1388, 1404, 1420, 1436, 1452, 1468, 1484, 1500, 1516, 1532, 1550, 1568, 1586, 1604, 1622, 1640, 1658, 1676, 1694, 1712, 1730, 1748, 1766, 1784, 1802, 1820, 1838, 1856, 1874, 1892, 1910, 1928, 1946, 1964, 1984, 2004, 2024, 2044, 2064, 2084, 2104, 2124, 2144, 2164, 2184, 2204, 2224, 2244, 2264, 2284, 2304, 2324, 2344, 2364, 2384, 2406, 2428, 2450, 2472, 2494, 2516, 2538, 2560, 2582, 2604, 2626, 2648, 2670, 2692, 2714, 2738, 2762, 2786, 2810, 2834, 2858, 2882, 2906, 2930, 2956, 2982, 3008, 3034, 3060, 3088, 3116, 3146, 3178, 3180, 3184, 3190, 3196, 3204, 3212, 3220, 3228, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, 3326, 3336, 3348, 3360, 3372, 3384, 3396, 3408, 3420, 3432, 3444, 3456, 3468, 3480, 3492, 3504, 3516, 3528, 3540, 3552, 3564, 3576, 3588, 3602, 3616, 3630, 3644, 3658, 3672, 3686, 3700, 3714, 3728, 3742, 3756, 3770, 3784, 3798, 3812, 3826, 3840, 3854, 3868, 3882, 3896, 3910, 3924, 3938, 3952, 3966, 3980, 3994, 4008, 4022, 4036, 4050, 4064, 4078, 4092, 4106, 4120, 4134, 4148, 4162, 4178, 4194, 4210, 4226, 4242, 4258, 4274, 4290, 4306, 4322, 4338, 4354, 4370, 4386, 4402, 4418, 4434, 4450, 4466, 4482, 4498, 4514, 4530, 4546, 4562, 4578, 4594, 4610, 4626, 4642, 4658, 4674, 4690, 4706, 4722, 4738, 4754, 4770, 4786, 4802, 4818, 4834, 4850, 4866, 4882, 4898, 4914, 4930, 4946, 4962, 4978, 4994, 5010, 5026, 5042, 5058, 5074, 5090, 5106, 5122, 5138, 5154, 5170, 5186, 5202, 5220, 5238, 5256, 5274, 5292, 5310, 5328, 5346, 5364, 5382, 5400, 5418, 5436, 5454, 5472, 5490, 5508, 5526, 5544, 5562, 5580, 5598, 5616, 5634, 5652, 5670, 5688, 5706, 5724, 5742, 5760, 5778, 5796, 5814, 5832, 5850, 5868, 5886, 5904, 5922, 5940, 5958, 5976, 5994, 6012, 6030, 6048, 6066, 6084, 6102, 6120, 6138, 6156, 6174, 6192, 6210, 6228, 6246, 6264, 6282, 6300, 6318, 6336, 6354, 6372, 6390, 6408, 6426, 6444, 6462, 6480, 6498, 6516, 6534, 6552, 6570, 6588, 6606, 6624, 6642, 6660, 6678, 6696, 6714, 6732, 6750, 6768, 6786, 6804, 6822, 6840, 6858, 6876, 6894, 6912, 6930, 6948, 6968, 6988, 7008, 7028, 7048, 7068, 7088, 7108, 7128, 7148, 7168, 7188, 7208, 7228, 7248, 7268, 7288, 7308, 7328, 7348, 7368, 7388, 7408, 7428, 7448, 7468, 7488, 7508, 7528, 7548, 7568, 7588, 7608, 7628, 7648, 7668, 7688, 7708, 7728, 7748, 7768, 7788, 7808, 7828, 7848, 7868, 7888, 7908, 7928, 7948, 7968, 7988, 8008, 8028, 8048, 8068, 8088, 8108, 8128, 8148, 8168, 8188, 8208, 8228, 8248, 8268, 8288, 8308, 8328, 8348, 8368, 8388, 8408, 8428, 8448, 8468, 8488, 8508, 8528, 8548, 8568, 8588, 8608, 8628, 8648, 8668, 8688, 8708, 8728, 8748, 8768, 8788, 8808, 8828, 8848, 8868, 8888, 8908, 8928, 8948, 8968, 8988, 9008, 9028, 9048, 9068, 9088, 9108, 9128, 9148, 9168, 9188, 9208, 9228, 9248, 9268, 9288, 9308, 9328, 9348, 9368, 9388, 9408, 9428, 9448, 9468, 9488, 9508, 9528, 9548, 9568, 9590, 9612, 9634, 9656, 9678, 9700, 9722, 9744, 9766, 9788, 9810, 9832, 9854, 9876, 9898, 9920, 9942, 9964, 9986, 10008, 10030, 10052, 10074, 10096, 10118, 10140, 10162, 10184, 10206, 10228, 10250, 10272, 10294, 10316, 10338, 10360, 10382, 10404, 10426, 10448, 10470, 10492, 10514, 10536, 10558, 10580, 10602, 10624, 10646, 10668, 10690, 10712, 10734, 10756, 10778, 10800, 10822, 10844, 10866, 10888, 10910, 10932, 10954, 10976, 10998, 11020, 11042, 11064, 11086, 11108, 11130, 11152, 11174, 11196, 11218, 11240, 11262, 11284, 11306, 11328, 11350, 11372, 11394, 11416, 11438, 11460, 11482, 11504, 11526, 11548, 11570, 11592, 11614, 11636, 11658, 11680, 11702, 11724, 11746, 11768, 11790, 11812, 11834, 11856, 11878, 11900, 11922, 11944, 11966, 11988, 12010, 12032, 12054, 12076, 12098, 12120, 12142, 12164, 12186, 12208, 12230, 12252, 12274, 12296, 12318, 12340, 12362, 12384, 12406, 12428, 12450, 12472, 12494, 12516, 12538, 12560, 12582, 12604, 12626, 12648, 12670, 12692, 12714, 12736, 12758, 12780, 12802, 12824, 12848, 12872, 12896, 12920, 12944, 12968, 12992, 13016, 13040, 13064, 13088, 13112, 13136, 13160, 13184, 13208, 13232, 13256, 13280, 13304, 13328, 13352, 13376, 13400, 13424, 13448, 13472, 13496, 13520, 13544, 13568, 13592, 13616, 13640, 13664, 13688, 13712, 13736, 13760, 13784, 13808, 13832, 13856, 13880, 13904, 13928, 13952, 13976, 14000, 14024, 14048, 14072, 14096, 14120, 14144, 14168, 14192, 14216, 14240, 14264, 14288, 14312, 14336, 14360, 14384, 14408, 14432, 14456, 14480, 14504, 14528, 14552, 14576, 14600, 14624, 14648, 14672, 14696, 14720, 14744, 14768, 14792, 14816, 14840, 14864, 14888, 14912, 14936, 14960, 14984, 15008, 15032, 15056, 15080, 15104, 15128, 15152, 15176, 15200, 15224, 15248, 15272, 15296, 15320, 15344, 15368, 15392, 15416, 15440, 15464, 15488, 15512, 15536, 15560, 15584, 15608, 15632, 15656, 15680, 15704, 15728, 15752, 15776, 15800, 15824, 15848, 15872, 15896, 15920, 15944, 15968, 15992, 16016, 16040, 16064, 16088, 16112, 16136, 16160, 16184, 16208, 16232, 16256, 16280, 16304, 16328, 16352, 16376, 16402, 16428, 16454, 16480, 16506, 16532, 16558, 16584, 16610, 16636, 16662, 16688, 16714, 16740, 16766, 16792, 16818, 16844, 16870, 16896, 16922, 16948, 16974, 17000, 17026, 17052, 17078, 17104, 17130, 17156, 17182, 17208, 17234, 17260, 17286, 17312, 17338, 17364, 17390, 17416, 17442, 17468, 17494, 17520, 17546, 17572, 17598, 17624, 17650, 17676, 17702, 17728, 17754, 17780, 17806, 17832, 17858, 17884, 17910, 17936, 17962, 17988, 18014, 18040, 18066, 18092, 18118, 18144, 18170, 18196, 18222, 18248, 18274, 18300, 18326, 18352, 18378, 18404, 18430, 18456, 18482, 18508, 18534, 18560, 18586, 18612, 18638, 18664, 18690, 18716, 18742, 18768, 18794, 18820, 18846, 18872, 18898, 18924, 18950, 18976, 19002, 19028, 19054, 19080, 19106, 19132, 19158, 19184, 19210, 19236, 19262, 19288, 19314, 19340, 19366, 19392, 19418, 19444, 19470, 19496, 19522, 19548, 19574, 19600, 19626, 19652, 19678, 19704, 19730, 19756, 19782, 19810, 19838, 19866, 19894, 19922, 19950, 19978, 20006, 20034, 20062, 20090, 20118, 20146, 20174, 20202, 20230, 20258, 20286, 20314, 20342, 20370, 20398, 20426, 20454, 20482, 20510, 20538, 20566, 20594, 20622, 20650, 20678, 20706, 20734, 20762, 20790, 20818, 20846, 20874, 20902, 20930, 20958, 20986, 21014, 21042, 21070, 21098, 21126, 21154, 21182, 21210, 21238, 21266, 21294, 21322, 21350, 21378, 21406, 21434, 21462, 21490, 21518, 21546, 21574, 21602, 21630, 21658, 21686, 21714, 21742, 21770, 21798, 21826, 21854, 21882, 21910, 21938, 21966, 21994, 22022, 22050, 22078, 22106, 22134, 22162, 22190, 22218, 22246, 22274, 22302, 22330, 22358, 22386, 22414, 22442, 22470, 22498, 22528, 22558, 22588, 22618, 22648, 22678, 22708, 22738, 22768, 22798, 22828, 22858, 22888, 22918, 22948, 22978, 23008, 23038, 23068, 23098, 23128, 23158, 23188, 23218, 23248, 23278, 23308, 23338, 23368, 23398, 23428, 23458, 23488, 23518, 23548, 23578, 23608, 23638, 23668, 23698, 23728, 23758, 23788, 23818, 23848, 23878, 23908, 23938, 23968, 23998, 24028, 24058, 24088, 24118, 24148, 24178, 24208, 24238, 24268, 24298, 24328, 24358, 24388, 24418, 24448, 24480, 24512, 24544, 24576, 24608, 24640, 24672, 24704, 24736, 24768, 24800, 24832, 24864, 24896, 24928, 24960, 24992, 25024, 25056, 25088, 25120, 25152, 25184, 25216, 25248, 25280, 25312, 25344, 25376, 25408, 25440, 25472, 25504, 25536, 25568, 25600, 25632, 25664, 25696, 25728, 25760, 25794, 25828, 25862, 25896, 25930, 25964, 25998, 26032, 26066, 26100, 26134, 26168, 26202, 26236, 26270, 26304, 26338, 26372, 26406, 26440, 26474, 26510, 26546, 26582, 26618, 26654, 26690, 26726, 26762, 26798, 26834, 26872, 26910, 26948, 26986, 27024, 27064, 27104, 27146}; +const igraph_int_t igraph_i_atlas_edges_pos[] = {0, 2, 4, 6, 10, 12, 16, 22, 30, 32, 36, 42, 48, 56, 64, 72, 82, 92, 104, 118, 120, 124, 130, 136, 144, 152, 160, 168, 178, 188, 198, 208, 218, 228, 240, 252, 264, 276, 288, 300, 314, 328, 342, 356, 370, 384, 400, 416, 432, 448, 466, 484, 504, 526, 528, 532, 538, 544, 552, 560, 568, 576, 584, 594, 604, 614, 624, 634, 644, 654, 664, 674, 686, 698, 710, 722, 734, 746, 758, 770, 782, 794, 806, 818, 830, 842, 854, 868, 882, 896, 910, 924, 938, 952, 966, 980, 994, 1008, 1022, 1036, 1050, 1064, 1078, 1092, 1106, 1120, 1134, 1148, 1164, 1180, 1196, 1212, 1228, 1244, 1260, 1276, 1292, 1308, 1324, 1340, 1356, 1372, 1388, 1404, 1420, 1436, 1452, 1468, 1484, 1500, 1516, 1532, 1550, 1568, 1586, 1604, 1622, 1640, 1658, 1676, 1694, 1712, 1730, 1748, 1766, 1784, 1802, 1820, 1838, 1856, 1874, 1892, 1910, 1928, 1946, 1964, 1984, 2004, 2024, 2044, 2064, 2084, 2104, 2124, 2144, 2164, 2184, 2204, 2224, 2244, 2264, 2284, 2304, 2324, 2344, 2364, 2384, 2406, 2428, 2450, 2472, 2494, 2516, 2538, 2560, 2582, 2604, 2626, 2648, 2670, 2692, 2714, 2738, 2762, 2786, 2810, 2834, 2858, 2882, 2906, 2930, 2956, 2982, 3008, 3034, 3060, 3088, 3116, 3146, 3178, 3180, 3184, 3190, 3196, 3204, 3212, 3220, 3228, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, 3326, 3336, 3348, 3360, 3372, 3384, 3396, 3408, 3420, 3432, 3444, 3456, 3468, 3480, 3492, 3504, 3516, 3528, 3540, 3552, 3564, 3576, 3588, 3602, 3616, 3630, 3644, 3658, 3672, 3686, 3700, 3714, 3728, 3742, 3756, 3770, 3784, 3798, 3812, 3826, 3840, 3854, 3868, 3882, 3896, 3910, 3924, 3938, 3952, 3966, 3980, 3994, 4008, 4022, 4036, 4050, 4064, 4078, 4092, 4106, 4120, 4134, 4148, 4162, 4178, 4194, 4210, 4226, 4242, 4258, 4274, 4290, 4306, 4322, 4338, 4354, 4370, 4386, 4402, 4418, 4434, 4450, 4466, 4482, 4498, 4514, 4530, 4546, 4562, 4578, 4594, 4610, 4626, 4642, 4658, 4674, 4690, 4706, 4722, 4738, 4754, 4770, 4786, 4802, 4818, 4834, 4850, 4866, 4882, 4898, 4914, 4930, 4946, 4962, 4978, 4994, 5010, 5026, 5042, 5058, 5074, 5090, 5106, 5122, 5138, 5154, 5170, 5186, 5202, 5220, 5238, 5256, 5274, 5292, 5310, 5328, 5346, 5364, 5382, 5400, 5418, 5436, 5454, 5472, 5490, 5508, 5526, 5544, 5562, 5580, 5598, 5616, 5634, 5652, 5670, 5688, 5706, 5724, 5742, 5760, 5778, 5796, 5814, 5832, 5850, 5868, 5886, 5904, 5922, 5940, 5958, 5976, 5994, 6012, 6030, 6048, 6066, 6084, 6102, 6120, 6138, 6156, 6174, 6192, 6210, 6228, 6246, 6264, 6282, 6300, 6318, 6336, 6354, 6372, 6390, 6408, 6426, 6444, 6462, 6480, 6498, 6516, 6534, 6552, 6570, 6588, 6606, 6624, 6642, 6660, 6678, 6696, 6714, 6732, 6750, 6768, 6786, 6804, 6822, 6840, 6858, 6876, 6894, 6912, 6930, 6948, 6968, 6988, 7008, 7028, 7048, 7068, 7088, 7108, 7128, 7148, 7168, 7188, 7208, 7228, 7248, 7268, 7288, 7308, 7328, 7348, 7368, 7388, 7408, 7428, 7448, 7468, 7488, 7508, 7528, 7548, 7568, 7588, 7608, 7628, 7648, 7668, 7688, 7708, 7728, 7748, 7768, 7788, 7808, 7828, 7848, 7868, 7888, 7908, 7928, 7948, 7968, 7988, 8008, 8028, 8048, 8068, 8088, 8108, 8128, 8148, 8168, 8188, 8208, 8228, 8248, 8268, 8288, 8308, 8328, 8348, 8368, 8388, 8408, 8428, 8448, 8468, 8488, 8508, 8528, 8548, 8568, 8588, 8608, 8628, 8648, 8668, 8688, 8708, 8728, 8748, 8768, 8788, 8808, 8828, 8848, 8868, 8888, 8908, 8928, 8948, 8968, 8988, 9008, 9028, 9048, 9068, 9088, 9108, 9128, 9148, 9168, 9188, 9208, 9228, 9248, 9268, 9288, 9308, 9328, 9348, 9368, 9388, 9408, 9428, 9448, 9468, 9488, 9508, 9528, 9548, 9568, 9590, 9612, 9634, 9656, 9678, 9700, 9722, 9744, 9766, 9788, 9810, 9832, 9854, 9876, 9898, 9920, 9942, 9964, 9986, 10008, 10030, 10052, 10074, 10096, 10118, 10140, 10162, 10184, 10206, 10228, 10250, 10272, 10294, 10316, 10338, 10360, 10382, 10404, 10426, 10448, 10470, 10492, 10514, 10536, 10558, 10580, 10602, 10624, 10646, 10668, 10690, 10712, 10734, 10756, 10778, 10800, 10822, 10844, 10866, 10888, 10910, 10932, 10954, 10976, 10998, 11020, 11042, 11064, 11086, 11108, 11130, 11152, 11174, 11196, 11218, 11240, 11262, 11284, 11306, 11328, 11350, 11372, 11394, 11416, 11438, 11460, 11482, 11504, 11526, 11548, 11570, 11592, 11614, 11636, 11658, 11680, 11702, 11724, 11746, 11768, 11790, 11812, 11834, 11856, 11878, 11900, 11922, 11944, 11966, 11988, 12010, 12032, 12054, 12076, 12098, 12120, 12142, 12164, 12186, 12208, 12230, 12252, 12274, 12296, 12318, 12340, 12362, 12384, 12406, 12428, 12450, 12472, 12494, 12516, 12538, 12560, 12582, 12604, 12626, 12648, 12670, 12692, 12714, 12736, 12758, 12780, 12802, 12824, 12848, 12872, 12896, 12920, 12944, 12968, 12992, 13016, 13040, 13064, 13088, 13112, 13136, 13160, 13184, 13208, 13232, 13256, 13280, 13304, 13328, 13352, 13376, 13400, 13424, 13448, 13472, 13496, 13520, 13544, 13568, 13592, 13616, 13640, 13664, 13688, 13712, 13736, 13760, 13784, 13808, 13832, 13856, 13880, 13904, 13928, 13952, 13976, 14000, 14024, 14048, 14072, 14096, 14120, 14144, 14168, 14192, 14216, 14240, 14264, 14288, 14312, 14336, 14360, 14384, 14408, 14432, 14456, 14480, 14504, 14528, 14552, 14576, 14600, 14624, 14648, 14672, 14696, 14720, 14744, 14768, 14792, 14816, 14840, 14864, 14888, 14912, 14936, 14960, 14984, 15008, 15032, 15056, 15080, 15104, 15128, 15152, 15176, 15200, 15224, 15248, 15272, 15296, 15320, 15344, 15368, 15392, 15416, 15440, 15464, 15488, 15512, 15536, 15560, 15584, 15608, 15632, 15656, 15680, 15704, 15728, 15752, 15776, 15800, 15824, 15848, 15872, 15896, 15920, 15944, 15968, 15992, 16016, 16040, 16064, 16088, 16112, 16136, 16160, 16184, 16208, 16232, 16256, 16280, 16304, 16328, 16352, 16376, 16402, 16428, 16454, 16480, 16506, 16532, 16558, 16584, 16610, 16636, 16662, 16688, 16714, 16740, 16766, 16792, 16818, 16844, 16870, 16896, 16922, 16948, 16974, 17000, 17026, 17052, 17078, 17104, 17130, 17156, 17182, 17208, 17234, 17260, 17286, 17312, 17338, 17364, 17390, 17416, 17442, 17468, 17494, 17520, 17546, 17572, 17598, 17624, 17650, 17676, 17702, 17728, 17754, 17780, 17806, 17832, 17858, 17884, 17910, 17936, 17962, 17988, 18014, 18040, 18066, 18092, 18118, 18144, 18170, 18196, 18222, 18248, 18274, 18300, 18326, 18352, 18378, 18404, 18430, 18456, 18482, 18508, 18534, 18560, 18586, 18612, 18638, 18664, 18690, 18716, 18742, 18768, 18794, 18820, 18846, 18872, 18898, 18924, 18950, 18976, 19002, 19028, 19054, 19080, 19106, 19132, 19158, 19184, 19210, 19236, 19262, 19288, 19314, 19340, 19366, 19392, 19418, 19444, 19470, 19496, 19522, 19548, 19574, 19600, 19626, 19652, 19678, 19704, 19730, 19756, 19782, 19810, 19838, 19866, 19894, 19922, 19950, 19978, 20006, 20034, 20062, 20090, 20118, 20146, 20174, 20202, 20230, 20258, 20286, 20314, 20342, 20370, 20398, 20426, 20454, 20482, 20510, 20538, 20566, 20594, 20622, 20650, 20678, 20706, 20734, 20762, 20790, 20818, 20846, 20874, 20902, 20930, 20958, 20986, 21014, 21042, 21070, 21098, 21126, 21154, 21182, 21210, 21238, 21266, 21294, 21322, 21350, 21378, 21406, 21434, 21462, 21490, 21518, 21546, 21574, 21602, 21630, 21658, 21686, 21714, 21742, 21770, 21798, 21826, 21854, 21882, 21910, 21938, 21966, 21994, 22022, 22050, 22078, 22106, 22134, 22162, 22190, 22218, 22246, 22274, 22302, 22330, 22358, 22386, 22414, 22442, 22470, 22498, 22528, 22558, 22588, 22618, 22648, 22678, 22708, 22738, 22768, 22798, 22828, 22858, 22888, 22918, 22948, 22978, 23008, 23038, 23068, 23098, 23128, 23158, 23188, 23218, 23248, 23278, 23308, 23338, 23368, 23398, 23428, 23458, 23488, 23518, 23548, 23578, 23608, 23638, 23668, 23698, 23728, 23758, 23788, 23818, 23848, 23878, 23908, 23938, 23968, 23998, 24028, 24058, 24088, 24118, 24148, 24178, 24208, 24238, 24268, 24298, 24328, 24358, 24388, 24418, 24448, 24480, 24512, 24544, 24576, 24608, 24640, 24672, 24704, 24736, 24768, 24800, 24832, 24864, 24896, 24928, 24960, 24992, 25024, 25056, 25088, 25120, 25152, 25184, 25216, 25248, 25280, 25312, 25344, 25376, 25408, 25440, 25472, 25504, 25536, 25568, 25600, 25632, 25664, 25696, 25728, 25760, 25794, 25828, 25862, 25896, 25930, 25964, 25998, 26032, 26066, 26100, 26134, 26168, 26202, 26236, 26270, 26304, 26338, 26372, 26406, 26440, 26474, 26510, 26546, 26582, 26618, 26654, 26690, 26726, 26762, 26798, 26834, 26872, 26910, 26948, 26986, 27024, 27064, 27104, 27146}; IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/constructors/atlas.c b/src/vendor/cigraph/src/constructors/atlas.c index b8a6751a197..fac3875de0f 100644 --- a/src/vendor/cigraph/src/constructors/atlas.c +++ b/src/vendor/cigraph/src/constructors/atlas.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -60,10 +60,9 @@ * * \example examples/simple/igraph_atlas.c */ -igraph_error_t igraph_atlas(igraph_t *graph, igraph_integer_t number) { +igraph_error_t igraph_atlas(igraph_t *graph, igraph_int_t number) { - igraph_vector_int_t v; - const igraph_integer_t atlas_size = + const igraph_int_t atlas_size = sizeof(igraph_i_atlas_edges_pos) / sizeof(igraph_i_atlas_edges_pos[0]); if (number < 0 || @@ -74,12 +73,13 @@ igraph_error_t igraph_atlas(igraph_t *graph, igraph_integer_t number) { atlas_size); } - igraph_integer_t pos = igraph_i_atlas_edges_pos[number]; - igraph_integer_t n = igraph_i_atlas_edges[pos]; - igraph_integer_t e = igraph_i_atlas_edges[pos + 1]; + igraph_int_t pos = igraph_i_atlas_edges_pos[number]; + igraph_int_t n = igraph_i_atlas_edges[pos]; + igraph_int_t e = igraph_i_atlas_edges[pos + 1]; + const igraph_vector_int_t edges = igraph_vector_int_view(igraph_i_atlas_edges + pos + 2, e * 2); IGRAPH_CHECK(igraph_create(graph, - igraph_vector_int_view(&v, igraph_i_atlas_edges + pos + 2, e * 2), + &edges, n, IGRAPH_UNDIRECTED)); diff --git a/src/vendor/cigraph/src/constructors/basic_constructors.c b/src/vendor/cigraph/src/constructors/basic_constructors.c index b626884cdf8..c048e1dd6fd 100644 --- a/src/vendor/cigraph/src/constructors/basic_constructors.c +++ b/src/vendor/cigraph/src/constructors/basic_constructors.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -23,16 +23,6 @@ #include "igraph_interface.h" -/** - * \section about_generators - * - * Graph generators create graphs. - * - * Almost all functions which create graph objects are documented - * here. The exceptions are \ref igraph_induced_subgraph() and alike, these - * create graphs based on another graph. - */ - /** * \ingroup generators @@ -61,9 +51,9 @@ * \example examples/simple/igraph_create.c */ igraph_error_t igraph_create(igraph_t *graph, const igraph_vector_int_t *edges, - igraph_integer_t n, igraph_bool_t directed) { + igraph_int_t n, igraph_bool_t directed) { igraph_bool_t has_edges = igraph_vector_int_size(edges) > 0; - igraph_integer_t max; + igraph_int_t max; if (igraph_vector_int_size(edges) % 2 != 0) { IGRAPH_ERROR("Invalid (odd) edges vector.", IGRAPH_EINVAL); @@ -130,7 +120,7 @@ igraph_error_t igraph_create(igraph_t *graph, const igraph_vector_int_t *edges, * \example examples/simple/igraph_small.c */ -igraph_error_t igraph_small(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, +igraph_error_t igraph_small(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, int first, ...) { igraph_vector_int_t edges; va_list ap; diff --git a/src/vendor/cigraph/src/constructors/circulant.c b/src/vendor/cigraph/src/constructors/circulant.c index cd5eba60cbe..232f966249e 100644 --- a/src/vendor/cigraph/src/constructors/circulant.c +++ b/src/vendor/cigraph/src/constructors/circulant.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -48,13 +48,13 @@ * of shifts. */ -igraph_error_t igraph_circulant(igraph_t *graph, igraph_integer_t n, const igraph_vector_int_t *shifts, igraph_bool_t directed) { +igraph_error_t igraph_circulant(igraph_t *graph, igraph_int_t n, const igraph_vector_int_t *shifts, igraph_bool_t directed) { igraph_vector_int_t edges; igraph_vector_bool_t shift_seen; - igraph_integer_t i, j; - igraph_integer_t limit; - igraph_integer_t shift_size = igraph_vector_int_size(shifts); + igraph_int_t i, j; + igraph_int_t limit; + igraph_int_t shift_size = igraph_vector_int_size(shifts); if (n < 0) { IGRAPH_ERRORF("Number of nodes = %" IGRAPH_PRId " must be non-negative.", IGRAPH_EINVAL, n); @@ -65,7 +65,7 @@ igraph_error_t igraph_circulant(igraph_t *graph, igraph_integer_t n, const igrap IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); { - igraph_integer_t size; + igraph_int_t size; IGRAPH_SAFE_MULT(n, shift_size, &size); IGRAPH_SAFE_MULT(size, 2, &size); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, size)); @@ -76,7 +76,7 @@ igraph_error_t igraph_circulant(igraph_t *graph, igraph_integer_t n, const igrap for (i = 0; i < shift_size; i++) { /* simplify the shift */ - igraph_integer_t shift = VECTOR(*shifts)[i] % n; + igraph_int_t shift = VECTOR(*shifts)[i] % n; if (shift < 0) { shift += n; } diff --git a/src/vendor/cigraph/src/constructors/de_bruijn.c b/src/vendor/cigraph/src/constructors/de_bruijn.c index 58df531f502..0eb5afb061e 100644 --- a/src/vendor/cigraph/src/constructors/de_bruijn.c +++ b/src/vendor/cigraph/src/constructors/de_bruijn.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -55,14 +55,14 @@ * * Time complexity: O(|V|+|E|), the number of vertices plus the number of edges. */ -igraph_error_t igraph_de_bruijn(igraph_t *graph, igraph_integer_t m, igraph_integer_t n) { +igraph_error_t igraph_de_bruijn(igraph_t *graph, igraph_int_t m, igraph_int_t n) { /* m - number of symbols */ /* n - length of strings */ - igraph_integer_t no_of_nodes, no_of_edges; + igraph_int_t no_of_nodes, no_of_edges; igraph_vector_int_t edges; - igraph_integer_t i, j; + igraph_int_t i, j; int iter = 0; if (m < 0 || n < 0) { @@ -89,17 +89,17 @@ igraph_error_t igraph_de_bruijn(igraph_t *graph, igraph_integer_t m, igraph_inte IGRAPH_SAFE_MULT(no_of_nodes, m, &no_of_edges); { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(no_of_edges, 2, &no_of_edges2); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); } for (i = 0; i < no_of_nodes; i++) { - igraph_integer_t basis = (i * m) % no_of_nodes; + igraph_int_t basis = (i * m) % no_of_nodes; for (j = 0; j < m; j++) { - igraph_vector_int_push_back(&edges, i); - igraph_vector_int_push_back(&edges, basis + j); + igraph_vector_int_push_back(&edges, i); /* reserved */ + igraph_vector_int_push_back(&edges, basis + j); /* reserved */ } IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 10); } diff --git a/src/vendor/cigraph/src/constructors/famous.c b/src/vendor/cigraph/src/constructors/famous.c index 98ea77062eb..7e963a49a16 100644 --- a/src/vendor/cigraph/src/constructors/famous.c +++ b/src/vendor/cigraph/src/constructors/famous.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -23,18 +23,18 @@ #include "internal/hacks.h" /* strcasecmp */ -const igraph_integer_t igraph_i_famous_bull[] = { +const igraph_int_t igraph_i_famous_bull[] = { 5, 5, 0, 0, 1, 0, 2, 1, 2, 1, 3, 2, 4 }; -const igraph_integer_t igraph_i_famous_chvatal[] = { +const igraph_int_t igraph_i_famous_chvatal[] = { 12, 24, 0, 5, 6, 6, 7, 7, 8, 8, 9, 5, 9, 4, 5, 4, 8, 2, 8, 2, 6, 0, 6, 0, 9, 3, 9, 3, 7, 1, 7, 1, 5, 1, 10, 4, 10, 4, 11, 2, 11, 0, 10, 0, 11, 3, 11, 3, 10, 1, 2 }; -const igraph_integer_t igraph_i_famous_coxeter[] = { +const igraph_int_t igraph_i_famous_coxeter[] = { 28, 42, 0, 0, 1, 0, 2, 0, 7, 1, 4, 1, 13, 2, 3, 2, 8, 3, 6, 3, 9, 4, 5, 4, 12, 5, 6, 5, 11, 6, 10, 7, 19, 7, 24, 8, 20, 8, 23, 9, 14, 9, 22, 10, 15, 10, 21, 11, 16, @@ -42,24 +42,24 @@ const igraph_integer_t igraph_i_famous_coxeter[] = { 16, 20, 17, 20, 21, 23, 21, 26, 22, 24, 22, 27, 23, 25, 24, 26, 25, 27 }; -const igraph_integer_t igraph_i_famous_cubical[] = { +const igraph_int_t igraph_i_famous_cubical[] = { 8, 12, 0, 0, 1, 1, 2, 2, 3, 0, 3, 4, 5, 5, 6, 6, 7, 4, 7, 0, 4, 1, 5, 2, 6, 3, 7 }; -const igraph_integer_t igraph_i_famous_diamond[] = { +const igraph_int_t igraph_i_famous_diamond[] = { 4, 5, 0, 0, 1, 0, 2, 1, 2, 1, 3, 2, 3 }; -const igraph_integer_t igraph_i_famous_dodecahedron[] = { +const igraph_int_t igraph_i_famous_dodecahedron[] = { 20, 30, 0, 0, 1, 0, 4, 0, 5, 1, 2, 1, 6, 2, 3, 2, 7, 3, 4, 3, 8, 4, 9, 5, 10, 5, 11, 6, 10, 6, 14, 7, 13, 7, 14, 8, 12, 8, 13, 9, 11, 9, 12, 10, 15, 11, 16, 12, 17, 13, 18, 14, 19, 15, 16, 15, 19, 16, 17, 17, 18, 18, 19 }; -const igraph_integer_t igraph_i_famous_folkman[] = { +const igraph_int_t igraph_i_famous_folkman[] = { 20, 40, 0, 0, 5, 0, 8, 0, 10, 0, 13, 1, 7, 1, 9, 1, 12, 1, 14, 2, 6, 2, 8, 2, 11, 2, 13, 3, 5, 3, 7, 3, 10, 3, 12, 4, 6, 4, 9, 4, 11, 4, 14, 5, 15, 5, 19, 6, 15, 6, 16, @@ -67,59 +67,59 @@ const igraph_integer_t igraph_i_famous_folkman[] = { 16, 12, 17, 13, 17, 13, 18, 14, 18, 14, 19 }; -const igraph_integer_t igraph_i_famous_franklin[] = { +const igraph_int_t igraph_i_famous_franklin[] = { 12, 18, 0, 0, 1, 0, 2, 0, 6, 1, 3, 1, 7, 2, 4, 2, 10, 3, 5, 3, 11, 4, 5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 9, 8, 11, 9, 10, 10, 11 }; -const igraph_integer_t igraph_i_famous_frucht[] = { +const igraph_int_t igraph_i_famous_frucht[] = { 12, 18, 0, 0, 1, 0, 2, 0, 11, 1, 3, 1, 6, 2, 5, 2, 10, 3, 4, 3, 6, 4, 8, 4, 11, 5, 9, 5, 10, 6, 7, 7, 8, 7, 9, 8, 9, 10, 11 }; -const igraph_integer_t igraph_i_famous_grotzsch[] = { +const igraph_int_t igraph_i_famous_grotzsch[] = { 11, 20, 0, 0, 1, 0, 2, 0, 7, 0, 10, 1, 3, 1, 6, 1, 9, 2, 4, 2, 6, 2, 8, 3, 4, 3, 8, 3, 10, 4, 7, 4, 9, 5, 6, 5, 7, 5, 8, 5, 9, 5, 10 }; -const igraph_integer_t igraph_i_famous_heawood[] = { +const igraph_int_t igraph_i_famous_heawood[] = { 14, 21, 0, 0, 1, 0, 5, 0, 13, 1, 2, 1, 10, 2, 3, 2, 7, 3, 4, 3, 12, 4, 5, 4, 9, 5, 6, 6, 7, 6, 11, 7, 8, 8, 9, 8, 13, 9, 10, 10, 11, 11, 12, 12, 13 }; -const igraph_integer_t igraph_i_famous_herschel[] = { +const igraph_int_t igraph_i_famous_herschel[] = { 11, 18, 0, 0, 2, 0, 3, 0, 4, 0, 5, 1, 2, 1, 3, 1, 6, 1, 7, 2, 10, 3, 9, 4, 8, 4, 9, 5, 8, 5, 10, 6, 8, 6, 9, 7, 8, 7, 10 }; -const igraph_integer_t igraph_i_famous_house[] = { +const igraph_int_t igraph_i_famous_house[] = { 5, 6, 0, 0, 1, 0, 2, 1, 3, 2, 3, 2, 4, 3, 4 }; -const igraph_integer_t igraph_i_famous_housex[] = { +const igraph_int_t igraph_i_famous_housex[] = { 5, 8, 0, 0, 1, 0, 2, 0, 3, 1, 2, 1, 3, 2, 3, 2, 4, 3, 4 }; -const igraph_integer_t igraph_i_famous_icosahedron[] = { +const igraph_int_t igraph_i_famous_icosahedron[] = { 12, 30, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 8, 1, 2, 1, 6, 1, 7, 1, 8, 2, 4, 2, 5, 2, 6, 3, 4, 3, 8, 3, 9, 3, 11, 4, 5, 4, 11, 5, 6, 5, 10, 5, 11, 6, 7, 6, 10, 7, 8, 7, 9, 7, 10, 8, 9, 9, 10, 9, 11, 10, 11 }; -const igraph_integer_t igraph_i_famous_krackhardt_kite[] = { +const igraph_int_t igraph_i_famous_krackhardt_kite[] = { 10, 18, 0, 0, 1, 0, 2, 0, 3, 0, 5, 1, 3, 1, 4, 1, 6, 2, 3, 2, 5, 3, 4, 3, 5, 3, 6, 4, 6, 5, 6, 5, 7, 6, 7, 7, 8, 8, 9 }; -const igraph_integer_t igraph_i_famous_levi[] = { +const igraph_int_t igraph_i_famous_levi[] = { 30, 45, 0, 0, 1, 0, 7, 0, 29, 1, 2, 1, 24, 2, 3, 2, 11, 3, 4, 3, 16, 4, 5, 4, 21, 5, 6, 5, 26, 6, 7, 6, 13, 7, 8, 8, 9, 8, 17, 9, 10, 9, 22, 10, 11, 10, 27, 11, 12, 12, @@ -128,7 +128,7 @@ const igraph_integer_t igraph_i_famous_levi[] = { 28, 28, 29 }; -const igraph_integer_t igraph_i_famous_mcgee[] = { +const igraph_int_t igraph_i_famous_mcgee[] = { 24, 36, 0, 0, 1, 0, 7, 0, 23, 1, 2, 1, 18, 2, 3, 2, 14, 3, 4, 3, 10, 4, 5, 4, 21, 5, 6, 5, 17, 6, 7, 6, 13, 7, 8, 8, 9, 8, 20, 9, 10, 9, 16, 10, 11, 11, 12, 11, 23, 12, @@ -136,7 +136,7 @@ const igraph_integer_t igraph_i_famous_mcgee[] = { 21, 21, 22, 22, 23 }; -const igraph_integer_t igraph_i_famous_meredith[] = { +const igraph_int_t igraph_i_famous_meredith[] = { 70, 140, 0, 0, 4, 0, 5, 0, 6, 1, 4, 1, 5, 1, 6, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6, 7, 11, 7, 12, 7, 13, 8, 11, 8, 12, 8, 13, 9, 11, 9, 12, 9, 13, 10, 11, 10, 12, 10, 13, @@ -154,14 +154,14 @@ const igraph_integer_t igraph_i_famous_meredith[] = { 28, 38, 42, 35, 66, 59, 63, 52, 56, 45, 49 }; -const igraph_integer_t igraph_i_famous_noperfectmatching[] = { +const igraph_int_t igraph_i_famous_noperfectmatching[] = { 16, 27, 0, 0, 1, 0, 2, 0, 3, 1, 2, 1, 3, 2, 3, 2, 4, 3, 4, 4, 5, 5, 6, 5, 7, 6, 12, 6, 13, 7, 8, 7, 9, 8, 9, 8, 10, 8, 11, 9, 10, 9, 11, 10, 11, 12, 13, 12, 14, 12, 15, 13, 14, 13, 15, 14, 15 }; -const igraph_integer_t igraph_i_famous_nonline[] = { +const igraph_int_t igraph_i_famous_nonline[] = { 50, 72, 0, 0, 1, 0, 2, 0, 3, 4, 6, 4, 7, 5, 6, 5, 7, 6, 7, 7, 8, 9, 11, 9, 12, 9, 13, 10, 11, 10, 12, 10, 13, 11, 12, 11, 13, 12, 13, 14, 15, 15, 16, 15, 17, 16, 17, 16, @@ -172,17 +172,17 @@ const igraph_integer_t igraph_i_famous_nonline[] = { 43, 44, 45, 44, 46, 45, 46, 45, 47, 46, 47, 46, 48, 47, 48, 47, 49, 48, 49 }; -const igraph_integer_t igraph_i_famous_octahedron[] = { +const igraph_int_t igraph_i_famous_octahedron[] = { 6, 12, 0, 0, 1, 0, 2, 1, 2, 3, 4, 3, 5, 4, 5, 0, 3, 0, 5, 1, 3, 1, 4, 2, 4, 2, 5 }; -const igraph_integer_t igraph_i_famous_petersen[] = { +const igraph_int_t igraph_i_famous_petersen[] = { 10, 15, 0, 0, 1, 0, 4, 0, 5, 1, 2, 1, 6, 2, 3, 2, 7, 3, 4, 3, 8, 4, 9, 5, 7, 5, 8, 6, 8, 6, 9, 7, 9 }; -const igraph_integer_t igraph_i_famous_robertson[] = { +const igraph_int_t igraph_i_famous_robertson[] = { 19, 38, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 0, 18, 0, 4, 4, 9, 9, 13, 13, @@ -190,18 +190,18 @@ const igraph_integer_t igraph_i_famous_robertson[] = { 7, 14, 3, 14, 3, 11, 11, 18 }; -const igraph_integer_t igraph_i_famous_smallestcyclicgroup[] = { +const igraph_int_t igraph_i_famous_smallestcyclicgroup[] = { 9, 15, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 1, 2, 1, 3, 1, 7, 1, 8, 2, 5, 2, 6, 2, 7, 3, 8, 4, 5, 6, 7 }; -const igraph_integer_t igraph_i_famous_tetrahedron[] = { +const igraph_int_t igraph_i_famous_tetrahedron[] = { 4, 6, 0, 0, 3, 1, 3, 2, 3, 0, 1, 1, 2, 0, 2 }; -const igraph_integer_t igraph_i_famous_thomassen[] = { +const igraph_int_t igraph_i_famous_thomassen[] = { 34, 52, 0, 0, 2, 0, 3, 1, 3, 1, 4, 2, 4, 5, 7, 5, 8, 6, 8, 6, 9, 7, 9, 10, 12, 10, 13, 11, 13, 11, 14, 12, 14, 15, 17, 15, 18, 16, 18, 16, 19, 17, 19, 9, 19, 4, 14, 24, @@ -210,7 +210,7 @@ const igraph_integer_t igraph_i_famous_thomassen[] = { 23, 10, 27, 11, 28, 12, 29, 13, 30, 15, 30, 16, 31, 17, 32, 18, 33 }; -const igraph_integer_t igraph_i_famous_tutte[] = { +const igraph_int_t igraph_i_famous_tutte[] = { 46, 69, 0, 0, 10, 0, 11, 0, 12, 1, 2, 1, 7, 1, 19, 2, 3, 2, 41, 3, 4, 3, 27, 4, 5, 4, 33, 5, 6, 5, 45, 6, 9, 6, 29, 7, 8, 7, 21, 8, 9, 8, 22, 9, 24, 10, 13, 10, 14, 11, @@ -221,20 +221,20 @@ const igraph_integer_t igraph_i_famous_tutte[] = { 40, 39, 41, 40, 41, 42, 43, 43, 45, 44, 45 }; -const igraph_integer_t igraph_i_famous_uniquely3colorable[] = { +const igraph_int_t igraph_i_famous_uniquely3colorable[] = { 12, 22, 0, 0, 1, 0, 3, 0, 6, 0, 8, 1, 4, 1, 7, 1, 9, 2, 3, 2, 6, 2, 7, 2, 9, 2, 11, 3, 4, 3, 10, 4, 5, 4, 11, 5, 6, 5, 7, 5, 8, 5, 10, 8, 11, 9, 10 }; -const igraph_integer_t igraph_i_famous_walther[] = { +const igraph_int_t igraph_i_famous_walther[] = { 25, 31, 0, 0, 1, 1, 2, 1, 8, 2, 3, 2, 13, 3, 4, 3, 16, 4, 5, 5, 6, 5, 19, 6, 7, 6, 20, 7, 21, 8, 9, 8, 13, 9, 10, 9, 22, 10, 11, 10, 20, 11, 12, 13, 14, 14, 15, 14, 23, 15, 16, 15, 17, 17, 18, 18, 19, 18, 24, 20, 24, 22, 23, 23, 24 }; -const igraph_integer_t igraph_i_famous_zachary[] = { +const igraph_int_t igraph_i_famous_zachary[] = { 34, 78, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 10, 0, 11, 0, 12, 0, 13, 0, 17, 0, 19, 0, 21, 0, 31, @@ -249,14 +249,14 @@ const igraph_integer_t igraph_i_famous_zachary[] = { 32, 33 }; -static igraph_error_t igraph_i_famous(igraph_t *graph, const igraph_integer_t *data) { - igraph_integer_t no_of_nodes = data[0]; - igraph_integer_t no_of_edges = data[1]; +static igraph_error_t igraph_i_famous(igraph_t *graph, const igraph_int_t *data) { + igraph_int_t no_of_nodes = data[0]; + igraph_int_t no_of_edges = data[1]; igraph_bool_t directed = (igraph_bool_t) data[2]; - igraph_vector_int_t edges; + const igraph_vector_int_t edges = igraph_vector_int_view(data + 3, 2 * no_of_edges); - igraph_vector_int_view(&edges, data + 3, 2 * no_of_edges); IGRAPH_CHECK(igraph_create(graph, &edges, no_of_nodes, directed)); + return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/constructors/full.c b/src/vendor/cigraph/src/constructors/full.c index 16ac90cd275..583e87f69bf 100644 --- a/src/vendor/cigraph/src/constructors/full.c +++ b/src/vendor/cigraph/src/constructors/full.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -51,11 +51,11 @@ * * \example examples/simple/igraph_full.c */ -igraph_error_t igraph_full(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, +igraph_error_t igraph_full(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t loops) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; if (n < 0) { IGRAPH_ERROR("Invalid number of vertices.", IGRAPH_EINVAL); @@ -68,8 +68,8 @@ igraph_error_t igraph_full(igraph_t *graph, igraph_integer_t n, igraph_bool_t di IGRAPH_SAFE_MULT(n, n, &no_of_edges2); IGRAPH_SAFE_MULT(no_of_edges2, 2, &no_of_edges2); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); - for (igraph_integer_t i = 0; i < n; i++) { - for (igraph_integer_t j = 0; j < n; j++) { + for (igraph_int_t i = 0; i < n; i++) { + for (igraph_int_t j = 0; j < n; j++) { igraph_vector_int_push_back(&edges, i); /* reserved */ igraph_vector_int_push_back(&edges, j); /* reserved */ } @@ -80,12 +80,12 @@ igraph_error_t igraph_full(igraph_t *graph, igraph_integer_t n, igraph_bool_t di IGRAPH_SAFE_MULT(n, n - 1, &no_of_edges2); IGRAPH_SAFE_MULT(no_of_edges2, 2, &no_of_edges2); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); - for (igraph_integer_t i = 0; i < n; i++) { - for (igraph_integer_t j = 0; j < i; j++) { + for (igraph_int_t i = 0; i < n; i++) { + for (igraph_int_t j = 0; j < i; j++) { igraph_vector_int_push_back(&edges, i); /* reserved */ igraph_vector_int_push_back(&edges, j); /* reserved */ } - for (igraph_integer_t j = i + 1; j < n; j++) { + for (igraph_int_t j = i + 1; j < n; j++) { igraph_vector_int_push_back(&edges, i); /* reserved */ igraph_vector_int_push_back(&edges, j); /* reserved */ } @@ -96,8 +96,8 @@ igraph_error_t igraph_full(igraph_t *graph, igraph_integer_t n, igraph_bool_t di IGRAPH_SAFE_ADD(n, 1, &no_of_edges2); IGRAPH_SAFE_MULT(n, no_of_edges2, &no_of_edges2); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); - for (igraph_integer_t i = 0; i < n; i++) { - for (igraph_integer_t j = i; j < n; j++) { + for (igraph_int_t i = 0; i < n; i++) { + for (igraph_int_t j = i; j < n; j++) { igraph_vector_int_push_back(&edges, i); /* reserved */ igraph_vector_int_push_back(&edges, j); /* reserved */ } @@ -107,8 +107,8 @@ igraph_error_t igraph_full(igraph_t *graph, igraph_integer_t n, igraph_bool_t di /* ecount = n * (n - 1) / 2 */ IGRAPH_SAFE_MULT(n, n - 1, &no_of_edges2); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); - for (igraph_integer_t i = 0; i < n; i++) { - for (igraph_integer_t j = i + 1; j < n; j++) { + for (igraph_int_t i = 0; i < n; i++) { + for (igraph_int_t j = i + 1; j < n; j++) { igraph_vector_int_push_back(&edges, i); /* reserved */ igraph_vector_int_push_back(&edges, j); /* reserved */ } @@ -160,7 +160,7 @@ igraph_error_t igraph_full_multipartite(igraph_t *graph, igraph_vector_int_t edges; igraph_vector_int_t n_acc; - igraph_integer_t no_of_types = igraph_vector_int_size(n); + igraph_int_t no_of_types = igraph_vector_int_size(n); if (no_of_types == 0) { IGRAPH_CHECK(igraph_empty(graph, 0, directed)); @@ -176,16 +176,16 @@ igraph_error_t igraph_full_multipartite(igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&n_acc, no_of_types+1); VECTOR(n_acc)[0] = 0; - for (igraph_integer_t i = 1; i < no_of_types+1; i++) { + for (igraph_int_t i = 1; i < no_of_types+1; i++) { IGRAPH_SAFE_ADD(VECTOR(n_acc)[i-1], VECTOR(*n)[i-1], &VECTOR(n_acc)[i]); } - igraph_integer_t no_of_edges2 = 0; + igraph_int_t no_of_edges2 = 0; - for (igraph_integer_t i = 0; i < no_of_types; i++) { - igraph_integer_t v = VECTOR(*n)[i]; - igraph_integer_t partial_sum = VECTOR(n_acc)[no_of_types] - v; + for (igraph_int_t i = 0; i < no_of_types; i++) { + igraph_int_t v = VECTOR(*n)[i]; + igraph_int_t partial_sum = VECTOR(n_acc)[no_of_types] - v; IGRAPH_SAFE_MULT(partial_sum, v, &partial_sum); IGRAPH_SAFE_ADD(no_of_edges2, partial_sum, &no_of_edges2); } @@ -196,14 +196,14 @@ igraph_error_t igraph_full_multipartite(igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges2); - igraph_integer_t ptr = 0; + igraph_int_t ptr = 0; - for (igraph_integer_t from_type = 0; from_type < no_of_types-1; from_type++) { - igraph_integer_t edge_from = VECTOR(n_acc)[from_type]; - for (igraph_integer_t i = 0; i < VECTOR(*n)[from_type]; i++) { - for (igraph_integer_t to_type = from_type+1; to_type < no_of_types; to_type++) { - igraph_integer_t edge_to = VECTOR(n_acc)[to_type]; - for (igraph_integer_t j = 0; j < VECTOR(*n)[to_type]; j++) { + for (igraph_int_t from_type = 0; from_type < no_of_types-1; from_type++) { + igraph_int_t edge_from = VECTOR(n_acc)[from_type]; + for (igraph_int_t i = 0; i < VECTOR(*n)[from_type]; i++) { + for (igraph_int_t to_type = from_type+1; to_type < no_of_types; to_type++) { + igraph_int_t edge_to = VECTOR(n_acc)[to_type]; + for (igraph_int_t j = 0; j < VECTOR(*n)[to_type]; j++) { if (!directed || mode == IGRAPH_OUT) { VECTOR(edges)[ptr++] = edge_from; VECTOR(edges)[ptr++] = edge_to; @@ -229,8 +229,8 @@ igraph_error_t igraph_full_multipartite(igraph_t *graph, if (types) { IGRAPH_CHECK(igraph_vector_int_resize(types, VECTOR(n_acc)[no_of_types])); if (VECTOR(n_acc)[no_of_types] > 0) { - igraph_integer_t v = 1; - for (igraph_integer_t i = 0; i < VECTOR(n_acc)[no_of_types]; i++) { + igraph_int_t v = 1; + for (igraph_int_t i = 0; i < VECTOR(n_acc)[no_of_types]; i++) { if (i == VECTOR(n_acc)[v]) { v++; } @@ -280,10 +280,10 @@ igraph_error_t igraph_full_multipartite(igraph_t *graph, */ igraph_error_t igraph_turan(igraph_t *graph, igraph_vector_int_t *types, - igraph_integer_t n, - igraph_integer_t r) { - igraph_integer_t quotient; - igraph_integer_t remainder; + igraph_int_t n, + igraph_int_t r) { + igraph_int_t quotient; + igraph_int_t remainder; igraph_vector_int_t subsets; if (n < 0) { @@ -312,7 +312,7 @@ igraph_error_t igraph_turan(igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&subsets, r); igraph_vector_int_fill(&subsets, quotient); - for (igraph_integer_t i = 0; i < remainder; i++) { + for (igraph_int_t i = 0; i < remainder; i++) { VECTOR(subsets)[i]++; } @@ -345,23 +345,23 @@ igraph_error_t igraph_turan(igraph_t *graph, * Time complexity: O(|V|^2) = O(|E|), * where |V| is the number of vertices and |E| is the number of edges. */ -igraph_error_t igraph_full_citation(igraph_t *graph, igraph_integer_t n, +igraph_error_t igraph_full_citation(igraph_t *graph, igraph_int_t n, igraph_bool_t directed) { igraph_vector_int_t edges; - igraph_integer_t ptr = 0; + igraph_int_t ptr = 0; if (n < 0) { IGRAPH_ERROR("Invalid number of vertices.", IGRAPH_EINVAL); } { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(n, n-1, &no_of_edges2); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges2); } - for (igraph_integer_t i = 1; i < n; i++) { - for (igraph_integer_t j = 0; j < i; j++) { + for (igraph_int_t i = 1; i < n; i++) { + for (igraph_int_t j = 0; j < i; j++) { VECTOR(edges)[ptr++] = i; VECTOR(edges)[ptr++] = j; } diff --git a/src/vendor/cigraph/src/constructors/generalized_petersen.c b/src/vendor/cigraph/src/constructors/generalized_petersen.c index 0b34f7e8488..a6670454c15 100644 --- a/src/vendor/cigraph/src/constructors/generalized_petersen.c +++ b/src/vendor/cigraph/src/constructors/generalized_petersen.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -55,11 +55,11 @@ * * Time complexity: O(|V|), the number of vertices in the graph. */ -igraph_error_t igraph_generalized_petersen(igraph_t *graph, igraph_integer_t n, igraph_integer_t k) { +igraph_error_t igraph_generalized_petersen(igraph_t *graph, igraph_int_t n, igraph_int_t k) { /* This is a generalized Petersen graph constructor */ igraph_vector_int_t edges; - igraph_integer_t no_of_nodes, no_of_edges2; - igraph_integer_t i; + igraph_int_t no_of_nodes, no_of_edges2; + igraph_int_t i; if (n < 3) { IGRAPH_ERRORF("n = %" IGRAPH_PRId " must be at least 3.", IGRAPH_EINVAL, n); @@ -78,12 +78,12 @@ igraph_error_t igraph_generalized_petersen(igraph_t *graph, igraph_integer_t n, IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); for (i = 0; i < n; i++) { - igraph_vector_int_push_back(&edges, i); - igraph_vector_int_push_back(&edges, (i + 1) % n); - igraph_vector_int_push_back(&edges, i); - igraph_vector_int_push_back(&edges, i + n); - igraph_vector_int_push_back(&edges, i + n); - igraph_vector_int_push_back(&edges, ((i + k) % n) + n); + igraph_vector_int_push_back(&edges, i); /* reserved */ + igraph_vector_int_push_back(&edges, (i + 1) % n); /* reserved */ + igraph_vector_int_push_back(&edges, i); /* reserved */ + igraph_vector_int_push_back(&edges, i + n); /* reserved */ + igraph_vector_int_push_back(&edges, i + n); /* reserved */ + igraph_vector_int_push_back(&edges, ((i + k) % n) + n); /* reserved */ } IGRAPH_CHECK(igraph_create(graph, &edges, no_of_nodes, IGRAPH_UNDIRECTED)); diff --git a/src/vendor/cigraph/src/constructors/kautz.c b/src/vendor/cigraph/src/constructors/kautz.c index 7976f116203..7b68a268651 100644 --- a/src/vendor/cigraph/src/constructors/kautz.c +++ b/src/vendor/cigraph/src/constructors/kautz.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -58,19 +58,19 @@ * like O(|V|+|E|). |V| is the number of vertices, |E| is the number * of edges and \c m and \c n are the corresponding arguments. */ -igraph_error_t igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_t n) { +igraph_error_t igraph_kautz(igraph_t *graph, igraph_int_t m, igraph_int_t n) { /* m+1 - number of symbols */ /* n+1 - length of strings */ - igraph_integer_t no_of_nodes, no_of_edges; - igraph_integer_t allstrings; - igraph_integer_t i, j, idx = 0; + igraph_int_t no_of_nodes, no_of_edges; + igraph_int_t allstrings; + igraph_int_t i, j, idx = 0; igraph_vector_int_t edges; igraph_vector_int_t digits, table; igraph_vector_int_t index1, index2; - igraph_integer_t actb = 0; - igraph_integer_t actvalue = 0; + igraph_int_t actb = 0; + igraph_int_t actvalue = 0; int iter = 0; if (m < 0 || n < 0) { @@ -88,7 +88,7 @@ igraph_error_t igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_ /* no_of_nodes = ((m + 1) * pow(m, n)) */ { igraph_real_t m_to_pow_n_real = pow(m, n); - igraph_integer_t m_to_pow_n = m_to_pow_n_real; + igraph_int_t m_to_pow_n = m_to_pow_n_real; if (m_to_pow_n != m_to_pow_n_real) { IGRAPH_ERRORF("Parameters (%" IGRAPH_PRId ", %" IGRAPH_PRId ") too large for Kautz graph.", IGRAPH_EINVAL, m, n); @@ -128,7 +128,7 @@ igraph_error_t igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_ while (true) { /* at the beginning of the loop, 0:actb contain the valid prefix */ /* we might need to fill it to get a valid string */ - igraph_integer_t z = 0; + igraph_int_t z = 0; if (VECTOR(digits)[actb] == 0) { z = 1; } @@ -152,7 +152,7 @@ igraph_error_t igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_ /* not yet, we need a valid prefix now */ while (true) { /* try to increase digits at position actb */ - igraph_integer_t next = VECTOR(digits)[actb] + 1; + igraph_int_t next = VECTOR(digits)[actb] + 1; if (actb != 0 && VECTOR(digits)[actb - 1] == next) { next++; } @@ -170,18 +170,18 @@ igraph_error_t igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_ } { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(no_of_edges, 2, &no_of_edges2); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); } /* Now come the edges at last */ for (i = 0; i < no_of_nodes; i++) { - igraph_integer_t fromvalue = VECTOR(index2)[i]; - igraph_integer_t lastdigit = fromvalue % (m + 1); - igraph_integer_t basis = (fromvalue * (m + 1)) % allstrings; + igraph_int_t fromvalue = VECTOR(index2)[i]; + igraph_int_t lastdigit = fromvalue % (m + 1); + igraph_int_t basis = (fromvalue * (m + 1)) % allstrings; for (j = 0; j <= m; j++) { - igraph_integer_t tovalue, to; + igraph_int_t tovalue, to; if (j == lastdigit) { continue; } diff --git a/src/vendor/cigraph/src/constructors/lattices.c b/src/vendor/cigraph/src/constructors/lattices.c index 323b9308cf6..bdbc1c50efb 100644 --- a/src/vendor/cigraph/src/constructors/lattices.c +++ b/src/vendor/cigraph/src/constructors/lattices.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -88,10 +88,10 @@ static igraph_error_t triangular_lattice( igraph_t *graph, igraph_bool_t directed, igraph_bool_t mutual, igraph_bool_t lex_ordering, const igraph_vector_int_t *row_lengths_vector, const igraph_vector_int_t *row_start_vector) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t row_count = igraph_vector_int_size(row_lengths_vector); - igraph_integer_t no_of_nodes; + igraph_int_t row_count = igraph_vector_int_size(row_lengths_vector); + igraph_int_t no_of_nodes; igraph_vector_int_t row_lengths_prefix_sum_vector; - igraph_integer_t i, j; + igraph_int_t i, j; if (igraph_vector_int_size(row_lengths_vector) != igraph_vector_int_size(row_start_vector)) { IGRAPH_ERRORF( @@ -122,8 +122,8 @@ static igraph_error_t triangular_lattice( COMPUTE_NUMBER_OF_VERTICES(); /* computing the number of edges in the constructed triangular lattice */ - igraph_integer_t no_of_edges2 = VECTOR(*row_lengths_vector)[row_count - 1] - 1; - igraph_integer_t multiplier = mutual && directed ? 4 : 2; + igraph_int_t no_of_edges2 = VECTOR(*row_lengths_vector)[row_count - 1] - 1; + igraph_int_t multiplier = mutual && directed ? 4 : 2; for (j = 0; j < row_count - 1; j++) { IGRAPH_SAFE_ADD(no_of_edges2, VECTOR(*row_lengths_vector)[j] - 1, &no_of_edges2); IGRAPH_SAFE_ADD(no_of_edges2, MIN(ROW_END(j), ROW_END((j + 1))) - MAX(VECTOR(*row_start_vector)[j], VECTOR(*row_start_vector)[j + 1]) + 1, @@ -135,7 +135,7 @@ static igraph_error_t triangular_lattice( IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); /* constructing the edge array */ - igraph_integer_t k; + igraph_int_t k; for (j = 0; j < row_count; j++) { IGRAPH_ALLOW_INTERRUPTION(); for (i = 0; i < VECTOR(*row_lengths_vector)[j]; i++) { @@ -157,11 +157,11 @@ static igraph_error_t triangular_lattice( return IGRAPH_SUCCESS; } -static igraph_error_t triangular_lattice_triangle_shape(igraph_t *graph, igraph_integer_t size, igraph_bool_t directed, igraph_bool_t mutual) { - igraph_integer_t row_count = size; +static igraph_error_t triangular_lattice_triangle_shape(igraph_t *graph, igraph_int_t size, igraph_bool_t directed, igraph_bool_t mutual) { + igraph_int_t row_count = size; igraph_vector_int_t row_lengths_vector; igraph_vector_int_t row_start_vector; - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&row_lengths_vector, row_count); IGRAPH_VECTOR_INT_INIT_FINALLY(&row_start_vector, row_count); @@ -181,12 +181,12 @@ static igraph_error_t triangular_lattice_triangle_shape(igraph_t *graph, igraph_ } static igraph_error_t triangular_lattice_rectangle_shape( - igraph_t *graph, igraph_integer_t size_x, igraph_integer_t size_y, + igraph_t *graph, igraph_int_t size_x, igraph_int_t size_y, igraph_bool_t directed, igraph_bool_t mutual) { - igraph_integer_t row_count = size_x; + igraph_int_t row_count = size_x; igraph_vector_int_t row_lengths_vector; igraph_vector_int_t row_start_vector; - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&row_lengths_vector, row_count); IGRAPH_VECTOR_INT_INIT_FINALLY(&row_start_vector, row_count); @@ -206,21 +206,21 @@ static igraph_error_t triangular_lattice_rectangle_shape( } static igraph_error_t triangular_lattice_hex_shape( - igraph_t *graph, igraph_integer_t size_x, igraph_integer_t size_y, - igraph_integer_t size_z, igraph_bool_t directed, igraph_bool_t mutual) { - igraph_integer_t row_count = size_y + size_z - 1; + igraph_t *graph, igraph_int_t size_x, igraph_int_t size_y, + igraph_int_t size_z, igraph_bool_t directed, igraph_bool_t mutual) { + igraph_int_t row_count = size_y + size_z - 1; igraph_vector_int_t row_lengths_vector; igraph_vector_int_t row_start_vector; - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&row_lengths_vector, row_count); IGRAPH_VECTOR_INT_INIT_FINALLY(&row_start_vector, row_count); - igraph_integer_t row_length = size_x; - igraph_integer_t row_start = size_y - 1; - igraph_integer_t first_threshold = MIN(size_y - 1, size_z - 1); - igraph_integer_t second_threshold = MAX(size_y - 1, size_z - 1); - igraph_integer_t sgn_flag = size_y < size_z ? 0 : -1; + igraph_int_t row_length = size_x; + igraph_int_t row_start = size_y - 1; + igraph_int_t first_threshold = MIN(size_y - 1, size_z - 1); + igraph_int_t second_threshold = MAX(size_y - 1, size_z - 1); + igraph_int_t sgn_flag = size_y < size_z ? 0 : -1; for (i = 0; i < row_count; i++) { VECTOR(row_lengths_vector)[i] = row_length; @@ -290,7 +290,7 @@ static igraph_error_t triangular_lattice_hex_shape( igraph_error_t igraph_triangular_lattice( igraph_t *graph, const igraph_vector_int_t *dims, igraph_bool_t directed, igraph_bool_t mutual) { - igraph_integer_t num_dims = igraph_vector_int_size(dims); + igraph_int_t num_dims = igraph_vector_int_size(dims); if (igraph_vector_int_any_smaller(dims, 0)) { IGRAPH_ERROR("Invalid dimension vector.", IGRAPH_EINVAL); } @@ -352,10 +352,10 @@ static igraph_error_t hexagonal_lattice( const igraph_vector_int_t *row_lengths_vector, const igraph_vector_int_t *row_start_vector ) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t row_count = igraph_vector_int_size(row_lengths_vector); - igraph_integer_t no_of_nodes; + igraph_int_t row_count = igraph_vector_int_size(row_lengths_vector); + igraph_int_t no_of_nodes; igraph_vector_int_t row_lengths_prefix_sum_vector; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_bool_t lex_ordering = false; if (igraph_vector_int_size(row_lengths_vector) != igraph_vector_int_size(row_start_vector)) { @@ -382,8 +382,8 @@ static igraph_error_t hexagonal_lattice( COMPUTE_NUMBER_OF_VERTICES(); /* computing the number of edges in the constructed hex lattice */ - igraph_integer_t no_of_edges2 = VECTOR(*row_lengths_vector)[row_count - 1] - 1; - igraph_integer_t multiplier = mutual && directed ? 4 : 2, low, high; + igraph_int_t no_of_edges2 = VECTOR(*row_lengths_vector)[row_count - 1] - 1; + igraph_int_t multiplier = mutual && directed ? 4 : 2, low, high; for (j = 0; j < row_count - 1; j++) { IGRAPH_SAFE_ADD(no_of_edges2, VECTOR(*row_lengths_vector)[j] - 1, &no_of_edges2); low = MAX((VECTOR(*row_start_vector)[j] - 1), (VECTOR(*row_start_vector)[j + 1])); @@ -396,7 +396,7 @@ static igraph_error_t hexagonal_lattice( IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); /* constructing the edge array */ - igraph_integer_t k; + igraph_int_t k; for (j = 0; j < row_count; j++) { IGRAPH_ALLOW_INTERRUPTION(); for (i = 0; i < VECTOR(*row_lengths_vector)[j]; i++) { @@ -417,12 +417,12 @@ static igraph_error_t hexagonal_lattice( return IGRAPH_SUCCESS; } -static igraph_error_t hexagonal_lattice_triangle_shape(igraph_t *graph, igraph_integer_t size, igraph_bool_t directed, igraph_bool_t mutual) { - igraph_integer_t row_count; +static igraph_error_t hexagonal_lattice_triangle_shape(igraph_t *graph, igraph_int_t size, igraph_bool_t directed, igraph_bool_t mutual) { + igraph_int_t row_count; IGRAPH_SAFE_ADD(size, 2, &row_count); igraph_vector_int_t row_lengths_vector; igraph_vector_int_t row_start_vector; - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&row_lengths_vector, row_count - 1); IGRAPH_VECTOR_INT_INIT_FINALLY(&row_start_vector, row_count - 1); @@ -442,17 +442,17 @@ static igraph_error_t hexagonal_lattice_triangle_shape(igraph_t *graph, igraph_i } static igraph_error_t hexagonal_lattice_rectangle_shape( - igraph_t *graph, igraph_integer_t size_x, igraph_integer_t size_y, + igraph_t *graph, igraph_int_t size_x, igraph_int_t size_y, igraph_bool_t directed, igraph_bool_t mutual ) { - igraph_integer_t row_count; + igraph_int_t row_count; IGRAPH_SAFE_ADD(size_x, 1, &row_count); igraph_vector_int_t row_lengths_vector; igraph_vector_int_t row_start_vector; - igraph_integer_t actual_size_y; + igraph_int_t actual_size_y; IGRAPH_SAFE_ADD(size_y, 1, &actual_size_y); IGRAPH_SAFE_MULT(actual_size_y, 2, &actual_size_y); - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&row_lengths_vector, row_count); IGRAPH_VECTOR_INT_INIT_FINALLY(&row_start_vector, row_count); @@ -477,26 +477,26 @@ static igraph_error_t hexagonal_lattice_rectangle_shape( } static igraph_error_t hexagonal_lattice_hex_shape( - igraph_t *graph, igraph_integer_t size_x, igraph_integer_t size_y, - igraph_integer_t size_z, igraph_bool_t directed, igraph_bool_t mutual + igraph_t *graph, igraph_int_t size_x, igraph_int_t size_y, + igraph_int_t size_z, igraph_bool_t directed, igraph_bool_t mutual ) { - igraph_integer_t row_count = size_y + size_z; + igraph_int_t row_count = size_y + size_z; igraph_vector_int_t row_lengths_vector; igraph_vector_int_t row_start_vector; - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&row_lengths_vector, row_count); IGRAPH_VECTOR_INT_INIT_FINALLY(&row_start_vector, row_count); - igraph_integer_t row_length; + igraph_int_t row_length; IGRAPH_SAFE_MULT(size_x, 2, &row_length); IGRAPH_SAFE_ADD(row_length, 1, &row_length); - igraph_integer_t row_start; + igraph_int_t row_start; IGRAPH_SAFE_MULT(size_y, 2, &row_start); IGRAPH_SAFE_ADD(row_start, -1, &row_start); - igraph_integer_t first_threshold = MIN(size_y - 1, size_z - 1); - igraph_integer_t second_threshold = MAX(size_y - 1, size_z - 1); - igraph_integer_t sgn_flag = size_y < size_z ? 0 : -2; + igraph_int_t first_threshold = MIN(size_y - 1, size_z - 1); + igraph_int_t second_threshold = MAX(size_y - 1, size_z - 1); + igraph_int_t sgn_flag = size_y < size_z ? 0 : -2; for (i = 0; i < row_count; i++) { VECTOR(row_lengths_vector)[i] = row_length; @@ -572,7 +572,7 @@ static igraph_error_t hexagonal_lattice_hex_shape( igraph_error_t igraph_hexagonal_lattice( igraph_t *graph, const igraph_vector_int_t *dims, igraph_bool_t directed, igraph_bool_t mutual) { - igraph_integer_t num_dims = igraph_vector_int_size(dims); + igraph_int_t num_dims = igraph_vector_int_size(dims); if (igraph_vector_int_any_smaller(dims, 0)) { IGRAPH_ERROR("Invalid dimension vector.", IGRAPH_EINVAL); } diff --git a/src/vendor/cigraph/src/constructors/lcf.c b/src/vendor/cigraph/src/constructors/lcf.c index 0409db4ad70..8df89e2c78c 100644 --- a/src/vendor/cigraph/src/constructors/lcf.c +++ b/src/vendor/cigraph/src/constructors/lcf.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -49,16 +49,16 @@ * Time complexity: O(|V|+|E|), linear in the number of vertices plus * the number of edges. */ -igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, +igraph_error_t igraph_lcf(igraph_t *graph, igraph_int_t n, const igraph_vector_int_t *shifts, - igraph_integer_t repeats) { + igraph_int_t repeats) { igraph_vector_int_t edges; - igraph_integer_t no_of_shifts = igraph_vector_int_size(shifts); - igraph_integer_t ptr = 0, sptr = 0; - igraph_integer_t no_of_nodes = n; - igraph_integer_t no_of_edges; - igraph_integer_t no_of_edges2; + igraph_int_t no_of_shifts = igraph_vector_int_size(shifts); + igraph_int_t ptr = 0, sptr = 0; + igraph_int_t no_of_nodes = n; + igraph_int_t no_of_edges; + igraph_int_t no_of_edges2; if (repeats < 0) { IGRAPH_ERROR("Number of repeats must not be negative.", IGRAPH_EINVAL); @@ -73,7 +73,7 @@ igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, if (no_of_nodes > 0) { /* Create a ring first */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(edges)[ptr++] = i; VECTOR(edges)[ptr++] = i + 1; } @@ -82,9 +82,9 @@ igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, /* Then add the rest */ while (ptr < 2 * no_of_edges) { - igraph_integer_t sh = VECTOR(*shifts)[sptr % no_of_shifts]; - igraph_integer_t from = sptr % no_of_nodes; - igraph_integer_t to = (no_of_nodes + sptr + sh) % no_of_nodes; + igraph_int_t sh = VECTOR(*shifts)[sptr % no_of_shifts]; + igraph_int_t from = sptr % no_of_nodes; + igraph_int_t to = (no_of_nodes + sptr + sh) % no_of_nodes; VECTOR(edges)[ptr++] = from; VECTOR(edges)[ptr++] = to; sptr++; @@ -121,9 +121,9 @@ igraph_error_t igraph_lcf(igraph_t *graph, igraph_integer_t n, * * \example examples/simple/igraph_lcf.c */ -igraph_error_t igraph_lcf_small(igraph_t *graph, igraph_integer_t n, ...) { +igraph_error_t igraph_lcf_small(igraph_t *graph, igraph_int_t n, ...) { igraph_vector_int_t shifts; - igraph_integer_t repeats; + igraph_int_t repeats; va_list ap; IGRAPH_VECTOR_INT_INIT_FINALLY(&shifts, 0); diff --git a/src/vendor/cigraph/src/constructors/linegraph.c b/src/vendor/cigraph/src/constructors/linegraph.c index 1c7ab491b94..413dd992f9f 100644 --- a/src/vendor/cigraph/src/constructors/linegraph.c +++ b/src/vendor/cigraph/src/constructors/linegraph.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,19 +29,19 @@ * with minimal performance improvements on a graph with 70K vertices and 360K * edges. (1.09s instead of 1.10s). I think it's not worth the fuss. */ static igraph_error_t igraph_i_linegraph_undirected(const igraph_t *graph, igraph_t *linegraph) { - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t adjedges, adjedges2; igraph_vector_int_t edges; - igraph_integer_t prev = -1; + igraph_int_t prev = -1; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&adjedges, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&adjedges2, 0); - for (igraph_integer_t e1 = 0; e1 < no_of_edges; e1++) { - igraph_integer_t from = IGRAPH_FROM(graph, e1); - igraph_integer_t to = IGRAPH_TO(graph, e1); - igraph_integer_t n; + for (igraph_int_t e1 = 0; e1 < no_of_edges; e1++) { + igraph_int_t from = IGRAPH_FROM(graph, e1); + igraph_int_t to = IGRAPH_TO(graph, e1); + igraph_int_t n; IGRAPH_ALLOW_INTERRUPTION(); @@ -49,8 +49,8 @@ static igraph_error_t igraph_i_linegraph_undirected(const igraph_t *graph, igrap IGRAPH_CHECK(igraph_incident(graph, &adjedges, from, IGRAPH_ALL, IGRAPH_LOOPS)); } n = igraph_vector_int_size(&adjedges); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t e2 = VECTOR(adjedges)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t e2 = VECTOR(adjedges)[i]; if (e2 < e1) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, e1)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, e2)); @@ -59,8 +59,8 @@ static igraph_error_t igraph_i_linegraph_undirected(const igraph_t *graph, igrap IGRAPH_CHECK(igraph_incident(graph, &adjedges2, to, IGRAPH_ALL, IGRAPH_LOOPS)); n = igraph_vector_int_size(&adjedges2); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t e2 = VECTOR(adjedges2)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t e2 = VECTOR(adjedges2)[i]; if (e2 < e1) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, e1)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, e2)); @@ -89,17 +89,17 @@ static igraph_error_t igraph_i_linegraph_undirected(const igraph_t *graph, igrap } static igraph_error_t igraph_i_linegraph_directed(const igraph_t *graph, igraph_t *linegraph) { - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t i, j, n; + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t i, j, n; igraph_vector_int_t adjedges; igraph_vector_int_t edges; - igraph_integer_t prev = -1; + igraph_int_t prev = -1; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&adjedges, 0); for (i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); + igraph_int_t from = IGRAPH_FROM(graph, i); IGRAPH_ALLOW_INTERRUPTION(); @@ -108,7 +108,7 @@ static igraph_error_t igraph_i_linegraph_directed(const igraph_t *graph, igraph_ } n = igraph_vector_int_size(&adjedges); for (j = 0; j < n; j++) { - igraph_integer_t e = VECTOR(adjedges)[j]; + igraph_int_t e = VECTOR(adjedges)[j]; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, e)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); } diff --git a/src/vendor/cigraph/src/constructors/mycielskian.c b/src/vendor/cigraph/src/constructors/mycielskian.c index 2dd0cea7864..ff0f9eabced 100644 --- a/src/vendor/cigraph/src/constructors/mycielskian.c +++ b/src/vendor/cigraph/src/constructors/mycielskian.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,6 +29,8 @@ * \function igraph_mycielskian * \brief Generate the Mycielskian of a graph with \p k iterations. * + * \experimental + * * The Mycielskian of a graph is a larger graph formed using a construction due * to Jan Mycielski that increases the chromatic number by one while preserving * the triangle-free property. The Mycielski construction can be used to create @@ -92,9 +94,9 @@ * Time complexity: O(|V| 2^k + |E| 3^k) where |V| and |E| are the vertex and * edge counts, respectively. */ -igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_integer_t k) { - igraph_integer_t vcount = igraph_vcount(graph); - igraph_integer_t ecount = igraph_ecount(graph); +igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_int_t k) { + igraph_int_t vcount = igraph_vcount(graph); + igraph_int_t ecount = igraph_ecount(graph); igraph_vector_int_t edges; if (k < 0) { @@ -126,10 +128,10 @@ igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_i /* Compute the number of vertices and edges. Since these are exponential in k, * overflow checks are important. */ - igraph_integer_t new_vcount = vcount; - igraph_integer_t new_ecount = ecount; + igraph_int_t new_vcount = vcount; + igraph_int_t new_ecount = ecount; - for (igraph_integer_t i = 0; i < k; i++) { + for (igraph_int_t i = 0; i < k; i++) { // new edges = 3 * old edges + old vertices IGRAPH_SAFE_MULT(new_ecount, 3, &new_ecount); IGRAPH_SAFE_ADD(new_ecount, new_vcount, &new_ecount); @@ -141,18 +143,18 @@ igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_i IGRAPH_CHECK(igraph_vector_int_resize(&edges, new_ecount * 2)); - igraph_integer_t edge_index = 2 * ecount; // Current last edge index in edge vector - igraph_integer_t offset = vcount; // Tracks where new vertices start + igraph_int_t edge_index = 2 * ecount; // Current last edge index in edge vector + igraph_int_t offset = vcount; // Tracks where new vertices start - for (igraph_integer_t i = 0; i < k; i++) { - igraph_integer_t prev_vcount = offset; // Number of vertices before this step - igraph_integer_t w = offset * 2; // The new 'w' node index - igraph_integer_t last_edge_index = edge_index; // Mark where edges before this step end + for (igraph_int_t i = 0; i < k; i++) { + igraph_int_t prev_vcount = offset; // Number of vertices before this step + igraph_int_t w = offset * 2; // The new 'w' node index + igraph_int_t last_edge_index = edge_index; // Mark where edges before this step end // For each edge before this step, add two new edges - for (igraph_integer_t j = 0; j < last_edge_index; j += 2) { - igraph_integer_t v1 = VECTOR(edges)[j]; - igraph_integer_t v2 = VECTOR(edges)[j + 1]; + for (igraph_int_t j = 0; j < last_edge_index; j += 2) { + igraph_int_t v1 = VECTOR(edges)[j]; + igraph_int_t v2 = VECTOR(edges)[j + 1]; VECTOR(edges)[edge_index++] = v1; VECTOR(edges)[edge_index++] = offset + v2; @@ -162,7 +164,7 @@ igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_i } // Add edges connecting each `ui` to `w` (forming a star) - for (igraph_integer_t j = prev_vcount; j < w; j++) { + for (igraph_int_t j = prev_vcount; j < w; j++) { VECTOR(edges)[edge_index++] = j; VECTOR(edges)[edge_index++] = w; } @@ -216,7 +218,7 @@ igraph_error_t igraph_mycielskian(const igraph_t *graph, igraph_t *res, igraph_i * * Time complexity: O(3^k), i.e. exponential in \p k. */ -igraph_error_t igraph_mycielski_graph(igraph_t *graph, igraph_integer_t k) { +igraph_error_t igraph_mycielski_graph(igraph_t *graph, igraph_int_t k) { igraph_t g; if (k < 0) { diff --git a/src/vendor/cigraph/src/constructors/prufer.c b/src/vendor/cigraph/src/constructors/prufer.c index 85df30d7e5a..bc18212029c 100644 --- a/src/vendor/cigraph/src/constructors/prufer.c +++ b/src/vendor/cigraph/src/constructors/prufer.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -55,23 +55,23 @@ igraph_error_t igraph_from_prufer(igraph_t *graph, const igraph_vector_int_t *prufer) { igraph_vector_int_t degree; igraph_vector_int_t edges; - igraph_integer_t n; - igraph_integer_t i, k; - igraph_integer_t u, v; /* vertices */ - igraph_integer_t ec; + igraph_int_t n; + igraph_int_t i, k; + igraph_int_t u, v; /* vertices */ + igraph_int_t ec; IGRAPH_SAFE_ADD(igraph_vector_int_size(prufer), 2, &n); IGRAPH_VECTOR_INT_INIT_FINALLY(°ree, n); /* initializes vector to zeros */ { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(n - 1, 2, &no_of_edges2); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges2); } /* build out-degree vector (i.e. number of child vertices) and verify Prufer sequence */ for (i = 0; i < n - 2; ++i) { - igraph_integer_t w = VECTOR(*prufer)[i]; + igraph_int_t w = VECTOR(*prufer)[i]; if (w >= n || w < 0) { IGRAPH_ERROR("Invalid Prufer sequence.", IGRAPH_EINVAL); } diff --git a/src/vendor/cigraph/src/constructors/regular.c b/src/vendor/cigraph/src/constructors/regular.c index d3780785fcb..426559f336a 100644 --- a/src/vendor/cigraph/src/constructors/regular.c +++ b/src/vendor/cigraph/src/constructors/regular.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -70,11 +70,11 @@ * * \example examples/simple/igraph_star.c */ -igraph_error_t igraph_star(igraph_t *graph, igraph_integer_t n, igraph_star_mode_t mode, - igraph_integer_t center) { +igraph_error_t igraph_star(igraph_t *graph, igraph_int_t n, igraph_star_mode_t mode, + igraph_int_t center) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t i; + igraph_int_t i; if (n < 0) { IGRAPH_ERROR("Invalid number of vertices.", IGRAPH_EINVVID); @@ -88,11 +88,11 @@ igraph_error_t igraph_star(igraph_t *graph, igraph_integer_t n, igraph_star_mode } if (mode != IGRAPH_STAR_MUTUAL) { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(n-1, 2, &no_of_edges2); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges2); } else { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(n-1, 4, &no_of_edges2); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges2); } @@ -190,12 +190,12 @@ igraph_error_t igraph_star(igraph_t *graph, igraph_integer_t n, igraph_star_mode * */ -igraph_error_t igraph_wheel(igraph_t *graph, igraph_integer_t n, igraph_wheel_mode_t mode, - igraph_integer_t center) { +igraph_error_t igraph_wheel(igraph_t *graph, igraph_int_t n, igraph_wheel_mode_t mode, + igraph_int_t center) { igraph_star_mode_t star_mode; igraph_vector_int_t rim_edges = IGRAPH_VECTOR_NULL; - igraph_integer_t i; + igraph_int_t i; /* Firstly creates a star by the function \ref igraph_star() and makes * use of its existing input parameter checking ability, it can check @@ -333,15 +333,15 @@ igraph_error_t igraph_wheel(igraph_t *graph, igraph_integer_t n, igraph_wheel_mo * is the average degree of the graph, k is the \p nei argument. */ igraph_error_t igraph_square_lattice( - igraph_t *graph, const igraph_vector_int_t *dimvector, igraph_integer_t nei, + igraph_t *graph, const igraph_vector_int_t *dimvector, igraph_int_t nei, igraph_bool_t directed, igraph_bool_t mutual, const igraph_vector_bool_t *periodic ) { - igraph_integer_t dims = igraph_vector_int_size(dimvector); - igraph_integer_t no_of_nodes; + igraph_int_t dims = igraph_vector_int_size(dimvector); + igraph_int_t no_of_nodes; igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t *coords, *weights; - igraph_integer_t i, j; + igraph_int_t *coords, *weights; + igraph_int_t i, j; int carry, pos; int iter = 0; @@ -362,11 +362,11 @@ igraph_error_t igraph_square_lattice( /* init coords & weights */ - coords = IGRAPH_CALLOC(dims, igraph_integer_t); + coords = IGRAPH_CALLOC(dims, igraph_int_t); IGRAPH_CHECK_OOM(coords, "Lattice creation failed."); IGRAPH_FINALLY(igraph_free, coords); - weights = IGRAPH_CALLOC(dims, igraph_integer_t); + weights = IGRAPH_CALLOC(dims, igraph_int_t); IGRAPH_CHECK_OOM(weights, "Lattice creation failed."); IGRAPH_FINALLY(igraph_free, weights); @@ -379,12 +379,12 @@ igraph_error_t igraph_square_lattice( IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); if (mutual && directed) { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(no_of_nodes, dims, &no_of_edges2); IGRAPH_SAFE_MULT(no_of_edges2, 2, &no_of_edges2); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); } else { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(no_of_nodes, dims, &no_of_edges2); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); } @@ -399,7 +399,7 @@ igraph_error_t igraph_square_lattice( igraph_bool_t is_periodic = IS_PERIODIC(j); if (is_periodic|| coords[j] != VECTOR(*dimvector)[j] - 1) { - igraph_integer_t new_nei; + igraph_int_t new_nei; if (coords[j] != VECTOR(*dimvector)[j] - 1) { new_nei = i + weights[j] + 1; } else { @@ -412,7 +412,7 @@ igraph_error_t igraph_square_lattice( } } /* if is_periodic || coords[j] */ if (mutual && directed && (is_periodic || coords[j] != 0)) { - igraph_integer_t new_nei; + igraph_int_t new_nei; if (coords[j] != 0) { new_nei = i - weights[j] + 1; } else { @@ -490,12 +490,12 @@ igraph_error_t igraph_square_lattice( * * \example examples/simple/igraph_ring.c */ -igraph_error_t igraph_ring(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, +igraph_error_t igraph_ring(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t mutual, igraph_bool_t circular) { igraph_vector_int_t edges; - igraph_integer_t no_of_edges, no_of_edges2; - igraph_integer_t i; + igraph_int_t no_of_edges, no_of_edges2; + igraph_int_t i; if (n < 0) { IGRAPH_ERRORF("The number of vertices must be non-negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, n); @@ -566,7 +566,7 @@ igraph_error_t igraph_ring(igraph_t *graph, igraph_integer_t n, igraph_bool_t di * Time complexity: O(|V|), the number of vertices in the graph. */ igraph_error_t igraph_path_graph( - igraph_t *graph, igraph_integer_t n, + igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t mutual) { return igraph_ring(graph, n, directed, mutual, /* circular= */ false); } @@ -596,7 +596,7 @@ igraph_error_t igraph_path_graph( * Time complexity: O(|V|), the number of vertices in the graph. */ igraph_error_t igraph_cycle_graph( - igraph_t *graph, igraph_integer_t n, + igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_bool_t mutual) { return igraph_ring(graph, n, directed, mutual, /* circular= */ true); } @@ -648,13 +648,13 @@ igraph_error_t igraph_cycle_graph( * * \example examples/simple/igraph_kary_tree.c */ -igraph_error_t igraph_kary_tree(igraph_t *graph, igraph_integer_t n, igraph_integer_t children, +igraph_error_t igraph_kary_tree(igraph_t *graph, igraph_int_t n, igraph_int_t children, igraph_tree_mode_t type) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t i, j; - igraph_integer_t idx = 0; - igraph_integer_t to = 1; + igraph_int_t i, j; + igraph_int_t idx = 0; + igraph_int_t to = 1; if (n < 0) { IGRAPH_ERROR("Number of vertices cannot be negative.", IGRAPH_EINVAL); @@ -668,7 +668,7 @@ igraph_error_t igraph_kary_tree(igraph_t *graph, igraph_integer_t n, igraph_inte } { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; if (n > 0) { IGRAPH_SAFE_MULT(n-1, 2, &no_of_edges2); } else { @@ -744,8 +744,8 @@ igraph_error_t igraph_symmetric_tree(igraph_t *graph, const igraph_vector_int_t igraph_tree_mode_t type) { igraph_vector_int_t edges; - igraph_integer_t j, k, temp, no_of_nodes, idx, parent, child, level_end; - igraph_integer_t branching_counts_size = igraph_vector_int_size(branches); + igraph_int_t j, k, temp, no_of_nodes, idx, parent, child, level_end; + igraph_int_t branching_counts_size = igraph_vector_int_size(branches); if (type != IGRAPH_TREE_OUT && type != IGRAPH_TREE_IN && type != IGRAPH_TREE_UNDIRECTED) { IGRAPH_ERROR("Invalid tree orientation type.", IGRAPH_EINVMODE); @@ -764,7 +764,7 @@ igraph_error_t igraph_symmetric_tree(igraph_t *graph, const igraph_vector_int_t /* Trees have precisely |E| = |V| - 1 edges. */ { - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(no_of_nodes - 1, 2, &no_of_edges2); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges2); } @@ -838,7 +838,7 @@ igraph_error_t igraph_symmetric_tree(igraph_t *graph, const igraph_vector_int_t * \example examples/simple/igraph_regular_tree.c */ -igraph_error_t igraph_regular_tree(igraph_t *graph, igraph_integer_t h, igraph_integer_t k, igraph_tree_mode_t type) { +igraph_error_t igraph_regular_tree(igraph_t *graph, igraph_int_t h, igraph_int_t k, igraph_tree_mode_t type) { igraph_vector_int_t branching_counts; if (h < 1) { @@ -902,12 +902,12 @@ igraph_error_t igraph_regular_tree(igraph_t *graph, igraph_integer_t h, igraph_i * of edges. */ igraph_error_t igraph_extended_chordal_ring( - igraph_t *graph, igraph_integer_t nodes, const igraph_matrix_int_t *W, + igraph_t *graph, igraph_int_t nodes, const igraph_matrix_int_t *W, igraph_bool_t directed) { igraph_vector_int_t edges; - igraph_integer_t period = igraph_matrix_int_ncol(W); - igraph_integer_t nrow = igraph_matrix_int_nrow(W); - igraph_integer_t i, j, mpos = 0, epos = 0; + igraph_int_t period = igraph_matrix_int_ncol(W); + igraph_int_t nrow = igraph_matrix_int_nrow(W); + igraph_int_t i, j, mpos = 0, epos = 0; if (nodes < 3) { IGRAPH_ERROR("An extended chordal ring has at least 3 nodes.", IGRAPH_EINVAL); @@ -920,7 +920,7 @@ igraph_error_t igraph_extended_chordal_ring( { /* ecount = nodes + nodes * nrow */ - igraph_integer_t no_of_edges2; + igraph_int_t no_of_edges2; IGRAPH_SAFE_MULT(nodes, nrow, &no_of_edges2); IGRAPH_SAFE_ADD(no_of_edges2, nodes, &no_of_edges2); IGRAPH_SAFE_MULT(no_of_edges2, 2, &no_of_edges2); @@ -937,8 +937,8 @@ igraph_error_t igraph_extended_chordal_ring( if (nrow > 0) { for (i = 0; i < nodes; i++) { for (j = 0; j < nrow; j++) { - igraph_integer_t offset = MATRIX(*W, j, mpos); - igraph_integer_t v = (i + offset) % nodes; + igraph_int_t offset = MATRIX(*W, j, mpos); + igraph_int_t v = (i + offset) % nodes; if (v < 0) { v += nodes; /* handle negative offsets */ @@ -979,15 +979,19 @@ igraph_error_t igraph_extended_chordal_ring( * Time complexity: O(2^n) */ igraph_error_t igraph_hypercube(igraph_t *graph, - igraph_integer_t n, igraph_bool_t directed) { + igraph_int_t n, igraph_bool_t directed) { /* An n-dimensional hypercube graph has 2^n vertices and 2^(n-1)*n edges. * The maximum possible dimension is calculated with the assumption that * the largest possible edge count is no more than half IGRAPH_INTEGER_MAX, * which is in fact the current limit. */ - const igraph_integer_t maxn = - (IGRAPH_INTEGER_SIZE - 1) - (igraph_integer_t) ceil(log2(IGRAPH_INTEGER_SIZE)); + const igraph_int_t maxn = + (IGRAPH_INTEGER_SIZE - 1) - (igraph_int_t) ceil(log2(IGRAPH_INTEGER_SIZE)); + + if (n < 0) { + IGRAPH_ERROR("Hypercube dimension must not be negative.", IGRAPH_EINVAL); + } if (n > maxn) { IGRAPH_ERRORF("The requested hypercube graph dimension (%" IGRAPH_PRId @@ -997,19 +1001,19 @@ igraph_error_t igraph_hypercube(igraph_t *graph, /* Integer overflow is no longer a concern after the above check. */ - const igraph_integer_t vcount = (igraph_integer_t) 1 << n; - const igraph_integer_t ecount = n > 0 ? ((igraph_integer_t) 1 << (n-1)) * n : 0; /* avoid UBSan warning */ + const igraph_int_t vcount = (igraph_int_t) 1 << n; + const igraph_int_t ecount = n > 0 ? ((igraph_int_t) 1 << (n-1)) * n : 0; /* avoid UBSan warning */ igraph_vector_int_t edges; - igraph_integer_t p; + igraph_int_t p; int iter = 0; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2*ecount); p = 0; - for (igraph_integer_t v=0; v < vcount; v++) { - igraph_integer_t bit = 1; - for (igraph_integer_t i=0; i < n; i++) { - const igraph_integer_t u = v ^ bit; + for (igraph_int_t v=0; v < vcount; v++) { + igraph_int_t bit = 1; + for (igraph_int_t i=0; i < n; i++) { + const igraph_int_t u = v ^ bit; if (v < u) { VECTOR(edges)[p++] = v; VECTOR(edges)[p++] = u; diff --git a/src/vendor/cigraph/src/constructors/trees.c b/src/vendor/cigraph/src/constructors/trees.c index e68b3478aeb..880de40edeb 100644 --- a/src/vendor/cigraph/src/constructors/trees.c +++ b/src/vendor/cigraph/src/constructors/trees.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -72,7 +72,7 @@ igraph_error_t igraph_tree_from_parent_vector( const igraph_vector_int_t *parents, igraph_tree_mode_t type) { - const igraph_integer_t no_of_nodes = igraph_vector_int_size(parents); + const igraph_int_t no_of_nodes = igraph_vector_int_size(parents); igraph_vector_int_t seen; igraph_vector_int_t edges; igraph_bool_t directed, intree; @@ -102,14 +102,14 @@ igraph_error_t igraph_tree_from_parent_vector( IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_nodes > 1024 ? 2048 : 2*(no_of_nodes-1)); igraph_vector_int_clear(&edges); - igraph_integer_t c=1; - for (igraph_integer_t i=0; i < no_of_nodes; i++) { - igraph_integer_t v = i; + igraph_int_t c=1; + for (igraph_int_t i=0; i < no_of_nodes; i++) { + igraph_int_t v = i; if (VECTOR(seen)[v]) continue; while (true) { - igraph_integer_t u; + igraph_int_t u; VECTOR(seen)[v] = c; /* mark v as seen in the current round */ u = VECTOR(*parents)[v]; diff --git a/src/vendor/cigraph/src/core/bitset.c b/src/vendor/cigraph/src/core/bitset.c index e21b02309d5..1ffe9020d2e 100644 --- a/src/vendor/cigraph/src/core/bitset.c +++ b/src/vendor/cigraph/src/core/bitset.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -21,12 +21,12 @@ #include "igraph_bitset.h" #include "igraph_memory.h" -igraph_integer_t igraph_i_ctz32(igraph_uint_t x) { +igraph_int_t igraph_i_ctz32(igraph_uint_t x) { #ifdef HAVE__BITSCANFORWARD unsigned long index; return _BitScanForward(&index, x) ? index : 32; #else - for (igraph_integer_t i = 0; i < 32; ++i) { + for (igraph_int_t i = 0; i < 32; ++i) { if (IGRAPH_BIT_MASK(i) & x) { return i; } @@ -35,12 +35,12 @@ igraph_integer_t igraph_i_ctz32(igraph_uint_t x) { #endif } -igraph_integer_t igraph_i_clz32(igraph_uint_t x) { +igraph_int_t igraph_i_clz32(igraph_uint_t x) { #ifdef HAVE_BITSCANREVERSE unsigned long index; return _BitScanReverse(&index, x) ? 31 - index : 32; #else - for (igraph_integer_t i = 31; i >= 0; --i) { + for (igraph_int_t i = 31; i >= 0; --i) { if (IGRAPH_BIT_MASK(i) & x) { return 31 - i; } @@ -49,8 +49,8 @@ igraph_integer_t igraph_i_clz32(igraph_uint_t x) { #endif } -igraph_integer_t igraph_i_popcnt(igraph_uint_t x) { - igraph_integer_t result = 0; +igraph_int_t igraph_i_popcnt(igraph_uint_t x) { + igraph_int_t result = 0; while (x) { result++; x = x & (x - 1); @@ -58,14 +58,14 @@ igraph_integer_t igraph_i_popcnt(igraph_uint_t x) { return result; } -/* Fallbacks for 64-bit word (and igraph_integer_t/igraph_uint_t) size */ +/* Fallbacks for 64-bit word (and igraph_int_t/igraph_uint_t) size */ #if IGRAPH_INTEGER_SIZE == 64 -igraph_integer_t igraph_i_ctz64(igraph_uint_t x) { +igraph_int_t igraph_i_ctz64(igraph_uint_t x) { #ifdef HAVE_BITSCANFORWARD64 unsigned long index; return _BitScanForward64(&index, x) ? index : 64; #else - for (igraph_integer_t i = 0; i < 64; ++i) { + for (igraph_int_t i = 0; i < 64; ++i) { if (IGRAPH_BIT_MASK(i) & x) { return i; } @@ -74,12 +74,12 @@ igraph_integer_t igraph_i_ctz64(igraph_uint_t x) { #endif } -igraph_integer_t igraph_i_clz64(igraph_uint_t x) { +igraph_int_t igraph_i_clz64(igraph_uint_t x) { #ifdef HAVE_BITSCANREVERSE64 unsigned long index; return _BitScanReverse64(&index, x) ? 63 - index : 64; #else - for (igraph_integer_t i = 63; i >= 0; --i) { + for (igraph_int_t i = 63; i >= 0; --i) { if (IGRAPH_BIT_MASK(i) & x) { return 63 - i; } @@ -99,7 +99,7 @@ igraph_integer_t igraph_i_clz64(igraph_uint_t x) { * difference being the C++ version's size is initialized at compile time. * * The \type igraph_bitset_t type and use O(n/w) space - * to store n elements, where w is the bit width of \type igraph_integer_t, + * to store n elements, where w is the bit width of \type igraph_int_t, * the integer type used throughout the library (either 32 or 64). * Sometimes they use more, this is because bitsets can * shrink, but even if they shrink, the current implementation does not free a @@ -146,8 +146,6 @@ igraph_integer_t igraph_i_clz64(igraph_uint_t x) { * \function igraph_bitset_init * \brief Initializes a bitset object (constructor). * - * \experimental - * * * Every bitset needs to be initialized before it can be used, and * there are a number of initialization functions or otherwise called @@ -172,8 +170,8 @@ igraph_integer_t igraph_i_clz64(igraph_uint_t x) { * w is the word size of the machine (32 or 64). */ -igraph_error_t igraph_bitset_init(igraph_bitset_t *bitset, igraph_integer_t size) { - igraph_integer_t alloc_size = IGRAPH_BIT_NSLOTS(size); +igraph_error_t igraph_bitset_init(igraph_bitset_t *bitset, igraph_int_t size) { + igraph_int_t alloc_size = IGRAPH_BIT_NSLOTS(size); bitset->stor_begin = IGRAPH_CALLOC(alloc_size, igraph_uint_t); IGRAPH_CHECK_OOM(bitset->stor_begin, "Cannot initialize bitset."); bitset->size = size; @@ -186,8 +184,6 @@ igraph_error_t igraph_bitset_init(igraph_bitset_t *bitset, igraph_integer_t size * \function igraph_bitset_destroy * \brief Destroys a bitset object. * - * \experimental - * * All bitsets initialized by \ref igraph_bitset_init() should be properly * destroyed by this function. A destroyed bitset needs to be * reinitialized by \ref igraph_bitset_init() or @@ -210,8 +206,6 @@ void igraph_bitset_destroy(igraph_bitset_t *bitset) { * \function igraph_bitset_init_copy * \brief Initializes a bitset from another bitset object (constructor). * - * \experimental - * * The contents of the existing bitset object will be copied to * the new one. * @@ -230,7 +224,7 @@ igraph_error_t igraph_bitset_init_copy(igraph_bitset_t *dest, const igraph_bitse IGRAPH_ASSERT(src != NULL); IGRAPH_ASSERT(src->stor_begin != NULL); IGRAPH_CHECK(igraph_bitset_init(dest, src->size)); - for (igraph_integer_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { + for (igraph_int_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { VECTOR(*dest)[i] = VECTOR(*src)[i]; } return IGRAPH_SUCCESS; @@ -241,8 +235,6 @@ igraph_error_t igraph_bitset_init_copy(igraph_bitset_t *dest, const igraph_bitse * \function igraph_bitset_update * \brief Update a bitset from another one. * - * \experimental - * * The size and contents of \p dest will be identical to that of \p src. * * \param dest Pointer to an initialized bitset object. This will be updated. @@ -261,7 +253,7 @@ igraph_error_t igraph_bitset_update(igraph_bitset_t *dest, const igraph_bitset_t IGRAPH_ASSERT(src->stor_begin != NULL); IGRAPH_CHECK(igraph_bitset_reserve(dest, src->size)); dest->size = src->size; - for (igraph_integer_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { + for (igraph_int_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { VECTOR(*dest)[i] = VECTOR(*src)[i]; } return IGRAPH_SUCCESS; @@ -272,8 +264,6 @@ igraph_error_t igraph_bitset_update(igraph_bitset_t *dest, const igraph_bitset_t * \function igraph_bitset_capacity * \brief Returns the allocated capacity of the bitset. * - * \experimental - * * Note that this might be different from the size of the bitset (as * queried by \ref igraph_bitset_size()), and specifies how many elements * the bitset can hold, without reallocation. @@ -287,7 +277,7 @@ igraph_error_t igraph_bitset_update(igraph_bitset_t *dest, const igraph_bitset_t * Time complexity: O(1). */ -igraph_integer_t igraph_bitset_capacity(const igraph_bitset_t *bitset) { +igraph_int_t igraph_bitset_capacity(const igraph_bitset_t *bitset) { return IGRAPH_INTEGER_SIZE * (bitset->stor_end - bitset->stor_begin); } @@ -296,15 +286,13 @@ igraph_integer_t igraph_bitset_capacity(const igraph_bitset_t *bitset) { * \function igraph_bitset_size * \brief Returns the length of the bitset. * - * \experimental - * * \param bitset The bitset object * \return The size of the bitset. * * Time complexity: O(1). */ -igraph_integer_t igraph_bitset_size(const igraph_bitset_t *bitset) { +igraph_int_t igraph_bitset_size(const igraph_bitset_t *bitset) { return bitset->size; } @@ -313,8 +301,6 @@ igraph_integer_t igraph_bitset_size(const igraph_bitset_t *bitset) { * \function igraph_bitset_reserve * \brief Reserves memory for a bitset. * - * \experimental - * * \a igraph bitsets are flexible, they can grow and * shrink. Growing * however occasionally needs the data in the bitset to be copied. @@ -339,8 +325,8 @@ igraph_integer_t igraph_bitset_size(const igraph_bitset_t *bitset) { * w is the word size of the machine (32 or 64). */ -igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_integer_t capacity) { - igraph_integer_t current_capacity; +igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_int_t capacity) { + igraph_int_t current_capacity; igraph_uint_t *tmp; IGRAPH_ASSERT(bitset != NULL); @@ -367,8 +353,6 @@ igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_integer_t c * \function igraph_bitset_resize * \brief Resizes the bitset. * - * \experimental - * * Note that this function does not free any memory, just sets the * size of the bitset to the given one. It may, on the other hand, * allocate more memory if the new size is larger than the previous @@ -392,13 +376,13 @@ igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_integer_t c * w is the word size of the machine (32 or 64). */ -igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_integer_t new_size) { +igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_int_t new_size) { IGRAPH_ASSERT(bitset != NULL); IGRAPH_ASSERT(bitset->stor_begin != NULL); IGRAPH_CHECK(igraph_bitset_reserve(bitset, new_size)); if (new_size > bitset->size) { - for (igraph_integer_t i = bitset->size; i % IGRAPH_INTEGER_SIZE != 0; ++i) { + for (igraph_int_t i = bitset->size; i % IGRAPH_INTEGER_SIZE != 0; ++i) { IGRAPH_BIT_CLEAR(*bitset, i); } memset(bitset->stor_begin + IGRAPH_BIT_NSLOTS(bitset->size), 0, @@ -414,8 +398,6 @@ igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_integer_t ne * \function igraph_bitset_popcount * \brief The population count of the bitset. * - * \experimental - * * Returns the number of set bits, also called the population count, * of the bitset. * @@ -425,14 +407,14 @@ igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_integer_t ne * Time complexity: O(n/w). */ -igraph_integer_t igraph_bitset_popcount(const igraph_bitset_t *bitset) { - const igraph_integer_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; - const igraph_integer_t slots = IGRAPH_BIT_NSLOTS(bitset->size); +igraph_int_t igraph_bitset_popcount(const igraph_bitset_t *bitset) { + const igraph_int_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; + const igraph_int_t slots = IGRAPH_BIT_NSLOTS(bitset->size); const igraph_uint_t one = 1, zero = 0; /* to avoid the need to cast 1 and 0 to igraph_uint_t below */ const igraph_uint_t mask = final_block_size == IGRAPH_INTEGER_SIZE ? ~zero : ((one << final_block_size) - 1); - igraph_integer_t count = 0; + igraph_int_t count = 0; - for (igraph_integer_t i = 0; i + 1 < slots; ++i) { + for (igraph_int_t i = 0; i + 1 < slots; ++i) { count += IGRAPH_POPCOUNT(VECTOR(*bitset)[i]); } if (bitset->size) { @@ -447,8 +429,6 @@ igraph_integer_t igraph_bitset_popcount(const igraph_bitset_t *bitset) { * \function igraph_bitset_countl_zero * \brief The number of leading zeros in the bitset. * - * \experimental - * * Returns the number of leading (starting at the most significant bit) * zeros in the bitset before the first one is encountered. If the bitset * is all zeros, then its size is returned. @@ -459,17 +439,17 @@ igraph_integer_t igraph_bitset_popcount(const igraph_bitset_t *bitset) { * Time complexity: O(n/w). */ -igraph_integer_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset) { - const igraph_integer_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; - const igraph_integer_t padding = IGRAPH_INTEGER_SIZE - final_block_size; - const igraph_integer_t slots = IGRAPH_BIT_NSLOTS(bitset->size); +igraph_int_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset) { + const igraph_int_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; + const igraph_int_t padding = IGRAPH_INTEGER_SIZE - final_block_size; + const igraph_int_t slots = IGRAPH_BIT_NSLOTS(bitset->size); const igraph_uint_t one = 1, zero = 0; const igraph_uint_t mask = final_block_size == IGRAPH_INTEGER_SIZE ? ~zero : ((one << final_block_size) - one); if (bitset->size && (mask & VECTOR(*bitset)[slots - 1]) != 0) { return IGRAPH_CLZ(mask & VECTOR(*bitset)[slots - 1]) - padding; } - for (igraph_integer_t i = 1; i < slots; ++i) { + for (igraph_int_t i = 1; i < slots; ++i) { if (VECTOR(*bitset)[slots - i - 1] != 0) { return IGRAPH_INTEGER_SIZE * i + IGRAPH_CLZ(VECTOR(*bitset)[slots - i - 1]) - padding; } @@ -483,8 +463,6 @@ igraph_integer_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset) { * \function igraph_bitset_countl_one * \brief The number of leading ones in the bitset. * - * \experimental - * * Returns the number of leading ones (starting at the most significant bit) * in the bitset before the first zero is encountered. * If the bitset is all ones, then its size is returned. @@ -495,17 +473,17 @@ igraph_integer_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset) { * Time complexity: O(n/w). */ -igraph_integer_t igraph_bitset_countl_one(const igraph_bitset_t *bitset) { - const igraph_integer_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; - const igraph_integer_t padding = IGRAPH_INTEGER_SIZE - final_block_size; - const igraph_integer_t slots = IGRAPH_BIT_NSLOTS(bitset->size); +igraph_int_t igraph_bitset_countl_one(const igraph_bitset_t *bitset) { + const igraph_int_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; + const igraph_int_t padding = IGRAPH_INTEGER_SIZE - final_block_size; + const igraph_int_t slots = IGRAPH_BIT_NSLOTS(bitset->size); const igraph_uint_t one = 1, zero = 0; /* to avoid the need to cast 1 and 0 to igraph_uint_t below */ const igraph_uint_t mask = final_block_size == IGRAPH_INTEGER_SIZE ? zero : ~((one << final_block_size) - one); if (bitset->size && (mask | VECTOR(*bitset)[slots - 1]) != ~zero) { return IGRAPH_CLO(mask | VECTOR(*bitset)[slots - 1]) - padding; } - for (igraph_integer_t i = 1; i < slots; ++i) { + for (igraph_int_t i = 1; i < slots; ++i) { if (VECTOR(*bitset)[slots - i - 1] != ~zero) { return IGRAPH_INTEGER_SIZE * i + IGRAPH_CLO(VECTOR(*bitset)[slots - i - 1]) - padding; } @@ -519,8 +497,6 @@ igraph_integer_t igraph_bitset_countl_one(const igraph_bitset_t *bitset) { * \function igraph_bitset_countr_zero * \brief The number of trailing zeros in the bitset. * - * \experimental - * * Returns the number of trailing (starting at the least significant bit) * zeros in the bitset before the first one is encountered. * If the bitset is all zeros, then its size is returned. @@ -531,13 +507,13 @@ igraph_integer_t igraph_bitset_countl_one(const igraph_bitset_t *bitset) { * Time complexity: O(n/w). */ -igraph_integer_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset) { - const igraph_integer_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; - const igraph_integer_t slots = IGRAPH_BIT_NSLOTS(bitset->size); +igraph_int_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset) { + const igraph_int_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; + const igraph_int_t slots = IGRAPH_BIT_NSLOTS(bitset->size); const igraph_uint_t one = 1, zero = 0; /* to avoid the need to cast 1 and 0 to igraph_uint_t below */ const igraph_uint_t mask = final_block_size == IGRAPH_INTEGER_SIZE ? ~zero : ((one << final_block_size) - one); - for (igraph_integer_t i = 0; i + 1 < slots; ++i) { + for (igraph_int_t i = 0; i + 1 < slots; ++i) { if (VECTOR(*bitset)[i] != zero) { return IGRAPH_INTEGER_SIZE * i + IGRAPH_CTZ(VECTOR(*bitset)[i]); } @@ -554,8 +530,6 @@ igraph_integer_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset) { * \function igraph_bitset_countr_one * \brief The number of trailing ones in the bitset. * - * \experimental - * * Returns the number of trailing ones (starting at the least significant bit) * in the bitset before the first zero is encountered. * If the bitset is all ones, then its size is returned. @@ -566,13 +540,13 @@ igraph_integer_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset) { * Time complexity: O(n/w). */ -igraph_integer_t igraph_bitset_countr_one(const igraph_bitset_t *bitset) { - const igraph_integer_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; - const igraph_integer_t slots = IGRAPH_BIT_NSLOTS(bitset->size); +igraph_int_t igraph_bitset_countr_one(const igraph_bitset_t *bitset) { + const igraph_int_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; + const igraph_int_t slots = IGRAPH_BIT_NSLOTS(bitset->size); const igraph_uint_t one = 1, zero = 0; /* to avoid the need to cast 1 and 0 to igraph_uint_t below */ const igraph_uint_t mask = final_block_size == IGRAPH_INTEGER_SIZE ? zero : ~((one << final_block_size) - one); - for (igraph_integer_t i = 0; i + 1 < slots; ++i) { + for (igraph_int_t i = 0; i + 1 < slots; ++i) { if (VECTOR(*bitset)[i] != ~zero) { return IGRAPH_INTEGER_SIZE * i + IGRAPH_CTO(VECTOR(*bitset)[i]); } @@ -589,8 +563,6 @@ igraph_integer_t igraph_bitset_countr_one(const igraph_bitset_t *bitset) { * \function igraph_bitset_is_all_zero * \brief Are all bits zeros? * - * \experimental - * * \param bitset The bitset object to test. * \return True if none of the bits are set. * @@ -598,12 +570,12 @@ igraph_integer_t igraph_bitset_countr_one(const igraph_bitset_t *bitset) { */ igraph_bool_t igraph_bitset_is_all_zero(const igraph_bitset_t *bitset) { - const igraph_integer_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; - const igraph_integer_t slots = IGRAPH_BIT_NSLOTS(bitset->size); + const igraph_int_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; + const igraph_int_t slots = IGRAPH_BIT_NSLOTS(bitset->size); const igraph_uint_t one = 1, zero = 0; /* to avoid the need to cast 1 and 0 to igraph_uint_t below */ const igraph_uint_t mask = final_block_size == IGRAPH_INTEGER_SIZE ? ~zero : ((one << final_block_size) - one); - for (igraph_integer_t i = 0; i < slots - 1; i++) { + for (igraph_int_t i = 0; i < slots - 1; i++) { if (VECTOR(*bitset)[i] != zero) { return false; } @@ -619,8 +591,6 @@ igraph_bool_t igraph_bitset_is_all_zero(const igraph_bitset_t *bitset) { * \function igraph_bitset_is_all_one * \brief Are all bits ones? * - * \experimental - * * \param bitset The bitset object to test. * \return True if all of the bits are set. * @@ -628,12 +598,12 @@ igraph_bool_t igraph_bitset_is_all_zero(const igraph_bitset_t *bitset) { */ igraph_bool_t igraph_bitset_is_all_one(const igraph_bitset_t *bitset) { - const igraph_integer_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; - const igraph_integer_t slots = IGRAPH_BIT_NSLOTS(bitset->size); + const igraph_int_t final_block_size = bitset->size % IGRAPH_INTEGER_SIZE ? bitset->size % IGRAPH_INTEGER_SIZE : IGRAPH_INTEGER_SIZE; + const igraph_int_t slots = IGRAPH_BIT_NSLOTS(bitset->size); const igraph_uint_t one = 1, zero = 0; /* to avoid the need to cast 1 and 0 to igraph_uint_t below */ const igraph_uint_t mask = final_block_size == IGRAPH_INTEGER_SIZE ? zero : ~((one << final_block_size) - one); - for (igraph_integer_t i = 0; i < slots - 1; i++) { + for (igraph_int_t i = 0; i < slots - 1; i++) { if (VECTOR(*bitset)[i] != ~zero) { return false; } @@ -649,8 +619,6 @@ igraph_bool_t igraph_bitset_is_all_one(const igraph_bitset_t *bitset) { * \function igraph_bitset_is_any_zero * \brief Are any bits zeros? * - * \experimental - * * \param bitset The bitset object to test. * \return True if at least one bit is zero. * @@ -666,8 +634,6 @@ igraph_bool_t igraph_bitset_is_any_zero(const igraph_bitset_t *bitset) { * \function igraph_bitset_is_any_one * \brief Are any bits ones? * - * \experimental - * * \param bitset The bitset object to test. * \return True if at least one bit is one. * @@ -683,8 +649,6 @@ igraph_bool_t igraph_bitset_is_any_one(const igraph_bitset_t *bitset) { * \function igraph_bitset_or * \brief Bitwise OR of two bitsets. * - * \experimental - * * Applies a bitwise or to the contents of two bitsets and stores it in an * already initialized bitset. The destination bitset may be equal to one * (or even both) of the sources. When working with bitsets, it is common @@ -701,7 +665,7 @@ igraph_bool_t igraph_bitset_is_any_one(const igraph_bitset_t *bitset) { void igraph_bitset_or(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2) { - for (igraph_integer_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { + for (igraph_int_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { VECTOR(*dest)[i] = VECTOR(*src1)[i] | VECTOR(*src2)[i]; } } @@ -711,8 +675,6 @@ void igraph_bitset_or(igraph_bitset_t *dest, * \function igraph_bitset_and * \brief Bitwise AND of two bitsets. * - * \experimental - * * Applies a bitwise and to the contents of two bitsets and stores it in an * already initialized bitset. The destination bitset may be equal to one * (or even both) of the sources. When working with bitsets, it is common @@ -728,7 +690,7 @@ void igraph_bitset_or(igraph_bitset_t *dest, */ void igraph_bitset_and(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2) { - for (igraph_integer_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { + for (igraph_int_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { VECTOR(*dest)[i] = VECTOR(*src1)[i] & VECTOR(*src2)[i]; } } @@ -738,8 +700,6 @@ void igraph_bitset_and(igraph_bitset_t *dest, const igraph_bitset_t *src1, const * \function igraph_bitset_xor * \brief Bitwise XOR of two bitsets. * - * \experimental - * * Applies a bitwise xor to the contents of two bitsets and stores it in * an already initialized bitset. The destination bitset may be equal to * one (or even both) of the sources. When working with bitsets, it is common @@ -756,7 +716,7 @@ void igraph_bitset_and(igraph_bitset_t *dest, const igraph_bitset_t *src1, const void igraph_bitset_xor(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2) { - for (igraph_integer_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { + for (igraph_int_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { VECTOR(*dest)[i] = VECTOR(*src1)[i] ^ VECTOR(*src2)[i]; } } @@ -766,8 +726,6 @@ void igraph_bitset_xor(igraph_bitset_t *dest, * \function igraph_bitset_not * \brief Bitwise negation of a bitset. * - * \experimental - * * Applies a bitwise not to the contents of a bitset and stores it in an * already initialized bitset. The destination bitset may be equal to the * source. When working with bitsets, it is common that those created are @@ -781,7 +739,7 @@ void igraph_bitset_xor(igraph_bitset_t *dest, */ void igraph_bitset_not(igraph_bitset_t *dest, const igraph_bitset_t *src) { - for (igraph_integer_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { + for (igraph_int_t i = 0; i < IGRAPH_BIT_NSLOTS(dest->size); ++i) { VECTOR(*dest)[i] = ~VECTOR(*src)[i]; } } @@ -791,8 +749,6 @@ void igraph_bitset_not(igraph_bitset_t *dest, const igraph_bitset_t *src) { * \function igraph_bitset_fill * \brief Fills a bitset with a constant value. * - * \experimental - * * Sets all bits of a bitset to the same value. * * \param bitset The bitset object to modify. @@ -814,8 +770,6 @@ void igraph_bitset_fill(igraph_bitset_t *bitset, igraph_bool_t value) { * \function igraph_bitset_null * \brief Clears all bits in a bitset. * - * \experimental - * * \param bitset The bitset object to clear all bits in. * * \sa \ref igraph_bitset_fill() @@ -832,8 +786,6 @@ void igraph_bitset_null(igraph_bitset_t *bitset) { * \function igraph_bitset_fprint * \brief Prints the bits of a bitset. * - * \experimental - * * Outputs the contents of a bitset to a file. * The bitset is written from index n-1 to index 0, left to right, * such that index 0 is the least significant bit and index n-1 is @@ -852,7 +804,7 @@ void igraph_bitset_null(igraph_bitset_t *bitset) { * Time complexity: O(n). */ igraph_error_t igraph_bitset_fprint(const igraph_bitset_t *bitset, FILE *file) { - for (igraph_integer_t i = bitset->size - 1; i >= 0; i--) { + for (igraph_int_t i = bitset->size - 1; i >= 0; i--) { fputc(IGRAPH_BIT_TEST(*bitset, i) ? '1' : '0', file); } return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/core/bitset_list.c b/src/vendor/cigraph/src/core/bitset_list.c index 4b3ec576be6..c6dc79c25ac 100644 --- a/src/vendor/cigraph/src/core/bitset_list.c +++ b/src/vendor/cigraph/src/core/bitset_list.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/core/buckets.c b/src/vendor/cigraph/src/core/buckets.c index 7aa08b4b39b..28330b3d2f3 100644 --- a/src/vendor/cigraph/src/core/buckets.c +++ b/src/vendor/cigraph/src/core/buckets.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -42,7 +42,7 @@ * _empty() and _popmax() operations. */ -igraph_error_t igraph_buckets_init(igraph_buckets_t *b, igraph_integer_t bsize, igraph_integer_t size) { +igraph_error_t igraph_buckets_init(igraph_buckets_t *b, igraph_int_t bsize, igraph_int_t size) { IGRAPH_VECTOR_INT_INIT_FINALLY(&b->bptr, bsize); IGRAPH_VECTOR_INT_INIT_FINALLY(&b->buckets, size); b->max = -1; b->no = 0; @@ -55,10 +55,10 @@ void igraph_buckets_destroy(igraph_buckets_t *b) { igraph_vector_int_destroy(&b->buckets); } -igraph_integer_t igraph_buckets_popmax(igraph_buckets_t *b) { +igraph_int_t igraph_buckets_popmax(igraph_buckets_t *b) { /* Precondition: there is at least a non-empty bucket */ /* Search for the highest bucket first */ - igraph_integer_t max; + igraph_int_t max; while ( (max = VECTOR(b->bptr)[b->max]) == 0) { b->max --; } @@ -68,8 +68,8 @@ igraph_integer_t igraph_buckets_popmax(igraph_buckets_t *b) { return max - 1; } -igraph_integer_t igraph_buckets_pop(igraph_buckets_t *b, igraph_integer_t bucket) { - igraph_integer_t ret = VECTOR(b->bptr)[bucket] - 1; +igraph_int_t igraph_buckets_pop(igraph_buckets_t *b, igraph_int_t bucket) { + igraph_int_t ret = VECTOR(b->bptr)[bucket] - 1; VECTOR(b->bptr)[bucket] = VECTOR(b->buckets)[ret]; b->no--; return ret; @@ -80,12 +80,12 @@ igraph_bool_t igraph_buckets_empty(const igraph_buckets_t *b) { } igraph_bool_t igraph_buckets_empty_bucket(const igraph_buckets_t *b, - igraph_integer_t bucket) { + igraph_int_t bucket) { return VECTOR(b->bptr)[bucket] == 0; } -void igraph_buckets_add(igraph_buckets_t *b, igraph_integer_t bucket, - igraph_integer_t elem) { +void igraph_buckets_add(igraph_buckets_t *b, igraph_int_t bucket, + igraph_int_t elem) { VECTOR(b->buckets)[elem] = VECTOR(b->bptr)[bucket]; VECTOR(b->bptr)[bucket] = elem + 1; @@ -102,7 +102,7 @@ void igraph_buckets_clear(igraph_buckets_t *b) { b->no = 0; } -igraph_error_t igraph_dbuckets_init(igraph_dbuckets_t *b, igraph_integer_t bsize, igraph_integer_t size) { +igraph_error_t igraph_dbuckets_init(igraph_dbuckets_t *b, igraph_int_t bsize, igraph_int_t size) { IGRAPH_VECTOR_INT_INIT_FINALLY(&b->bptr, bsize); IGRAPH_VECTOR_INT_INIT_FINALLY(&b->next, size); IGRAPH_VECTOR_INT_INIT_FINALLY(&b->prev, size); @@ -125,16 +125,16 @@ void igraph_dbuckets_clear(igraph_dbuckets_t *b) { b->no = 0; } -igraph_integer_t igraph_dbuckets_popmax(igraph_dbuckets_t *b) { +igraph_int_t igraph_dbuckets_popmax(igraph_dbuckets_t *b) { while ( VECTOR(b->bptr)[b->max] == 0) { b->max--; } return igraph_dbuckets_pop(b, b->max); } -igraph_integer_t igraph_dbuckets_pop(igraph_dbuckets_t *b, igraph_integer_t bucket) { - igraph_integer_t ret = VECTOR(b->bptr)[bucket] - 1; - igraph_integer_t next = VECTOR(b->next)[ret]; +igraph_int_t igraph_dbuckets_pop(igraph_dbuckets_t *b, igraph_int_t bucket) { + igraph_int_t ret = VECTOR(b->bptr)[bucket] - 1; + igraph_int_t next = VECTOR(b->next)[ret]; VECTOR(b->bptr)[bucket] = next; if (next != 0) { VECTOR(b->prev)[next - 1] = 0; @@ -149,13 +149,13 @@ igraph_bool_t igraph_dbuckets_empty(const igraph_dbuckets_t *b) { } igraph_bool_t igraph_dbuckets_empty_bucket(const igraph_dbuckets_t *b, - igraph_integer_t bucket) { + igraph_int_t bucket) { return VECTOR(b->bptr)[bucket] == 0; } -void igraph_dbuckets_add(igraph_dbuckets_t *b, igraph_integer_t bucket, - igraph_integer_t elem) { - igraph_integer_t oldfirst = VECTOR(b->bptr)[bucket]; +void igraph_dbuckets_add(igraph_dbuckets_t *b, igraph_int_t bucket, + igraph_int_t elem) { + igraph_int_t oldfirst = VECTOR(b->bptr)[bucket]; VECTOR(b->bptr)[bucket] = elem + 1; VECTOR(b->next)[elem] = oldfirst; if (oldfirst != 0) { @@ -169,18 +169,18 @@ void igraph_dbuckets_add(igraph_dbuckets_t *b, igraph_integer_t bucket, /* Remove an arbitrary element */ -void igraph_dbuckets_delete(igraph_dbuckets_t *b, igraph_integer_t bucket, - igraph_integer_t elem) { +void igraph_dbuckets_delete(igraph_dbuckets_t *b, igraph_int_t bucket, + igraph_int_t elem) { if (VECTOR(b->bptr)[bucket] == elem + 1) { /* First element in bucket */ - igraph_integer_t next = VECTOR(b->next)[elem]; + igraph_int_t next = VECTOR(b->next)[elem]; if (next != 0) { VECTOR(b->prev)[next - 1] = 0; } VECTOR(b->bptr)[bucket] = next; } else { - igraph_integer_t next = VECTOR(b->next)[elem]; - igraph_integer_t prev = VECTOR(b->prev)[elem]; + igraph_int_t next = VECTOR(b->next)[elem]; + igraph_int_t prev = VECTOR(b->prev)[elem]; if (next != 0) { VECTOR(b->prev)[next - 1] = prev; } diff --git a/src/vendor/cigraph/src/core/buckets.h b/src/vendor/cigraph/src/core/buckets.h index e88c4c923d2..6b862593f60 100644 --- a/src/vendor/cigraph/src/core/buckets.h +++ b/src/vendor/cigraph/src/core/buckets.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -33,38 +33,38 @@ IGRAPH_BEGIN_C_DECLS typedef struct igraph_buckets_t { igraph_vector_int_t bptr; igraph_vector_int_t buckets; - igraph_integer_t max, no; + igraph_int_t max, no; } igraph_buckets_t; -igraph_error_t igraph_buckets_init(igraph_buckets_t *b, igraph_integer_t bsize, igraph_integer_t size); +igraph_error_t igraph_buckets_init(igraph_buckets_t *b, igraph_int_t bsize, igraph_int_t size); void igraph_buckets_destroy(igraph_buckets_t *b); void igraph_buckets_clear(igraph_buckets_t *b); -igraph_integer_t igraph_buckets_popmax(igraph_buckets_t *b); -igraph_integer_t igraph_buckets_pop(igraph_buckets_t *b, igraph_integer_t bucket); +igraph_int_t igraph_buckets_popmax(igraph_buckets_t *b); +igraph_int_t igraph_buckets_pop(igraph_buckets_t *b, igraph_int_t bucket); IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_buckets_empty(const igraph_buckets_t *b); IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_buckets_empty_bucket(const igraph_buckets_t *b, - igraph_integer_t bucket); -void igraph_buckets_add(igraph_buckets_t *b, igraph_integer_t bucket, - igraph_integer_t elem); + igraph_int_t bucket); +void igraph_buckets_add(igraph_buckets_t *b, igraph_int_t bucket, + igraph_int_t elem); typedef struct igraph_dbuckets_t { igraph_vector_int_t bptr; igraph_vector_int_t next, prev; - igraph_integer_t max, no; + igraph_int_t max, no; } igraph_dbuckets_t; -igraph_error_t igraph_dbuckets_init(igraph_dbuckets_t *b, igraph_integer_t bsize, igraph_integer_t size); +igraph_error_t igraph_dbuckets_init(igraph_dbuckets_t *b, igraph_int_t bsize, igraph_int_t size); void igraph_dbuckets_destroy(igraph_dbuckets_t *b); void igraph_dbuckets_clear(igraph_dbuckets_t *b); -igraph_integer_t igraph_dbuckets_popmax(igraph_dbuckets_t *b); -igraph_integer_t igraph_dbuckets_pop(igraph_dbuckets_t *b, igraph_integer_t bucket); +igraph_int_t igraph_dbuckets_popmax(igraph_dbuckets_t *b); +igraph_int_t igraph_dbuckets_pop(igraph_dbuckets_t *b, igraph_int_t bucket); IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_dbuckets_empty(const igraph_dbuckets_t *b); IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_dbuckets_empty_bucket(const igraph_dbuckets_t *b, - igraph_integer_t bucket); -void igraph_dbuckets_add(igraph_dbuckets_t *b, igraph_integer_t bucket, - igraph_integer_t elem); -void igraph_dbuckets_delete(igraph_dbuckets_t *b, igraph_integer_t bucket, - igraph_integer_t elem); + igraph_int_t bucket); +void igraph_dbuckets_add(igraph_dbuckets_t *b, igraph_int_t bucket, + igraph_int_t elem); +void igraph_dbuckets_delete(igraph_dbuckets_t *b, igraph_int_t bucket, + igraph_int_t elem); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/core/cutheap.c b/src/vendor/cigraph/src/core/cutheap.c index 2d1abc9fff2..29d15cd7c16 100644 --- a/src/vendor/cigraph/src/core/cutheap.c +++ b/src/vendor/cigraph/src/core/cutheap.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -31,10 +31,10 @@ #define INDEXINC 1 static void igraph_i_cutheap_switch(igraph_i_cutheap_t *ch, - igraph_integer_t hidx1, igraph_integer_t hidx2) { + igraph_int_t hidx1, igraph_int_t hidx2) { if (hidx1 != hidx2) { - igraph_integer_t idx1 = VECTOR(ch->index)[hidx1]; - igraph_integer_t idx2 = VECTOR(ch->index)[hidx2]; + igraph_int_t idx1 = VECTOR(ch->index)[hidx1]; + igraph_int_t idx2 = VECTOR(ch->index)[hidx2]; igraph_real_t tmp = VECTOR(ch->heap)[hidx1]; VECTOR(ch->heap)[hidx1] = VECTOR(ch->heap)[hidx2]; @@ -48,8 +48,8 @@ static void igraph_i_cutheap_switch(igraph_i_cutheap_t *ch, } } -static void igraph_i_cutheap_sink(igraph_i_cutheap_t *ch, igraph_integer_t hidx) { - igraph_integer_t size = igraph_vector_size(&ch->heap); +static void igraph_i_cutheap_sink(igraph_i_cutheap_t *ch, igraph_int_t hidx) { + igraph_int_t size = igraph_vector_size(&ch->heap); if (LEFTCHILD(hidx) >= size) { /* leaf node */ } else if (RIGHTCHILD(hidx) == size || @@ -69,7 +69,7 @@ static void igraph_i_cutheap_sink(igraph_i_cutheap_t *ch, igraph_integer_t hidx) } } -static void igraph_i_cutheap_shift_up(igraph_i_cutheap_t *ch, igraph_integer_t hidx) { +static void igraph_i_cutheap_shift_up(igraph_i_cutheap_t *ch, igraph_int_t hidx) { if (hidx == 0 || VECTOR(ch->heap)[hidx] < VECTOR(ch->heap)[PARENT(hidx)]) { /* at the top */ } else { @@ -78,7 +78,7 @@ static void igraph_i_cutheap_shift_up(igraph_i_cutheap_t *ch, igraph_integer_t h } } -igraph_error_t igraph_i_cutheap_init(igraph_i_cutheap_t *ch, igraph_integer_t nodes) { +igraph_error_t igraph_i_cutheap_init(igraph_i_cutheap_t *ch, igraph_int_t nodes) { ch->dnodes = nodes; IGRAPH_VECTOR_INIT_FINALLY(&ch->heap, nodes); /* all zero */ IGRAPH_CHECK(igraph_vector_int_init_range(&ch->index, 0, nodes)); @@ -100,13 +100,13 @@ igraph_bool_t igraph_i_cutheap_empty(igraph_i_cutheap_t *ch) { /* Number of active vertices */ -igraph_integer_t igraph_i_cutheap_active_size(igraph_i_cutheap_t *ch) { +igraph_int_t igraph_i_cutheap_active_size(igraph_i_cutheap_t *ch) { return igraph_vector_size(&ch->heap); } /* Number of all (defined) vertices */ -igraph_integer_t igraph_i_cutheap_size(igraph_i_cutheap_t *ch) { +igraph_int_t igraph_i_cutheap_size(igraph_i_cutheap_t *ch) { return ch->dnodes; } @@ -114,9 +114,9 @@ igraph_real_t igraph_i_cutheap_maxvalue(igraph_i_cutheap_t *ch) { return VECTOR(ch->heap)[0]; } -igraph_integer_t igraph_i_cutheap_popmax(igraph_i_cutheap_t *ch) { - igraph_integer_t size = igraph_vector_size(&ch->heap); - igraph_integer_t maxindex = VECTOR(ch->index)[0]; +igraph_int_t igraph_i_cutheap_popmax(igraph_i_cutheap_t *ch) { + igraph_int_t size = igraph_vector_size(&ch->heap); + igraph_int_t maxindex = VECTOR(ch->index)[0]; /* put the last element to the top */ igraph_i_cutheap_switch(ch, 0, size - 1); /* remove the last element */ @@ -131,10 +131,10 @@ igraph_integer_t igraph_i_cutheap_popmax(igraph_i_cutheap_t *ch) { /* Update the value of an active vertex, if not active it will be ignored */ void igraph_i_cutheap_update( - igraph_i_cutheap_t *ch, igraph_integer_t index, igraph_real_t add) { + igraph_i_cutheap_t *ch, igraph_int_t index, igraph_real_t add) { igraph_real_t hidx = VECTOR(ch->hptr)[index]; if (hidx != INACTIVE && hidx != UNDEFINED) { - igraph_integer_t hidx2 = (hidx - INDEXINC); + igraph_int_t hidx2 = (hidx - INDEXINC); /* printf("updating vertex %li, heap index %li\n", index, hidx2); */ VECTOR(ch->heap)[hidx2] += add; igraph_i_cutheap_sink(ch, hidx2); @@ -144,8 +144,8 @@ void igraph_i_cutheap_update( /* Reset the value of all vertices to zero and make them active */ -igraph_error_t igraph_i_cutheap_reset_undefine(igraph_i_cutheap_t *ch, igraph_integer_t vertex) { - igraph_integer_t i, j, n = igraph_vector_size(&ch->hptr); +igraph_error_t igraph_i_cutheap_reset_undefine(igraph_i_cutheap_t *ch, igraph_int_t vertex) { + igraph_int_t i, j, n = igraph_vector_size(&ch->hptr); /* undefine */ VECTOR(ch->hptr)[vertex] = UNDEFINED; ch->dnodes -= 1; diff --git a/src/vendor/cigraph/src/core/cutheap.h b/src/vendor/cigraph/src/core/cutheap.h index 078813dea21..30901d3e7fc 100644 --- a/src/vendor/cigraph/src/core/cutheap.h +++ b/src/vendor/cigraph/src/core/cutheap.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -34,18 +34,18 @@ typedef struct igraph_i_cutheap_t { igraph_vector_t heap; igraph_vector_int_t index; igraph_vector_t hptr; - igraph_integer_t dnodes; + igraph_int_t dnodes; } igraph_i_cutheap_t; -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_cutheap_init(igraph_i_cutheap_t *ch, igraph_integer_t nodes); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_cutheap_init(igraph_i_cutheap_t *ch, igraph_int_t nodes); IGRAPH_PRIVATE_EXPORT void igraph_i_cutheap_destroy(igraph_i_cutheap_t *ch); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_i_cutheap_empty(igraph_i_cutheap_t *ch); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_i_cutheap_active_size(igraph_i_cutheap_t *ch); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_i_cutheap_size(igraph_i_cutheap_t *ch); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_i_cutheap_active_size(igraph_i_cutheap_t *ch); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_i_cutheap_size(igraph_i_cutheap_t *ch); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_i_cutheap_maxvalue(igraph_i_cutheap_t *ch); -IGRAPH_PRIVATE_EXPORT igraph_integer_t igraph_i_cutheap_popmax(igraph_i_cutheap_t *ch); -IGRAPH_PRIVATE_EXPORT void igraph_i_cutheap_update(igraph_i_cutheap_t *ch, igraph_integer_t index, igraph_real_t add); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_cutheap_reset_undefine(igraph_i_cutheap_t *ch, igraph_integer_t vertex); +IGRAPH_PRIVATE_EXPORT igraph_int_t igraph_i_cutheap_popmax(igraph_i_cutheap_t *ch); +IGRAPH_PRIVATE_EXPORT void igraph_i_cutheap_update(igraph_i_cutheap_t *ch, igraph_int_t index, igraph_real_t add); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_cutheap_reset_undefine(igraph_i_cutheap_t *ch, igraph_int_t vertex); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/core/dqueue.c b/src/vendor/cigraph/src/core/dqueue.c index f226ed09cdf..142f2bced0a 100644 --- a/src/vendor/cigraph/src/core/dqueue.c +++ b/src/vendor/cigraph/src/core/dqueue.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/core/dqueue.pmt b/src/vendor/cigraph/src/core/dqueue.pmt index d9bc11698d5..e7803fc94ac 100644 --- a/src/vendor/cigraph/src/core/dqueue.pmt +++ b/src/vendor/cigraph/src/core/dqueue.pmt @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -72,7 +72,7 @@ * Time complexity: O(\p capacity). */ -igraph_error_t FUNCTION(igraph_dqueue, init)(TYPE(igraph_dqueue)* q, igraph_integer_t capacity) { +igraph_error_t FUNCTION(igraph_dqueue, init)(TYPE(igraph_dqueue)* q, igraph_int_t capacity) { IGRAPH_ASSERT(q != NULL); IGRAPH_ASSERT(capacity >= 0); @@ -168,7 +168,7 @@ igraph_bool_t FUNCTION(igraph_dqueue, full)(TYPE(igraph_dqueue)* q) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_dqueue, size)(const TYPE(igraph_dqueue)* q) { +igraph_int_t FUNCTION(igraph_dqueue, size)(const TYPE(igraph_dqueue)* q) { IGRAPH_ASSERT(q != NULL); IGRAPH_ASSERT(q->stor_begin != NULL); if (q->end == NULL) { @@ -321,8 +321,8 @@ igraph_error_t FUNCTION(igraph_dqueue, push)(TYPE(igraph_dqueue)* q, BASE elem) /* full, allocate more storage */ BASE *bigger = NULL, *old = q->stor_begin; - igraph_integer_t old_size = q->stor_end - q->stor_begin; - igraph_integer_t new_capacity = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = q->stor_end - q->stor_begin; + igraph_int_t new_capacity = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot push to dqueue, already at maximum size.", IGRAPH_EOVERFLOW); @@ -413,7 +413,7 @@ igraph_error_t FUNCTION(igraph_dqueue, fprint)(const TYPE(igraph_dqueue)* q, FIL * Time complexity: O(1). */ -BASE FUNCTION(igraph_dqueue, get)(const TYPE(igraph_dqueue) *q, igraph_integer_t idx) { +BASE FUNCTION(igraph_dqueue, get)(const TYPE(igraph_dqueue) *q, igraph_int_t idx) { IGRAPH_ASSERT(idx >= 0); IGRAPH_ASSERT(idx < FUNCTION(igraph_dqueue, size)(q)); if ((q->begin + idx < q->end) || diff --git a/src/vendor/cigraph/src/core/error.c b/src/vendor/cigraph/src/core/error.c index e0202cd92f9..27180adb5cb 100644 --- a/src/vendor/cigraph/src/core/error.c +++ b/src/vendor/cigraph/src/core/error.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -127,7 +127,7 @@ static const char *igraph_i_error_strings[] = { /* 36 */ NULL, // "Unknown ARPACK error", /* ARPACK error codes end here */ - /* 37 */ "Negative loop detected while calculating shortest paths", + /* 37 */ "Negative cycle detected while calculating shortest paths", /* 38 */ "Internal error, likely a bug in igraph", /* More ARPACK error codes moved to igraph_arpack_error_t in arpack.c from version 1.0 */ diff --git a/src/vendor/cigraph/src/core/estack.c b/src/vendor/cigraph/src/core/estack.c index 7be14c90113..918b47a1f87 100644 --- a/src/vendor/cigraph/src/core/estack.c +++ b/src/vendor/cigraph/src/core/estack.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -22,8 +22,8 @@ #include "core/estack.h" -igraph_error_t igraph_estack_init(igraph_estack_t *s, igraph_integer_t setsize, - igraph_integer_t stacksize) { +igraph_error_t igraph_estack_init(igraph_estack_t *s, igraph_int_t setsize, + igraph_int_t stacksize) { IGRAPH_CHECK(igraph_bitset_init(&s->isin, setsize)); IGRAPH_FINALLY(igraph_bitset_destroy, &s->isin); IGRAPH_CHECK(igraph_stack_int_init(&s->stack, stacksize)); @@ -36,7 +36,7 @@ void igraph_estack_destroy(igraph_estack_t *s) { igraph_bitset_destroy(&s->isin); } -igraph_error_t igraph_estack_push(igraph_estack_t *s, igraph_integer_t elem) { +igraph_error_t igraph_estack_push(igraph_estack_t *s, igraph_int_t elem) { if ( !IGRAPH_BIT_TEST(s->isin, elem)) { IGRAPH_CHECK(igraph_stack_int_push(&s->stack, elem)); IGRAPH_BIT_SET(s->isin, elem); @@ -44,18 +44,18 @@ igraph_error_t igraph_estack_push(igraph_estack_t *s, igraph_integer_t elem) { return IGRAPH_SUCCESS; } -igraph_integer_t igraph_estack_pop(igraph_estack_t *s) { - igraph_integer_t elem = igraph_stack_int_pop(&s->stack); +igraph_int_t igraph_estack_pop(igraph_estack_t *s) { + igraph_int_t elem = igraph_stack_int_pop(&s->stack); IGRAPH_BIT_CLEAR(s->isin, elem); return elem; } igraph_bool_t igraph_estack_iselement(const igraph_estack_t *s, - igraph_integer_t elem) { + igraph_int_t elem) { return IGRAPH_BIT_TEST(s->isin, elem); } -igraph_integer_t igraph_estack_size(const igraph_estack_t *s) { +igraph_int_t igraph_estack_size(const igraph_estack_t *s) { return igraph_stack_int_size(&s->stack); } diff --git a/src/vendor/cigraph/src/core/estack.h b/src/vendor/cigraph/src/core/estack.h index 6dbe7282d13..8ffd1830940 100644 --- a/src/vendor/cigraph/src/core/estack.h +++ b/src/vendor/cigraph/src/core/estack.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -35,14 +35,14 @@ typedef struct igraph_estack_t { } igraph_estack_t; IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_estack_init( - igraph_estack_t *s, igraph_integer_t setsize, igraph_integer_t stacksize); + igraph_estack_t *s, igraph_int_t setsize, igraph_int_t stacksize); IGRAPH_PRIVATE_EXPORT void igraph_estack_destroy(igraph_estack_t *s); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_estack_push(igraph_estack_t *s, igraph_integer_t elem); -IGRAPH_PRIVATE_EXPORT igraph_integer_t igraph_estack_pop(igraph_estack_t *s); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_estack_push(igraph_estack_t *s, igraph_int_t elem); +IGRAPH_PRIVATE_EXPORT igraph_int_t igraph_estack_pop(igraph_estack_t *s); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_estack_iselement(const igraph_estack_t *s, - igraph_integer_t elem); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_estack_size(const igraph_estack_t *s); + igraph_int_t elem); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_estack_size(const igraph_estack_t *s); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_estack_print(const igraph_estack_t *s); diff --git a/src/vendor/cigraph/src/core/fixed_vectorlist.c b/src/vendor/cigraph/src/core/fixed_vectorlist.c index 89b239d8016..724c83ba7bf 100644 --- a/src/vendor/cigraph/src/core/fixed_vectorlist.c +++ b/src/vendor/cigraph/src/core/fixed_vectorlist.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -28,10 +28,10 @@ void igraph_fixed_vectorlist_destroy(igraph_fixed_vectorlist_t *l) { igraph_error_t igraph_fixed_vectorlist_convert( igraph_fixed_vectorlist_t *l, const igraph_vector_int_t *from, - igraph_integer_t size + igraph_int_t size ) { igraph_vector_int_t sizes; - igraph_integer_t i, no = igraph_vector_int_size(from), to; + igraph_int_t i, no = igraph_vector_int_size(from), to; IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(&l->vecs, size); IGRAPH_VECTOR_INT_INIT_FINALLY(&sizes, size); diff --git a/src/vendor/cigraph/src/core/fixed_vectorlist.h b/src/vendor/cigraph/src/core/fixed_vectorlist.h index 9e393e36765..2571a2d007f 100644 --- a/src/vendor/cigraph/src/core/fixed_vectorlist.h +++ b/src/vendor/cigraph/src/core/fixed_vectorlist.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -36,13 +36,13 @@ IGRAPH_BEGIN_C_DECLS typedef struct igraph_fixed_vectorlist_t { igraph_vector_int_list_t vecs; - igraph_integer_t length; + igraph_int_t length; } igraph_fixed_vectorlist_t; void igraph_fixed_vectorlist_destroy(igraph_fixed_vectorlist_t *l); igraph_error_t igraph_fixed_vectorlist_convert(igraph_fixed_vectorlist_t *l, const igraph_vector_int_t *from, - igraph_integer_t size); + igraph_int_t size); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/core/genheap.c b/src/vendor/cigraph/src/core/genheap.c index 1e4ec3f3fa9..c748c3ea2c6 100644 --- a/src/vendor/cigraph/src/core/genheap.c +++ b/src/vendor/cigraph/src/core/genheap.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -50,9 +50,9 @@ static void swapfunc(char * restrict a, char * restrict b, size_t es) { } static void igraph_i_gen2wheap_switch(igraph_gen2wheap_t *h, - igraph_integer_t e1, igraph_integer_t e2) { + igraph_int_t e1, igraph_int_t e2) { if (e1 != e2) { - igraph_integer_t tmp1, tmp2; + igraph_int_t tmp1, tmp2; swapfunc(ELEM(h, e1), ELEM(h, e2), h->item_size); @@ -68,7 +68,7 @@ static void igraph_i_gen2wheap_switch(igraph_gen2wheap_t *h, } static void igraph_i_gen2wheap_shift_up(igraph_gen2wheap_t *h, - igraph_integer_t elem) { + igraph_int_t elem) { if (elem == 0 || h->cmp(ELEM(h, elem), ELEM(h, PARENT(elem))) < 0) { /* at the top */ } else { @@ -78,8 +78,8 @@ static void igraph_i_gen2wheap_shift_up(igraph_gen2wheap_t *h, } static void igraph_i_gen2wheap_sink(igraph_gen2wheap_t *h, - igraph_integer_t head) { - igraph_integer_t size = igraph_gen2wheap_size(h); + igraph_int_t head) { + igraph_int_t size = igraph_gen2wheap_size(h); if (LEFTCHILD(head) >= size) { /* no subtrees */ } else if (RIGHTCHILD(head) == size || @@ -109,7 +109,7 @@ static void igraph_i_gen2wheap_sink(igraph_gen2wheap_t *h, igraph_error_t igraph_gen2wheap_init( igraph_gen2wheap_t *h, int (*cmp)(const void *, const void *), - size_t item_size, igraph_integer_t max_size + size_t item_size, igraph_int_t max_size ) { /* TODO: Currently, storage is allocated for the maximum number of elements * right from the start. This is sufficient for the only use case as of this @@ -142,7 +142,7 @@ void igraph_gen2wheap_destroy(igraph_gen2wheap_t *h) { /** * Returns the current number of elements in the two-way heap. */ -igraph_integer_t igraph_gen2wheap_size(const igraph_gen2wheap_t *h) { +igraph_int_t igraph_gen2wheap_size(const igraph_gen2wheap_t *h) { return igraph_vector_int_size(&h->index); } @@ -168,9 +168,9 @@ igraph_bool_t igraph_gen2wheap_empty(const igraph_gen2wheap_t *h) { * the same index. */ igraph_error_t igraph_gen2wheap_push_with_index(igraph_gen2wheap_t *h, - igraph_integer_t idx, const void *elem) { + igraph_int_t idx, const void *elem) { - igraph_integer_t size = igraph_vector_int_size(&h->index); + igraph_int_t size = igraph_vector_int_size(&h->index); if (size > IGRAPH_INTEGER_MAX - 2) { /* to allow size+2 below */ @@ -192,7 +192,7 @@ igraph_error_t igraph_gen2wheap_push_with_index(igraph_gen2wheap_t *h, * is also one larger than the maximum allowed index that can be passed to * \c igraph_gen2wheap_push_with_index . */ -igraph_integer_t igraph_gen2wheap_max_size(const igraph_gen2wheap_t *h) { +igraph_int_t igraph_gen2wheap_max_size(const igraph_gen2wheap_t *h) { return h->max_size; } @@ -207,7 +207,7 @@ const void *igraph_gen2wheap_max(const igraph_gen2wheap_t *h) { * Returns the index that was associated to the largest element in the heap * when it was pushed to the heap. */ -igraph_integer_t igraph_gen2wheap_max_index(const igraph_gen2wheap_t *h) { +igraph_int_t igraph_gen2wheap_max_index(const igraph_gen2wheap_t *h) { return VECTOR(h->index)[0]; } @@ -215,7 +215,7 @@ igraph_integer_t igraph_gen2wheap_max_index(const igraph_gen2wheap_t *h) { * Returns whether the heap contains an element with the given index, even if * it was deactivated earlier. */ -igraph_bool_t igraph_gen2wheap_has_elem(const igraph_gen2wheap_t *h, igraph_integer_t idx) { +igraph_bool_t igraph_gen2wheap_has_elem(const igraph_gen2wheap_t *h, igraph_int_t idx) { return VECTOR(h->index2)[idx] != 0; } @@ -223,15 +223,15 @@ igraph_bool_t igraph_gen2wheap_has_elem(const igraph_gen2wheap_t *h, igraph_inte * Returns whether the heap contains an element with the given index \em and it * has not been deactivated yet. */ -igraph_bool_t igraph_gen2wheap_has_active(const igraph_gen2wheap_t *h, igraph_integer_t idx) { +igraph_bool_t igraph_gen2wheap_has_active(const igraph_gen2wheap_t *h, igraph_int_t idx) { return VECTOR(h->index2)[idx] > 1; } /** * Returns a pointer to the item at the given index in the two-way heap. */ -const void *igraph_gen2wheap_get(const igraph_gen2wheap_t *h, igraph_integer_t idx) { - igraph_integer_t i = VECTOR(h->index2)[idx] - 2; +const void *igraph_gen2wheap_get(const igraph_gen2wheap_t *h, igraph_int_t idx) { + igraph_int_t i = VECTOR(h->index2)[idx] - 2; return ELEM(h, i); } @@ -242,7 +242,7 @@ const void *igraph_gen2wheap_get(const igraph_gen2wheap_t *h, igraph_integer_t i * that remain in the heap. */ void igraph_gen2wheap_delete_max(igraph_gen2wheap_t *h) { - igraph_integer_t tmpidx = VECTOR(h->index)[0]; + igraph_int_t tmpidx = VECTOR(h->index)[0]; igraph_i_gen2wheap_switch(h, 0, igraph_gen2wheap_size(h) - 1); igraph_vector_int_pop_back(&h->index); VECTOR(h->index2)[tmpidx] = 0; @@ -256,7 +256,7 @@ void igraph_gen2wheap_delete_max(igraph_gen2wheap_t *h) { * that remain in the heap. */ void igraph_gen2wheap_deactivate_max(igraph_gen2wheap_t *h) { - igraph_integer_t tmpidx = VECTOR(h->index)[0]; + igraph_int_t tmpidx = VECTOR(h->index)[0]; igraph_i_gen2wheap_switch(h, 0, igraph_gen2wheap_size(h) - 1); igraph_vector_int_pop_back(&h->index); VECTOR(h->index2)[tmpidx] = 1; @@ -266,9 +266,9 @@ void igraph_gen2wheap_deactivate_max(igraph_gen2wheap_t *h) { /** * Modifies the value associated to the given index in the two-way heap. */ -void igraph_gen2wheap_modify(igraph_gen2wheap_t *h, igraph_integer_t idx, const void *elem) { +void igraph_gen2wheap_modify(igraph_gen2wheap_t *h, igraph_int_t idx, const void *elem) { - igraph_integer_t pos = VECTOR(h->index2)[idx] - 2; + igraph_int_t pos = VECTOR(h->index2)[idx] - 2; memcpy(ELEM(h, pos), elem, h->item_size); igraph_i_gen2wheap_sink(h, pos); @@ -279,8 +279,8 @@ void igraph_gen2wheap_modify(igraph_gen2wheap_t *h, igraph_integer_t idx, const * Checks that the heap is in a consistent state */ igraph_error_t igraph_gen2wheap_check(const igraph_gen2wheap_t *h) { - igraph_integer_t size = igraph_gen2wheap_size(h); - igraph_integer_t i; + igraph_int_t size = igraph_gen2wheap_size(h); + igraph_int_t i; igraph_bool_t error = false; /* Check the heap property */ diff --git a/src/vendor/cigraph/src/core/genheap.h b/src/vendor/cigraph/src/core/genheap.h index e711b430fd8..c8b18ddfd56 100644 --- a/src/vendor/cigraph/src/core/genheap.h +++ b/src/vendor/cigraph/src/core/genheap.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ typedef struct igraph_gen2wheap_t { /** Maximum number of items in the heap */ - igraph_integer_t max_size; + igraph_int_t max_size; /** The size of an individual item */ size_t item_size; @@ -53,21 +53,21 @@ typedef struct igraph_gen2wheap_t { IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_gen2wheap_init( igraph_gen2wheap_t *h, int (*cmp)(const void *, const void *), - size_t item_size, igraph_integer_t max_size + size_t item_size, igraph_int_t max_size ); IGRAPH_PRIVATE_EXPORT void igraph_gen2wheap_destroy(igraph_gen2wheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gen2wheap_size(const igraph_gen2wheap_t *h); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gen2wheap_size(const igraph_gen2wheap_t *h); IGRAPH_PRIVATE_EXPORT void igraph_gen2wheap_clear(igraph_gen2wheap_t *h); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_gen2wheap_empty(const igraph_gen2wheap_t *h); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_gen2wheap_push_with_index(igraph_gen2wheap_t *h, - igraph_integer_t idx, const void *elem); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gen2wheap_max_size(const igraph_gen2wheap_t *h); + igraph_int_t idx, const void *elem); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gen2wheap_max_size(const igraph_gen2wheap_t *h); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE const void *igraph_gen2wheap_max(const igraph_gen2wheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gen2wheap_max_index(const igraph_gen2wheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_gen2wheap_has_elem(const igraph_gen2wheap_t *h, igraph_integer_t idx); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_gen2wheap_has_active(const igraph_gen2wheap_t *h, igraph_integer_t idx); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE const void *igraph_gen2wheap_get(const igraph_gen2wheap_t *h, igraph_integer_t idx); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gen2wheap_max_index(const igraph_gen2wheap_t *h); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_gen2wheap_has_elem(const igraph_gen2wheap_t *h, igraph_int_t idx); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_gen2wheap_has_active(const igraph_gen2wheap_t *h, igraph_int_t idx); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE const void *igraph_gen2wheap_get(const igraph_gen2wheap_t *h, igraph_int_t idx); IGRAPH_PRIVATE_EXPORT void igraph_gen2wheap_delete_max(igraph_gen2wheap_t *h); IGRAPH_PRIVATE_EXPORT void igraph_gen2wheap_deactivate_max(igraph_gen2wheap_t *h); -IGRAPH_PRIVATE_EXPORT void igraph_gen2wheap_modify(igraph_gen2wheap_t *h, igraph_integer_t idx, const void *elem); +IGRAPH_PRIVATE_EXPORT void igraph_gen2wheap_modify(igraph_gen2wheap_t *h, igraph_int_t idx, const void *elem); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_gen2wheap_check(const igraph_gen2wheap_t *h); diff --git a/src/vendor/cigraph/src/core/grid.c b/src/vendor/cigraph/src/core/grid.c index 1c620349b8d..d0d9102ad47 100644 --- a/src/vendor/cigraph/src/core/grid.c +++ b/src/vendor/cigraph/src/core/grid.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -26,7 +26,7 @@ static void igraph_i_2dgrid_which( igraph_2dgrid_t *grid, igraph_real_t xc, igraph_real_t yc, - igraph_integer_t *x, igraph_integer_t *y + igraph_int_t *x, igraph_int_t *y ) { if (xc <= grid->minx) { *x = 0; @@ -48,7 +48,7 @@ static void igraph_i_2dgrid_which( igraph_error_t igraph_2dgrid_init(igraph_2dgrid_t *grid, igraph_matrix_t *coords, igraph_real_t minx, igraph_real_t maxx, igraph_real_t deltax, igraph_real_t miny, igraph_real_t maxy, igraph_real_t deltay) { - igraph_integer_t no_of_points; + igraph_int_t no_of_points; IGRAPH_ASSERT(minx <= maxx); IGRAPH_ASSERT(miny <= maxy); @@ -91,10 +91,10 @@ void igraph_2dgrid_destroy(igraph_2dgrid_t *grid) { igraph_vector_int_destroy(&grid->prev); } -void igraph_2dgrid_add(igraph_2dgrid_t *grid, igraph_integer_t elem, +void igraph_2dgrid_add(igraph_2dgrid_t *grid, igraph_int_t elem, igraph_real_t xc, igraph_real_t yc) { - igraph_integer_t x, y; - igraph_integer_t first; + igraph_int_t x, y; + igraph_int_t first; MATRIX(*grid->coords, elem, 0) = xc; MATRIX(*grid->coords, elem, 1) = yc; @@ -114,9 +114,9 @@ void igraph_2dgrid_add(igraph_2dgrid_t *grid, igraph_integer_t elem, grid->vertices += 1; } -void igraph_2dgrid_add2(igraph_2dgrid_t *grid, igraph_integer_t elem) { - igraph_integer_t x, y; - igraph_integer_t first; +void igraph_2dgrid_add2(igraph_2dgrid_t *grid, igraph_int_t elem) { + igraph_int_t x, y; + igraph_int_t first; igraph_real_t xc, yc; xc = MATRIX(*grid->coords, elem, 0); @@ -137,13 +137,13 @@ void igraph_2dgrid_add2(igraph_2dgrid_t *grid, igraph_integer_t elem) { grid->vertices += 1; } -void igraph_2dgrid_move(igraph_2dgrid_t *grid, igraph_integer_t elem, +void igraph_2dgrid_move(igraph_2dgrid_t *grid, igraph_int_t elem, igraph_real_t xc, igraph_real_t yc) { - igraph_integer_t oldx, oldy; - igraph_integer_t newx, newy; + igraph_int_t oldx, oldy; + igraph_int_t newx, newy; igraph_real_t oldxc = MATRIX(*grid->coords, elem, 0); igraph_real_t oldyc = MATRIX(*grid->coords, elem, 1); - igraph_integer_t first; + igraph_int_t first; xc = oldxc + xc; yc = oldyc + yc; @@ -186,12 +186,12 @@ void igraph_2dgrid_getcenter(const igraph_2dgrid_t *grid, *massy = (grid->massy) / (grid->vertices); } -igraph_bool_t igraph_2dgrid_in(const igraph_2dgrid_t *grid, igraph_integer_t elem) { +igraph_bool_t igraph_2dgrid_in(const igraph_2dgrid_t *grid, igraph_int_t elem) { return VECTOR(grid->next)[elem] != -1; } igraph_real_t igraph_2dgrid_sq_dist(const igraph_2dgrid_t *grid, - igraph_integer_t e1, igraph_integer_t e2) { + igraph_int_t e1, igraph_int_t e2) { igraph_real_t x = MATRIX(*grid->coords, e1, 0) - MATRIX(*grid->coords, e2, 0); igraph_real_t y = MATRIX(*grid->coords, e1, 1) - MATRIX(*grid->coords, e2, 1); @@ -210,9 +210,9 @@ void igraph_2dgrid_reset(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it) { } } -igraph_integer_t igraph_2dgrid_next(igraph_2dgrid_t *grid, +igraph_int_t igraph_2dgrid_next(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it) { - igraph_integer_t ret = it->vid; + igraph_int_t ret = it->vid; if (ret == 0) { return 0; @@ -259,9 +259,9 @@ igraph_integer_t igraph_2dgrid_next(igraph_2dgrid_t *grid, return ret; } -igraph_integer_t igraph_2dgrid_next_nei(igraph_2dgrid_t *grid, +igraph_int_t igraph_2dgrid_next_nei(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it) { - igraph_integer_t ret = it->nei; + igraph_int_t ret = it->nei; if (it->nei != 0) { it->nei = VECTOR(grid->next) [ ret - 1 ]; diff --git a/src/vendor/cigraph/src/core/grid.h b/src/vendor/cigraph/src/core/grid.h index 0446940a4be..65a41ff13d1 100644 --- a/src/vendor/cigraph/src/core/grid.h +++ b/src/vendor/cigraph/src/core/grid.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -37,39 +37,39 @@ typedef struct igraph_2dgrid_t { igraph_matrix_t *coords; /* The current coordinates in the grid */ igraph_real_t minx, maxx, deltax; /* Minimum and maximum X coordinates and X spacing */ igraph_real_t miny, maxy, deltay; /* Minimum and maximum Y coordinates and Y spacing */ - igraph_integer_t stepsx, stepsy; /* Number of cells in the X and Y directions */ + igraph_int_t stepsx, stepsy; /* Number of cells in the X and Y directions */ igraph_matrix_int_t startidx; /* startidx[i, j] is the index of an arbitrary point in that grid cell, plus one; zero means "empty cell" */ igraph_vector_int_t next; /* next[i] is the index of the point following point i in the same cell, plus one; zero means "last point" */ igraph_vector_int_t prev; /* prev[i] is the index of the point preceding point i in the same cell, plus one; zero means "first point" */ igraph_real_t massx, massy; /* The sum of the coordinates */ - igraph_integer_t vertices; /* Number of active vertices */ + igraph_int_t vertices; /* Number of active vertices */ } igraph_2dgrid_t; igraph_error_t igraph_2dgrid_init(igraph_2dgrid_t *grid, igraph_matrix_t *coords, igraph_real_t minx, igraph_real_t maxx, igraph_real_t deltax, igraph_real_t miny, igraph_real_t maxy, igraph_real_t deltay); void igraph_2dgrid_destroy(igraph_2dgrid_t *grid); -void igraph_2dgrid_add(igraph_2dgrid_t *grid, igraph_integer_t elem, +void igraph_2dgrid_add(igraph_2dgrid_t *grid, igraph_int_t elem, igraph_real_t xc, igraph_real_t yc); -void igraph_2dgrid_add2(igraph_2dgrid_t *grid, igraph_integer_t elem); -void igraph_2dgrid_move(igraph_2dgrid_t *grid, igraph_integer_t elem, +void igraph_2dgrid_add2(igraph_2dgrid_t *grid, igraph_int_t elem); +void igraph_2dgrid_move(igraph_2dgrid_t *grid, igraph_int_t elem, igraph_real_t xc, igraph_real_t yc); void igraph_2dgrid_getcenter(const igraph_2dgrid_t *grid, igraph_real_t *massx, igraph_real_t *massy); -IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_2dgrid_in(const igraph_2dgrid_t *grid, igraph_integer_t elem); +IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_2dgrid_in(const igraph_2dgrid_t *grid, igraph_int_t elem); IGRAPH_FUNCATTR_PURE igraph_real_t igraph_2dgrid_sq_dist(const igraph_2dgrid_t *grid, - igraph_integer_t e1, igraph_integer_t e2); + igraph_int_t e1, igraph_int_t e2); typedef struct igraph_2dgrid_iterator_t { - igraph_integer_t vid, x, y; - igraph_integer_t nei; - igraph_integer_t nx[4], ny[4], ncells; + igraph_int_t vid, x, y; + igraph_int_t nei; + igraph_int_t nx[4], ny[4], ncells; } igraph_2dgrid_iterator_t; void igraph_2dgrid_reset(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it); -igraph_integer_t igraph_2dgrid_next(igraph_2dgrid_t *grid, +igraph_int_t igraph_2dgrid_next(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it); -igraph_integer_t igraph_2dgrid_next_nei(igraph_2dgrid_t *grid, +igraph_int_t igraph_2dgrid_next_nei(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/core/heap.c b/src/vendor/cigraph/src/core/heap.c index 641e0aee8a3..ac0523dc8c0 100644 --- a/src/vendor/cigraph/src/core/heap.c +++ b/src/vendor/cigraph/src/core/heap.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/core/heap.pmt b/src/vendor/cigraph/src/core/heap.pmt index 7883a9f261d..6b406c59556 100644 --- a/src/vendor/cigraph/src/core/heap.pmt +++ b/src/vendor/cigraph/src/core/heap.pmt @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -31,10 +31,10 @@ #define RIGHTCHILD(x) (((x)+1)*2) /* Declare internal functions */ -static void FUNCTION(igraph_heap, i_build)(BASE* arr, igraph_integer_t size, igraph_integer_t head); -static void FUNCTION(igraph_heap, i_shift_up)(BASE* arr, igraph_integer_t size, igraph_integer_t elem); -static void FUNCTION(igraph_heap, i_sink)(BASE* arr, igraph_integer_t size, igraph_integer_t head); -static void FUNCTION(igraph_heap, i_switch)(BASE* arr, igraph_integer_t e1, igraph_integer_t e2); +static void FUNCTION(igraph_heap, i_build)(BASE* arr, igraph_int_t size, igraph_int_t head); +static void FUNCTION(igraph_heap, i_shift_up)(BASE* arr, igraph_int_t size, igraph_int_t elem); +static void FUNCTION(igraph_heap, i_sink)(BASE* arr, igraph_int_t size, igraph_int_t head); +static void FUNCTION(igraph_heap, i_switch)(BASE* arr, igraph_int_t e1, igraph_int_t e2); /** * \ingroup heap @@ -52,7 +52,7 @@ static void FUNCTION(igraph_heap, i_switch)(BASE* arr, igraph_integer_t e1, igra * linear operation. */ -igraph_error_t FUNCTION(igraph_heap, init)(TYPE(igraph_heap)* h, igraph_integer_t capacity) { +igraph_error_t FUNCTION(igraph_heap, init)(TYPE(igraph_heap)* h, igraph_int_t capacity) { IGRAPH_ASSERT(capacity >= 0); if (capacity == 0 ) { capacity = 1; @@ -81,7 +81,7 @@ igraph_error_t FUNCTION(igraph_heap, init)(TYPE(igraph_heap)* h, igraph_integer_ * Time complexity: O(n), the number of elements in the heap. */ -igraph_error_t FUNCTION(igraph_heap, init_array)(TYPE(igraph_heap) *h, const BASE *data, igraph_integer_t len) { +igraph_error_t FUNCTION(igraph_heap, init_array)(TYPE(igraph_heap) *h, const BASE *data, igraph_int_t len) { h->stor_begin = IGRAPH_CALLOC(len, BASE); IGRAPH_CHECK_OOM(h->stor_begin, "Cannot initialize heap from array."); h->stor_end = h->stor_begin + len; @@ -169,8 +169,8 @@ igraph_error_t FUNCTION(igraph_heap, push)(TYPE(igraph_heap)* h, BASE elem) { /* full, allocate more storage */ if (h->stor_end == h->end) { - igraph_integer_t old_size = FUNCTION(igraph_heap, size)(h); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = FUNCTION(igraph_heap, size)(h); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot push to heap, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -254,7 +254,7 @@ BASE FUNCTION(igraph_heap, delete_top)(TYPE(igraph_heap)* h) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_heap, size)(const TYPE(igraph_heap)* h) { +igraph_int_t FUNCTION(igraph_heap, size)(const TYPE(igraph_heap)* h) { IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); return h->end - h->stor_begin; @@ -277,8 +277,8 @@ igraph_integer_t FUNCTION(igraph_heap, size)(const TYPE(igraph_heap)* h) { * number of elements. O(1) otherwise. */ -igraph_error_t FUNCTION(igraph_heap, reserve)(TYPE(igraph_heap)* h, igraph_integer_t capacity) { - igraph_integer_t actual_size = FUNCTION(igraph_heap, size)(h); +igraph_error_t FUNCTION(igraph_heap, reserve)(TYPE(igraph_heap)* h, igraph_int_t capacity) { + igraph_int_t actual_size = FUNCTION(igraph_heap, size)(h); BASE *tmp; IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); @@ -304,7 +304,7 @@ igraph_error_t FUNCTION(igraph_heap, reserve)(TYPE(igraph_heap)* h, igraph_integ */ void FUNCTION(igraph_heap, i_build)(BASE* arr, - igraph_integer_t size, igraph_integer_t head) { + igraph_int_t size, igraph_int_t head) { if (RIGHTCHILD(head) < size) { /* both subtrees */ @@ -326,7 +326,7 @@ void FUNCTION(igraph_heap, i_build)(BASE* arr, * called directly. */ -void FUNCTION(igraph_heap, i_shift_up)(BASE* arr, igraph_integer_t size, igraph_integer_t elem) { +void FUNCTION(igraph_heap, i_shift_up)(BASE* arr, igraph_int_t size, igraph_int_t elem) { if (elem == 0 || arr[elem] HEAPLESS arr[PARENT(elem)]) { /* at the top */ @@ -342,7 +342,7 @@ void FUNCTION(igraph_heap, i_shift_up)(BASE* arr, igraph_integer_t size, igraph_ * called directly. */ -void FUNCTION(igraph_heap, i_sink)(BASE* arr, igraph_integer_t size, igraph_integer_t head) { +void FUNCTION(igraph_heap, i_sink)(BASE* arr, igraph_int_t size, igraph_int_t head) { if (LEFTCHILD(head) >= size) { /* no subtrees */ @@ -368,7 +368,7 @@ void FUNCTION(igraph_heap, i_sink)(BASE* arr, igraph_integer_t size, igraph_inte * called directly. */ -void FUNCTION(igraph_heap, i_switch)(BASE* arr, igraph_integer_t e1, igraph_integer_t e2) { +void FUNCTION(igraph_heap, i_switch)(BASE* arr, igraph_int_t e1, igraph_int_t e2) { if (e1 != e2) { BASE tmp = arr[e1]; arr[e1] = arr[e2]; diff --git a/src/vendor/cigraph/src/core/indheap.c b/src/vendor/cigraph/src/core/indheap.c index 49de46a7a6c..662041a4d14 100644 --- a/src/vendor/cigraph/src/core/indheap.c +++ b/src/vendor/cigraph/src/core/indheap.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -36,10 +36,10 @@ #define LEFTCHILD(x) (((x)+1)*2-1) #define RIGHTCHILD(x) (((x)+1)*2) -static void igraph_indheap_i_build(igraph_indheap_t* h, igraph_integer_t head); -static void igraph_indheap_i_shift_up(igraph_indheap_t* h, igraph_integer_t elem); -static void igraph_indheap_i_sink(igraph_indheap_t* h, igraph_integer_t head); -static void igraph_indheap_i_switch(igraph_indheap_t* h, igraph_integer_t e1, igraph_integer_t e2); +static void igraph_indheap_i_build(igraph_indheap_t* h, igraph_int_t head); +static void igraph_indheap_i_shift_up(igraph_indheap_t* h, igraph_int_t elem); +static void igraph_indheap_i_sink(igraph_indheap_t* h, igraph_int_t head); +static void igraph_indheap_i_switch(igraph_indheap_t* h, igraph_int_t e1, igraph_int_t e2); /** * \ingroup indheap @@ -49,7 +49,7 @@ static void igraph_indheap_i_switch(igraph_indheap_t* h, igraph_integer_t e1, ig * - IGRAPH_ENOMEM: out of memory */ -igraph_error_t igraph_indheap_init(igraph_indheap_t* h, igraph_integer_t alloc_size) { +igraph_error_t igraph_indheap_init(igraph_indheap_t* h, igraph_int_t alloc_size) { IGRAPH_ASSERT(alloc_size >= 0); if (alloc_size == 0 ) { alloc_size = 1; @@ -59,7 +59,7 @@ igraph_error_t igraph_indheap_init(igraph_indheap_t* h, igraph_integer_t alloc_s h->index_begin = NULL; IGRAPH_ERROR("indheap init failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } - h->index_begin = IGRAPH_CALLOC(alloc_size, igraph_integer_t); + h->index_begin = IGRAPH_CALLOC(alloc_size, igraph_int_t); if (! h->index_begin) { IGRAPH_FREE(h->stor_begin); h->stor_begin = NULL; @@ -84,9 +84,9 @@ void igraph_indheap_clear(igraph_indheap_t *h) { * - IGRAPH_ENOMEM: out of memory */ -igraph_error_t igraph_indheap_init_array(igraph_indheap_t *h, const igraph_real_t *data, igraph_integer_t len) { - igraph_integer_t i; - igraph_integer_t alloc_size; +igraph_error_t igraph_indheap_init_array(igraph_indheap_t *h, const igraph_real_t *data, igraph_int_t len) { + igraph_int_t i; + igraph_int_t alloc_size; IGRAPH_ASSERT(len >= 0); alloc_size = (len <= 0) ? 1 : len; @@ -96,7 +96,7 @@ igraph_error_t igraph_indheap_init_array(igraph_indheap_t *h, const igraph_real_ h->index_begin = 0; IGRAPH_ERROR("indheap init from array failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } - h->index_begin = IGRAPH_CALLOC(alloc_size, igraph_integer_t); + h->index_begin = IGRAPH_CALLOC(alloc_size, igraph_int_t); if (! h->index_begin) { IGRAPH_FREE(h->stor_begin); h->stor_begin = 0; @@ -152,8 +152,8 @@ igraph_error_t igraph_indheap_push(igraph_indheap_t* h, igraph_real_t elem) { /* full, allocate more storage */ if (h->stor_end == h->end) { - igraph_integer_t old_size = igraph_indheap_size(h); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = igraph_indheap_size(h); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot push to indheap, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -178,14 +178,14 @@ igraph_error_t igraph_indheap_push(igraph_indheap_t* h, igraph_real_t elem) { * \brief Adds an element to an indexed heap with a given index. */ -igraph_error_t igraph_indheap_push_with_index(igraph_indheap_t* h, igraph_integer_t idx, igraph_real_t elem) { +igraph_error_t igraph_indheap_push_with_index(igraph_indheap_t* h, igraph_int_t idx, igraph_real_t elem) { IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); /* full, allocate more storage */ if (h->stor_end == h->end) { - igraph_integer_t old_size = igraph_indheap_size(h); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = igraph_indheap_size(h); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot push to indheap, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -210,8 +210,8 @@ igraph_error_t igraph_indheap_push_with_index(igraph_indheap_t* h, igraph_intege * \brief Modifies an element in an indexed heap. */ -void igraph_indheap_modify(igraph_indheap_t* h, igraph_integer_t idx, igraph_real_t elem) { - igraph_integer_t i, n; +void igraph_indheap_modify(igraph_indheap_t* h, igraph_int_t idx, igraph_real_t elem) { + igraph_int_t i, n; IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); @@ -268,7 +268,7 @@ igraph_real_t igraph_indheap_delete_max(igraph_indheap_t* h) { * \brief Gives the number of elements in an indexed heap. */ -igraph_integer_t igraph_indheap_size(const igraph_indheap_t* h) { +igraph_int_t igraph_indheap_size(const igraph_indheap_t* h) { IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); return h->end - h->stor_begin; @@ -282,10 +282,10 @@ igraph_integer_t igraph_indheap_size(const igraph_indheap_t* h) { * - IGRAPH_ENOMEM: out of memory */ -igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_integer_t size) { - igraph_integer_t actual_size = igraph_indheap_size(h); +igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_int_t size) { + igraph_int_t actual_size = igraph_indheap_size(h); igraph_real_t *tmp1; - igraph_integer_t *tmp2; + igraph_int_t *tmp2; IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); @@ -298,13 +298,13 @@ igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_integer_t size IGRAPH_ERROR("indheap reserve failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } IGRAPH_FINALLY(igraph_free, tmp1); - tmp2 = IGRAPH_CALLOC(size, igraph_integer_t); + tmp2 = IGRAPH_CALLOC(size, igraph_int_t); if (tmp2 == 0) { IGRAPH_ERROR("indheap reserve failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } IGRAPH_FINALLY(igraph_free, tmp2); memcpy(tmp1, h->stor_begin, (size_t) actual_size * sizeof(igraph_real_t)); - memcpy(tmp2, h->index_begin, (size_t) actual_size * sizeof(igraph_integer_t)); + memcpy(tmp2, h->index_begin, (size_t) actual_size * sizeof(igraph_int_t)); IGRAPH_FREE(h->stor_begin); IGRAPH_FREE(h->index_begin); @@ -322,7 +322,7 @@ igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_integer_t size * \brief Returns the index of the largest element in an indexed heap. */ -igraph_integer_t igraph_indheap_max_index(const igraph_indheap_t *h) { +igraph_int_t igraph_indheap_max_index(const igraph_indheap_t *h) { IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); return h->index_begin[0]; @@ -334,9 +334,9 @@ igraph_integer_t igraph_indheap_max_index(const igraph_indheap_t *h) { * directly. */ -static void igraph_indheap_i_build(igraph_indheap_t* h, igraph_integer_t head) { +static void igraph_indheap_i_build(igraph_indheap_t* h, igraph_int_t head) { - igraph_integer_t size = igraph_indheap_size(h); + igraph_int_t size = igraph_indheap_size(h); if (RIGHTCHILD(head) < size) { /* both subtrees */ igraph_indheap_i_build(h, LEFTCHILD(head) ); @@ -357,7 +357,7 @@ static void igraph_indheap_i_build(igraph_indheap_t* h, igraph_integer_t head) { * directly. */ -static void igraph_indheap_i_shift_up(igraph_indheap_t *h, igraph_integer_t elem) { +static void igraph_indheap_i_shift_up(igraph_indheap_t *h, igraph_int_t elem) { if (elem == 0 || h->stor_begin[elem] < h->stor_begin[PARENT(elem)]) { /* at the top */ @@ -373,9 +373,9 @@ static void igraph_indheap_i_shift_up(igraph_indheap_t *h, igraph_integer_t elem * directly. */ -static void igraph_indheap_i_sink(igraph_indheap_t* h, igraph_integer_t head) { +static void igraph_indheap_i_sink(igraph_indheap_t* h, igraph_int_t head) { - igraph_integer_t size = igraph_indheap_size(h); + igraph_int_t size = igraph_indheap_size(h); if (LEFTCHILD(head) >= size) { /* no subtrees */ } else if (RIGHTCHILD(head) == size || @@ -400,7 +400,7 @@ static void igraph_indheap_i_sink(igraph_indheap_t* h, igraph_integer_t head) { * directly. */ -static void igraph_indheap_i_switch(igraph_indheap_t* h, igraph_integer_t e1, igraph_integer_t e2) { +static void igraph_indheap_i_switch(igraph_indheap_t* h, igraph_int_t e1, igraph_int_t e2) { if (e1 != e2) { igraph_real_t tmp = h->stor_begin[e1]; h->stor_begin[e1] = h->stor_begin[e2]; @@ -418,10 +418,10 @@ static void igraph_indheap_i_switch(igraph_indheap_t* h, igraph_integer_t e1, ig /* Doubly indexed heap */ /* -------------------------------------------------- */ -/* static void igraph_d_indheap_i_build(igraph_d_indheap_t* h, igraph_integer_t head); */ /* Unused function */ -static void igraph_d_indheap_i_shift_up(igraph_d_indheap_t* h, igraph_integer_t elem); -static void igraph_d_indheap_i_sink(igraph_d_indheap_t* h, igraph_integer_t head); -static void igraph_d_indheap_i_switch(igraph_d_indheap_t* h, igraph_integer_t e1, igraph_integer_t e2); +/* static void igraph_d_indheap_i_build(igraph_d_indheap_t* h, igraph_int_t head); */ /* Unused function */ +static void igraph_d_indheap_i_shift_up(igraph_d_indheap_t* h, igraph_int_t elem); +static void igraph_d_indheap_i_sink(igraph_d_indheap_t* h, igraph_int_t head); +static void igraph_d_indheap_i_switch(igraph_d_indheap_t* h, igraph_int_t e1, igraph_int_t e2); /** * \ingroup doubleindheap @@ -431,7 +431,7 @@ static void igraph_d_indheap_i_switch(igraph_d_indheap_t* h, igraph_integer_t e1 * - IGRAPH_ENOMEM: out of memory */ -igraph_error_t igraph_d_indheap_init(igraph_d_indheap_t* h, igraph_integer_t alloc_size) { +igraph_error_t igraph_d_indheap_init(igraph_d_indheap_t* h, igraph_int_t alloc_size) { IGRAPH_ASSERT(alloc_size >= 0); if (alloc_size == 0 ) { alloc_size = 1; @@ -444,14 +444,14 @@ 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->index_begin = IGRAPH_CALLOC(alloc_size, igraph_integer_t); + h->index_begin = IGRAPH_CALLOC(alloc_size, igraph_int_t); if (h->index_begin == NULL) { IGRAPH_FREE(h->stor_begin); h->stor_begin = NULL; h->index2_begin = NULL; IGRAPH_ERROR("d_indheap init failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } - h->index2_begin = IGRAPH_CALLOC(alloc_size, igraph_integer_t); + h->index2_begin = IGRAPH_CALLOC(alloc_size, igraph_int_t); if (h->index2_begin == NULL) { IGRAPH_FREE(h->stor_begin); IGRAPH_FREE(h->index_begin); @@ -498,14 +498,14 @@ igraph_bool_t igraph_d_indheap_empty(const igraph_d_indheap_t *h) { */ igraph_error_t igraph_d_indheap_push(igraph_d_indheap_t* h, igraph_real_t elem, - igraph_integer_t idx, igraph_integer_t idx2) { + igraph_int_t idx, igraph_int_t idx2) { IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); /* full, allocate more storage */ if (h->stor_end == h->end) { - igraph_integer_t old_size = igraph_d_indheap_size(h); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = igraph_d_indheap_size(h); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot push to indheap, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -563,7 +563,7 @@ igraph_real_t igraph_d_indheap_delete_max(igraph_d_indheap_t* h) { * \brief Gives the number of elements in the heap. */ -igraph_integer_t igraph_d_indheap_size(const igraph_d_indheap_t* h) { +igraph_int_t igraph_d_indheap_size(const igraph_d_indheap_t* h) { IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); return h->end - h->stor_begin; @@ -577,10 +577,10 @@ igraph_integer_t igraph_d_indheap_size(const igraph_d_indheap_t* h) { * - IGRAPH_ENOMEM: out of memory */ -igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t* h, igraph_integer_t size) { - igraph_integer_t actual_size = igraph_d_indheap_size(h); +igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t* h, igraph_int_t size) { + igraph_int_t actual_size = igraph_d_indheap_size(h); igraph_real_t *tmp1; - igraph_integer_t *tmp2, *tmp3; + igraph_int_t *tmp2, *tmp3; IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); @@ -593,20 +593,20 @@ igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t* h, igraph_integer_t IGRAPH_ERROR("d_indheap reserve failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } IGRAPH_FINALLY(igraph_free, tmp1); - tmp2 = IGRAPH_CALLOC(size, igraph_integer_t); + tmp2 = IGRAPH_CALLOC(size, igraph_int_t); if (tmp2 == 0) { IGRAPH_ERROR("d_indheap reserve failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } IGRAPH_FINALLY(igraph_free, tmp2); - tmp3 = IGRAPH_CALLOC(size, igraph_integer_t); + tmp3 = IGRAPH_CALLOC(size, igraph_int_t); if (tmp3 == 0) { IGRAPH_ERROR("d_indheap reserve failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } IGRAPH_FINALLY(igraph_free, tmp3); memcpy(tmp1, h->stor_begin, (size_t) actual_size * sizeof(igraph_real_t)); - memcpy(tmp2, h->index_begin, (size_t) actual_size * sizeof(igraph_integer_t)); - memcpy(tmp3, h->index2_begin, (size_t) actual_size * sizeof(igraph_integer_t)); + memcpy(tmp2, h->index_begin, (size_t) actual_size * sizeof(igraph_int_t)); + memcpy(tmp3, h->index2_begin, (size_t) actual_size * sizeof(igraph_int_t)); IGRAPH_FREE(h->stor_begin); IGRAPH_FREE(h->index_begin); IGRAPH_FREE(h->index2_begin); @@ -626,7 +626,7 @@ igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t* h, igraph_integer_t * \brief Gives the indices of the maximal element in the heap. */ -void igraph_d_indheap_max_index(igraph_d_indheap_t *h, igraph_integer_t *idx, igraph_integer_t *idx2) { +void igraph_d_indheap_max_index(igraph_d_indheap_t *h, igraph_int_t *idx, igraph_int_t *idx2) { IGRAPH_ASSERT(h != NULL); IGRAPH_ASSERT(h->stor_begin != NULL); (*idx) = h->index_begin[0]; @@ -640,9 +640,9 @@ void igraph_d_indheap_max_index(igraph_d_indheap_t *h, igraph_integer_t *idx, ig /* Unused function, temporarily disabled */ #if 0 -static void igraph_d_indheap_i_build(igraph_d_indheap_t* h, igraph_integer_t head) { +static void igraph_d_indheap_i_build(igraph_d_indheap_t* h, igraph_int_t head) { - igraph_integer_t size = igraph_d_indheap_size(h); + igraph_int_t size = igraph_d_indheap_size(h); if (RIGHTCHILD(head) < size) { /* both subtrees */ igraph_d_indheap_i_build(h, LEFTCHILD(head) ); @@ -663,7 +663,7 @@ static void igraph_d_indheap_i_build(igraph_d_indheap_t* h, igraph_integer_t hea * \brief Moves an element up in the heap, don't call it directly. */ -static void igraph_d_indheap_i_shift_up(igraph_d_indheap_t *h, igraph_integer_t elem) { +static void igraph_d_indheap_i_shift_up(igraph_d_indheap_t *h, igraph_int_t elem) { if (elem == 0 || h->stor_begin[elem] < h->stor_begin[PARENT(elem)]) { /* at the top */ @@ -678,9 +678,9 @@ static void igraph_d_indheap_i_shift_up(igraph_d_indheap_t *h, igraph_integer_t * \brief Moves an element down in the heap, don't call it directly. */ -static void igraph_d_indheap_i_sink(igraph_d_indheap_t* h, igraph_integer_t head) { +static void igraph_d_indheap_i_sink(igraph_d_indheap_t* h, igraph_int_t head) { - igraph_integer_t size = igraph_d_indheap_size(h); + igraph_int_t size = igraph_d_indheap_size(h); if (LEFTCHILD(head) >= size) { /* no subtrees */ } else if (RIGHTCHILD(head) == size || @@ -704,9 +704,9 @@ static void igraph_d_indheap_i_sink(igraph_d_indheap_t* h, igraph_integer_t head * \brief Switches two elements in the heap, don't call it directly. */ -static void igraph_d_indheap_i_switch(igraph_d_indheap_t* h, igraph_integer_t e1, igraph_integer_t e2) { +static void igraph_d_indheap_i_switch(igraph_d_indheap_t* h, igraph_int_t e1, igraph_int_t e2) { if (e1 != e2) { - igraph_integer_t tmpi; + igraph_int_t tmpi; igraph_real_t tmp = h->stor_begin[e1]; h->stor_begin[e1] = h->stor_begin[e2]; h->stor_begin[e2] = tmp; @@ -740,9 +740,9 @@ static void igraph_d_indheap_i_switch(igraph_d_indheap_t* h, igraph_integer_t e1 normal heap does this in O(n) time.... */ static void igraph_i_2wheap_switch(igraph_2wheap_t *h, - igraph_integer_t e1, igraph_integer_t e2) { + igraph_int_t e1, igraph_int_t e2) { if (e1 != e2) { - igraph_integer_t tmp1, tmp2; + igraph_int_t tmp1, tmp2; igraph_real_t tmp3 = VECTOR(h->data)[e1]; VECTOR(h->data)[e1] = VECTOR(h->data)[e2]; VECTOR(h->data)[e2] = tmp3; @@ -759,7 +759,7 @@ static void igraph_i_2wheap_switch(igraph_2wheap_t *h, } static void igraph_i_2wheap_shift_up(igraph_2wheap_t *h, - igraph_integer_t elem) { + igraph_int_t elem) { if (elem == 0 || VECTOR(h->data)[elem] < VECTOR(h->data)[PARENT(elem)]) { /* at the top */ } else { @@ -769,8 +769,8 @@ static void igraph_i_2wheap_shift_up(igraph_2wheap_t *h, } static void igraph_i_2wheap_sink(igraph_2wheap_t *h, - igraph_integer_t head) { - igraph_integer_t size = igraph_2wheap_size(h); + igraph_int_t head) { + igraph_int_t size = igraph_2wheap_size(h); if (LEFTCHILD(head) >= size) { /* no subtrees */ } else if (RIGHTCHILD(head) == size || @@ -797,7 +797,7 @@ static void igraph_i_2wheap_sink(igraph_2wheap_t *h, * Initializes a new two-way heap. The max_size parameter defines the maximum * number of items that the heap can hold. */ -igraph_error_t igraph_2wheap_init(igraph_2wheap_t *h, igraph_integer_t max_size) { +igraph_error_t igraph_2wheap_init(igraph_2wheap_t *h, igraph_int_t max_size) { h->max_size = max_size; /* We start with the biggest */ IGRAPH_VECTOR_INT_INIT_FINALLY(&h->index2, max_size); @@ -841,11 +841,11 @@ igraph_bool_t igraph_2wheap_empty(const igraph_2wheap_t *h) { * the same index. */ igraph_error_t igraph_2wheap_push_with_index(igraph_2wheap_t *h, - igraph_integer_t idx, igraph_real_t elem) { + igraph_int_t idx, igraph_real_t elem) { /* printf("-> %.2g [%li]\n", elem, idx); */ - igraph_integer_t size = igraph_vector_size(&h->data); + igraph_int_t size = igraph_vector_size(&h->data); if (size > IGRAPH_INTEGER_MAX - 2) { /* to allow size+2 below */ @@ -864,7 +864,7 @@ igraph_error_t igraph_2wheap_push_with_index(igraph_2wheap_t *h, /** * Returns the current number of elements in the two-way heap. */ -igraph_integer_t igraph_2wheap_size(const igraph_2wheap_t *h) { +igraph_int_t igraph_2wheap_size(const igraph_2wheap_t *h) { return igraph_vector_size(&h->data); } @@ -873,7 +873,7 @@ igraph_integer_t igraph_2wheap_size(const igraph_2wheap_t *h) { * is also one larger than the maximum allowed index that can be passed to * \c igraph_2wheap_push_with_index . */ -igraph_integer_t igraph_2wheap_max_size(const igraph_2wheap_t *h) { +igraph_int_t igraph_2wheap_max_size(const igraph_2wheap_t *h) { return h->max_size; } @@ -888,7 +888,7 @@ igraph_real_t igraph_2wheap_max(const igraph_2wheap_t *h) { * Returns the index that was associated to the largest element in the heap * when it was pushed to the heap. */ -igraph_integer_t igraph_2wheap_max_index(const igraph_2wheap_t *h) { +igraph_int_t igraph_2wheap_max_index(const igraph_2wheap_t *h) { return VECTOR(h->index)[0]; } @@ -896,7 +896,7 @@ igraph_integer_t igraph_2wheap_max_index(const igraph_2wheap_t *h) { * Returns whether the heap contains an element with the given index, even if * it was deactivated earlier. */ -igraph_bool_t igraph_2wheap_has_elem(const igraph_2wheap_t *h, igraph_integer_t idx) { +igraph_bool_t igraph_2wheap_has_elem(const igraph_2wheap_t *h, igraph_int_t idx) { return (VECTOR(h->index2)[idx] != 0); } @@ -904,15 +904,15 @@ igraph_bool_t igraph_2wheap_has_elem(const igraph_2wheap_t *h, igraph_integer_t * Returns whether the heap contains an element with the given index \em and it * has not been deactivated yet. */ -igraph_bool_t igraph_2wheap_has_active(const igraph_2wheap_t *h, igraph_integer_t idx) { +igraph_bool_t igraph_2wheap_has_active(const igraph_2wheap_t *h, igraph_int_t idx) { return VECTOR(h->index2)[idx] > 1; } /** * Returns the item at the given index in the two-way heap. */ -igraph_real_t igraph_2wheap_get(const igraph_2wheap_t *h, igraph_integer_t idx) { - igraph_integer_t i = VECTOR(h->index2)[idx] - 2; +igraph_real_t igraph_2wheap_get(const igraph_2wheap_t *h, igraph_int_t idx) { + igraph_int_t i = VECTOR(h->index2)[idx] - 2; return VECTOR(h->data)[i]; } @@ -925,7 +925,7 @@ igraph_real_t igraph_2wheap_get(const igraph_2wheap_t *h, igraph_integer_t idx) igraph_real_t igraph_2wheap_delete_max(igraph_2wheap_t *h) { igraph_real_t tmp = VECTOR(h->data)[0]; - igraph_integer_t tmpidx = VECTOR(h->index)[0]; + igraph_int_t tmpidx = VECTOR(h->index)[0]; igraph_i_2wheap_switch(h, 0, igraph_2wheap_size(h) - 1); igraph_vector_pop_back(&h->data); igraph_vector_int_pop_back(&h->index); @@ -946,7 +946,7 @@ igraph_real_t igraph_2wheap_delete_max(igraph_2wheap_t *h) { igraph_real_t igraph_2wheap_deactivate_max(igraph_2wheap_t *h) { igraph_real_t tmp = VECTOR(h->data)[0]; - igraph_integer_t tmpidx = VECTOR(h->index)[0]; + igraph_int_t tmpidx = VECTOR(h->index)[0]; igraph_i_2wheap_switch(h, 0, igraph_2wheap_size(h) - 1); igraph_vector_pop_back(&h->data); igraph_vector_int_pop_back(&h->index); @@ -963,10 +963,10 @@ igraph_real_t igraph_2wheap_deactivate_max(igraph_2wheap_t *h) { * This function does \em not change the indices associated to the elements * that remain in the heap. */ -igraph_real_t igraph_2wheap_delete_max_index(igraph_2wheap_t *h, igraph_integer_t *idx) { +igraph_real_t igraph_2wheap_delete_max_index(igraph_2wheap_t *h, igraph_int_t *idx) { igraph_real_t tmp = VECTOR(h->data)[0]; - igraph_integer_t tmpidx = VECTOR(h->index)[0]; + igraph_int_t tmpidx = VECTOR(h->index)[0]; igraph_i_2wheap_switch(h, 0, igraph_2wheap_size(h) - 1); igraph_vector_pop_back(&h->data); igraph_vector_int_pop_back(&h->index); @@ -982,9 +982,9 @@ igraph_real_t igraph_2wheap_delete_max_index(igraph_2wheap_t *h, igraph_integer_ /** * Modifies the value associated to the given index in the two-way heap. */ -void igraph_2wheap_modify(igraph_2wheap_t *h, igraph_integer_t idx, igraph_real_t elem) { +void igraph_2wheap_modify(igraph_2wheap_t *h, igraph_int_t idx, igraph_real_t elem) { - igraph_integer_t pos = VECTOR(h->index2)[idx] - 2; + igraph_int_t pos = VECTOR(h->index2)[idx] - 2; /* printf("-- %.2g -> %.2g\n", VECTOR(h->data)[pos], elem); */ @@ -997,8 +997,8 @@ void igraph_2wheap_modify(igraph_2wheap_t *h, igraph_integer_t idx, igraph_real_ * Checks that the heap is in a consistent state */ igraph_error_t igraph_2wheap_check(const igraph_2wheap_t *h) { - igraph_integer_t size = igraph_2wheap_size(h); - igraph_integer_t i; + igraph_int_t size = igraph_2wheap_size(h); + igraph_int_t i; igraph_bool_t error = false; /* Check the heap property */ diff --git a/src/vendor/cigraph/src/core/indheap.h b/src/vendor/cigraph/src/core/indheap.h index 840d51ae413..a718b45e9bc 100644 --- a/src/vendor/cigraph/src/core/indheap.h +++ b/src/vendor/cigraph/src/core/indheap.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -41,24 +41,24 @@ typedef struct s_indheap { igraph_real_t* stor_begin; igraph_real_t* stor_end; igraph_real_t* end; - igraph_integer_t* index_begin; + igraph_int_t* index_begin; } igraph_indheap_t; #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); +igraph_error_t igraph_indheap_init(igraph_indheap_t* h, igraph_int_t size); +igraph_error_t igraph_indheap_init_array(igraph_indheap_t *t, const igraph_real_t *data, igraph_int_t len); void igraph_indheap_destroy(igraph_indheap_t* h); void igraph_indheap_clear(igraph_indheap_t *h); IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_indheap_empty(const igraph_indheap_t* h); igraph_error_t igraph_indheap_push(igraph_indheap_t* h, igraph_real_t elem); -igraph_error_t igraph_indheap_push_with_index(igraph_indheap_t* h, igraph_integer_t idx, igraph_real_t elem); -void igraph_indheap_modify(igraph_indheap_t* h, igraph_integer_t idx, igraph_real_t elem); +igraph_error_t igraph_indheap_push_with_index(igraph_indheap_t* h, igraph_int_t idx, igraph_real_t elem); +void igraph_indheap_modify(igraph_indheap_t* h, igraph_int_t idx, igraph_real_t elem); IGRAPH_FUNCATTR_PURE igraph_real_t igraph_indheap_max(const igraph_indheap_t* h); igraph_real_t igraph_indheap_delete_max(igraph_indheap_t* h); -IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_indheap_size(const igraph_indheap_t *h); -igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_integer_t size); -IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_indheap_max_index(const igraph_indheap_t *h); +IGRAPH_FUNCATTR_PURE igraph_int_t igraph_indheap_size(const igraph_indheap_t *h); +igraph_error_t igraph_indheap_reserve(igraph_indheap_t* h, igraph_int_t size); +IGRAPH_FUNCATTR_PURE igraph_int_t igraph_indheap_max_index(const igraph_indheap_t *h); /* -------------------------------------------------- */ @@ -79,23 +79,23 @@ typedef struct s_indheap_d { igraph_real_t* stor_begin; igraph_real_t* stor_end; igraph_real_t* end; - igraph_integer_t* index_begin; - igraph_integer_t* index2_begin; + igraph_int_t* index_begin; + igraph_int_t* index2_begin; } igraph_d_indheap_t; #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 igraph_error_t igraph_d_indheap_init(igraph_d_indheap_t *h, igraph_int_t size); IGRAPH_PRIVATE_EXPORT void igraph_d_indheap_destroy(igraph_d_indheap_t *h); IGRAPH_PRIVATE_EXPORT igraph_bool_t igraph_d_indheap_empty(const igraph_d_indheap_t *h); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_d_indheap_push(igraph_d_indheap_t *h, igraph_real_t elem, - igraph_integer_t idx, igraph_integer_t idx2); + igraph_int_t idx, igraph_int_t idx2); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_d_indheap_max(const igraph_d_indheap_t *h); IGRAPH_PRIVATE_EXPORT igraph_real_t igraph_d_indheap_delete_max(igraph_d_indheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_d_indheap_size(const igraph_d_indheap_t *h); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t *h, igraph_integer_t size); -IGRAPH_PRIVATE_EXPORT void igraph_d_indheap_max_index(igraph_d_indheap_t *h, igraph_integer_t *idx, igraph_integer_t *idx2); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_d_indheap_size(const igraph_d_indheap_t *h); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_d_indheap_reserve(igraph_d_indheap_t *h, igraph_int_t size); +IGRAPH_PRIVATE_EXPORT void igraph_d_indheap_max_index(igraph_d_indheap_t *h, igraph_int_t *idx, igraph_int_t *idx2); /* -------------------------------------------------- */ /* Two-way indexed heap */ @@ -108,7 +108,7 @@ IGRAPH_PRIVATE_EXPORT void igraph_d_indheap_max_index(igraph_d_indheap_t *h, igr typedef struct igraph_2wheap_t { /** Number of items in the heap */ - igraph_integer_t max_size; + igraph_int_t max_size; /** The items themselves in the heap */ igraph_vector_t data; @@ -130,23 +130,23 @@ typedef struct igraph_2wheap_t { igraph_vector_int_t index2; } igraph_2wheap_t; -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_2wheap_init(igraph_2wheap_t *h, igraph_integer_t size); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_2wheap_init(igraph_2wheap_t *h, igraph_int_t size); IGRAPH_PRIVATE_EXPORT void igraph_2wheap_destroy(igraph_2wheap_t *h); IGRAPH_PRIVATE_EXPORT void igraph_2wheap_clear(igraph_2wheap_t *h); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_2wheap_push_with_index(igraph_2wheap_t *h, - igraph_integer_t idx, igraph_real_t elem); + igraph_int_t idx, igraph_real_t elem); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_2wheap_empty(const igraph_2wheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_2wheap_size(const igraph_2wheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_2wheap_max_size(const igraph_2wheap_t *h); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_2wheap_size(const igraph_2wheap_t *h); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_2wheap_max_size(const igraph_2wheap_t *h); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_2wheap_max(const igraph_2wheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_2wheap_max_index(const igraph_2wheap_t *h); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_2wheap_max_index(const igraph_2wheap_t *h); IGRAPH_PRIVATE_EXPORT igraph_real_t igraph_2wheap_deactivate_max(igraph_2wheap_t *h); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_2wheap_has_elem(const igraph_2wheap_t *h, igraph_integer_t idx); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_2wheap_has_active(const igraph_2wheap_t *h, igraph_integer_t idx); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_2wheap_get(const igraph_2wheap_t *h, igraph_integer_t idx); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_2wheap_has_elem(const igraph_2wheap_t *h, igraph_int_t idx); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_2wheap_has_active(const igraph_2wheap_t *h, igraph_int_t idx); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_real_t igraph_2wheap_get(const igraph_2wheap_t *h, igraph_int_t idx); IGRAPH_PRIVATE_EXPORT igraph_real_t igraph_2wheap_delete_max(igraph_2wheap_t *h); -IGRAPH_PRIVATE_EXPORT igraph_real_t igraph_2wheap_delete_max_index(igraph_2wheap_t *h, igraph_integer_t *idx); -IGRAPH_PRIVATE_EXPORT void igraph_2wheap_modify(igraph_2wheap_t *h, igraph_integer_t idx, igraph_real_t elem); +IGRAPH_PRIVATE_EXPORT igraph_real_t igraph_2wheap_delete_max_index(igraph_2wheap_t *h, igraph_int_t *idx); +IGRAPH_PRIVATE_EXPORT void igraph_2wheap_modify(igraph_2wheap_t *h, igraph_int_t idx, igraph_real_t elem); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_2wheap_check(const igraph_2wheap_t *h); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/core/interruption.c b/src/vendor/cigraph/src/core/interruption.c index 13cd2a65a88..2c30c179b4b 100644 --- a/src/vendor/cigraph/src/core/interruption.c +++ b/src/vendor/cigraph/src/core/interruption.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/core/interruption.h b/src/vendor/cigraph/src/core/interruption.h index 089e0742583..b05f6713ae4 100644 --- a/src/vendor/cigraph/src/core/interruption.h +++ b/src/vendor/cigraph/src/core/interruption.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -61,7 +61,7 @@ extern IGRAPH_THREAD_LOCAL igraph_interruption_handler_t *igraph_i_interruption_ * and initialized to 0. Example: * * int myiter = 0; - * for (igraph_integer_t i=0; i < n; i++) { + * for (igraph_int_t i=0; i < n; i++) { * // Allow for interruption every 1000th iteration * IGRAPH_ALLOW_INTERRUPTION_LIMITED(myiter, 1000); * } diff --git a/src/vendor/cigraph/src/core/marked_queue.c b/src/vendor/cigraph/src/core/marked_queue.c index 3d4fa87f688..7c8da9395e1 100644 --- a/src/vendor/cigraph/src/core/marked_queue.c +++ b/src/vendor/cigraph/src/core/marked_queue.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -25,7 +25,7 @@ #define BATCH_MARKER -1 igraph_error_t igraph_marked_queue_int_init(igraph_marked_queue_int_t *q, - igraph_integer_t size) { + igraph_int_t size) { IGRAPH_CHECK(igraph_dqueue_int_init(&q->Q, 0)); IGRAPH_FINALLY(igraph_dqueue_int_destroy, &q->Q); IGRAPH_CHECK(igraph_vector_int_init(&q->set, size)); @@ -54,16 +54,16 @@ igraph_bool_t igraph_marked_queue_int_empty(const igraph_marked_queue_int_t *q) return q->size == 0; } -igraph_integer_t igraph_marked_queue_int_size(const igraph_marked_queue_int_t *q) { +igraph_int_t igraph_marked_queue_int_size(const igraph_marked_queue_int_t *q) { return q->size; } igraph_bool_t igraph_marked_queue_int_iselement(const igraph_marked_queue_int_t *q, - igraph_integer_t elem) { + igraph_int_t elem) { return (VECTOR(q->set)[elem] == q->mark); } -igraph_error_t igraph_marked_queue_int_push(igraph_marked_queue_int_t *q, igraph_integer_t elem) { +igraph_error_t igraph_marked_queue_int_push(igraph_marked_queue_int_t *q, igraph_int_t elem) { if (VECTOR(q->set)[elem] != q->mark) { IGRAPH_CHECK(igraph_dqueue_int_push(&q->Q, elem)); VECTOR(q->set)[elem] = q->mark; @@ -78,8 +78,8 @@ igraph_error_t igraph_marked_queue_int_start_batch(igraph_marked_queue_int_t *q) } void igraph_marked_queue_int_pop_back_batch(igraph_marked_queue_int_t *q) { - igraph_integer_t size = igraph_dqueue_int_size(&q->Q); - igraph_integer_t elem; + igraph_int_t size = igraph_dqueue_int_size(&q->Q); + igraph_int_t elem; while (size > 0 && (elem = igraph_dqueue_int_pop_back(&q->Q)) != BATCH_MARKER) { VECTOR(q->set)[elem] = 0; @@ -102,10 +102,10 @@ igraph_error_t igraph_marked_queue_int_fprint(const igraph_marked_queue_int_t *q igraph_error_t igraph_marked_queue_int_as_vector(const igraph_marked_queue_int_t *q, igraph_vector_int_t *vec) { - igraph_integer_t i, p, n = igraph_dqueue_int_size(&q->Q); + igraph_int_t i, p, n = igraph_dqueue_int_size(&q->Q); IGRAPH_CHECK(igraph_vector_int_resize(vec, q->size)); for (i = 0, p = 0; i < n; i++) { - igraph_integer_t e = igraph_dqueue_int_get(&q->Q, i); + igraph_int_t e = igraph_dqueue_int_get(&q->Q, i); if (e != BATCH_MARKER) { VECTOR(*vec)[p++] = e; } diff --git a/src/vendor/cigraph/src/core/marked_queue.h b/src/vendor/cigraph/src/core/marked_queue.h index f0f8dac5553..93a9bfd21ac 100644 --- a/src/vendor/cigraph/src/core/marked_queue.h +++ b/src/vendor/cigraph/src/core/marked_queue.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -44,24 +44,24 @@ IGRAPH_BEGIN_C_DECLS typedef struct igraph_marked_queue_int_t { igraph_dqueue_int_t Q; igraph_vector_int_t set; - igraph_integer_t mark; - igraph_integer_t size; + igraph_int_t mark; + igraph_int_t size; } igraph_marked_queue_int_t; IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_marked_queue_int_init(igraph_marked_queue_int_t *q, - igraph_integer_t size); + igraph_int_t size); IGRAPH_PRIVATE_EXPORT void igraph_marked_queue_int_destroy(igraph_marked_queue_int_t *q); IGRAPH_PRIVATE_EXPORT void igraph_marked_queue_int_reset(igraph_marked_queue_int_t *q); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_marked_queue_int_empty(const igraph_marked_queue_int_t *q); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_marked_queue_int_size(const igraph_marked_queue_int_t *q); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_marked_queue_int_size(const igraph_marked_queue_int_t *q); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_marked_queue_int_print(const igraph_marked_queue_int_t *q); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_marked_queue_int_fprint(const igraph_marked_queue_int_t *q, FILE *file); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_marked_queue_int_iselement(const igraph_marked_queue_int_t *q, - igraph_integer_t elem); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_marked_queue_int_push(igraph_marked_queue_int_t *q, igraph_integer_t elem); + igraph_int_t elem); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_marked_queue_int_push(igraph_marked_queue_int_t *q, igraph_int_t elem); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_marked_queue_int_start_batch(igraph_marked_queue_int_t *q); IGRAPH_PRIVATE_EXPORT void igraph_marked_queue_int_pop_back_batch(igraph_marked_queue_int_t *q); diff --git a/src/vendor/cigraph/src/core/math.h b/src/vendor/cigraph/src/core/math.h index 9c406c26fd9..c91c19a17e6 100644 --- a/src/vendor/cigraph/src/core/math.h +++ b/src/vendor/cigraph/src/core/math.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/core/matrix.c b/src/vendor/cigraph/src/core/matrix.c index 79b0db9c521..643dd9883cc 100644 --- a/src/vendor/cigraph/src/core/matrix.c +++ b/src/vendor/cigraph/src/core/matrix.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -69,8 +69,8 @@ igraph_error_t igraph_matrix_complex_real(const igraph_matrix_complex_t *m, igraph_matrix_t *real) { - igraph_integer_t nrow = igraph_matrix_complex_nrow(m); - igraph_integer_t ncol = igraph_matrix_complex_ncol(m); + igraph_int_t nrow = igraph_matrix_complex_nrow(m); + igraph_int_t ncol = igraph_matrix_complex_ncol(m); IGRAPH_CHECK(igraph_matrix_resize(real, nrow, ncol)); IGRAPH_CHECK(igraph_vector_complex_real(&m->data, &real->data)); return IGRAPH_SUCCESS; @@ -92,8 +92,8 @@ igraph_error_t igraph_matrix_complex_real(const igraph_matrix_complex_t *m, igraph_error_t igraph_matrix_complex_imag(const igraph_matrix_complex_t *m, igraph_matrix_t *imag) { - igraph_integer_t nrow = igraph_matrix_complex_nrow(m); - igraph_integer_t ncol = igraph_matrix_complex_ncol(m); + igraph_int_t nrow = igraph_matrix_complex_nrow(m); + igraph_int_t ncol = igraph_matrix_complex_ncol(m); IGRAPH_CHECK(igraph_matrix_resize(imag, nrow, ncol)); IGRAPH_CHECK(igraph_vector_complex_imag(&m->data, &imag->data)); return IGRAPH_SUCCESS; @@ -117,8 +117,8 @@ igraph_error_t igraph_matrix_complex_imag(const igraph_matrix_complex_t *m, igraph_error_t igraph_matrix_complex_realimag(const igraph_matrix_complex_t *m, igraph_matrix_t *real, igraph_matrix_t *imag) { - igraph_integer_t nrow = igraph_matrix_complex_nrow(m); - igraph_integer_t ncol = igraph_matrix_complex_ncol(m); + igraph_int_t nrow = igraph_matrix_complex_nrow(m); + igraph_int_t ncol = igraph_matrix_complex_ncol(m); IGRAPH_CHECK(igraph_matrix_resize(real, nrow, ncol)); IGRAPH_CHECK(igraph_matrix_resize(imag, nrow, ncol)); IGRAPH_CHECK(igraph_vector_complex_realimag(&m->data, &real->data, @@ -144,10 +144,10 @@ igraph_error_t igraph_matrix_complex_realimag(const igraph_matrix_complex_t *m, igraph_error_t igraph_matrix_complex_create(igraph_matrix_complex_t *m, const igraph_matrix_t *real, const igraph_matrix_t *imag) { - igraph_integer_t nrowr = igraph_matrix_nrow(real); - igraph_integer_t ncolr = igraph_matrix_ncol(real); - igraph_integer_t nrowi = igraph_matrix_nrow(imag); - igraph_integer_t ncoli = igraph_matrix_ncol(imag); + igraph_int_t nrowr = igraph_matrix_nrow(real); + igraph_int_t ncolr = igraph_matrix_ncol(real); + igraph_int_t nrowi = igraph_matrix_nrow(imag); + igraph_int_t ncoli = igraph_matrix_ncol(imag); if (nrowr != nrowi || ncolr != ncoli) { IGRAPH_ERRORF("Dimensions of real (%" IGRAPH_PRId " by %" IGRAPH_PRId ") and " @@ -157,7 +157,7 @@ igraph_error_t igraph_matrix_complex_create(igraph_matrix_complex_t *m, IGRAPH_CHECK(igraph_matrix_complex_init(m, nrowr, ncolr)); - for (igraph_integer_t i = 0; i < nrowr * ncolr; i++) { + for (igraph_int_t i = 0; i < nrowr * ncolr; i++) { VECTOR(m->data)[i] = igraph_complex(VECTOR(real->data)[i], VECTOR(imag->data)[i]); } @@ -182,10 +182,10 @@ igraph_error_t igraph_matrix_complex_create(igraph_matrix_complex_t *m, igraph_error_t igraph_matrix_complex_create_polar(igraph_matrix_complex_t *m, const igraph_matrix_t *r, const igraph_matrix_t *theta) { - igraph_integer_t nrowr = igraph_matrix_nrow(r); - igraph_integer_t ncolr = igraph_matrix_ncol(r); - igraph_integer_t nrowt = igraph_matrix_nrow(theta); - igraph_integer_t ncolt = igraph_matrix_ncol(theta); + igraph_int_t nrowr = igraph_matrix_nrow(r); + igraph_int_t ncolr = igraph_matrix_ncol(r); + igraph_int_t nrowt = igraph_matrix_nrow(theta); + igraph_int_t ncolt = igraph_matrix_ncol(theta); if (nrowr != nrowt || ncolr != ncolt) { IGRAPH_ERRORF("Dimensions of magnitude (%" IGRAPH_PRId " by %" IGRAPH_PRId ") and " @@ -195,7 +195,7 @@ igraph_error_t igraph_matrix_complex_create_polar(igraph_matrix_complex_t *m, IGRAPH_CHECK(igraph_matrix_complex_init(m, nrowr, ncolr)); - for (igraph_integer_t i = 0; i < nrowr * ncolr; i++) { + for (igraph_int_t i = 0; i < nrowr * ncolr; i++) { VECTOR(m->data)[i] = igraph_complex_polar(VECTOR(r->data)[i], VECTOR(theta->data)[i]); } return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/core/matrix.pmt b/src/vendor/cigraph/src/core/matrix.pmt index 84dac7de7c3..c73b4ef16bb 100644 --- a/src/vendor/cigraph/src/core/matrix.pmt +++ b/src/vendor/cigraph/src/core/matrix.pmt @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -61,8 +61,8 @@ */ igraph_error_t FUNCTION(igraph_matrix, init)( - TYPE(igraph_matrix) *m, igraph_integer_t nrow, igraph_integer_t ncol) { - igraph_integer_t size; + TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) { + igraph_int_t size; IGRAPH_ASSERT(nrow >= 0 && ncol >= 0); IGRAPH_SAFE_MULT(nrow, ncol, &size); IGRAPH_CHECK(FUNCTION(igraph_vector, init)(&m->data, size)); @@ -84,35 +84,33 @@ igraph_error_t FUNCTION(igraph_matrix, init)( * * * Since this function creates a view into an existing array, you must \em not - * destroy the \c igraph_matrix_t object when you are done with it. Similarly, + * destroy the \type igraph_matrix_t object when you are done with it. Similarly, * you must \em not call any function on it that may attempt to modify the size * of the matrix. Modifying an element in the matrix will modify the underlying * array as the two share the same memory block. * - * \param m Pointer to a not yet initialized matrix object where the view will - * be created. - * \param data The array that the matrix provides a view into. + * \param data The raw array that the matrix provides a view into. * \param nrow The number of rows in the matrix. * \param ncol The number of columns in the matrix. - * \return Pointer to the matrix object, the same as the \p m parameter, for - * convenience. + * \return The matrix object providing the view into the array. * * Time complexity: O(1). */ -const TYPE(igraph_matrix)* FUNCTION(igraph_matrix, view)( - const TYPE(igraph_matrix) *m, const BASE *data, - igraph_integer_t nrow, igraph_integer_t ncol) { +TYPE(igraph_matrix) FUNCTION(igraph_matrix, view)( + const BASE *data, + igraph_int_t nrow, igraph_int_t ncol) { + /* temporarily cast away the constness */ - TYPE(igraph_matrix) *m2 = (TYPE(igraph_matrix)*)m; + TYPE(igraph_matrix) m; /* No overflow checking, as this function does not return igraph_error_t. * It is the caller's resposibility to ensure that the size of 'data' * matches nrow*ncol, which also implies that nrow*ncol does not overflow. */ - FUNCTION(igraph_vector, view)(&m2->data, data, ncol * nrow); - m2->nrow = nrow; - m2->ncol = ncol; + m.data = FUNCTION(igraph_vector, view)(data, ncol * nrow); + m.nrow = nrow; + m.ncol = ncol; return m; } @@ -141,33 +139,24 @@ const TYPE(igraph_matrix)* FUNCTION(igraph_matrix, view)( * block of the vector, and the matrix view will not be informed about the * re-allocation so it will point to an invalid memory area afterwards. * - * \param m Pointer to a not yet initialized matrix object where the view will - * be created. * \param v The vector that the matrix will provide a view into. * \param nrow The number of rows in the matrix. The number of columns will be * derived implicitly from the size of the vector. If the number of * items in the vector is not divisible by the number of rows, the * last few elements of the vector will not be covered by the view. - * \return Error code. + * \return The matrix object providing the view into the vector. * * Time complexity: O(1). */ -const TYPE(igraph_matrix) *FUNCTION(igraph_matrix, view_from_vector)( - const TYPE(igraph_matrix) *m, const TYPE(igraph_vector) *v, - igraph_integer_t nrow +TYPE(igraph_matrix) FUNCTION(igraph_matrix, view_from_vector)( + const TYPE(igraph_vector) *v, + igraph_int_t nrow ) { - /* temporarily cast away the constness */ - TYPE(igraph_matrix) *m2 = (TYPE(igraph_matrix)*)m; - - igraph_integer_t size = FUNCTION(igraph_vector, size)(v); - igraph_integer_t ncol = nrow > 0 ? size / nrow : 0; + igraph_int_t size = FUNCTION(igraph_vector, size)(v); + igraph_int_t ncol = nrow > 0 ? size / nrow : 0; - FUNCTION(igraph_vector, view)(&m2->data, VECTOR(*v), ncol * nrow); - m2->nrow = nrow; - m2->ncol = ncol; - - return m; + return FUNCTION(igraph_matrix, view)(VECTOR(*v), nrow, ncol); } /** @@ -206,7 +195,7 @@ void FUNCTION(igraph_matrix, destroy)(TYPE(igraph_matrix) *m) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_matrix, capacity)(const TYPE(igraph_matrix) *m) { +igraph_int_t FUNCTION(igraph_matrix, capacity)(const TYPE(igraph_matrix) *m) { return FUNCTION(igraph_vector, capacity)(&m->data); } @@ -237,8 +226,8 @@ igraph_integer_t FUNCTION(igraph_matrix, capacity)(const TYPE(igraph_matrix) *m) * number of elements in the resized matrix. */ -igraph_error_t FUNCTION(igraph_matrix, resize)(TYPE(igraph_matrix) *m, igraph_integer_t nrow, igraph_integer_t ncol) { - igraph_integer_t size; +igraph_error_t FUNCTION(igraph_matrix, resize)(TYPE(igraph_matrix) *m, igraph_int_t nrow, igraph_int_t ncol) { + igraph_int_t size; IGRAPH_ASSERT(nrow >= 0 && ncol >= 0); IGRAPH_SAFE_MULT(nrow, ncol, &size); IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, size)); @@ -278,7 +267,7 @@ void FUNCTION(igraph_matrix, resize_min)(TYPE(igraph_matrix) *m) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_matrix, size)(const TYPE(igraph_matrix) *m) { +igraph_int_t FUNCTION(igraph_matrix, size)(const TYPE(igraph_matrix) *m) { return (m->nrow) * (m->ncol); } @@ -293,7 +282,7 @@ igraph_integer_t FUNCTION(igraph_matrix, size)(const TYPE(igraph_matrix) *m) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m) { +igraph_int_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m) { return m->nrow; } @@ -308,31 +297,72 @@ igraph_integer_t FUNCTION(igraph_matrix, nrow)(const TYPE(igraph_matrix) *m) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_matrix, ncol)(const TYPE(igraph_matrix) *m) { +igraph_int_t FUNCTION(igraph_matrix, ncol)(const TYPE(igraph_matrix) *m) { return m->ncol; } +/** + * Copies matrix data stored contiguously while transposing. Applications include implementing + * matrix transposition as well as changing between row-major and column-major storage formats. + * + * \param dst Data will be copied into this vector. It must have length m-by-n. It will not be resized. + * \param src Vector containing the data to be copied. It is assumed to have length m-by-n. + * Must not be the same as \p dst . + * \param m The size of contiguous blocks. This is the number of columns when using column-major + * storage format, or the number of rows when using row-major format. + * \param n The number of blocks. This is the number of rows when using column-major format, + * or the number of columns when using row-major format. + */ +static void FUNCTION(igraph_i, transpose_copy)( + TYPE(igraph_vector) *dst, const TYPE(igraph_vector) *src, + size_t m, size_t n) { + + IGRAPH_ASSERT(dst != src); + + /* Block size of 4 was found to yield the best performance when benchmarking with: + * - Intel Core i7-7920HQ on macOS. + * - AMD Ryzen Threadripper 3990X on Linux. + */ + const size_t blocksize = 4; + for (size_t i=0; i < m; i += blocksize) { + for (size_t j=0; j < n; j++) { + for (size_t k=0; k < blocksize && i+k < m; k++) { + VECTOR(*dst)[j + (i+k)*n] = VECTOR(*src)[i+k + j*m]; + } + } + } +} + /** * \ingroup matrix * \function igraph_matrix_copy_to * \brief Copies a matrix to a regular C array. * * - * The matrix is copied columnwise, as this is the format most - * programs and languages use. * The C array should be of sufficient size; there are (of course) no * range checks. + * * \param m Pointer to an initialized matrix object. * \param to Pointer to a C array; the place to copy the data to. + * \param storage \c IGRAPH_ROW_MAJOR to write the data in row-major format, + * \c IGRAPH_COLUMN_MAJOR to write it in column-major format. Currently + * igraph uses column-major storage internally, thus \c IGRAPH_COLUMN_MAJOR + * is much faster. * \return Error code. * * Time complexity: O(n), * n is the number of * elements in the matrix. */ - -void FUNCTION(igraph_matrix, copy_to)(const TYPE(igraph_matrix) *m, BASE *to) { - FUNCTION(igraph_vector, copy_to)(&m->data, to); +void FUNCTION(igraph_matrix, copy_to)(const TYPE(igraph_matrix) *m, BASE *to, igraph_matrix_storage_t storage) { + if (storage == IGRAPH_ROW_MAJOR) { + TYPE(igraph_vector) dst = FUNCTION(igraph_vector, view)(to, m->nrow * m->ncol); + FUNCTION(igraph_i, transpose_copy)(&dst, &m->data, m->nrow, m->ncol); + } else if (storage == IGRAPH_COLUMN_MAJOR) { + FUNCTION(igraph_vector, copy_to)(&m->data, to); + } else { + IGRAPH_FATAL("Invalid matrix storage format."); + } } /** @@ -364,8 +394,8 @@ void FUNCTION(igraph_matrix, null)(TYPE(igraph_matrix) *m) { * resized matrix. */ -igraph_error_t FUNCTION(igraph_matrix, add_cols)(TYPE(igraph_matrix) *m, igraph_integer_t n) { - igraph_integer_t new_ncol; +igraph_error_t FUNCTION(igraph_matrix, add_cols)(TYPE(igraph_matrix) *m, igraph_int_t n) { + igraph_int_t new_ncol; IGRAPH_SAFE_ADD(m->ncol, n, &new_ncol); IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(m, m->nrow, new_ncol)); return IGRAPH_SUCCESS; @@ -384,12 +414,12 @@ igraph_error_t FUNCTION(igraph_matrix, add_cols)(TYPE(igraph_matrix) *m, igraph_ * resized matrix. */ -igraph_error_t FUNCTION(igraph_matrix, add_rows)(TYPE(igraph_matrix) *m, igraph_integer_t n) { - igraph_integer_t new_nrow, new_size; +igraph_error_t FUNCTION(igraph_matrix, add_rows)(TYPE(igraph_matrix) *m, igraph_int_t n) { + igraph_int_t new_nrow, new_size; IGRAPH_SAFE_ADD(m->nrow, n, &new_nrow); IGRAPH_SAFE_MULT(m->ncol, new_nrow, &new_size); IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&m->data, new_size)); - for (igraph_integer_t i = m->ncol - 1; i >= 0; i--) { + for (igraph_int_t i = m->ncol - 1; i >= 0; i--) { FUNCTION(igraph_vector, move_interval)(&m->data, (m->nrow)*i, (m->nrow) * (i + 1), new_nrow * i); } @@ -410,7 +440,7 @@ igraph_error_t FUNCTION(igraph_matrix, add_rows)(TYPE(igraph_matrix) *m, igraph_ * resized matrix. */ -igraph_error_t FUNCTION(igraph_matrix, remove_col)(TYPE(igraph_matrix) *m, igraph_integer_t col) { +igraph_error_t FUNCTION(igraph_matrix, remove_col)(TYPE(igraph_matrix) *m, igraph_int_t col) { FUNCTION(igraph_vector, remove_section)(&m->data, (m->nrow)*col, (m->nrow) * (col + 1)); m->ncol--; return IGRAPH_SUCCESS; @@ -426,8 +456,8 @@ igraph_error_t FUNCTION(igraph_matrix, remove_col)(TYPE(igraph_matrix) *m, igrap */ igraph_error_t FUNCTION(igraph_matrix, permdelete_rows)( - TYPE(igraph_matrix) *m, igraph_integer_t *index, igraph_integer_t nremove) { - igraph_integer_t i, j; + TYPE(igraph_matrix) *m, igraph_int_t *index, igraph_int_t nremove) { + igraph_int_t i, j; for (j = 0; j < m->nrow; j++) { if (index[j] != 0) { for (i = 0; i < m->ncol; i++) { @@ -444,38 +474,6 @@ igraph_error_t FUNCTION(igraph_matrix, permdelete_rows)( return IGRAPH_SUCCESS; } -/** - * Copies matrix data stored contiguously while transposing. Applications include implementing - * matrix transposition as well as changing between row-major and column-major storage formats. - * - * \param dst Data will be copied into this vector. It must have length m-by-n. It will not be resized. - * \param src Vector containing the data to be copied. It is assumed to have length m-by-n. - * Must not be the same as \p dst . - * \param m The size of contiguous blocks. This is the number of columns when using column-major - * storage format, or the number of rows when using row-major format. - * \param n The number of blocks. The is the number of rows when using column-major format, - * or the number of column when using row-major format. - */ -static void FUNCTION(igraph_i, transpose_copy)( - TYPE(igraph_vector) *dst, const TYPE(igraph_vector) *src, - size_t m, size_t n) { - - IGRAPH_ASSERT(dst != src); - - /* Block size of 4 was found to yield the best performance when benchmarking with: - * - Intel Core i7-7920HQ on macOS. - * - AMD Ryzen Threadripper 3990X on Linux. - */ - const size_t blocksize = 4; - for (size_t i=0; i < m; i += blocksize) { - for (size_t j=0; j < n; j++) { - for (size_t k=0; k < blocksize && i+k < m; k++) { - VECTOR(*dst)[j + (i+k)*n] = VECTOR(*src)[i+k + j*m]; - } - } - } -} - /** * \ingroup matrix * \function igraph_matrix_init_array @@ -504,20 +502,20 @@ static void FUNCTION(igraph_i, transpose_copy)( igraph_error_t FUNCTION(igraph_matrix, init_array)( TYPE(igraph_matrix) *m, const BASE *data, - igraph_integer_t nrow, igraph_integer_t ncol, + igraph_int_t nrow, igraph_int_t ncol, igraph_matrix_storage_t storage) { - igraph_integer_t length; - TYPE(igraph_vector) v; + igraph_int_t length; IGRAPH_SAFE_MULT(nrow, ncol, &length); IGRAPH_CHECK(FUNCTION(igraph_matrix, init)(m, nrow, ncol)); - FUNCTION(igraph_vector, view)(&v, data, length); + const TYPE(igraph_vector) v = FUNCTION(igraph_vector, view)(data, length); + if (storage == IGRAPH_COLUMN_MAJOR) { IGRAPH_CHECK(FUNCTION(igraph_vector, update)(&m->data, &v)); } else if (storage == IGRAPH_ROW_MAJOR) { FUNCTION(igraph_i, transpose_copy)(&m->data, &v, ncol, nrow); } else { - IGRAPH_ERROR("Invalid storage type argument", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid storage type argument.", IGRAPH_EINVAL); } return IGRAPH_SUCCESS; @@ -605,8 +603,8 @@ void FUNCTION(igraph_matrix, scale)(TYPE(igraph_matrix) *m, BASE by) { igraph_error_t FUNCTION(igraph_matrix, select_rows)(const TYPE(igraph_matrix) *m, TYPE(igraph_matrix) *res, const igraph_vector_int_t *rows) { - igraph_integer_t norows = igraph_vector_int_size(rows); - igraph_integer_t i, j, ncols = FUNCTION(igraph_matrix, ncol)(m); + igraph_int_t norows = igraph_vector_int_size(rows); + igraph_int_t i, j, ncols = FUNCTION(igraph_matrix, ncol)(m); IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(res, norows, ncols)); /* Iterate in column-major order for better performance. */ @@ -643,9 +641,9 @@ igraph_error_t FUNCTION(igraph_matrix, select_rows_cols)(const TYPE(igraph_matri TYPE(igraph_matrix) *res, const igraph_vector_int_t *rows, const igraph_vector_int_t *cols) { - igraph_integer_t nrows = igraph_vector_int_size(rows); - igraph_integer_t ncols = igraph_vector_int_size(cols); - igraph_integer_t i, j; + igraph_int_t nrows = igraph_vector_int_size(rows); + igraph_int_t ncols = igraph_vector_int_size(cols); + igraph_int_t i, j; IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(res, nrows, ncols)); /* Iterate in column-major order for better performance. */ @@ -674,8 +672,8 @@ igraph_error_t FUNCTION(igraph_matrix, select_rows_cols)(const TYPE(igraph_matri igraph_error_t FUNCTION(igraph_matrix, get_col)(const TYPE(igraph_matrix) *m, TYPE(igraph_vector) *res, - igraph_integer_t index) { - igraph_integer_t nrow = FUNCTION(igraph_matrix, nrow)(m); + igraph_int_t index) { + igraph_int_t nrow = FUNCTION(igraph_matrix, nrow)(m); if (index >= m->ncol) { IGRAPH_ERROR("Index out of range for selecting matrix column", IGRAPH_EINVAL); @@ -891,7 +889,7 @@ igraph_error_t FUNCTION(igraph_matrix, transpose)(TYPE(igraph_matrix) *m) { } } - SWAP(igraph_integer_t, m->nrow, m->ncol); + SWAP(igraph_int_t, m->nrow, m->ncol); return IGRAPH_SUCCESS; } @@ -913,7 +911,7 @@ igraph_error_t FUNCTION(igraph_matrix, transpose)(TYPE(igraph_matrix) *m) { */ BASE FUNCTION(igraph_matrix, get)(const TYPE(igraph_matrix) *m, - igraph_integer_t row, igraph_integer_t col) { + igraph_int_t row, igraph_int_t col) { return MATRIX(*m, row, col); } @@ -932,7 +930,7 @@ BASE FUNCTION(igraph_matrix, get)(const TYPE(igraph_matrix) *m, */ BASE* FUNCTION(igraph_matrix, get_ptr)(const TYPE(igraph_matrix) *m, - igraph_integer_t row, igraph_integer_t col) { + igraph_int_t row, igraph_int_t col) { return &MATRIX(*m, row, col); } @@ -950,7 +948,7 @@ BASE* FUNCTION(igraph_matrix, get_ptr)(const TYPE(igraph_matrix) *m, */ void FUNCTION(igraph_matrix, set)( - TYPE(igraph_matrix)* m, igraph_integer_t row, igraph_integer_t col, + TYPE(igraph_matrix)* m, igraph_int_t row, igraph_int_t col, BASE value) { MATRIX(*m, row, col) = value; } @@ -1008,14 +1006,14 @@ igraph_error_t FUNCTION(igraph_matrix, update)(TYPE(igraph_matrix) *to, igraph_error_t FUNCTION(igraph_matrix, rbind)(TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from) { - igraph_integer_t tocols = to->ncol, fromcols = from->ncol; - igraph_integer_t torows = to->nrow, fromrows = from->nrow; - igraph_integer_t offset, c, r, index, offset2; + igraph_int_t tocols = to->ncol, fromcols = from->ncol; + igraph_int_t torows = to->nrow, fromrows = from->nrow; + igraph_int_t offset, c, r, index, offset2; if (tocols != fromcols) { IGRAPH_ERROR("Cannot do rbind, number of columns do not match", IGRAPH_EINVAL); } - igraph_integer_t new_size; /* new_size = tocols * (fromrows + torows) */ + igraph_int_t new_size; /* new_size = tocols * (fromrows + torows) */ IGRAPH_SAFE_ADD(fromrows, torows, &new_size); IGRAPH_SAFE_MULT(tocols, new_size, &new_size); IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(&to->data, new_size)); @@ -1056,13 +1054,13 @@ igraph_error_t FUNCTION(igraph_matrix, rbind)(TYPE(igraph_matrix) *to, igraph_error_t FUNCTION(igraph_matrix, cbind)(TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from) { - igraph_integer_t tocols = to->ncol, fromcols = from->ncol; - igraph_integer_t torows = to->nrow, fromrows = from->nrow; + igraph_int_t tocols = to->ncol, fromcols = from->ncol; + igraph_int_t torows = to->nrow, fromrows = from->nrow; if (torows != fromrows) { IGRAPH_ERROR("Cannot do rbind, number of rows do not match", IGRAPH_EINVAL); } - igraph_integer_t new_tocols; + igraph_int_t new_tocols; IGRAPH_SAFE_ADD(tocols, fromcols, &new_tocols); IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(to, torows, new_tocols)); @@ -1083,7 +1081,7 @@ igraph_error_t FUNCTION(igraph_matrix, cbind)(TYPE(igraph_matrix) *to, */ void FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igraph_matrix) *m2) { - igraph_integer_t tmp; + igraph_int_t tmp; tmp = m1->nrow; m1->nrow = m2->nrow; @@ -1111,9 +1109,9 @@ void FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igraph_matrix) */ igraph_error_t FUNCTION(igraph_matrix, get_row)(const TYPE(igraph_matrix) *m, - TYPE(igraph_vector) *res, igraph_integer_t index) { - igraph_integer_t rows = m->nrow, cols = m->ncol; - igraph_integer_t i, j; + TYPE(igraph_vector) *res, igraph_int_t index) { + igraph_int_t rows = m->nrow, cols = m->ncol; + igraph_int_t i, j; if (index >= rows) { IGRAPH_ERROR("Index out of range for selecting matrix row", IGRAPH_EINVAL); @@ -1143,8 +1141,8 @@ igraph_error_t FUNCTION(igraph_matrix, get_row)(const TYPE(igraph_matrix) *m, */ igraph_error_t FUNCTION(igraph_matrix, set_row)(TYPE(igraph_matrix) *m, - const TYPE(igraph_vector) *v, igraph_integer_t index) { - const igraph_integer_t rows = m->nrow, cols = m->ncol; + const TYPE(igraph_vector) *v, igraph_int_t index) { + const igraph_int_t rows = m->nrow, cols = m->ncol; if (index >= rows) { IGRAPH_ERROR("Index out of range for selecting matrix row.", IGRAPH_EINVAL); @@ -1152,7 +1150,7 @@ igraph_error_t FUNCTION(igraph_matrix, set_row)(TYPE(igraph_matrix) *m, if (FUNCTION(igraph_vector, size)(v) != cols) { IGRAPH_ERROR("Cannot set matrix row, invalid vector length.", IGRAPH_EINVAL); } - for (igraph_integer_t i = index, j = 0; j < cols; i += rows, j++) { + for (igraph_int_t i = index, j = 0; j < cols; i += rows, j++) { VECTOR(m->data)[i] = VECTOR(*v)[j]; } return IGRAPH_SUCCESS; @@ -1175,8 +1173,8 @@ igraph_error_t FUNCTION(igraph_matrix, set_row)(TYPE(igraph_matrix) *m, */ igraph_error_t FUNCTION(igraph_matrix, set_col)(TYPE(igraph_matrix) *m, - const TYPE(igraph_vector) *v, igraph_integer_t index) { - const igraph_integer_t rows = m->nrow, cols = m->ncol; + const TYPE(igraph_vector) *v, igraph_int_t index) { + const igraph_int_t rows = m->nrow, cols = m->ncol; if (index >= cols) { IGRAPH_ERROR("Index out of range for setting matrix column.", IGRAPH_EINVAL); @@ -1184,7 +1182,7 @@ igraph_error_t FUNCTION(igraph_matrix, set_col)(TYPE(igraph_matrix) *m, if (FUNCTION(igraph_vector, size)(v) != rows) { IGRAPH_ERROR("Cannot set matrix column, invalid vector length.", IGRAPH_EINVAL); } - for (igraph_integer_t i = index * rows, j = 0; j < rows; i++, j++) { + for (igraph_int_t i = index * rows, j = 0; j < rows; i++, j++) { VECTOR(m->data)[i] = VECTOR(*v)[j]; } return IGRAPH_SUCCESS; @@ -1204,9 +1202,9 @@ igraph_error_t FUNCTION(igraph_matrix, set_col)(TYPE(igraph_matrix) *m, */ igraph_error_t FUNCTION(igraph_matrix, swap_rows)(TYPE(igraph_matrix) *m, - igraph_integer_t i, igraph_integer_t j) { - const igraph_integer_t ncol = m->ncol, nrow = m->nrow; - const igraph_integer_t n = nrow * ncol; + igraph_int_t i, igraph_int_t j) { + const igraph_int_t ncol = m->ncol, nrow = m->nrow; + const igraph_int_t n = nrow * ncol; if (i >= nrow || j >= nrow) { IGRAPH_ERROR("Cannot swap rows, index out of range", IGRAPH_EINVAL); @@ -1214,7 +1212,7 @@ igraph_error_t FUNCTION(igraph_matrix, swap_rows)(TYPE(igraph_matrix) *m, if (i == j) { return IGRAPH_SUCCESS; } - for (igraph_integer_t index1 = i, index2 = j; index1 < n; index1 += nrow, index2 += nrow) { + for (igraph_int_t index1 = i, index2 = j; index1 < n; index1 += nrow, index2 += nrow) { BASE tmp; tmp = VECTOR(m->data)[index1]; VECTOR(m->data)[index1] = VECTOR(m->data)[index2]; @@ -1237,8 +1235,8 @@ igraph_error_t FUNCTION(igraph_matrix, swap_rows)(TYPE(igraph_matrix) *m, */ igraph_error_t FUNCTION(igraph_matrix, swap_cols)(TYPE(igraph_matrix) *m, - igraph_integer_t i, igraph_integer_t j) { - const igraph_integer_t ncol = m->ncol, nrow = m->nrow; + igraph_int_t i, igraph_int_t j) { + const igraph_int_t ncol = m->ncol, nrow = m->nrow; if (i >= ncol || j >= ncol) { IGRAPH_ERROR("Cannot swap columns, index out of range.", IGRAPH_EINVAL); @@ -1246,7 +1244,7 @@ igraph_error_t FUNCTION(igraph_matrix, swap_cols)(TYPE(igraph_matrix) *m, if (i == j) { return IGRAPH_SUCCESS; } - for (igraph_integer_t index1 = i * nrow, index2 = j * nrow, k = 0; k < nrow; k++, index1++, index2++) { + for (igraph_int_t index1 = i * nrow, index2 = j * nrow, k = 0; k < nrow; k++, index1++, index2++) { BASE tmp = VECTOR(m->data)[index1]; VECTOR(m->data)[index1] = VECTOR(m->data)[index2]; VECTOR(m->data)[index2] = tmp; @@ -1380,17 +1378,17 @@ igraph_real_t FUNCTION(igraph_matrix, min)(const TYPE(igraph_matrix) *m) { * NaN values, the indices of the first NaN value are returned. * * \param m The matrix. - * \param i Pointer to an igraph_integer_t. The row index of the + * \param i Pointer to an igraph_int_t. The row index of the * minimum is stored here. - * \param j Pointer to an igraph_integer_t. The column index of + * \param j Pointer to an igraph_int_t. The column index of * the minimum is stored here. * * Time complexity: O(mn), the number of elements. */ void FUNCTION(igraph_matrix, which_min)( - const TYPE(igraph_matrix) *m, igraph_integer_t *i, igraph_integer_t *j) { - igraph_integer_t vmin = FUNCTION(igraph_vector, which_min)(&m->data); + const TYPE(igraph_matrix) *m, igraph_int_t *i, igraph_int_t *j) { + igraph_int_t vmin = FUNCTION(igraph_vector, which_min)(&m->data); *i = vmin % m->nrow; *j = vmin / m->nrow; } @@ -1404,17 +1402,17 @@ void FUNCTION(igraph_matrix, which_min)( * NaN values, the indices of the first NaN value are returned. * * \param m The matrix. - * \param i Pointer to an igraph_integer_t. The row index of the + * \param i Pointer to an igraph_int_t. The row index of the * maximum is stored here. - * \param j Pointer to an igraph_integer_t. The column index of + * \param j Pointer to an igraph_int_t. The column index of * the maximum is stored here. * * Time complexity: O(mn), the number of elements. */ void FUNCTION(igraph_matrix, which_max)( - const TYPE(igraph_matrix) *m, igraph_integer_t *i, igraph_integer_t *j) { - igraph_integer_t vmax = FUNCTION(igraph_vector, which_max)(&m->data); + const TYPE(igraph_matrix) *m, igraph_int_t *i, igraph_int_t *j) { + igraph_int_t vmax = FUNCTION(igraph_vector, which_max)(&m->data); *i = vmax % m->nrow; *j = vmax / m->nrow; } @@ -1451,22 +1449,22 @@ void FUNCTION(igraph_matrix, minmax)(const TYPE(igraph_matrix) *m, * will point to the first NaN value. * * \param m The input matrix. - * \param imin Pointer to an igraph_integer_t, the row index of + * \param imin Pointer to an igraph_int_t, the row index of * the minimum is stored here. - * \param jmin Pointer to an igraph_integer_t, the column index of + * \param jmin Pointer to an igraph_int_t, the column index of * the minimum is stored here. - * \param imax Pointer to an igraph_integer_t, the row index of + * \param imax Pointer to an igraph_int_t, the row index of * the maximum is stored here. - * \param jmax Pointer to an igraph_integer_t, the column index of + * \param jmax Pointer to an igraph_int_t, the column index of * the maximum is stored here. * * Time complexity: O(mn), the number of elements. */ void FUNCTION(igraph_matrix, which_minmax)(const TYPE(igraph_matrix) *m, - igraph_integer_t *imin, igraph_integer_t *jmin, - igraph_integer_t *imax, igraph_integer_t *jmax) { - igraph_integer_t vmin, vmax; + igraph_int_t *imin, igraph_int_t *jmin, + igraph_int_t *imax, igraph_int_t *jmax) { + igraph_int_t vmin, vmax; FUNCTION(igraph_vector, which_minmax)(&m->data, &vmin, &vmax); *imin = vmin % m->nrow; *jmin = vmin / m->nrow; @@ -1527,12 +1525,12 @@ igraph_bool_t FUNCTION(igraph_matrix, empty)(const TYPE(igraph_matrix) *m) { igraph_bool_t FUNCTION(igraph_matrix, is_symmetric)(const TYPE(igraph_matrix) *m) { - const igraph_integer_t n = m->nrow; + const igraph_int_t n = m->nrow; if (m->ncol != n) { return false; } - for (igraph_integer_t r = 1; r < n; r++) { - for (igraph_integer_t c = 0; c < r; c++) { + for (igraph_int_t r = 1; r < n; r++) { + for (igraph_int_t c = 0; c < r; c++) { BASE a1 = MATRIX(*m, r, c); BASE a2 = MATRIX(*m, c, r); #ifdef EQ @@ -1582,12 +1580,12 @@ BASE FUNCTION(igraph_matrix, prod)(const TYPE(igraph_matrix) *m) { igraph_error_t FUNCTION(igraph_matrix, rowsum)(const TYPE(igraph_matrix) *m, TYPE(igraph_vector) *res) { - const igraph_integer_t nrow = m->nrow, ncol = m->ncol; + const igraph_int_t nrow = m->nrow, ncol = m->ncol; IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(res, nrow)); FUNCTION(igraph_vector, null)(res); /* Iterate in column-major order for better performance. */ - for (igraph_integer_t c = 0; c < ncol; c++) { - for (igraph_integer_t r = 0; r < nrow; r++) { + for (igraph_int_t c = 0; c < ncol; c++) { + for (igraph_int_t r = 0; r < nrow; r++) { #ifdef SUM SUM(VECTOR(*res)[r], VECTOR(*res)[r], MATRIX(*m, r, c)); #else @@ -1614,11 +1612,11 @@ igraph_error_t FUNCTION(igraph_matrix, rowsum)(const TYPE(igraph_matrix) *m, igraph_error_t FUNCTION(igraph_matrix, colsum)(const TYPE(igraph_matrix) *m, TYPE(igraph_vector) *res) { - const igraph_integer_t nrow = m->nrow, ncol = m->ncol; + const igraph_int_t nrow = m->nrow, ncol = m->ncol; IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(res, ncol)); - for (igraph_integer_t c = 0; c < ncol; c++) { + for (igraph_int_t c = 0; c < ncol; c++) { BASE sum = ZERO; - for (igraph_integer_t r = 0; r < nrow; r++) { + for (igraph_int_t r = 0; r < nrow; r++) { #ifdef SUM SUM(sum, sum, MATRIX(*m, r, c)); #else @@ -1658,11 +1656,11 @@ igraph_bool_t FUNCTION(igraph_matrix, contains)(const TYPE(igraph_matrix) *m, * \param from The position to search from, the positions are * enumerated columnwise. * \param what The element to search for. - * \param pos Pointer to an igraph_integer_t. If the element is + * \param pos Pointer to an igraph_int_t. If the element is * found, then this is set to the position of its first appearance. - * \param row Pointer to an igraph_integer_t. If the element is + * \param row Pointer to an igraph_int_t. If the element is * found, then this is set to its row index. - * \param col Pointer to an igraph_integer_t. If the element is + * \param col Pointer to an igraph_int_t. If the element is * found, then this is set to its column index. * \return Boolean, \c true if the element is found, \c false * otherwise. @@ -1671,8 +1669,8 @@ igraph_bool_t FUNCTION(igraph_matrix, contains)(const TYPE(igraph_matrix) *m, */ igraph_bool_t FUNCTION(igraph_matrix, search)(const TYPE(igraph_matrix) *m, - igraph_integer_t from, BASE what, igraph_integer_t *pos, - igraph_integer_t *row, igraph_integer_t *col) { + igraph_int_t from, BASE what, igraph_int_t *pos, + igraph_int_t *row, igraph_int_t *col) { igraph_bool_t find = FUNCTION(igraph_vector, search)(&m->data, from, what, pos); if (find) { *row = *pos % m->nrow; @@ -1693,9 +1691,9 @@ igraph_bool_t FUNCTION(igraph_matrix, search)(const TYPE(igraph_matrix) *m, * Time complexity: O(mn), the number of elements in the matrix. */ -igraph_error_t FUNCTION(igraph_matrix, remove_row)(TYPE(igraph_matrix) *m, igraph_integer_t row) { +igraph_error_t FUNCTION(igraph_matrix, remove_row)(TYPE(igraph_matrix) *m, igraph_int_t row) { - igraph_integer_t c, r, index = row + 1, leap = 1, n = m->nrow * m->ncol; + igraph_int_t c, r, index = row + 1, leap = 1, n = m->nrow * m->ncol; if (row >= m->nrow) { IGRAPH_ERROR("Cannot remove row, index out of range", IGRAPH_EINVAL); } @@ -1734,9 +1732,9 @@ igraph_error_t FUNCTION(igraph_matrix, remove_row)(TYPE(igraph_matrix) *m, igrap igraph_error_t FUNCTION(igraph_matrix, select_cols)(const TYPE(igraph_matrix) *m, TYPE(igraph_matrix) *res, const igraph_vector_int_t *cols) { - igraph_integer_t ncols = igraph_vector_int_size(cols); - igraph_integer_t nrows = m->nrow; - igraph_integer_t i, j; + igraph_int_t ncols = igraph_vector_int_size(cols); + igraph_int_t nrows = m->nrow; + igraph_int_t i, j; IGRAPH_CHECK(FUNCTION(igraph_matrix, resize)(res, nrows, ncols)); /* Iterate in column-major order for better performance. */ @@ -1752,9 +1750,9 @@ igraph_error_t FUNCTION(igraph_matrix, select_cols)(const TYPE(igraph_matrix) *m #ifndef USING_R igraph_error_t FUNCTION(igraph_matrix, printf)(const TYPE(igraph_matrix) *m, const char *format) { - igraph_integer_t nr = FUNCTION(igraph_matrix, nrow)(m); - igraph_integer_t nc = FUNCTION(igraph_matrix, ncol)(m); - igraph_integer_t i, j; + igraph_int_t nr = FUNCTION(igraph_matrix, nrow)(m); + igraph_int_t nc = FUNCTION(igraph_matrix, ncol)(m); + igraph_int_t i, j; for (i = 0; i < nr; i++) { for (j = 0; j < nc; j++) { @@ -1782,9 +1780,9 @@ igraph_error_t FUNCTION(igraph_matrix, print)(const TYPE(igraph_matrix) *m) { #endif /* USING_R */ igraph_error_t FUNCTION(igraph_matrix, fprint)(const TYPE(igraph_matrix) *m, FILE *file) { - igraph_integer_t nr = FUNCTION(igraph_matrix, nrow)(m); - igraph_integer_t nc = FUNCTION(igraph_matrix, ncol)(m); - igraph_integer_t i, j; + igraph_int_t nr = FUNCTION(igraph_matrix, nrow)(m); + igraph_int_t nc = FUNCTION(igraph_matrix, ncol)(m); + igraph_int_t i, j; igraph_vector_int_t column_width; #ifdef OUT_FORMAT diff --git a/src/vendor/cigraph/src/core/matrix_list.c b/src/vendor/cigraph/src/core/matrix_list.c index 0dd8d4cda3f..5d6b295f8a2 100644 --- a/src/vendor/cigraph/src/core/matrix_list.c +++ b/src/vendor/cigraph/src/core/matrix_list.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/core/memory.c b/src/vendor/cigraph/src/core/memory.c index b3e244c0592..f6164f793f0 100644 --- a/src/vendor/cigraph/src/core/memory.c +++ b/src/vendor/cigraph/src/core/memory.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2024 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/core/printing.c b/src/vendor/cigraph/src/core/printing.c index 181039d453d..8c82ae84b23 100644 --- a/src/vendor/cigraph/src/core/printing.c +++ b/src/vendor/cigraph/src/core/printing.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/core/progress.c b/src/vendor/cigraph/src/core/progress.c index 4a547d21072..11725f1a8ab 100644 --- a/src/vendor/cigraph/src/core/progress.c +++ b/src/vendor/cigraph/src/core/progress.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/core/psumtree.c b/src/vendor/cigraph/src/core/psumtree.c index 96c74c353d6..5d9384149fb 100644 --- a/src/vendor/cigraph/src/core/psumtree.c +++ b/src/vendor/cigraph/src/core/psumtree.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA Copyright (C) 2006 Elliot Paquette @@ -86,8 +86,8 @@ * * Time complexity: O(n) for a tree containing n elements */ -igraph_error_t igraph_psumtree_init(igraph_psumtree_t *t, igraph_integer_t size) { - igraph_integer_t vecsize; +igraph_error_t igraph_psumtree_init(igraph_psumtree_t *t, igraph_int_t size) { + igraph_int_t vecsize; IGRAPH_ASSERT(size > 0); @@ -145,7 +145,7 @@ void igraph_psumtree_destroy(igraph_psumtree_t *t) { * * Time complexity: O(1) */ -igraph_real_t igraph_psumtree_get(const igraph_psumtree_t *t, igraph_integer_t idx) { +igraph_real_t igraph_psumtree_get(const igraph_psumtree_t *t, igraph_int_t idx) { const igraph_vector_t *tree = &t->v; return VECTOR(*tree)[t->offset + idx]; } @@ -176,11 +176,11 @@ igraph_real_t igraph_psumtree_get(const igraph_psumtree_t *t, igraph_integer_t i * * Time complexity: O(log n), where n is the number of items in the tree. */ -igraph_error_t igraph_psumtree_search(const igraph_psumtree_t *t, igraph_integer_t *idx, +igraph_error_t igraph_psumtree_search(const igraph_psumtree_t *t, igraph_int_t *idx, igraph_real_t search) { const igraph_vector_t *tree = &t->v; - igraph_integer_t i = 1; - igraph_integer_t size = igraph_vector_size(tree); + igraph_int_t i = 1; + igraph_int_t size = igraph_vector_size(tree); IGRAPH_ASSERT(search >= 0); IGRAPH_ASSERT(search < igraph_psumtree_sum(t)); @@ -215,7 +215,7 @@ igraph_error_t igraph_psumtree_search(const igraph_psumtree_t *t, igraph_integer * * Time complexity: O(log n), where n is the number of items in the tree. */ -igraph_error_t igraph_psumtree_update(igraph_psumtree_t *t, igraph_integer_t idx, +igraph_error_t igraph_psumtree_update(igraph_psumtree_t *t, igraph_int_t idx, igraph_real_t new_value) { const igraph_vector_t *tree = &t->v; igraph_real_t difference; @@ -248,7 +248,7 @@ igraph_error_t igraph_psumtree_update(igraph_psumtree_t *t, igraph_integer_t idx * * Time complexity: O(1). */ -igraph_integer_t igraph_psumtree_size(const igraph_psumtree_t *t) { +igraph_int_t igraph_psumtree_size(const igraph_psumtree_t *t) { return t->size; } diff --git a/src/vendor/cigraph/src/core/set.c b/src/vendor/cigraph/src/core/set.c index a6be5a0964e..5bcfc52aba0 100644 --- a/src/vendor/cigraph/src/core/set.c +++ b/src/vendor/cigraph/src/core/set.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -42,12 +42,12 @@ * Time complexity: operating system dependent, should be around * O(n), n is the expected size of the set. */ -igraph_error_t igraph_set_init(igraph_set_t *set, igraph_integer_t capacity) { - igraph_integer_t alloc_size; +igraph_error_t igraph_set_init(igraph_set_t *set, igraph_int_t capacity) { + igraph_int_t alloc_size; IGRAPH_ASSERT(capacity >= 0); alloc_size = capacity > 0 ? capacity : 1; - set->stor_begin = IGRAPH_CALLOC(alloc_size, igraph_integer_t); + set->stor_begin = IGRAPH_CALLOC(alloc_size, igraph_int_t); if (! set->stor_begin) { IGRAPH_ERROR("Cannot initialize set.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -105,16 +105,16 @@ igraph_bool_t igraph_set_inited(igraph_set_t *set) { * Time complexity: operating system dependent, should be around * O(n), n is the new allocated size of the set. */ -igraph_error_t igraph_set_reserve(igraph_set_t *set, igraph_integer_t capacity) { - igraph_integer_t actual_size = igraph_set_size(set); - igraph_integer_t *tmp; +igraph_error_t igraph_set_reserve(igraph_set_t *set, igraph_int_t capacity) { + igraph_int_t actual_size = igraph_set_size(set); + igraph_int_t *tmp; IGRAPH_ASSERT(set != NULL); IGRAPH_ASSERT(set->stor_begin != NULL); if (capacity <= actual_size) { return IGRAPH_SUCCESS; } - tmp = IGRAPH_REALLOC(set->stor_begin, capacity, igraph_integer_t); + tmp = IGRAPH_REALLOC(set->stor_begin, capacity, igraph_int_t); IGRAPH_CHECK_OOM(tmp, "Cannot reserve space for set."); set->stor_begin = tmp; @@ -174,7 +174,7 @@ void igraph_set_clear(igraph_set_t *set) { * Time complexity: O(1). */ -igraph_integer_t igraph_set_size(const igraph_set_t *set) { +igraph_int_t igraph_set_size(const igraph_set_t *set) { IGRAPH_ASSERT(set != NULL); IGRAPH_ASSERT(set->stor_begin != NULL); return set->end - set->stor_begin; @@ -193,9 +193,9 @@ igraph_integer_t igraph_set_size(const igraph_set_t *set) { * * Time complexity: O(log(n)), n is the number of elements in \p set. */ -igraph_error_t igraph_set_add(igraph_set_t *set, igraph_integer_t e) { - igraph_integer_t left, right, middle; - igraph_integer_t size; +igraph_error_t igraph_set_add(igraph_set_t *set, igraph_int_t e) { + igraph_int_t left, right, middle; + igraph_int_t size; IGRAPH_ASSERT(set != NULL); IGRAPH_ASSERT(set->stor_begin != NULL); @@ -226,7 +226,7 @@ igraph_error_t igraph_set_add(igraph_set_t *set, igraph_integer_t e) { if (left >= size || set->stor_begin[left] != e) { /* full, allocate more storage */ if (set->stor_end == set->end) { - igraph_integer_t new_size = size < IGRAPH_INTEGER_MAX/2 ? size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t new_size = size < IGRAPH_INTEGER_MAX/2 ? size * 2 : IGRAPH_INTEGER_MAX; if (size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot add to set, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -259,8 +259,8 @@ igraph_error_t igraph_set_add(igraph_set_t *set, igraph_integer_t e) { * * Time complexity: O(log(n)), n is the number of elements in \p set. */ -igraph_bool_t igraph_set_contains(const igraph_set_t *set, igraph_integer_t e) { - igraph_integer_t left, right, middle; +igraph_bool_t igraph_set_contains(const igraph_set_t *set, igraph_int_t e) { + igraph_int_t left, right, middle; IGRAPH_ASSERT(set != NULL); IGRAPH_ASSERT(set->stor_begin != NULL); @@ -296,7 +296,7 @@ igraph_bool_t igraph_set_contains(const igraph_set_t *set, igraph_integer_t e) { * * \param set The set object. * \param state Internal state of the iteration. - * This should be a pointer to a \type igraph_integer_t variable + * This should be a pointer to a \type igraph_int_t variable * which must be zero for the first invocation. * The object must not be adjusted and its value should * not be used for anything during the iteration. @@ -305,8 +305,8 @@ igraph_bool_t igraph_set_contains(const igraph_set_t *set, igraph_integer_t e) { * * \return True if there are more elements, false otherwise. */ -igraph_bool_t igraph_set_iterate(const igraph_set_t *set, igraph_integer_t *state, - igraph_integer_t *element) { +igraph_bool_t igraph_set_iterate(const igraph_set_t *set, igraph_int_t *state, + igraph_int_t *element) { IGRAPH_ASSERT(set != 0); IGRAPH_ASSERT(set->stor_begin != 0); IGRAPH_ASSERT(state != 0); diff --git a/src/vendor/cigraph/src/core/set.h b/src/vendor/cigraph/src/core/set.h index 63d4f16dab3..5ac0cdac7cc 100644 --- a/src/vendor/cigraph/src/core/set.h +++ b/src/vendor/cigraph/src/core/set.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,9 +35,9 @@ IGRAPH_BEGIN_C_DECLS */ typedef struct s_set { - igraph_integer_t* stor_begin; - igraph_integer_t* stor_end; - igraph_integer_t* end; + igraph_int_t* stor_begin; + igraph_int_t* stor_end; + igraph_int_t* end; } igraph_set_t; #define IGRAPH_SET_NULL { 0,0,0 } @@ -45,18 +45,18 @@ typedef struct s_set { do { IGRAPH_CHECK(igraph_set_init(v, size)); \ IGRAPH_FINALLY(igraph_set_destroy, v); } while (0) -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_init(igraph_set_t *set, igraph_integer_t capacity); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_init(igraph_set_t *set, igraph_int_t capacity); IGRAPH_PRIVATE_EXPORT void igraph_set_destroy(igraph_set_t *set); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_set_inited(igraph_set_t *set); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_reserve(igraph_set_t *set, igraph_integer_t capacity); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_reserve(igraph_set_t *set, igraph_int_t capacity); IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_set_empty(const igraph_set_t *set); IGRAPH_PRIVATE_EXPORT void igraph_set_clear(igraph_set_t *set); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_set_size(const igraph_set_t *set); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_add(igraph_set_t *set, igraph_integer_t e); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_set_contains(const igraph_set_t *set, igraph_integer_t e); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_set_size(const igraph_set_t *set); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_add(igraph_set_t *set, igraph_int_t e); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_set_contains(const igraph_set_t *set, igraph_int_t e); IGRAPH_PRIVATE_EXPORT igraph_bool_t igraph_set_iterate(const igraph_set_t *set, - igraph_integer_t *state, - igraph_integer_t *element); + igraph_int_t *state, + igraph_int_t *element); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/core/setup.c b/src/vendor/cigraph/src/core/setup.c index 729f36704cc..bef69f0d2f9 100644 --- a/src/vendor/cigraph/src/core/setup.c +++ b/src/vendor/cigraph/src/core/setup.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -65,4 +65,3 @@ igraph_error_t igraph_setup(void) { IGRAPH_CHECK(setup_rng()); return IGRAPH_SUCCESS; } - diff --git a/src/vendor/cigraph/src/core/sparsemat.c b/src/vendor/cigraph/src/core/sparsemat.c index fdd8accdc18..f946467ca87 100644 --- a/src/vendor/cigraph/src/core/sparsemat.c +++ b/src/vendor/cigraph/src/core/sparsemat.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -22,9 +22,6 @@ #include "igraph_sparsemat.h" -#include "igraph_attributes.h" -#include "igraph_constructors.h" -#include "igraph_interface.h" #include "igraph_memory.h" #include "igraph_types.h" @@ -108,9 +105,9 @@ static CS_INT igraph_i_sparsemat_count_elements(const igraph_sparsemat_t* A) { * Time complexity: TODO. */ -igraph_error_t igraph_sparsemat_init(igraph_sparsemat_t *A, igraph_integer_t rows, - igraph_integer_t cols, igraph_integer_t nzmax) { - IGRAPH_STATIC_ASSERT(sizeof(igraph_integer_t) == sizeof(CS_INT)); +igraph_error_t igraph_sparsemat_init(igraph_sparsemat_t *A, igraph_int_t rows, + igraph_int_t cols, igraph_int_t nzmax) { + IGRAPH_STATIC_ASSERT(sizeof(igraph_int_t) == sizeof(CS_INT)); IGRAPH_STATIC_ASSERT(sizeof(igraph_real_t) == sizeof(CS_ENTRY)); if (rows < 0) { @@ -201,7 +198,7 @@ void igraph_sparsemat_destroy(igraph_sparsemat_t *A) { * Time complexity: TODO. */ -igraph_error_t igraph_sparsemat_realloc(igraph_sparsemat_t *A, igraph_integer_t nzmax) { +igraph_error_t igraph_sparsemat_realloc(igraph_sparsemat_t *A, igraph_int_t nzmax) { if (!cs_sprealloc(A->cs, nzmax)) { IGRAPH_ERROR("Could not allocate more memory for sparse matrix.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -218,7 +215,7 @@ igraph_error_t igraph_sparsemat_realloc(igraph_sparsemat_t *A, igraph_integer_t * Time complexity: O(1). */ -igraph_integer_t igraph_sparsemat_nrow(const igraph_sparsemat_t *A) { +igraph_int_t igraph_sparsemat_nrow(const igraph_sparsemat_t *A) { return A->cs->m; } @@ -232,7 +229,7 @@ igraph_integer_t igraph_sparsemat_nrow(const igraph_sparsemat_t *A) { * Time complexity: O(1). */ -igraph_integer_t igraph_sparsemat_ncol(const igraph_sparsemat_t *A) { +igraph_int_t igraph_sparsemat_ncol(const igraph_sparsemat_t *A) { return A->cs->n; } @@ -345,8 +342,8 @@ static igraph_error_t igraph_i_sparsemat_index_rows(const igraph_sparsemat_t *A, igraph_sparsemat_t II, II2; CS_INT nrow = A->cs->m; - igraph_integer_t idx_rows = igraph_vector_int_size(p); - igraph_integer_t k; + igraph_int_t idx_rows = igraph_vector_int_size(p); + igraph_int_t k; /* Create index matrix */ IGRAPH_CHECK(igraph_sparsemat_init(&II2, idx_rows, nrow, idx_rows)); @@ -382,8 +379,8 @@ static igraph_error_t igraph_i_sparsemat_index_cols(const igraph_sparsemat_t *A, igraph_sparsemat_t JJ, JJ2; CS_INT ncol = A->cs->n; - igraph_integer_t idx_cols = igraph_vector_int_size(q); - igraph_integer_t k; + igraph_int_t idx_cols = igraph_vector_int_size(q); + igraph_int_t k; /* Create index matrix */ IGRAPH_CHECK(igraph_sparsemat_init(&JJ2, ncol, idx_cols, idx_cols)); @@ -448,9 +445,9 @@ igraph_error_t igraph_sparsemat_index(const igraph_sparsemat_t *A, igraph_sparsemat_t II, JJ, II2, JJ2, tmp; CS_INT nrow = A->cs->m; CS_INT ncol = A->cs->n; - igraph_integer_t idx_rows = p ? igraph_vector_int_size(p) : -1; - igraph_integer_t idx_cols = q ? igraph_vector_int_size(q) : -1; - igraph_integer_t k; + igraph_int_t idx_rows = p ? igraph_vector_int_size(p) : -1; + igraph_int_t idx_cols = q ? igraph_vector_int_size(q) : -1; + igraph_int_t k; igraph_sparsemat_t *myres = res, mres; @@ -540,7 +537,7 @@ igraph_error_t igraph_sparsemat_index(const igraph_sparsemat_t *A, */ igraph_error_t igraph_sparsemat_entry(igraph_sparsemat_t *A, - igraph_integer_t row, igraph_integer_t col, igraph_real_t elem) { + igraph_int_t row, igraph_int_t col, igraph_real_t elem) { if (!igraph_sparsemat_is_triplet(A)) { IGRAPH_ERROR("Entries can only be added to sparse matrices that are in triplet format.", IGRAPH_EINVAL); @@ -585,7 +582,7 @@ igraph_error_t igraph_sparsemat_compress(const igraph_sparsemat_t *A, } static igraph_real_t igraph_i_sparsemat_get_cc( - const igraph_sparsemat_t *A, igraph_integer_t row, igraph_integer_t col + const igraph_sparsemat_t *A, igraph_int_t row, igraph_int_t col ) { /* elements in column 'col' are at indices * A->cs->p[col] .. A->cs->p[col+1] (open from right) in @@ -610,7 +607,7 @@ static igraph_real_t igraph_i_sparsemat_get_cc( } static igraph_real_t igraph_i_sparsemat_get_triplet( - const igraph_sparsemat_t *A, igraph_integer_t row, igraph_integer_t col + const igraph_sparsemat_t *A, igraph_int_t row, igraph_int_t col ) { igraph_sparsemat_iterator_t it; igraph_real_t result = 0.0; @@ -642,7 +639,7 @@ static igraph_real_t igraph_i_sparsemat_get_triplet( * Time complexity: TODO. */ igraph_real_t igraph_sparsemat_get( - const igraph_sparsemat_t *A, igraph_integer_t row, igraph_integer_t col + const igraph_sparsemat_t *A, igraph_int_t row, igraph_int_t col ) { if (row < 0 || col < 0 || row >= A->cs->m || col >= A->cs->n) { return 0.0; @@ -689,7 +686,7 @@ igraph_error_t igraph_sparsemat_transpose( static igraph_error_t igraph_i_sparsemat_is_symmetric_cc(const igraph_sparsemat_t *A, igraph_bool_t *result) { igraph_sparsemat_t t, tt; igraph_bool_t res; - igraph_integer_t nz; + igraph_int_t nz; IGRAPH_CHECK(igraph_sparsemat_transpose(A, &t)); IGRAPH_FINALLY(igraph_sparsemat_destroy, &t); @@ -777,7 +774,7 @@ igraph_error_t igraph_sparsemat_dupl(igraph_sparsemat_t *A) { } struct fkeep_wrapper_data { - igraph_integer_t (*fkeep) (igraph_integer_t, igraph_integer_t, igraph_real_t, void*); + igraph_int_t (*fkeep) (igraph_int_t, igraph_int_t, igraph_real_t, void*); void* data; }; @@ -798,8 +795,8 @@ static CS_INT fkeep_wrapper(CS_INT row, CS_INT col, double value, void* data) { * * \param A The input matrix, in column-compressed format. * \param fkeep The filter function. It must take four arguments: the - * first is an \c igraph_integer_t, the row index of the entry, the second is - * another \c igraph_integer_t, the column index. The third is \c igraph_real_t, + * first is an \c igraph_int_t, the row index of the entry, the second is + * another \c igraph_int_t, the column index. The third is \c igraph_real_t, * the value of the entry. The fourth element is a \c void pointer, * the \p other argument is passed here. The function must return * an \c int. If this is zero, then the entry is deleted, otherwise @@ -813,7 +810,7 @@ static CS_INT fkeep_wrapper(CS_INT row, CS_INT col, double value, void* data) { igraph_error_t igraph_sparsemat_fkeep( igraph_sparsemat_t *A, - igraph_integer_t (*fkeep)(igraph_integer_t, igraph_integer_t, igraph_real_t, void*), + igraph_int_t (*fkeep)(igraph_int_t, igraph_int_t, igraph_real_t, void*), void *other ) { struct fkeep_wrapper_data wrapper_data = { @@ -1140,7 +1137,7 @@ igraph_error_t igraph_sparsemat_utsolve(const igraph_sparsemat_t *U, igraph_error_t igraph_sparsemat_cholsol(const igraph_sparsemat_t *A, const igraph_vector_t *b, igraph_vector_t *res, - igraph_integer_t order) { + igraph_int_t order) { if (A->cs->m != A->cs->n) { IGRAPH_ERROR( @@ -1183,7 +1180,7 @@ igraph_error_t igraph_sparsemat_cholsol(const igraph_sparsemat_t *A, igraph_error_t igraph_sparsemat_lusol(const igraph_sparsemat_t *A, const igraph_vector_t *b, igraph_vector_t *res, - igraph_integer_t order, + igraph_int_t order, igraph_real_t tol) { if (A->cs->m != A->cs->n) { @@ -1248,10 +1245,10 @@ igraph_error_t igraph_sparsemat_print(const igraph_sparsemat_t *A, #undef CHECK static igraph_error_t igraph_i_sparsemat_eye_triplet( - igraph_sparsemat_t *A, igraph_integer_t n, igraph_integer_t nzmax, + igraph_sparsemat_t *A, igraph_int_t n, igraph_int_t nzmax, igraph_real_t value ) { - igraph_integer_t i; + igraph_int_t i; IGRAPH_CHECK(igraph_sparsemat_init(A, n, n, nzmax)); @@ -1263,9 +1260,9 @@ static igraph_error_t igraph_i_sparsemat_eye_triplet( } static igraph_error_t igraph_i_sparsemat_eye_cc( - igraph_sparsemat_t *A, igraph_integer_t n, igraph_real_t value + igraph_sparsemat_t *A, igraph_int_t n, igraph_real_t value ) { - igraph_integer_t i; + igraph_int_t i; A->cs = cs_spalloc(n, n, n, /*values=*/ 1, /*triplet=*/ 0); if (!A->cs) { @@ -1301,7 +1298,7 @@ static igraph_error_t igraph_i_sparsemat_eye_cc( */ igraph_error_t igraph_sparsemat_init_eye( - igraph_sparsemat_t *A, igraph_integer_t n, igraph_integer_t nzmax, + igraph_sparsemat_t *A, igraph_int_t n, igraph_int_t nzmax, igraph_real_t value, igraph_bool_t compress ) { if (compress) { @@ -1312,7 +1309,7 @@ igraph_error_t igraph_sparsemat_init_eye( } static igraph_error_t igraph_i_sparsemat_init_diag_triplet( - igraph_sparsemat_t *A, igraph_integer_t nzmax, const igraph_vector_t *values + igraph_sparsemat_t *A, igraph_int_t nzmax, const igraph_vector_t *values ) { CS_INT i, n = igraph_vector_size(values); @@ -1367,7 +1364,7 @@ static igraph_error_t igraph_i_sparsemat_init_diag_cc(igraph_sparsemat_t *A, */ igraph_error_t igraph_sparsemat_init_diag( - igraph_sparsemat_t *A, igraph_integer_t nzmax, const igraph_vector_t *values, + igraph_sparsemat_t *A, igraph_int_t nzmax, const igraph_vector_t *values, igraph_bool_t compress ) { if (compress) { @@ -1382,11 +1379,12 @@ static igraph_error_t igraph_i_sparsemat_arpack_multiply(igraph_real_t *to, int n, void *extra) { igraph_sparsemat_t *A = extra; - igraph_vector_t vto, vfrom; - igraph_vector_view(&vto, to, n); - igraph_vector_view(&vfrom, from, n); + const igraph_vector_t vfrom = igraph_vector_view(from, n); + igraph_vector_t vto = igraph_vector_view(to, n); + igraph_vector_null(&vto); IGRAPH_CHECK(igraph_sparsemat_gaxpy(A, &vfrom, &vto)); + return IGRAPH_SUCCESS; } @@ -1403,10 +1401,8 @@ static igraph_error_t igraph_i_sparsemat_arpack_solve(igraph_real_t *to, void *extra) { igraph_i_sparsemat_arpack_rssolve_data_t *data = extra; - igraph_vector_t vfrom, vto; - - igraph_vector_view(&vfrom, from, n); - igraph_vector_view(&vto, to, n); + const igraph_vector_t vfrom = igraph_vector_view(from, n); + igraph_vector_t vto = igraph_vector_view(to, n); if (data->method == IGRAPH_SPARSEMAT_SOLVE_LU) { IGRAPH_CHECK(igraph_sparsemat_luresol(data->dis, data->din, &vfrom, @@ -1458,7 +1454,7 @@ igraph_error_t igraph_sparsemat_arpack_rssolve(const igraph_sparsemat_t *A, igraph_matrix_t *vectors, igraph_sparsemat_solve_t solvemethod) { - igraph_integer_t n = igraph_sparsemat_nrow(A); + igraph_int_t n = igraph_sparsemat_nrow(A); if (n != igraph_sparsemat_ncol(A)) { IGRAPH_ERROR("Non-square matrix for ARPACK.", IGRAPH_EINVAL); @@ -1562,7 +1558,7 @@ igraph_error_t igraph_sparsemat_arpack_rnsolve(const igraph_sparsemat_t *A, igraph_matrix_t *values, igraph_matrix_t *vectors) { - igraph_integer_t n = igraph_sparsemat_nrow(A); + igraph_int_t n = igraph_sparsemat_nrow(A); if (n > INT_MAX) { IGRAPH_ERROR("Matrix too large for ARPACK.", IGRAPH_EOVERFLOW); @@ -1604,7 +1600,7 @@ igraph_error_t igraph_sparsemat_arpack_rnsolve(const igraph_sparsemat_t *A, * Time complexity: TODO. */ -igraph_error_t igraph_sparsemat_symbqr(igraph_integer_t order, const igraph_sparsemat_t *A, +igraph_error_t igraph_sparsemat_symbqr(igraph_int_t order, const igraph_sparsemat_t *A, igraph_sparsemat_symbolic_t *dis) { dis->symbolic = cs_sqr(order, A->cs, /*qr=*/ 1); @@ -1635,7 +1631,7 @@ igraph_error_t igraph_sparsemat_symbqr(igraph_integer_t order, const igraph_spar * Time complexity: TODO. */ -igraph_error_t igraph_sparsemat_symblu(igraph_integer_t order, const igraph_sparsemat_t *A, +igraph_error_t igraph_sparsemat_symblu(igraph_int_t order, const igraph_sparsemat_t *A, igraph_sparsemat_symbolic_t *dis) { dis->symbolic = cs_sqr(order, A->cs, /*qr=*/ 0); @@ -1729,7 +1725,7 @@ igraph_error_t igraph_sparsemat_luresol(const igraph_sparsemat_symbolic_t *dis, const igraph_sparsemat_numeric_t *din, const igraph_vector_t *b, igraph_vector_t *res) { - igraph_integer_t n = din->numeric->L->n; + igraph_int_t n = din->numeric->L->n; igraph_real_t *workspace; if (res != b) { @@ -1785,9 +1781,9 @@ igraph_error_t igraph_sparsemat_qrresol(const igraph_sparsemat_symbolic_t *dis, const igraph_sparsemat_numeric_t *din, const igraph_vector_t *b, igraph_vector_t *res) { - igraph_integer_t n = din->numeric->L->n; + igraph_int_t n = din->numeric->L->n; igraph_real_t *workspace; - igraph_integer_t k; + igraph_int_t k; if (res != b) { IGRAPH_CHECK(igraph_vector_update(res, b)); @@ -1876,9 +1872,9 @@ void igraph_sparsemat_numeric_destroy(igraph_sparsemat_numeric_t *din) { igraph_error_t igraph_matrix_as_sparsemat(igraph_sparsemat_t *res, const igraph_matrix_t *mat, igraph_real_t tol) { - igraph_integer_t nrow = igraph_matrix_nrow(mat); - igraph_integer_t ncol = igraph_matrix_ncol(mat); - igraph_integer_t i, j, nzmax = 0; + igraph_int_t nrow = igraph_matrix_nrow(mat); + igraph_int_t ncol = igraph_matrix_ncol(mat); + igraph_int_t i, j, nzmax = 0; for (i = 0; i < nrow; i++) { for (j = 0; j < ncol; j++) { @@ -1904,8 +1900,8 @@ igraph_error_t igraph_matrix_as_sparsemat(igraph_sparsemat_t *res, static igraph_error_t igraph_i_sparsemat_as_matrix_cc(igraph_matrix_t *res, const igraph_sparsemat_t *spmat) { - igraph_integer_t nrow = igraph_sparsemat_nrow(spmat); - igraph_integer_t ncol = igraph_sparsemat_ncol(spmat); + igraph_int_t nrow = igraph_sparsemat_nrow(spmat); + igraph_int_t ncol = igraph_sparsemat_ncol(spmat); CS_INT from = 0, to = 0; CS_INT *p = spmat->cs->p; CS_INT *i = spmat->cs->i; @@ -1931,8 +1927,8 @@ static igraph_error_t igraph_i_sparsemat_as_matrix_cc(igraph_matrix_t *res, static igraph_error_t igraph_i_sparsemat_as_matrix_triplet(igraph_matrix_t *res, const igraph_sparsemat_t *spmat) { - igraph_integer_t nrow = igraph_sparsemat_nrow(spmat); - igraph_integer_t ncol = igraph_sparsemat_ncol(spmat); + igraph_int_t nrow = igraph_sparsemat_nrow(spmat); + igraph_int_t ncol = igraph_sparsemat_ncol(spmat); CS_INT *i = spmat->cs->p; CS_INT *j = spmat->cs->i; CS_ENTRY *x = spmat->cs->x; @@ -2092,10 +2088,10 @@ igraph_error_t igraph_sparsemat_minmax(igraph_sparsemat_t *A, * Time complexity: TODO. */ -igraph_integer_t igraph_sparsemat_count_nonzero(igraph_sparsemat_t *A) { +igraph_int_t igraph_sparsemat_count_nonzero(igraph_sparsemat_t *A) { CS_INT i, n; CS_ENTRY *ptr; - igraph_integer_t res = 0; + igraph_int_t res = 0; IGRAPH_CHECK(igraph_sparsemat_dupl(A)); @@ -2125,11 +2121,11 @@ igraph_integer_t igraph_sparsemat_count_nonzero(igraph_sparsemat_t *A) { * Time complexity: TODO. */ -igraph_integer_t igraph_sparsemat_count_nonzerotol(igraph_sparsemat_t *A, +igraph_int_t igraph_sparsemat_count_nonzerotol(igraph_sparsemat_t *A, igraph_real_t tol) { CS_INT i, n; CS_ENTRY *ptr; - igraph_integer_t res = 0; + igraph_int_t res = 0; IGRAPH_CHECK(igraph_sparsemat_dupl(A)); @@ -2444,7 +2440,7 @@ static igraph_error_t igraph_i_sparsemat_which_min_rows_cc(igraph_sparsemat_t *A CS_ENTRY *px; CS_INT *pp; CS_INT *pi; - igraph_integer_t j; + igraph_int_t j; IGRAPH_CHECK(igraph_sparsemat_dupl(A)); @@ -2510,7 +2506,7 @@ static igraph_error_t igraph_i_sparsemat_which_min_cols_cc(igraph_sparsemat_t *A CS_INT n, j, p; CS_ENTRY *px; double *pr; - igraph_integer_t *ppos; + igraph_int_t *ppos; IGRAPH_CHECK(igraph_sparsemat_dupl(A)); @@ -2643,7 +2639,7 @@ igraph_error_t igraph_sparsemat_scale(igraph_sparsemat_t *A, igraph_real_t by) { * Time complexity: O(1). */ -igraph_error_t igraph_sparsemat_add_rows(igraph_sparsemat_t *A, igraph_integer_t n) { +igraph_error_t igraph_sparsemat_add_rows(igraph_sparsemat_t *A, igraph_int_t n) { A->cs->m += n; return IGRAPH_SUCCESS; } @@ -2661,7 +2657,7 @@ igraph_error_t igraph_sparsemat_add_rows(igraph_sparsemat_t *A, igraph_integer_t * Time complexity: TODO. */ -igraph_error_t igraph_sparsemat_add_cols(igraph_sparsemat_t *A, igraph_integer_t n) { +igraph_error_t igraph_sparsemat_add_cols(igraph_sparsemat_t *A, igraph_int_t n) { if (igraph_sparsemat_is_triplet(A)) { A->cs->n += n; } else { @@ -2697,8 +2693,8 @@ igraph_error_t igraph_sparsemat_add_cols(igraph_sparsemat_t *A, igraph_integer_t * Time complexity: O(nzmax), the maximum number of non-zero elements. */ -igraph_error_t igraph_sparsemat_resize(igraph_sparsemat_t *A, igraph_integer_t nrow, - igraph_integer_t ncol, igraph_integer_t nzmax) { +igraph_error_t igraph_sparsemat_resize(igraph_sparsemat_t *A, igraph_int_t nrow, + igraph_int_t ncol, igraph_int_t nzmax) { if (igraph_sparsemat_is_cc(A)) { igraph_sparsemat_t tmp; @@ -2730,7 +2726,7 @@ igraph_error_t igraph_sparsemat_resize(igraph_sparsemat_t *A, igraph_integer_t n * Time complexity: O(1). */ -igraph_integer_t igraph_sparsemat_nonzero_storage(const igraph_sparsemat_t *A) { +igraph_int_t igraph_sparsemat_nonzero_storage(const igraph_sparsemat_t *A) { return igraph_i_sparsemat_count_elements(A); } @@ -2848,10 +2844,10 @@ igraph_error_t igraph_sparsemat_multiply_by_dense(const igraph_sparsemat_t *A, const igraph_matrix_t *B, igraph_matrix_t *res) { - igraph_integer_t m = igraph_sparsemat_nrow(A); - igraph_integer_t n = igraph_sparsemat_ncol(A); - igraph_integer_t p = igraph_matrix_ncol(B); - igraph_integer_t i; + igraph_int_t m = igraph_sparsemat_nrow(A); + igraph_int_t n = igraph_sparsemat_ncol(A); + igraph_int_t p = igraph_matrix_ncol(B); + igraph_int_t i; if (igraph_matrix_nrow(B) != n) { IGRAPH_ERROR("Invalid dimensions in sparse-dense matrix product", @@ -2874,10 +2870,10 @@ igraph_error_t igraph_sparsemat_multiply_by_dense(const igraph_sparsemat_t *A, igraph_error_t igraph_sparsemat_dense_multiply(const igraph_matrix_t *A, const igraph_sparsemat_t *B, igraph_matrix_t *res) { - igraph_integer_t m = igraph_matrix_nrow(A); - igraph_integer_t n = igraph_matrix_ncol(A); - igraph_integer_t p = igraph_sparsemat_ncol(B); - igraph_integer_t r, c; + igraph_int_t m = igraph_matrix_nrow(A); + igraph_int_t n = igraph_matrix_ncol(A); + igraph_int_t p = igraph_sparsemat_ncol(B); + igraph_int_t r, c; CS_INT *Bp = B->cs->p; if (igraph_sparsemat_nrow(B) != n) { @@ -2895,7 +2891,7 @@ igraph_error_t igraph_sparsemat_dense_multiply(const igraph_matrix_t *A, for (c = 0; c < p; c++) { for (r = 0; r < m; r++) { - igraph_integer_t idx = *Bp; + igraph_int_t idx = *Bp; while (idx < * (Bp + 1)) { MATRIX(*res, r, c) += MATRIX(*A, r, B->cs->i[idx]) * B->cs->x[idx]; idx++; @@ -2907,71 +2903,6 @@ igraph_error_t igraph_sparsemat_dense_multiply(const igraph_matrix_t *A, return IGRAPH_SUCCESS; } -/** - * \function igraph_sparsemat_view - * \brief Initialize a sparse matrix and set all parameters. - * - * This function can be used to temporarily handle existing sparse matrix data, - * usually created by another software library, as an \c igraph_sparsemat_t object, - * and thus avoid unnecessary copying. It supports data stored in either the - * compressed sparse column format, or the (i, j, x) triplet format - * where \c i and \c j are the matrix indices of a non-zero element, and \c x - * is its value. - * - * - * The compressed sparse column (or row) format is commonly used to represent - * sparse matrix data. It consists of three vectors, the \p p column pointers, the - * \p i row indices, and the \p x values. p[k] is the number - * of non-zero entires in matrix columns k-1 and lower. - * p[0] is always zero and p[n] is always the total - * number of non-zero entires in the matrix. i[l] is the row index - * of the \c l-th stored element, while x[l] is its value. - * If a matrix element with indices (j, k) is explicitly stored, - * it must be located between positions p[k] and p[k+1] - 1 - * (inclusive) in the \p i and \p x vectors. - * - * - * Do not call \ref igraph_sparsemat_destroy() on a sparse matrix created with - * this function. Instead, \ref igraph_free() must be called on the \c cs - * field of \p A to free the storage allocated by this function. - * - * - * Warning: Matrices created with this function must not be used with functions - * that may reallocate the underlying storage, such as \ref igraph_sparsemat_entry(). - * - * \param A The non-initialized sparse matrix. - * \param nzmax The maximum number of entries, typically the actual number of entries. - * \param m The number of matrix rows. - * \param n The number of matrix columns. - * \param p For a compressed matrix, this is the column pointer vector, and - * must be of size n+1. For a triplet format matrix, it - * is a vector of column indices and must be of size \p nzmax. - * \param i The row vector. This should contain the row indices of the - * elements in \p x. It must be of size \p nzmax. - * \param x The values of the non-zero elements of the sparse matrix. - * It must be of size \p nzmax. - * \param nz For a compressed matrix, is must be -1. For a triplet format - * matrix, is must contain the number of entries. - * \return Error code. - * - * Time complexity: O(1). - */ - -igraph_error_t igraph_sparsemat_view(igraph_sparsemat_t *A, igraph_integer_t nzmax, igraph_integer_t m, igraph_integer_t n, - igraph_integer_t *p, igraph_integer_t *i, igraph_real_t *x, igraph_integer_t nz) { - - A->cs = IGRAPH_CALLOC(1, cs_igraph); - A->cs->nzmax = nzmax; - A->cs->m = m; - A->cs->n = n; - A->cs->p = (CS_INT*) p; - A->cs->i = (CS_INT*) i; - A->cs->x = x; - A->cs->nz = nz; - - return IGRAPH_SUCCESS; -} - /** * \function igraph_sparsemat_sort @@ -3091,7 +3022,7 @@ igraph_error_t igraph_sparsemat_getelements_sorted(const igraph_sparsemat_t *A, return IGRAPH_SUCCESS; } -igraph_integer_t igraph_sparsemat_nzmax(const igraph_sparsemat_t *A) { +igraph_int_t igraph_sparsemat_nzmax(const igraph_sparsemat_t *A) { return A->cs->nzmax; } @@ -3123,12 +3054,12 @@ igraph_error_t igraph_sparsemat_normalize_cols( igraph_sparsemat_t *sparsemat, igraph_bool_t allow_zeros ) { igraph_vector_t sum; - const igraph_integer_t no_of_nodes = igraph_sparsemat_nrow(sparsemat); + const igraph_int_t no_of_nodes = igraph_sparsemat_nrow(sparsemat); IGRAPH_VECTOR_INIT_FINALLY(&sum, no_of_nodes); IGRAPH_CHECK(igraph_sparsemat_colsums(sparsemat, &sum)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(sum)[i] != 0.0) { VECTOR(sum)[i] = 1.0 / VECTOR(sum)[i]; } else if (!allow_zeros) { @@ -3159,12 +3090,12 @@ igraph_error_t igraph_sparsemat_normalize_rows( igraph_sparsemat_t *sparsemat, igraph_bool_t allow_zeros ) { igraph_vector_t sum; - const igraph_integer_t no_of_nodes = igraph_sparsemat_nrow(sparsemat); + const igraph_int_t no_of_nodes = igraph_sparsemat_nrow(sparsemat); IGRAPH_VECTOR_INIT_FINALLY(&sum, no_of_nodes); IGRAPH_CHECK(igraph_sparsemat_rowsums(sparsemat, &sum)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(sum)[i] != 0.0) { VECTOR(sum)[i] = 1.0 / VECTOR(sum)[i]; } else if (!allow_zeros) { @@ -3249,7 +3180,7 @@ igraph_sparsemat_iterator_end(const igraph_sparsemat_iterator_t *it) { * Time complexity: O(1). */ -igraph_integer_t igraph_sparsemat_iterator_row(const igraph_sparsemat_iterator_t *it) { +igraph_int_t igraph_sparsemat_iterator_row(const igraph_sparsemat_iterator_t *it) { return it->mat->cs->i[it->pos]; } @@ -3263,7 +3194,7 @@ igraph_integer_t igraph_sparsemat_iterator_row(const igraph_sparsemat_iterator_t * Time complexity: O(1). */ -igraph_integer_t igraph_sparsemat_iterator_col(const igraph_sparsemat_iterator_t *it) { +igraph_int_t igraph_sparsemat_iterator_col(const igraph_sparsemat_iterator_t *it) { if (igraph_sparsemat_is_triplet(it->mat)) { return it->mat->cs->p[it->pos]; } else { @@ -3296,7 +3227,7 @@ igraph_sparsemat_iterator_get(const igraph_sparsemat_iterator_t *it) { * Time complexity: O(n), the number of columns of the sparse matrix. */ -igraph_integer_t igraph_sparsemat_iterator_next(igraph_sparsemat_iterator_t *it) { +igraph_int_t igraph_sparsemat_iterator_next(igraph_sparsemat_iterator_t *it) { it->pos += 1; while (it->col < it->mat->cs->n && it->mat->cs->p[it->col + 1] == it->pos) { @@ -3315,6 +3246,6 @@ igraph_integer_t igraph_sparsemat_iterator_next(igraph_sparsemat_iterator_t *it) * Time complexity: O(1). */ -igraph_integer_t igraph_sparsemat_iterator_idx(const igraph_sparsemat_iterator_t *it) { +igraph_int_t igraph_sparsemat_iterator_idx(const igraph_sparsemat_iterator_t *it) { return it->pos; } diff --git a/src/vendor/cigraph/src/core/stack.c b/src/vendor/cigraph/src/core/stack.c index 483aa40bfeb..0f567d4f200 100644 --- a/src/vendor/cigraph/src/core/stack.c +++ b/src/vendor/cigraph/src/core/stack.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/core/stack.pmt b/src/vendor/cigraph/src/core/stack.pmt index 7f081117941..cfc7bed3793 100644 --- a/src/vendor/cigraph/src/core/stack.pmt +++ b/src/vendor/cigraph/src/core/stack.pmt @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -41,8 +41,8 @@ * Time complexity: O(\p size). */ -igraph_error_t FUNCTION(igraph_stack, init)(TYPE(igraph_stack)* s, igraph_integer_t capacity) { - igraph_integer_t alloc_size; +igraph_error_t FUNCTION(igraph_stack, init)(TYPE(igraph_stack)* s, igraph_int_t capacity) { + igraph_int_t alloc_size; IGRAPH_ASSERT(capacity >= 0); alloc_size = capacity > 0 ? capacity : 1; IGRAPH_ASSERT(s != NULL); @@ -95,7 +95,7 @@ void FUNCTION(igraph_stack, destroy) (TYPE(igraph_stack)* s) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_stack, capacity)(const TYPE(igraph_stack) *s) { +igraph_int_t FUNCTION(igraph_stack, capacity)(const TYPE(igraph_stack) *s) { return s->stor_end - s->stor_begin; } @@ -115,8 +115,8 @@ igraph_integer_t FUNCTION(igraph_stack, capacity)(const TYPE(igraph_stack) *s) { * the stack. */ -igraph_error_t FUNCTION(igraph_stack, reserve)(TYPE(igraph_stack)* s, igraph_integer_t capacity) { - igraph_integer_t current_capacity; +igraph_error_t FUNCTION(igraph_stack, reserve)(TYPE(igraph_stack)* s, igraph_int_t capacity) { + igraph_int_t current_capacity; BASE *tmp; IGRAPH_ASSERT(s != NULL); @@ -168,7 +168,7 @@ igraph_bool_t FUNCTION(igraph_stack, empty)(TYPE(igraph_stack)* s) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_stack, size)(const TYPE(igraph_stack)* s) { +igraph_int_t FUNCTION(igraph_stack, size)(const TYPE(igraph_stack)* s) { IGRAPH_ASSERT(s != NULL); IGRAPH_ASSERT(s->stor_begin != NULL); return s->end - s->stor_begin; @@ -211,8 +211,8 @@ igraph_error_t FUNCTION(igraph_stack, push)(TYPE(igraph_stack)* s, BASE elem) { if (s->stor_end == s->end) { /* full, allocate more storage */ - igraph_integer_t old_size = FUNCTION(igraph_stack, size)(s); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = FUNCTION(igraph_stack, size)(s); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot push to stack, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -283,7 +283,7 @@ igraph_error_t FUNCTION(igraph_stack, print)(const TYPE(igraph_stack) *s) { #endif /* USING_R */ igraph_error_t FUNCTION(igraph_stack, fprint)(const TYPE(igraph_stack) *s, FILE *file) { - igraph_integer_t i, n = FUNCTION(igraph_stack, size)(s); + igraph_int_t i, n = FUNCTION(igraph_stack, size)(s); if (n != 0) { #ifdef FPRINTFUNC FPRINTFUNC(file, s->stor_begin[0]); diff --git a/src/vendor/cigraph/src/core/statusbar.c b/src/vendor/cigraph/src/core/statusbar.c index d8b947ff2a8..b56e113b528 100644 --- a/src/vendor/cigraph/src/core/statusbar.c +++ b/src/vendor/cigraph/src/core/statusbar.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/core/strvector.c b/src/vendor/cigraph/src/core/strvector.c index 51714ed5bdf..84e6a6d3758 100644 --- a/src/vendor/cigraph/src/core/strvector.c +++ b/src/vendor/cigraph/src/core/strvector.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -68,7 +68,7 @@ * Time complexity: O(\p len). */ -igraph_error_t igraph_strvector_init(igraph_strvector_t *sv, igraph_integer_t size) { +igraph_error_t igraph_strvector_init(igraph_strvector_t *sv, igraph_int_t size) { sv->stor_begin = IGRAPH_CALLOC(size, const char *); IGRAPH_CHECK_OOM(sv->stor_begin, "Cannot initialize string vector."); @@ -114,7 +114,7 @@ void igraph_strvector_destroy(igraph_strvector_t *sv) { * Time complexity: O(1). */ -const char *igraph_strvector_get(const igraph_strvector_t *sv, igraph_integer_t idx) { +const char *igraph_strvector_get(const igraph_strvector_t *sv, igraph_int_t idx) { IGRAPH_ASSERT(sv != NULL); IGRAPH_ASSERT(sv->stor_begin != NULL); return sv->stor_begin[idx] ? sv->stor_begin[idx] : ""; @@ -137,7 +137,7 @@ const char *igraph_strvector_get(const igraph_strvector_t *sv, igraph_integer_t * depending on the memory management, if reallocation is needed. */ -igraph_error_t igraph_strvector_set(igraph_strvector_t *sv, igraph_integer_t idx, +igraph_error_t igraph_strvector_set(igraph_strvector_t *sv, igraph_int_t idx, const char *value) { return igraph_strvector_set_len(sv, idx, value, strlen(value)); } @@ -159,7 +159,7 @@ igraph_error_t igraph_strvector_set(igraph_strvector_t *sv, igraph_integer_t idx * Time complexity: O(l), the length of the new string. Maybe more, * depending on the memory management, if reallocation is needed. */ -igraph_error_t igraph_strvector_set_len(igraph_strvector_t *sv, igraph_integer_t idx, +igraph_error_t igraph_strvector_set_len(igraph_strvector_t *sv, igraph_int_t idx, const char *value, size_t len) { IGRAPH_ASSERT(sv != NULL); IGRAPH_ASSERT(sv->stor_begin != NULL); @@ -192,9 +192,9 @@ igraph_error_t igraph_strvector_set_len(igraph_strvector_t *sv, igraph_integer_t */ void igraph_strvector_remove_section( - igraph_strvector_t *sv, igraph_integer_t from, igraph_integer_t to) { - igraph_integer_t size = igraph_strvector_size(sv); - igraph_integer_t i; + igraph_strvector_t *sv, igraph_int_t from, igraph_int_t to) { + igraph_int_t size = igraph_strvector_size(sv); + igraph_int_t i; if (from < 0) { from = 0; @@ -227,7 +227,7 @@ void igraph_strvector_remove_section( * Time complexity: O(n), the length of the string. */ -void igraph_strvector_remove(igraph_strvector_t *sv, igraph_integer_t elem) { +void igraph_strvector_remove(igraph_strvector_t *sv, igraph_int_t elem) { igraph_strvector_remove_section(sv, elem, elem + 1); } @@ -247,12 +247,12 @@ void igraph_strvector_remove(igraph_strvector_t *sv, igraph_integer_t elem) { 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); + igraph_int_t from_size = igraph_strvector_size(from); 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++) { + for (igraph_int_t i = 0; i < from_size; i++) { /* If the string in the 'from' vector is empty, we represent it as NULL. * The NULL value was already set by IGRAPH_CALLOC(). */ if (from->stor_begin[i] == NULL || from->stor_begin[i][0] == '\0') { @@ -261,7 +261,7 @@ igraph_error_t igraph_strvector_init_copy(igraph_strvector_t *to, to->stor_begin[i] = strdup(from->stor_begin[i]); if (to->stor_begin[i] == NULL) { /* LCOV_EXCL_START */ - for (igraph_integer_t j = 0; j < i; j++) { + for (igraph_int_t j = 0; j < i; j++) { IGRAPH_FREE(to->stor_begin[j]); } IGRAPH_FREE(to->stor_begin); @@ -298,24 +298,24 @@ igraph_error_t igraph_strvector_init_copy(igraph_strvector_t *to, igraph_error_t igraph_strvector_append(igraph_strvector_t *to, const igraph_strvector_t *from) { - const igraph_integer_t to_size = igraph_strvector_size(to); - const igraph_integer_t from_size = igraph_strvector_size(from); - const igraph_integer_t to_capacity = igraph_strvector_capacity(to); - igraph_integer_t new_to_size; + const igraph_int_t to_size = igraph_strvector_size(to); + const igraph_int_t from_size = igraph_strvector_size(from); + const igraph_int_t to_capacity = igraph_strvector_capacity(to); + igraph_int_t new_to_size; igraph_bool_t error = false; const char *tmp; IGRAPH_SAFE_ADD(to_size, from_size, &new_to_size); if (to_capacity < new_to_size) { - igraph_integer_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; if (new_to_capacity < new_to_size) { new_to_capacity = new_to_size; } IGRAPH_CHECK(igraph_strvector_reserve(to, new_to_capacity)); } - for (igraph_integer_t i = 0; i < from_size; i++) { + for (igraph_int_t i = 0; i < from_size; i++) { if (from->stor_begin[i] == NULL || from->stor_begin[i][0] == '\0') { /* Represent empty strings as NULL. */ tmp = NULL; @@ -359,7 +359,7 @@ igraph_error_t igraph_strvector_append(igraph_strvector_t *to, */ igraph_error_t igraph_strvector_merge(igraph_strvector_t *to, igraph_strvector_t *from) { const char **p1, **p2, **pe; - igraph_integer_t newlen; + igraph_int_t newlen; IGRAPH_SAFE_ADD(igraph_strvector_size(to), igraph_strvector_size(from), &newlen); IGRAPH_CHECK(igraph_strvector_reserve(to, newlen)); @@ -391,9 +391,9 @@ igraph_error_t igraph_strvector_merge(igraph_strvector_t *to, igraph_strvector_t */ void igraph_strvector_clear(igraph_strvector_t *sv) { - igraph_integer_t n = igraph_strvector_size(sv); + igraph_int_t n = igraph_strvector_size(sv); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { IGRAPH_FREE(sv->stor_begin[i]); } sv->end = sv->stor_begin; @@ -416,12 +416,12 @@ void igraph_strvector_clear(igraph_strvector_t *sv) { * smaller, maybe less, depending on memory management. */ -igraph_error_t igraph_strvector_resize(igraph_strvector_t *sv, igraph_integer_t newsize) { - igraph_integer_t toadd = newsize - igraph_strvector_size(sv); - igraph_integer_t oldsize = igraph_strvector_size(sv); +igraph_error_t igraph_strvector_resize(igraph_strvector_t *sv, igraph_int_t newsize) { + igraph_int_t toadd = newsize - igraph_strvector_size(sv); + igraph_int_t oldsize = igraph_strvector_size(sv); if (newsize < oldsize) { - for (igraph_integer_t i = newsize; i < oldsize; i++) { + for (igraph_int_t i = newsize; i < oldsize; i++) { IGRAPH_FREE(sv->stor_begin[i]); } sv->end = sv->stor_begin + newsize; @@ -445,7 +445,7 @@ igraph_error_t igraph_strvector_resize(igraph_strvector_t *sv, igraph_integer_t * Time complexity: O(1). */ -igraph_integer_t igraph_strvector_capacity(const igraph_strvector_t *sv) { +igraph_int_t igraph_strvector_capacity(const igraph_strvector_t *sv) { IGRAPH_ASSERT(sv != NULL); IGRAPH_ASSERT(sv->stor_begin != NULL); return sv->stor_end - sv->stor_begin; @@ -478,8 +478,8 @@ igraph_integer_t igraph_strvector_capacity(const igraph_strvector_t *sv) { * O(n), n is the new allocated size of the vector. */ -igraph_error_t igraph_strvector_reserve(igraph_strvector_t *sv, igraph_integer_t capacity) { - igraph_integer_t current_capacity = igraph_strvector_capacity(sv); +igraph_error_t igraph_strvector_reserve(igraph_strvector_t *sv, igraph_int_t capacity) { + igraph_int_t current_capacity = igraph_strvector_capacity(sv); if (capacity <= current_capacity) { return IGRAPH_SUCCESS; @@ -515,7 +515,7 @@ void igraph_strvector_resize_min(igraph_strvector_t *sv) { return; } - const igraph_integer_t size = (sv->end - sv->stor_begin); + const igraph_int_t size = (sv->end - sv->stor_begin); const char **tmp = IGRAPH_REALLOC(sv->stor_begin, size, const char *); if (tmp != NULL) { @@ -535,7 +535,7 @@ void igraph_strvector_resize_min(igraph_strvector_t *sv) { * Time complexity: O(1). */ -igraph_integer_t igraph_strvector_size(const igraph_strvector_t *sv) { +igraph_int_t igraph_strvector_size(const igraph_strvector_t *sv) { IGRAPH_ASSERT(sv != NULL); IGRAPH_ASSERT(sv->stor_begin != NULL); return sv->end - sv->stor_begin; @@ -550,8 +550,8 @@ static igraph_error_t strvector_expand_if_full(igraph_strvector_t *sv) { IGRAPH_ASSERT(sv->stor_begin != NULL); if (sv->stor_end == sv->end) { - igraph_integer_t old_size = igraph_strvector_size(sv); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = igraph_strvector_size(sv); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot add new item to string vector, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -628,11 +628,11 @@ igraph_error_t igraph_strvector_push_back_len( igraph_error_t igraph_strvector_fprint(const igraph_strvector_t *sv, FILE *file, const char *sep) { - const igraph_integer_t n = igraph_strvector_size(sv); + const igraph_int_t n = igraph_strvector_size(sv); if (n != 0) { fprintf(file, "%s", igraph_strvector_get(sv, 0)); } - for (igraph_integer_t i = 1; i < n; i++) { + for (igraph_int_t i = 1; i < n; i++) { fprintf(file, "%s%s", sep, igraph_strvector_get(sv, i)); } return IGRAPH_SUCCESS; @@ -668,11 +668,11 @@ igraph_error_t igraph_strvector_index(const igraph_strvector_t *sv, igraph_strvector_t *newv, const igraph_vector_int_t *idx) { - igraph_integer_t newlen = igraph_vector_int_size(idx); + igraph_int_t newlen = igraph_vector_int_size(idx); IGRAPH_CHECK(igraph_strvector_resize(newv, newlen)); - for (igraph_integer_t i = 0; i < newlen; i++) { - igraph_integer_t j = VECTOR(*idx)[i]; + for (igraph_int_t i = 0; i < newlen; i++) { + igraph_int_t j = VECTOR(*idx)[i]; const char *str = igraph_strvector_get(sv, j); IGRAPH_CHECK(igraph_strvector_set(newv, i, str)); } @@ -731,7 +731,7 @@ void igraph_strvector_swap(igraph_strvector_t *v1, igraph_strvector_t *v2) { * * Time complexity: O(1). */ -void igraph_strvector_swap_elements(igraph_strvector_t *sv, igraph_integer_t i, igraph_integer_t j) { +void igraph_strvector_swap_elements(igraph_strvector_t *sv, igraph_int_t i, igraph_int_t j) { const char *tmp = sv->stor_begin[i]; sv->stor_begin[i] = sv->stor_begin[j]; sv->stor_begin[j] = tmp; diff --git a/src/vendor/cigraph/src/core/trie.c b/src/vendor/cigraph/src/core/trie.c index 751f55e9e82..99cc6ab1d9b 100644 --- a/src/vendor/cigraph/src/core/trie.c +++ b/src/vendor/cigraph/src/core/trie.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -73,8 +73,8 @@ igraph_error_t igraph_trie_init(igraph_trie_t *t, igraph_bool_t storekeys) { static void igraph_i_trie_destroy_node_helper(igraph_trie_node_t *t, igraph_bool_t sfree) { igraph_strvector_destroy(&t->strs); - igraph_integer_t children_size = igraph_vector_ptr_size(&t->children); - for (igraph_integer_t i = 0; i < children_size; i++) { + igraph_int_t children_size = igraph_vector_ptr_size(&t->children); + for (igraph_int_t i = 0; i < children_size; i++) { igraph_trie_node_t *child = VECTOR(t->children)[i]; if (child != NULL) { igraph_i_trie_destroy_node_helper(child, true); @@ -124,8 +124,8 @@ static size_t igraph_i_strdiff(const char *str, const char *key) { */ static igraph_error_t igraph_i_trie_get_node( - igraph_trie_node_t *t, const char *key, igraph_integer_t newvalue, - igraph_integer_t *id + igraph_trie_node_t *t, const char *key, igraph_int_t newvalue, + igraph_int_t *id ) { assert(key != NULL); @@ -133,8 +133,8 @@ static igraph_error_t igraph_i_trie_get_node( * for its existence */ igraph_bool_t add = (newvalue >= 0); - igraph_integer_t strs_size = igraph_strvector_size(&t->strs); - for (igraph_integer_t i = 0; i < strs_size; i++) { + igraph_int_t strs_size = igraph_strvector_size(&t->strs); + for (igraph_int_t i = 0; i < strs_size; i++) { size_t diff; const char *str = igraph_strvector_get(&t->strs, i); diff = igraph_i_strdiff(str, key); @@ -295,7 +295,7 @@ static igraph_error_t igraph_i_trie_get_node( * \return Error code, usually \c IGRAPH_ENOMEM. */ -igraph_error_t igraph_trie_get(igraph_trie_t *t, const char *key, igraph_integer_t *id) { +igraph_error_t igraph_trie_get(igraph_trie_t *t, const char *key, igraph_int_t *id) { assert(key != NULL); if (*key == '\0') { @@ -353,8 +353,8 @@ igraph_error_t igraph_trie_get(igraph_trie_t *t, const char *key, igraph_integer igraph_error_t igraph_trie_get_len( igraph_trie_t *t, const char *key, - igraph_integer_t length, - igraph_integer_t *id) { + igraph_int_t length, + igraph_int_t *id) { char *tmp = strndup(key, length); IGRAPH_CHECK_OOM(tmp, "Cannot get from trie."); @@ -380,7 +380,7 @@ igraph_error_t igraph_trie_get_len( * \return Error code. */ -igraph_error_t igraph_trie_check(igraph_trie_t *t, const char *key, igraph_integer_t *id) { +igraph_error_t igraph_trie_check(igraph_trie_t *t, const char *key, igraph_int_t *id) { IGRAPH_CHECK(igraph_i_trie_get_node(&t->node, key, -1, id)); return IGRAPH_SUCCESS; } @@ -395,7 +395,7 @@ igraph_error_t igraph_trie_check(igraph_trie_t *t, const char *key, igraph_integ * reverse lookup, \c NULL is returned. */ -const char* igraph_trie_idx(igraph_trie_t *t, igraph_integer_t idx) { +const char* igraph_trie_idx(igraph_trie_t *t, igraph_int_t idx) { if (! t->storekeys) { return NULL; } @@ -410,7 +410,7 @@ const char* igraph_trie_idx(igraph_trie_t *t, igraph_integer_t idx) { * \return The size of the trie, i.e. one larger than the maximum index. */ -igraph_integer_t igraph_trie_size(igraph_trie_t *t) { +igraph_int_t igraph_trie_size(igraph_trie_t *t) { return t->maxvalue + 1; } diff --git a/src/vendor/cigraph/src/core/trie.h b/src/vendor/cigraph/src/core/trie.h index 58d75b4f017..84a8daa59ea 100644 --- a/src/vendor/cigraph/src/core/trie.h +++ b/src/vendor/cigraph/src/core/trie.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -43,7 +43,7 @@ typedef struct s_igraph_trie_node { typedef struct s_igraph_trie { igraph_trie_node_t node; - igraph_integer_t maxvalue; + igraph_int_t maxvalue; igraph_bool_t storekeys; igraph_strvector_t keys; } igraph_trie_t; @@ -57,12 +57,12 @@ typedef struct s_igraph_trie { IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_trie_init(igraph_trie_t *t, igraph_bool_t storekeys); IGRAPH_PRIVATE_EXPORT void igraph_trie_destroy(igraph_trie_t *t); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_trie_get(igraph_trie_t *t, const char *key, igraph_integer_t *id); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_trie_check(igraph_trie_t *t, const char *key, igraph_integer_t *id); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_trie_get_len(igraph_trie_t *t, const char *key, igraph_integer_t length, - igraph_integer_t *id); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE const char* igraph_trie_idx(igraph_trie_t *t, igraph_integer_t idx); -IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_trie_size(igraph_trie_t *t); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_trie_get(igraph_trie_t *t, const char *key, igraph_int_t *id); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_trie_check(igraph_trie_t *t, const char *key, igraph_int_t *id); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_trie_get_len(igraph_trie_t *t, const char *key, igraph_int_t length, + igraph_int_t *id); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE const char* igraph_trie_idx(igraph_trie_t *t, igraph_int_t idx); +IGRAPH_PRIVATE_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_trie_size(igraph_trie_t *t); const igraph_strvector_t* igraph_i_trie_borrow_keys(igraph_trie_t *t); diff --git a/src/vendor/cigraph/src/core/typed_list.pmt b/src/vendor/cigraph/src/core/typed_list.pmt index 7c30fdad6a3..4f23915e81b 100644 --- a/src/vendor/cigraph/src/core/typed_list.pmt +++ b/src/vendor/cigraph/src/core/typed_list.pmt @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -106,8 +106,8 @@ static int INTERNAL_FUNCTION(sort_ind_cmp)(void *thunk, const void *p1, const vo * n is the number of elements. */ -igraph_error_t FUNCTION(init)(TYPE *v, igraph_integer_t size) { - igraph_integer_t alloc_size = size > 0 ? size : 1; +igraph_error_t FUNCTION(init)(TYPE *v, igraph_int_t size) { + igraph_int_t alloc_size = size > 0 ? size : 1; IGRAPH_ASSERT(size >= 0); v->stor_begin = IGRAPH_CALLOC(alloc_size, ITEM_TYPE); if (v->stor_begin == 0) { @@ -139,7 +139,7 @@ igraph_error_t FUNCTION(init)(TYPE *v, igraph_integer_t size) { */ igraph_error_t FUNCTION(init_copy)(TYPE* to, const TYPE* from) { - igraph_integer_t i, size = FUNCTION(size)(from); + igraph_int_t i, size = FUNCTION(size)(from); IGRAPH_CHECK(FUNCTION(init)(to, 0)); IGRAPH_FINALLY(FUNCTION(destroy), to); @@ -200,7 +200,7 @@ void FUNCTION(destroy)(TYPE *v) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(capacity)(const TYPE *v) { +igraph_int_t FUNCTION(capacity)(const TYPE *v) { return v->stor_end - v->stor_begin; } @@ -230,8 +230,8 @@ igraph_integer_t FUNCTION(capacity)(const TYPE *v) { * O(n), n is the new allocated size of the list. */ -igraph_error_t FUNCTION(reserve)(TYPE *v, igraph_integer_t capacity) { - igraph_integer_t current_capacity; +igraph_error_t FUNCTION(reserve)(TYPE *v, igraph_int_t capacity) { + igraph_int_t current_capacity; ITEM_TYPE *tmp; IGRAPH_ASSERT(v != NULL); @@ -284,7 +284,7 @@ igraph_bool_t FUNCTION(empty)(const TYPE *v) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(size)(const TYPE *v) { +igraph_int_t FUNCTION(size)(const TYPE *v) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return v->end - v->stor_begin; @@ -321,8 +321,8 @@ igraph_integer_t FUNCTION(size)(const TYPE *v) { * size is larger. In the latter case it is usually around O(n), where n is the * new size of the vector. */ -igraph_error_t FUNCTION(resize)(TYPE *v, igraph_integer_t new_size) { - igraph_integer_t old_size; +igraph_error_t FUNCTION(resize)(TYPE *v, igraph_int_t new_size) { + igraph_int_t old_size; IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); @@ -374,7 +374,7 @@ void FUNCTION(clear)(TYPE *v) { * * Time complexity: O(1). */ -ITEM_TYPE *FUNCTION(get_ptr)(const TYPE *v, igraph_integer_t pos) { +ITEM_TYPE *FUNCTION(get_ptr)(const TYPE *v, igraph_int_t pos) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return v->stor_begin + pos; @@ -399,7 +399,7 @@ ITEM_TYPE *FUNCTION(get_ptr)(const TYPE *v, igraph_integer_t pos) { * * Time complexity: O(1). */ -void FUNCTION(set)(TYPE *v, igraph_integer_t pos, ITEM_TYPE *e) { +void FUNCTION(set)(TYPE *v, igraph_int_t pos, ITEM_TYPE *e) { INTERNAL_FUNCTION(destroy_item)(v->stor_begin + pos); v->stor_begin[pos] = *e; } @@ -424,7 +424,7 @@ void FUNCTION(set)(TYPE *v, igraph_integer_t pos, ITEM_TYPE *e) { * * Time complexity: O(1). */ -void FUNCTION(replace)(TYPE *v, igraph_integer_t pos, ITEM_TYPE *e) { +void FUNCTION(replace)(TYPE *v, igraph_int_t pos, ITEM_TYPE *e) { ITEM_TYPE old_value = *(FUNCTION(get_ptr)(v, pos)); v->stor_begin[pos] = *e; *e = old_value; @@ -464,7 +464,7 @@ void FUNCTION(swap)(TYPE *v1, TYPE *v2) { * Time complexity: O(1). */ -void FUNCTION(swap_elements)(TYPE *v1, igraph_integer_t i, igraph_integer_t j) { +void FUNCTION(swap_elements)(TYPE *v1, igraph_int_t i, igraph_int_t j) { ITEM_TYPE tmp = v1->stor_begin[i]; v1->stor_begin[i] = v1->stor_begin[j]; v1->stor_begin[j] = tmp; @@ -482,7 +482,7 @@ void FUNCTION(swap_elements)(TYPE *v1, igraph_integer_t i, igraph_integer_t j) { * Time complexity: O(1). */ ITEM_TYPE *FUNCTION(tail_ptr)(const TYPE *v) { - igraph_integer_t size = FUNCTION(size)(v); + igraph_int_t size = FUNCTION(size)(v); return size > 0 ? FUNCTION(get_ptr)(v, size - 1) : 0; } @@ -503,8 +503,8 @@ ITEM_TYPE *FUNCTION(tail_ptr)(const TYPE *v) { * * Time complexity: O(n), where n is the number of items in the list. */ -void FUNCTION(discard)(TYPE *v, igraph_integer_t index) { - igraph_integer_t size = FUNCTION(size)(v); +void FUNCTION(discard)(TYPE *v, igraph_int_t index) { + igraph_int_t size = FUNCTION(size)(v); if (size > 0) { INTERNAL_FUNCTION(destroy_item)(v->stor_begin + index); @@ -525,7 +525,7 @@ void FUNCTION(discard)(TYPE *v, igraph_integer_t index) { * Time complexity: O(1). */ void FUNCTION(discard_back)(TYPE *v) { - igraph_integer_t size = FUNCTION(size)(v); + igraph_int_t size = FUNCTION(size)(v); if (size > 0) { INTERNAL_FUNCTION(destroy_item)(v->end - 1); v->end -= 1; @@ -549,8 +549,8 @@ void FUNCTION(discard_back)(TYPE *v) { * * Time complexity: O(1). */ -void FUNCTION(discard_fast)(TYPE *v, igraph_integer_t index) { - igraph_integer_t size = FUNCTION(size)(v); +void FUNCTION(discard_fast)(TYPE *v, igraph_int_t index) { + igraph_int_t size = FUNCTION(size)(v); if (size > 0) { INTERNAL_FUNCTION(destroy_item)(v->stor_begin + index); @@ -666,8 +666,8 @@ igraph_error_t FUNCTION(push_back_new)(TYPE *v, ITEM_TYPE** e) { * * Time complexity: O(n). */ -igraph_error_t FUNCTION(insert)(TYPE *v, igraph_integer_t pos, ITEM_TYPE *e) { - igraph_integer_t size = FUNCTION(size)(v); +igraph_error_t FUNCTION(insert)(TYPE *v, igraph_int_t pos, ITEM_TYPE *e) { + igraph_int_t size = FUNCTION(size)(v); IGRAPH_ASSERT(0 <= pos && pos <= size); IGRAPH_CHECK(INTERNAL_FUNCTION(expand_if_full)(v)); if (pos < size) { @@ -697,7 +697,7 @@ igraph_error_t FUNCTION(insert)(TYPE *v, igraph_integer_t pos, ITEM_TYPE *e) { * Time complexity: same as \ref igraph_vector_list_insert() plus the time * needed to copy the vector (which is O(n) for n elements in the vector). */ -igraph_error_t FUNCTION(insert_copy)(TYPE *v, igraph_integer_t pos, const ITEM_TYPE *e) { +igraph_error_t FUNCTION(insert_copy)(TYPE *v, igraph_int_t pos, const ITEM_TYPE *e) { ITEM_TYPE copy; IGRAPH_CHECK(INTERNAL_FUNCTION(copy_item)(©, e)); IGRAPH_FINALLY(INTERNAL_FUNCTION(destroy_item), ©); @@ -726,7 +726,7 @@ igraph_error_t FUNCTION(insert_copy)(TYPE *v, igraph_integer_t pos, const ITEM_T * * Time complexity: same as \ref igraph_vector_list_push_back(). */ -igraph_error_t FUNCTION(insert_new)(TYPE *v, igraph_integer_t pos, ITEM_TYPE** e) { +igraph_error_t FUNCTION(insert_new)(TYPE *v, igraph_int_t pos, ITEM_TYPE** e) { ITEM_TYPE copy; IGRAPH_CHECK(INTERNAL_FUNCTION(init_item)(v, ©)); IGRAPH_FINALLY(INTERNAL_FUNCTION(destroy_item), ©); @@ -760,8 +760,8 @@ igraph_error_t FUNCTION(insert_new)(TYPE *v, igraph_integer_t pos, ITEM_TYPE** e * * Time complexity: O(n), where n is the number of items in the list. */ -igraph_error_t FUNCTION(remove)(TYPE *v, igraph_integer_t index, ITEM_TYPE *result) { - igraph_integer_t size = FUNCTION(size)(v); +igraph_error_t FUNCTION(remove)(TYPE *v, igraph_int_t index, ITEM_TYPE *result) { + igraph_int_t size = FUNCTION(size)(v); IGRAPH_ASSERT(result != 0); @@ -825,8 +825,8 @@ ITEM_TYPE FUNCTION(pop_back)(TYPE *v) { * * Time complexity: O(1). */ -igraph_error_t FUNCTION(remove_fast)(TYPE *v, igraph_integer_t index, ITEM_TYPE *result) { - igraph_integer_t size = FUNCTION(size)(v); +igraph_error_t FUNCTION(remove_fast)(TYPE *v, igraph_int_t index, ITEM_TYPE *result) { + igraph_int_t size = FUNCTION(size)(v); IGRAPH_ASSERT(result != 0); @@ -872,7 +872,7 @@ igraph_error_t FUNCTION(remove_fast)(TYPE *v, igraph_integer_t index, ITEM_TYPE */ igraph_error_t FUNCTION(permute)(TYPE *v, const igraph_vector_int_t* index) { ITEM_TYPE *work; - igraph_integer_t i, size; + igraph_int_t i, size; IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); @@ -946,7 +946,7 @@ igraph_error_t FUNCTION(sort_ind)( TYPE *v, igraph_vector_int_t *inds, int (*cmp)(const ITEM_TYPE*, const ITEM_TYPE*) ) { - igraph_integer_t i, n = FUNCTION(size)(v); + igraph_int_t i, n = FUNCTION(size)(v); ITEM_TYPE **vind, *first; IGRAPH_CHECK(igraph_vector_int_resize(inds, n)); @@ -1002,7 +1002,7 @@ igraph_error_t FUNCTION(sort_ind)( void FUNCTION(remove_consecutive_duplicates)( TYPE *v, igraph_bool_t (*eq)(const ITEM_TYPE*, const ITEM_TYPE*) ) { - igraph_integer_t i, j, n = FUNCTION(size)(v); + igraph_int_t i, j, n = FUNCTION(size)(v); ITEM_TYPE *p = v->stor_begin; if (n < 2) { @@ -1033,8 +1033,8 @@ void FUNCTION(remove_consecutive_duplicates)( * Time complexity: O(n), the number of elements. */ igraph_error_t FUNCTION(reverse)(TYPE *v) { - igraph_integer_t n = FUNCTION(size)(v), n2 = n / 2; - igraph_integer_t i, j; + igraph_int_t n = FUNCTION(size)(v), n2 = n / 2; + igraph_int_t i, j; for (i = 0, j = n - 1; i < n2; i++, j--) { ITEM_TYPE tmp; tmp = VECTOR(*v)[i]; @@ -1096,8 +1096,8 @@ static igraph_error_t INTERNAL_FUNCTION(expand_if_full)(TYPE *v) { IGRAPH_ASSERT(v->stor_begin != NULL); if (v->stor_end == v->end) { - igraph_integer_t old_size = FUNCTION(size)(v); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = FUNCTION(size)(v); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot add new item to list, already at maximum size.", IGRAPH_EOVERFLOW); } diff --git a/src/vendor/cigraph/src/core/vector.c b/src/vendor/cigraph/src/core/vector.c index e5da75c1b56..86d58d0b8a2 100644 --- a/src/vendor/cigraph/src/core/vector.c +++ b/src/vendor/cigraph/src/core/vector.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -73,10 +73,10 @@ * Time complexity: O(n), where n is the number of elements in the vector. */ igraph_error_t igraph_vector_floor(const igraph_vector_t *from, igraph_vector_int_t *to) { - const igraph_integer_t n = igraph_vector_size(from); + const igraph_int_t n = igraph_vector_size(from); IGRAPH_CHECK(igraph_vector_int_resize(to, n)); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { VECTOR(*to)[i] = floor(VECTOR(*from)[i]); } @@ -84,10 +84,10 @@ igraph_error_t igraph_vector_floor(const igraph_vector_t *from, igraph_vector_in } igraph_error_t igraph_vector_round(const igraph_vector_t *from, igraph_vector_int_t *to) { - const igraph_integer_t n = igraph_vector_size(from); + const igraph_int_t n = igraph_vector_size(from); IGRAPH_CHECK(igraph_vector_int_resize(to, n)); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { VECTOR(*to)[i] = round(VECTOR(*from)[i]); } @@ -116,11 +116,11 @@ igraph_error_t igraph_vector_round(const igraph_vector_t *from, igraph_vector_in igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, const igraph_vector_int_t* v2, - igraph_vector_int_t* res, igraph_integer_t nodes) { - igraph_integer_t edges = igraph_vector_int_size(v); + igraph_vector_int_t* res, igraph_int_t nodes) { + igraph_int_t edges = igraph_vector_int_size(v); igraph_vector_int_t ptr; igraph_vector_int_t rad; - igraph_integer_t i, j; + igraph_int_t i, j; IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); @@ -130,7 +130,7 @@ igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, IGRAPH_CHECK(igraph_vector_int_resize(res, edges)); for (i = 0; i < edges; i++) { - igraph_integer_t radix = VECTOR(*v2)[i]; + igraph_int_t radix = VECTOR(*v2)[i]; if (VECTOR(ptr)[radix] != 0) { VECTOR(rad)[i] = VECTOR(ptr)[radix]; } @@ -140,7 +140,7 @@ igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, j = 0; for (i = 0; i < nodes + 1; i++) { if (VECTOR(ptr)[i] != 0) { - igraph_integer_t next = VECTOR(ptr)[i] - 1; + igraph_int_t next = VECTOR(ptr)[i] - 1; VECTOR(*res)[j++] = next; while (VECTOR(rad)[next] != 0) { next = VECTOR(rad)[next] - 1; @@ -153,8 +153,8 @@ igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, igraph_vector_int_null(&rad); for (i = 0; i < edges; i++) { - igraph_integer_t edge = VECTOR(*res)[edges - i - 1]; - igraph_integer_t radix = VECTOR(*v)[edge]; + igraph_int_t edge = VECTOR(*res)[edges - i - 1]; + igraph_int_t radix = VECTOR(*v)[edge]; if (VECTOR(ptr)[radix] != 0) { VECTOR(rad)[edge] = VECTOR(ptr)[radix]; } @@ -164,7 +164,7 @@ igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, j = 0; for (i = 0; i < nodes + 1; i++) { if (VECTOR(ptr)[i] != 0) { - igraph_integer_t next = VECTOR(ptr)[i] - 1; + igraph_int_t next = VECTOR(ptr)[i] - 1; VECTOR(*res)[j++] = next; while (VECTOR(rad)[next] != 0) { next = VECTOR(rad)[next] - 1; @@ -194,12 +194,12 @@ igraph_error_t igraph_vector_int_pair_order(const igraph_vector_int_t* v, igraph_error_t igraph_i_vector_int_order( const igraph_vector_int_t *v, igraph_vector_int_t *res, - igraph_integer_t maxval) { + igraph_int_t maxval) { - const igraph_integer_t size = igraph_vector_int_size(v); + const igraph_int_t size = igraph_vector_int_size(v); igraph_vector_int_t ptr; igraph_vector_int_t rad; - igraph_integer_t j; + igraph_int_t j; IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); @@ -208,8 +208,8 @@ igraph_error_t igraph_i_vector_int_order( IGRAPH_VECTOR_INT_INIT_FINALLY(&rad, size); IGRAPH_CHECK(igraph_vector_int_resize(res, size)); - for (igraph_integer_t i = 0; i < size; i++) { - igraph_integer_t radix = VECTOR(*v)[i]; + for (igraph_int_t i = 0; i < size; i++) { + igraph_int_t radix = VECTOR(*v)[i]; if (VECTOR(ptr)[radix] != 0) { VECTOR(rad)[i] = VECTOR(ptr)[radix]; } @@ -217,9 +217,9 @@ igraph_error_t igraph_i_vector_int_order( } j = 0; - for (igraph_integer_t i = 0; i < maxval + 1; i++) { + for (igraph_int_t i = 0; i < maxval + 1; i++) { if (VECTOR(ptr)[i] != 0) { - igraph_integer_t next = VECTOR(ptr)[i] - 1; + igraph_int_t next = VECTOR(ptr)[i] - 1; VECTOR(*res)[j++] = next; while (VECTOR(rad)[next] != 0) { next = VECTOR(rad)[next] - 1; @@ -249,25 +249,25 @@ igraph_error_t igraph_i_vector_int_order( igraph_error_t igraph_i_vector_int_rank( const igraph_vector_int_t *v, igraph_vector_int_t *res, - igraph_integer_t maxval) { + igraph_int_t maxval) { - const igraph_integer_t size = igraph_vector_int_size(v); + const igraph_int_t size = igraph_vector_int_size(v); igraph_vector_int_t rad; igraph_vector_int_t ptr; - igraph_integer_t c = 0; + igraph_int_t c = 0; IGRAPH_VECTOR_INT_INIT_FINALLY(&rad, maxval); IGRAPH_VECTOR_INT_INIT_FINALLY(&ptr, size); IGRAPH_CHECK(igraph_vector_int_resize(res, size)); - for (igraph_integer_t i = 0; i < size; i++) { - igraph_integer_t elem = VECTOR(*v)[i]; + for (igraph_int_t i = 0; i < size; i++) { + igraph_int_t elem = VECTOR(*v)[i]; VECTOR(ptr)[i] = VECTOR(rad)[elem]; VECTOR(rad)[elem] = i + 1; } - for (igraph_integer_t i = 0; i < maxval; i++) { - igraph_integer_t p = VECTOR(rad)[i]; + for (igraph_int_t i = 0; i < maxval; i++) { + igraph_int_t p = VECTOR(rad)[i]; while (p != 0) { VECTOR(*res)[p - 1] = c++; p = VECTOR(ptr)[p - 1]; @@ -295,7 +295,7 @@ igraph_error_t igraph_i_vector_int_rank( igraph_error_t igraph_vector_complex_real(const igraph_vector_complex_t *v, igraph_vector_t *real) { - igraph_integer_t i, n = igraph_vector_complex_size(v); + igraph_int_t i, n = igraph_vector_complex_size(v); IGRAPH_CHECK(igraph_vector_resize(real, n)); for (i = 0; i < n; i++) { VECTOR(*real)[i] = IGRAPH_REAL(VECTOR(*v)[i]); @@ -318,7 +318,7 @@ igraph_error_t igraph_vector_complex_real(const igraph_vector_complex_t *v, igraph_error_t igraph_vector_complex_imag(const igraph_vector_complex_t *v, igraph_vector_t *imag) { - igraph_integer_t i, n = igraph_vector_complex_size(v); + igraph_int_t i, n = igraph_vector_complex_size(v); IGRAPH_CHECK(igraph_vector_resize(imag, n)); for (i = 0; i < n; i++) { VECTOR(*imag)[i] = IGRAPH_IMAG(VECTOR(*v)[i]); @@ -343,7 +343,7 @@ igraph_error_t igraph_vector_complex_imag(const igraph_vector_complex_t *v, igraph_error_t igraph_vector_complex_realimag(const igraph_vector_complex_t *v, igraph_vector_t *real, igraph_vector_t *imag) { - igraph_integer_t i, n = igraph_vector_complex_size(v); + igraph_int_t i, n = igraph_vector_complex_size(v); IGRAPH_CHECK(igraph_vector_resize(real, n)); IGRAPH_CHECK(igraph_vector_resize(imag, n)); for (i = 0; i < n; i++) { @@ -371,7 +371,7 @@ igraph_error_t igraph_vector_complex_realimag(const igraph_vector_complex_t *v, igraph_error_t igraph_vector_complex_create(igraph_vector_complex_t *v, const igraph_vector_t *real, const igraph_vector_t *imag) { - igraph_integer_t i, n = igraph_vector_size(real); + igraph_int_t i, n = igraph_vector_size(real); if (n != igraph_vector_size(imag)) { IGRAPH_ERROR("Real and imag vector sizes don't match", IGRAPH_EINVAL); } @@ -402,7 +402,7 @@ igraph_error_t igraph_vector_complex_create(igraph_vector_complex_t *v, igraph_error_t igraph_vector_complex_create_polar(igraph_vector_complex_t *v, const igraph_vector_t *r, const igraph_vector_t *theta) { - igraph_integer_t i, n = igraph_vector_size(r); + igraph_int_t i, n = igraph_vector_size(r); if (n != igraph_vector_size(theta)) { IGRAPH_ERROR("'r' and 'theta' vector sizes don't match", IGRAPH_EINVAL); } @@ -433,7 +433,7 @@ igraph_bool_t igraph_vector_complex_all_almost_e(const igraph_vector_complex_t * const igraph_vector_complex_t *rhs, igraph_real_t eps) { - igraph_integer_t n = igraph_vector_complex_size(lhs); + igraph_int_t n = igraph_vector_complex_size(lhs); if (lhs == rhs) { return true; @@ -443,7 +443,7 @@ igraph_bool_t igraph_vector_complex_all_almost_e(const igraph_vector_complex_t * return false; } - for (igraph_integer_t i=0; i < n; i++) { + for (igraph_int_t i=0; i < n; i++) { if (! igraph_complex_almost_equals(VECTOR(*lhs)[i], VECTOR(*rhs)[i], eps)) return false; } @@ -468,7 +468,7 @@ igraph_bool_t igraph_vector_all_almost_e(const igraph_vector_t *lhs, const igraph_vector_t *rhs, igraph_real_t eps) { - igraph_integer_t n = igraph_vector_size(lhs); + igraph_int_t n = igraph_vector_size(lhs); if (lhs == rhs) { return true; @@ -478,7 +478,7 @@ igraph_bool_t igraph_vector_all_almost_e(const igraph_vector_t *lhs, return false; } - for (igraph_integer_t i=0; i < n; i++) { + for (igraph_int_t i=0; i < n; i++) { if (! igraph_almost_equals(VECTOR(*lhs)[i], VECTOR(*rhs)[i], eps)) return false; } @@ -505,7 +505,7 @@ igraph_bool_t igraph_vector_all_almost_e(const igraph_vector_t *lhs, * perform comparisons with relative tolerances. */ igraph_error_t igraph_vector_zapsmall(igraph_vector_t *v, igraph_real_t tol) { - igraph_integer_t i, n = igraph_vector_size(v); + igraph_int_t i, n = igraph_vector_size(v); if (tol < 0.0) { IGRAPH_ERROR("Tolerance must be positive or zero.", IGRAPH_EINVAL); } @@ -544,7 +544,7 @@ igraph_error_t igraph_vector_zapsmall(igraph_vector_t *v, igraph_real_t tol) { * tolerances. */ igraph_error_t igraph_vector_complex_zapsmall(igraph_vector_complex_t *v, igraph_real_t tol) { - igraph_integer_t i, n = igraph_vector_complex_size(v); + igraph_int_t i, n = igraph_vector_complex_size(v); if (tol < 0.0) { IGRAPH_ERROR("Tolerance must be positive or zero.", IGRAPH_EINVAL); } diff --git a/src/vendor/cigraph/src/core/vector.pmt b/src/vendor/cigraph/src/core/vector.pmt index 40a691f0bcb..15c34f94806 100644 --- a/src/vendor/cigraph/src/core/vector.pmt +++ b/src/vendor/cigraph/src/core/vector.pmt @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -42,7 +42,7 @@ * * There are multiple variants of \type igraph_vector_t; the basic variant * stores doubles, but there is also \type igraph_vector_int_t for integers (of - * type \type igraph_integer_t), \c igraph_vector_bool_t for booleans (of type + * type \type igraph_int_t), \c igraph_vector_bool_t for booleans (of type * \type igraph_bool_t) and so on. Vectors are used extensively in \a igraph; all * functions that expect or return a list of numbers use \type igraph_vector_t or * \type igraph_vector_int_t to achieve this. Integer vectors are typically used @@ -131,8 +131,8 @@ * n is the number of elements. */ -igraph_error_t FUNCTION(igraph_vector, init)(TYPE(igraph_vector) *v, igraph_integer_t size) { - igraph_integer_t alloc_size; +igraph_error_t FUNCTION(igraph_vector, init)(TYPE(igraph_vector) *v, igraph_int_t size) { + igraph_int_t alloc_size; IGRAPH_ASSERT(size >= 0); alloc_size = size > 0 ? size : 1; @@ -155,25 +155,36 @@ igraph_error_t FUNCTION(igraph_vector, init)(TYPE(igraph_vector) *v, igraph_inte * \function igraph_vector_view * \brief Handle a regular C array as a \type igraph_vector_t. * + * This function lets you treat an existing C array as an \ref igraph_vector_t. + * * - * This is a special \type igraph_vector_t constructor. It allows to - * handle a regular C array as a \type igraph_vector_t temporarily. - * Be sure that you \em don't ever call the destructor (\ref - * igraph_vector_destroy()) on objects created by this constructor. - * \param v Pointer to an uninitialized \type igraph_vector_t object. - * \param data Pointer, the C array. It may not be \c NULL, except - * when \p length is zero. + * Since this function creates a view into an existing array, you must \em not + * destroy the \c igraph_vector_t object when you are done with it. Similarly, + * you must \em not call any function on it that may attempt to modify the size + * of the vector. Modifying an element in the vector will modify the underlying + * array as the two share the same memory block. + * + * + * Typical usage pattern: + * + * + * igraph_real_t array[] = { 1.0, 1.5, 2.0 }; + * const igraph_vector_t v = igraph_vector_view(array, sizeof(array) / sizeof(array[0])); + * printf("The sum of vector elements is %g.\n", igraph_vector_sum(&v)); + * + * + * \param data The raw array that the vector provides a view into. * \param length The length of the C array. - * \return Pointer to the vector object, the same as the - * \p v parameter, for convenience. + * \return The vector object providing the view into the array. * * Time complexity: O(1) */ -const TYPE(igraph_vector)* FUNCTION(igraph_vector, view)(const TYPE(igraph_vector) *v, - const BASE *data, igraph_integer_t length) { +TYPE(igraph_vector) FUNCTION(igraph_vector, view)( + const BASE *data, igraph_int_t length) { + static const BASE dummy = ZERO; - TYPE(igraph_vector) *v2 = (TYPE(igraph_vector)*)v; + TYPE(igraph_vector) v; /* When the length is zero, we allow 'data' to be NULL. * An igraph_vector_t may never contain a NULL pointer, @@ -184,9 +195,9 @@ const TYPE(igraph_vector)* FUNCTION(igraph_vector, view)(const TYPE(igraph_vecto IGRAPH_ASSERT(data != NULL); } - v2->stor_begin = (BASE*)data; - v2->stor_end = (BASE*)data + length; - v2->end = v2->stor_end; + v.stor_begin = (BASE*)data; + v.stor_end = (BASE*)data + length; + v.end = v.stor_end; return v; } @@ -424,7 +435,7 @@ void FUNCTION(igraph_vector, destroy)(TYPE(igraph_vector) *v) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_vector, capacity)(const TYPE(igraph_vector) *v) { +igraph_int_t FUNCTION(igraph_vector, capacity)(const TYPE(igraph_vector) *v) { return v->stor_end - v->stor_begin; } @@ -456,8 +467,8 @@ igraph_integer_t FUNCTION(igraph_vector, capacity)(const TYPE(igraph_vector) *v) * is the new allocated size of the vector. */ -igraph_error_t FUNCTION(igraph_vector, reserve)(TYPE(igraph_vector) *v, igraph_integer_t capacity) { - igraph_integer_t current_capacity; +igraph_error_t FUNCTION(igraph_vector, reserve)(TYPE(igraph_vector) *v, igraph_int_t capacity) { + igraph_int_t current_capacity; BASE *tmp; IGRAPH_ASSERT(v != NULL); @@ -510,7 +521,7 @@ igraph_bool_t FUNCTION(igraph_vector, empty)(const TYPE(igraph_vector) *v) { * Time complexity: O(1). */ -igraph_integer_t FUNCTION(igraph_vector, size)(const TYPE(igraph_vector) *v) { +igraph_int_t FUNCTION(igraph_vector, size)(const TYPE(igraph_vector) *v) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return v->end - v->stor_begin; @@ -567,8 +578,8 @@ igraph_error_t FUNCTION(igraph_vector, push_back)(TYPE(igraph_vector) *v, BASE e if (v->stor_end == v->end) { /* full, allocate more storage */ - igraph_integer_t old_size = FUNCTION(igraph_vector, size)(v); - igraph_integer_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t old_size = FUNCTION(igraph_vector, size)(v); + igraph_int_t new_size = old_size < IGRAPH_INTEGER_MAX/2 ? old_size * 2 : IGRAPH_INTEGER_MAX; if (old_size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot push to vector, already at maximum size.", IGRAPH_EOVERFLOW); } @@ -599,8 +610,8 @@ igraph_error_t FUNCTION(igraph_vector, push_back)(TYPE(igraph_vector) *v, BASE e * \param value The new element to be inserted. */ igraph_error_t FUNCTION(igraph_vector, insert)( - TYPE(igraph_vector) *v, igraph_integer_t pos, BASE value) { - igraph_integer_t size = FUNCTION(igraph_vector, size)(v); + TYPE(igraph_vector) *v, igraph_int_t pos, BASE value) { + igraph_int_t size = FUNCTION(igraph_vector, size)(v); IGRAPH_ASSERT(0 <= pos && pos <= size); if (size == IGRAPH_INTEGER_MAX) { IGRAPH_ERROR("Cannot insert to vector, already at maximum size.", IGRAPH_EOVERFLOW); @@ -647,7 +658,7 @@ igraph_error_t FUNCTION(igraph_vector, insert)( * Time complexity: O(1). */ -BASE FUNCTION(igraph_vector, get)(const TYPE(igraph_vector) *v, igraph_integer_t pos) { +BASE FUNCTION(igraph_vector, get)(const TYPE(igraph_vector) *v, igraph_int_t pos) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return * (v->stor_begin + pos); @@ -670,7 +681,7 @@ BASE FUNCTION(igraph_vector, get)(const TYPE(igraph_vector) *v, igraph_integer_t * Time complexity: O(1). */ -BASE* FUNCTION(igraph_vector, get_ptr)(const TYPE(igraph_vector) *v, igraph_integer_t pos) { +BASE* FUNCTION(igraph_vector, get_ptr)(const TYPE(igraph_vector) *v, igraph_int_t pos) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return v->stor_begin + pos; @@ -690,7 +701,7 @@ BASE* FUNCTION(igraph_vector, get_ptr)(const TYPE(igraph_vector) *v, igraph_inte * \sa \ref igraph_vector_get(). */ -void FUNCTION(igraph_vector, set)(TYPE(igraph_vector) *v, igraph_integer_t pos, BASE value) { +void FUNCTION(igraph_vector, set)(TYPE(igraph_vector) *v, igraph_int_t pos, BASE value) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); *(v->stor_begin + pos) = value; @@ -882,7 +893,7 @@ igraph_error_t FUNCTION(igraph_vector, permute)(TYPE(igraph_vector) *v, const ig TYPE(igraph_vector) v_copy; BASE *v_ptr; - igraph_integer_t *ind_ptr; + igraph_int_t *ind_ptr; /* There is a more space-efficient algorithm that needs O(1) space only, * but it messes up the index vector, which we don't want */ @@ -1035,7 +1046,7 @@ igraph_error_t FUNCTION(igraph_vector, sort_ind)( igraph_vector_int_t *inds, igraph_order_t order) { - igraph_integer_t i, n = FUNCTION(igraph_vector, size)(v); + igraph_int_t i, n = FUNCTION(igraph_vector, size)(v); BASE **vind, *first; IGRAPH_CHECK(igraph_vector_int_resize(inds, n)); if (n == 0) { @@ -1086,7 +1097,7 @@ igraph_error_t FUNCTION(igraph_vector, sort_ind)( int FUNCTION(igraph_vector, lex_cmp)( const TYPE(igraph_vector) *lhs, const TYPE(igraph_vector) *rhs ) { - igraph_integer_t i, sa, sb; + igraph_int_t i, sa, sb; const TYPE(igraph_vector) *a = lhs, *b = rhs; sa = FUNCTION(igraph_vector, size)(a); @@ -1166,7 +1177,7 @@ int FUNCTION(igraph_vector, lex_cmp_untyped)(const void *lhs, const void *rhs) { int FUNCTION(igraph_vector, colex_cmp)( const TYPE(igraph_vector) *lhs, const TYPE(igraph_vector) *rhs ) { - igraph_integer_t i, sa, sb, rai, rbi; + igraph_int_t i, sa, sb, rai, rbi; const TYPE(igraph_vector) *a = lhs, *b = rhs; sa = FUNCTION(igraph_vector, size)(a); @@ -1254,7 +1265,7 @@ int FUNCTION(igraph_vector, colex_cmp_untyped)(const void *lhs, const void *rhs) * n is the new size of the vector. */ -igraph_error_t FUNCTION(igraph_vector, resize)(TYPE(igraph_vector)* v, igraph_integer_t new_size) { +igraph_error_t FUNCTION(igraph_vector, resize)(TYPE(igraph_vector)* v, igraph_int_t new_size) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); IGRAPH_CHECK(FUNCTION(igraph_vector, reserve)(v, new_size)); @@ -1280,7 +1291,7 @@ igraph_error_t FUNCTION(igraph_vector, resize)(TYPE(igraph_vector)* v, igraph_in */ void FUNCTION(igraph_vector, resize_min)(TYPE(igraph_vector) *v) { - igraph_integer_t size; + igraph_int_t size; BASE *tmp; if (v->stor_end == v->end) { return; @@ -1355,7 +1366,7 @@ BASE FUNCTION(igraph_vector, max)(const TYPE(igraph_vector) *v) { * * Time complexity: O(n), n is the size of the vector. */ -igraph_integer_t FUNCTION(igraph_vector, which_max)(const TYPE(igraph_vector) *v) { +igraph_int_t FUNCTION(igraph_vector, which_max)(const TYPE(igraph_vector) *v) { BASE *max; BASE *ptr; IGRAPH_ASSERT(!FUNCTION(igraph_vector, empty)(v)); @@ -1428,7 +1439,7 @@ BASE FUNCTION(igraph_vector, min)(const TYPE(igraph_vector) *v) { * * Time complexity: O(n), the number of elements. */ -igraph_integer_t FUNCTION(igraph_vector, which_min)(const TYPE(igraph_vector)* v) { +igraph_int_t FUNCTION(igraph_vector, which_min)(const TYPE(igraph_vector)* v) { BASE *min; BASE *ptr; IGRAPH_ASSERT(!FUNCTION(igraph_vector, empty)(v)); @@ -1473,7 +1484,7 @@ igraph_integer_t FUNCTION(igraph_vector, which_min)(const TYPE(igraph_vector)* v */ igraph_error_t FUNCTION(igraph_vector, init_array)( - TYPE(igraph_vector) *v, const BASE *data, igraph_integer_t length) { + TYPE(igraph_vector) *v, const BASE *data, igraph_int_t length) { IGRAPH_CHECK(FUNCTION(igraph_vector, init)(v, length)); @@ -1529,7 +1540,7 @@ void FUNCTION(igraph_vector, copy_to)(const TYPE(igraph_vector) *v, BASE *to) { igraph_error_t FUNCTION(igraph_vector, init_copy)( TYPE(igraph_vector) *to, const TYPE(igraph_vector) *from ) { - igraph_integer_t from_size; + igraph_int_t from_size; IGRAPH_ASSERT(from != NULL); IGRAPH_ASSERT(from->stor_begin != NULL); @@ -1706,8 +1717,8 @@ igraph_error_t FUNCTION(igraph_vector, init_range)(TYPE(igraph_vector) *v, BASE */ void FUNCTION(igraph_vector, remove_section)( - TYPE(igraph_vector) *v, igraph_integer_t from, igraph_integer_t to) { - igraph_integer_t size = FUNCTION(igraph_vector, size)(v); + TYPE(igraph_vector) *v, igraph_int_t from, igraph_int_t to) { + igraph_int_t size = FUNCTION(igraph_vector, size)(v); IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); @@ -1741,7 +1752,7 @@ void FUNCTION(igraph_vector, remove_section)( * vector. */ -void FUNCTION(igraph_vector, remove)(TYPE(igraph_vector) *v, igraph_integer_t elem) { +void FUNCTION(igraph_vector, remove)(TYPE(igraph_vector) *v, igraph_int_t elem) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); FUNCTION(igraph_vector, remove_section)(v, elem, elem + 1); @@ -1766,11 +1777,11 @@ void FUNCTION(igraph_vector, remove)(TYPE(igraph_vector) *v, igraph_integer_t el * Time complexity: O(1). */ -void FUNCTION(igraph_vector, remove_fast)(TYPE(igraph_vector) *v, igraph_integer_t elem) { +void FUNCTION(igraph_vector, remove_fast)(TYPE(igraph_vector) *v, igraph_int_t elem) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); - igraph_integer_t len = FUNCTION(igraph_vector, size)(v); + igraph_int_t len = FUNCTION(igraph_vector, size)(v); VECTOR(*v)[elem] = VECTOR(*v)[len - 1]; FUNCTION(igraph_vector, pop_back)(v); } @@ -1794,7 +1805,7 @@ void FUNCTION(igraph_vector, remove_fast)(TYPE(igraph_vector) *v, igraph_integer */ igraph_error_t FUNCTION(igraph_vector, move_interval)(TYPE(igraph_vector) *v, - igraph_integer_t begin, igraph_integer_t end, igraph_integer_t to) { + igraph_int_t begin, igraph_int_t end, igraph_int_t to) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); memmove(v->stor_begin + to, v->stor_begin + begin, @@ -1883,7 +1894,7 @@ igraph_bool_t FUNCTION(igraph_vector, any_smaller)(const TYPE(igraph_vector) *v, igraph_bool_t FUNCTION(igraph_vector, all_e)(const TYPE(igraph_vector) *lhs, const TYPE(igraph_vector) *rhs) { - igraph_integer_t i, s; + igraph_int_t i, s; IGRAPH_ASSERT(lhs != 0); IGRAPH_ASSERT(rhs != 0); IGRAPH_ASSERT(lhs->stor_begin != 0); @@ -1948,7 +1959,7 @@ igraph_bool_t FUNCTION(igraph_vector, is_equal)(const TYPE(igraph_vector) *lhs, igraph_bool_t FUNCTION(igraph_vector, all_l)(const TYPE(igraph_vector) *lhs, const TYPE(igraph_vector) *rhs) { - igraph_integer_t i, s; + igraph_int_t i, s; IGRAPH_ASSERT(lhs != 0); IGRAPH_ASSERT(rhs != 0); IGRAPH_ASSERT(lhs->stor_begin != 0); @@ -1987,7 +1998,7 @@ igraph_bool_t FUNCTION(igraph_vector, all_l)(const TYPE(igraph_vector) *lhs, igraph_bool_t FUNCTION(igraph_vector, all_g)(const TYPE(igraph_vector) *lhs, const TYPE(igraph_vector) *rhs) { - igraph_integer_t i, s; + igraph_int_t i, s; IGRAPH_ASSERT(lhs != 0); IGRAPH_ASSERT(rhs != 0); IGRAPH_ASSERT(lhs->stor_begin != 0); @@ -2025,7 +2036,7 @@ igraph_bool_t FUNCTION(igraph_vector, all_g)(const TYPE(igraph_vector) *lhs, igraph_bool_t FUNCTION(igraph_vector, all_le)(const TYPE(igraph_vector) *lhs, const TYPE(igraph_vector) *rhs) { - igraph_integer_t i, s; + igraph_int_t i, s; IGRAPH_ASSERT(lhs != 0); IGRAPH_ASSERT(rhs != 0); IGRAPH_ASSERT(lhs->stor_begin != 0); @@ -2063,7 +2074,7 @@ igraph_bool_t FUNCTION(igraph_vector, all_le)(const TYPE(igraph_vector) *lhs, igraph_bool_t FUNCTION(igraph_vector, all_ge)(const TYPE(igraph_vector) *lhs, const TYPE(igraph_vector) *rhs) { - igraph_integer_t i, s; + igraph_int_t i, s; IGRAPH_ASSERT(lhs != 0); IGRAPH_ASSERT(rhs != 0); IGRAPH_ASSERT(lhs->stor_begin != 0); @@ -2090,7 +2101,7 @@ igraph_bool_t FUNCTION(igraph_vector, all_ge)(const TYPE(igraph_vector) *lhs, #ifndef NOTORDERED static igraph_bool_t FUNCTION(igraph_i_vector, binsearch_slice)(const TYPE(igraph_vector) *v, - BASE what, igraph_integer_t *pos, igraph_integer_t start, igraph_integer_t end); + BASE what, igraph_int_t *pos, igraph_int_t start, igraph_int_t end); /** * \ingroup vector @@ -2106,7 +2117,7 @@ static igraph_bool_t FUNCTION(igraph_i_vector, binsearch_slice)(const TYPE(igrap * * \param v The \type igraph_vector_t object. * \param what The element to search for. - * \param pos Pointer to an \type igraph_integer_t. This is set to the + * \param pos Pointer to an \type igraph_int_t. This is set to the * position of an instance of \p what in the * vector if it is present. If \p v does not * contain \p what then @@ -2120,7 +2131,7 @@ static igraph_bool_t FUNCTION(igraph_i_vector, binsearch_slice)(const TYPE(igrap */ igraph_bool_t FUNCTION(igraph_vector, binsearch)(const TYPE(igraph_vector) *v, - BASE what, igraph_integer_t *pos) { + BASE what, igraph_int_t *pos) { return FUNCTION(igraph_i_vector, binsearch_slice)(v, what, pos, 0, FUNCTION(igraph_vector, size)(v)); } @@ -2142,7 +2153,7 @@ igraph_bool_t FUNCTION(igraph_vector, binsearch)(const TYPE(igraph_vector) *v, * * \param v The \type igraph_vector_t object. * \param what The element to search for. - * \param pos Pointer to an \type igraph_integer_t. This is set to the position of an + * \param pos Pointer to an \type igraph_int_t. This is set to the position of an * instance of \p what in the slice of the vector if it is present. If \p * v does not contain \p what then \p pos is set to the position to which * it should be inserted (to keep the vector sorted). @@ -2155,9 +2166,9 @@ igraph_bool_t FUNCTION(igraph_vector, binsearch)(const TYPE(igraph_vector) *v, */ igraph_bool_t FUNCTION(igraph_vector, binsearch_slice)(const TYPE(igraph_vector) *v, - BASE what, igraph_integer_t *pos, igraph_integer_t start, igraph_integer_t end) { - igraph_integer_t left = start; - igraph_integer_t right = end - 1; + BASE what, igraph_int_t *pos, igraph_int_t start, igraph_int_t end) { + igraph_int_t left = start; + igraph_int_t right = end - 1; if (left < 0) IGRAPH_ERROR("Invalid start position.", IGRAPH_EINVAL); @@ -2173,13 +2184,13 @@ igraph_bool_t FUNCTION(igraph_vector, binsearch_slice)(const TYPE(igraph_vector) } static igraph_bool_t FUNCTION(igraph_i_vector, binsearch_slice)(const TYPE(igraph_vector) *v, - BASE what, igraph_integer_t *pos, igraph_integer_t start, igraph_integer_t end) { - igraph_integer_t left = start; - igraph_integer_t right = end - 1; + BASE what, igraph_int_t *pos, igraph_int_t start, igraph_int_t end) { + igraph_int_t left = start; + igraph_int_t right = end - 1; while (left <= right) { /* (right + left) / 2 could theoretically overflow for long vectors */ - igraph_integer_t middle = left + ((right - left) >> 1); + igraph_int_t middle = left + ((right - left) >> 1); if (VECTOR(*v)[middle] > what) { right = middle - 1; } else if (VECTOR(*v)[middle] < what) { @@ -2215,12 +2226,12 @@ static igraph_bool_t FUNCTION(igraph_i_vector, binsearch_slice)(const TYPE(igrap */ igraph_bool_t FUNCTION(igraph_vector, contains_sorted)(const TYPE(igraph_vector) *v, BASE what) { - igraph_integer_t left = 0; - igraph_integer_t right = FUNCTION(igraph_vector, size)(v) - 1; + igraph_int_t left = 0; + igraph_int_t right = FUNCTION(igraph_vector, size)(v) - 1; while (left <= right) { /* (right + left) / 2 could theoretically overflow for long vectors */ - igraph_integer_t middle = left + ((right - left) >> 1); + igraph_int_t middle = left + ((right - left) >> 1); if (what < VECTOR(*v)[middle]) { right = middle - 1; } else if (what > VECTOR(*v)[middle]) { @@ -2249,8 +2260,18 @@ igraph_bool_t FUNCTION(igraph_vector, contains_sorted)(const TYPE(igraph_vector) */ void FUNCTION(igraph_vector, scale)(TYPE(igraph_vector) *v, BASE by) { - igraph_integer_t i; - for (i = 0; i < FUNCTION(igraph_vector, size)(v); i++) { + const igraph_int_t n = FUNCTION(igraph_vector, size)(v); +#ifdef EQ + const BASE one = ONE; + if (EQ(by, one)) { + return; + } +#else + if (by == ONE) { + return; + } +#endif + for (igraph_int_t i = 0; i < n; i++) { #ifdef PROD PROD(VECTOR(*v)[i], VECTOR(*v)[i], by); #else @@ -2272,8 +2293,18 @@ void FUNCTION(igraph_vector, scale)(TYPE(igraph_vector) *v, BASE by) { */ void FUNCTION(igraph_vector, add_constant)(TYPE(igraph_vector) *v, BASE plus) { - igraph_integer_t i, n = FUNCTION(igraph_vector, size)(v); - for (i = 0; i < n; i++) { + const igraph_int_t n = FUNCTION(igraph_vector, size)(v); +#ifdef EQ + const BASE zero = ZERO; + if (EQ(plus, zero)) { + return; + } +#else + if (plus == ZERO) { + return; + } +#endif + for (igraph_int_t i = 0; i < n; i++) { #ifdef SUM SUM(VECTOR(*v)[i], VECTOR(*v)[i], plus); #else @@ -2334,8 +2365,8 @@ igraph_bool_t FUNCTION(igraph_vector, contains)(const TYPE(igraph_vector) *v, */ igraph_bool_t FUNCTION(igraph_vector, search)(const TYPE(igraph_vector) *v, - igraph_integer_t from, BASE what, igraph_integer_t *pos) { - igraph_integer_t i, n = FUNCTION(igraph_vector, size)(v); + igraph_int_t from, BASE what, igraph_int_t *pos) { + igraph_int_t i, n = FUNCTION(igraph_vector, size)(v); for (i = from; i < n; i++) { #ifdef EQ if (EQ(VECTOR(*v)[i], what)) { @@ -2367,8 +2398,8 @@ igraph_bool_t FUNCTION(igraph_vector, search)(const TYPE(igraph_vector) *v, igraph_error_t FUNCTION(igraph_vector, filter_smaller)(TYPE(igraph_vector) *v, BASE elem) { - igraph_integer_t i = 0, n = FUNCTION(igraph_vector, size)(v); - igraph_integer_t s; + igraph_int_t i = 0, n = FUNCTION(igraph_vector, size)(v); + igraph_int_t s; while (i < n && VECTOR(*v)[i] < elem) { i++; } @@ -2401,15 +2432,15 @@ igraph_error_t FUNCTION(igraph_vector, append)(TYPE(igraph_vector) *to, IGRAPH_ASSERT(to != NULL); IGRAPH_ASSERT(to->stor_begin != NULL); - const igraph_integer_t to_size = FUNCTION(igraph_vector, size)(to); - const igraph_integer_t from_size = FUNCTION(igraph_vector, size)(from); - const igraph_integer_t to_capacity = FUNCTION(igraph_vector, capacity)(to); - igraph_integer_t new_to_size; + const igraph_int_t to_size = FUNCTION(igraph_vector, size)(to); + const igraph_int_t from_size = FUNCTION(igraph_vector, size)(from); + const igraph_int_t to_capacity = FUNCTION(igraph_vector, capacity)(to); + igraph_int_t new_to_size; IGRAPH_SAFE_ADD(to_size, from_size, &new_to_size); if (to_capacity < new_to_size) { - igraph_integer_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; if (new_to_capacity < new_to_size) { new_to_capacity = new_to_size; } @@ -2428,7 +2459,7 @@ igraph_error_t FUNCTION(igraph_vector, append)(TYPE(igraph_vector) *to, */ igraph_error_t FUNCTION(igraph_vector, get_interval)(const TYPE(igraph_vector) *v, - TYPE(igraph_vector) *res, igraph_integer_t from, igraph_integer_t to) { + TYPE(igraph_vector) *res, igraph_int_t from, igraph_int_t to) { IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(res, to - from)); memcpy(res->stor_begin, v->stor_begin + from, (to - from) * sizeof(BASE)); @@ -2455,10 +2486,10 @@ igraph_error_t FUNCTION(igraph_vector, get_interval)(const TYPE(igraph_vector) * igraph_real_t FUNCTION(igraph_vector, maxdifference)(const TYPE(igraph_vector) *m1, const TYPE(igraph_vector) *m2) { - igraph_integer_t n1 = FUNCTION(igraph_vector, size)(m1); - igraph_integer_t n2 = FUNCTION(igraph_vector, size)(m2); - igraph_integer_t n = n1 < n2 ? n1 : n2; - igraph_integer_t i; + igraph_int_t n1 = FUNCTION(igraph_vector, size)(m1); + igraph_int_t n2 = FUNCTION(igraph_vector, size)(m2); + igraph_int_t n = n1 < n2 ? n1 : n2; + igraph_int_t i; igraph_real_t diff = 0.0; for (i = 0; i < n; i++) { @@ -2495,7 +2526,7 @@ igraph_real_t FUNCTION(igraph_vector, maxdifference)(const TYPE(igraph_vector) * igraph_error_t FUNCTION(igraph_vector, update)(TYPE(igraph_vector) *to, const TYPE(igraph_vector) *from) { - igraph_integer_t n = FUNCTION(igraph_vector, size)(from); + igraph_int_t n = FUNCTION(igraph_vector, size)(from); IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(to, n)); memcpy(to->stor_begin, from->stor_begin, sizeof(BASE)*n); return IGRAPH_SUCCESS; @@ -2534,7 +2565,7 @@ void FUNCTION(igraph_vector, swap)(TYPE(igraph_vector) *v1, TYPE(igraph_vector) */ void FUNCTION(igraph_vector, swap_elements)(TYPE(igraph_vector) *v, - igraph_integer_t i, igraph_integer_t j) { + igraph_int_t i, igraph_int_t j) { BASE tmp = VECTOR(*v)[i]; VECTOR(*v)[i] = VECTOR(*v)[j]; VECTOR(*v)[j] = tmp; @@ -2553,9 +2584,9 @@ void FUNCTION(igraph_vector, swap_elements)(TYPE(igraph_vector) *v, * Time complexity: O(to - from), the number of elements to reverse. */ -void FUNCTION(igraph_vector, reverse_section)(TYPE(igraph_vector) *v, igraph_integer_t from, igraph_integer_t to) { - const igraph_integer_t mid = (from + to) / 2; - for (igraph_integer_t i = from, j = to - 1; i < mid; i++, j--) { +void FUNCTION(igraph_vector, reverse_section)(TYPE(igraph_vector) *v, igraph_int_t from, igraph_int_t to) { + const igraph_int_t mid = (from + to) / 2; + for (igraph_int_t i = from, j = to - 1; i < mid; i++, j--) { BASE tmp = VECTOR(*v)[i]; VECTOR(*v)[i] = VECTOR(*v)[j]; VECTOR(*v)[j] = tmp; @@ -2596,8 +2627,8 @@ void FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v) { * Time complexity: O(n), the number of elements. */ -void FUNCTION(igraph_vector, rotate_left)(TYPE(igraph_vector) *v, igraph_integer_t n) { - const igraph_integer_t size = FUNCTION(igraph_vector, size)(v); +void FUNCTION(igraph_vector, rotate_left)(TYPE(igraph_vector) *v, igraph_int_t n) { + const igraph_int_t size = FUNCTION(igraph_vector, size)(v); n = n % size; if (n < 0) n += size; if (n == 0) return; @@ -2639,8 +2670,8 @@ void FUNCTION(igraph_vector, rotate_left)(TYPE(igraph_vector) *v, igraph_integer */ void FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v) { - igraph_integer_t n = FUNCTION(igraph_vector, size)(v); - igraph_integer_t k; + igraph_int_t n = FUNCTION(igraph_vector, size)(v); + igraph_int_t k; BASE dummy; while (n > 1) { @@ -2668,9 +2699,9 @@ void FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v) { igraph_error_t FUNCTION(igraph_vector, add)(TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2) { - igraph_integer_t n1 = FUNCTION(igraph_vector, size)(v1); - igraph_integer_t n2 = FUNCTION(igraph_vector, size)(v2); - igraph_integer_t i; + igraph_int_t n1 = FUNCTION(igraph_vector, size)(v1); + igraph_int_t n2 = FUNCTION(igraph_vector, size)(v2); + igraph_int_t i; if (n1 != n2) { IGRAPH_ERROR("Vectors to be added must have the same sizes.", IGRAPH_EINVAL); @@ -2704,9 +2735,9 @@ igraph_error_t FUNCTION(igraph_vector, add)(TYPE(igraph_vector) *v1, igraph_error_t FUNCTION(igraph_vector, sub)(TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2) { - igraph_integer_t n1 = FUNCTION(igraph_vector, size)(v1); - igraph_integer_t n2 = FUNCTION(igraph_vector, size)(v2); - igraph_integer_t i; + igraph_int_t n1 = FUNCTION(igraph_vector, size)(v1); + igraph_int_t n2 = FUNCTION(igraph_vector, size)(v2); + igraph_int_t i; if (n1 != n2) { IGRAPH_ERROR("Vectors to be subtracted must have the same sizes.", IGRAPH_EINVAL); @@ -2739,9 +2770,9 @@ igraph_error_t FUNCTION(igraph_vector, sub)(TYPE(igraph_vector) *v1, igraph_error_t FUNCTION(igraph_vector, mul)(TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2) { - igraph_integer_t n1 = FUNCTION(igraph_vector, size)(v1); - igraph_integer_t n2 = FUNCTION(igraph_vector, size)(v2); - igraph_integer_t i; + igraph_int_t n1 = FUNCTION(igraph_vector, size)(v1); + igraph_int_t n2 = FUNCTION(igraph_vector, size)(v2); + igraph_int_t i; if (n1 != n2) { IGRAPH_ERROR("Vectors to be multiplied must have the same sizes.", IGRAPH_EINVAL); @@ -2776,9 +2807,9 @@ igraph_error_t FUNCTION(igraph_vector, mul)(TYPE(igraph_vector) *v1, igraph_error_t FUNCTION(igraph_vector, div)(TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2) { - igraph_integer_t n1 = FUNCTION(igraph_vector, size)(v1); - igraph_integer_t n2 = FUNCTION(igraph_vector, size)(v2); - igraph_integer_t i; + igraph_int_t n1 = FUNCTION(igraph_vector, size)(v1); + igraph_int_t n2 = FUNCTION(igraph_vector, size)(v2); + igraph_int_t i; if (n1 != n2) { IGRAPH_ERROR("Vectors to be divided must have the same sizes.", IGRAPH_EINVAL); @@ -2802,7 +2833,7 @@ igraph_error_t FUNCTION(igraph_vector, abs)(TYPE(igraph_vector) *v) { /* Nothing do to, unsigned type */ IGRAPH_UNUSED(v); #else - igraph_integer_t i, n = FUNCTION(igraph_vector, size)(v); + igraph_int_t i, n = FUNCTION(igraph_vector, size)(v); for (i = 0; i < n; i++) { VECTOR(*v)[i] = VECTOR(*v)[i] >= 0 ? VECTOR(*v)[i] : -VECTOR(*v)[i]; } @@ -2876,7 +2907,7 @@ void FUNCTION(igraph_vector, minmax)(const TYPE(igraph_vector) *v, */ void FUNCTION(igraph_vector, which_minmax)(const TYPE(igraph_vector) *v, - igraph_integer_t *which_min, igraph_integer_t *which_max) { + igraph_int_t *which_min, igraph_int_t *which_max) { BASE *min, *max; BASE *ptr; IGRAPH_ASSERT(!FUNCTION(igraph_vector, empty)(v)); @@ -2922,8 +2953,8 @@ void FUNCTION(igraph_vector, which_minmax)(const TYPE(igraph_vector) *v, igraph_bool_t FUNCTION(igraph_vector, isnull)(const TYPE(igraph_vector) *v) { - igraph_integer_t n = FUNCTION(igraph_vector, size)(v); - igraph_integer_t i = 0; + igraph_int_t n = FUNCTION(igraph_vector, size)(v); + igraph_int_t i = 0; #ifdef EQ while (i < n && EQ(VECTOR(*v)[i], (BASE) ZERO)) { @@ -2945,10 +2976,10 @@ igraph_bool_t FUNCTION(igraph_vector, isnull)(const TYPE(igraph_vector) *v) { /* Recursive Baeza-Yates intersection algorithm for sorted vector intersection. */ static igraph_error_t FUNCTION(igraph_i_vector, intersect_sorted)( - const TYPE(igraph_vector) *v1, igraph_integer_t begin1, igraph_integer_t end1, - const TYPE(igraph_vector) *v2, igraph_integer_t begin2, igraph_integer_t end2, + const TYPE(igraph_vector) *v1, igraph_int_t begin1, igraph_int_t end1, + const TYPE(igraph_vector) *v2, igraph_int_t begin2, igraph_int_t end2, TYPE(igraph_vector) *result) { - igraph_integer_t size1, size2, probe1, probe2; + igraph_int_t size1, size2, probe1, probe2; if (begin1 == end1 || begin2 == end2) { return IGRAPH_SUCCESS; @@ -3025,7 +3056,7 @@ static igraph_error_t FUNCTION(igraph_i_vector, intersect_sorted)( */ igraph_error_t FUNCTION(igraph_vector, intersect_sorted)(const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2, TYPE(igraph_vector) *result) { - igraph_integer_t size1, size2; + igraph_int_t size1, size2; igraph_real_t r; size1 = FUNCTION(igraph_vector, size)(v1); @@ -3042,7 +3073,7 @@ igraph_error_t FUNCTION(igraph_vector, intersect_sorted)(const TYPE(igraph_vecto /* When the set size ratio is small, use a simple linear scan. See comments in * igraph_vector_intersection_size_sorted() for the justification of this r threshold. */ if (r < 10) { - igraph_integer_t i1 = 0, i2 = 0; + igraph_int_t i1 = 0, i2 = 0; while (i1 < size1 && i2 < size2) { BASE e1 = VECTOR(*v1)[i1], e2 = VECTOR(*v2)[i2]; if (e1 < e2) { @@ -3063,11 +3094,11 @@ igraph_error_t FUNCTION(igraph_vector, intersect_sorted)(const TYPE(igraph_vecto /* Recursive Baeza-Yates intersection algorithm for sorted vector intersection size. */ static void FUNCTION(igraph_i_vector, intersection_size_sorted)( - const TYPE(igraph_vector) *v1, igraph_integer_t begin1, igraph_integer_t end1, - const TYPE(igraph_vector) *v2, igraph_integer_t begin2, igraph_integer_t end2, - igraph_integer_t *result) { + const TYPE(igraph_vector) *v1, igraph_int_t begin1, igraph_int_t end1, + const TYPE(igraph_vector) *v2, igraph_int_t begin2, igraph_int_t end2, + igraph_int_t *result) { - igraph_integer_t size1, size2, probe1, probe2; + igraph_int_t size1, size2, probe1, probe2; if (begin1 == end1 || begin2 == end2) { return; @@ -3109,8 +3140,6 @@ static void FUNCTION(igraph_i_vector, intersection_size_sorted)( * \function igraph_vector_intersection_size_sorted * \brief Intersection size of two sorted vectors. * - * \experimental - * * Counts elements that are present in both vectors. This is particularly * useful for counting common neighbours of two vertices. * @@ -3142,11 +3171,11 @@ static void FUNCTION(igraph_i_vector, intersection_size_sorted)( * and n is the size of the larger one. */ -igraph_integer_t FUNCTION(igraph_vector, intersection_size_sorted)( +igraph_int_t FUNCTION(igraph_vector, intersection_size_sorted)( const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2) { - igraph_integer_t size1, size2, count; + igraph_int_t size1, size2, count; igraph_real_t r; size1 = FUNCTION(igraph_vector, size)(v1); @@ -3168,10 +3197,10 @@ igraph_integer_t FUNCTION(igraph_vector, intersection_size_sorted)( if (r < 10) { /* This is a fast branchless implementation that uses arithmetic * instead of conditionals. */ - igraph_integer_t i1 = 0, i2 = 0; + igraph_int_t i1 = 0, i2 = 0; while (i1 < size1 && i2 < size2) { BASE e1 = VECTOR(*v1)[i1], e2 = VECTOR(*v2)[i2]; - igraph_integer_t d1 = (e1 <= e2), d2 = (e1 >= e2); + igraph_int_t d1 = (e1 <= e2), d2 = (e1 >= e2); i1 += d1; i2 += d2; count += (d1 == d2); } @@ -3190,65 +3219,147 @@ igraph_integer_t FUNCTION(igraph_vector, intersection_size_sorted)( * The elements that are contained in only the first vector but not the second are * stored in the result vector. All three vectors must be initialized. * + * + * The algorithm keeps the multiplicities of the elements: if an element appears + * \c k1 times in the first vector and \c k2 times in the second, the result + * will include that element max(0, k1-k2) times. + * * \param v1 the first vector * \param v2 the second vector * \param result the result vector */ igraph_error_t FUNCTION(igraph_vector, difference_sorted)(const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2, TYPE(igraph_vector) *result) { - igraph_integer_t i, j, i0, j0; + return FUNCTION(igraph_vector, difference_and_intersection_sorted)( + v1, v2, result, NULL, NULL + ); +} + +/** + * \function igraph_vector_difference_and_intersection_sorted + * \brief Simultaneous difference and intersection of two sorted vectors. + * + * This function iterates over all the elements of the two input vectors and + * sorts them into three other vectors: elements that are in the first vector + * but not in the second, elements that are in the second vector but not in the + * first, and the intersection of the two vectors. The input vectors must be + * initialized. The output arguments can be \c NULL, but they must be initialized + * if they are not \c NULL and will be resized accordingly. + * + * + * The multiplicities of the individual elements are treated consistently with + * \ref igraph_vector_difference_sorted() and \ref igraph_vector_intersect_sorted(): + * The algorithm keeps the multiplicities of the elements: if an element appears + * \c k1 times in the first vector and \c k2 times in the second, the intersection + * vector will include that element min(k1, k2) times, while the + * difference vectors will include that element max(0, k1-k2) and + * max(0, k2-k1) times, respectively. + * + * \param v1 the first vector + * \param v2 the second vector + * \param vdiff12 output vector containing the elements that are in the first + * vector but not the second one, or \c NULL if not needed + * \param vdiff21 output vector containing the elements that are in the second + * vector but not the first one, or \c NULL if not needed + * \param vint output vector containing the intersection, or \c NULL if not + * needed + */ +igraph_error_t FUNCTION(igraph_vector, difference_and_intersection_sorted)( + const TYPE(igraph_vector) *v1, const TYPE(igraph_vector) *v2, + TYPE(igraph_vector) *vdiff12, TYPE(igraph_vector)*vdiff21, + TYPE(igraph_vector)*vint) { + igraph_int_t i, j, i0, j0, oldsize; i0 = FUNCTION(igraph_vector, size)(v1); j0 = FUNCTION(igraph_vector, size)(v2); i = j = 0; + if (!vdiff12 && !vdiff21 && !vint) { + /* nothing to compute */ + return IGRAPH_SUCCESS; + } + + if (vdiff12) { + FUNCTION(igraph_vector, clear)(vdiff12); + } + if (vdiff21) { + FUNCTION(igraph_vector, clear)(vdiff21); + } + if (vint) { + FUNCTION(igraph_vector, clear)(vint); + } + if (i0 == 0) { /* v1 is empty, this is easy */ - FUNCTION(igraph_vector, clear)(result); + if (vdiff21) { + IGRAPH_CHECK(FUNCTION(igraph_vector, update)(vdiff21, v2)); + } return IGRAPH_SUCCESS; } if (j0 == 0) { /* v2 is empty, this is easy */ - IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(result, i0)); - memcpy(result->stor_begin, v1->stor_begin, sizeof(BASE) * i0); + if (vdiff12) { + IGRAPH_CHECK(FUNCTION(igraph_vector, update)(vdiff12, v1)); + } return IGRAPH_SUCCESS; } - FUNCTION(igraph_vector, clear)(result); - /* Copy the part of v1 that is less than the first element of v2 */ while (i < i0 && VECTOR(*v1)[i] < VECTOR(*v2)[j]) { i++; } - if (i > 0) { - IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(result, i)); - memcpy(result->stor_begin, v1->stor_begin, sizeof(BASE) * i); + if (vdiff12 && i > 0) { + IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(vdiff12, i)); + memcpy(vdiff12->stor_begin, v1->stor_begin, sizeof(BASE) * i); } + /* Copy the part of v2 that is less than the first element of v1 */ + while (j < j0 && VECTOR(*v2)[j] < VECTOR(*v1)[i]) { + j++; + } + if (vdiff21 && j > 0) { + IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(vdiff21, j)); + memcpy(vdiff21->stor_begin, v2->stor_begin, sizeof(BASE) * j); + } + + /* Now process the common segments */ while (i < i0 && j < j0) { - BASE element = VECTOR(*v1)[i]; - if (element == VECTOR(*v2)[j]) { + BASE element1 = VECTOR(*v1)[i]; + BASE element2 = VECTOR(*v2)[j]; + if (element1 == element2) { i++; j++; - while (i < i0 && VECTOR(*v1)[i] == element) { - i++; + if (vint) { + IGRAPH_CHECK(FUNCTION(igraph_vector, push_back)(vint, element1)); } - while (j < j0 && VECTOR(*v2)[j] == element) { - j++; + } else if (element1 < element2) { + if (vdiff12) { + IGRAPH_CHECK(FUNCTION(igraph_vector, push_back)(vdiff12, element1)); } - } else if (element < VECTOR(*v2)[j]) { - IGRAPH_CHECK(FUNCTION(igraph_vector, push_back)(result, element)); i++; } else { + if (vdiff21) { + IGRAPH_CHECK(FUNCTION(igraph_vector, push_back)(vdiff21, element2)); + } j++; } } - if (i < i0) { - igraph_integer_t oldsize = FUNCTION(igraph_vector, size)(result); - IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(result, oldsize + i0 - i)); - memcpy(result->stor_begin + oldsize, v1->stor_begin + i, + + /* Copy the part of v1 that is greater than the last element of v2 */ + if (vdiff12 && i < i0) { + oldsize = FUNCTION(igraph_vector, size)(vdiff12); + IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(vdiff12, oldsize + i0 - i)); + memcpy(vdiff12->stor_begin + oldsize, v1->stor_begin + i, sizeof(BASE) * (i0 - i)); } + /* Copy the part of v2 that is greater than the last element of v1 */ + if (vdiff21 && j < j0) { + oldsize = FUNCTION(igraph_vector, size)(vdiff21); + IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(vdiff21, oldsize + j0 - j)); + memcpy(vdiff21->stor_begin + oldsize, v2->stor_begin + j, + sizeof(BASE) * (j0 - j)); + } + return IGRAPH_SUCCESS; } @@ -3257,7 +3368,7 @@ igraph_error_t FUNCTION(igraph_vector, difference_sorted)(const TYPE(igraph_vect #ifdef OUT_FORMAT #ifndef USING_R igraph_error_t FUNCTION(igraph_vector, printf)(const TYPE(igraph_vector) *v, const char *format) { - igraph_integer_t i, n = FUNCTION(igraph_vector, size)(v); + igraph_int_t i, n = FUNCTION(igraph_vector, size)(v); if (n != 0) { printf(format, VECTOR(*v)[0]); } @@ -3279,7 +3390,7 @@ igraph_error_t FUNCTION(igraph_vector, print)(const TYPE(igraph_vector) *v) { #endif igraph_error_t FUNCTION(igraph_vector, fprint)(const TYPE(igraph_vector) *v, FILE *file) { - igraph_integer_t i, n = FUNCTION(igraph_vector, size)(v); + igraph_int_t i, n = FUNCTION(igraph_vector, size)(v); if (n != 0) { #ifdef FPRINTFUNC FPRINTFUNC(file, VECTOR(*v)[0]); @@ -3315,7 +3426,7 @@ igraph_error_t FUNCTION(igraph_vector, index)(const TYPE(igraph_vector) *v, TYPE(igraph_vector) *newv, const igraph_vector_int_t *idx) { - igraph_integer_t i, j, newlen = igraph_vector_int_size(idx); + igraph_int_t i, j, newlen = igraph_vector_int_size(idx); IGRAPH_CHECK(FUNCTION(igraph_vector, resize)(newv, newlen)); for (i = 0; i < newlen; i++) { @@ -3340,7 +3451,7 @@ igraph_error_t FUNCTION(igraph_vector, index)(const TYPE(igraph_vector) *v, igraph_error_t FUNCTION(igraph_vector, index_in_place)(TYPE(igraph_vector) *v, const igraph_vector_int_t *idx) { BASE *tmp; - igraph_integer_t i, n = igraph_vector_int_size(idx); + igraph_int_t i, n = igraph_vector_int_size(idx); tmp = IGRAPH_CALLOC(n, BASE); if (!tmp) { diff --git a/src/vendor/cigraph/src/core/vector_list.c b/src/vendor/cigraph/src/core/vector_list.c index bd51b4ccc28..93455d2af51 100644 --- a/src/vendor/cigraph/src/core/vector_list.c +++ b/src/vendor/cigraph/src/core/vector_list.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/core/vector_ptr.c b/src/vendor/cigraph/src/core/vector_ptr.c index 182afb82465..f451713cd39 100644 --- a/src/vendor/cigraph/src/core/vector_ptr.c +++ b/src/vendor/cigraph/src/core/vector_ptr.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -83,8 +83,8 @@ * time \endquote required to allocate \p size elements. */ -igraph_error_t igraph_vector_ptr_init(igraph_vector_ptr_t* v, igraph_integer_t size) { - igraph_integer_t alloc_size = size > 0 ? size : 1; +igraph_error_t igraph_vector_ptr_init(igraph_vector_ptr_t* v, igraph_int_t size) { + igraph_int_t alloc_size = size > 0 ? size : 1; IGRAPH_ASSERT(v != NULL); if (size < 0) { size = 0; @@ -103,14 +103,14 @@ igraph_error_t igraph_vector_ptr_init(igraph_vector_ptr_t* v, igraph_integer_t s /** */ -const igraph_vector_ptr_t *igraph_vector_ptr_view( - const igraph_vector_ptr_t *v, void *const *data, igraph_integer_t length +igraph_vector_ptr_t igraph_vector_ptr_view( + void *const *data, igraph_int_t length ) { - igraph_vector_ptr_t *v2 = (igraph_vector_ptr_t*) v; - v2->stor_begin = (void **)data; - v2->stor_end = (void**)data + length; - v2->end = v2->stor_end; - v2->item_destructor = 0; + igraph_vector_ptr_t v; + v.stor_begin = (void **)data; + v.stor_end = (void**)data + length; + v.end = v.stor_end; + v.item_destructor = 0; return v; } @@ -212,8 +212,8 @@ void igraph_vector_ptr_destroy_all(igraph_vector_ptr_t* v) { * \return Error code. */ -igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_integer_t capacity) { - igraph_integer_t actual_size = igraph_vector_ptr_size(v); +igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_int_t capacity) { + igraph_int_t actual_size = igraph_vector_ptr_size(v); void **tmp; IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); @@ -251,7 +251,7 @@ igraph_error_t igraph_vector_ptr_reserve(igraph_vector_ptr_t* v, igraph_integer_ */ void igraph_vector_ptr_resize_min(igraph_vector_ptr_t* v) { - igraph_integer_t size; + igraph_int_t size; void **tmp; if (v->stor_end == v->end) { return; @@ -288,7 +288,7 @@ igraph_bool_t igraph_vector_ptr_empty(const igraph_vector_ptr_t* v) { * Time complexity: O(1). */ -igraph_integer_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v) { +igraph_int_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return v->end - v->stor_begin; @@ -305,7 +305,7 @@ igraph_integer_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v) { * Time complexity: O(1). */ -igraph_integer_t igraph_vector_ptr_capacity(const igraph_vector_ptr_t* v) { +igraph_int_t igraph_vector_ptr_capacity(const igraph_vector_ptr_t* v) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return v->stor_end - v->stor_begin; @@ -363,7 +363,7 @@ igraph_error_t igraph_vector_ptr_push_back(igraph_vector_ptr_t* v, void* e) { /* full, allocate more storage */ if (v->stor_end == v->end) { - igraph_integer_t new_size = igraph_vector_ptr_size(v) * 2; + igraph_int_t new_size = igraph_vector_ptr_size(v) * 2; if (new_size == 0) { new_size = 1; } @@ -413,8 +413,8 @@ void *igraph_vector_ptr_pop_back(igraph_vector_ptr_t *v) { * \param pos The position where the new element is inserted. * \param e The inserted element */ -igraph_error_t igraph_vector_ptr_insert(igraph_vector_ptr_t* v, igraph_integer_t pos, void* e) { - igraph_integer_t size = igraph_vector_ptr_size(v); +igraph_error_t igraph_vector_ptr_insert(igraph_vector_ptr_t* v, igraph_int_t pos, void* e) { + igraph_int_t size = igraph_vector_ptr_size(v); IGRAPH_CHECK(igraph_vector_ptr_resize(v, size + 1)); if (pos < size) { memmove(v->stor_begin + pos + 1, v->stor_begin + pos, @@ -436,7 +436,7 @@ igraph_error_t igraph_vector_ptr_insert(igraph_vector_ptr_t* v, igraph_integer_t * Time complexity: O(1). */ -void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_integer_t pos) { +void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_int_t pos) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); return *(v->stor_begin + pos); @@ -454,7 +454,7 @@ void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_integer_t pos) * Time complexity: O(1). */ -void igraph_vector_ptr_set(igraph_vector_ptr_t* v, igraph_integer_t pos, void* value) { +void igraph_vector_ptr_set(igraph_vector_ptr_t* v, igraph_int_t pos, void* value) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); *(v->stor_begin + pos) = value; @@ -493,7 +493,7 @@ void igraph_vector_ptr_null(igraph_vector_ptr_t* v) { * needed to allocate the memory for the vector elements. */ -igraph_error_t igraph_vector_ptr_resize(igraph_vector_ptr_t* v, igraph_integer_t newsize) { +igraph_error_t igraph_vector_ptr_resize(igraph_vector_ptr_t* v, igraph_int_t newsize) { IGRAPH_CHECK(igraph_vector_ptr_reserve(v, newsize)); v->end = v->stor_begin + newsize; return IGRAPH_SUCCESS; @@ -512,7 +512,7 @@ igraph_error_t igraph_vector_ptr_resize(igraph_vector_ptr_t* v, igraph_integer_t * \c IGRAPH_ENOMEM if out of memory */ -igraph_error_t igraph_vector_ptr_init_array(igraph_vector_ptr_t *v, void *const *data, igraph_integer_t length) { +igraph_error_t igraph_vector_ptr_init_array(igraph_vector_ptr_t *v, void *const *data, igraph_int_t length) { v->stor_begin = IGRAPH_CALLOC(length, void*); if (v->stor_begin == 0) { IGRAPH_ERROR("Cannot initialize pointer vector from array", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ @@ -566,7 +566,7 @@ void igraph_vector_ptr_copy_to(const igraph_vector_ptr_t *v, void** to) { */ igraph_error_t igraph_vector_ptr_init_copy(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from) { - igraph_integer_t from_size; + igraph_int_t from_size; IGRAPH_ASSERT(from != NULL); /* IGRAPH_ASSERT(from->stor_begin != NULL); */ /* TODO */ @@ -591,7 +591,7 @@ igraph_error_t igraph_vector_ptr_init_copy(igraph_vector_ptr_t *to, const igraph * \brief Remove an element from a pointer vector. */ -void igraph_vector_ptr_remove(igraph_vector_ptr_t *v, igraph_integer_t pos) { +void igraph_vector_ptr_remove(igraph_vector_ptr_t *v, igraph_int_t pos) { IGRAPH_ASSERT(v != NULL); IGRAPH_ASSERT(v->stor_begin != NULL); if (pos + 1 < igraph_vector_ptr_size(v)) { /* No need to move data when removing the last element. */ @@ -628,15 +628,15 @@ void igraph_vector_ptr_sort(igraph_vector_ptr_t *v, int (*compar)(const void*, c } igraph_error_t igraph_vector_ptr_append(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from) { - const igraph_integer_t to_size = igraph_vector_ptr_size(to); - const igraph_integer_t from_size = igraph_vector_ptr_size(from); - const igraph_integer_t to_capacity = igraph_vector_ptr_capacity(to); - igraph_integer_t new_to_size; + const igraph_int_t to_size = igraph_vector_ptr_size(to); + const igraph_int_t from_size = igraph_vector_ptr_size(from); + const igraph_int_t to_capacity = igraph_vector_ptr_capacity(to); + igraph_int_t new_to_size; IGRAPH_SAFE_ADD(to_size, from_size, &new_to_size); if (to_capacity < new_to_size) { - igraph_integer_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; + igraph_int_t new_to_capacity = to_capacity < IGRAPH_INTEGER_MAX/2 ? to_capacity * 2 : IGRAPH_INTEGER_MAX; if (new_to_capacity < new_to_size) { new_to_capacity = new_to_size; } @@ -738,9 +738,9 @@ static int igraph_vector_ptr_i_sort_ind_cmp(void *thunk, const void *p1, const v igraph_error_t igraph_vector_ptr_sort_ind(igraph_vector_ptr_t *v, igraph_vector_int_t *inds, cmp_t *cmp) { - igraph_integer_t i; + igraph_int_t i; uintptr_t *vind, first; - igraph_integer_t n = igraph_vector_ptr_size(v); + igraph_int_t n = igraph_vector_ptr_size(v); IGRAPH_CHECK(igraph_vector_int_resize(inds, n)); if (n == 0) { @@ -813,7 +813,7 @@ igraph_error_t igraph_vector_ptr_permute(igraph_vector_ptr_t* v, const igraph_ve igraph_vector_ptr_t v_copy; void** v_ptr; - igraph_integer_t *ind_ptr; + igraph_int_t *ind_ptr; /* There is a more space-efficient algorithm that needs O(1) space only, * but it messes up the index vector, which we don't want */ diff --git a/src/vendor/cigraph/src/misc/cycle_bases.c b/src/vendor/cigraph/src/cycles/cycle_bases.c similarity index 86% rename from src/vendor/cigraph/src/misc/cycle_bases.c rename to src/vendor/cigraph/src/cycles/cycle_bases.c index 6ba87fd04a2..c81feab2f2d 100644 --- a/src/vendor/cigraph/src/misc/cycle_bases.c +++ b/src/vendor/cigraph/src/cycles/cycle_bases.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2021-2022 The igraph development team + igraph library. + Copyright (C) 2021-2025 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 @@ -25,7 +25,7 @@ #include "igraph_interface.h" #include "core/interruption.h" -#include "misc/order_cycle.h" +#include "cycles/order_cycle.h" /**** Fundamental cycles *****/ @@ -46,13 +46,13 @@ static igraph_error_t igraph_i_fundamental_cycles_bfs( const igraph_t *graph, igraph_vector_int_list_t *result, - igraph_integer_t start_vid, - igraph_integer_t bfs_cutoff, + igraph_int_t start_vid, + igraph_int_t bfs_cutoff, const igraph_inclist_t *inclist, igraph_vector_int_t *visited, - igraph_integer_t mark /* mark used in 'visited' */) { + igraph_int_t mark /* mark used in 'visited' */) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; igraph_vector_int_t pred_edge; igraph_vector_int_t u_back, v_back; @@ -77,18 +77,18 @@ igraph_i_fundamental_cycles_bfs( VECTOR(pred_edge)[start_vid] = -1; /* non-valid predecessor edge id for root vertex */ while (! igraph_dqueue_int_empty(&q)) { - igraph_integer_t v = igraph_dqueue_int_pop(&q); - igraph_integer_t vdist = igraph_dqueue_int_pop(&q); + igraph_int_t v = igraph_dqueue_int_pop(&q); + igraph_int_t vdist = igraph_dqueue_int_pop(&q); igraph_vector_int_t *incs = igraph_inclist_get(inclist, v); - igraph_integer_t n = igraph_vector_int_size(incs); - igraph_integer_t i, j; + igraph_int_t n = igraph_vector_int_size(incs); + igraph_int_t i, j; IGRAPH_ALLOW_INTERRUPTION(); for (i=0; i < n; ++i) { - igraph_integer_t e = VECTOR(*incs)[i]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); + igraph_int_t e = VECTOR(*incs)[i]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); if (e == VECTOR(pred_edge)[v]) { /* do not follow the edge through which we came to v */ @@ -106,13 +106,13 @@ igraph_i_fundamental_cycles_bfs( * that the distance of u from the start vertex is either the * same as that of v, or one greater. */ - igraph_integer_t up = u, vp = v; - igraph_integer_t u_back_len, v_back_len; + igraph_int_t up = u, vp = v; + igraph_int_t u_back_len, v_back_len; igraph_vector_int_t cycle; IGRAPH_CHECK(igraph_vector_int_push_back(&v_back, e)); for (;;) { - igraph_integer_t upe, vpe; + igraph_int_t upe, vpe; if (up == vp) { break; @@ -187,6 +187,7 @@ igraph_i_fundamental_cycles_bfs( * Edge directions are ignored. Multi-edges and self-loops are supported. * * \param graph The graph object. + * \param weights Currently unused. * \param result An initialized integer vector list. The result will be stored here, * each vector containing the edge IDs of a basis element. * \param start_vid If negative, a complete fundamental cycle basis is returned. @@ -196,23 +197,21 @@ igraph_i_fundamental_cycles_bfs( * \param bfs_cutoff If negative, a complete cycle basis is returned. Otherwise, only * cycles of length 2*bfs_cutoff + 1 or shorter are included. \p bfs_cutoff * is used to limit the depth of the BFS tree when searching for cycle edges. - * \param weights Currently unused. * \return Error code. * * \sa \ref igraph_minimum_cycle_basis() * * Time complexity: O(|V| + |E|). */ -igraph_error_t igraph_fundamental_cycles(const igraph_t *graph, - igraph_vector_int_list_t *result, - igraph_integer_t start_vid, - igraph_integer_t bfs_cutoff, - const igraph_vector_t *weights) { - - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t estimated_rank; - igraph_integer_t i; +igraph_error_t igraph_fundamental_cycles( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_list_t *result, + igraph_int_t start_vid, igraph_real_t bfs_cutoff) { + + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t estimated_rank; + igraph_int_t i; igraph_inclist_t inclist; igraph_vector_int_t visited; /* see comments before igraph_i_fundamental_cycles_bfs() */ @@ -264,7 +263,7 @@ igraph_error_t igraph_fundamental_cycles(const igraph_t *graph, * order for equal length ones. Lexicographic order helps keep row insertion into the reduced matrix * efficient during Gaussian elimination, by ensuring that insertions usually happen near the end. */ static int cycle_cmp(const igraph_vector_int_t *v1, const igraph_vector_int_t *v2) { - igraph_integer_t n1 = igraph_vector_int_size(v1), n2 = igraph_vector_int_size(v2); + igraph_int_t n1 = igraph_vector_int_size(v1), n2 = igraph_vector_int_size(v2); if (n1 < n2) { return -1; @@ -277,9 +276,9 @@ static int cycle_cmp(const igraph_vector_int_t *v1, const igraph_vector_int_t *v /* Adding cycle vectors produces the symmetric difference of the corresponding edge sets. */ static igraph_error_t cycle_add(const igraph_vector_int_t *a, const igraph_vector_int_t *b, igraph_vector_int_t *res) { - igraph_integer_t na = igraph_vector_int_size(a), nb = igraph_vector_int_size(b); - const igraph_integer_t *pa = VECTOR(*a), *pb = VECTOR(*b); - const igraph_integer_t *pa_end = pa + na, *pb_end = pb + nb; + igraph_int_t na = igraph_vector_int_size(a), nb = igraph_vector_int_size(b); + const igraph_int_t *pa = VECTOR(*a), *pb = VECTOR(*b); + const igraph_int_t *pa_end = pa + na, *pb_end = pb + nb; igraph_vector_int_clear(res); for (;;) { @@ -324,8 +323,8 @@ static igraph_error_t gaussian_elimination(igraph_vector_int_list_t *reduced_mat const igraph_vector_int_t *cycle, igraph_bool_t *independent) { - const igraph_integer_t nrow = igraph_vector_int_list_size(reduced_matrix); - igraph_integer_t i; + const igraph_int_t nrow = igraph_vector_int_list_size(reduced_matrix); + igraph_int_t i; igraph_vector_int_t work, tmp; @@ -390,6 +389,7 @@ static igraph_error_t gaussian_elimination(igraph_vector_int_list_t *reduced_mat * https://doi.org/10.1137%2F0216026 * * \param graph The graph object. + * \param weights Currently unused. * \param result An initialized integer vector list, the elements of the cycle * basis will be stored here as vectors of edge IDs. * \param bfs_cutoff If negative, an exact minimum cycle basis is returned. Otherwise @@ -407,23 +407,21 @@ static igraph_error_t gaussian_elimination(igraph_vector_int_list_t *reduced_mat * performance cost. If false, no guarantees are given about the ordering * of edge IDs within cycles. This parameter exists solely to control * performance tradeoffs. - * \param weights Currently unused. * \return Error code. * * \sa \ref igraph_fundamental_cycles() * * Time complexity: TODO. */ -igraph_error_t igraph_minimum_cycle_basis(const igraph_t *graph, - igraph_vector_int_list_t *result, - igraph_integer_t bfs_cutoff, - igraph_bool_t complete, - igraph_bool_t use_cycle_order, - const igraph_vector_t *weights) { - - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t rank; +igraph_error_t igraph_minimum_cycle_basis( + const igraph_t *graph, const igraph_vector_t *weights, + igraph_vector_int_list_t *result, + igraph_real_t bfs_cutoff, + igraph_bool_t complete, igraph_bool_t use_cycle_order) { + + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t rank; igraph_vector_int_list_t candidates; IGRAPH_UNUSED(weights); @@ -433,8 +431,8 @@ igraph_error_t igraph_minimum_cycle_basis(const igraph_t *graph, igraph_inclist_t inclist; igraph_vector_int_t visited; /* visited[v] % 3 is zero for unvisited vertices, see igraph_i_fundamental_cycles_bfs() */ igraph_vector_int_t degrees; - igraph_integer_t no_of_comps; - igraph_integer_t mark; + igraph_int_t no_of_comps; + igraph_int_t mark; /* We use the degrees to avoid doing a BFS from vertices with d < 3, except in special cases. * Degrees cannot be computed from the inclist because there we use IGRAPH_LOOPS_ONCE. */ @@ -454,8 +452,8 @@ igraph_error_t igraph_minimum_cycle_basis(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_list_reserve(&candidates, rank)); mark = 0; - for (igraph_integer_t i=0; i < no_of_nodes; ++i) { - igraph_integer_t degree = VECTOR(degrees)[i]; + for (igraph_int_t i=0; i < no_of_nodes; ++i) { + igraph_int_t degree = VECTOR(degrees)[i]; igraph_bool_t vis = VECTOR(visited)[i] % 3 != 0; /* was vertex i visited already? */ /* Generally, we only need to run a BFS from vertices of degree 3 or greater. @@ -483,9 +481,9 @@ igraph_error_t igraph_minimum_cycle_basis(const igraph_t *graph, /* Sort candidates by size (= weight) and remove duplicates. */ { - igraph_integer_t cand_count = igraph_vector_int_list_size(&candidates); + igraph_int_t cand_count = igraph_vector_int_list_size(&candidates); - for (igraph_integer_t i=0; i < cand_count; ++i) { + for (igraph_int_t i=0; i < cand_count; ++i) { igraph_vector_int_sort(igraph_vector_int_list_get_ptr(&candidates, i)); } igraph_vector_int_list_sort(&candidates, &cycle_cmp); @@ -498,13 +496,13 @@ igraph_error_t igraph_minimum_cycle_basis(const igraph_t *graph, /* Find a complete basis, starting with smallest elements. */ /* This is typically the slowest part of the algorithm. */ { - igraph_integer_t cand_len = igraph_vector_int_list_size(&candidates); + igraph_int_t cand_len = igraph_vector_int_list_size(&candidates); igraph_vector_int_list_t reduced_matrix; igraph_bool_t independent; IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(&reduced_matrix, 0); - for (igraph_integer_t i=0; i < cand_len; ++i) { + for (igraph_int_t i=0; i < cand_len; ++i) { const igraph_vector_int_t *cycle = igraph_vector_int_list_get_ptr(&candidates, i); IGRAPH_ALLOW_INTERRUPTION(); @@ -528,10 +526,10 @@ igraph_error_t igraph_minimum_cycle_basis(const igraph_t *graph, IGRAPH_FINALLY_CLEAN(1); if (use_cycle_order) { - igraph_integer_t result_size = igraph_vector_int_list_size(result); + igraph_int_t result_size = igraph_vector_int_list_size(result); igraph_vector_int_t tmp; IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, 0); - for (igraph_integer_t i=0; i < result_size; ++i) { + for (igraph_int_t i=0; i < result_size; ++i) { igraph_vector_int_t *cycle = igraph_vector_int_list_get_ptr(result, i); IGRAPH_CHECK(igraph_vector_int_update(&tmp, cycle)); IGRAPH_CHECK(igraph_i_order_cycle(graph, &tmp, cycle)); diff --git a/src/vendor/cigraph/src/misc/feedback_arc_set.c b/src/vendor/cigraph/src/cycles/feedback_sets.c similarity index 92% rename from src/vendor/cigraph/src/misc/feedback_arc_set.c rename to src/vendor/cigraph/src/cycles/feedback_sets.c index 03dd6ee6b1b..09f5c7aab76 100644 --- a/src/vendor/cigraph/src/misc/feedback_arc_set.c +++ b/src/vendor/cigraph/src/cycles/feedback_sets.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -16,16 +16,16 @@ along with this program. If not, see . */ -#include "igraph_structural.h" -#include "misc/feedback_arc_set.h" +#include "igraph_cycles.h" +#include "cycles/feedback_sets.h" #include "igraph_bitset.h" #include "igraph_components.h" -#include "igraph_cycles.h" #include "igraph_dqueue.h" #include "igraph_interface.h" #include "igraph_memory.h" #include "igraph_stack.h" +#include "igraph_structural.h" #include "igraph_vector.h" #include "igraph_vector_list.h" #include "igraph_visitor.h" @@ -51,14 +51,14 @@ static igraph_error_t igraph_i_find_cycle(const igraph_t *graph, igraph_neimode_t mode, const igraph_bitset_t *removed) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_stack_int_t stack; igraph_vector_int_t inc; igraph_vector_int_t vpath, epath; igraph_vector_char_t seen; /* 0 = unseen, 1 = acestor of current, 2 = seen, non-ancestor */ - igraph_integer_t ea, va; - igraph_integer_t depth; + igraph_int_t ea, va; + igraph_int_t depth; if (vertices) { igraph_vector_int_clear(vertices); @@ -97,7 +97,7 @@ static igraph_error_t igraph_i_find_cycle(const igraph_t *graph, IGRAPH_VECTOR_CHAR_INIT_FINALLY(&seen, vcount); IGRAPH_STACK_INT_INIT_FINALLY(&stack, 200); - for (igraph_integer_t v=0; v < vcount; v++) { + for (igraph_int_t v=0; v < vcount; v++) { if (VECTOR(seen)[v]) { continue; } @@ -106,7 +106,7 @@ static igraph_error_t igraph_i_find_cycle(const igraph_t *graph, IGRAPH_CHECK(igraph_stack_int_push(&stack, v)); while (! igraph_stack_int_empty(&stack)) { - igraph_integer_t x = igraph_stack_int_pop(&stack); + igraph_int_t x = igraph_stack_int_pop(&stack); if (x == -1) { PATH_POP(); continue; @@ -125,10 +125,10 @@ static igraph_error_t igraph_i_find_cycle(const igraph_t *graph, IGRAPH_CHECK(igraph_stack_int_push(&stack, -1)); IGRAPH_CHECK(igraph_incident(graph, &inc, va, mode, IGRAPH_LOOPS)); - igraph_integer_t n = igraph_vector_int_size(&inc); - for (igraph_integer_t i=0; i < n; i++) { - igraph_integer_t eb = VECTOR(inc)[i]; - igraph_integer_t vb = IGRAPH_OTHER(graph, eb, va); + igraph_int_t n = igraph_vector_int_size(&inc); + for (igraph_int_t i=0; i < n; i++) { + igraph_int_t eb = VECTOR(inc)[i]; + igraph_int_t vb = IGRAPH_OTHER(graph, eb, va); if (eb == ea) continue; if (VECTOR(seen)[vb] == 2) continue; if (removed && IGRAPH_BIT_TEST(*removed, eb)) continue; @@ -149,7 +149,7 @@ static igraph_error_t igraph_i_find_cycle(const igraph_t *graph, depth = igraph_vector_int_size(&vpath); if (depth > 0) { - igraph_integer_t i = depth; + igraph_int_t i = depth; while (VECTOR(vpath)[i-1] != va) i--; for (; i < depth; i++) { if (vertices) { @@ -185,8 +185,6 @@ static igraph_error_t igraph_i_find_cycle(const igraph_t *graph, * \function igraph_find_cycle * \brief Finds a single cycle in the graph. * - * \experimental - * * This function returns a cycle of the graph, if there is one. If the graph * is acyclic, it returns empty vectors. * @@ -385,8 +383,6 @@ igraph_error_t igraph_feedback_arc_set( * \function igraph_feedback_vertex_set * \brief Feedback vertex set of a graph. * - * \experimental - * * A feedback vertex set is a set of vertices whose removal makes the graph * acyclic. Finding a \em minimum feedback vertex set is an NP-complete * problem, both on directed and undirected graphs. @@ -436,8 +432,8 @@ igraph_error_t igraph_feedback_vertex_set( igraph_error_t igraph_i_feedback_arc_set_undirected(const igraph_t *graph, igraph_vector_int_t *result, const igraph_vector_t *weights, igraph_vector_int_t *layering) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t edges; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_nodes > 0 ? no_of_nodes - 1 : 0); @@ -464,7 +460,7 @@ igraph_error_t igraph_i_feedback_arc_set_undirected(const igraph_t *graph, igrap if (result) { igraph_vector_int_clear(result); - for (igraph_integer_t i = 0, j = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0, j = 0; i < no_of_edges; i++) { if (i == VECTOR(edges)[j]) { j++; continue; @@ -515,16 +511,16 @@ igraph_error_t igraph_i_feedback_arc_set_undirected(const igraph_t *graph, igrap */ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vector_int_t *result, const igraph_vector_t *weights, igraph_vector_int_t *layers) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t nodes_left; - igraph_integer_t neis_size; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t nodes_left; + igraph_int_t neis_size; igraph_dqueue_int_t sources, sinks; igraph_vector_int_t neis; igraph_vector_int_t indegrees, outdegrees; igraph_vector_t instrengths, outstrengths; igraph_vector_int_t ordering; - igraph_integer_t order_next_pos = 0, order_next_neg = -1; + igraph_int_t order_next_pos = 0, order_next_neg = -1; IGRAPH_VECTOR_INT_INIT_FINALLY(&ordering, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); @@ -543,7 +539,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec IGRAPH_CHECK(igraph_strength(graph, &instrengths, igraph_vss_all(), IGRAPH_IN, IGRAPH_NO_LOOPS, weights)); IGRAPH_CHECK(igraph_strength(graph, &outstrengths, igraph_vss_all(), IGRAPH_OUT, IGRAPH_NO_LOOPS, weights)); } else { - for (igraph_integer_t u = 0; u < no_of_nodes; u++) { + for (igraph_int_t u = 0; u < no_of_nodes; u++) { VECTOR(instrengths)[u] = VECTOR(indegrees)[u]; VECTOR(outstrengths)[u] = VECTOR(outdegrees)[u]; } @@ -551,7 +547,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Find initial sources and sinks */ nodes_left = no_of_nodes; - for (igraph_integer_t u = 0; u < no_of_nodes; u++) { + for (igraph_int_t u = 0; u < no_of_nodes; u++) { if (VECTOR(indegrees)[u] == 0) { if (VECTOR(outdegrees)[u] == 0) { /* Isolated vertex, we simply ignore it */ @@ -573,7 +569,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* (1) Remove the sources one by one */ while (!igraph_dqueue_int_empty(&sources)) { - const igraph_integer_t u = igraph_dqueue_int_pop(&sources); + const igraph_int_t u = igraph_dqueue_int_pop(&sources); /* Add the node to the ordering */ VECTOR(ordering)[u] = order_next_pos++; /* Exclude the node from further searches */ @@ -581,9 +577,9 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Get the neighbors and decrease their degrees */ IGRAPH_CHECK(igraph_incident(graph, &neis, u, IGRAPH_OUT, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < neis_size; i++) { - const igraph_integer_t eid = VECTOR(neis)[i]; - const igraph_integer_t w = IGRAPH_TO(graph, eid); + for (igraph_int_t i = 0; i < neis_size; i++) { + const igraph_int_t eid = VECTOR(neis)[i]; + const igraph_int_t w = IGRAPH_TO(graph, eid); if (VECTOR(indegrees)[w] <= 0) { /* Already removed, continue */ continue; @@ -599,7 +595,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* (2) Remove the sinks one by one */ while (!igraph_dqueue_int_empty(&sinks)) { - const igraph_integer_t u = igraph_dqueue_int_pop(&sinks); + const igraph_int_t u = igraph_dqueue_int_pop(&sinks); /* Maybe the vertex became sink and source at the same time, hence it * was already removed in the previous iteration. Check it. */ if (VECTOR(indegrees)[u] < 0) { @@ -612,9 +608,9 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Get the neighbors and decrease their degrees */ IGRAPH_CHECK(igraph_incident(graph, &neis, u, IGRAPH_IN, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < neis_size; i++) { - const igraph_integer_t eid = VECTOR(neis)[i]; - const igraph_integer_t w = IGRAPH_FROM(graph, eid); + for (igraph_int_t i = 0; i < neis_size; i++) { + const igraph_int_t eid = VECTOR(neis)[i]; + const igraph_int_t w = IGRAPH_FROM(graph, eid); if (VECTOR(outdegrees)[w] <= 0) { /* Already removed, continue */ continue; @@ -630,9 +626,9 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* (3) No more sources or sinks. Find the node with the largest * difference between its out-strength and in-strength */ - igraph_integer_t v = -1; + igraph_int_t v = -1; igraph_real_t maxdiff = -IGRAPH_INFINITY; - for (igraph_integer_t u = 0; u < no_of_nodes; u++) { + for (igraph_int_t u = 0; u < no_of_nodes; u++) { if (VECTOR(outdegrees)[u] < 0) { continue; } @@ -648,9 +644,9 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Remove outgoing edges */ IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_OUT, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < neis_size; i++) { - const igraph_integer_t eid = VECTOR(neis)[i]; - const igraph_integer_t w = IGRAPH_TO(graph, eid); + for (igraph_int_t i = 0; i < neis_size; i++) { + const igraph_int_t eid = VECTOR(neis)[i]; + const igraph_int_t w = IGRAPH_TO(graph, eid); if (VECTOR(indegrees)[w] <= 0) { /* Already removed, continue */ continue; @@ -664,9 +660,9 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Remove incoming edges */ IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_IN, IGRAPH_LOOPS)); neis_size = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < neis_size; i++) { - const igraph_integer_t eid = VECTOR(neis)[i]; - const igraph_integer_t w = IGRAPH_FROM(graph, eid); + for (igraph_int_t i = 0; i < neis_size; i++) { + const igraph_int_t eid = VECTOR(neis)[i]; + const igraph_int_t w = IGRAPH_FROM(graph, eid); if (VECTOR(outdegrees)[w] <= 0) { /* Already removed, continue */ continue; @@ -693,7 +689,7 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec IGRAPH_FINALLY_CLEAN(6); /* Tidy up the ordering */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(ordering)[i] < 0) { VECTOR(ordering)[i] += no_of_nodes; } @@ -702,9 +698,9 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec /* Find the feedback edges based on the ordering */ if (result) { igraph_vector_int_clear(result); - for (igraph_integer_t eid = 0; eid < no_of_edges; eid++) { - igraph_integer_t from = IGRAPH_FROM(graph, eid); - igraph_integer_t to = IGRAPH_TO(graph, eid); + for (igraph_int_t eid = 0; eid < no_of_edges; eid++) { + igraph_int_t from = IGRAPH_FROM(graph, eid); + igraph_int_t to = IGRAPH_TO(graph, eid); if (from == to || VECTOR(ordering)[from] > VECTOR(ordering)[to]) { IGRAPH_CHECK(igraph_vector_int_push_back(result, eid)); } @@ -722,14 +718,14 @@ igraph_error_t igraph_i_feedback_arc_set_eades(const igraph_t *graph, igraph_vec IGRAPH_CHECK(igraph_vector_int_sort_ind(&ordering, &ranks, IGRAPH_ASCENDING)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t from = VECTOR(ranks)[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t from = VECTOR(ranks)[i]; IGRAPH_CHECK(igraph_neighbors( graph, &neis, from, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); neis_size = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < neis_size; j++) { - igraph_integer_t to = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < neis_size; j++) { + igraph_int_t to = VECTOR(neis)[j]; if (from == to) { continue; } @@ -766,13 +762,13 @@ igraph_error_t igraph_i_feedback_arc_set_ip_ti( IGRAPH_ERROR("GLPK is not available.", IGRAPH_UNIMPLEMENTED); #else - const igraph_integer_t no_of_vertices = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_components; + const igraph_int_t no_of_vertices = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_components; igraph_vector_int_t membership, *vec; igraph_vector_int_t ordering, vertex_remapping; igraph_vector_int_list_t vertices_by_components, edges_by_components; - igraph_integer_t i, j, k, l, m, n, from, to, no_of_rows, n_choose_2; + igraph_int_t i, j, k, l, m, n, from, to, no_of_rows, n_choose_2; igraph_real_t weight; glp_prob *ip; glp_iocp parm; @@ -893,8 +889,8 @@ igraph_error_t igraph_i_feedback_arc_set_ip_ti( */ /* res = n * (n - 1) * (n - 2) / 3 */ - igraph_integer_t mod = n % 3; - igraph_integer_t res = n / 3; /* same as (n - mod) / 3 */ + igraph_int_t mod = n % 3; + igraph_int_t res = n / 3; /* same as (n - mod) / 3 */ mod = (mod + 1) % 3; IGRAPH_SAFE_MULT(res, n - mod, &res); @@ -1088,7 +1084,7 @@ igraph_error_t igraph_i_feedback_arc_set_ip_cg( #ifndef HAVE_GLPK IGRAPH_ERROR("GLPK is not available.", IGRAPH_UNIMPLEMENTED); #else - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_bool_t is_dag; igraph_bitset_t removed; igraph_vector_int_t cycle; @@ -1179,7 +1175,7 @@ igraph_error_t igraph_i_feedback_arc_set_ip_cg( igraph_bitset_null(&removed); for (int j=1; j <= var_count; j++) { if (glp_mip_col_val(ip, j) > 0) { - igraph_integer_t i = VAR_TO_ID(j); + igraph_int_t i = VAR_TO_ID(j); IGRAPH_CHECK(igraph_vector_int_push_back(result, i)); IGRAPH_BIT_SET(removed, i); } @@ -1205,8 +1201,8 @@ igraph_error_t igraph_i_feedback_vertex_set_ip_cg( IGRAPH_ERROR("GLPK is not available.", IGRAPH_UNIMPLEMENTED); #else - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_bool_t is_acyclic; igraph_bitset_t removed; igraph_vector_int_t cycle; @@ -1275,9 +1271,9 @@ igraph_error_t igraph_i_feedback_vertex_set_ip_cg( while (true) { for (int i=0; i < cycle_size; i++) { IGRAPH_CHECK(igraph_incident(graph, &incident, VECTOR(cycle)[i], IGRAPH_ALL, IGRAPH_LOOPS)); - const igraph_integer_t incident_size = igraph_vector_int_size(&incident); - for (igraph_integer_t j = 0; j < incident_size; j++) { - igraph_integer_t eid = VECTOR(incident)[j]; + const igraph_int_t incident_size = igraph_vector_int_size(&incident); + for (igraph_int_t j = 0; j < incident_size; j++) { + igraph_int_t eid = VECTOR(incident)[j]; IGRAPH_BIT_SET(removed, eid); } } @@ -1301,14 +1297,14 @@ igraph_error_t igraph_i_feedback_vertex_set_ip_cg( for (int j=1; j <= var_count; j++) { if (glp_mip_col_val(ip, j) > 0) { - igraph_integer_t i = VAR_TO_ID(j); + igraph_int_t i = VAR_TO_ID(j); IGRAPH_CHECK(igraph_vector_int_push_back(result, i)); IGRAPH_CHECK(igraph_incident(graph, &incident, i, IGRAPH_ALL, IGRAPH_LOOPS)); - const igraph_integer_t incident_size = igraph_vector_int_size(&incident); - for (igraph_integer_t k = 0; k < incident_size; k++) { - igraph_integer_t eid = VECTOR(incident)[k]; + const igraph_int_t incident_size = igraph_vector_int_size(&incident); + for (igraph_int_t k = 0; k < incident_size; k++) { + igraph_int_t eid = VECTOR(incident)[k]; IGRAPH_BIT_SET(removed, eid); } } diff --git a/src/vendor/cigraph/src/misc/feedback_arc_set.h b/src/vendor/cigraph/src/cycles/feedback_sets.h similarity index 92% rename from src/vendor/cigraph/src/misc/feedback_arc_set.h rename to src/vendor/cigraph/src/cycles/feedback_sets.h index e47a03d8113..8218fe181f9 100644 --- a/src/vendor/cigraph/src/misc/feedback_arc_set.h +++ b/src/vendor/cigraph/src/cycles/feedback_sets.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -16,8 +16,8 @@ along with this program. If not, see . */ -#ifndef IGRAPH_FEEDBACK_ARC_SET_INTERNAL_H -#define IGRAPH_FEEDBACK_ARC_SET_INTERNAL_H +#ifndef IGRAPH_CYCLES_FEEDBACK_SETS_H +#define IGRAPH_CYCLES_FEEDBACK_SETS_H #include "igraph_decls.h" #include "igraph_datatype.h" @@ -49,4 +49,4 @@ igraph_error_t igraph_i_feedback_vertex_set_ip_cg( IGRAPH_END_C_DECLS -#endif +#endif /* IGRAPH_CYCLES_FEEDBACK_SETS_H */ diff --git a/src/vendor/cigraph/src/misc/order_cycle.cpp b/src/vendor/cigraph/src/cycles/order_cycle.cpp similarity index 72% rename from src/vendor/cigraph/src/misc/order_cycle.cpp rename to src/vendor/cigraph/src/cycles/order_cycle.cpp index e977db593e3..5c15e05c0e5 100644 --- a/src/vendor/cigraph/src/misc/order_cycle.cpp +++ b/src/vendor/cigraph/src/cycles/order_cycle.cpp @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2022 The igraph development team + igraph library. + Copyright (C) 2022-2025 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 @@ -16,7 +16,7 @@ along with this program. If not, see . */ -#include "misc/order_cycle.h" +#include "cycles/order_cycle.h" #include "igraph_interface.h" @@ -26,8 +26,8 @@ #include // Initialized to {-1, -1} -struct eid_pair_t : public std::pair { - eid_pair_t() : std::pair(-1, -1) { } +struct eid_pair_t : public std::pair { + eid_pair_t() : std::pair(-1, -1) { } }; /** @@ -45,15 +45,15 @@ igraph_error_t igraph_i_order_cycle( IGRAPH_HANDLE_EXCEPTIONS_BEGIN; - igraph_integer_t n = igraph_vector_int_size(cycle); + igraph_int_t n = igraph_vector_int_size(cycle); IGRAPH_ASSERT(n > 0); - std::map inclist; - for (igraph_integer_t i=0; i < n; ++i) { - igraph_integer_t eid = VECTOR(*cycle)[i]; + std::map inclist; + for (igraph_int_t i=0; i < n; ++i) { + igraph_int_t eid = VECTOR(*cycle)[i]; { - igraph_integer_t from = IGRAPH_FROM(graph, eid); + igraph_int_t from = IGRAPH_FROM(graph, eid); auto &p = inclist[from]; if (p.first < 0) { p.first = eid; @@ -64,7 +64,7 @@ igraph_error_t igraph_i_order_cycle( } { - igraph_integer_t to = IGRAPH_TO(graph, eid); + igraph_int_t to = IGRAPH_TO(graph, eid); auto &p = inclist[to]; if (p.first < 0) { p.first = eid; @@ -77,17 +77,17 @@ igraph_error_t igraph_i_order_cycle( igraph_vector_int_clear(res); IGRAPH_CHECK(igraph_vector_int_reserve(res, igraph_vector_int_size(cycle))); - igraph_integer_t current_e = VECTOR(*cycle)[0]; - igraph_integer_t current_v = IGRAPH_FROM(graph, current_e); - for (igraph_integer_t i=0; i < n; ++i) { + igraph_int_t current_e = VECTOR(*cycle)[0]; + igraph_int_t current_v = IGRAPH_FROM(graph, current_e); + for (igraph_int_t i=0; i < n; ++i) { const auto &p = inclist.at(current_v); igraph_vector_int_push_back(res, current_e); /* reserved */ - igraph_integer_t next_e = p.first; + igraph_int_t next_e = p.first; if (next_e == current_e) { next_e = p.second; } current_e = next_e; - igraph_integer_t next_v = IGRAPH_FROM(graph, current_e); + igraph_int_t next_v = IGRAPH_FROM(graph, current_e); if (next_v == current_v) { next_v = IGRAPH_TO(graph, current_e); } diff --git a/src/vendor/cigraph/src/misc/order_cycle.h b/src/vendor/cigraph/src/cycles/order_cycle.h similarity index 98% rename from src/vendor/cigraph/src/misc/order_cycle.h rename to src/vendor/cigraph/src/cycles/order_cycle.h index 32dd34f67f1..291577b9d5f 100644 --- a/src/vendor/cigraph/src/misc/order_cycle.h +++ b/src/vendor/cigraph/src/cycles/order_cycle.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/cycles/simple_cycles.c b/src/vendor/cigraph/src/cycles/simple_cycles.c index 2e303974667..1eb0c8502d4 100644 --- a/src/vendor/cigraph/src/cycles/simple_cycles.c +++ b/src/vendor/cigraph/src/cycles/simple_cycles.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -41,7 +41,7 @@ */ typedef struct { /* Number of vertices in the graph */ - igraph_integer_t N; + igraph_int_t N; /* The incidence list of the graph */ igraph_inclist_t IK; @@ -80,6 +80,10 @@ typedef struct { igraph_vector_int_list_t *vertices; /* the edges in the cycle */ igraph_vector_int_list_t *edges; + /* number of cycles found so far */ + igraph_int_t cycle_count; + /* how many cycles to record at most? */ + igraph_int_t max_results; } simple_cycle_results_t; /** @@ -87,7 +91,7 @@ typedef struct { */ static igraph_error_t simple_cycles_unblock( simple_cycle_search_state_t *state, - igraph_integer_t u) { + igraph_int_t u) { // TODO: introduce stack for w & neis in order to reduce the number of // iterations. @@ -99,13 +103,13 @@ static igraph_error_t simple_cycles_unblock( while (igraph_stack_int_size(&u_stack) > 0) { igraph_bool_t recurse_deeper = false; - const igraph_integer_t current_u = igraph_stack_int_top(&u_stack); + const igraph_int_t current_u = igraph_stack_int_top(&u_stack); IGRAPH_BIT_CLEAR(state->v_blocked, current_u); neis = igraph_adjlist_get(&state->B, current_u); while (!igraph_vector_int_empty(neis) && !recurse_deeper) { - const igraph_integer_t w = igraph_vector_int_pop_back(neis); + const igraph_int_t w = igraph_vector_int_pop_back(neis); if (IGRAPH_BIT_TEST(state->v_blocked, w)) { IGRAPH_CHECK(igraph_stack_int_push(&u_stack, w)); recurse_deeper = true; @@ -135,17 +139,17 @@ static igraph_error_t simple_cycles_unblock( */ static igraph_error_t simple_cycles_circuit( simple_cycle_search_state_t *state, - igraph_integer_t V, - igraph_integer_t max_cycle_length, - igraph_integer_t min_cycle_length, + igraph_int_t V, + igraph_int_t max_cycle_length, + igraph_int_t min_cycle_length, igraph_cycle_handler_t *callback, void *arg) { const igraph_vector_int_t *neighbors; const igraph_vector_int_t *incident_edges; - igraph_integer_t num_neighbors; - igraph_integer_t S = V; // start - igraph_integer_t E = -1; // edge start + igraph_int_t num_neighbors; + igraph_int_t S = V; // start + igraph_int_t E = -1; // edge start igraph_bool_t local_found = false; igraph_bool_t loop_length_stop = false; @@ -171,7 +175,7 @@ static igraph_error_t simple_cycles_circuit( IGRAPH_ASSERT(igraph_stack_int_size(&v_stack) == igraph_stack_int_size(&e_stack)); - igraph_integer_t i0 = 0; + igraph_int_t i0 = 0; if (recurse_deeper) { // stack v & e IGRAPH_CHECK(igraph_vector_int_push_back(&state->vertex_stack, V)); @@ -196,9 +200,9 @@ static igraph_error_t simple_cycles_circuit( incident_edges = igraph_inclist_get(&state->IK, V); num_neighbors = igraph_vector_int_size(neighbors); IGRAPH_ASSERT(igraph_vector_int_size(incident_edges) == num_neighbors); - for (igraph_integer_t i = i0; i < num_neighbors; ++i) { - igraph_integer_t W = VECTOR(*neighbors)[i]; - igraph_integer_t WE = VECTOR(*incident_edges)[i]; + for (igraph_int_t i = i0; i < num_neighbors; ++i) { + igraph_int_t W = VECTOR(*neighbors)[i]; + igraph_int_t WE = VECTOR(*incident_edges)[i]; if (W == S) { igraph_error_t ret; @@ -267,8 +271,8 @@ static igraph_error_t simple_cycles_circuit( if (local_found || loop_length_stop) { IGRAPH_CHECK(simple_cycles_unblock(state, V)); } else { - for (igraph_integer_t i = 0; i < num_neighbors; ++i) { - const igraph_integer_t W = VECTOR(*neighbors)[i]; + for (igraph_int_t i = 0; i < num_neighbors; ++i) { + const igraph_int_t W = VECTOR(*neighbors)[i]; if (!igraph_vector_int_contains(igraph_adjlist_get(&state->B, W), V)) { IGRAPH_CHECK( igraph_vector_int_push_back(igraph_adjlist_get(&state->B, W), V)); @@ -291,9 +295,11 @@ static igraph_error_t simple_cycles_circuit( IGRAPH_ALLOW_INTERRUPTION(); } - IGRAPH_ASSERT(igraph_stack_int_size(&v_stack) == 0); - IGRAPH_ASSERT(igraph_stack_int_size(&e_stack) == 0); - IGRAPH_ASSERT(igraph_stack_int_size(&neigh_iteration_progress) == 0); + if (! state->stop_search) { + IGRAPH_ASSERT(igraph_stack_int_size(&v_stack) == 0); + IGRAPH_ASSERT(igraph_stack_int_size(&e_stack) == 0); + IGRAPH_ASSERT(igraph_stack_int_size(&neigh_iteration_progress) == 0); + } igraph_stack_int_destroy(&neigh_iteration_progress); igraph_stack_int_destroy(&v_stack); @@ -393,8 +399,8 @@ static igraph_error_t append_simple_cycle_result( const igraph_vector_int_t *edges, void *arg) { - simple_cycle_results_t *res_list = - (simple_cycle_results_t *)arg; + simple_cycle_results_t *res_list = (simple_cycle_results_t *) arg; + if (res_list->vertices != NULL) { // copy output: from stack to vector. No need to reverse because // we were putting vertices in the stack in reverse order anyway. @@ -415,7 +421,13 @@ static igraph_error_t append_simple_cycle_result( IGRAPH_FINALLY_CLEAN(1); } - return IGRAPH_SUCCESS; + res_list->cycle_count++; + + if (res_list->max_results >= 0 && res_list->cycle_count == res_list->max_results) { + return IGRAPH_STOP; + } else { + return IGRAPH_SUCCESS; + } } /** @@ -438,14 +450,14 @@ static igraph_error_t append_simple_cycle_result( */ static igraph_error_t simple_cycles_search_callback_from_one_vertex( simple_cycle_search_state_t *state, - igraph_integer_t s, - igraph_integer_t min_cycle_length, - igraph_integer_t max_cycle_length, + igraph_int_t s, + igraph_int_t min_cycle_length, + igraph_int_t max_cycle_length, igraph_cycle_handler_t *callback, void *arg) { // L3: - for (igraph_integer_t i = s; i < state->N; ++i) { + for (igraph_int_t i = s; i < state->N; ++i) { IGRAPH_BIT_CLEAR(state->v_blocked, i); igraph_vector_int_clear(igraph_adjlist_get(&state->B, i)); } @@ -453,11 +465,11 @@ static igraph_error_t simple_cycles_search_callback_from_one_vertex( IGRAPH_CHECK(simple_cycles_circuit(state, s, max_cycle_length, min_cycle_length, callback, arg)); - for (igraph_integer_t i = 0; i < state->N; ++i) { + for (igraph_int_t i = 0; i < state->N; ++i) { // We want to remove the vertex with value s, not at position s. // It's fine to use binary search since we never add to, only remove from // an already sorted adjacency list. - igraph_integer_t pos; + igraph_int_t pos; if (igraph_vector_int_binsearch(igraph_adjlist_get(&state->AK, i), s, &pos)) { igraph_vector_int_remove(igraph_adjlist_get(&state->AK, i), pos); @@ -513,8 +525,8 @@ static igraph_error_t simple_cycles_search_callback_from_one_vertex( igraph_error_t igraph_simple_cycles_callback( const igraph_t *graph, igraph_neimode_t mode, - igraph_integer_t min_cycle_length, - igraph_integer_t max_cycle_length, + igraph_int_t min_cycle_length, + igraph_int_t max_cycle_length, igraph_cycle_handler_t *callback, void *arg) { @@ -536,13 +548,13 @@ igraph_error_t igraph_simple_cycles_callback( // // Thus, we iterate over the vertices, and check if they can be skipped as // a starting point according to the rules laid out above. - for (igraph_integer_t i = 0; i < state.N; i++) { + for (igraph_int_t i = 0; i < state.N; i++) { // Check if the vertex is a candidate for a cycle. // Note that we call igraph_degree_1() here instead of retrieving the // neighbor count from igraph_adjlist_get(&state.AK, i) because: // - we need to the undirected degree in all cases, and // - our algorithm modifies the adjlist state.AK - igraph_integer_t degree; + igraph_int_t degree; IGRAPH_CHECK(igraph_degree_1(graph, °ree, i, IGRAPH_ALL, true)); if (degree < 3 && IGRAPH_BIT_TEST(state.v_visited, i)) { continue; @@ -596,6 +608,8 @@ igraph_error_t igraph_simple_cycles_callback( * Pass a negative value to search for all cycles. * \param max_cycle_length Limit the maximum length of cycles to search for. * Pass a negative value to search for all cycles. + * \param max_results At most this many cycles will be recorded. If + * negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_simple_cycles_callback() to call a function for each found @@ -607,15 +621,16 @@ igraph_error_t igraph_simple_cycles_callback( */ igraph_error_t igraph_simple_cycles( const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, + igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, igraph_neimode_t mode, - igraph_integer_t min_cycle_length, - igraph_integer_t max_cycle_length) { + igraph_int_t min_cycle_length, igraph_int_t max_cycle_length, + igraph_int_t max_results) { simple_cycle_results_t result_list; result_list.vertices = vertices; result_list.edges = edges; + result_list.cycle_count = 0; + result_list.max_results = max_results; if (vertices) { igraph_vector_int_list_clear(vertices); @@ -624,6 +639,10 @@ igraph_error_t igraph_simple_cycles( igraph_vector_int_list_clear(edges); } + if (max_results == 0) { + return IGRAPH_SUCCESS; + } + IGRAPH_CHECK(igraph_simple_cycles_callback(graph, mode, min_cycle_length, max_cycle_length, &append_simple_cycle_result, &result_list)); diff --git a/src/vendor/cigraph/src/f2c.h b/src/vendor/cigraph/src/f2c.h index ddb322575c4..120a29fa0f6 100644 --- a/src/vendor/cigraph/src/f2c.h +++ b/src/vendor/cigraph/src/f2c.h @@ -144,7 +144,7 @@ union Multitype { /* for multiple entry points */ typedef union Multitype Multitype; -/*typedef igraph_integer_t Long;*/ /* No longer used; formerly in Namelist */ +/*typedef igraph_int_t Long;*/ /* No longer used; formerly in Namelist */ struct Vardesc { /* for Namelist */ char *name; diff --git a/src/vendor/cigraph/src/flow/flow.c b/src/vendor/cigraph/src/flow/flow.c index d638a044724..fb6a376cd9c 100644 --- a/src/vendor/cigraph/src/flow/flow.c +++ b/src/vendor/cigraph/src/flow/flow.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -161,17 +161,17 @@ static igraph_error_t igraph_i_maxflow_undirected( igraph_vector_int_t *cut, igraph_vector_int_t *partition, igraph_vector_int_t *partition2, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t source, + igraph_int_t target, const igraph_vector_t *capacity, igraph_maxflow_stats_t *stats) { - const igraph_integer_t no_of_edges = igraph_ecount(graph); - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t edges; igraph_vector_t newcapacity; igraph_t newgraph; - igraph_integer_t size; + igraph_int_t size; /* We need to convert this to directed by hand, since we need to be sure that the edge IDs will be handled properly to build the new @@ -183,7 +183,7 @@ static igraph_error_t igraph_i_maxflow_undirected( IGRAPH_CHECK(igraph_vector_int_reserve(&edges, size)); IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0)); IGRAPH_CHECK(igraph_vector_int_resize(&edges, size)); - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { VECTOR(edges)[no_of_edges * 2 + i * 2] = VECTOR(edges)[i * 2 + 1]; VECTOR(edges)[no_of_edges * 2 + i * 2 + 1] = VECTOR(edges)[i * 2]; VECTOR(newcapacity)[i] = VECTOR(newcapacity)[no_of_edges + i] = @@ -197,8 +197,8 @@ static igraph_error_t igraph_i_maxflow_undirected( partition2, source, target, &newcapacity, stats)); if (cut) { - igraph_integer_t cs = igraph_vector_int_size(cut); - for (igraph_integer_t i = 0; i < cs; i++) { + igraph_int_t cs = igraph_vector_int_size(cut); + for (igraph_int_t i = 0; i < cs; i++) { if (VECTOR(*cut)[i] >= no_of_edges) { VECTOR(*cut)[i] -= no_of_edges; } @@ -211,7 +211,7 @@ static igraph_error_t igraph_i_maxflow_undirected( from the bigger vertex ID to the smaller one. For positive values the direction is the opposite. */ if (flow) { - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { VECTOR(*flow)[i] -= VECTOR(*flow)[i + no_of_edges]; } IGRAPH_CHECK(igraph_vector_resize(flow, no_of_edges)); @@ -253,33 +253,33 @@ static igraph_error_t igraph_i_maxflow_undirected( &first, ¤t, &to, &excess, \ &rescap, &rev)) -static void igraph_i_mf_gap(igraph_integer_t b, igraph_maxflow_stats_t *stats, +static void igraph_i_mf_gap(igraph_int_t b, igraph_maxflow_stats_t *stats, igraph_buckets_t *buckets, igraph_dbuckets_t *ibuckets, - igraph_integer_t no_of_nodes, + igraph_int_t no_of_nodes, igraph_vector_int_t *distance) { IGRAPH_UNUSED(buckets); - igraph_integer_t bo; + igraph_int_t bo; (stats->nogap)++; for (bo = b + 1; bo <= no_of_nodes; bo++) { while (!igraph_dbuckets_empty_bucket(ibuckets, bo)) { - igraph_integer_t n = igraph_dbuckets_pop(ibuckets, bo); + igraph_int_t n = igraph_dbuckets_pop(ibuckets, bo); (stats->nogapnodes)++; DIST(n) = no_of_nodes; } } } -static void igraph_i_mf_relabel(igraph_integer_t v, igraph_integer_t no_of_nodes, +static void igraph_i_mf_relabel(igraph_int_t v, igraph_int_t no_of_nodes, igraph_vector_int_t *distance, igraph_vector_int_t *first, igraph_vector_t *rescap, igraph_vector_int_t *to, igraph_vector_int_t *current, - igraph_maxflow_stats_t *stats, igraph_integer_t *nrelabelsince) { + igraph_maxflow_stats_t *stats, igraph_int_t *nrelabelsince) { - igraph_integer_t min = no_of_nodes; - igraph_integer_t k, l, min_edge = 0; + igraph_int_t min = no_of_nodes; + igraph_int_t k, l, min_edge = 0; (stats->norelabel)++; (*nrelabelsince)++; DIST(v) = no_of_nodes; for (k = FIRST(v), l = LAST(v); k < l; k++) { @@ -295,14 +295,14 @@ static void igraph_i_mf_relabel(igraph_integer_t v, igraph_integer_t no_of_nodes } } -static void igraph_i_mf_push(igraph_integer_t v, igraph_integer_t e, igraph_integer_t n, +static void igraph_i_mf_push(igraph_int_t v, igraph_int_t e, igraph_int_t n, igraph_vector_int_t *current, igraph_vector_t *rescap, igraph_vector_t *excess, - igraph_integer_t target, igraph_integer_t source, + igraph_int_t target, igraph_int_t source, igraph_buckets_t *buckets, igraph_dbuckets_t *ibuckets, igraph_vector_int_t *distance, igraph_vector_int_t *rev, igraph_maxflow_stats_t *stats, - igraph_integer_t *npushsince) { + igraph_int_t *npushsince) { IGRAPH_UNUSED(current); IGRAPH_UNUSED(source); @@ -320,27 +320,27 @@ static void igraph_i_mf_push(igraph_integer_t v, igraph_integer_t e, igraph_inte EXCESS(v) -= delta; } -static void igraph_i_mf_discharge(igraph_integer_t v, +static void igraph_i_mf_discharge(igraph_int_t v, igraph_vector_int_t *current, igraph_vector_int_t *first, igraph_vector_t *rescap, igraph_vector_int_t *to, igraph_vector_int_t *distance, igraph_vector_t *excess, - igraph_integer_t no_of_nodes, igraph_integer_t source, - igraph_integer_t target, igraph_buckets_t *buckets, + igraph_int_t no_of_nodes, igraph_int_t source, + igraph_int_t target, igraph_buckets_t *buckets, igraph_dbuckets_t *ibuckets, igraph_vector_int_t *rev, igraph_maxflow_stats_t *stats, - igraph_integer_t *npushsince, igraph_integer_t *nrelabelsince) { + igraph_int_t *npushsince, igraph_int_t *nrelabelsince) { do { - igraph_integer_t i; - igraph_integer_t start = CURRENT(v); - igraph_integer_t stop = LAST(v); + igraph_int_t i; + igraph_int_t start = CURRENT(v); + igraph_int_t stop = LAST(v); for (i = start; i < stop; i++) { if (RESCAP(i) > 0) { - igraph_integer_t nei = HEAD(i); + igraph_int_t nei = HEAD(i); if (DIST(v) == DIST(nei) + 1) { PUSH((v), i, nei); if (EXCESS(v) == 0) { @@ -350,7 +350,7 @@ static void igraph_i_mf_discharge(igraph_integer_t v, } } if (i == stop) { - igraph_integer_t origdist = DIST(v); + igraph_int_t origdist = DIST(v); RELABEL(v); if (igraph_buckets_empty_bucket(buckets, origdist) && igraph_dbuckets_empty_bucket(ibuckets, origdist)) { @@ -368,15 +368,15 @@ static void igraph_i_mf_discharge(igraph_integer_t v, } static igraph_error_t igraph_i_mf_bfs(igraph_dqueue_int_t *bfsq, - igraph_integer_t source, igraph_integer_t target, - igraph_integer_t no_of_nodes, igraph_buckets_t *buckets, + igraph_int_t source, igraph_int_t target, + igraph_int_t no_of_nodes, igraph_buckets_t *buckets, igraph_dbuckets_t *ibuckets, igraph_vector_int_t *distance, igraph_vector_int_t *first, igraph_vector_int_t *current, igraph_vector_int_t *to, igraph_vector_t *excess, igraph_vector_t *rescap, igraph_vector_int_t *rev) { - igraph_integer_t k, l; + igraph_int_t k, l; IGRAPH_UNUSED(source); @@ -387,11 +387,11 @@ static igraph_error_t igraph_i_mf_bfs(igraph_dqueue_int_t *bfsq, IGRAPH_CHECK(igraph_dqueue_int_push(bfsq, target)); while (!igraph_dqueue_int_empty(bfsq)) { - igraph_integer_t node = igraph_dqueue_int_pop(bfsq); - igraph_integer_t ndist = DIST(node) + 1; + igraph_int_t node = igraph_dqueue_int_pop(bfsq); + igraph_int_t ndist = DIST(node) + 1; for (k = FIRST(node), l = LAST(node); k < l; k++) { if (RESCAP(REV(k)) > 0) { - igraph_integer_t nei = HEAD(k); + igraph_int_t nei = HEAD(k); if (DIST(nei) == no_of_nodes) { DIST(nei) = ndist; CURRENT(nei) = FIRST(nei); @@ -487,13 +487,13 @@ static igraph_error_t igraph_i_mf_bfs(igraph_dqueue_int_t *bfsq, igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, igraph_vector_t *flow, igraph_vector_int_t *cut, igraph_vector_int_t *partition, igraph_vector_int_t *partition2, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity, igraph_maxflow_stats_t *stats) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_orig_edges = igraph_ecount(graph); - const igraph_integer_t no_of_edges = 2 * no_of_orig_edges; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_orig_edges = igraph_ecount(graph); + const igraph_int_t no_of_edges = 2 * no_of_orig_edges; igraph_vector_t rescap, excess; igraph_vector_int_t from, to, rev, distance; @@ -504,8 +504,8 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, igraph_dqueue_int_t bfsq; - igraph_integer_t idx; - igraph_integer_t npushsince = 0, nrelabelsince = 0; + igraph_int_t idx; + igraph_int_t npushsince = 0, nrelabelsince = 0; igraph_maxflow_stats_t local_stats; /* used if the user passed a null pointer for stats */ @@ -595,9 +595,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0)); IGRAPH_CHECK(igraph_i_vector_int_rank(&edges, &rank, no_of_nodes)); - for (igraph_integer_t i = 0; i < no_of_edges; i += 2) { - const igraph_integer_t pos = VECTOR(rank)[i]; - const igraph_integer_t pos2 = VECTOR(rank)[i + 1]; + for (igraph_int_t i = 0; i < no_of_edges; i += 2) { + const igraph_int_t pos = VECTOR(rank)[i]; + const igraph_int_t pos2 = VECTOR(rank)[i + 1]; VECTOR(from)[pos] = VECTOR(edges)[i]; VECTOR(to)[pos] = VECTOR(edges)[i + 1]; VECTOR(from)[pos2] = VECTOR(edges)[i + 1]; @@ -612,13 +612,13 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, think, because of the possible isolate vertices. */ idx = -1; - for (igraph_integer_t i = 0; i <= VECTOR(from)[0]; i++) { + for (igraph_int_t i = 0; i <= VECTOR(from)[0]; i++) { idx++; VECTOR(first)[idx] = 0; } - for (igraph_integer_t i = 1; i < no_of_edges; i++) { - const igraph_integer_t n = (VECTOR(from)[i] - + for (igraph_int_t i = 1; i < no_of_edges; i++) { + const igraph_int_t n = (VECTOR(from)[i] - VECTOR(from)[ VECTOR(first)[idx] ]); - for (igraph_integer_t j = 0; j < n; j++) { + for (igraph_int_t j = 0; j < n; j++) { idx++; VECTOR(first)[idx] = i; } } @@ -638,7 +638,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* And the current pointers, initially the same as the first */ IGRAPH_VECTOR_INT_INIT_FINALLY(¤t, no_of_nodes); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(current)[i] = VECTOR(first)[i]; } @@ -650,7 +650,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, IGRAPH_FINALLY(igraph_dbuckets_destroy, &ibuckets); /* Send as much flow as possible from the source to its neighbors */ - for (igraph_integer_t i = FIRST(source), j = LAST(source); i < j; i++) { + for (igraph_int_t i = FIRST(source), j = LAST(source); i < j; i++) { if (HEAD(i) != source) { const igraph_real_t delta = RESCAP(i); RESCAP(i) = 0; @@ -663,7 +663,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, (stats->nobfs)++; while (!igraph_buckets_empty(&buckets)) { - const igraph_integer_t vertex = igraph_buckets_popmax(&buckets); + const igraph_int_t vertex = igraph_buckets_popmax(&buckets); DISCHARGE(vertex); if (npushsince > no_of_nodes / 2 && nrelabelsince > no_of_nodes) { (stats->nobfs)++; @@ -684,7 +684,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, backwards. */ igraph_dqueue_int_t Q; igraph_vector_bool_t added; - igraph_integer_t marked = 0; + igraph_int_t marked = 0; IGRAPH_CHECK(igraph_vector_bool_init(&added, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &added); @@ -696,9 +696,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, VECTOR(added)[target] = true; marked++; while (!igraph_dqueue_int_empty(&Q)) { - const igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); - for (igraph_integer_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) { - igraph_integer_t nei = HEAD(i); + const igraph_int_t actnode = igraph_dqueue_int_pop(&Q); + for (igraph_int_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) { + igraph_int_t nei = HEAD(i); if (!VECTOR(added)[nei] && RESCAP(REV(i)) > 0.0) { VECTOR(added)[nei] = true; marked++; @@ -714,9 +714,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, if (cut) { igraph_vector_int_clear(cut); - for (igraph_integer_t i = 0; i < no_of_orig_edges; i++) { - igraph_integer_t f = IGRAPH_FROM(graph, i); - igraph_integer_t t = IGRAPH_TO(graph, i); + for (igraph_int_t i = 0; i < no_of_orig_edges; i++) { + igraph_int_t f = IGRAPH_FROM(graph, i); + igraph_int_t t = IGRAPH_TO(graph, i); if (!VECTOR(added)[f] && VECTOR(added)[t]) { IGRAPH_CHECK(igraph_vector_int_push_back(cut, i)); } @@ -724,9 +724,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, } if (partition2) { - igraph_integer_t x = 0; + igraph_int_t x = 0; IGRAPH_CHECK(igraph_vector_int_resize(partition2, marked)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(added)[i]) { VECTOR(*partition2)[x++] = i; } @@ -734,10 +734,10 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, } if (partition) { - igraph_integer_t x = 0; + igraph_int_t x = 0; IGRAPH_CHECK(igraph_vector_int_resize(partition, no_of_nodes - marked)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (!VECTOR(added)[i]) { VECTOR(*partition)[x++] = i; } @@ -766,12 +766,12 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, IGRAPH_CHECK(igraph_dqueue_int_push(&Q, 0)); VECTOR(added)[source] = 1; while (!igraph_dqueue_int_empty(&Q)) { - const igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); - const igraph_integer_t actdist = igraph_dqueue_int_pop(&Q); + const igraph_int_t actnode = igraph_dqueue_int_pop(&Q); + const igraph_int_t actdist = igraph_dqueue_int_pop(&Q); DIST(actnode) = actdist; - for (igraph_integer_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) { - const igraph_integer_t nei = HEAD(i); + for (igraph_int_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) { + const igraph_int_t nei = HEAD(i); if (!VECTOR(added)[nei] && RESCAP(REV(i)) > 0.0) { VECTOR(added)[nei] = 1; IGRAPH_CHECK(igraph_dqueue_int_push(&Q, nei)); @@ -786,7 +786,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* Reinitialize the buckets */ igraph_buckets_clear(&buckets); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (EXCESS(i) > 0.0 && i != source && i != target) { igraph_buckets_add(&buckets, DIST(i), i); } @@ -794,14 +794,14 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* Now we return the flow to the source */ while (!igraph_buckets_empty(&buckets)) { - const igraph_integer_t vertex = igraph_buckets_popmax(&buckets); + const igraph_int_t vertex = igraph_buckets_popmax(&buckets); /* DISCHARGE(vertex) comes here */ do { - igraph_integer_t i, j; + igraph_int_t i, j; for (i = CURRENT(vertex), j = LAST(vertex); i < j; i++) { if (RESCAP(i) > 0) { - igraph_integer_t nei = HEAD(i); + igraph_int_t nei = HEAD(i); if (DIST(vertex) == DIST(nei) + 1) { igraph_real_t delta = @@ -828,10 +828,10 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, if (i == j) { /* RELABEL(vertex) comes here */ - igraph_integer_t min; - igraph_integer_t min_edge = 0; + igraph_int_t min; + igraph_int_t min_edge = 0; DIST(vertex) = min = no_of_nodes; - for (igraph_integer_t k = FIRST(vertex), l = LAST(vertex); k < l; k++) { + for (igraph_int_t k = FIRST(vertex), l = LAST(vertex); k < l; k++) { if (RESCAP(k) > 0) { if (DIST(HEAD(k)) < min) { min = DIST(HEAD(k)); @@ -879,8 +879,8 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, 'stack', but it was visited before. */ IGRAPH_VECTOR_INT_INIT_FINALLY(&flow_edges, 0); - for (igraph_integer_t i = 0, j = 0; i < no_of_edges; i += 2, j++) { - const igraph_integer_t pos = VECTOR(rank)[i]; + for (igraph_int_t i = 0, j = 0; i < no_of_edges; i += 2, j++) { + const igraph_int_t pos = VECTOR(rank)[i]; if ((capacity ? VECTOR(*capacity)[j] : 1.0) > RESCAP(pos)) { IGRAPH_CHECK(igraph_vector_int_push_back(&flow_edges, IGRAPH_FROM(graph, j))); @@ -909,9 +909,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, #define MYCAP(i) (VECTOR(mycap)[(i)]) - for (igraph_integer_t i = 0; i < no_of_edges; i += 2) { - const igraph_integer_t pos = VECTOR(rank)[i]; - const igraph_integer_t pos2 = VECTOR(rank)[i + 1]; + for (igraph_int_t i = 0; i < no_of_edges; i += 2) { + const igraph_int_t pos = VECTOR(rank)[i]; + const igraph_int_t pos2 = VECTOR(rank)[i + 1]; MYCAP(pos) = (capacity ? VECTOR(*capacity)[i / 2] : 1.0) - RESCAP(pos); MYCAP(pos2) = 0.0; } @@ -926,9 +926,9 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, VECTOR(added)[source] = 1; while (!igraph_vector_int_empty(&stack) && igraph_vector_int_tail(&stack) != target) { - const igraph_integer_t actnode = igraph_vector_int_tail(&stack); - igraph_integer_t edge = FIRST(actnode) + CURRENT(actnode); - igraph_integer_t nei; + const igraph_int_t actnode = igraph_vector_int_tail(&stack); + igraph_int_t edge = FIRST(actnode) + CURRENT(actnode); + igraph_int_t nei; while (edge < LAST(actnode) && MYCAP(edge) == 0.0) { edge++; } @@ -946,18 +946,18 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, until we find 'nei' again, determine the flow along the cycle. */ igraph_real_t thisflow = MYCAP(edge); - for (igraph_integer_t idx = igraph_vector_int_size(&stack) - 2; + for (igraph_int_t idx = igraph_vector_int_size(&stack) - 2; idx >= 0 && VECTOR(stack)[idx + 1] != nei; idx -= 2) { - const igraph_integer_t e = VECTOR(stack)[idx]; + const igraph_int_t e = VECTOR(stack)[idx]; const igraph_real_t rcap = e >= 0 ? MYCAP(e) : MYCAP(edge); if (rcap < thisflow) { thisflow = rcap; } } MYCAP(edge) -= thisflow; RESCAP(edge) += thisflow; - for (igraph_integer_t idx = igraph_vector_int_size(&stack) - 2; + for (igraph_int_t idx = igraph_vector_int_size(&stack) - 2; idx >= 0 && VECTOR(stack)[idx + 1] != nei; idx -= 2) { - const igraph_integer_t e = VECTOR(stack)[idx]; + const igraph_int_t e = VECTOR(stack)[idx]; if (e >= 0) { MYCAP(e) -= thisflow; RESCAP(e) += thisflow; @@ -979,17 +979,17 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* If non-empty, then it contains a path from source to target in the residual graph. We factor out this path from the flow. */ if (!igraph_vector_int_empty(&stack)) { - const igraph_integer_t pl = igraph_vector_int_size(&stack); + const igraph_int_t pl = igraph_vector_int_size(&stack); igraph_real_t thisflow = EXCESS(target); - for (igraph_integer_t i = 2; i < pl; i += 2) { - const igraph_integer_t edge = VECTOR(stack)[i]; + for (igraph_int_t i = 2; i < pl; i += 2) { + const igraph_int_t edge = VECTOR(stack)[i]; const igraph_real_t rcap = MYCAP(edge); if (rcap < thisflow) { thisflow = rcap; } } - for (igraph_integer_t i = 2; i < pl; i += 2) { - const igraph_integer_t edge = VECTOR(stack)[i]; + for (igraph_int_t i = 2; i < pl; i += 2) { + const igraph_int_t edge = VECTOR(stack)[i]; MYCAP(edge) -= thisflow; } } @@ -1005,8 +1005,8 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, /* ----------------------------------------------------------- */ IGRAPH_CHECK(igraph_vector_resize(flow, no_of_orig_edges)); - for (igraph_integer_t i = 0, j = 0; i < no_of_edges; i += 2, j++) { - const igraph_integer_t pos = VECTOR(rank)[i]; + for (igraph_int_t i = 0, j = 0; i < no_of_edges; i += 2, j++) { + const igraph_int_t pos = VECTOR(rank)[i]; VECTOR(*flow)[j] = (capacity ? VECTOR(*capacity)[j] : 1.0) - RESCAP(pos); } @@ -1086,7 +1086,7 @@ igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value, */ igraph_error_t igraph_maxflow_value(const igraph_t *graph, igraph_real_t *value, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity, igraph_maxflow_stats_t *stats) { @@ -1125,7 +1125,7 @@ igraph_error_t igraph_maxflow_value(const igraph_t *graph, igraph_real_t *value, */ igraph_error_t igraph_st_mincut_value(const igraph_t *graph, igraph_real_t *value, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity) { if (source == target) { @@ -1176,7 +1176,7 @@ igraph_error_t igraph_st_mincut_value(const igraph_t *graph, igraph_real_t *valu igraph_error_t igraph_st_mincut(const igraph_t *graph, igraph_real_t *value, igraph_vector_int_t *cut, igraph_vector_int_t *partition, igraph_vector_int_t *partition2, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity) { return igraph_maxflow(graph, value, /*flow=*/ NULL, @@ -1199,19 +1199,19 @@ static igraph_error_t igraph_i_mincut_undirected( igraph_vector_int_t *cut, const igraph_vector_t *capacity) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_i_cutheap_t heap; igraph_real_t mincut = IGRAPH_INFINITY; /* infinity */ - igraph_integer_t i; + igraph_int_t i; igraph_adjlist_t adjlist; igraph_inclist_t inclist; igraph_vector_int_t mergehist; igraph_bool_t calc_cut = partition || partition2 || cut; - igraph_integer_t act_step = 0, mincut_step = 0; + igraph_int_t act_step = 0, mincut_step = 0; if (capacity && igraph_vector_size(capacity) != no_of_edges) { IGRAPH_ERROR("Invalid capacity vector size", IGRAPH_EINVAL); @@ -1221,7 +1221,7 @@ static igraph_error_t igraph_i_mincut_undirected( { igraph_vector_int_t memb; igraph_vector_int_t csize; - igraph_integer_t no; + igraph_int_t no; IGRAPH_VECTOR_INT_INIT_FINALLY(&memb, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&csize, 0); IGRAPH_CHECK(igraph_connected_components(graph, &memb, &csize, &no, IGRAPH_WEAK)); @@ -1233,7 +1233,7 @@ static igraph_error_t igraph_i_mincut_undirected( igraph_vector_int_clear(cut); } if (partition) { - igraph_integer_t j = 0; + igraph_int_t j = 0; IGRAPH_CHECK(igraph_vector_int_resize(partition, VECTOR(csize)[0])); for (i = 0; i < no_of_nodes; i++) { @@ -1243,7 +1243,7 @@ static igraph_error_t igraph_i_mincut_undirected( } } if (partition2) { - igraph_integer_t j = 0; + igraph_int_t j = 0; IGRAPH_CHECK(igraph_vector_int_resize(partition2, no_of_nodes - VECTOR(csize)[0])); for (i = 0; i < no_of_nodes; i++) { @@ -1278,9 +1278,9 @@ static igraph_error_t igraph_i_mincut_undirected( while (igraph_i_cutheap_size(&heap) >= 2) { - igraph_integer_t last; + igraph_int_t last; igraph_real_t acut; - igraph_integer_t a, n; + igraph_int_t a, n; igraph_vector_int_t *edges, *edges2; igraph_vector_int_t *neis, *neis2; @@ -1293,8 +1293,8 @@ static igraph_error_t igraph_i_mincut_undirected( neis = igraph_adjlist_get(&adjlist, a); n = igraph_vector_int_size(edges); for (i = 0; i < n; i++) { - igraph_integer_t edge = VECTOR(*edges)[i]; - igraph_integer_t to = VECTOR(*neis)[i]; + igraph_int_t edge = VECTOR(*edges)[i]; + igraph_int_t to = VECTOR(*neis)[i]; igraph_real_t weight = capacity ? VECTOR(*capacity)[edge] : 1.0; igraph_i_cutheap_update(&heap, to, weight); } @@ -1358,8 +1358,8 @@ static igraph_error_t igraph_i_mincut_undirected( neis = igraph_adjlist_get(&adjlist, last); n = igraph_vector_int_size(neis); for (i = 0; i < n; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; - igraph_integer_t n2, j; + igraph_int_t nei = VECTOR(*neis)[i]; + igraph_int_t n2, j; neis2 = igraph_adjlist_get(&adjlist, nei); n2 = igraph_vector_int_size(neis2); for (j = 0; j < n2; j++) { @@ -1391,9 +1391,9 @@ static igraph_error_t igraph_i_mincut_undirected( IGRAPH_FINALLY_CLEAN(3); if (calc_cut) { - igraph_integer_t bignode = VECTOR(mergehist)[2 * mincut_step + 1]; - igraph_integer_t i, idx; - igraph_integer_t size = 1; + igraph_int_t bignode = VECTOR(mergehist)[2 * mincut_step + 1]; + igraph_int_t i, idx; + igraph_int_t size = 1; igraph_bitset_t mark; IGRAPH_BITSET_INIT_FINALLY(&mark, no_of_nodes); @@ -1435,7 +1435,7 @@ static igraph_error_t igraph_i_mincut_undirected( so we first collect the edges in mergehist, we don't need that anymore. Then we copy it to 'cut'; */ if (cut) { - igraph_integer_t from, to; + igraph_int_t from, to; igraph_vector_int_clear(&mergehist); for (i = 0; i < no_of_edges; i++) { igraph_edge(graph, i, &from, &to); @@ -1464,8 +1464,8 @@ static igraph_error_t igraph_i_mincut_directed( igraph_vector_int_t *cut, const igraph_vector_t *capacity) { - igraph_integer_t i; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i; + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_real_t flow; igraph_real_t minmaxflow = IGRAPH_INFINITY; igraph_vector_int_t mypartition, mypartition2, mycut; @@ -1691,9 +1691,9 @@ static igraph_error_t igraph_i_mincut_value_undirected( igraph_error_t igraph_mincut_value(const igraph_t *graph, igraph_real_t *res, const igraph_vector_t *capacity) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_real_t minmaxflow, flow; - igraph_integer_t i; + igraph_int_t i; minmaxflow = IGRAPH_INFINITY; @@ -1730,15 +1730,15 @@ igraph_error_t igraph_mincut_value(const igraph_t *graph, igraph_real_t *res, static igraph_error_t igraph_i_st_vertex_connectivity_check_errors( const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target, igraph_vconn_nei_t neighbors, igraph_bool_t *done, - igraph_integer_t *no_conn) { + igraph_int_t *no_conn) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t eid; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t eid; igraph_bool_t conn; *done = true; *no_conn = 0; @@ -1788,18 +1788,18 @@ static igraph_error_t igraph_i_st_vertex_connectivity_check_errors( static igraph_error_t igraph_i_st_vertex_connectivity_directed( const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target, igraph_vconn_nei_t neighbors) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges; igraph_real_t real_res; igraph_t newgraph; - igraph_integer_t i, len; + igraph_int_t i, len; igraph_bool_t done; - igraph_integer_t no_conn; + igraph_int_t no_conn; igraph_vector_int_t incs; igraph_vector_t capacity; @@ -1836,7 +1836,7 @@ static igraph_error_t igraph_i_st_vertex_connectivity_directed( /* Do the maximum flow */ IGRAPH_CHECK(igraph_maxflow_value(&newgraph, &real_res, source, target + no_of_nodes, &capacity, NULL)); - *res = (igraph_integer_t) real_res; + *res = (igraph_int_t) real_res; *res -= no_conn; @@ -1849,14 +1849,14 @@ static igraph_error_t igraph_i_st_vertex_connectivity_directed( static igraph_error_t igraph_i_st_vertex_connectivity_undirected( const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target, igraph_vconn_nei_t neighbors) { igraph_t newgraph; igraph_bool_t done; - igraph_integer_t no_conn; + igraph_int_t no_conn; IGRAPH_CHECK(igraph_i_st_vertex_connectivity_check_errors(graph, res, source, target, neighbors, &done, &no_conn)); if (done) { @@ -1920,9 +1920,9 @@ static igraph_error_t igraph_i_st_vertex_connectivity_undirected( igraph_error_t igraph_st_vertex_connectivity( const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target, igraph_vconn_nei_t neighbors) { if (igraph_is_directed(graph)) { @@ -1940,17 +1940,17 @@ igraph_error_t igraph_st_vertex_connectivity( static igraph_error_t igraph_i_vertex_connectivity_directed( const igraph_t *graph, - igraph_integer_t *res, + igraph_int_t *res, igraph_bool_t all_edges_are_mutual) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges; - igraph_integer_t i, j, k, len; - igraph_integer_t minconn = no_of_nodes - 1, conn = 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges; + igraph_int_t i, j, k, len; + igraph_int_t minconn = no_of_nodes - 1, conn = 0; igraph_t split_graph; igraph_vector_t capacity; igraph_bool_t done; - igraph_integer_t dummy_num_connections; + igraph_int_t dummy_num_connections; igraph_vector_int_t incs; igraph_real_t real_res; @@ -2019,7 +2019,7 @@ static igraph_error_t igraph_i_vertex_connectivity_directed( VECTOR(capacity)[VECTOR(incs)[k]] = 1; } - conn = (igraph_integer_t) real_res; + conn = (igraph_int_t) real_res; } if (conn < minconn) { @@ -2049,7 +2049,7 @@ static igraph_error_t igraph_i_vertex_connectivity_directed( static igraph_error_t igraph_i_vertex_connectivity_undirected( const igraph_t *graph, - igraph_integer_t *res) { + igraph_int_t *res) { igraph_t newgraph; @@ -2074,7 +2074,7 @@ static igraph_error_t igraph_i_vertex_connectivity_undirected( */ static igraph_error_t igraph_i_connectivity_checks( const igraph_t *graph, - igraph_integer_t *res, + igraph_int_t *res, igraph_bool_t *found) { igraph_bool_t conn; @@ -2155,7 +2155,7 @@ static igraph_error_t igraph_i_connectivity_checks( */ igraph_error_t igraph_vertex_connectivity( - const igraph_t *graph, igraph_integer_t *res, + const igraph_t *graph, igraph_int_t *res, igraph_bool_t checks) { igraph_bool_t ret = false; @@ -2216,9 +2216,9 @@ igraph_error_t igraph_vertex_connectivity( */ igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target) { + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target) { igraph_real_t flow; @@ -2227,7 +2227,7 @@ igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph, } IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL)); - *res = (igraph_integer_t) flow; + *res = (igraph_int_t) flow; return IGRAPH_SUCCESS; } @@ -2267,11 +2267,11 @@ igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph, */ igraph_error_t igraph_edge_connectivity(const igraph_t *graph, - igraph_integer_t *res, + igraph_int_t *res, igraph_bool_t checks) { igraph_bool_t ret = false; - igraph_integer_t number_of_nodes = igraph_vcount(graph); + igraph_int_t number_of_nodes = igraph_vcount(graph); /* igraph_mincut_value returns infinity for the singleton graph, * which cannot be cast to an integer. We catch this case early @@ -2290,7 +2290,7 @@ igraph_error_t igraph_edge_connectivity(const igraph_t *graph, if (!ret) { igraph_real_t real_res; IGRAPH_CHECK(igraph_mincut_value(graph, &real_res, 0)); - *res = (igraph_integer_t)real_res; + *res = (igraph_int_t)real_res; } return IGRAPH_SUCCESS; @@ -2323,9 +2323,9 @@ igraph_error_t igraph_edge_connectivity(const igraph_t *graph, */ igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target) { + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target) { igraph_real_t flow; @@ -2336,7 +2336,7 @@ igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph, IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL)); - *res = (igraph_integer_t) flow; + *res = (igraph_int_t) flow; return IGRAPH_SUCCESS; } @@ -2371,9 +2371,9 @@ igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph, */ igraph_error_t igraph_vertex_disjoint_paths(const igraph_t *graph, - igraph_integer_t *res, - igraph_integer_t source, - igraph_integer_t target) { + igraph_int_t *res, + igraph_int_t source, + igraph_int_t target) { igraph_vector_int_t eids; @@ -2433,7 +2433,7 @@ igraph_error_t igraph_vertex_disjoint_paths(const igraph_t *graph, */ igraph_error_t igraph_adhesion(const igraph_t *graph, - igraph_integer_t *res, + igraph_int_t *res, igraph_bool_t checks) { return igraph_edge_connectivity(graph, res, checks); } @@ -2467,7 +2467,7 @@ igraph_error_t igraph_adhesion(const igraph_t *graph, */ igraph_error_t igraph_cohesion(const igraph_t *graph, - igraph_integer_t *res, + igraph_int_t *res, igraph_bool_t checks) { IGRAPH_CHECK(igraph_vertex_connectivity(graph, res, checks)); @@ -2521,8 +2521,8 @@ igraph_error_t igraph_gomory_hu_tree(const igraph_t *graph, igraph_vector_t *flows, const igraph_vector_t *capacity) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t source, target, mid, i, n; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t source, target, mid, i, n; igraph_vector_int_t neighbors; igraph_vector_t flow_values; igraph_vector_int_t partition; diff --git a/src/vendor/cigraph/src/flow/flow_conversion.c b/src/vendor/cigraph/src/flow/flow_conversion.c index 22814f54f3f..1cbebaf495c 100644 --- a/src/vendor/cigraph/src/flow/flow_conversion.c +++ b/src/vendor/cigraph/src/flow/flow_conversion.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -59,9 +59,9 @@ * \param result an uninitialized graph object; the result will be returned here */ igraph_error_t igraph_i_split_vertices(const igraph_t* graph, igraph_t* result) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t i; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t i; igraph_vector_int_t edges; if (!igraph_is_directed(graph)) { @@ -74,7 +74,7 @@ igraph_error_t igraph_i_split_vertices(const igraph_t* graph, igraph_t* result) IGRAPH_CHECK(igraph_vector_int_resize(&edges, 2 * (no_of_edges + no_of_nodes))); for (i = 0; i < 2 * no_of_edges; i += 2) { - igraph_integer_t to = VECTOR(edges)[i + 1]; + igraph_int_t to = VECTOR(edges)[i + 1]; VECTOR(edges)[i + 1] = no_of_nodes + to; } diff --git a/src/vendor/cigraph/src/flow/flow_internal.h b/src/vendor/cigraph/src/flow/flow_internal.h index d95a7c165e9..6308baf4f24 100644 --- a/src/vendor/cigraph/src/flow/flow_internal.h +++ b/src/vendor/cigraph/src/flow/flow_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -33,8 +33,8 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_all_st_cuts_pivot( const igraph_t *graph, const igraph_marked_queue_int_t *S, - const igraph_estack_t *T, igraph_integer_t source, igraph_integer_t target, - igraph_integer_t *v, igraph_vector_int_t *Isv, void *arg); + const igraph_estack_t *T, igraph_int_t source, igraph_int_t target, + igraph_int_t *v, igraph_vector_int_t *Isv, void *arg); igraph_error_t igraph_i_split_vertices(const igraph_t* graph, igraph_t* result); diff --git a/src/vendor/cigraph/src/flow/st-cuts.c b/src/vendor/cigraph/src/flow/st-cuts.c index 891c419ec68..6af56657c11 100644 --- a/src/vendor/cigraph/src/flow/st-cuts.c +++ b/src/vendor/cigraph/src/flow/st-cuts.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -42,9 +42,9 @@ typedef igraph_error_t igraph_provan_shier_pivot_t(const igraph_t *graph, const igraph_marked_queue_int_t *S, const igraph_estack_t *T, - igraph_integer_t source, - igraph_integer_t target, - igraph_integer_t *v, + igraph_int_t source, + igraph_int_t target, + igraph_int_t *v, igraph_vector_int_t *Isv, void *arg); @@ -87,15 +87,15 @@ typedef igraph_error_t igraph_provan_shier_pivot_t(const igraph_t *graph, igraph_error_t igraph_even_tarjan_reduction(const igraph_t *graph, igraph_t *graphbar, igraph_vector_t *capacity) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); - igraph_integer_t new_no_of_nodes; - igraph_integer_t new_no_of_edges = no_of_edges * 2; + igraph_int_t new_no_of_nodes; + igraph_int_t new_no_of_edges = no_of_edges * 2; igraph_vector_int_t edges; - igraph_integer_t edgeptr = 0, capptr = 0; - igraph_integer_t i; + igraph_int_t edgeptr = 0, capptr = 0; + igraph_int_t i; IGRAPH_SAFE_MULT(no_of_nodes, 2, &new_no_of_nodes); IGRAPH_SAFE_ADD(new_no_of_edges, no_of_nodes, &new_no_of_edges); @@ -126,8 +126,8 @@ igraph_error_t igraph_even_tarjan_reduction(const igraph_t *graph, igraph_t *gra /* Two news edges for each original edge (from,to) becomes (from'',to'), (to'',from') */ for (i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); VECTOR(edges)[edgeptr++] = from + no_of_nodes; VECTOR(edges)[edgeptr++] = to; VECTOR(edges)[edgeptr++] = to + no_of_nodes; @@ -154,10 +154,10 @@ static igraph_error_t igraph_i_residual_graph(const igraph_t *graph, const igraph_vector_t *flow, igraph_vector_int_t *tmp) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t i, no_new_edges = 0; - igraph_integer_t edgeptr = 0, capptr = 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t i, no_new_edges = 0; + igraph_int_t edgeptr = 0, capptr = 0; for (i = 0; i < no_of_edges; i++) { if (VECTOR(*flow)[i] < VECTOR(*capacity)[i]) { @@ -173,8 +173,8 @@ static igraph_error_t igraph_i_residual_graph(const igraph_t *graph, for (i = 0; i < no_of_edges; i++) { igraph_real_t c = VECTOR(*capacity)[i] - VECTOR(*flow)[i]; if (c > 0) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); VECTOR(*tmp)[edgeptr++] = from; VECTOR(*tmp)[edgeptr++] = to; if (residual_capacity) { @@ -196,7 +196,7 @@ igraph_error_t igraph_residual_graph(const igraph_t *graph, const igraph_vector_t *flow) { igraph_vector_int_t tmp; - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); if (igraph_vector_size(capacity) != no_of_edges) { IGRAPH_ERROR("Invalid `capacity' vector size", IGRAPH_EINVAL); @@ -222,10 +222,10 @@ static igraph_error_t igraph_i_reverse_residual_graph(const igraph_t *graph, const igraph_vector_t *flow, igraph_vector_int_t *tmp) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t i, no_new_edges = 0; - igraph_integer_t edgeptr = 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t i, no_new_edges = 0; + igraph_int_t edgeptr = 0; for (i = 0; i < no_of_edges; i++) { igraph_real_t cap = capacity ? VECTOR(*capacity)[i] : 1.0; @@ -240,8 +240,8 @@ static igraph_error_t igraph_i_reverse_residual_graph(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(tmp, no_new_edges * 2)); for (i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); igraph_real_t cap = capacity ? VECTOR(*capacity)[i] : 1.0; if (VECTOR(*flow)[i] > 0) { VECTOR(*tmp)[edgeptr++] = from; @@ -264,7 +264,7 @@ igraph_error_t igraph_reverse_residual_graph(const igraph_t *graph, igraph_t *residual, const igraph_vector_t *flow) { igraph_vector_int_t tmp; - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); if (capacity && igraph_vector_size(capacity) != no_of_edges) { IGRAPH_ERROR("Invalid `capacity' vector size", IGRAPH_EINVAL); @@ -288,7 +288,7 @@ typedef struct igraph_i_dbucket_t { igraph_vector_int_t next; } igraph_i_dbucket_t; -static igraph_error_t igraph_i_dbucket_init(igraph_i_dbucket_t *buck, igraph_integer_t size) { +static igraph_error_t igraph_i_dbucket_init(igraph_i_dbucket_t *buck, igraph_int_t size) { IGRAPH_VECTOR_INT_INIT_FINALLY(&buck->head, size); IGRAPH_CHECK(igraph_vector_int_init(&buck->next, size)); IGRAPH_FINALLY_CLEAN(1); @@ -300,8 +300,8 @@ static void igraph_i_dbucket_destroy(igraph_i_dbucket_t *buck) { igraph_vector_int_destroy(&buck->next); } -static igraph_error_t igraph_i_dbucket_insert(igraph_i_dbucket_t *buck, igraph_integer_t bid, - igraph_integer_t elem) { +static igraph_error_t igraph_i_dbucket_insert(igraph_i_dbucket_t *buck, igraph_int_t bid, + igraph_int_t elem) { /* Note: we can do this, since elem is not in any buckets */ VECTOR(buck->next)[elem] = VECTOR(buck->head)[bid]; VECTOR(buck->head)[bid] = elem + 1; @@ -309,17 +309,17 @@ static igraph_error_t igraph_i_dbucket_insert(igraph_i_dbucket_t *buck, igraph_i } static igraph_bool_t igraph_i_dbucket_empty(const igraph_i_dbucket_t *buck, - igraph_integer_t bid) { + igraph_int_t bid) { return VECTOR(buck->head)[bid] == 0; } -static igraph_integer_t igraph_i_dbucket_delete(igraph_i_dbucket_t *buck, igraph_integer_t bid) { - igraph_integer_t elem = VECTOR(buck->head)[bid] - 1; +static igraph_int_t igraph_i_dbucket_delete(igraph_i_dbucket_t *buck, igraph_int_t bid) { + igraph_int_t elem = VECTOR(buck->head)[bid] - 1; VECTOR(buck->head)[bid] = VECTOR(buck->next)[elem]; return elem; } -static igraph_error_t igraph_i_dominator_LINK(igraph_integer_t v, igraph_integer_t w, +static igraph_error_t igraph_i_dominator_LINK(igraph_int_t v, igraph_int_t w, igraph_vector_int_t *ancestor) { VECTOR(*ancestor)[w] = v + 1; return IGRAPH_SUCCESS; @@ -327,13 +327,13 @@ static igraph_error_t igraph_i_dominator_LINK(igraph_integer_t v, igraph_integer /* TODO: don't always reallocate path */ -static igraph_error_t igraph_i_dominator_COMPRESS(igraph_integer_t v, +static igraph_error_t igraph_i_dominator_COMPRESS(igraph_int_t v, igraph_vector_int_t *ancestor, igraph_vector_int_t *label, igraph_vector_int_t *semi) { igraph_stack_int_t path; - igraph_integer_t w = v; - igraph_integer_t top, pretop; + igraph_int_t w = v; + igraph_int_t top, pretop; IGRAPH_CHECK(igraph_stack_int_init(&path, 10)); IGRAPH_FINALLY(igraph_stack_int_destroy, &path); @@ -362,7 +362,7 @@ static igraph_error_t igraph_i_dominator_COMPRESS(igraph_integer_t v, return IGRAPH_SUCCESS; } -static igraph_integer_t igraph_i_dominator_EVAL(igraph_integer_t v, +static igraph_int_t igraph_i_dominator_EVAL(igraph_int_t v, igraph_vector_int_t *ancestor, igraph_vector_int_t *label, igraph_vector_int_t *semi) { @@ -432,13 +432,13 @@ static igraph_integer_t igraph_i_dominator_EVAL(igraph_integer_t v, */ igraph_error_t igraph_dominator_tree(const igraph_t *graph, - igraph_integer_t root, + igraph_int_t root, igraph_vector_int_t *dom, igraph_t *domtree, igraph_vector_int_t *leftout, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_adjlist_t succ, pred; igraph_vector_int_t parent; @@ -452,7 +452,7 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, igraph_vector_int_t vdom, *mydom = dom; - igraph_integer_t component_size = 0; + igraph_int_t component_size = 0; if (root < 0 || root >= no_of_nodes) { IGRAPH_ERROR("Invalid root vertex ID for dominator tree.", @@ -498,17 +498,17 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, /*dist=*/ NULL, /*in_callback=*/ NULL, /*out_callback=*/ NULL, /*extra=*/ NULL)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(vertex)[i] >= 0) { - igraph_integer_t t = VECTOR(vertex)[i]; + igraph_int_t t = VECTOR(vertex)[i]; VECTOR(semi)[t] = component_size + 1; VECTOR(vertex)[component_size] = t + 1; component_size++; } } if (leftout) { - igraph_integer_t n = no_of_nodes - component_size; - igraph_integer_t p = 0, j; + igraph_int_t n = no_of_nodes - component_size; + igraph_int_t p = 0, j; IGRAPH_CHECK(igraph_vector_int_resize(leftout, n)); for (j = 0; j < no_of_nodes && p < n; j++) { if (VECTOR(parent)[j] < -1) { @@ -519,11 +519,11 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, /* We need to go over 'pred' because it should contain only the edges towards the target vertex. */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_vector_int_t *v = igraph_adjlist_get(&pred, i); - igraph_integer_t n = igraph_vector_int_size(v); - for (igraph_integer_t j = 0; j < n; ) { - igraph_integer_t v2 = VECTOR(*v)[j]; + igraph_int_t n = igraph_vector_int_size(v); + for (igraph_int_t j = 0; j < n; ) { + igraph_int_t v2 = VECTOR(*v)[j]; if (VECTOR(parent)[v2] >= -1) { j++; } else { @@ -536,13 +536,13 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, /* Now comes the main algorithm, steps 2 & 3 */ - for (igraph_integer_t i = component_size - 1; i > 0; i--) { - igraph_integer_t w = VECTOR(vertex)[i] - 1; + for (igraph_int_t i = component_size - 1; i > 0; i--) { + igraph_int_t w = VECTOR(vertex)[i] - 1; igraph_vector_int_t *predw = igraph_adjlist_get(&pred, w); - igraph_integer_t j, n = igraph_vector_int_size(predw); + igraph_int_t j, n = igraph_vector_int_size(predw); for (j = 0; j < n; j++) { - igraph_integer_t v = VECTOR(*predw)[j]; - igraph_integer_t u = igraph_i_dominator_EVAL(v, &ancestor, &label, &semi); + igraph_int_t v = VECTOR(*predw)[j]; + igraph_int_t u = igraph_i_dominator_EVAL(v, &ancestor, &label, &semi); if (VECTOR(semi)[u] < VECTOR(semi)[w]) { VECTOR(semi)[w] = VECTOR(semi)[u]; } @@ -550,8 +550,8 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, igraph_i_dbucket_insert(&bucket, VECTOR(vertex)[ VECTOR(semi)[w] - 1 ] - 1, w); igraph_i_dominator_LINK(VECTOR(parent)[w], w, &ancestor); while (!igraph_i_dbucket_empty(&bucket, VECTOR(parent)[w])) { - igraph_integer_t v = igraph_i_dbucket_delete(&bucket, VECTOR(parent)[w]); - igraph_integer_t u = igraph_i_dominator_EVAL(v, &ancestor, &label, &semi); + igraph_int_t v = igraph_i_dbucket_delete(&bucket, VECTOR(parent)[w]); + igraph_int_t u = igraph_i_dominator_EVAL(v, &ancestor, &label, &semi); VECTOR(*mydom)[v] = VECTOR(semi)[u] < VECTOR(semi)[v] ? u : VECTOR(parent)[w]; } @@ -559,8 +559,8 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, /* Finally, step 4 */ - for (igraph_integer_t i = 1; i < component_size; i++) { - igraph_integer_t w = VECTOR(vertex)[i] - 1; + for (igraph_int_t i = 1; i < component_size; i++) { + igraph_int_t w = VECTOR(vertex)[i] - 1; if (VECTOR(*mydom)[w] != VECTOR(vertex)[VECTOR(semi)[w] - 1] - 1) { VECTOR(*mydom)[w] = VECTOR(*mydom)[VECTOR(*mydom)[w]]; } @@ -579,9 +579,9 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, if (domtree) { igraph_vector_int_t edges; - igraph_integer_t ptr = 0; + igraph_int_t ptr = 0; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, component_size * 2 - 2); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (i != root && VECTOR(*mydom)[i] >= 0) { if (mode == IGRAPH_OUT) { VECTOR(edges)[ptr++] = VECTOR(*mydom)[i]; @@ -612,14 +612,14 @@ typedef struct igraph_i_all_st_cuts_minimal_dfs_data_t { igraph_stack_int_t *stack; igraph_bitset_t *nomark; const igraph_bitset_t *GammaX; - igraph_integer_t root; + igraph_int_t root; const igraph_vector_int_t *map; } igraph_i_all_st_cuts_minimal_dfs_data_t; static igraph_error_t igraph_i_all_st_cuts_minimal_dfs_incb( const igraph_t *graph, - igraph_integer_t vid, - igraph_integer_t dist, + igraph_int_t vid, + igraph_int_t dist, void *extra) { igraph_i_all_st_cuts_minimal_dfs_data_t *data = extra; @@ -627,13 +627,13 @@ static igraph_error_t igraph_i_all_st_cuts_minimal_dfs_incb( igraph_bitset_t *nomark = data->nomark; const igraph_bitset_t *GammaX = data->GammaX; const igraph_vector_int_t *map = data->map; - igraph_integer_t realvid = VECTOR(*map)[vid]; + igraph_int_t realvid = VECTOR(*map)[vid]; IGRAPH_UNUSED(graph); IGRAPH_UNUSED(dist); if (IGRAPH_BIT_TEST(*GammaX, realvid)) { if (!igraph_stack_int_empty(stack)) { - igraph_integer_t top = igraph_stack_int_top(stack); + igraph_int_t top = igraph_stack_int_top(stack); IGRAPH_BIT_SET(*nomark, top); /* we just found a smaller one */ } IGRAPH_CHECK(igraph_stack_int_push(stack, realvid)); @@ -644,13 +644,13 @@ static igraph_error_t igraph_i_all_st_cuts_minimal_dfs_incb( static igraph_error_t igraph_i_all_st_cuts_minimal_dfs_outcb( const igraph_t *graph, - igraph_integer_t vid, - igraph_integer_t dist, + igraph_int_t vid, + igraph_int_t dist, void *extra) { igraph_i_all_st_cuts_minimal_dfs_data_t *data = extra; igraph_stack_int_t *stack = data->stack; const igraph_vector_int_t *map = data->map; - igraph_integer_t realvid = VECTOR(*map)[vid]; + igraph_int_t realvid = VECTOR(*map)[vid]; IGRAPH_UNUSED(graph); IGRAPH_UNUSED(dist); @@ -664,17 +664,17 @@ static igraph_error_t igraph_i_all_st_cuts_minimal_dfs_outcb( static igraph_error_t igraph_i_all_st_cuts_minimal(const igraph_t *graph, const igraph_t *domtree, - igraph_integer_t root, + igraph_int_t root, const igraph_marked_queue_int_t *X, const igraph_bitset_t *GammaX, const igraph_vector_int_t *invmap, igraph_vector_int_t *minimal) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_stack_int_t stack; igraph_bitset_t nomark; igraph_i_all_st_cuts_minimal_dfs_data_t data; - igraph_integer_t i; + igraph_int_t i; IGRAPH_UNUSED(X); @@ -721,24 +721,24 @@ static igraph_error_t igraph_i_all_st_cuts_minimal(const igraph_t *graph, /* not 'static' because used in igraph_all_st_cuts.c test program */ igraph_error_t igraph_i_all_st_cuts_pivot( const igraph_t *graph, const igraph_marked_queue_int_t *S, - const igraph_estack_t *T, igraph_integer_t source, igraph_integer_t target, - igraph_integer_t *v, igraph_vector_int_t *Isv, void *arg + const igraph_estack_t *T, igraph_int_t source, igraph_int_t target, + igraph_int_t *v, igraph_vector_int_t *Isv, void *arg ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_t Sbar; igraph_vector_int_t Sbar_map, Sbar_invmap; igraph_vector_int_t keep; igraph_t domtree; igraph_vector_int_t leftout; - igraph_integer_t i, nomin, n; - igraph_integer_t root; + igraph_int_t i, nomin, n; + igraph_int_t root; igraph_vector_int_t M; igraph_bitset_t GammaS; igraph_vector_int_t Nuv; igraph_vector_int_t Isv_min; igraph_vector_int_t GammaS_vec; - igraph_integer_t Sbar_size; + igraph_int_t Sbar_size; IGRAPH_UNUSED(arg); @@ -787,14 +787,14 @@ igraph_error_t igraph_i_all_st_cuts_pivot( for (i = 0; i < no_of_nodes; i++) { if (igraph_marked_queue_int_iselement(S, i)) { igraph_vector_int_t neis; - igraph_integer_t j; + igraph_int_t j; IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); IGRAPH_CHECK(igraph_neighbors( graph, &neis, i, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE )); n = igraph_vector_int_size(&neis); for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + igraph_int_t nei = VECTOR(neis)[j]; if (!igraph_marked_queue_int_iselement(S, nei)) { IGRAPH_BIT_SET(GammaS, nei); } @@ -838,8 +838,8 @@ 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] ]; - igraph_integer_t nuvsize, isvlen, j; + igraph_int_t min = VECTOR(Sbar_map)[ VECTOR(M)[i] ]; + igraph_int_t nuvsize, isvlen, j; IGRAPH_CHECK(igraph_dfs(&domtree, min, IGRAPH_IN, /*unreachable=*/ false, /*order=*/ &Nuv, /*order_out=*/ NULL, /*parents=*/ NULL, /*dist=*/ NULL, @@ -847,7 +847,7 @@ igraph_error_t igraph_i_all_st_cuts_pivot( /*extra=*/ NULL)); /* Remove the negative values from the end of the vector */ for (nuvsize = 0; nuvsize < Sbar_size; nuvsize++) { - igraph_integer_t t = VECTOR(Nuv)[nuvsize]; + igraph_int_t t = VECTOR(Nuv)[nuvsize]; if (t >= 0) { VECTOR(Nuv)[nuvsize] = VECTOR(Sbar_invmap)[t]; } else { @@ -878,7 +878,7 @@ igraph_error_t igraph_i_all_st_cuts_pivot( such a v is found, compute Isv={x|v[Nu(v) U K]x} and return v and Isv; otherwise return Isv={}. */ for (j = 0; j < isvlen; j++) { - igraph_integer_t u = VECTOR(Isv_min)[j]; + igraph_int_t u = VECTOR(Isv_min)[j]; if (igraph_estack_iselement(T, u) || u == target) { break; } @@ -927,14 +927,14 @@ igraph_error_t igraph_i_all_st_cuts_pivot( static igraph_error_t igraph_i_provan_shier_list_recursive( const igraph_t *graph, igraph_marked_queue_int_t *S, - igraph_estack_t *T, igraph_integer_t source, igraph_integer_t target, + igraph_estack_t *T, igraph_int_t source, igraph_int_t target, igraph_vector_int_list_t *result, igraph_provan_shier_pivot_t *pivot, igraph_vector_int_t *Isv, void *pivot_arg ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t v = 0; - igraph_integer_t i, n; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t v = 0; + igraph_int_t i, n; pivot(graph, S, T, source, target, &v, Isv, pivot_arg); @@ -979,7 +979,7 @@ static igraph_error_t igraph_i_provan_shier_list_recursive( static igraph_error_t igraph_provan_shier_list( const igraph_t *graph, igraph_marked_queue_int_t *S, - igraph_estack_t *T, igraph_integer_t source, igraph_integer_t target, + igraph_estack_t *T, igraph_int_t source, igraph_int_t target, igraph_vector_int_list_t *result, igraph_provan_shier_pivot_t *pivot, void *pivot_arg ) { @@ -1030,8 +1030,8 @@ static igraph_error_t igraph_provan_shier_list( igraph_error_t igraph_all_st_cuts(const igraph_t *graph, igraph_vector_int_list_t *cuts, igraph_vector_int_list_t *partition1s, - igraph_integer_t source, - igraph_integer_t target) { + igraph_int_t source, + igraph_int_t target) { /* S is a special stack, in which elements are pushed in batches. It is then possible to remove the whole batch in one step. @@ -1040,13 +1040,13 @@ igraph_error_t igraph_all_st_cuts(const igraph_t *graph, Every element is included at most once. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_marked_queue_int_t S; igraph_estack_t T; igraph_vector_int_list_t *mypartition1s = partition1s, vpartition1s; igraph_vector_int_t cut; - igraph_integer_t i, nocuts; + igraph_int_t i, nocuts; if (!igraph_is_directed(graph)) { IGRAPH_ERROR("Listing all s-t cuts only implemented for " @@ -1083,19 +1083,19 @@ igraph_error_t igraph_all_st_cuts(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_list_reserve(cuts, nocuts)); for (i = 0; i < nocuts; i++) { igraph_vector_int_t *part = igraph_vector_int_list_get_ptr(mypartition1s, i); - igraph_integer_t cutsize = 0; - igraph_integer_t j, partlen = igraph_vector_int_size(part); + igraph_int_t cutsize = 0; + igraph_int_t j, partlen = igraph_vector_int_size(part); /* Mark elements */ for (j = 0; j < partlen; j++) { - igraph_integer_t v = VECTOR(*part)[j]; + igraph_int_t v = VECTOR(*part)[j]; VECTOR(inS)[v] = i + 1; } /* Check how many edges */ for (j = 0; j < no_of_edges; j++) { - igraph_integer_t from = IGRAPH_FROM(graph, j); - igraph_integer_t to = IGRAPH_TO(graph, j); - igraph_integer_t pfrom = VECTOR(inS)[from]; - igraph_integer_t pto = VECTOR(inS)[to]; + igraph_int_t from = IGRAPH_FROM(graph, j); + igraph_int_t to = IGRAPH_TO(graph, j); + igraph_int_t pfrom = VECTOR(inS)[from]; + igraph_int_t pto = VECTOR(inS)[to]; if (pfrom == i + 1 && pto != i + 1) { cutsize++; } @@ -1104,10 +1104,10 @@ igraph_error_t igraph_all_st_cuts(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(&cut, cutsize)); cutsize = 0; for (j = 0; j < no_of_edges; j++) { - igraph_integer_t from = IGRAPH_FROM(graph, j); - igraph_integer_t to = IGRAPH_TO(graph, j); - igraph_integer_t pfrom = VECTOR(inS)[from]; - igraph_integer_t pto = VECTOR(inS)[to]; + igraph_int_t from = IGRAPH_FROM(graph, j); + igraph_int_t to = IGRAPH_TO(graph, j); + igraph_int_t pfrom = VECTOR(inS)[from]; + igraph_int_t pto = VECTOR(inS)[to]; if ((pfrom == i + 1 && pto != i + 1)) { VECTOR(cut)[cutsize++] = j; } @@ -1149,8 +1149,8 @@ static igraph_error_t igraph_i_all_st_mincuts_minimal(const igraph_t *residual, const igraph_bitset_t *active, igraph_vector_int_t *minimal) { - igraph_integer_t no_of_nodes = igraph_vcount(residual); - igraph_integer_t i; + igraph_int_t no_of_nodes = igraph_vcount(residual); + igraph_int_t i; igraph_vector_int_t neis; igraph_bitset_t connected_to_minimal; @@ -1168,7 +1168,7 @@ static igraph_error_t igraph_i_all_st_mincuts_minimal(const igraph_t *residual, * active or not. */ for (i = 0; i < no_of_nodes; i++) { - igraph_integer_t j, n; + igraph_int_t j, n; IGRAPH_CHECK(igraph_neighbors( residual, &neis, i, IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE )); @@ -1177,10 +1177,10 @@ static igraph_error_t igraph_i_all_st_mincuts_minimal(const igraph_t *residual, // Only consider nodes that are not in S. if (!igraph_marked_queue_int_iselement(S, i)) { for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + igraph_int_t nei = VECTOR(neis)[j]; /* If connected to node that is connected to node that is minimal, - * this node is also connected to node that is minimal. - */ + * this node is also connected to node that is minimal. + */ if (IGRAPH_BIT_TEST(connected_to_minimal, nei)) { IGRAPH_BIT_SET(connected_to_minimal, i); break; @@ -1188,15 +1188,15 @@ static igraph_error_t igraph_i_all_st_mincuts_minimal(const igraph_t *residual, } /* If this node is not connected to node that is minimal, and this node - * is minimal and active itself, set it as a minimal node. - */ + * is minimal and active itself, set it as a minimal node. + */ if (!IGRAPH_BIT_TEST(connected_to_minimal, i) && IGRAPH_BIT_TEST(*active, i)) { - igraph_vector_int_push_back(minimal, i); + IGRAPH_CHECK(igraph_vector_int_push_back(minimal, i)); /* Also mark this node as connected to minimal, to make sure that - * any descendants will be marked as being connected to a minimal - * node. - */ + * any descendants will be marked as being connected to a minimal + * node. + */ IGRAPH_BIT_SET(connected_to_minimal, i); } } @@ -1216,20 +1216,20 @@ typedef struct igraph_i_all_st_mincuts_data_t { static igraph_error_t igraph_i_all_st_mincuts_pivot(const igraph_t *graph, const igraph_marked_queue_int_t *S, const igraph_estack_t *T, - igraph_integer_t source, - igraph_integer_t target, - igraph_integer_t *v, + igraph_int_t source, + igraph_int_t target, + igraph_int_t *v, igraph_vector_int_t *Isv, void *arg) { igraph_i_all_st_mincuts_data_t *data = arg; const igraph_bitset_t *active = data->active; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i, j; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i, j; igraph_vector_int_t keep; igraph_vector_int_t M; - igraph_integer_t nomin; + igraph_int_t nomin; IGRAPH_UNUSED(source); IGRAPH_UNUSED(target); @@ -1255,7 +1255,7 @@ static igraph_error_t igraph_i_all_st_mincuts_pivot(const igraph_t *graph, igraph_vector_int_clear(Isv); nomin = igraph_vector_int_size(&M); for (i = 0; i < nomin; i++) { - igraph_integer_t min = VECTOR(M)[i]; + igraph_int_t min = VECTOR(M)[i]; if (min != target) if (!igraph_estack_iselement(T, min)) { break; @@ -1275,7 +1275,7 @@ static igraph_error_t igraph_i_all_st_mincuts_pivot(const igraph_t *graph, /*succ=*/ NULL, /*dist=*/ NULL, /*callback=*/ NULL, /*extra=*/ NULL)); for (j = 0; j < no_of_nodes; j++) { - igraph_integer_t u = VECTOR(Isv_min)[j]; + igraph_int_t u = VECTOR(Isv_min)[j]; if (u < 0) { break; } @@ -1335,23 +1335,23 @@ static igraph_error_t igraph_i_all_st_mincuts_pivot(const igraph_t *graph, igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value, igraph_vector_int_list_t *cuts, igraph_vector_int_list_t *partition1s, - igraph_integer_t source, - igraph_integer_t target, + igraph_int_t source, + igraph_int_t target, const igraph_vector_t *capacity) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_t flow; igraph_t residual; igraph_vector_int_t NtoL; igraph_vector_int_t cut; - igraph_integer_t newsource, newtarget; + igraph_int_t newsource, newtarget; igraph_marked_queue_int_t S; igraph_estack_t T; igraph_i_all_st_mincuts_data_t pivot_data; igraph_bitset_t VE1bool; - igraph_integer_t i, nocuts; - igraph_integer_t proj_nodes; + igraph_int_t i, nocuts; + igraph_int_t proj_nodes; igraph_vector_int_t revmap_ptr, revmap_next; igraph_vector_int_list_t closedsets; igraph_vector_int_list_t *mypartition1s = partition1s, vpartition1s; @@ -1408,7 +1408,7 @@ igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value IGRAPH_CHECK(igraph_simplify(&residual, /*remove_multiple=*/ true, /*remove_loops=*/ true, /*edge_comb=*/ NULL)); /* We relabel the residual graph so that it is in topological sort order. */ - igraph_integer_t no_of_nodes_residual = igraph_vcount(&residual); + igraph_int_t no_of_nodes_residual = igraph_vcount(&residual); igraph_vector_int_t order; igraph_t tmpgraph; IGRAPH_VECTOR_INT_INIT_FINALLY(&order, no_of_nodes_residual); @@ -1448,10 +1448,10 @@ igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value IGRAPH_BITSET_INIT_FINALLY(&VE1bool, proj_nodes); for (i = 0; i < no_of_edges; i++) { if (VECTOR(flow)[i] > 0) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); - igraph_integer_t pfrom = VECTOR(NtoL)[from]; - igraph_integer_t pto = VECTOR(NtoL)[to]; + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); + igraph_int_t pfrom = VECTOR(NtoL)[from]; + igraph_int_t pto = VECTOR(NtoL)[to]; if (!IGRAPH_BIT_TEST(VE1bool, pfrom)) { IGRAPH_BIT_SET(VE1bool, pfrom); } @@ -1490,7 +1490,7 @@ igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value IGRAPH_VECTOR_INT_INIT_FINALLY(&revmap_ptr, igraph_vcount(&residual)); IGRAPH_VECTOR_INT_INIT_FINALLY(&revmap_next, no_of_nodes); for (i = 0; i < no_of_nodes; i++) { - igraph_integer_t id = VECTOR(NtoL)[i]; + igraph_int_t id = VECTOR(NtoL)[i]; VECTOR(revmap_next)[i] = VECTOR(revmap_ptr)[id]; VECTOR(revmap_ptr)[id] = i + 1; } @@ -1501,12 +1501,12 @@ igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value IGRAPH_CHECK(igraph_vector_int_list_reserve(mypartition1s, nocuts)); for (i = 0; i < nocuts; i++) { igraph_vector_int_t *supercut = igraph_vector_int_list_get_ptr(&closedsets, i); - igraph_integer_t j, supercutsize = igraph_vector_int_size(supercut); + igraph_int_t j, supercutsize = igraph_vector_int_size(supercut); igraph_vector_int_clear(&cut); for (j = 0; j < supercutsize; j++) { - igraph_integer_t vtx = VECTOR(*supercut)[j]; - igraph_integer_t ovtx = VECTOR(revmap_ptr)[vtx]; + igraph_int_t vtx = VECTOR(*supercut)[j]; + igraph_int_t ovtx = VECTOR(revmap_ptr)[vtx]; while (ovtx != 0) { ovtx--; IGRAPH_CHECK(igraph_vector_int_push_back(&cut, ovtx)); @@ -1533,17 +1533,17 @@ igraph_error_t igraph_all_st_mincuts(const igraph_t *graph, igraph_real_t *value for (i = 0; i < nocuts; i++) { igraph_vector_int_t *part = igraph_vector_int_list_get_ptr(mypartition1s, i); - igraph_integer_t j, n = igraph_vector_int_size(part); + igraph_int_t j, n = igraph_vector_int_size(part); igraph_vector_int_clear(&cut); for (j = 0; j < n; j++) { - igraph_integer_t vtx = VECTOR(*part)[j]; + igraph_int_t vtx = VECTOR(*part)[j]; VECTOR(memb)[vtx] = i + 1; } for (j = 0; j < no_of_edges; j++) { if (VECTOR(flow)[j] > 0) { - igraph_integer_t from = IGRAPH_FROM(graph, j); - igraph_integer_t to = IGRAPH_TO(graph, j); + igraph_int_t from = IGRAPH_FROM(graph, j); + igraph_int_t to = IGRAPH_TO(graph, j); if (VECTOR(memb)[from] == i + 1 && VECTOR(memb)[to] != i + 1) { IGRAPH_CHECK(igraph_vector_int_push_back(&cut, j)); } diff --git a/src/vendor/cigraph/src/games/barabasi.c b/src/vendor/cigraph/src/games/barabasi.c index 45b7144ede1..49e91292d24 100644 --- a/src/vendor/cigraph/src/games/barabasi.c +++ b/src/vendor/cigraph/src/games/barabasi.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -37,17 +37,17 @@ static igraph_real_t attraction(igraph_real_t degree, igraph_real_t power, igrap return ( power == 0 ? 1.0 : pow(degree, power) ) + A; } -static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer_t n, - igraph_integer_t m, +static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_int_t n, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_bool_t directed, const igraph_t *start_from); static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, - igraph_integer_t n, + igraph_int_t n, igraph_real_t power, - igraph_integer_t m, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t A, @@ -55,30 +55,30 @@ static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, const igraph_t *start_from); static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, - igraph_integer_t n, + igraph_int_t n, igraph_real_t power, - igraph_integer_t m, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t A, igraph_bool_t directed, const igraph_t *start_from); -static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer_t n, - igraph_integer_t m, +static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_int_t n, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_bool_t directed, const igraph_t *start_from) { - igraph_integer_t no_of_nodes = n; - igraph_integer_t no_of_neighbors = m; - igraph_integer_t *bag; - igraph_integer_t bagp = 0; + igraph_int_t no_of_nodes = n; + igraph_int_t no_of_neighbors = m; + igraph_int_t *bag; + igraph_int_t bagp = 0; igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t resp; - igraph_integer_t i, j, k; - igraph_integer_t bagsize, start_nodes, start_edges, new_edges, no_of_edges; + igraph_int_t resp; + igraph_int_t i, j, k; + igraph_int_t bagsize, start_nodes, start_edges, new_edges, no_of_edges; if (!directed) { outpref = true; @@ -110,7 +110,7 @@ static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); - bag = IGRAPH_CALLOC(bagsize, igraph_integer_t); + bag = IGRAPH_CALLOC(bagsize, igraph_int_t); if (bag == 0) { IGRAPH_ERROR("barabasi_game failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -119,14 +119,14 @@ static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer /* The first node(s) in the bag */ if (start_from) { igraph_vector_int_t deg; - igraph_integer_t ii, jj, sn = igraph_vcount(start_from); + igraph_int_t ii, jj, sn = igraph_vcount(start_from); igraph_neimode_t mm = outpref ? IGRAPH_ALL : IGRAPH_IN; IGRAPH_VECTOR_INT_INIT_FINALLY(°, sn); IGRAPH_CHECK(igraph_degree(start_from, °, igraph_vss_all(), mm, IGRAPH_LOOPS)); for (ii = 0; ii < sn; ii++) { - igraph_integer_t d = VECTOR(deg)[ii]; + igraph_int_t d = VECTOR(deg)[ii]; for (jj = 0; jj <= d; jj++) { bag[bagp++] = ii; } @@ -156,7 +156,7 @@ static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer no_of_neighbors = VECTOR(*outseq)[k]; } for (j = 0; j < no_of_neighbors; j++) { - igraph_integer_t to = bag[RNG_INTEGER(0, bagp - 1)]; + igraph_int_t to = bag[RNG_INTEGER(0, bagp - 1)]; VECTOR(edges)[resp++] = i; VECTOR(edges)[resp++] = to; } @@ -179,23 +179,23 @@ static igraph_error_t igraph_i_barabasi_game_bag(igraph_t *graph, igraph_integer } static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, - igraph_integer_t n, + igraph_int_t n, igraph_real_t power, - igraph_integer_t m, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t A, igraph_bool_t directed, const igraph_t *start_from) { - igraph_integer_t no_of_nodes = n; - igraph_integer_t no_of_neighbors = m; + igraph_int_t no_of_nodes = n; + igraph_int_t no_of_neighbors = m; igraph_vector_int_t edges; - igraph_integer_t i, j, k; + igraph_int_t i, j, k; igraph_psumtree_t sumtree; - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; igraph_vector_int_t degree; - igraph_integer_t start_nodes, start_edges, new_edges, no_of_edges; + igraph_int_t start_nodes, start_edges, new_edges, no_of_edges; if (!directed) { outpref = true; @@ -227,7 +227,7 @@ static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, /* First node(s): */ if (start_from) { - igraph_integer_t ii, sn = igraph_vcount(start_from); + igraph_int_t ii, sn = igraph_vcount(start_from); igraph_neimode_t mm = outpref ? IGRAPH_ALL : IGRAPH_IN; IGRAPH_CHECK(igraph_degree(start_from, °ree, igraph_vss_all(), mm, IGRAPH_LOOPS)); @@ -251,7 +251,7 @@ static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, for (i = (start_from ? start_nodes : 1), k = (start_from ? 0 : 1); i < no_of_nodes; i++, k++) { igraph_real_t sum = igraph_psumtree_sum(&sumtree); - igraph_integer_t to; + igraph_int_t to; IGRAPH_ALLOW_INTERRUPTION(); @@ -272,7 +272,7 @@ static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, } /* update probabilities */ for (j = 0; j < no_of_neighbors; j++) { - igraph_integer_t nn = VECTOR(edges)[edgeptr - 2 * j - 1]; + igraph_int_t nn = VECTOR(edges)[edgeptr - 2 * j - 1]; IGRAPH_CHECK(igraph_psumtree_update(&sumtree, nn, attraction(VECTOR(degree)[nn], power, A))); } if (outpref) { @@ -295,23 +295,23 @@ static igraph_error_t igraph_i_barabasi_game_psumtree_multiple(igraph_t *graph, } static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, - igraph_integer_t n, + igraph_int_t n, igraph_real_t power, - igraph_integer_t m, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t A, igraph_bool_t directed, const igraph_t *start_from) { - igraph_integer_t no_of_nodes = n; - igraph_integer_t no_of_neighbors = m; + igraph_int_t no_of_nodes = n; + igraph_int_t no_of_neighbors = m; igraph_vector_int_t edges; - igraph_integer_t i, j, k; + igraph_int_t i, j, k; igraph_psumtree_t sumtree; - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; igraph_vector_int_t degree; - igraph_integer_t start_nodes, start_edges, new_edges, no_of_edges; + igraph_int_t start_nodes, start_edges, new_edges, no_of_edges; if (!directed) { outpref = true; @@ -344,7 +344,7 @@ static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, /* First node(s): */ if (start_from) { - igraph_integer_t ii, sn = igraph_vcount(start_from); + igraph_int_t ii, sn = igraph_vcount(start_from); igraph_neimode_t mm = outpref ? IGRAPH_ALL : IGRAPH_IN; IGRAPH_CHECK(igraph_degree(start_from, °ree, igraph_vss_all(), mm, IGRAPH_LOOPS)); @@ -367,7 +367,7 @@ static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, for (i = (start_from ? start_nodes : 1), k = (start_from ? 0 : 1); i < no_of_nodes; i++, k++) { igraph_real_t sum; - igraph_integer_t to; + igraph_int_t to; IGRAPH_ALLOW_INTERRUPTION(); @@ -401,7 +401,7 @@ static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, } /* update probabilities */ for (j = 0; j < no_of_neighbors; j++) { - igraph_integer_t nn = VECTOR(edges)[edgeptr - 2 * j - 1]; + igraph_int_t nn = VECTOR(edges)[edgeptr - 2 * j - 1]; IGRAPH_CHECK(igraph_psumtree_update(&sumtree, nn, attraction(VECTOR(degree)[nn], power, A))); } } @@ -520,9 +520,9 @@ static igraph_error_t igraph_i_barabasi_game_psumtree(igraph_t *graph, * \example examples/simple/igraph_barabasi_game.c * \example examples/simple/igraph_barabasi_game2.c */ -igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_integer_t n, +igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_int_t n, igraph_real_t power, - igraph_integer_t m, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t A, @@ -530,8 +530,8 @@ igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_integer_t n, igraph_barabasi_algorithm_t algo, const igraph_t *start_from) { - igraph_integer_t start_nodes = start_from ? igraph_vcount(start_from) : 0; - igraph_integer_t newn = start_from ? n - start_nodes : n; + igraph_int_t start_nodes = start_from ? igraph_vcount(start_from) : 0; + igraph_int_t newn = start_from ? n - start_nodes : n; /* In undirected graphs, always consider the total degree. */ if (!directed) { @@ -666,26 +666,26 @@ static igraph_real_t attraction_aging( * of vertices, |E| the number of edges. */ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, - igraph_integer_t nodes, - igraph_integer_t m, + igraph_int_t nodes, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t pa_exp, igraph_real_t aging_exp, - igraph_integer_t aging_bins, + igraph_int_t aging_bins, igraph_real_t zero_deg_appeal, igraph_real_t zero_age_appeal, igraph_real_t deg_coef, igraph_real_t age_coef, igraph_bool_t directed) { - igraph_integer_t no_of_nodes = nodes; - igraph_integer_t no_of_neighbors = m; - igraph_integer_t binwidth; - igraph_integer_t no_of_edges; + igraph_int_t no_of_nodes = nodes; + igraph_int_t no_of_neighbors = m; + igraph_int_t binwidth; + igraph_int_t no_of_edges; igraph_vector_int_t edges; - igraph_integer_t i, j, k; + igraph_int_t i, j, k; igraph_psumtree_t sumtree; - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; igraph_vector_int_t degree; if (no_of_nodes < 0) { @@ -762,7 +762,7 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, /* And the rest: */ for (i = 1; i < no_of_nodes; i++) { igraph_real_t sum; - igraph_integer_t to; + igraph_int_t to; IGRAPH_ALLOW_INTERRUPTION(); @@ -784,8 +784,8 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, } /* update probabilities */ for (j = 0; j < no_of_neighbors; j++) { - igraph_integer_t n = VECTOR(edges)[edgeptr - 2 * j - 1]; - igraph_integer_t age = (i - n) / binwidth; + igraph_int_t n = VECTOR(edges)[edgeptr - 2 * j - 1]; + igraph_int_t age = (i - n) / binwidth; IGRAPH_CHECK(igraph_psumtree_update( &sumtree, n, attraction_aging(VECTOR(degree)[n], age+1, @@ -815,9 +815,9 @@ igraph_error_t igraph_barabasi_aging_game(igraph_t *graph, /* aging */ for (k = 1; binwidth * k <= i; k++) { - igraph_integer_t shnode = i - binwidth * k; - igraph_integer_t deg = VECTOR(degree)[shnode]; - igraph_integer_t age = (i - shnode) / binwidth; + igraph_int_t shnode = i - binwidth * k; + igraph_int_t deg = VECTOR(degree)[shnode]; + igraph_int_t age = (i - shnode) / binwidth; /* igraph_real_t old=igraph_psumtree_get(&sumtree, shnode); */ IGRAPH_CHECK(igraph_psumtree_update( &sumtree, shnode, diff --git a/src/vendor/cigraph/src/games/callaway_traits.c b/src/vendor/cigraph/src/games/callaway_traits.c index 0e019ee0279..7b93af44ce7 100644 --- a/src/vendor/cigraph/src/games/callaway_traits.c +++ b/src/vendor/cigraph/src/games/callaway_traits.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -68,13 +68,13 @@ * Time complexity: O(|V|*k*log(|V|)), |V| is the number of vertices, * k is \p edges_per_step. */ -igraph_error_t igraph_callaway_traits_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t types, igraph_integer_t edges_per_step, +igraph_error_t igraph_callaway_traits_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t types, igraph_int_t edges_per_step, const igraph_vector_t *type_dist, const igraph_matrix_t *pref_matrix, igraph_bool_t directed, igraph_vector_int_t *node_type_vec) { - igraph_integer_t i, j; + igraph_int_t i, j; igraph_vector_int_t edges; igraph_vector_t cumdist; igraph_real_t maxcum; @@ -163,17 +163,17 @@ igraph_error_t igraph_callaway_traits_game(igraph_t *graph, igraph_integer_t nod for (i = 0; i < nodes; i++) { igraph_real_t uni = RNG_UNIF(0, maxcum); - igraph_integer_t type; + igraph_int_t type; igraph_vector_binsearch(&cumdist, uni, &type); VECTOR(*nodetypes)[i] = type - 1; } for (i = 1; i < nodes; i++) { for (j = 0; j < edges_per_step; j++) { - igraph_integer_t node1 = RNG_INTEGER(0, i); - igraph_integer_t node2 = RNG_INTEGER(0, i); - igraph_integer_t type1 = VECTOR(*nodetypes)[node1]; - igraph_integer_t type2 = VECTOR(*nodetypes)[node2]; + igraph_int_t node1 = RNG_INTEGER(0, i); + igraph_int_t node2 = RNG_INTEGER(0, i); + igraph_int_t type1 = VECTOR(*nodetypes)[node1]; + igraph_int_t type2 = VECTOR(*nodetypes)[node2]; /* printf("unif: %f, %f, types: %li, %li\n", uni1, uni2, type1, type2); */ if (RNG_UNIF01() < MATRIX(*pref_matrix, type1, type2)) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, node1)); diff --git a/src/vendor/cigraph/src/games/chung_lu.c b/src/vendor/cigraph/src/games/chung_lu.c index 6aa5a4c2698..235c7d60c60 100644 --- a/src/vendor/cigraph/src/games/chung_lu.c +++ b/src/vendor/cigraph/src/games/chung_lu.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -196,7 +196,7 @@ igraph_error_t igraph_chung_lu_game(igraph_t *graph, igraph_bool_t loops, igraph_chung_lu_t variant) { - const igraph_integer_t no_of_nodes = igraph_vector_size(out_weights); + const igraph_int_t no_of_nodes = igraph_vector_size(out_weights); const igraph_bool_t directed = in_weights != NULL; igraph_vector_int_t edges, idx; igraph_real_t wsum = igraph_vector_sum(out_weights); @@ -234,12 +234,12 @@ igraph_error_t igraph_chung_lu_game(igraph_t *graph, IGRAPH_CHECK(igraph_vector_sort_ind(in_weights, &idx, IGRAPH_DESCENDING)); - for (igraph_integer_t i=0; i < no_of_nodes; i++) { - igraph_integer_t vi, vj; + for (igraph_int_t i=0; i < no_of_nodes; i++) { + igraph_int_t vi, vj; igraph_real_t wi, wj; igraph_real_t p, q; - igraph_integer_t j = directed ? 0 : i; + igraph_int_t j = directed ? 0 : i; vi = VECTOR(idx)[i]; wi = VECTOR(*out_weights)[vi]; @@ -256,7 +256,7 @@ igraph_error_t igraph_chung_lu_game(igraph_t *graph, /* This formulation not only terminates the loop when necessary, * but also protects against overflow when 'p' is very small * and 'gap' becomes very large, perhaps larger than representable - * in an igraph_integer_t. */ + * in an igraph_int_t. */ if (gap >= no_of_nodes-j) { break; } diff --git a/src/vendor/cigraph/src/games/citations.c b/src/vendor/cigraph/src/games/citations.c index e193f16e957..9ce6a4143be 100644 --- a/src/vendor/cigraph/src/games/citations.c +++ b/src/vendor/cigraph/src/games/citations.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -30,7 +30,7 @@ #include "math/safe_intop.h" typedef struct { - igraph_integer_t no; + igraph_int_t no; igraph_psumtree_t *sumtrees; } igraph_i_citing_cited_type_game_struct_t; @@ -89,17 +89,17 @@ static void igraph_i_citing_cited_type_game_free ( * |E| is the total number of edges, a is the \p agebins parameter. */ igraph_error_t igraph_lastcit_game(igraph_t *graph, - igraph_integer_t nodes, igraph_integer_t edges_per_node, - igraph_integer_t agebins, + igraph_int_t nodes, igraph_int_t edges_per_node, + igraph_int_t agebins, const igraph_vector_t *preference, igraph_bool_t directed) { - igraph_integer_t no_of_nodes = nodes; + igraph_int_t no_of_nodes = nodes; igraph_psumtree_t sumtree; igraph_vector_int_t edges; - igraph_integer_t *lastcit; - igraph_integer_t *index; - igraph_integer_t binwidth; + igraph_int_t *lastcit; + igraph_int_t *index; + igraph_int_t binwidth; if (agebins != igraph_vector_size(preference) - 1) { IGRAPH_ERRORF("The `preference' vector should be of length `agebins' plus one." @@ -141,11 +141,11 @@ igraph_error_t igraph_lastcit_game(igraph_t *graph, binwidth = no_of_nodes / agebins + 1; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - lastcit = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + lastcit = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(lastcit, "Insufficient memory for lastcit game."); IGRAPH_FINALLY(igraph_free, lastcit); - index = IGRAPH_CALLOC(no_of_nodes + 1, igraph_integer_t); + index = IGRAPH_CALLOC(no_of_nodes + 1, igraph_int_t); IGRAPH_CHECK_OOM(index, "Insufficient memory for lastcit game."); IGRAPH_FINALLY(igraph_free, index); @@ -158,11 +158,11 @@ igraph_error_t igraph_lastcit_game(igraph_t *graph, index[0] = 0; index[1] = 0; - for (igraph_integer_t i = 1; i < no_of_nodes; i++) { + for (igraph_int_t i = 1; i < no_of_nodes; i++) { /* Add new edges */ - for (igraph_integer_t j = 0; j < edges_per_node; j++) { - igraph_integer_t to; + for (igraph_int_t j = 0; j < edges_per_node; j++) { + igraph_int_t to; const igraph_real_t sum = igraph_psumtree_sum(&sumtree); if (sum == 0) { /* If none of the so-far added nodes have positive weight, @@ -183,11 +183,11 @@ igraph_error_t igraph_lastcit_game(igraph_t *graph, /* Update the preference of some vertices if they got to another bin. We need to know the citations of some older vertices, this is in the index. */ - for (igraph_integer_t k = 1; i - binwidth * k >= 1; k++) { - const igraph_integer_t shnode = i - binwidth * k; - const igraph_integer_t m = index[shnode], n = index[shnode + 1]; - for (igraph_integer_t j = 2 * m; j < 2 * n; j += 2) { - const igraph_integer_t cnode = VECTOR(edges)[j + 1]; + for (igraph_int_t k = 1; i - binwidth * k >= 1; k++) { + const igraph_int_t shnode = i - binwidth * k; + const igraph_int_t m = index[shnode], n = index[shnode + 1]; + for (igraph_int_t j = 2 * m; j < 2 * n; j += 2) { + const igraph_int_t cnode = VECTOR(edges)[j + 1]; if (lastcit[cnode] == shnode + 1) { IGRAPH_CHECK(igraph_psumtree_update(&sumtree, cnode, VECTOR(*preference)[k])); } @@ -243,17 +243,17 @@ igraph_error_t igraph_lastcit_game(igraph_t *graph, * vertices and edges, respectively. */ -igraph_error_t igraph_cited_type_game(igraph_t *graph, igraph_integer_t nodes, +igraph_error_t igraph_cited_type_game(igraph_t *graph, igraph_int_t nodes, const igraph_vector_int_t *types, const igraph_vector_t *pref, - igraph_integer_t edges_per_step, + igraph_int_t edges_per_step, igraph_bool_t directed) { igraph_vector_int_t edges; igraph_vector_t cumsum; igraph_real_t sum, nnval; - igraph_integer_t i, j, type; - igraph_integer_t pref_len = igraph_vector_size(pref); + igraph_int_t i, j, type; + igraph_int_t pref_len = igraph_vector_size(pref); if (igraph_vector_int_size(types) != nodes) { IGRAPH_ERRORF("Length of types vector (%" IGRAPH_PRId ") must match number of nodes (%" IGRAPH_PRId ").", @@ -296,7 +296,7 @@ igraph_error_t igraph_cited_type_game(igraph_t *graph, igraph_integer_t nodes, for (i = 1; i < nodes; i++) { for (j = 0; j < edges_per_step; j++) { - igraph_integer_t to; + igraph_int_t to; if (sum > 0) { igraph_vector_binsearch(&cumsum, RNG_UNIF(0, sum), &to); } else { @@ -338,7 +338,7 @@ static void igraph_i_citing_cited_type_game_free(igraph_i_citing_cited_type_game if (!s->sumtrees) { return; } - for (igraph_integer_t i = 0; i < s->no; i++) { + for (igraph_int_t i = 0; i < s->no; i++) { igraph_psumtree_destroy(&s->sumtrees[i]); } IGRAPH_FREE(s->sumtrees); @@ -384,18 +384,18 @@ static void igraph_i_citing_cited_type_game_free(igraph_i_citing_cited_type_game * vertices and edges, respectively. */ -igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_integer_t nodes, +igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_int_t nodes, const igraph_vector_int_t *types, const igraph_matrix_t *pref, - igraph_integer_t edges_per_step, + igraph_int_t edges_per_step, igraph_bool_t directed) { igraph_vector_int_t edges; igraph_i_citing_cited_type_game_struct_t str = { 0, NULL }; igraph_psumtree_t *sumtrees; igraph_vector_t sums; - igraph_integer_t no_of_types; - igraph_integer_t i, j, no_of_edges, no_of_edge_endpoints; + igraph_int_t no_of_types; + igraph_int_t i, j, no_of_edges, no_of_edge_endpoints; if (igraph_vector_int_size(types) != nodes) { IGRAPH_ERRORF("Length of types vector (%" IGRAPH_PRId ") not equal to number" @@ -451,7 +451,7 @@ igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_integer_t n /* First node */ for (i = 0; i < no_of_types; i++) { - igraph_integer_t type = VECTOR(*types)[0]; + igraph_int_t type = VECTOR(*types)[0]; if ( MATRIX(*pref, i, type) < 0) { IGRAPH_ERRORF("Preference matrix contains negative entry: %g.", IGRAPH_EINVAL, MATRIX(*pref, i, type)); } @@ -460,10 +460,10 @@ igraph_error_t igraph_citing_cited_type_game(igraph_t *graph, igraph_integer_t n } for (i = 1; i < nodes; i++) { - igraph_integer_t type = VECTOR(*types)[i]; + igraph_int_t type = VECTOR(*types)[i]; igraph_real_t sum = VECTOR(sums)[type]; for (j = 0; j < edges_per_step; j++) { - igraph_integer_t to; + igraph_int_t to; if (sum == 0) { /* If none of the so-far added nodes have positive weight, * we choose one uniformly to connect to. */ diff --git a/src/vendor/cigraph/src/games/correlated.c b/src/vendor/cigraph/src/games/correlated.c index b66b4c28901..5965406e008 100644 --- a/src/vendor/cigraph/src/games/correlated.c +++ b/src/vendor/cigraph/src/games/correlated.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -24,6 +24,7 @@ #include "igraph_conversion.h" #include "igraph_constructors.h" #include "igraph_interface.h" +#include "igraph_isomorphism.h" #include "igraph_qsort.h" #include "igraph_random.h" #include "igraph_structural.h" @@ -42,9 +43,9 @@ /* TODO: Slight speedup may be possible if repeated vertex count queries are avoided. */ static int code_cmp(void *graph, const void *va, const void *vb) { - const igraph_integer_t *a = (const igraph_integer_t *) va; - const igraph_integer_t *b = (const igraph_integer_t *) vb; - const igraph_integer_t no_of_nodes = igraph_vcount((igraph_t *) graph); + const igraph_int_t *a = (const igraph_int_t *) va; + const igraph_int_t *b = (const igraph_int_t *) vb; + const igraph_int_t no_of_nodes = igraph_vcount((igraph_t *) graph); const igraph_bool_t directed = igraph_is_directed((igraph_t *) graph); const igraph_real_t codea = CODE(a[0], a[1]); const igraph_real_t codeb = CODE(b[0], b[1]); @@ -59,7 +60,7 @@ static int code_cmp(void *graph, const void *va, const void *vb) { /* Sort an edge vector by edge codes. */ static void sort_edges(igraph_vector_int_t *edges, const igraph_t *graph) { - igraph_qsort_r(VECTOR(*edges), igraph_vector_int_size(edges) / 2, 2*sizeof(igraph_integer_t), (void *) graph, code_cmp); + igraph_qsort_r(VECTOR(*edges), igraph_vector_int_size(edges) / 2, 2*sizeof(igraph_int_t), (void *) graph, code_cmp); } /** @@ -69,41 +70,43 @@ static void sort_edges(igraph_vector_int_t *edges, const igraph_t *graph) { * Sample a new graph by perturbing the adjacency matrix of a * given simple graph and shuffling its vertices. * - * \param old_graph The original graph, it must be simple. - * \param new_graph The new graph will be stored here. + * \param new_graph The new graph to initialize based on an existing graph. + * \param old_graph The original graph, which must be a simple graph. * \param corr A value in the unit interval [0,1], the target Pearson * correlation between the adjacency matrices of the original and the * generated graph (the adjacency matrix being used as a vector). * \param p The probability of an edge between two vertices. It must in the * open (0,1) interval. Typically, the density of \p old_graph. * \param permutation A permutation to apply to the vertices of the - * generated graph. It can also be a null pointer, in which case - * the vertices will not be permuted. + * generated graph. The i-th element of the vector specifies the index + * of the vertex in the \em original graph that will become vertex i in the + * new graph. It can also be a null pointer, in which case the vertices + * will not be permuted. * \return Error code * * \sa \ref igraph_correlated_pair_game() for generating a pair * of correlated random graphs in one go. */ -igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_graph, +igraph_error_t igraph_correlated_game(igraph_t *new_graph, const igraph_t *old_graph, igraph_real_t corr, igraph_real_t p, const igraph_vector_int_t *permutation) { - igraph_integer_t no_of_nodes = igraph_vcount(old_graph); - igraph_integer_t no_of_edges = igraph_ecount(old_graph); - igraph_bool_t directed = igraph_is_directed(old_graph); - igraph_real_t no_of_all = directed ? ((igraph_real_t) no_of_nodes) * (no_of_nodes - 1) : + const igraph_int_t no_of_nodes = igraph_vcount(old_graph); + const igraph_int_t no_of_edges = igraph_ecount(old_graph); + const igraph_bool_t directed = igraph_is_directed(old_graph); + const igraph_real_t no_of_all = directed ? ((igraph_real_t) no_of_nodes) * (no_of_nodes - 1) : ((igraph_real_t) no_of_nodes) * (no_of_nodes - 1) / 2; - igraph_real_t no_of_missing = no_of_all - no_of_edges; - igraph_real_t q = p + corr * (1 - p); - igraph_real_t p_del = 1 - q; - igraph_real_t p_add = ((1 - q) * (p / (1 - p))); + const igraph_real_t no_of_missing = no_of_all - no_of_edges; + const igraph_real_t q = p + corr * (1 - p); + const igraph_real_t p_del = 1 - q; + const igraph_real_t p_add = ((1 - q) * (p / (1 - p))); igraph_vector_t add, delete; igraph_vector_int_t edges, newedges; + igraph_vector_int_t inverted_permutation; igraph_real_t last; - igraph_integer_t p_e = 0, p_a = 0, p_d = 0; - igraph_integer_t no_add, no_del; + igraph_int_t p_e = 0, p_a = 0, p_d = 0; + igraph_int_t no_add, no_del; igraph_real_t next_e, next_a, next_d; - igraph_integer_t i, newec; igraph_bool_t simple; if (corr < 0 || corr > 1) { @@ -129,18 +132,26 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g /* Special cases */ if (corr == 0) { - return igraph_erdos_renyi_game_gnp(new_graph, no_of_nodes, p, directed, IGRAPH_NO_LOOPS); + return igraph_erdos_renyi_game_gnp(new_graph, no_of_nodes, p, directed, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED); } if (corr == 1) { /* We don't copy, because we don't need the attributes.... */ IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); - IGRAPH_CHECK(igraph_get_edgelist(old_graph, &edges, /* bycol= */ 0)); + IGRAPH_CHECK(igraph_get_edgelist(old_graph, &edges, /* bycol= */ false)); if (permutation) { - newec = igraph_vector_int_size(&edges); - for (i = 0; i < newec; i++) { - igraph_integer_t tmp = VECTOR(edges)[i]; - VECTOR(edges)[i] = VECTOR(*permutation)[tmp]; + const igraph_int_t newec = igraph_vector_int_size(&edges); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&inverted_permutation, no_of_nodes); + /* Also checks that 'permutation' is valid: */ + IGRAPH_CHECK(igraph_invert_permutation(permutation, &inverted_permutation)); + + for (igraph_int_t i = 0; i < newec; i++) { + igraph_int_t tmp = VECTOR(edges)[i]; + VECTOR(edges)[i] = VECTOR(inverted_permutation)[tmp]; } + + igraph_vector_int_destroy(&inverted_permutation); + IGRAPH_FINALLY_CLEAN(1); } IGRAPH_CHECK(igraph_create(new_graph, &edges, no_of_nodes, directed)); igraph_vector_int_destroy(&edges); @@ -193,10 +204,10 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g /* First we (re)code the edges to delete */ - for (i = 0; i < no_del; i++) { - igraph_integer_t td = VECTOR(delete)[i]; - igraph_integer_t from = VECTOR(edges)[2 * td]; - igraph_integer_t to = VECTOR(edges)[2 * td + 1]; + for (igraph_int_t i = 0; i < no_del; i++) { + igraph_int_t td = VECTOR(delete)[i]; + igraph_int_t from = VECTOR(edges)[2 * td]; + igraph_int_t to = VECTOR(edges)[2 * td + 1]; VECTOR(delete)[i] = CODE(from, to); } @@ -235,16 +246,16 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g } else { /* add an edge */ - igraph_integer_t to, from; + igraph_int_t to, from; IGRAPH_ASSERT(isfinite(next_a)); if (directed) { - to = floor(next_a / no_of_nodes); + to = trunc(next_a / no_of_nodes); from = next_a - ((igraph_real_t)to) * no_of_nodes; if (from == to) { to = no_of_nodes - 1; } } else { - to = floor((sqrt(8 * next_a + 1) + 1) / 2); + to = trunc((sqrt(8 * next_a + 1) + 1) / 2); from = next_a - (((igraph_real_t)to) * (to - 1)) / 2; } IGRAPH_CHECK(igraph_vector_int_push_back(&newedges, from)); @@ -260,11 +271,19 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g IGRAPH_FINALLY_CLEAN(3); if (permutation) { - newec = igraph_vector_int_size(&newedges); - for (i = 0; i < newec; i++) { - igraph_integer_t tmp = VECTOR(newedges)[i]; - VECTOR(newedges)[i] = VECTOR(*permutation)[tmp]; + igraph_int_t newec = igraph_vector_int_size(&newedges); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&inverted_permutation, no_of_nodes); + /* Also checks that 'permutation' is valid: */ + IGRAPH_CHECK(igraph_invert_permutation(permutation, &inverted_permutation)); + + for (igraph_int_t i = 0; i < newec; i++) { + igraph_int_t tmp = VECTOR(newedges)[i]; + VECTOR(newedges)[i] = VECTOR(inverted_permutation)[tmp]; } + + igraph_vector_int_destroy(&inverted_permutation); + IGRAPH_FINALLY_CLEAN(1); } IGRAPH_CHECK(igraph_create(new_graph, &newedges, no_of_nodes, directed)); @@ -299,19 +318,21 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g * vertices, it must in the open (0,1) interval. * \param directed Whether to generate directed graphs. * \param permutation A permutation to apply to the vertices of the - * second graph. It can also be a null pointer, in which case - * the vertices will not be permuted. + * generated graph. The i-th element of the vector specifies the index + * of the vertex in the \em first graph that will become vertex i in the + * second graph. It can also be a null pointer, in which case the vertices + * will not be permuted. * \return Error code * * \sa \ref igraph_correlated_game() for generating a correlated pair * to a given graph. */ igraph_error_t igraph_correlated_pair_game(igraph_t *graph1, igraph_t *graph2, - igraph_integer_t n, igraph_real_t corr, igraph_real_t p, + igraph_int_t n, igraph_real_t corr, igraph_real_t p, igraph_bool_t directed, const igraph_vector_int_t *permutation) { - IGRAPH_CHECK(igraph_erdos_renyi_game_gnp(graph1, n, p, directed, IGRAPH_NO_LOOPS)); - IGRAPH_CHECK(igraph_correlated_game(graph1, graph2, corr, p, permutation)); + IGRAPH_CHECK(igraph_erdos_renyi_game_gnp(graph1, n, p, directed, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED)); + IGRAPH_CHECK(igraph_correlated_game(graph2, graph1, corr, p, permutation)); return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/games/degree_sequence.c b/src/vendor/cigraph/src/games/degree_sequence.c index b5646bd429c..5addbff2222 100644 --- a/src/vendor/cigraph/src/games/degree_sequence.c +++ b/src/vendor/cigraph/src/games/degree_sequence.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -40,11 +40,11 @@ static igraph_error_t configuration( const igraph_vector_int_t *in_seq) { const igraph_bool_t directed = (in_seq != NULL); - igraph_integer_t outsum = 0, insum = 0; + igraph_int_t outsum = 0, insum = 0; igraph_bool_t graphical; - igraph_integer_t no_of_nodes, no_of_edges; - igraph_integer_t *bag1, *bag2; - igraph_integer_t bagp1 = 0, bagp2 = 0; + igraph_int_t no_of_nodes, no_of_edges; + igraph_int_t *bag1, *bag2; + igraph_int_t bagp1 = 0, bagp2 = 0; igraph_vector_int_t edges; IGRAPH_CHECK(igraph_is_graphical(out_seq, in_seq, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, &graphical)); @@ -61,21 +61,21 @@ static igraph_error_t configuration( no_of_nodes = igraph_vector_int_size(out_seq); no_of_edges = directed ? outsum : outsum / 2; - bag1 = IGRAPH_CALLOC(outsum, igraph_integer_t); + bag1 = IGRAPH_CALLOC(outsum, igraph_int_t); IGRAPH_CHECK_OOM(bag1, "Insufficient memory for sampling from configuration model."); IGRAPH_FINALLY(igraph_free, bag1); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - for (igraph_integer_t j = 0; j < VECTOR(*out_seq)[i]; j++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t j = 0; j < VECTOR(*out_seq)[i]; j++) { bag1[bagp1++] = i; } } if (directed) { - bag2 = IGRAPH_CALLOC(insum, igraph_integer_t); + bag2 = IGRAPH_CALLOC(insum, igraph_int_t); IGRAPH_CHECK_OOM(bag2, "Insufficient memory for sampling from configuration model."); IGRAPH_FINALLY(igraph_free, bag2); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - for (igraph_integer_t j = 0; j < VECTOR(*in_seq)[i]; j++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t j = 0; j < VECTOR(*in_seq)[i]; j++) { bag2[bagp2++] = i; } } @@ -85,9 +85,9 @@ static igraph_error_t configuration( IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges * 2)); if (directed) { - for (igraph_integer_t i = 0; i < no_of_edges; i++) { - igraph_integer_t from = RNG_INTEGER(0, bagp1 - 1); - igraph_integer_t to = RNG_INTEGER(0, bagp2 - 1); + for (igraph_int_t i = 0; i < no_of_edges; i++) { + igraph_int_t from = RNG_INTEGER(0, bagp1 - 1); + igraph_int_t to = RNG_INTEGER(0, bagp2 - 1); igraph_vector_int_push_back(&edges, bag1[from]); /* safe, already reserved */ igraph_vector_int_push_back(&edges, bag2[to]); /* ditto */ bag1[from] = bag1[bagp1 - 1]; @@ -95,9 +95,9 @@ static igraph_error_t configuration( bagp1--; bagp2--; } } else { - for (igraph_integer_t i = 0; i < no_of_edges; i++) { - igraph_integer_t from = RNG_INTEGER(0, bagp1 - 1); - igraph_integer_t to; + for (igraph_int_t i = 0; i < no_of_edges; i++) { + igraph_int_t from = RNG_INTEGER(0, bagp1 - 1); + igraph_int_t to; igraph_vector_int_push_back(&edges, bag1[from]); /* safe, already reserved */ bag1[from] = bag1[bagp1 - 1]; bagp1--; @@ -132,9 +132,9 @@ static igraph_error_t fast_heur_undirected( igraph_set_t incomplete_vertices; igraph_adjlist_t al; igraph_bool_t finished, failed; - igraph_integer_t from, to, dummy; - igraph_integer_t i, j, k; - igraph_integer_t no_of_nodes, outsum = 0; + igraph_int_t from, to, dummy; + igraph_int_t i, j, k; + igraph_int_t no_of_nodes, outsum = 0; igraph_bool_t graphical; int iter = 0; @@ -177,7 +177,7 @@ static igraph_error_t fast_heur_undirected( igraph_vector_int_clear(&stubs); for (i = 0; i < no_of_nodes; i++) { for (j = 0; j < VECTOR(residual_degrees)[i]; j++) { - igraph_vector_int_push_back(&stubs, i); + igraph_vector_int_push_back(&stubs, i); /* reserved */ } } @@ -272,9 +272,9 @@ static igraph_error_t fast_heur_directed( igraph_vector_int_t *neis; igraph_vector_int_t residual_in_degrees, residual_out_degrees; igraph_set_t incomplete_in_vertices, incomplete_out_vertices; - igraph_integer_t from, to; - igraph_integer_t i, j, k; - igraph_integer_t no_of_nodes, outsum; + igraph_int_t from, to; + igraph_int_t i, j, k; + igraph_int_t no_of_nodes, outsum; int iter = 0; IGRAPH_CHECK(igraph_is_graphical(out_seq, in_seq, IGRAPH_SIMPLE_SW, °_seq_ok)); @@ -323,10 +323,10 @@ static igraph_error_t fast_heur_directed( igraph_vector_int_clear(&in_stubs); for (i = 0; i < no_of_nodes; i++) { for (j = 0; j < VECTOR(residual_out_degrees)[i]; j++) { - igraph_vector_int_push_back(&out_stubs, i); + igraph_vector_int_push_back(&out_stubs, i); /* reserved */ } for (j = 0; j < VECTOR(residual_in_degrees)[i]; j++) { - igraph_vector_int_push_back(&in_stubs, i); + igraph_vector_int_push_back(&in_stubs, i); /* reserved */ } } @@ -404,7 +404,7 @@ static igraph_error_t fast_heur_directed( /* swap two elements of a vector_int */ #define SWAP_INT_ELEM(vec, i, j) \ { \ - igraph_integer_t temp; \ + igraph_int_t temp; \ temp = VECTOR(vec)[i]; \ VECTOR(vec)[i] = VECTOR(vec)[j]; \ VECTOR(vec)[j] = temp; \ @@ -414,9 +414,9 @@ static igraph_error_t fast_heur_directed( static igraph_error_t configuration_simple_undirected_set( const igraph_vector_int_t *degseq, igraph_vector_int_t *stubs, - igraph_integer_t vcount, igraph_integer_t stub_count) { + igraph_int_t vcount, igraph_int_t stub_count) { - const igraph_integer_t ecount = stub_count / 2; + const igraph_int_t ecount = stub_count / 2; igraph_vector_ptr_t adjlist; int iter = 0; @@ -424,7 +424,7 @@ static igraph_error_t configuration_simple_undirected_set( IGRAPH_CHECK(igraph_vector_ptr_init(&adjlist, vcount)); IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&adjlist, igraph_set_destroy); IGRAPH_FINALLY(igraph_vector_ptr_destroy_all, &adjlist); - for (igraph_integer_t i = 0; i < vcount; ++i) { + for (igraph_int_t i = 0; i < vcount; ++i) { igraph_set_t *set = IGRAPH_CALLOC(1, igraph_set_t); IGRAPH_CHECK_OOM(set, "Insufficient memory for configuration model (simple graphs)."); IGRAPH_CHECK(igraph_set_init(set, 0)); @@ -436,8 +436,8 @@ static igraph_error_t configuration_simple_undirected_set( igraph_bool_t success = true; /* Shuffle stubs vector with Fisher-Yates and check for self-loops and multi-edges as we go. */ - for (igraph_integer_t i = 0; i < ecount; ++i) { - igraph_integer_t k, from, to; + for (igraph_int_t i = 0; i < ecount; ++i) { + igraph_int_t k, from, to; k = RNG_INTEGER(2*i, stub_count-1); SWAP_INT_ELEM(*stubs, 2*i, k); @@ -470,7 +470,7 @@ static igraph_error_t configuration_simple_undirected_set( } /* Clear adjacency list. */ - for (igraph_integer_t j = 0; j < vcount; ++j) { + for (igraph_int_t j = 0; j < vcount; ++j) { igraph_set_clear((igraph_set_t *) VECTOR(adjlist)[j]); } @@ -486,15 +486,15 @@ static igraph_error_t configuration_simple_undirected_set( /* Uses a bitset to check for multi-edges. Efficient for smaller graphs. */ static igraph_error_t configuration_simple_undirected_bitset( igraph_vector_int_t *stubs, - igraph_integer_t vcount, igraph_integer_t stub_count) { + igraph_int_t vcount, igraph_int_t stub_count) { - const igraph_integer_t ecount = stub_count / 2; + const igraph_int_t ecount = stub_count / 2; igraph_bitset_list_t adjlist; int iter = 0; /* Build an adjacency list in terms of bitsets; used to check for multi-edges. */ IGRAPH_BITSET_LIST_INIT_FINALLY(&adjlist, vcount); - for (igraph_integer_t i = 0; i < vcount; ++i) { + for (igraph_int_t i = 0; i < vcount; ++i) { IGRAPH_CHECK(igraph_bitset_resize(igraph_bitset_list_get_ptr(&adjlist, i), vcount)); } @@ -502,8 +502,8 @@ static igraph_error_t configuration_simple_undirected_bitset( igraph_bool_t success = true; /* Shuffle stubs vector with Fisher-Yates and check for self-loops and multi-edges as we go. */ - for (igraph_integer_t i = 0; i < ecount; ++i) { - igraph_integer_t k, from, to; + for (igraph_int_t i = 0; i < ecount; ++i) { + igraph_int_t k, from, to; k = RNG_INTEGER(2*i, stub_count-1); SWAP_INT_ELEM(*stubs, 2*i, k); @@ -536,7 +536,7 @@ static igraph_error_t configuration_simple_undirected_bitset( } /* Clear adjacency list. */ - for (igraph_integer_t j = 0; j < vcount; ++j) { + for (igraph_int_t j = 0; j < vcount; ++j) { igraph_bitset_null(igraph_bitset_list_get_ptr(&adjlist, j)); } @@ -555,7 +555,7 @@ static igraph_error_t configuration_simple_undirected( igraph_vector_int_t stubs; igraph_bool_t graphical; - igraph_integer_t vcount, stub_count; + igraph_int_t vcount, stub_count; IGRAPH_CHECK(igraph_is_graphical(degseq, NULL, IGRAPH_SIMPLE_SW, &graphical)); if (!graphical) { @@ -569,10 +569,10 @@ static igraph_error_t configuration_simple_undirected( /* Fill stubs vector. */ { - igraph_integer_t k = 0; - for (igraph_integer_t i = 0; i < vcount; ++i) { - igraph_integer_t deg = VECTOR(*degseq)[i]; - for (igraph_integer_t j = 0; j < deg; ++j) { + igraph_int_t k = 0; + for (igraph_int_t i = 0; i < vcount; ++i) { + igraph_int_t deg = VECTOR(*degseq)[i]; + for (igraph_int_t j = 0; j < deg; ++j) { VECTOR(stubs)[k++] = i; } } @@ -603,7 +603,7 @@ static igraph_error_t configuration_simple_directed( igraph_vector_int_t edges; igraph_vector_int_t vertex_done; igraph_bool_t graphical; - igraph_integer_t vcount, ecount; + igraph_int_t vcount, ecount; int iter = 0; IGRAPH_CHECK(igraph_is_graphical(out_deg, in_deg, IGRAPH_SIMPLE_SW, &graphical)); @@ -629,31 +629,31 @@ static igraph_error_t configuration_simple_directed( /* Fill in- and out-stubs vectors. */ { - igraph_integer_t k = 0, l = 0; - for (igraph_integer_t i = 0; i < vcount; ++i) { - igraph_integer_t dout, din; + igraph_int_t k = 0, l = 0; + for (igraph_int_t i = 0; i < vcount; ++i) { + igraph_int_t dout, din; dout = VECTOR(*out_deg)[i]; - for (igraph_integer_t j = 0; j < dout; ++j) { + for (igraph_int_t j = 0; j < dout; ++j) { VECTOR(out_stubs)[k++] = i; } din = VECTOR(*in_deg)[i]; - for (igraph_integer_t j = 0; j < din; ++j) { + for (igraph_int_t j = 0; j < din; ++j) { VECTOR(in_stubs)[l++] = i; } } } - igraph_integer_t vertex_done_mark = 1; + igraph_int_t vertex_done_mark = 1; for (;;) { igraph_bool_t success = true; - igraph_integer_t previous_to = -1; + igraph_int_t previous_to = -1; /* Shuffle out-stubs vector with Fisher-Yates and check for self-loops and multi-edges as we go. */ - for (igraph_integer_t i = 0; i < ecount; ++i) { - igraph_integer_t k, from, to; + for (igraph_int_t i = 0; i < ecount; ++i) { + igraph_int_t k, from, to; k = RNG_INTEGER(i, ecount-1); SWAP_INT_ELEM(out_stubs, i, k); @@ -689,7 +689,7 @@ static igraph_error_t configuration_simple_directed( IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); } - for (igraph_integer_t i=0; i < ecount; i++) { + for (igraph_int_t i=0; i < ecount; i++) { VECTOR(edges)[2*i] = VECTOR(out_stubs)[i]; VECTOR(edges)[2*i+1] = VECTOR(in_stubs)[i]; } @@ -716,7 +716,7 @@ igraph_error_t edge_switching( IGRAPH_CHECK(igraph_realize_degree_sequence(graph, out_seq, in_seq, IGRAPH_SIMPLE_SW, IGRAPH_REALIZE_DEGSEQ_INDEX)); IGRAPH_FINALLY(igraph_destroy, graph); - IGRAPH_CHECK(igraph_rewire(graph, 10 * igraph_ecount(graph), IGRAPH_SIMPLE_SW)); + IGRAPH_CHECK(igraph_rewire(graph, 10 * igraph_ecount(graph), IGRAPH_SIMPLE_SW, NULL)); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h b/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h index 4c6ee6dae78..9daa8f70a99 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/degree_sequence_vl.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_definitions.h b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_definitions.h index c96e24b35bc..faf551ca64c 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_definitions.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_definitions.h @@ -82,8 +82,8 @@ double my_random01(); // (0,1] //Edge type typedef struct { - igraph_integer_t from; - igraph_integer_t to; + igraph_int_t from; + igraph_int_t to; } edge; // Tag Int @@ -105,15 +105,15 @@ inline double logp(double x) { //Fast search or replace -inline igraph_integer_t* fast_rpl(igraph_integer_t *m, igraph_integer_t a, igraph_integer_t b) { +inline igraph_int_t* fast_rpl(igraph_int_t *m, igraph_int_t a, igraph_int_t b) { while (*m != a) { m++; } *m = b; return m; } -inline igraph_integer_t* fast_search(igraph_integer_t *m, igraph_integer_t size, igraph_integer_t a) { - igraph_integer_t *p = m + size; +inline igraph_int_t* fast_search(igraph_int_t *m, igraph_int_t size, igraph_int_t a) { + igraph_int_t *p = m + size; while (m != p--) { if (*p == a) { return p; diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.cpp b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.cpp index 2db0a080abd..347083dca1e 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.cpp +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.cpp @@ -33,11 +33,11 @@ using namespace std; namespace gengraph { -// shuffle an igraph_integer_t[] randomly -void random_permute(igraph_integer_t *a, igraph_integer_t n); +// shuffle an igraph_int_t[] randomly +void random_permute(igraph_int_t *a, igraph_int_t n); // sort an array of positive integers in time & place O(n + max) -void cumul_sort(igraph_integer_t *q, igraph_integer_t n); +void cumul_sort(igraph_int_t *q, igraph_int_t n); degree_sequence::~degree_sequence() { @@ -46,13 +46,13 @@ degree_sequence::~degree_sequence() { void degree_sequence::compute_total() { total = 0; - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { total += deg[i]; } } degree_sequence:: -degree_sequence(igraph_integer_t n0, igraph_integer_t *degs) { +degree_sequence(igraph_int_t n0, igraph_int_t *degs) { deg = degs; n = n0; compute_total(); @@ -71,11 +71,11 @@ degree_sequence(const igraph_vector_int_t *out_seq) { bool degree_sequence::havelhakimi() { - igraph_integer_t i; - igraph_integer_t dm = dmax() + 1; + igraph_int_t i; + igraph_int_t dm = dmax() + 1; // Sort vertices using basket-sort, in descending degrees - igraph_integer_t *nb = new igraph_integer_t[dm]; - igraph_integer_t *sorted = new igraph_integer_t[n]; + igraph_int_t *nb = new igraph_int_t[dm]; + igraph_int_t *sorted = new igraph_int_t[n]; // init basket for (i = 0; i < dm; i++) { nb[i] = 0; @@ -85,9 +85,9 @@ bool degree_sequence::havelhakimi() { nb[deg[i]]++; } // cumul - igraph_integer_t c = 0; + igraph_int_t c = 0; for (i = dm - 1; i >= 0; i--) { - igraph_integer_t t = nb[i]; + igraph_int_t t = nb[i]; nb[i] = c; c += t; } @@ -97,8 +97,8 @@ bool degree_sequence::havelhakimi() { } // Binding process starts - igraph_integer_t first = 0; // vertex with biggest residual degree - igraph_integer_t d = dm - 1; // maximum residual degree available + igraph_int_t first = 0; // vertex with biggest residual degree + igraph_int_t d = dm - 1; // maximum residual degree available for (c = total / 2; c > 0; ) { // We design by 'v' the vertex of highest degree (indexed by first) @@ -107,14 +107,14 @@ bool degree_sequence::havelhakimi() { d--; } // store it in dv - igraph_integer_t dv = d; + igraph_int_t dv = d; // bind it ! c -= dv; - igraph_integer_t dc = d; // residual degree of vertices we bind to - igraph_integer_t fc = ++first; // position of the first vertex with degree dc + igraph_int_t dc = d; // residual degree of vertices we bind to + igraph_int_t fc = ++first; // position of the first vertex with degree dc while (dv > 0 && dc > 0) { - igraph_integer_t lc = nb[dc]; + igraph_int_t lc = nb[dc]; if (lc != fc) { while (dv > 0 && lc > fc) { // binds v with sorted[--lc] diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.h b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.h index ef286bf0f8a..3d9eb5c92c7 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_degree_sequence.h @@ -29,37 +29,37 @@ namespace gengraph { class degree_sequence { private: - igraph_integer_t n; - igraph_integer_t *deg; - igraph_integer_t total; + igraph_int_t n; + igraph_int_t *deg; + igraph_int_t total; public : // #vertices - inline igraph_integer_t size() { + inline igraph_int_t size() { return n; }; - inline igraph_integer_t sum() { + inline igraph_int_t sum() { return total; }; - inline igraph_integer_t operator[](igraph_integer_t i) { + inline igraph_int_t operator[](igraph_int_t i) { return deg[i]; }; - inline igraph_integer_t *seq() { + inline igraph_int_t *seq() { return deg; }; - inline void assign(igraph_integer_t n0, igraph_integer_t* d0) { + inline void assign(igraph_int_t n0, igraph_int_t* d0) { n = n0; deg = d0; }; - inline igraph_integer_t dmax() { - igraph_integer_t dm = deg[0]; - for (igraph_integer_t i = 1; i < n; i++) if (deg[i] > dm) { + inline igraph_int_t dmax() { + igraph_int_t dm = deg[0]; + for (igraph_int_t i = 1; i < n; i++) if (deg[i] > dm) { dm = deg[i]; } return dm; } - degree_sequence(igraph_integer_t n, igraph_integer_t *degs); + degree_sequence(igraph_int_t n, igraph_int_t *degs); // igraph constructor degree_sequence(const igraph_vector_int_t *out_seq); diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp index 586d944fc4c..9d534fafbd2 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp @@ -38,8 +38,8 @@ namespace gengraph { //_________________________________________________________________________ void graph_molloy_hash::compute_neigh() { - igraph_integer_t *p = links; - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t *p = links; + for (igraph_int_t i = 0; i < n; i++) { neigh[i] = p; p += HASH_SIZE(deg[i]); } @@ -48,14 +48,14 @@ void graph_molloy_hash::compute_neigh() { //_________________________________________________________________________ void graph_molloy_hash::compute_size() { size = 0; - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { size += HASH_SIZE(deg[i]); } } //_________________________________________________________________________ void graph_molloy_hash::init() { - for (igraph_integer_t i = 0; i < size; i++) { + for (igraph_int_t i = 0; i < size; i++) { links[i] = HASH_NONE; } } @@ -66,29 +66,29 @@ graph_molloy_hash::graph_molloy_hash(degree_sequence °s) { } //_________________________________________________________________________ -igraph_integer_t graph_molloy_hash::alloc(degree_sequence °s) { +igraph_int_t graph_molloy_hash::alloc(degree_sequence °s) { n = degs.size(); a = degs.sum(); assert(a % 2 == 0); deg = degs.seq(); compute_size(); - deg = new igraph_integer_t[n + size]; + deg = new igraph_int_t[n + size]; if (deg == NULL) { return 0; } - igraph_integer_t i; + igraph_int_t i; for (i = 0; i < n; i++) { deg[i] = degs[i]; } links = deg + n; init(); - neigh = new igraph_integer_t*[n]; + neigh = new igraph_int_t*[n]; if (neigh == NULL) { return 0; } compute_neigh(); - return sizeof(igraph_integer_t *)*n + sizeof(igraph_integer_t) * (n + size); + return sizeof(igraph_int_t *)*n + sizeof(igraph_int_t) * (n + size); } //_________________________________________________________________________ @@ -104,7 +104,7 @@ graph_molloy_hash::~graph_molloy_hash() { } //_________________________________________________________________________ -graph_molloy_hash::graph_molloy_hash(igraph_integer_t *svg) { +graph_molloy_hash::graph_molloy_hash(igraph_int_t *svg) { // Read n n = *(svg++); // Read a @@ -119,15 +119,15 @@ graph_molloy_hash::graph_molloy_hash(igraph_integer_t *svg) { } //_________________________________________________________________________ -igraph_integer_t *graph_molloy_hash::hard_copy() { - igraph_integer_t *hc = new igraph_integer_t[2 + n + a / 2]; // to store n,a,deg[] and links[] +igraph_int_t *graph_molloy_hash::hard_copy() { + igraph_int_t *hc = new igraph_int_t[2 + n + a / 2]; // to store n,a,deg[] and links[] hc[0] = n; hc[1] = a; - memcpy(hc + 2, deg, sizeof(igraph_integer_t)*n); - igraph_integer_t *p = hc + 2 + n; - igraph_integer_t *l = links; - for (igraph_integer_t i = 0; i < n; i++) for (igraph_integer_t j = HASH_SIZE(deg[i]); j--; l++) { - igraph_integer_t d; + memcpy(hc + 2, deg, sizeof(igraph_int_t)*n); + igraph_int_t *p = hc + 2 + n; + igraph_int_t *l = links; + for (igraph_int_t i = 0; i < n; i++) for (igraph_int_t j = HASH_SIZE(deg[i]); j--; l++) { + igraph_int_t d; if ((d = *l) != HASH_NONE && d >= i) { *(p++) = d; } @@ -139,20 +139,20 @@ igraph_integer_t *graph_molloy_hash::hard_copy() { //_________________________________________________________________________ bool graph_molloy_hash::is_connected() { bool *visited = new bool[n]; - igraph_integer_t *buff = new igraph_integer_t[n]; - igraph_integer_t comp_size = depth_search(visited, buff); + igraph_int_t *buff = new igraph_int_t[n]; + igraph_int_t comp_size = depth_search(visited, buff); delete[] visited; delete[] buff; return (comp_size == n); } //_________________________________________________________________________ -igraph_integer_t* graph_molloy_hash::backup() { - igraph_integer_t *b = new igraph_integer_t[a / 2]; - igraph_integer_t *c = b; - igraph_integer_t *p = links; - for (igraph_integer_t i = 0; i < n; i++) - for (igraph_integer_t d = HASH_SIZE(deg[i]); d--; p++) if (*p != HASH_NONE && *p > i) { +igraph_int_t* graph_molloy_hash::backup() { + igraph_int_t *b = new igraph_int_t[a / 2]; + igraph_int_t *c = b; + igraph_int_t *p = links; + for (igraph_int_t i = 0; i < n; i++) + for (igraph_int_t d = HASH_SIZE(deg[i]); d--; p++) if (*p != HASH_NONE && *p > i) { *(c++) = *p; } assert(c == b + (a / 2)); @@ -160,11 +160,11 @@ igraph_integer_t* graph_molloy_hash::backup() { } //_________________________________________________________________________ -void graph_molloy_hash::restore(igraph_integer_t* b) { +void graph_molloy_hash::restore(igraph_int_t* b) { init(); - igraph_integer_t i; - igraph_integer_t *dd = new igraph_integer_t[n]; - memcpy(dd, deg, sizeof(igraph_integer_t)*n); + igraph_int_t i; + igraph_int_t *dd = new igraph_int_t[n]; + memcpy(dd, deg, sizeof(igraph_int_t)*n); for (i = 0; i < n; i++) { deg[i] = 0; } @@ -178,7 +178,7 @@ void graph_molloy_hash::restore(igraph_integer_t* b) { } //_________________________________________________________________________ -bool graph_molloy_hash::isolated(igraph_integer_t v, igraph_integer_t K, igraph_integer_t *Kbuff, bool *visited) { +bool graph_molloy_hash::isolated(igraph_int_t v, igraph_int_t K, igraph_int_t *Kbuff, bool *visited) { if (K < 2) { return false; } @@ -187,18 +187,18 @@ bool graph_molloy_hash::isolated(igraph_integer_t v, igraph_integer_t K, igraph_ return false; } #endif //OPT_ISOLATED - igraph_integer_t *seen = Kbuff; - igraph_integer_t *known = Kbuff; - igraph_integer_t *max = Kbuff + K; + igraph_int_t *seen = Kbuff; + igraph_int_t *known = Kbuff; + igraph_int_t *max = Kbuff + K; *(known++) = v; visited[v] = true; bool is_isolated = true; while (known != seen) { v = *(seen++); - igraph_integer_t *ww = neigh[v]; - igraph_integer_t w; - for (igraph_integer_t d = HASH_SIZE(deg[v]); d--; ww++) if ((w = *ww) != HASH_NONE && !visited[w]) { + igraph_int_t *ww = neigh[v]; + igraph_int_t w; + for (igraph_int_t d = HASH_SIZE(deg[v]); d--; ww++) if ((w = *ww) != HASH_NONE && !visited[w]) { #ifdef OPT_ISOLATED if (K <= deg[w] + 1 || known == max) { #else //OPT_ISOLATED @@ -220,19 +220,19 @@ bool graph_molloy_hash::isolated(igraph_integer_t v, igraph_integer_t K, igraph_ } //_________________________________________________________________________ -int graph_molloy_hash::random_edge_swap(igraph_integer_t K, igraph_integer_t *Kbuff, bool *visited) { +int graph_molloy_hash::random_edge_swap(igraph_int_t K, igraph_int_t *Kbuff, bool *visited) { // Pick two random vertices a and c - igraph_integer_t f1 = pick_random_vertex(); - igraph_integer_t f2 = pick_random_vertex(); + igraph_int_t f1 = pick_random_vertex(); + igraph_int_t f2 = pick_random_vertex(); // Check that f1 != f2 if (f1 == f2) { return 0; } // Get two random edges (f1,*f1t1) and (f2,*f2t2) - igraph_integer_t *f1t1 = random_neighbour(f1); - igraph_integer_t t1 = *f1t1; - igraph_integer_t *f2t2 = random_neighbour(f2); - igraph_integer_t t2 = *f2t2; + igraph_int_t *f1t1 = random_neighbour(f1); + igraph_int_t t1 = *f1t1; + igraph_int_t *f2t2 = random_neighbour(f2); + igraph_int_t t2 = *f2t2; // Check simplicity if (t1 == t2 || f1 == t2 || f2 == t1) { return 0; @@ -241,10 +241,10 @@ int graph_molloy_hash::random_edge_swap(igraph_integer_t K, igraph_integer_t *Kb return 0; } // Swap - igraph_integer_t *f1t2 = H_rpl(neigh[f1], deg[f1], f1t1, t2); - igraph_integer_t *f2t1 = H_rpl(neigh[f2], deg[f2], f2t2, t1); - igraph_integer_t *t1f2 = H_rpl(neigh[t1], deg[t1], f1, f2); - igraph_integer_t *t2f1 = H_rpl(neigh[t2], deg[t2], f2, f1); + igraph_int_t *f1t2 = H_rpl(neigh[f1], deg[f1], f1t1, t2); + igraph_int_t *f2t1 = H_rpl(neigh[f2], deg[f2], f2t2, t1); + igraph_int_t *t1f2 = H_rpl(neigh[t1], deg[t1], f1, f2); + igraph_int_t *t2f1 = H_rpl(neigh[t2], deg[t2], f2, f1); // isolation test if (K <= 2) { return 1; @@ -261,13 +261,13 @@ int graph_molloy_hash::random_edge_swap(igraph_integer_t K, igraph_integer_t *Kb } //_________________________________________________________________________ -igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times, - igraph_integer_t maxtimes, int type) { +igraph_int_t graph_molloy_hash::shuffle(igraph_int_t times, + igraph_int_t maxtimes, int type) { igraph_progress("Shuffle", 0, 0); // assert(verify()); // counters - igraph_integer_t nb_swaps = 0; - igraph_integer_t all_swaps = 0; + igraph_int_t nb_swaps = 0; + igraph_int_t all_swaps = 0; unsigned long cost = 0; // window double T = double(((a < times) ? a : times) / 10); @@ -279,14 +279,14 @@ igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times, } // isolation test parameter, and buffers double K = 2.4; - igraph_integer_t *Kbuff = new igraph_integer_t[int(K) + 1]; + igraph_int_t *Kbuff = new igraph_int_t[int(K) + 1]; bool *visited = new bool[n]; - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { visited[i] = false; } // Used for monitoring , active only if VERBOSE() - igraph_integer_t failures = 0; - igraph_integer_t successes = 0; + igraph_int_t failures = 0; + igraph_int_t successes = 0; double avg_K = 0; double avg_T = 0; unsigned long next = times; @@ -295,14 +295,14 @@ igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times, // Shuffle: while #edge swap attempts validated by connectivity < times ... while (times > nb_swaps && maxtimes > all_swaps) { // Backup graph - igraph_integer_t *save = backup(); + igraph_int_t *save = backup(); // Prepare counters, K, T - igraph_integer_t swaps = 0; - igraph_integer_t K_int = 0; + igraph_int_t swaps = 0; + igraph_int_t K_int = 0; if (type == FINAL_HEURISTICS || type == BRUTE_FORCE_HEURISTICS) { - K_int = igraph_integer_t(K); + K_int = igraph_int_t(K); } - igraph_integer_t T_int = (igraph_integer_t)(floor(T)); + igraph_int_t T_int = (igraph_int_t)(floor(T)); if (T_int < 1) { T_int = 1; } @@ -312,7 +312,7 @@ igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times, cost += K_int + T_int; } // Perform T edge swap attempts - for (igraph_integer_t i = T_int; i > 0; i--) { + for (igraph_int_t i = T_int; i > 0; i--) { // try one swap swaps += random_edge_swap(K_int, Kbuff, visited); all_swaps++; @@ -377,7 +377,7 @@ igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times, } else { K *= 1.35; delete[] Kbuff; - Kbuff = new igraph_integer_t[igraph_integer_t(K) + 1]; + Kbuff = new igraph_int_t[igraph_int_t(K) + 1]; } break; case OPTIMAL_HEURISTICS: @@ -386,7 +386,7 @@ igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times, } break; case BRUTE_FORCE_HEURISTICS: - K *= 2; delete[] Kbuff; Kbuff = new igraph_integer_t[igraph_integer_t(K) + 1]; + K *= 2; delete[] Kbuff; Kbuff = new igraph_int_t[igraph_int_t(K) + 1]; break; default: throw std::invalid_argument("Error in graph_molloy_hash::shuffle(): Unknown heuristics type."); @@ -407,7 +407,7 @@ igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times, /* void graph_molloy_hash::print(FILE *f) { - igraph_integer_t i, j; + igraph_int_t i, j; for (i = 0; i < n; i++) { fprintf(f, "%" IGRAPH_PRId, i); for (j = 0; j < HASH_SIZE(deg[i]); j++) if (neigh[i][j] != HASH_NONE) { @@ -419,8 +419,8 @@ void graph_molloy_hash::print(FILE *f) { */ igraph_error_t graph_molloy_hash::print(igraph_t *graph) { - igraph_integer_t i, j; - igraph_integer_t ptr = 0; + igraph_int_t i, j; + igraph_int_t ptr = 0; igraph_vector_int_t edges; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, a); // every edge is counted twice.... @@ -444,18 +444,18 @@ igraph_error_t graph_molloy_hash::print(igraph_t *graph) { } //_________________________________________________________________________ -bool graph_molloy_hash::try_shuffle(igraph_integer_t T, igraph_integer_t K, igraph_integer_t *backup_graph) { +bool graph_molloy_hash::try_shuffle(igraph_int_t T, igraph_int_t K, igraph_int_t *backup_graph) { // init all - igraph_integer_t *Kbuff = NULL; + igraph_int_t *Kbuff = NULL; bool *visited = NULL; if (K > 2) { - Kbuff = new igraph_integer_t[K]; + Kbuff = new igraph_int_t[K]; visited = new bool[n]; - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { visited[i] = false; } } - igraph_integer_t *back = backup_graph; + igraph_int_t *back = backup_graph; if (back == NULL) { back = backup(); } @@ -506,7 +506,7 @@ bool bernoulli_param_is_lower(int success, int trials, double param) { //_________________________________________________________________________ #define _MIN_SUCCESS_FOR_BERNOULLI_TRUST 100 -double graph_molloy_hash::average_cost(igraph_integer_t T, igraph_integer_t *backup, double min_cost) { +double graph_molloy_hash::average_cost(igraph_int_t T, igraph_int_t *backup, double min_cost) { if (T < 1) { return 1e+99; } @@ -527,11 +527,11 @@ double graph_molloy_hash::average_cost(igraph_integer_t T, igraph_integer_t *bac } //_________________________________________________________________________ -igraph_integer_t graph_molloy_hash::optimal_window() { - igraph_integer_t Tmax; - igraph_integer_t optimal_T = 1; +igraph_int_t graph_molloy_hash::optimal_window() { + igraph_int_t Tmax; + igraph_int_t optimal_T = 1; double min_cost = 1e+99; - igraph_integer_t *back = backup(); + igraph_int_t *back = backup(); // on cherche une borne sup pour Tmax int been_greater = 0; for (Tmax = 1; Tmax <= 5 * a ; Tmax *= 2) { @@ -551,8 +551,8 @@ igraph_integer_t graph_molloy_hash::optimal_window() { double span = 2.0; int try_again = 4; while (span > 1.05 && optimal_T <= 5 * a) { - igraph_integer_t T_low = igraph_integer_t(double(optimal_T) / span); - igraph_integer_t T_high = igraph_integer_t(double(optimal_T) * span); + igraph_int_t T_low = igraph_int_t(double(optimal_T) / span); + igraph_int_t T_high = igraph_int_t(double(optimal_T) * span); double c_low = average_cost(T_low, back, min_cost); double c_high = average_cost(T_high, back, min_cost); if (c_low < min_cost && c_high < min_cost) { @@ -594,21 +594,21 @@ double graph_molloy_hash::eval_K(int quality) { } //_________________________________________________________________________ -double graph_molloy_hash::effective_K(igraph_integer_t K, int quality) { +double graph_molloy_hash::effective_K(igraph_int_t K, int quality) { if (K < 3) { return 0.0; } long sum_K = 0; - igraph_integer_t *Kbuff = new igraph_integer_t[K]; + igraph_int_t *Kbuff = new igraph_int_t[K]; bool *visited = new bool[n]; - igraph_integer_t i; + igraph_int_t i; for (i = 0; i < n; i++) { visited[i] = false; } for (i = 0; i < quality; i++) { // assert(verify()); - igraph_integer_t f1, f2, t1, t2; - igraph_integer_t *f1t1, *f2t2; + igraph_int_t f1, f2, t1, t2; + igraph_int_t *f1t1, *f2t2; do { // Pick two random vertices do { @@ -639,14 +639,14 @@ double graph_molloy_hash::effective_K(igraph_integer_t K, int quality) { } //_________________________________________________________________________ -igraph_integer_t graph_molloy_hash::effective_isolated(igraph_integer_t v, igraph_integer_t K, igraph_integer_t *Kbuff, bool *visited) { - igraph_integer_t i; +igraph_int_t graph_molloy_hash::effective_isolated(igraph_int_t v, igraph_int_t K, igraph_int_t *Kbuff, bool *visited) { + igraph_int_t i; for (i = 0; i < K; i++) { Kbuff[i] = -1; } - igraph_integer_t count = 0; - igraph_integer_t left = K; - igraph_integer_t *KB = Kbuff; + igraph_int_t count = 0; + igraph_int_t left = K; + igraph_int_t *KB = Kbuff; //yapido = (my_random()%1000 == 0); depth_isolated(v, count, left, K, KB, visited); while (KB-- != Kbuff) { @@ -657,7 +657,7 @@ igraph_integer_t graph_molloy_hash::effective_isolated(igraph_integer_t v, igrap } //_________________________________________________________________________ -void graph_molloy_hash::depth_isolated(igraph_integer_t v, igraph_integer_t &calls, igraph_integer_t &left_to_explore, igraph_integer_t dmax, igraph_integer_t * &Kbuff, bool *visited) { +void graph_molloy_hash::depth_isolated(igraph_int_t v, igraph_int_t &calls, igraph_int_t &left_to_explore, igraph_int_t dmax, igraph_int_t * &Kbuff, bool *visited) { if (left_to_explore == 0) { return; } @@ -674,16 +674,16 @@ void graph_molloy_hash::depth_isolated(igraph_integer_t v, igraph_integer_t &cal // print(); // fflush(stdout); calls++; - igraph_integer_t *copy = NULL; - igraph_integer_t *w = neigh[v]; + igraph_int_t *copy = NULL; + igraph_int_t *w = neigh[v]; if (IS_HASH(deg[v])) { - copy = new igraph_integer_t[deg[v]]; + copy = new igraph_int_t[deg[v]]; H_copy(copy, w, deg[v]); w = copy; } qsort(deg, w, deg[v]); w += deg[v]; - for (igraph_integer_t i = deg[v]; i--; ) { + for (igraph_int_t i = deg[v]; i--; ) { if (visited[*--w]) { calls++; } else { @@ -699,19 +699,19 @@ void graph_molloy_hash::depth_isolated(igraph_integer_t v, igraph_integer_t &cal } //_________________________________________________________________________ -igraph_integer_t graph_molloy_hash::depth_search(bool *visited, igraph_integer_t *buff, igraph_integer_t v0) { - for (igraph_integer_t i = 0; i < n; i++) { +igraph_int_t graph_molloy_hash::depth_search(bool *visited, igraph_int_t *buff, igraph_int_t v0) { + for (igraph_int_t i = 0; i < n; i++) { visited[i] = false; } - igraph_integer_t *to_visit = buff; - igraph_integer_t nb_visited = 1; + igraph_int_t *to_visit = buff; + igraph_int_t nb_visited = 1; visited[v0] = true; *(to_visit++) = v0; while (to_visit != buff && nb_visited < n) { - igraph_integer_t v = *(--to_visit); - igraph_integer_t *ww = neigh[v]; - igraph_integer_t w; - for (igraph_integer_t k = HASH_SIZE(deg[v]); k--; ww++) { + igraph_int_t v = *(--to_visit); + igraph_int_t *ww = neigh[v]; + igraph_int_t w; + for (igraph_int_t k = HASH_SIZE(deg[v]); k--; ww++) { if (HASH_NONE != (w = *ww) && !visited[w]) { visited[w] = true; nb_visited++; diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.h b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.h index 086bcd9e082..ae19f71f711 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.h @@ -47,27 +47,27 @@ class graph_molloy_hash { private: // Number of vertices - igraph_integer_t n; + igraph_int_t n; //Number of arcs ( = #edges * 2 ) - igraph_integer_t a; + igraph_int_t a; //Total size of links[] - igraph_integer_t size; + igraph_int_t size; // The degree sequence of the graph - igraph_integer_t *deg; + igraph_int_t *deg; // The array containing all links - igraph_integer_t *links; + igraph_int_t *links; // The array containing pointers to adjacency list of every vertices - igraph_integer_t **neigh; + igraph_int_t **neigh; // Counts total size void compute_size(); // Build neigh with deg and links void compute_neigh(); // Allocate memory according to degree_sequence (for constructor use only!!) - igraph_integer_t alloc(degree_sequence &); + igraph_int_t alloc(degree_sequence &); // Add edge (u,v). Return FALSE if vertex a is already full. // WARNING : only to be used by havelhakimi(), restore() or constructors - inline bool add_edge(igraph_integer_t u, igraph_integer_t v, igraph_integer_t *realdeg) { - igraph_integer_t deg_u = realdeg[u]; + inline bool add_edge(igraph_int_t u, igraph_int_t v, igraph_int_t *realdeg) { + igraph_int_t deg_u = realdeg[u]; if (deg_u == deg[u]) { return false; } @@ -75,7 +75,7 @@ class graph_molloy_hash { assert(fast_search(neigh[u], (u == n - 1 ? links + size : neigh[u + 1]) - neigh[u], v) == NULL); assert(fast_search(neigh[v], (v == n - 1 ? links + size : neigh[v + 1]) - neigh[v], u) == NULL); assert(deg[u] < deg_u); - igraph_integer_t deg_v = realdeg[v]; + igraph_int_t deg_v = realdeg[v]; if (IS_HASH(deg_u)) { *H_add(neigh[u], HASH_EXPAND(deg_u), v) = v; } else { @@ -94,39 +94,39 @@ class graph_molloy_hash { return true; } // Swap edges - inline void swap_edges(igraph_integer_t from1, igraph_integer_t to1, igraph_integer_t from2, igraph_integer_t to2) { + inline void swap_edges(igraph_int_t from1, igraph_int_t to1, igraph_int_t from2, igraph_int_t to2) { H_rpl(neigh[from1], deg[from1], to1, to2); H_rpl(neigh[from2], deg[from2], to2, to1); H_rpl(neigh[to1], deg[to1], from1, from2); H_rpl(neigh[to2], deg[to2], from2, from1); } - // Backup graph [sizeof(igraph_integer_t) bytes per edge] - igraph_integer_t* backup(); + // Backup graph [sizeof(igraph_int_t) bytes per edge] + igraph_int_t* backup(); // Test if vertex is in an isolated component of size dmax. - void depth_isolated(igraph_integer_t v, igraph_integer_t &calls, igraph_integer_t &left_to_explore, igraph_integer_t dmax, igraph_integer_t * &Kbuff, bool *visited); + void depth_isolated(igraph_int_t v, igraph_int_t &calls, igraph_int_t &left_to_explore, igraph_int_t dmax, igraph_int_t * &Kbuff, bool *visited); public: //degree of v - inline igraph_integer_t degree(igraph_integer_t v) { + inline igraph_int_t degree(igraph_int_t v) { return deg[v]; }; // For debug purposes : verify validity of the graph (symetry, simplicity) @@ -136,19 +136,19 @@ class graph_molloy_hash { // Allocate memory for the graph. Create deg and links. No edge is created. graph_molloy_hash(degree_sequence &); // Create graph from hard copy - graph_molloy_hash(igraph_integer_t *); + graph_molloy_hash(igraph_int_t *); // Create hard copy of graph - igraph_integer_t *hard_copy(); + igraph_int_t *hard_copy(); // Restore from backup - void restore(igraph_integer_t* back); + void restore(igraph_int_t* back); //Clear hash tables void init(); // nb arcs - inline igraph_integer_t nbarcs() { + inline igraph_int_t nbarcs() { return a; }; // nb vertices - inline igraph_integer_t nbvertices() { + inline igraph_int_t nbvertices() { return n; }; // print graph in SUCC_LIST mode, in stdout @@ -157,7 +157,7 @@ class graph_molloy_hash { // Test if graph is connected bool is_connected(); // is edge ? - inline bool is_edge(igraph_integer_t u, igraph_integer_t v) { + inline bool is_edge(igraph_int_t u, igraph_int_t v) { assert(H_is(neigh[u], deg[u], v) == (fast_search(neigh[u], HASH_SIZE(deg[u]), v) != NULL)); assert(H_is(neigh[v], deg[v], u) == (fast_search(neigh[v], HASH_SIZE(deg[v]), u) != NULL)); assert(H_is(neigh[u], deg[u], v) == H_is(neigh[v], deg[v], u)); @@ -168,19 +168,19 @@ class graph_molloy_hash { } } // Random edge swap ATTEMPT. Return 1 if attempt was a succes, 0 otherwise - int random_edge_swap(igraph_integer_t K = 0, igraph_integer_t *Kbuff = NULL, bool *visited = NULL); + int random_edge_swap(igraph_int_t K = 0, igraph_int_t *Kbuff = NULL, bool *visited = NULL); // Connected Shuffle - igraph_integer_t shuffle(igraph_integer_t, igraph_integer_t, int type); + igraph_int_t shuffle(igraph_int_t, igraph_int_t, int type); // Optimal window for the gkantsidis heuristics - igraph_integer_t optimal_window(); + igraph_int_t optimal_window(); // Average unitary cost per post-validated edge swap, for some window - double average_cost(igraph_integer_t T, igraph_integer_t *back, double min_cost); + double average_cost(igraph_int_t T, igraph_int_t *back, double min_cost); // Get caracteristic K double eval_K(int quality = 100); // Get effective K - double effective_K(igraph_integer_t K, int quality = 10000); + double effective_K(igraph_int_t K, int quality = 10000); // Try to shuffle T times. Return true if at the end, the graph was still connected. - bool try_shuffle(igraph_integer_t T, igraph_integer_t K, igraph_integer_t *back = NULL); + bool try_shuffle(igraph_int_t T, igraph_int_t K, igraph_int_t *back = NULL); }; } // namespace gengraph diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.cpp b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.cpp index dc45a2aba4c..f5049ce99c7 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.cpp +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.cpp @@ -37,17 +37,17 @@ using namespace std; namespace gengraph { -igraph_integer_t graph_molloy_opt::max_degree() { - igraph_integer_t m = 0; - for (igraph_integer_t k = 0; k < n; k++) if (deg[k] > m) { +igraph_int_t graph_molloy_opt::max_degree() { + igraph_int_t m = 0; + for (igraph_int_t k = 0; k < n; k++) if (deg[k] > m) { m = deg[k]; } return m; } void graph_molloy_opt::compute_neigh() { - igraph_integer_t *p = links; - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t *p = links; + for (igraph_int_t i = 0; i < n; i++) { neigh[i] = p; p += deg[i]; } @@ -57,12 +57,12 @@ void graph_molloy_opt::alloc(degree_sequence °s) { n = degs.size(); a = degs.sum(); assert(a % 2 == 0); - deg = new igraph_integer_t[n + a]; - for (igraph_integer_t i = 0; i < n; i++) { + deg = new igraph_int_t[n + a]; + for (igraph_int_t i = 0; i < n; i++) { deg[i] = degs[i]; } links = deg + n; - neigh = new igraph_integer_t*[n]; + neigh = new igraph_int_t*[n]; compute_neigh(); } @@ -119,7 +119,7 @@ graph_molloy_opt::graph_molloy_opt(degree_sequence °s) { // if(VERBOSE()) fprintf(stderr,"done\n"); // } -graph_molloy_opt::graph_molloy_opt(igraph_integer_t *svg) { +graph_molloy_opt::graph_molloy_opt(igraph_int_t *svg) { // Read n n = *(svg++); // Read a @@ -148,14 +148,14 @@ graph_molloy_opt::~graph_molloy_opt() { detach(); } -igraph_integer_t* graph_molloy_opt::backup(igraph_integer_t *b) { +igraph_int_t* graph_molloy_opt::backup(igraph_int_t *b) { if (b == NULL) { - b = new igraph_integer_t[a / 2]; + b = new igraph_int_t[a / 2]; } - igraph_integer_t *c = b; - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t *p = neigh[i]; - for (igraph_integer_t d = deg[i]; d--; p++) { + igraph_int_t *c = b; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t *p = neigh[i]; + for (igraph_int_t d = deg[i]; d--; p++) { assert(*p != i); if (*p >= i) { *(c++) = *p; @@ -166,15 +166,15 @@ igraph_integer_t* graph_molloy_opt::backup(igraph_integer_t *b) { return b; } -igraph_integer_t *graph_molloy_opt::hard_copy() { - igraph_integer_t *hc = new igraph_integer_t[2 + n + a / 2]; // to store n,a,deg[] and links[] +igraph_int_t *graph_molloy_opt::hard_copy() { + igraph_int_t *hc = new igraph_int_t[2 + n + a / 2]; // to store n,a,deg[] and links[] hc[0] = n; hc[1] = a; - memcpy(hc + 2, deg, sizeof(igraph_integer_t)*n); - igraph_integer_t *c = hc + 2 + n; - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t *p = neigh[i]; - for (igraph_integer_t d = deg[i]; d--; p++) { + memcpy(hc + 2, deg, sizeof(igraph_int_t)*n); + igraph_int_t *c = hc + 2 + n; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t *p = neigh[i]; + for (igraph_int_t d = deg[i]; d--; p++) { assert(*p != i); if (*p >= i) { *(c++) = *p; @@ -185,15 +185,15 @@ igraph_integer_t *graph_molloy_opt::hard_copy() { return hc; } -void graph_molloy_opt::restore(igraph_integer_t* b) { - igraph_integer_t i; +void graph_molloy_opt::restore(igraph_int_t* b) { + igraph_int_t i; for (i = 0; i < n; i++) { deg[i] = 0; } - igraph_integer_t *p = links; + igraph_int_t *p = links; for (i = 0; i < n - 1; i++) { p += deg[i]; - deg[i] = igraph_integer_t(neigh[i + 1] - neigh[i]); + deg[i] = igraph_int_t(neigh[i + 1] - neigh[i]); assert((neigh[i] + deg[i]) == neigh[i + 1]); while (p != neigh[i + 1]) { // b points to the current 'j' @@ -203,95 +203,95 @@ void graph_molloy_opt::restore(igraph_integer_t* b) { } } -igraph_integer_t* graph_molloy_opt::backup_degs(igraph_integer_t *b) { +igraph_int_t* graph_molloy_opt::backup_degs(igraph_int_t *b) { if (b == NULL) { - b = new igraph_integer_t[n]; + b = new igraph_int_t[n]; } - memcpy(b, deg, sizeof(igraph_integer_t)*n); + memcpy(b, deg, sizeof(igraph_int_t)*n); return b; } -void graph_molloy_opt::restore_degs_only(igraph_integer_t *b) { - memcpy(deg, b, sizeof(igraph_integer_t)*n); +void graph_molloy_opt::restore_degs_only(igraph_int_t *b) { + memcpy(deg, b, sizeof(igraph_int_t)*n); refresh_nbarcs(); } -void graph_molloy_opt::restore_degs_and_neigh(igraph_integer_t *b) { +void graph_molloy_opt::restore_degs_and_neigh(igraph_int_t *b) { restore_degs_only(b); compute_neigh(); } -void graph_molloy_opt::restore_degs(igraph_integer_t last_degree) { +void graph_molloy_opt::restore_degs(igraph_int_t last_degree) { a = last_degree; deg[n - 1] = last_degree; - for (igraph_integer_t i = n - 2; i >= 0; i--) { - a += (deg[i] = igraph_integer_t(neigh[i + 1] - neigh[i])); + for (igraph_int_t i = n - 2; i >= 0; i--) { + a += (deg[i] = igraph_int_t(neigh[i + 1] - neigh[i])); } refresh_nbarcs(); } void graph_molloy_opt::clean() { - igraph_integer_t *b = hard_copy(); + igraph_int_t *b = hard_copy(); replace(b); delete[] b; } -void graph_molloy_opt::replace(igraph_integer_t *_hardcopy) { +void graph_molloy_opt::replace(igraph_int_t *_hardcopy) { delete[] deg; n = *(_hardcopy++); a = *(_hardcopy++); - deg = new igraph_integer_t[a + n]; - memcpy(deg, _hardcopy, sizeof(igraph_integer_t)*n); + deg = new igraph_int_t[a + n]; + memcpy(deg, _hardcopy, sizeof(igraph_int_t)*n); links = deg + n; compute_neigh(); restore(_hardcopy + n); } -igraph_integer_t* graph_molloy_opt::components(igraph_integer_t *comp) { - igraph_integer_t i; +igraph_int_t* graph_molloy_opt::components(igraph_int_t *comp) { + igraph_int_t i; // breadth-first search buffer - igraph_integer_t *buff = new igraph_integer_t[n]; + igraph_int_t *buff = new igraph_int_t[n]; // comp[i] will contain the index of the component that contains vertex i if (comp == NULL) { - comp = new igraph_integer_t[n]; + comp = new igraph_int_t[n]; } - memset(comp, 0, sizeof(igraph_integer_t)*n); + memset(comp, 0, sizeof(igraph_int_t)*n); // current component index - igraph_integer_t curr_comp = 0; + igraph_int_t curr_comp = 0; // loop over all non-visited vertices... - for (igraph_integer_t v0 = 0; v0 < n; v0++) if (comp[v0] == 0) { + for (igraph_int_t v0 = 0; v0 < n; v0++) if (comp[v0] == 0) { curr_comp++; // initiate breadth-first search - igraph_integer_t *to_visit = buff; - igraph_integer_t *visited = buff; + igraph_int_t *to_visit = buff; + igraph_int_t *visited = buff; *(to_visit++) = v0; comp[v0] = curr_comp; // breadth-first search while (visited != to_visit) { - igraph_integer_t v = *(visited++); - igraph_integer_t d = deg[v]; - for (igraph_integer_t *w = neigh[v]; d--; w++) if (comp[*w] == 0) { + igraph_int_t v = *(visited++); + igraph_int_t d = deg[v]; + for (igraph_int_t *w = neigh[v]; d--; w++) if (comp[*w] == 0) { comp[*w] = curr_comp; *(to_visit++) = *w; } } } // compute component sizes and store them in buff[] - igraph_integer_t nb_comp = 0; - memset(buff, 0, sizeof(igraph_integer_t)*n); + igraph_int_t nb_comp = 0; + memset(buff, 0, sizeof(igraph_int_t)*n); for (i = 0; i < n; i++) if (buff[comp[i] - 1]++ == 0 && comp[i] > nb_comp) { nb_comp = comp[i]; } // box-sort sizes - igraph_integer_t offset = 0; - igraph_integer_t *box = pre_boxsort(buff, nb_comp, offset); + igraph_int_t offset = 0; + igraph_int_t *box = pre_boxsort(buff, nb_comp, offset); for (i = nb_comp - 1; i >= 0; i--) { buff[i] = --box[buff[i] - offset]; } delete[] box; // reassign component indexes - for (igraph_integer_t *c = comp + n; comp != c--; *c = buff[*c - 1]) { } + for (igraph_int_t *c = comp + n; comp != c--; *c = buff[*c - 1]) { } // clean.. at last! delete[] buff; return comp; @@ -299,11 +299,11 @@ igraph_integer_t* graph_molloy_opt::components(igraph_integer_t *comp) { bool graph_molloy_opt::havelhakimi() { - igraph_integer_t i; - igraph_integer_t dmax = max_degree() + 1; + igraph_int_t i; + igraph_int_t dmax = max_degree() + 1; // Sort vertices using basket-sort, in descending degrees - igraph_integer_t *nb = new igraph_integer_t[dmax]; - igraph_integer_t *sorted = new igraph_integer_t[n]; + igraph_int_t *nb = new igraph_int_t[dmax]; + igraph_int_t *sorted = new igraph_int_t[n]; // init basket for (i = 0; i < dmax; i++) { nb[i] = 0; @@ -313,7 +313,7 @@ bool graph_molloy_opt::havelhakimi() { nb[deg[i]]++; } // cumul - igraph_integer_t c = 0; + igraph_int_t c = 0; for (i = dmax - 1; i >= 0; i--) { c += nb[i]; nb[i] = -nb[i] + c; @@ -324,30 +324,30 @@ bool graph_molloy_opt::havelhakimi() { } // Binding process starts - igraph_integer_t first = 0; // vertex with biggest residual degree - igraph_integer_t d = dmax - 1; // maximum residual degree available + igraph_int_t first = 0; // vertex with biggest residual degree + igraph_int_t d = dmax - 1; // maximum residual degree available for (c = a / 2; c > 0; ) { // pick a vertex. we could pick any, but here we pick the one with biggest degree - igraph_integer_t v = sorted[first]; + igraph_int_t v = sorted[first]; // look for current degree of v while (nb[d] <= first) { d--; } // store it in dv - igraph_integer_t dv = d; + igraph_int_t dv = d; // bind it ! c -= dv; - igraph_integer_t dc = d; // residual degree of vertices we bind to - igraph_integer_t fc = ++first; // position of the first vertex with degree dc + igraph_int_t dc = d; // residual degree of vertices we bind to + igraph_int_t fc = ++first; // position of the first vertex with degree dc while (dv > 0 && dc > 0) { - igraph_integer_t lc = nb[dc]; + igraph_int_t lc = nb[dc]; if (lc != fc) { while (dv > 0 && lc > fc) { // binds v with sorted[--lc] dv--; - igraph_integer_t w = sorted[--lc]; + igraph_int_t w = sorted[--lc]; *(neigh[v]++) = w; *(neigh[w]++) = v; } @@ -381,16 +381,16 @@ bool graph_molloy_opt::havelhakimi() { bool graph_molloy_opt::is_connected() { bool *visited = new bool[n]; - for (igraph_integer_t i = n; i > 0; visited[--i] = false) { } - igraph_integer_t *to_visit = new igraph_integer_t[n]; - igraph_integer_t *stop = to_visit; - igraph_integer_t left = n - 1; + for (igraph_int_t i = n; i > 0; visited[--i] = false) { } + igraph_int_t *to_visit = new igraph_int_t[n]; + igraph_int_t *stop = to_visit; + igraph_int_t left = n - 1; *(to_visit++) = 0; visited[0] = true; while (left > 0 && to_visit != stop) { - igraph_integer_t v = *(--to_visit); - igraph_integer_t *w = neigh[v]; - for (igraph_integer_t k = deg[v]; k--; w++) { + igraph_int_t v = *(--to_visit); + igraph_int_t *w = neigh[v]; + for (igraph_int_t k = deg[v]; k--; w++) { if (!visited[*w]) { visited[*w] = true; left--; @@ -411,13 +411,13 @@ bool graph_molloy_opt::make_connected() { // fprintf(stderr,"\ngraph::make_connected() failed : #edges < #vertices-1\n"); return false; } - igraph_integer_t i; + igraph_int_t i; // Data struct for the visit : // - buff[] contains vertices to visit // - dist[V] is V's distance modulo 4 to the root of its comp, or -1 if it hasn't been visited yet #define MC_BUFF_SIZE (n+2) - igraph_integer_t *buff = new igraph_integer_t[MC_BUFF_SIZE]; + igraph_int_t *buff = new igraph_int_t[MC_BUFF_SIZE]; unsigned char * dist = new unsigned char[n]; #define NOT_VISITED 255 #define FORBIDDEN 254 @@ -426,17 +426,17 @@ bool graph_molloy_opt::make_connected() { // Data struct to store components : either surplus trees or surplus edges are stored at buff[]'s end // - A Tree is coded by one of its vertices // - An edge (a,b) is coded by the TWO ints a and b - igraph_integer_t *ffub = buff + MC_BUFF_SIZE; + igraph_int_t *ffub = buff + MC_BUFF_SIZE; edge *edges = (edge *) ffub; - igraph_integer_t *trees = ffub; - igraph_integer_t *min_ffub = buff + 1 + (MC_BUFF_SIZE % 2 ? 0 : 1); + igraph_int_t *trees = ffub; + igraph_int_t *min_ffub = buff + 1 + (MC_BUFF_SIZE % 2 ? 0 : 1); // There will be only one "fatty" component, and trees. edge fatty_edge = { -1, -1 }; bool enough_edges = false; // start main loop - for (igraph_integer_t v0 = 0; v0 < n; v0++) if (dist[v0] == NOT_VISITED) { + for (igraph_int_t v0 = 0; v0 < n; v0++) if (dist[v0] == NOT_VISITED) { // is v0 an isolated vertex? if (deg[v0] == 0) { delete[] dist; @@ -445,20 +445,20 @@ bool graph_molloy_opt::make_connected() { return false; } dist[v0] = 0; // root - igraph_integer_t *to_visit = buff; - igraph_integer_t *current = buff; + igraph_int_t *to_visit = buff; + igraph_int_t *current = buff; *(to_visit++) = v0; // explore component connected to v0 bool is_a_tree = true; while (current != to_visit) { - igraph_integer_t v = *(current++); + igraph_int_t v = *(current++); unsigned char current_dist = dist[v]; unsigned char next_dist = (current_dist + 1) & 0x03; //unsigned char prev_dist = (current_dist-1) & 0x03; - igraph_integer_t* ww = neigh[v]; - igraph_integer_t w; - for (igraph_integer_t k = deg[v]; k--; ww++) { + igraph_int_t* ww = neigh[v]; + igraph_int_t w; + for (igraph_int_t k = deg[v]; k--; ww++) { if (dist[w = *ww] == NOT_VISITED) { // we didn't visit *w yet dist[w] = next_dist; @@ -539,7 +539,7 @@ bool graph_molloy_opt::make_connected() { return (trees == ffub || ((trees + 1) == ffub && fatty_edge.from < 0)); } -bool graph_molloy_opt::swap_edges_simple(igraph_integer_t from1, igraph_integer_t to1, igraph_integer_t from2, igraph_integer_t to2) { +bool graph_molloy_opt::swap_edges_simple(igraph_int_t from1, igraph_int_t to1, igraph_int_t from2, igraph_int_t to2) { if (from1 == to1 || from1 == from2 || from1 == to2 || to1 == from2 || to1 == to2 || from2 == to2) { return false; } @@ -551,7 +551,7 @@ bool graph_molloy_opt::swap_edges_simple(igraph_integer_t from1, igraph_integer_ } void graph_molloy_opt::print(FILE *f, bool NOZERO) { - igraph_integer_t i, j; + igraph_int_t i, j; for (i = 0; i < n; i++) { if (!NOZERO || deg[i] > 0) { fprintf(f, "%" IGRAPH_PRId, i); @@ -563,14 +563,14 @@ void graph_molloy_opt::print(FILE *f, bool NOZERO) { } } -igraph_integer_t graph_molloy_opt::effective_isolated(igraph_integer_t v, igraph_integer_t K, igraph_integer_t *Kbuff, bool *visited) { - igraph_integer_t i; +igraph_int_t graph_molloy_opt::effective_isolated(igraph_int_t v, igraph_int_t K, igraph_int_t *Kbuff, bool *visited) { + igraph_int_t i; for (i = 0; i < K; i++) { Kbuff[i] = -1; } - igraph_integer_t count = 0; - igraph_integer_t left = K; - igraph_integer_t *KB = Kbuff; + igraph_int_t count = 0; + igraph_int_t left = K; + igraph_int_t *KB = Kbuff; //yapido = (my_random()%1000 == 0); depth_isolated(v, count, left, K, KB, visited); while (KB-- != Kbuff) { @@ -580,7 +580,7 @@ igraph_integer_t graph_molloy_opt::effective_isolated(igraph_integer_t v, igraph return count; } -void graph_molloy_opt::depth_isolated(igraph_integer_t v, igraph_integer_t &calls, igraph_integer_t &left_to_explore, igraph_integer_t dmax, igraph_integer_t * &Kbuff, bool *visited) { +void graph_molloy_opt::depth_isolated(igraph_int_t v, igraph_int_t &calls, igraph_int_t &left_to_explore, igraph_int_t dmax, igraph_int_t * &Kbuff, bool *visited) { if (left_to_explore == 0) { return; } @@ -595,10 +595,10 @@ void graph_molloy_opt::depth_isolated(igraph_integer_t v, igraph_integer_t &call *(Kbuff++) = v; visited[v] = true; calls++; - igraph_integer_t *w = neigh[v]; + igraph_int_t *w = neigh[v]; qsort(deg, w, deg[v]); w += deg[v]; - for (igraph_integer_t i = deg[v]; i--; ) { + for (igraph_int_t i = deg[v]; i--; ) { if (visited[*--w]) { calls++; } else { @@ -610,19 +610,19 @@ void graph_molloy_opt::depth_isolated(igraph_integer_t v, igraph_integer_t &call } } -igraph_integer_t graph_molloy_opt::depth_search(bool *visited, igraph_integer_t *buff, igraph_integer_t v0) { - for (igraph_integer_t i = 0; i < n; i++) { +igraph_int_t graph_molloy_opt::depth_search(bool *visited, igraph_int_t *buff, igraph_int_t v0) { + for (igraph_int_t i = 0; i < n; i++) { visited[i] = false; } - igraph_integer_t *to_visit = buff; - igraph_integer_t nb_visited = 1; + igraph_int_t *to_visit = buff; + igraph_int_t nb_visited = 1; visited[v0] = true; *(to_visit++) = v0; while (to_visit != buff && nb_visited < n) { - igraph_integer_t v = *(--to_visit); - igraph_integer_t *ww = neigh[v]; - igraph_integer_t w; - for (igraph_integer_t k = deg[v]; k--; ww++) if (!visited[w = *ww]) { + igraph_int_t v = *(--to_visit); + igraph_int_t *ww = neigh[v]; + igraph_int_t w; + for (igraph_int_t k = deg[v]; k--; ww++) if (!visited[w = *ww]) { visited[w] = true; nb_visited++; *(to_visit++) = w; @@ -631,23 +631,23 @@ igraph_integer_t graph_molloy_opt::depth_search(bool *visited, igraph_integer_t return nb_visited; } -igraph_integer_t graph_molloy_opt::width_search(unsigned char *dist, igraph_integer_t *buff, igraph_integer_t v0, igraph_integer_t toclear) { - if (toclear >= 0) for (igraph_integer_t i = 0; i < toclear; i++) { +igraph_int_t graph_molloy_opt::width_search(unsigned char *dist, igraph_int_t *buff, igraph_int_t v0, igraph_int_t toclear) { + if (toclear >= 0) for (igraph_int_t i = 0; i < toclear; i++) { dist[buff[i]] = 0; - } else for (igraph_integer_t i = 0; i < n; i++) { + } else for (igraph_int_t i = 0; i < n; i++) { dist[i] = 0; } - igraph_integer_t *to_visit = buff; - igraph_integer_t *to_add = buff; - igraph_integer_t nb_visited = 1; + igraph_int_t *to_visit = buff; + igraph_int_t *to_add = buff; + igraph_int_t nb_visited = 1; dist[v0] = 1; *(to_add++) = v0; while (to_visit != to_add && nb_visited < n) { - igraph_integer_t v = *(to_visit++); - igraph_integer_t *ww = neigh[v]; - igraph_integer_t w; + igraph_int_t v = *(to_visit++); + igraph_int_t *ww = neigh[v]; + igraph_int_t w; unsigned char d = next_dist(dist[v]); - for (igraph_integer_t k = deg[v]; k--; ww++) if (dist[w = *ww] == 0) { + for (igraph_int_t k = deg[v]; k--; ww++) if (dist[w = *ww] == 0) { dist[w] = d; nb_visited++; *(to_add++) = w; @@ -657,25 +657,25 @@ igraph_integer_t graph_molloy_opt::width_search(unsigned char *dist, igraph_inte } // dist[] MUST be full of zeros !!!! -igraph_integer_t graph_molloy_opt::breadth_path_search(igraph_integer_t src, igraph_integer_t *buff, double *paths, unsigned char *dist) { +igraph_int_t graph_molloy_opt::breadth_path_search(igraph_int_t src, igraph_int_t *buff, double *paths, unsigned char *dist) { unsigned char last_dist = 0; unsigned char curr_dist = 1; - igraph_integer_t *to_visit = buff; - igraph_integer_t *visited = buff; + igraph_int_t *to_visit = buff; + igraph_int_t *visited = buff; *(to_visit++) = src; paths[src] = 1.0; dist[src] = curr_dist; - igraph_integer_t nb_visited = 1; + igraph_int_t nb_visited = 1; while (visited != to_visit) { - igraph_integer_t v = *(visited++); + igraph_int_t v = *(visited++); if (last_dist == (curr_dist = dist[v])) { break; } unsigned char nd = next_dist(curr_dist); - igraph_integer_t *ww = neigh[v]; + igraph_int_t *ww = neigh[v]; double p = paths[v]; - for (igraph_integer_t k = deg[v]; k--;) { - igraph_integer_t w = *(ww++); + for (igraph_int_t k = deg[v]; k--;) { + igraph_int_t w = *(ww++); unsigned char d = dist[w]; if (d == 0) { // not visited yet ! @@ -697,8 +697,8 @@ igraph_integer_t graph_molloy_opt::breadth_path_search(igraph_integer_t src, igr return nb_visited; } -igraph_integer_t *graph_molloy_opt::vertices_real(igraph_integer_t &nb_v) { - igraph_integer_t *yo; +igraph_int_t *graph_molloy_opt::vertices_real(igraph_int_t &nb_v) { + igraph_int_t *yo; if (nb_v < 0) { nb_v = 0; for (yo = deg; yo != deg + n; ) if (*(yo++) > 0) { @@ -709,9 +709,9 @@ igraph_integer_t *graph_molloy_opt::vertices_real(igraph_integer_t &nb_v) { IGRAPH_WARNING("graph is empty"); return NULL; } - igraph_integer_t *buff = new igraph_integer_t[nb_v]; + igraph_int_t *buff = new igraph_int_t[nb_v]; yo = buff; - for (igraph_integer_t i = 0; i < n; i++) if (deg[i] > 0) { + for (igraph_int_t i = 0; i < n; i++) if (deg[i] > 0) { *(yo++) = i; } if (yo != buff + nb_v) { @@ -723,7 +723,7 @@ igraph_integer_t *graph_molloy_opt::vertices_real(igraph_integer_t &nb_v) { } } -bool graph_molloy_opt::isolated(igraph_integer_t v, igraph_integer_t K, igraph_integer_t *Kbuff, bool *visited) { +bool graph_molloy_opt::isolated(igraph_int_t v, igraph_int_t K, igraph_int_t *Kbuff, bool *visited) { if (K < 2) { return false; } @@ -732,17 +732,17 @@ bool graph_molloy_opt::isolated(igraph_integer_t v, igraph_integer_t K, igraph_i return false; } #endif //OPT_ISOLATED - igraph_integer_t *seen = Kbuff; - igraph_integer_t *known = Kbuff; - igraph_integer_t *max = Kbuff + (K - 1); + igraph_int_t *seen = Kbuff; + igraph_int_t *known = Kbuff; + igraph_int_t *max = Kbuff + (K - 1); *(known++) = v; visited[v] = true; bool is_isolated = true; while (known != seen) { v = *(seen++); - igraph_integer_t *w = neigh[v]; - for (igraph_integer_t d = deg[v]; d--; w++) if (!visited[*w]) { + igraph_int_t *w = neigh[v]; + for (igraph_int_t d = deg[v]; d--; w++) if (!visited[*w]) { #ifdef OPT_ISOLATED if (K <= deg[*w] + 1 || known == max) { #else //OPT_ISOLATED @@ -776,7 +776,7 @@ void graph_molloy_opt::sort() { bool graph_molloy_opt::verify(int mode) { IGRAPH_UNUSED(mode); #ifndef NDEBUG - igraph_integer_t i, j, k; + igraph_int_t i, j, k; assert(neigh[0] == links); // verify edges count if ((mode & VERIFY_NOARCS) == 0) { @@ -800,8 +800,8 @@ bool graph_molloy_opt::verify(int mode) { // assert(neigh[i][j]!=neigh[i][k]); // verify symmetry for (i = 0; i < n; i++) for (j = 0; j < deg[i]; j++) { - igraph_integer_t v = neigh[i][j]; - igraph_integer_t nb = 0; + igraph_int_t v = neigh[i][j]; + igraph_int_t nb = 0; for (k = 0; k < deg[v]; k++) if (neigh[v][k] == i) { nb++; } diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.h b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.h index 657273c6033..b662bd7966e 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_optimized.h @@ -37,28 +37,28 @@ class graph_molloy_opt { // Random generator KW_RNG::RNG rng; // Number of vertices - igraph_integer_t n; + igraph_int_t n; //Number of arcs ( = #edges * 2 ) - igraph_integer_t a; + igraph_int_t a; // The degree sequence of the graph - igraph_integer_t *deg; + igraph_int_t *deg; // The array containing all links - igraph_integer_t *links; + igraph_int_t *links; // The array containing pointers to adjacency list of every vertices - igraph_integer_t **neigh; + igraph_int_t **neigh; // Allocate memory according to degree_sequence (for constructor use only!!) void alloc(degree_sequence &); // Compute #edges inline void refresh_nbarcs() { a = 0; - for (igraph_integer_t* d = deg + n; d != deg; ) { + for (igraph_int_t* d = deg + n; d != deg; ) { a += *(--d); } } // Build neigh with deg and links void compute_neigh(); // Swap edges. The swap MUST be valid !!! - inline void swap_edges(igraph_integer_t from1, igraph_integer_t to1, igraph_integer_t from2, igraph_integer_t to2) { + inline void swap_edges(igraph_int_t from1, igraph_int_t to1, igraph_int_t from2, igraph_int_t to2) { fast_rpl(neigh[from1], to1, to2); fast_rpl(neigh[from2], to2, to1); fast_rpl(neigh[to1], from1, from2); @@ -66,46 +66,46 @@ class graph_molloy_opt { } // Swap edges only if they are simple. return false if unsuccessful. - bool swap_edges_simple(igraph_integer_t, igraph_integer_t, igraph_integer_t, igraph_integer_t); + bool swap_edges_simple(igraph_int_t, igraph_int_t, igraph_int_t, igraph_int_t); // Test if vertex is in an isolated component of size dmax. - void depth_isolated(igraph_integer_t v, igraph_integer_t &calls, igraph_integer_t &left_to_explore, igraph_integer_t dmax, igraph_integer_t * &Kbuff, bool *visited); + void depth_isolated(igraph_int_t v, igraph_int_t &calls, igraph_int_t &left_to_explore, igraph_int_t dmax, igraph_int_t * &Kbuff, bool *visited); // breadth-first search. Store the distance (modulo 3) in dist[]. Returns eplorated component size. - igraph_integer_t width_search(unsigned char *dist, igraph_integer_t *buff, igraph_integer_t v0 = 0, igraph_integer_t toclear = -1); + igraph_int_t width_search(unsigned char *dist, igraph_int_t *buff, igraph_int_t v0 = 0, igraph_int_t toclear = -1); // depth-first search. - igraph_integer_t depth_search(bool *visited, igraph_integer_t *buff, igraph_integer_t v0 = 0); + igraph_int_t depth_search(bool *visited, igraph_int_t *buff, igraph_int_t v0 = 0); // breadth-first search that count the number of shortest paths going from src to each vertex - igraph_integer_t breadth_path_search(igraph_integer_t src, igraph_integer_t *buff, double *paths, unsigned char *dist); + igraph_int_t breadth_path_search(igraph_int_t src, igraph_int_t *buff, double *paths, unsigned char *dist); // Return component indexes where vertices belong to, starting from 0, // sorted by size (biggest component has index 0) - igraph_integer_t *components(igraph_integer_t *comp = NULL); + igraph_int_t *components(igraph_int_t *comp = NULL); public: // neigh[] - inline igraph_integer_t** neighbors() { + inline igraph_int_t** neighbors() { return neigh; }; // deg[] - inline igraph_integer_t* degrees() { + inline igraph_int_t* degrees() { return deg; }; //adjacency list of v - inline igraph_integer_t* operator[](const igraph_integer_t v) { + inline igraph_int_t* operator[](const igraph_int_t v) { return neigh[v]; }; //degree of v - inline igraph_integer_t degree(const igraph_integer_t v) { + inline igraph_int_t degree(const igraph_int_t v) { return deg[v]; }; // Detach deg[] and neigh[] @@ -117,27 +117,27 @@ class graph_molloy_opt { // Allocate memory for the graph. Create deg and links. No edge is created. graph_molloy_opt(degree_sequence &); // Create graph from hard copy - graph_molloy_opt(igraph_integer_t *); + graph_molloy_opt(igraph_int_t *); // Create hard copy of graph - igraph_integer_t *hard_copy(); + igraph_int_t *hard_copy(); // Remove unused edges, updates neigh[], recreate links[] void clean(); // nb arcs - inline igraph_integer_t nbarcs() { + inline igraph_int_t nbarcs() { return a; }; // last degree - inline igraph_integer_t last_degree() { + inline igraph_int_t last_degree() { return deg[n - 1]; }; // nb vertices - inline igraph_integer_t nbvertices() { + inline igraph_int_t nbvertices() { return n; }; // nb vertices having degree > 0 - inline igraph_integer_t nbvertices_real() { - igraph_integer_t s = 0; - for (igraph_integer_t *d = deg + n; d-- != deg; ) { + inline igraph_int_t nbvertices_real() { + igraph_int_t s = 0; + for (igraph_int_t *d = deg + n; d-- != deg; ) { if (*d) { s++; } @@ -145,7 +145,7 @@ class graph_molloy_opt { return s; }; // return list of vertices with degree > 0. Compute #vertices, if not given. - igraph_integer_t *vertices_real(igraph_integer_t &nb_v); + igraph_int_t *vertices_real(igraph_int_t &nb_v); // print graph in SUCC_LIST mode, in stdout void print(FILE *f = stdout, bool NOZERO = true); // Bind the graph avoiding multiple edges or self-edges (return false if fail) @@ -155,29 +155,29 @@ class graph_molloy_opt { // Test if graph is connected bool is_connected(); // Maximum degree - igraph_integer_t max_degree(); + igraph_int_t max_degree(); // is edge ? - inline bool is_edge(const igraph_integer_t u, const igraph_integer_t v) { + inline bool is_edge(const igraph_int_t u, const igraph_int_t v) { if (deg[v] < deg[u]) { return (fast_search(neigh[v], deg[v], u) != NULL); } else { return (fast_search(neigh[u], deg[u], v) != NULL); } } - // Backup graph [sizeof(igraph_integer_t) bytes per edge] - igraph_integer_t* backup(igraph_integer_t *here = NULL); + // Backup graph [sizeof(igraph_int_t) bytes per edge] + igraph_int_t* backup(igraph_int_t *here = NULL); // Restore from backup. Assume that degrees haven't changed - void restore(igraph_integer_t* back); + void restore(igraph_int_t* back); // Resplace with hard backup. - void replace(igraph_integer_t* _hardbackup); + void replace(igraph_int_t* _hardbackup); // Backup degs of graph - igraph_integer_t* backup_degs(igraph_integer_t *here = NULL); + igraph_int_t* backup_degs(igraph_int_t *here = NULL); // Restore degs from neigh[]. Need last degree, though - void restore_degs(igraph_integer_t last_degree); + void restore_degs(igraph_int_t last_degree); // Restore degs[] from backup. Assume that links[] has only been permuted - void restore_degs_only(igraph_integer_t* backup_degs); + void restore_degs_only(igraph_int_t* backup_degs); // Restore degs[] and neigh[]. Assume that links[] has only been permuted - void restore_degs_and_neigh(igraph_integer_t* backup_degs); + void restore_degs_and_neigh(igraph_int_t* backup_degs); // sort adjacency lists void sort(); // count cycles passing through vertex v diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_hash.h b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_hash.h index 9689c0a79b0..40601b86f88 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_hash.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_hash.h @@ -85,7 +85,7 @@ namespace gengraph { #define HASH_NONE (-1) #ifdef HASH_SIZE_IS_POWER2 -inline igraph_integer_t HASH_EXPAND(igraph_integer_t x) { +inline igraph_int_t HASH_EXPAND(igraph_int_t x) { /* Returns pow(2, floor(log2(x)) + 2) if x > 0, 1 otherwise. Works up to * x == 2^64, starts to break down afterwards */ _HASH_EXP_CALL(); @@ -109,19 +109,19 @@ inline igraph_integer_t HASH_EXPAND(igraph_integer_t x) { #define HASH_REKEY(k,size) ((k)==0 ? (size)-1 : (k)-1) #else //MACRO_RATHER_THAN_INLINE #ifndef HASH_SIZE_IS_POWER2 -inline igraph_integer_t HASH_KEY(igraph_integer_t x, igraph_integer_t size) { +inline igraph_int_t HASH_KEY(igraph_int_t x, igraph_int_t size) { assert(x >= 0); return x % size; }; -inline igraph_integer_t HASH_EXPAND(igraph_integer_t x) { +inline igraph_int_t HASH_EXPAND(igraph_int_t x) { _HASH_EXP_CALL(); return x + (x >> 1); }; -inline int HASH_UNEXPAND(igraph_integer_t x) { +inline int HASH_UNEXPAND(igraph_int_t x) { return ((x << 1) + 1) / 3; }; #endif //HASH_SIZE_IS_POWER2 -inline int HASH_REKEY(igraph_integer_t k, igraph_integer_t s) { +inline int HASH_REKEY(igraph_int_t k, igraph_int_t s) { assert(k >= 0); if (k == 0) { return s - 1; @@ -129,7 +129,7 @@ inline int HASH_REKEY(igraph_integer_t k, igraph_integer_t s) { return k - 1; } }; -inline int HASH_SIZE(igraph_integer_t x) { +inline int HASH_SIZE(igraph_int_t x) { if (IS_HASH(x)) { return HASH_EXPAND(x); } else { @@ -138,7 +138,7 @@ inline int HASH_SIZE(igraph_integer_t x) { }; #endif //MACRO_RATHER_THAN_INLINE -inline igraph_integer_t HASH_PAIR_KEY(igraph_integer_t x, igraph_integer_t y, igraph_integer_t size) { +inline igraph_int_t HASH_PAIR_KEY(igraph_int_t x, igraph_int_t y, igraph_int_t size) { return HASH_KEY(x * 1434879443 + y, size); } @@ -148,8 +148,8 @@ inline igraph_integer_t HASH_PAIR_KEY(igraph_integer_t x, igraph_integer_t y, ig //_________________________________________________________________________ // copy hash table into raw vector -inline void H_copy(igraph_integer_t *mem, igraph_integer_t *h, igraph_integer_t size) { - for (igraph_integer_t i = HASH_EXPAND(size); i--; h++) { +inline void H_copy(igraph_int_t *mem, igraph_int_t *h, igraph_int_t size) { + for (igraph_int_t i = HASH_EXPAND(size); i--; h++) { if (*h != HASH_NONE) { *(mem++) = *h; } @@ -157,10 +157,10 @@ inline void H_copy(igraph_integer_t *mem, igraph_integer_t *h, igraph_integer_t } // Look for the place to add an element. Return NULL if element is already here. -inline igraph_integer_t* H_add(igraph_integer_t* h, igraph_integer_t size, igraph_integer_t a) { +inline igraph_int_t* H_add(igraph_int_t* h, igraph_int_t size, igraph_int_t a) { _HASH_ADD_CALL(); _HASH_ADD_ITER(); - igraph_integer_t k = HASH_KEY(a, size); + igraph_int_t k = HASH_KEY(a, size); if (h[k] == HASH_NONE) { return h + k; } @@ -175,8 +175,8 @@ inline igraph_integer_t* H_add(igraph_integer_t* h, igraph_integer_t size, igrap } // would element be well placed in newk ? -inline bool H_better(igraph_integer_t a, igraph_integer_t size, igraph_integer_t currentk, igraph_integer_t newk) { - igraph_integer_t k = HASH_KEY(a, size); +inline bool H_better(igraph_int_t a, igraph_int_t size, igraph_int_t currentk, igraph_int_t newk) { + igraph_int_t k = HASH_KEY(a, size); if (newk < currentk) { return (k < currentk && k >= newk); } else { @@ -185,13 +185,13 @@ inline bool H_better(igraph_integer_t a, igraph_integer_t size, igraph_integer_t } // removes h[k] -inline void H_rm(igraph_integer_t* h, igraph_integer_t size, igraph_integer_t k) { +inline void H_rm(igraph_int_t* h, igraph_int_t size, igraph_int_t k) { _HASH_RM_CALL(); - igraph_integer_t lasthole = k; + igraph_int_t lasthole = k; do { _HASH_RM_ITER(); k = HASH_REKEY(k, size); - igraph_integer_t next = h[k]; + igraph_int_t next = h[k]; if (next == HASH_NONE) { break; } @@ -204,11 +204,11 @@ inline void H_rm(igraph_integer_t* h, igraph_integer_t size, igraph_integer_t k) } //put a -inline igraph_integer_t* H_put(igraph_integer_t* h, igraph_integer_t size, igraph_integer_t a) { +inline igraph_int_t* H_put(igraph_int_t* h, igraph_int_t size, igraph_int_t a) { assert(H_add(h, size, a) != NULL); _HASH_PUT_CALL(); _HASH_PUT_ITER(); - igraph_integer_t k = HASH_KEY(a, size); + igraph_int_t k = HASH_KEY(a, size); while (h[k] != HASH_NONE) { k = HASH_REKEY(k, size); _HASH_PUT_ITER(); @@ -219,11 +219,11 @@ inline igraph_integer_t* H_put(igraph_integer_t* h, igraph_integer_t size, igrap } // find A -inline igraph_integer_t H_find(igraph_integer_t *h, igraph_integer_t size, igraph_integer_t a) { +inline igraph_int_t H_find(igraph_int_t *h, igraph_int_t size, igraph_int_t a) { assert(H_add(h, size, a) == NULL); _HASH_FIND_CALL(); _HASH_FIND_ITER(); - igraph_integer_t k = HASH_KEY(a, size); + igraph_int_t k = HASH_KEY(a, size); while (h[k] != a) { k = HASH_REKEY(k, size); _HASH_FIND_ITER(); @@ -232,10 +232,10 @@ inline igraph_integer_t H_find(igraph_integer_t *h, igraph_integer_t size, igrap } // Look for the place to add an element. Return NULL if element is already here. -inline bool H_pair_insert(igraph_integer_t* h, igraph_integer_t size, igraph_integer_t a, igraph_integer_t b) { +inline bool H_pair_insert(igraph_int_t* h, igraph_int_t size, igraph_int_t a, igraph_int_t b) { _HASH_ADD_CALL(); _HASH_ADD_ITER(); - igraph_integer_t k = HASH_PAIR_KEY(a, b, size); + igraph_int_t k = HASH_PAIR_KEY(a, b, size); if (h[2 * k] == HASH_NONE) { h[2 * k] = a; h[2 * k + 1] = b; @@ -260,7 +260,7 @@ inline bool H_pair_insert(igraph_integer_t* h, igraph_integer_t size, igraph_int //_________________________________________________________________________ // Look for an element -inline bool H_is(igraph_integer_t *mem, igraph_integer_t size, igraph_integer_t elem) { +inline bool H_is(igraph_int_t *mem, igraph_int_t size, igraph_int_t elem) { if (IS_HASH(size)) { return (H_add(mem, HASH_EXPAND(size), elem) == NULL); } else { @@ -269,13 +269,13 @@ inline bool H_is(igraph_integer_t *mem, igraph_integer_t size, igraph_integer_t } //pick random location (containing an element) -inline igraph_integer_t* H_random(igraph_integer_t* mem, igraph_integer_t size) { +inline igraph_int_t* H_random(igraph_int_t* mem, igraph_int_t size) { if (!IS_HASH(size)) { return mem + (my_random() % size); } _HASH_RAND_CALL(); size = HASH_EXPAND(size); - igraph_integer_t* yo; + igraph_int_t* yo; do { yo = mem + HASH_KEY(my_random(), size); _HASH_RAND_ITER(); @@ -284,7 +284,7 @@ inline igraph_integer_t* H_random(igraph_integer_t* mem, igraph_integer_t size) } // replace *k by b -inline igraph_integer_t* H_rpl(igraph_integer_t *mem, igraph_integer_t size, igraph_integer_t* k, igraph_integer_t b) { +inline igraph_int_t* H_rpl(igraph_int_t *mem, igraph_int_t size, igraph_int_t* k, igraph_int_t b) { assert(!H_is(mem, size, b)); if (!IS_HASH(size)) { *k = b; @@ -298,7 +298,7 @@ inline igraph_integer_t* H_rpl(igraph_integer_t *mem, igraph_integer_t size, igr } // replace a by b -inline igraph_integer_t* H_rpl(igraph_integer_t *mem, igraph_integer_t size, igraph_integer_t a, igraph_integer_t b) { +inline igraph_int_t* H_rpl(igraph_int_t *mem, igraph_int_t size, igraph_int_t a, igraph_int_t b) { assert(H_is(mem, size, a)); assert(!H_is(mem, size, b)); if (!IS_HASH(size)) { diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp index 857cf5c5aa9..9dd5e2b1077 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_mr-connected.cpp @@ -167,7 +167,7 @@ igraph_error_t igraph_i_degree_sequence_game_vl(igraph_t *graph, IGRAPH_EINVAL); } - igraph_integer_t *hc = g->hard_copy(); + igraph_int_t *hc = g->hard_copy(); delete g; graph_molloy_hash *gh = new graph_molloy_hash(hc); delete [] hc; diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_qsort.h b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_qsort.h index 85df8bc4464..383bb6388aa 100644 --- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_qsort.h +++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_qsort.h @@ -30,8 +30,8 @@ namespace gengraph { //___________________________________________________________________________ // check if every element is zero -inline bool check_zero(igraph_integer_t *mem, igraph_integer_t n) { - for (igraph_integer_t *v = mem + n; v != mem; ) { +inline bool check_zero(igraph_int_t *mem, igraph_int_t n) { + for (igraph_int_t *v = mem + n; v != mem; ) { if (*(--v) != 0) { return false; } @@ -42,7 +42,7 @@ inline bool check_zero(igraph_integer_t *mem, igraph_integer_t n) { //___________________________________________________________________________ // Sort simple integer arrays in ASCENDING order //___________________________________________________________________________ -inline igraph_integer_t med3(igraph_integer_t a, igraph_integer_t b, igraph_integer_t c) { +inline igraph_int_t med3(igraph_int_t a, igraph_int_t b, igraph_int_t c) { if (a < b) { if (c < b) { return (a < c) ? c : a; @@ -58,13 +58,13 @@ inline igraph_integer_t med3(igraph_integer_t a, igraph_integer_t b, igraph_inte } } -inline void isort(igraph_integer_t *v, igraph_integer_t t) { +inline void isort(igraph_int_t *v, igraph_int_t t) { if (t < 2) { return; } - for (igraph_integer_t i = 1; i < t; i++) { - igraph_integer_t *w = v + i; - igraph_integer_t tmp = *w; + for (igraph_int_t i = 1; i < t; i++) { + igraph_int_t *w = v + i; + igraph_int_t tmp = *w; while (w != v && *(w - 1) > tmp) { *w = *(w - 1); w--; @@ -73,9 +73,9 @@ inline void isort(igraph_integer_t *v, igraph_integer_t t) { } } -inline igraph_integer_t partitionne(igraph_integer_t *v, igraph_integer_t t, igraph_integer_t p) { - igraph_integer_t i = 0; - igraph_integer_t j = t - 1; +inline igraph_int_t partitionne(igraph_int_t *v, igraph_int_t t, igraph_int_t p) { + igraph_int_t i = 0; + igraph_int_t j = t - 1; while (i < j) { while (i <= j && v[i] < p) { i++; @@ -84,7 +84,7 @@ inline igraph_integer_t partitionne(igraph_integer_t *v, igraph_integer_t t, igr j--; } if (i < j) { - igraph_integer_t tmp = v[i]; + igraph_int_t tmp = v[i]; v[i++] = v[j]; v[j--] = tmp; } @@ -96,22 +96,22 @@ inline igraph_integer_t partitionne(igraph_integer_t *v, igraph_integer_t t, igr return i; } -inline void qsort(igraph_integer_t *v, igraph_integer_t t) { +inline void qsort(igraph_int_t *v, igraph_int_t t) { if (t < 15) { isort(v, t); } else { - igraph_integer_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); + igraph_int_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); qsort(v, x); qsort(v + x, t - x); } } -inline igraph_integer_t qsort_median(igraph_integer_t *v, igraph_integer_t t, igraph_integer_t pos) { +inline igraph_int_t qsort_median(igraph_int_t *v, igraph_int_t t, igraph_int_t pos) { if (t < 10) { isort(v, t); return v[pos]; } - igraph_integer_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); + igraph_int_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); if (pos < x) { return qsort_median(v, x, pos); } else { @@ -119,7 +119,7 @@ inline igraph_integer_t qsort_median(igraph_integer_t *v, igraph_integer_t t, ig } } -inline igraph_integer_t qsort_median(igraph_integer_t *v, igraph_integer_t t) { +inline igraph_int_t qsort_median(igraph_int_t *v, igraph_int_t t) { return qsort_median(v, t, t / 2); } @@ -142,11 +142,11 @@ inline double med3(double a, double b, double c) { } } -inline void isort(double *v, igraph_integer_t t) { +inline void isort(double *v, igraph_int_t t) { if (t < 2) { return; } - for (igraph_integer_t i = 1; i < t; i++) { + for (igraph_int_t i = 1; i < t; i++) { double *w = v + i; double tmp = *w; while (w != v && *(w - 1) > tmp) { @@ -157,9 +157,9 @@ inline void isort(double *v, igraph_integer_t t) { } } -inline igraph_integer_t partitionne(double *v, igraph_integer_t t, double p) { - igraph_integer_t i = 0; - igraph_integer_t j = t - 1; +inline igraph_int_t partitionne(double *v, igraph_int_t t, double p) { + igraph_int_t i = 0; + igraph_int_t j = t - 1; while (i < j) { while (i <= j && v[i] < p) { i++; @@ -180,22 +180,22 @@ inline igraph_integer_t partitionne(double *v, igraph_integer_t t, double p) { return i; } -inline void qsort(double *v, igraph_integer_t t) { +inline void qsort(double *v, igraph_int_t t) { if (t < 15) { isort(v, t); } else { - igraph_integer_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); + igraph_int_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); qsort(v, x); qsort(v + x, t - x); } } -inline double qsort_median(double *v, igraph_integer_t t, igraph_integer_t pos) { +inline double qsort_median(double *v, igraph_int_t t, igraph_int_t pos) { if (t < 10) { isort(v, t); return v[pos]; } - igraph_integer_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); + igraph_int_t x = partitionne(v, t, med3(v[t >> 1], v[(t >> 2) + 2], v[t - (t >> 1) - 2])); if (pos < x) { return qsort_median(v, x, pos); } else { @@ -203,20 +203,20 @@ inline double qsort_median(double *v, igraph_integer_t t, igraph_integer_t pos) } } -inline double qsort_median(double *v, igraph_integer_t t) { +inline double qsort_median(double *v, igraph_int_t t) { return qsort_median(v, t, t / 2); } //___________________________________________________________________________ // Sort integer arrays according to value stored in mem[], in ASCENDING order -inline void isort(igraph_integer_t *mem, igraph_integer_t *v, igraph_integer_t t) { +inline void isort(igraph_int_t *mem, igraph_int_t *v, igraph_int_t t) { if (t < 2) { return; } - for (igraph_integer_t i = 1; i < t; i++) { - igraph_integer_t vtmp = v[i]; - igraph_integer_t tmp = mem[vtmp]; - igraph_integer_t j; + for (igraph_int_t i = 1; i < t; i++) { + igraph_int_t vtmp = v[i]; + igraph_int_t tmp = mem[vtmp]; + igraph_int_t j; for (j = i; j > 0 && tmp < mem[v[j - 1]]; j--) { v[j] = v[j - 1]; } @@ -224,13 +224,13 @@ inline void isort(igraph_integer_t *mem, igraph_integer_t *v, igraph_integer_t t } } -inline void qsort(igraph_integer_t *mem, igraph_integer_t *v, igraph_integer_t t) { +inline void qsort(igraph_int_t *mem, igraph_int_t *v, igraph_int_t t) { if (t < 15) { isort(mem, v, t); } else { - igraph_integer_t p = med3(mem[v[t >> 1]], mem[v[(t >> 2) + 3]], mem[v[t - (t >> 1) - 3]]); - igraph_integer_t i = 0; - igraph_integer_t j = t - 1; + igraph_int_t p = med3(mem[v[t >> 1]], mem[v[(t >> 2) + 3]], mem[v[t - (t >> 1) - 3]]); + igraph_int_t i = 0; + igraph_int_t j = t - 1; while (i < j) { while (i <= j && mem[v[i]] < p) { i++; @@ -239,7 +239,7 @@ inline void qsort(igraph_integer_t *mem, igraph_integer_t *v, igraph_integer_t t j--; } if (i < j) { - igraph_integer_t tmp = v[i]; + igraph_int_t tmp = v[i]; v[i++] = v[j]; v[j--] = tmp; } @@ -254,13 +254,13 @@ inline void qsort(igraph_integer_t *mem, igraph_integer_t *v, igraph_integer_t t } //Box-Sort 1..n according to value stored in mem[], in DESCENDING order. -inline igraph_integer_t *pre_boxsort(igraph_integer_t *mem, igraph_integer_t n, igraph_integer_t &offset) { - igraph_integer_t *yo; +inline igraph_int_t *pre_boxsort(igraph_int_t *mem, igraph_int_t n, igraph_int_t &offset) { + igraph_int_t *yo; // maximum and minimum - igraph_integer_t mx = mem[0]; - igraph_integer_t mn = mem[0]; + igraph_int_t mx = mem[0]; + igraph_int_t mn = mem[0]; for (yo = mem + n - 1; yo != mem; yo--) { - igraph_integer_t x = *yo; + igraph_int_t x = *yo; if (x > mx) { mx = x; } @@ -269,12 +269,12 @@ inline igraph_integer_t *pre_boxsort(igraph_integer_t *mem, igraph_integer_t n, } } // box - igraph_integer_t c = mx - mn + 1; - igraph_integer_t *box = new igraph_integer_t[c]; + igraph_int_t c = mx - mn + 1; + igraph_int_t *box = new igraph_int_t[c]; for (yo = box + c; yo != box; * (--yo) = 0) { } for (yo = mem + n; yo != mem; box[*(--yo) - mn]++) { } // cumul sum - igraph_integer_t sum = 0; + igraph_int_t sum = 0; for (yo = box + c; yo != box; ) { sum += *(--yo); *yo = sum; @@ -283,16 +283,16 @@ inline igraph_integer_t *pre_boxsort(igraph_integer_t *mem, igraph_integer_t n, return box; } -inline igraph_integer_t *boxsort(igraph_integer_t *mem, igraph_integer_t n, igraph_integer_t *buff = NULL) { - igraph_integer_t i; +inline igraph_int_t *boxsort(igraph_int_t *mem, igraph_int_t n, igraph_int_t *buff = NULL) { + igraph_int_t i; if (n <= 0) { return buff; } - igraph_integer_t offset = 0; - igraph_integer_t *box = pre_boxsort(mem, n, offset); + igraph_int_t offset = 0; + igraph_int_t *box = pre_boxsort(mem, n, offset); // sort if (buff == NULL) { - buff = new igraph_integer_t[n]; + buff = new igraph_int_t[n]; } for (i = 0; i < n; i++) { buff[--box[mem[i] - offset]] = i; diff --git a/src/vendor/cigraph/src/games/dotproduct.c b/src/vendor/cigraph/src/games/dotproduct.c index d0456f2a538..9281d3f07e7 100644 --- a/src/vendor/cigraph/src/games/dotproduct.c +++ b/src/vendor/cigraph/src/games/dotproduct.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2014 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -59,25 +59,24 @@ igraph_error_t igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *vecs, igraph_bool_t directed) { - igraph_integer_t nrow = igraph_matrix_nrow(vecs); - igraph_integer_t ncol = igraph_matrix_ncol(vecs); - igraph_integer_t i, j; + igraph_int_t nrow = igraph_matrix_nrow(vecs); + igraph_int_t ncol = igraph_matrix_ncol(vecs); + igraph_int_t i, j; igraph_vector_int_t edges; igraph_bool_t warned_neg = false, warned_big = false; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); for (i = 0; i < ncol; i++) { - igraph_integer_t from = directed ? 0 : i + 1; - igraph_vector_t v1; - igraph_vector_view(&v1, &MATRIX(*vecs, 0, i), nrow); + igraph_int_t from = directed ? 0 : i + 1; + const igraph_vector_t v1 = igraph_vector_view(&MATRIX(*vecs, 0, i), nrow); for (j = from; j < ncol; j++) { igraph_real_t prob; - igraph_vector_t v2; + const igraph_vector_t v2 = igraph_vector_view(&MATRIX(*vecs, 0, j), nrow); + if (i == j) { continue; } - igraph_vector_view(&v2, &MATRIX(*vecs, 0, j), nrow); IGRAPH_CHECK(igraph_blas_ddot(&v1, &v2, &prob)); if (prob < 0 && ! warned_neg) { warned_neg = true; diff --git a/src/vendor/cigraph/src/games/erdos_renyi.c b/src/vendor/cigraph/src/games/erdos_renyi.c index a52f19f648b..7d08e40c639 100644 --- a/src/vendor/cigraph/src/games/erdos_renyi.c +++ b/src/vendor/cigraph/src/games/erdos_renyi.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -26,317 +26,55 @@ #include "igraph_random.h" #include "core/interruption.h" +#include "internal/utils.h" #include "math/safe_intop.h" +#include "misc/graphicality.h" #include "random/random_internal.h" /** - * \section about_games + * \section about_erdos_renyi * - * Games are random graph generators, i.e. they generate a different - * graph every time they are called. igraph includes many such generators. - * Some implement stochastic graph construction processes inspired by real-world - * mechanics, such as preferential attachment, while others are designed to - * produce graphs with certain used properties (e.g. fixed number of edges, - * fixed degrees, etc.) - */ - -/* This implementation is used only with very large vertex counts, above - * sqrt(MAX_EXACT_REAL) ~ 100 million, when the default implementation would - * fail due to overflow. While this version avoids overflow and uses less memory, - * it is also slower than the default implementation. */ -static igraph_error_t gnp_large( - igraph_t *graph, igraph_integer_t n, igraph_real_t p, - igraph_bool_t directed, igraph_bool_t loops, igraph_integer_t ecount_estimate -) { - - igraph_vector_int_t edges; - int iter = 0; - - /* Necessitated by floating point arithmetic used in the implementation. */ - if (n >= IGRAPH_MAX_EXACT_REAL) { - IGRAPH_ERROR("Number of vertices is too large.", IGRAPH_EOVERFLOW); - } - - if (ecount_estimate > IGRAPH_ECOUNT_MAX) { - ecount_estimate = IGRAPH_ECOUNT_MAX; - } - - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount_estimate)); - - for (igraph_integer_t i=0; i < n; i++) { - igraph_integer_t j = directed ? 0 : i; - - while (true) { - igraph_real_t gap = RNG_GEOM(p); - - /* This formulation not only terminates the loop when necessary, - * but also protects against overflow when 'p' is very small - * and 'gap' becomes very large, perhaps larger than representable - * in an igraph_integer_t. */ - if (gap >= n - j) { - break; - } - - j += gap; - - if (loops || i != j) { - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j)); - } - - j++; - - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); - } - } - - 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_gnp - * \brief Generates a random (Erdős-Rényi) graph with fixed edge probabilities. - * - * In the G(n, p) Erdős-Rényi model, also known as the Gilbert model, - * or Bernoulli random graph, a graph with \p n vertices is generated such that - * every possible edge is included in the graph independently with probability - * \p p. This is equivalent to a maximum entropy random graph model model with - * a constraint on the \em expected edge count. Setting p = 1/2 - * generates all graphs on \p n vertices with the same probability. - * - * - * The expected mean degree of the graph is approximately p n; - * set p = k/n when a mean degree of approximately \c k is - * desired. More precisely, the expected mean degree is p(n-1) - * in (undirected or directed) graphs without self-loops, - * p(n+1) in undirected graphs with self-loops, and - * p n in directed graphs with self-loops. - * - * \param graph Pointer to an uninitialized graph object. - * \param n The number of vertices in the graph. - * \param p The probability of the existence of an edge in the graph. - * \param directed Whether to generate a directed graph. - * \param loops Whether to generate self-loops. - * \return Error code: - * \c IGRAPH_EINVAL: invalid \p n or \p p 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. - * - * \sa \ref igraph_erdos_renyi_game_gnm() to generate random graphs with - * a sharply fixed edge count; \ref igraph_chung_lu_game() and - * \ref igraph_static_fitness_game() to generate random graphs with a - * fixed expected degree sequence; \ref igraph_bipartite_game_gnm() for the - * bipartite version of this model; \ref igraph_barabasi_game() and - * \ref igraph_growing_random_game() for other commonly used random graph models. + * + * There are two classic random graph models referred to as the Erdős-Rényi + * random graph, or sometimes simply \em the random graph. Both fix the vertex + * count n, but while the G(n,m) model prescribes precisely m edges, the G(n,p) + * model connects all vertex pairs independently with probability p. While + * these models look superficially different, when n is large they behave in + * a similar manner. G(n,m) graphs have a density of exactly + * p = m / m_max, while G(n,p) graphs have m = p m_max + * edges on \em average, where \c m_max is the number of vertex pairs. Indeed, + * these two models turns out to be two sides of the same coin: both can be + * understood as maximum entropy models with a constraint on the number of + * edges. The G(n,m) is obtained from a sharp constraint, while G(n,p) from + * an average constraint (soft constraint). + * * - * \example examples/simple/igraph_erdos_renyi_game_gnp.c + * + * The maximum entropy framework allows for rigorous generalizations of these + * models to various scenarios, of which igraph supports many, such as models + * defined over directed graphs, bipartite graphs, multigraphs, or even over + * edge-labelled graphs. Constraining edge counts between various subsets of + * vertices yields further families of related models, such as + * \ref igraph_sbm_game() (given connection probabilities between categories) + * or \ref igraph_degree_sequence_game() (given incident edge counts, i.e. + * degrees, for each vertex). + * */ -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 -) { - /* This function uses doubles in its `s` vector, and for `maxedges` and `last`. - * This is because on a system with 32-bit ints, maxedges will be larger than - * IGRAPH_INTEGER_MAX and this will cause overflows when calculating `from` and `to` - * for tests on large graphs. - */ - igraph_integer_t no_of_nodes = n; - igraph_real_t no_of_nodes_real = (igraph_real_t) no_of_nodes; /* for divisions below */ - igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_vector_t s = IGRAPH_VECTOR_NULL; - int iter = 0; - - if (n < 0) { - IGRAPH_ERROR("Invalid number of vertices for G(n,p) model.", IGRAPH_EINVAL); - } - if (p < 0.0 || p > 1.0) { - IGRAPH_ERROR("Invalid probability given for G(n,p) model.", IGRAPH_EINVAL); - } - - if (p == 0.0 || no_of_nodes == 0) { - IGRAPH_CHECK(igraph_empty(graph, n, directed)); - } else if (p == 1.0) { - IGRAPH_CHECK(igraph_full(graph, n, directed, loops)); - } else { - igraph_real_t maxedges = n, last; - igraph_integer_t ecount_estimate, ecount; - - if (directed && loops) { - maxedges *= n; - } else if (directed && !loops) { - maxedges *= (n - 1); - } else if (!directed && loops) { - maxedges *= (n + 1) / 2.0; - } else { - maxedges *= (n - 1) / 2.0; - } - - IGRAPH_CHECK(igraph_i_safe_floor(maxedges * p * 1.1, &ecount_estimate)); - - if (maxedges > IGRAPH_MAX_EXACT_REAL) { - /* Use a slightly slower, but overflow-free implementation. */ - return gnp_large(graph, n, p, directed, loops, ecount_estimate); - } - - IGRAPH_VECTOR_INIT_FINALLY(&s, 0); - IGRAPH_CHECK(igraph_vector_reserve(&s, ecount_estimate)); - - last = RNG_GEOM(p); - while (last < maxedges) { - IGRAPH_CHECK(igraph_vector_push_back(&s, last)); - last += RNG_GEOM(p); - last += 1; - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); - } - - ecount = igraph_vector_size(&s); - if (ecount > IGRAPH_ECOUNT_MAX) { - IGRAPH_ERROR("Overflow in number of edges.", IGRAPH_EOVERFLOW); - } - - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount)); - - iter = 0; - if (directed && loops) { - for (igraph_integer_t i = 0; i < ecount; i++) { - igraph_integer_t to = floor(VECTOR(s)[i] / no_of_nodes_real); - igraph_integer_t from = VECTOR(s)[i] - to * no_of_nodes_real; - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); - } - } else if (directed && !loops) { - for (igraph_integer_t i = 0; i < ecount; i++) { - igraph_integer_t to = floor(VECTOR(s)[i] / no_of_nodes_real); - igraph_integer_t from = VECTOR(s)[i] - to * no_of_nodes_real; - if (from == to) { - to = no_of_nodes - 1; - } - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); - } - } else if (!directed && loops) { - for (igraph_integer_t i = 0; i < ecount; i++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) - 1) / 2); - igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to + 1)) / 2; - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); - } - } else { /* !directed && !loops */ - for (igraph_integer_t i = 0; i < ecount; i++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) + 1) / 2); - igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to - 1)) / 2; - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); - } - } - - igraph_vector_destroy(&s); - IGRAPH_FINALLY_CLEAN(1); - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); - } - return IGRAPH_SUCCESS; -} -/** - * \ingroup generators - * \function igraph_iea_game - * \brief Generates a random multigraph through independent edge assignment. - * - * \experimental - * - * This model generates random multigraphs on \p n vertices with \p m edges - * through independent edge assignment (IEA). Each of the \p m edges is assigned - * uniformly at random to an \em ordered vertex pair, independently of each - * other. - * - * - * This model does not sample multigraphs uniformly. Undirected graphs are - * generated with probability proportional to - * - * - * (prod_(i<j) A_ij ! prod_i A_ii !!)^(-1), - * - * - * where \c A denotes the adjacency matrix and !! denotes - * the double factorial. Here \c A is assumed to have twice the number of - * self-loops on its diagonal. The corresponding expression for directed - * graphs is - * - * - * (prod_(i,j) A_ij !)^(-1). - * - * - * Thus the probability of all simple graphs (which only have 0s and 1s in - * the adjacency matrix) is the same, while that of non-simple ones depends - * on their edge and self-loop multiplicities. - * - * - * An alternative way to think of this model is that it performs uniform - * sampling of \em edge-labeled graphs, i.e. graphs in which not only vertices, - * but also edges carry unique identities and are distinguishable. - * - * \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 Whether to generate a directed graph. - * \param loops Whether to generate self-loops. - * \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. - * - * \sa \ref igraph_erdos_renyi_game_gnm() to uniformly sample graphs with - * a given number of vertices and edges. - */ -igraph_error_t igraph_iea_game( +static igraph_error_t iea_game( igraph_t *graph, - igraph_integer_t n, igraph_integer_t m, + igraph_int_t n, igraph_int_t m, igraph_bool_t directed, igraph_bool_t loops) { igraph_vector_int_t edges; int iter = 0; - if (n < 0) { - IGRAPH_ERROR("Invalid number of vertices for IEA model.", IGRAPH_EINVAL); - } - if (m < 0 || m > IGRAPH_ECOUNT_MAX) { - IGRAPH_ERROR("Invalid number of edges for IEA model.", IGRAPH_EINVAL); - } - - /* Special cases of "too many edges" that also apply to multigraphs: - * - The null graph cannot have edges. - * - The singleton graph canot have edges unless loops are allowed. - */ - if (m > 0 && ((n == 0) || (!loops && n == 1))) { - IGRAPH_ERROR( - "Too many edges requested compared to the number of vertices for IEA model.", - IGRAPH_EINVAL); - } - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); - for (igraph_integer_t i = 0; i < m; i++) { - igraph_integer_t from, to; + for (igraph_int_t i = 0; i < m; i++) { + igraph_int_t from, to; from = RNG_INTEGER(0, n - 1); if (loops) { to = RNG_INTEGER(0, n - 1); @@ -358,11 +96,10 @@ igraph_error_t igraph_iea_game( return IGRAPH_SUCCESS; } - /* Uniform sampling of multigraphs from G(n,m) */ static igraph_error_t gnm_multi( igraph_t *graph, - igraph_integer_t n, igraph_integer_t m, + igraph_int_t n, igraph_int_t m, igraph_bool_t directed, igraph_bool_t loops) { /* Conceptually, uniform multigraph sampling works as follows: @@ -391,8 +128,8 @@ static igraph_error_t gnm_multi( */ igraph_vector_int_t edges; - igraph_integer_t nrow, ncol; - igraph_integer_t last; /* column index of last element in last row */ + igraph_int_t nrow, ncol; + igraph_int_t last; /* column index of last element in last row */ int iter = 0; /* Constraining n and m by IGRAPH_VCOUNT_MAX and IGRAPH_ECOUNT_MAX, @@ -410,13 +147,13 @@ static igraph_error_t gnm_multi( if (directed && loops) { nrow = ncol = n; last = ncol-1; - for (igraph_integer_t i=0; i < m; i++) { + for (igraph_int_t i=0; i < m; i++) { while (true) { - igraph_integer_t r = RNG_INTEGER(0, nrow-1); - igraph_integer_t c = RNG_INTEGER(0, ncol-1); + igraph_int_t r = RNG_INTEGER(0, nrow-1); + igraph_int_t c = RNG_INTEGER(0, ncol-1); if (r >= n) { - igraph_integer_t j = (r - n) * ncol + c; + igraph_int_t j = (r - n) * ncol + c; if (IGRAPH_UNLIKELY(j >= i)) continue; /* rejection sampling */ VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; @@ -439,13 +176,13 @@ static igraph_error_t gnm_multi( nrow = n; ncol = n-1; last = ncol-1; - for (igraph_integer_t i=0; i < m; i++) { + for (igraph_int_t i=0; i < m; i++) { while (true) { - igraph_integer_t r = RNG_INTEGER(0, nrow-1); - igraph_integer_t c = RNG_INTEGER(0, ncol-1); + igraph_int_t r = RNG_INTEGER(0, nrow-1); + igraph_int_t c = RNG_INTEGER(0, ncol-1); if (r >= n) { - igraph_integer_t j = (r - n) * ncol + c; + igraph_int_t j = (r - n) * ncol + c; if (IGRAPH_UNLIKELY(j >= i)) continue; /* rejection sampling */ VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; @@ -474,13 +211,13 @@ static igraph_error_t gnm_multi( nrow = n; ncol = n+1; last = ncol-1; - for (igraph_integer_t i=0; i < m; i++) { + for (igraph_int_t i=0; i < m; i++) { while (true) { - igraph_integer_t r = RNG_INTEGER(0, nrow-1); - igraph_integer_t c = RNG_INTEGER(0, ncol-1); + igraph_int_t r = RNG_INTEGER(0, nrow-1); + igraph_int_t c = RNG_INTEGER(0, ncol-1); if (r >= n) { - igraph_integer_t j = (r - n) * ncol + c; + igraph_int_t j = (r - n) * ncol + c; if (IGRAPH_UNLIKELY(j >= 2*i)) continue; /* rejection sampling */ VECTOR(edges)[2*i] = VECTOR(edges)[2*(j/2)]; VECTOR(edges)[2*i+1] = VECTOR(edges)[2*(j/2)+1]; @@ -510,13 +247,13 @@ static igraph_error_t gnm_multi( nrow = n; ncol = n-1; last = ncol-1; - for (igraph_integer_t i=0; i < m; i++) { + for (igraph_int_t i=0; i < m; i++) { while (true) { - igraph_integer_t r = RNG_INTEGER(0, nrow-1); - igraph_integer_t c = RNG_INTEGER(0, ncol-1); + igraph_int_t r = RNG_INTEGER(0, nrow-1); + igraph_int_t c = RNG_INTEGER(0, ncol-1); if (r >= n) { - igraph_integer_t j = (r - n) * ncol + c; + igraph_int_t j = (r - n) * ncol + c; if (IGRAPH_UNLIKELY(j >= 2*i)) continue; /* rejection sampling */ VECTOR(edges)[2*i] = VECTOR(edges)[2*(j/2)]; VECTOR(edges)[2*i+1] = VECTOR(edges)[2*(j/2)+1]; @@ -551,21 +288,126 @@ static igraph_error_t gnm_multi( return IGRAPH_SUCCESS; } -/** - * \ingroup generators - * \function igraph_erdos_renyi_game_gnm - * \brief Generates a random (Erdős-Rényi) graph with a fixed number of edges. - * - * In the G(n, m) Erdős-Rényi model, a graph with \p n vertices - * and \p m edges is generated uniformly at random. - * - * \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 Whether to generate a directed graph. - * \param loops Whether to generate self-loops. - * \param multiple Whether it is allowed to generate more than one edge between - * the same pair of vertices. +/* Uniform sampling of simple graphs (with loops) from G(n,m) */ +static igraph_error_t gnm_simple( + igraph_t *graph, + igraph_int_t n, igraph_int_t m, + igraph_bool_t directed, igraph_bool_t loops, + igraph_bool_t edge_labeled) { + + /* This function uses doubles in its `s` vector, and for `maxedges` and `last`. + * This is because on a system with 32-bit ints, maxedges will be larger than + * IGRAPH_INTEGER_MAX and this will cause overflows when calculating `from` and `to` + * for tests on large graphs. This is also why we need a 'real' version of random_sample. + */ + igraph_real_t n_real = (igraph_real_t) n; /* for divisions below */ + igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; + igraph_vector_t s = IGRAPH_VECTOR_NULL; + int iter = 0; + + + igraph_real_t maxedges = n; + if (directed && loops) { + maxedges *= n; + } else if (directed && !loops) { + maxedges *= (n - 1); + } else if (!directed && loops) { + maxedges *= (n + 1) / 2.0; + } else { + maxedges *= (n - 1) / 2.0; + } + + if (m > maxedges) { + IGRAPH_ERROR( + "Too many edges requested compared to the number of vertices for G(n,m) model.", + IGRAPH_EINVAL); + } + + if (maxedges == m && ! edge_labeled) { + /* TODO: Cannot use igraph_full() when edge_labeled as we must shuffle edges. */ + IGRAPH_CHECK(igraph_full(graph, n, directed, loops)); + } else { + igraph_int_t slen; + + IGRAPH_VECTOR_INIT_FINALLY(&s, 0); + IGRAPH_CHECK(igraph_i_random_sample_real(&s, 0, maxedges - 1, m)); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, igraph_vector_size(&s) * 2)); + + slen = igraph_vector_size(&s); + if (directed && loops) { + for (igraph_int_t i = 0; i < slen; i++) { + igraph_int_t to = trunc(VECTOR(s)[i] / n_real); + igraph_int_t from = VECTOR(s)[i] - to * n_real; + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else if (directed && !loops) { + for (igraph_int_t i = 0; i < slen; i++) { + igraph_int_t from = trunc(VECTOR(s)[i] / (n_real - 1)); + igraph_int_t to = VECTOR(s)[i] - from * (n_real - 1); + if (from == to) { + to = n - 1; + } + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else if (!directed && loops) { + for (igraph_int_t i = 0; i < slen; i++) { + igraph_int_t to = trunc((sqrt(8 * VECTOR(s)[i] + 1) - 1) / 2); + igraph_int_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to + 1)) / 2; + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } else { /* !directed && !loops */ + for (igraph_int_t i = 0; i < slen; i++) { + igraph_int_t to = trunc((sqrt(8 * VECTOR(s)[i] + 1) + 1) / 2); + igraph_int_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to - 1)) / 2; + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } + + igraph_vector_destroy(&s); + IGRAPH_FINALLY_CLEAN(1); + + if (edge_labeled) { + IGRAPH_CHECK(igraph_i_vector_int_shuffle_pairs(&edges)); + } + + 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 + * \brief Generates a random (Erdős-Rényi) graph with a fixed number of edges. + * + * In the G(n, m) Erdős-Rényi model, a graph with \p n vertices + * and \p m edges is generated uniformly at random. + * + * \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 Whether to generate a directed graph. + * \param allowed_edge_types Controls whether multi-edges and self-loops + * are generated. See \ref igraph_edge_type_sw_t. + * \param edge_labeled If true, the sampling is done uniformly from the set + * of ordered edge lists. See \ref igraph_iea_game() for more information. + * Set this to \c false to select the classic Erdős-Rényi model. + * The constants \c IGRAPH_EDGE_UNLABELED and \c IGRAPH_EDGE_LABELED + * may be used instead of \c false and \c true for better readability. * \return Error code: * \c IGRAPH_EINVAL: invalid \p n or \p m parameter. * \c IGRAPH_ENOMEM: there is not enough memory for the operation. @@ -585,19 +427,13 @@ static igraph_error_t gnm_multi( * \example examples/simple/igraph_erdos_renyi_game_gnm.c */ 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 multiple -) { + igraph_t *graph, + igraph_int_t n, igraph_int_t m, + igraph_bool_t directed, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled) { - /* This function uses doubles in its `s` vector, and for `maxedges` and `last`. - * This is because on a system with 32-bit ints, maxedges will be larger than - * IGRAPH_INTEGER_MAX and this will cause overflows when calculating `from` and `to` - * for tests on large graphs. This is also why we need a 'real' version of random_sample. - */ - igraph_real_t n_real = (igraph_real_t) n; /* for divisions below */ - igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_vector_t s = IGRAPH_VECTOR_NULL; - int iter = 0; + igraph_bool_t loops, multiple; /* The multigraph implementation relies on the below checks to avoid overflow. */ if (n < 0 || n > IGRAPH_VCOUNT_MAX) { @@ -607,9 +443,11 @@ igraph_error_t igraph_erdos_renyi_game_gnm( IGRAPH_ERROR("Invalid number of edges for G(n,m) model.", IGRAPH_EINVAL); } + IGRAPH_CHECK(igraph_i_edge_type_to_loops_multiple(allowed_edge_types, &loops, &multiple)); + /* Special cases of "too many edges" that also apply to multigraphs: * - The null graph cannot have edges. - * - The singleton graph canot have edges unless loops are allowed. + * - The singleton graph cannot have edges unless loops are allowed. */ if (m > 0 && ((n == 0) || (!loops && n == 1))) { IGRAPH_ERROR( @@ -621,70 +459,381 @@ igraph_error_t igraph_erdos_renyi_game_gnm( return igraph_empty(graph, n, directed); } + if (edge_labeled) { + if (multiple) { + return iea_game(graph, n, m, directed, loops); + } else { + return gnm_simple(graph, n, m, directed, loops, /*edge_labeled=*/ true); + } + } else { + if (multiple) { + return gnm_multi(graph, n, m, directed, loops); + } else { + return gnm_simple(graph, n, m, directed, loops, /*edge_labeled=*/ false); + } + } +} + + +/** + * \ingroup generators + * \function igraph_iea_game + * \brief Generates a random multigraph through independent edge assignment. + * + * \experimental + * + * This model generates random multigraphs on \p n vertices with \p m edges + * through independent edge assignment (IEA). Each of the \p m edges is assigned + * uniformly at random to an \em ordered vertex pair, independently of each + * other. + * + * + * This model does not sample multigraphs uniformly. Undirected graphs are + * generated with probability proportional to + * + * + * (prod_(i<j) A_ij ! prod_i A_ii !!)^(-1), + * + * + * where \c A denotes the adjacency matrix and !! denotes + * the double factorial. Here \c A is assumed to have twice the number of + * self-loops on its diagonal. The corresponding expression for directed + * graphs is + * + * + * (prod_(i,j) A_ij !)^(-1). + * + * + * Thus the probability of all simple graphs (which only have 0s and 1s in + * the adjacency matrix) is the same, while that of non-simple ones depends + * on their edge and self-loop multiplicities. + * + * + * An alternative way to think of this model is that it performs uniform + * sampling of \em edge-labeled graphs, i.e. graphs in which not only vertices, + * but also edges carry unique identities and are distinguishable. + * + * \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 Whether to generate a directed graph. + * \param loops Whether to generate self-loops. + * \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. + * + * \sa \ref igraph_erdos_renyi_game_gnm() to uniformly sample graphs with + * a given number of vertices and edges. + */ +igraph_error_t igraph_iea_game( + igraph_t *graph, + igraph_int_t n, igraph_int_t m, + igraph_bool_t directed, igraph_bool_t loops) { + + igraph_edge_type_sw_t allowed_edge_types = IGRAPH_MULTI_SW; + if (loops) { + allowed_edge_types |= IGRAPH_LOOPS_SW; + } + return igraph_erdos_renyi_game_gnm(graph, n, m, directed, allowed_edge_types, true); +} + +/* This G(n,p) implementation is used only with very large vertex counts, above + * sqrt(MAX_EXACT_REAL) ~ 100 million, when the default implementation would + * fail due to overflow. While this version avoids overflow and uses less memory, + * it is also slower than the default implementation. + * + * This function expects that when multiple=true, the p parameter has already + * been transformed by p = p / (1 + p). This is currently done by the caller. + */ +static igraph_error_t gnp_large( + igraph_t *graph, igraph_int_t n, igraph_real_t p, + igraph_bool_t directed, igraph_bool_t loops, igraph_bool_t multiple, + igraph_int_t ecount_estimate +) { + + igraph_vector_int_t edges; + int iter = 0; + + /* Necessitated by floating point arithmetic used in the implementation. */ + if (n >= IGRAPH_MAX_EXACT_REAL) { + IGRAPH_ERROR("Number of vertices is too large.", IGRAPH_EOVERFLOW); + } + + if (ecount_estimate > IGRAPH_ECOUNT_MAX) { + ecount_estimate = IGRAPH_ECOUNT_MAX; + } + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount_estimate)); + + for (igraph_int_t i=0; i < n; i++) { + igraph_int_t j = directed ? 0 : i; + + while (true) { + igraph_real_t gap = RNG_GEOM(p); + + /* This formulation not only terminates the loop when necessary, + * but also protects against overflow when 'p' is very small + * and 'gap' becomes very large, perhaps larger than representable + * in an igraph_int_t. */ + if (gap >= n - j) { + break; + } + + j += gap; + + if (loops || i != j) { + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j)); + } + + j += ! multiple; /* 1 for simple graph, 0 for multigraph */ + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + } + + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + +static igraph_error_t gnp_edge_labeled( + igraph_t *graph, + igraph_int_t n, igraph_real_t p, + igraph_bool_t directed, + igraph_bool_t loops, igraph_bool_t multiple) { + if (multiple) { - return gnm_multi(graph, n, m, directed, loops); + igraph_real_t maxedges = n; + + if (directed && loops) { + maxedges *= n; + } else if (directed && !loops) { + maxedges *= (n - 1); + } else if (!directed && loops) { + maxedges *= (n + 1) / 2.0; + } else { + maxedges *= (n - 1) / 2.0; + } + + igraph_real_t m; + do { + m = RNG_GEOM( 1.0 / (1.0 + maxedges * p) ); + } while (m > (igraph_real_t) IGRAPH_INTEGER_MAX); + + return iea_game(graph, n, m, directed, loops); + } else { + IGRAPH_ERROR("The edge-labeled G(n,p) model is not yet implemented for graphs without multi-edges.", + IGRAPH_UNIMPLEMENTED); } +} - igraph_real_t maxedges = n; - if (directed && loops) { - maxedges *= n; - } else if (directed && !loops) { - maxedges *= (n - 1); - } else if (!directed && loops) { - maxedges *= (n + 1) / 2.0; +/** + * \ingroup generators + * \function igraph_erdos_renyi_game_gnp + * \brief Generates a random (Erdős-Rényi) graph with fixed edge probabilities. + * + * In the G(n, p) Erdős-Rényi model, also known as the Gilbert model, + * or Bernoulli random graph, a graph with \p n vertices is generated such that + * every possible edge is included in the graph independently with probability + * \p p. This is equivalent to a maximum entropy random graph model model with + * a constraint on the \em expected edge count. The maximum entropy view allows + * for extending the model to multigraphs, as discussed by Park and Newman (2004), + * section III.D. In this case, \p p is interpreted as the expected number of + * edges between any vertex pair. + * + * + * Setting p = 1/2 and multiple = false generates all + * graphs without multi-edges on \p n vertices with the same probability. + * + * + * For both simple and multigraphs, the expected mean degree of the graph is + * approximately p n; set p = k/n when a mean degree + * of approximately \c k is desired. More precisely, the expected mean degree is + * p(n-1) in (undirected or directed) graphs without self-loops, + * p(n+1) in undirected graphs with self-loops, and + * p n in directed graphs with self-loops. + * + * + * When generating multigraphs, the distribution of the edge multiplicities is + * geometric, i.e. the probability of finding \c m edges between two vertices + * is q (1-q)^m, where q = 1 / (1+p). + * + * + * This function uses the sequential geometric sampling technique described in + * Batagelj and Brandes (2005), with a modification to handle multigraphs. + * + * + * References: + * + * + * J. Park and M. E. J. Newman: "Statistical Mechanics of Networks". + * Phys. Rev. E 70, 066117 (2004). + * https://doi.org/10.1103/PhysRevE.70.066117 + * + * + * V. Batagelj and U. Brandes: "Efficient Generation of Large Random Networks". + * Phys. Rev. E 71, 036113 (2005). + * https://doi.org/10.1103/PhysRevE.71.036113 + * + * \param graph Pointer to an uninitialized graph object. + * \param n The number of vertices in the graph. + * \param p The expected number of edges between any vertex pair. + * When multi-edges are disallowed, this is equivalent to the probability + * of having a connection between any two vertices. + * \param directed Whether to generate a directed graph. + * \param allowed_edge_types Controls whether multi-edges and self-loops + * are generated. See \ref igraph_edge_type_sw_t. + * \param edge_labeled If true, the model is defined over the set of ordered + * edge lists, i.e. over the set of edge-labeled graphs. Set it to + * \c false to select the classic Erdős-Rényi model. + * The constants \c IGRAPH_EDGE_UNLABELED and \c IGRAPH_EDGE_LABELED + * may be used instead of \c false and \c true for better readability. + * \return Error code: + * \c IGRAPH_EINVAL: invalid \p n or \p p 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. + * + * \sa \ref igraph_erdos_renyi_game_gnm() to generate random graphs with + * a sharply fixed edge count; \ref igraph_chung_lu_game() and + * \ref igraph_static_fitness_game() to generate random graphs with a + * fixed expected degree sequence; \ref igraph_bipartite_game_gnm() for the + * bipartite version of this model; \ref igraph_barabasi_game() and + * \ref igraph_growing_random_game() for other commonly used random graph models. + * + * \example examples/simple/igraph_erdos_renyi_game_gnp.c + */ +igraph_error_t igraph_erdos_renyi_game_gnp( + igraph_t *graph, + igraph_int_t n, igraph_real_t p, + igraph_bool_t directed, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled) { + + /* This function uses doubles in its `s` vector, and for `maxedges` and `last`. + * This is because on a system with 32-bit ints, maxedges will be larger than + * IGRAPH_INTEGER_MAX and this will cause overflows when calculating `from` and `to` + * for tests on large graphs. + */ + igraph_int_t no_of_nodes = n; + igraph_real_t no_of_nodes_real = (igraph_real_t) no_of_nodes; /* for divisions below */ + igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; + igraph_vector_t s = IGRAPH_VECTOR_NULL; + igraph_bool_t loops, multiple; + int iter = 0; + + if (n < 0) { + IGRAPH_ERROR("Invalid number of vertices for G(n,p) model.", IGRAPH_EINVAL); + } + + IGRAPH_CHECK(igraph_i_edge_type_to_loops_multiple(allowed_edge_types, &loops, &multiple)); + + if (multiple) { + if (p < 0.0) { + IGRAPH_ERROR("Invalid expected edge multiplicity given for G(n,p) multigraph model.", IGRAPH_EINVAL); + } } else { - maxedges *= (n - 1) / 2.0; + if (p < 0.0 || p > 1.0) { + IGRAPH_ERROR("Invalid probability given for G(n,p) model.", IGRAPH_EINVAL); + } } - if (m > maxedges) { - IGRAPH_ERROR( - "Too many edges requested compared to the number of vertices for G(n,m) model.", - IGRAPH_EINVAL); + if (edge_labeled) { + return gnp_edge_labeled(graph, n, p, directed, loops, multiple); + } + + if (multiple) { + /* Convert the expected edge count to the appropriate probability parameter + * of the geometric distribution when sampling lengths of runs of 0s in the + * adjacency matrix. */ + p = p / (1 + p); } - if (maxedges == m) { + if (p == 0.0 || no_of_nodes == 0) { + IGRAPH_CHECK(igraph_empty(graph, n, directed)); + } else if (! multiple && p == 1.0) { IGRAPH_CHECK(igraph_full(graph, n, directed, loops)); } else { - igraph_integer_t slen; + igraph_real_t maxedges = n, last; + igraph_int_t ecount_estimate, ecount; + + if (directed && loops) { + maxedges *= n; + } else if (directed && !loops) { + maxedges *= (n - 1); + } else if (!directed && loops) { + maxedges *= (n + 1) / 2.0; + } else { + maxedges *= (n - 1) / 2.0; + } + + IGRAPH_CHECK(igraph_i_safe_floor(maxedges * p * 1.1, &ecount_estimate)); + + if (maxedges > IGRAPH_MAX_EXACT_REAL) { + /* Use a slightly slower, but overflow-free implementation. */ + return gnp_large(graph, n, p, directed, loops, multiple, ecount_estimate); + } IGRAPH_VECTOR_INIT_FINALLY(&s, 0); - IGRAPH_CHECK(igraph_i_random_sample_real(&s, 0, maxedges - 1, m)); + IGRAPH_CHECK(igraph_vector_reserve(&s, ecount_estimate)); + + last = RNG_GEOM(p); + while (last < maxedges) { + IGRAPH_CHECK(igraph_vector_push_back(&s, last)); + last += RNG_GEOM(p); + last += ! multiple; /* 1 for simple graph, 0 for multigraph */ + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + + ecount = igraph_vector_size(&s); + if (ecount > IGRAPH_ECOUNT_MAX) { + IGRAPH_ERROR("Overflow in number of edges.", IGRAPH_EOVERFLOW); + } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, igraph_vector_size(&s) * 2)); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount)); - slen = igraph_vector_size(&s); + iter = 0; if (directed && loops) { - for (igraph_integer_t i = 0; i < slen; i++) { - igraph_integer_t to = floor(VECTOR(s)[i] / n_real); - igraph_integer_t from = VECTOR(s)[i] - to * n_real; + for (igraph_int_t i = 0; i < ecount; i++) { + igraph_int_t to = trunc(VECTOR(s)[i] / no_of_nodes_real); + igraph_int_t from = VECTOR(s)[i] - to * no_of_nodes_real; igraph_vector_int_push_back(&edges, from); igraph_vector_int_push_back(&edges, to); IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } } else if (directed && !loops) { - for (igraph_integer_t i = 0; i < slen; i++) { - igraph_integer_t from = floor(VECTOR(s)[i] / (n_real - 1)); - igraph_integer_t to = VECTOR(s)[i] - from * (n_real - 1); + for (igraph_int_t i = 0; i < ecount; i++) { + igraph_int_t to = trunc(VECTOR(s)[i] / no_of_nodes_real); + igraph_int_t from = VECTOR(s)[i] - to * no_of_nodes_real; if (from == to) { - to = n - 1; + to = no_of_nodes - 1; } igraph_vector_int_push_back(&edges, from); igraph_vector_int_push_back(&edges, to); IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } } else if (!directed && loops) { - for (igraph_integer_t i = 0; i < slen; i++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) - 1) / 2); - igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to + 1)) / 2; + for (igraph_int_t i = 0; i < ecount; i++) { + igraph_int_t to = trunc((sqrt(8 * VECTOR(s)[i] + 1) - 1) / 2); + igraph_int_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to + 1)) / 2; igraph_vector_int_push_back(&edges, from); igraph_vector_int_push_back(&edges, to); IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } } else { /* !directed && !loops */ - for (igraph_integer_t i = 0; i < slen; i++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[i] + 1) + 1) / 2); - igraph_integer_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to - 1)) / 2; + for (igraph_int_t i = 0; i < ecount; i++) { + igraph_int_t to = trunc((sqrt(8 * VECTOR(s)[i] + 1) + 1) / 2); + igraph_int_t from = VECTOR(s)[i] - (((igraph_real_t)to) * (to - 1)) / 2; igraph_vector_int_push_back(&edges, from); igraph_vector_int_push_back(&edges, to); IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); diff --git a/src/vendor/cigraph/src/games/establishment.c b/src/vendor/cigraph/src/games/establishment.c index 9ed1daabfda..5bbf08ea753 100644 --- a/src/vendor/cigraph/src/games/establishment.c +++ b/src/vendor/cigraph/src/games/establishment.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -54,13 +54,13 @@ * Time complexity: O(|V|*k*log(|V|)), |V| is the number of vertices * and k is the \p k parameter. */ -igraph_error_t igraph_establishment_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t types, igraph_integer_t k, +igraph_error_t igraph_establishment_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t types, igraph_int_t k, const igraph_vector_t *type_dist, const igraph_matrix_t *pref_matrix, igraph_bool_t directed, igraph_vector_int_t *node_type_vec) { - igraph_integer_t i, j; + igraph_int_t i, j; igraph_vector_int_t edges; igraph_vector_t cumdist; igraph_vector_int_t potneis; @@ -147,16 +147,16 @@ igraph_error_t igraph_establishment_game(igraph_t *graph, igraph_integer_t nodes for (i = 0; i < nodes; i++) { igraph_real_t uni = RNG_UNIF(0, maxcum); - igraph_integer_t type; + igraph_int_t type; igraph_vector_binsearch(&cumdist, uni, &type); VECTOR(*nodetypes)[i] = type - 1; } for (i = k; i < nodes; i++) { - igraph_integer_t type1 = VECTOR(*nodetypes)[i]; + igraph_int_t type1 = VECTOR(*nodetypes)[i]; igraph_random_sample(&potneis, 0, i - 1, k); for (j = 0; j < k; j++) { - igraph_integer_t type2 = VECTOR(*nodetypes)[VECTOR(potneis)[j]]; + igraph_int_t type2 = VECTOR(*nodetypes)[VECTOR(potneis)[j]]; if (RNG_UNIF01() < MATRIX(*pref_matrix, type1, type2)) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, VECTOR(potneis)[j])); diff --git a/src/vendor/cigraph/src/games/forestfire.c b/src/vendor/cigraph/src/games/forestfire.c index 11baf7a9218..9d85e94d3d4 100644 --- a/src/vendor/cigraph/src/games/forestfire.c +++ b/src/vendor/cigraph/src/games/forestfire.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -34,12 +34,12 @@ typedef struct igraph_i_forest_fire_data_t { igraph_vector_int_t *inneis; igraph_vector_int_t *outneis; - igraph_integer_t no_of_nodes; + igraph_int_t no_of_nodes; } igraph_i_forest_fire_data_t; static void igraph_i_forest_fire_free(igraph_i_forest_fire_data_t *data) { - for (igraph_integer_t i = 0; i < data->no_of_nodes; i++) { + for (igraph_int_t i = 0; i < data->no_of_nodes; i++) { igraph_vector_int_destroy(data->inneis + i); igraph_vector_int_destroy(data->outneis + i); } @@ -103,17 +103,17 @@ static void igraph_i_forest_fire_free(igraph_i_forest_fire_data_t *data) { * Time complexity: TODO. */ -igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes, +igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_int_t nodes, igraph_real_t fw_prob, igraph_real_t bw_factor, - igraph_integer_t pambs, igraph_bool_t directed) { + igraph_int_t pambs, igraph_bool_t directed) { igraph_vector_int_t visited; - igraph_integer_t no_of_nodes = nodes, actnode, i; + igraph_int_t no_of_nodes = nodes, actnode, i; igraph_vector_int_t edges; igraph_vector_int_t *inneis, *outneis; igraph_i_forest_fire_data_t data; igraph_dqueue_int_t neiq; - igraph_integer_t ambs = pambs; + igraph_int_t ambs = pambs; igraph_real_t param_geom_out = 1 - fw_prob; igraph_real_t param_geom_in = 1 - fw_prob * bw_factor; @@ -181,29 +181,29 @@ igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes, /* Choose ambassador(s) */ for (i = 0; i < ambs; i++) { - igraph_integer_t a = RNG_INTEGER(0, actnode - 1); + igraph_int_t a = RNG_INTEGER(0, actnode - 1); ADD_EDGE_TO(a); } while (!igraph_dqueue_int_empty(&neiq)) { - igraph_integer_t actamb = igraph_dqueue_int_pop(&neiq); + igraph_int_t actamb = igraph_dqueue_int_pop(&neiq); igraph_vector_int_t *outv = outneis + actamb; igraph_vector_int_t *inv = inneis + actamb; - igraph_integer_t no_in = igraph_vector_int_size(inv); - igraph_integer_t no_out = igraph_vector_int_size(outv); - igraph_integer_t neis_out = RNG_GEOM(param_geom_out); - igraph_integer_t neis_in = RNG_GEOM(param_geom_in); + igraph_int_t no_in = igraph_vector_int_size(inv); + igraph_int_t no_out = igraph_vector_int_size(outv); + igraph_int_t neis_out = RNG_GEOM(param_geom_out); + igraph_int_t neis_in = RNG_GEOM(param_geom_in); /* outgoing neighbors */ if (neis_out >= no_out) { for (i = 0; i < no_out; i++) { - igraph_integer_t nei = VECTOR(*outv)[i]; + igraph_int_t nei = VECTOR(*outv)[i]; ADD_EDGE_TO(nei); } } else { - igraph_integer_t oleft = no_out; + igraph_int_t oleft = no_out; for (i = 0; i < neis_out && oleft > 0; ) { - igraph_integer_t which = RNG_INTEGER(0, oleft - 1); - igraph_integer_t nei = VECTOR(*outv)[which]; + igraph_int_t which = RNG_INTEGER(0, oleft - 1); + igraph_int_t nei = VECTOR(*outv)[which]; VECTOR(*outv)[which] = VECTOR(*outv)[oleft - 1]; VECTOR(*outv)[oleft - 1] = nei; if (VECTOR(visited)[nei] != actnode + 1) { @@ -216,14 +216,14 @@ igraph_error_t igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes, /* incoming neighbors */ if (neis_in >= no_in) { for (i = 0; i < no_in; i++) { - igraph_integer_t nei = VECTOR(*inv)[i]; + igraph_int_t nei = VECTOR(*inv)[i]; ADD_EDGE_TO(nei); } } else { - igraph_integer_t ileft = no_in; + igraph_int_t ileft = no_in; for (i = 0; i < neis_in && ileft > 0; ) { - igraph_integer_t which = RNG_INTEGER(0, ileft - 1); - igraph_integer_t nei = VECTOR(*inv)[which]; + igraph_int_t which = RNG_INTEGER(0, ileft - 1); + igraph_int_t nei = VECTOR(*inv)[which]; VECTOR(*inv)[which] = VECTOR(*inv)[ileft - 1]; VECTOR(*inv)[ileft - 1] = nei; if (VECTOR(visited)[nei] != actnode + 1) { diff --git a/src/vendor/cigraph/src/games/grg.c b/src/vendor/cigraph/src/games/grg.c index a8804e2251c..246c9f735c5 100644 --- a/src/vendor/cigraph/src/games/grg.c +++ b/src/vendor/cigraph/src/games/grg.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -53,11 +53,11 @@ * * \example examples/simple/igraph_grg_game.c */ -igraph_error_t igraph_grg_game(igraph_t *graph, igraph_integer_t nodes, +igraph_error_t igraph_grg_game(igraph_t *graph, igraph_int_t nodes, igraph_real_t radius, igraph_bool_t torus, igraph_vector_t *x, igraph_vector_t *y) { - igraph_integer_t i; + igraph_int_t i; igraph_vector_t myx, myy, *xx = &myx, *yy = &myy; igraph_vector_int_t edges; igraph_real_t r2; @@ -100,7 +100,7 @@ igraph_error_t igraph_grg_game(igraph_t *graph, igraph_integer_t nodes, for (i = 0; i < nodes; i++) { igraph_real_t xx1 = VECTOR(*xx)[i]; igraph_real_t yy1 = VECTOR(*yy)[i]; - igraph_integer_t j = i + 1; + igraph_int_t j = i + 1; igraph_real_t dx, dy; IGRAPH_ALLOW_INTERRUPTION(); @@ -119,7 +119,7 @@ igraph_error_t igraph_grg_game(igraph_t *graph, igraph_integer_t nodes, for (i = 0; i < nodes; i++) { igraph_real_t xx1 = VECTOR(*xx)[i]; igraph_real_t yy1 = VECTOR(*yy)[i]; - igraph_integer_t j = i + 1; + igraph_int_t j = i + 1; igraph_real_t dx, dy; IGRAPH_ALLOW_INTERRUPTION(); diff --git a/src/vendor/cigraph/src/games/growing_random.c b/src/vendor/cigraph/src/games/growing_random.c index 9d343070b49..98954faa74d 100644 --- a/src/vendor/cigraph/src/games/growing_random.c +++ b/src/vendor/cigraph/src/games/growing_random.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -52,16 +52,16 @@ * Time complexity: O(|V|+|E|), the * number of vertices plus the number of edges. */ -igraph_error_t igraph_growing_random_game(igraph_t *graph, igraph_integer_t n, - igraph_integer_t m, igraph_bool_t directed, +igraph_error_t igraph_growing_random_game(igraph_t *graph, igraph_int_t n, + igraph_int_t m, igraph_bool_t directed, igraph_bool_t citation) { - igraph_integer_t no_of_nodes = n; - igraph_integer_t no_of_neighbors = m; - igraph_integer_t no_of_edges; + igraph_int_t no_of_nodes = n; + igraph_int_t no_of_neighbors = m; + igraph_int_t no_of_edges; igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t resp = 0; + igraph_int_t resp = 0; if (n < 0) { IGRAPH_ERROR("Invalid number of vertices.", IGRAPH_EINVAL); @@ -82,15 +82,15 @@ igraph_error_t igraph_growing_random_game(igraph_t *graph, igraph_integer_t n, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); - for (igraph_integer_t i = 1; i < no_of_nodes; i++) { - for (igraph_integer_t j = 0; j < no_of_neighbors; j++) { + for (igraph_int_t i = 1; i < no_of_nodes; i++) { + for (igraph_int_t j = 0; j < no_of_neighbors; j++) { if (citation) { - igraph_integer_t to = RNG_INTEGER(0, i - 1); + igraph_int_t to = RNG_INTEGER(0, i - 1); VECTOR(edges)[resp++] = i; VECTOR(edges)[resp++] = to; } else { - igraph_integer_t from = RNG_INTEGER(0, i); - igraph_integer_t to = RNG_INTEGER(1, i); + igraph_int_t from = RNG_INTEGER(0, i); + igraph_int_t to = RNG_INTEGER(1, i); VECTOR(edges)[resp++] = from; VECTOR(edges)[resp++] = to; } diff --git a/src/vendor/cigraph/src/games/islands.c b/src/vendor/cigraph/src/games/islands.c index 2143b8816c1..181a436d328 100644 --- a/src/vendor/cigraph/src/games/islands.c +++ b/src/vendor/cigraph/src/games/islands.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -55,21 +55,21 @@ */ igraph_error_t igraph_simple_interconnected_islands_game( igraph_t *graph, - igraph_integer_t islands_n, - igraph_integer_t islands_size, + igraph_int_t islands_n, + igraph_int_t islands_size, igraph_real_t islands_pin, - igraph_integer_t n_inter) { + igraph_int_t n_inter) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; igraph_vector_t s = IGRAPH_VECTOR_NULL; - igraph_integer_t number_of_nodes; + igraph_int_t number_of_nodes; igraph_real_t max_possible_edges_per_island; igraph_real_t avg_edges_per_island; - igraph_integer_t number_of_inter_island_edges; - igraph_integer_t start_index_of_island, start_index_of_other_island; - igraph_integer_t i, j, is, from, to; + igraph_int_t number_of_inter_island_edges; + igraph_int_t start_index_of_island, start_index_of_other_island; + igraph_int_t i, j, is, from, to; igraph_real_t last; - igraph_integer_t island_ecount; + igraph_int_t island_ecount; igraph_real_t nr_edges_reserved; if (islands_n < 0) { diff --git a/src/vendor/cigraph/src/games/k_regular.c b/src/vendor/cigraph/src/games/k_regular.c index 6f7536e50f7..0eab6e487a9 100644 --- a/src/vendor/cigraph/src/games/k_regular.c +++ b/src/vendor/cigraph/src/games/k_regular.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -55,7 +55,7 @@ * Time complexity: O(|V|+|E|) if \c multiple is true, otherwise not known. */ igraph_error_t igraph_k_regular_game(igraph_t *graph, - igraph_integer_t no_of_nodes, igraph_integer_t k, + igraph_int_t no_of_nodes, igraph_int_t k, igraph_bool_t directed, igraph_bool_t multiple) { igraph_vector_int_t degseq; igraph_degseq_t mode = multiple ? IGRAPH_DEGSEQ_CONFIGURATION : IGRAPH_DEGSEQ_FAST_HEUR_SIMPLE; diff --git a/src/vendor/cigraph/src/games/preference.c b/src/vendor/cigraph/src/games/preference.c index b2e78842ed4..e7b98e8d71e 100644 --- a/src/vendor/cigraph/src/games/preference.c +++ b/src/vendor/cigraph/src/games/preference.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -80,8 +80,8 @@ * \ref igraph_establishment_game(), \ref igraph_callaway_traits_game() */ -igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t types, +igraph_error_t igraph_preference_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t types, const igraph_vector_t *type_dist, igraph_bool_t fixed_sizes, const igraph_matrix_t *pref_matrix, @@ -89,7 +89,7 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, igraph_bool_t directed, igraph_bool_t loops) { - igraph_integer_t i, j, no_reserved_edges; + igraph_int_t i, j, no_reserved_edges; igraph_vector_int_t edges; igraph_vector_t s; igraph_vector_int_t* nodetypes; @@ -177,7 +177,7 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, maxcum = igraph_vector_tail(&cumdist); for (i = 0; i < nodes; i++) { - igraph_integer_t type1; + igraph_int_t type1; igraph_real_t uni1 = RNG_UNIF(0, maxcum); igraph_vector_binsearch(&cumdist, uni1, &type1); VECTOR(*nodetypes)[i] = type1 - 1; @@ -190,10 +190,10 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, IGRAPH_FINALLY_CLEAN(1); } else { - igraph_integer_t an = 0; + igraph_int_t an = 0; if (type_dist) { for (i = 0; i < types; i++) { - igraph_integer_t no = VECTOR(*type_dist)[i]; + igraph_int_t no = VECTOR(*type_dist)[i]; igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(&vids_by_type, i); for (j = 0; j < no && an < nodes; j++) { VECTOR(*nodetypes)[an] = i; @@ -202,8 +202,8 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, } } } else { - igraph_integer_t size_of_one_group = nodes / types; - igraph_integer_t num_groups_with_one_extra_node = nodes - size_of_one_group * types; + igraph_int_t size_of_one_group = nodes / types; + igraph_int_t num_groups_with_one_extra_node = nodes - size_of_one_group * types; for (i = 0; i < types; i++) { igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(&vids_by_type, i); for (j = 0; j < size_of_one_group; j++) { @@ -226,10 +226,10 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, for (i = 0; i < types; i++) { for (j = 0; j < types; j++) { /* Generating the random subgraph between vertices of type i and j */ - igraph_integer_t k, l, l_x2; + igraph_int_t k, l, l_x2; igraph_real_t p, last; igraph_vector_int_t *v1, *v2; - igraph_integer_t v1_size, v2_size; + igraph_int_t v1_size, v2_size; IGRAPH_ALLOW_INTERRUPTION(); @@ -280,8 +280,8 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, if (i != j) { /* Generating the subgraph between vertices of type i and j */ for (k = 0; k < l; k++) { - igraph_integer_t to = floor(VECTOR(s)[k] / v1_size); - igraph_integer_t from = (VECTOR(s)[k] - ((igraph_real_t)to) * v1_size); + igraph_int_t to = floor(VECTOR(s)[k] / v1_size); + igraph_int_t from = (VECTOR(s)[k] - ((igraph_real_t)to) * v1_size); igraph_vector_int_push_back(&edges, VECTOR(*v1)[from]); igraph_vector_int_push_back(&edges, VECTOR(*v2)[to]); } @@ -289,15 +289,15 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, /* Generating the subgraph among vertices of type i */ if (directed && loops) { for (k = 0; k < l; k++) { - igraph_integer_t to = floor(VECTOR(s)[k] / v1_size); - igraph_integer_t from = (VECTOR(s)[k] - ((igraph_real_t)to) * v1_size); + igraph_int_t to = floor(VECTOR(s)[k] / v1_size); + igraph_int_t from = (VECTOR(s)[k] - ((igraph_real_t)to) * v1_size); igraph_vector_int_push_back(&edges, VECTOR(*v1)[from]); igraph_vector_int_push_back(&edges, VECTOR(*v1)[to]); } } else if (directed && !loops) { for (k = 0; k < l; k++) { - igraph_integer_t to = floor(VECTOR(s)[k] / v1_size); - igraph_integer_t from = (VECTOR(s)[k] - ((igraph_real_t)to) * v1_size); + igraph_int_t to = floor(VECTOR(s)[k] / v1_size); + igraph_int_t from = (VECTOR(s)[k] - ((igraph_real_t)to) * v1_size); if (from == to) { to = v1_size - 1; } @@ -306,15 +306,15 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, } } else if (!directed && loops) { for (k = 0; k < l; k++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[k] + 1) - 1) / 2); - igraph_integer_t from = (VECTOR(s)[k] - (((igraph_real_t)to) * (to + 1)) / 2); + igraph_int_t to = floor((sqrt(8 * VECTOR(s)[k] + 1) - 1) / 2); + igraph_int_t from = (VECTOR(s)[k] - (((igraph_real_t)to) * (to + 1)) / 2); igraph_vector_int_push_back(&edges, VECTOR(*v1)[from]); igraph_vector_int_push_back(&edges, VECTOR(*v1)[to]); } } else { for (k = 0; k < l; k++) { - igraph_integer_t to = floor((sqrt(8 * VECTOR(s)[k] + 1) + 1) / 2); - igraph_integer_t from = (VECTOR(s)[k] - (((igraph_real_t)to) * (to - 1)) / 2); + igraph_int_t to = floor((sqrt(8 * VECTOR(s)[k] + 1) + 1) / 2); + igraph_int_t from = (VECTOR(s)[k] - (((igraph_real_t)to) * (to - 1)) / 2); igraph_vector_int_push_back(&edges, VECTOR(*v1)[from]); igraph_vector_int_push_back(&edges, VECTOR(*v1)[to]); } @@ -378,16 +378,16 @@ igraph_error_t igraph_preference_game(igraph_t *graph, igraph_integer_t nodes, * \sa \ref igraph_preference_game() */ -igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer_t nodes, - igraph_integer_t no_out_types, - igraph_integer_t no_in_types, +igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_int_t nodes, + igraph_int_t no_out_types, + igraph_int_t no_in_types, const igraph_matrix_t *type_dist_matrix, const igraph_matrix_t *pref_matrix, igraph_vector_int_t *node_type_out_vec, igraph_vector_int_t *node_type_in_vec, igraph_bool_t loops) { - igraph_integer_t i, j, k, no_reserved_edges; + igraph_int_t i, j, k, no_reserved_edges; igraph_vector_int_t edges; igraph_vector_t s; igraph_vector_t cumdist; @@ -485,7 +485,7 @@ igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer maxcum = igraph_vector_tail(&cumdist); for (i = 0; i < nodes; i++) { - igraph_integer_t in_type, out_type; + igraph_int_t in_type, out_type; igraph_real_t uni1 = RNG_UNIF(0, maxcum); igraph_vector_binsearch(&cumdist, uni1, &in_type); out_type = (in_type - 1) % no_out_types; @@ -508,11 +508,11 @@ igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer IGRAPH_VECTOR_INT_INIT_FINALLY(&intersect, 0); for (i = 0; i < no_out_types; i++) { for (j = 0; j < no_in_types; j++) { - igraph_integer_t kk, l, l_x2; - igraph_integer_t c = 0; + igraph_int_t kk, l, l_x2; + igraph_int_t c = 0; igraph_real_t p, last; igraph_vector_int_t *v1, *v2; - igraph_integer_t v1_size, v2_size; + igraph_int_t v1_size, v2_size; IGRAPH_ALLOW_INTERRUPTION(); @@ -554,8 +554,8 @@ igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer if (!loops && c > 0) { for (kk = 0; kk < l; kk++) { - igraph_integer_t to = floor(VECTOR(s)[kk] / v1_size); - igraph_integer_t from = (VECTOR(s)[kk] - ((igraph_real_t) to) * v1_size); + igraph_int_t to = floor(VECTOR(s)[kk] / v1_size); + igraph_int_t from = (VECTOR(s)[kk] - ((igraph_real_t) to) * v1_size); if (VECTOR(*v1)[from] == VECTOR(*v2)[to]) { /* remap loop edges */ to = v2_size - 1; @@ -576,8 +576,8 @@ igraph_error_t igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer } } else { for (kk = 0; kk < l; kk++) { - igraph_integer_t to = floor(VECTOR(s)[kk] / v1_size); - igraph_integer_t from = (VECTOR(s)[kk] - ((igraph_real_t)to) * v1_size); + igraph_int_t to = floor(VECTOR(s)[kk] / v1_size); + igraph_int_t from = (VECTOR(s)[kk] - ((igraph_real_t)to) * v1_size); igraph_vector_int_push_back(&edges, VECTOR(*v1)[from]); igraph_vector_int_push_back(&edges, VECTOR(*v2)[to]); } diff --git a/src/vendor/cigraph/src/games/recent_degree.c b/src/vendor/cigraph/src/games/recent_degree.c index 2edb02cccba..9461fda9067 100644 --- a/src/vendor/cigraph/src/games/recent_degree.c +++ b/src/vendor/cigraph/src/games/recent_degree.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -61,22 +61,22 @@ * vertices, |E| is the number of edges in the graph. * */ -igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes, +igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_int_t nodes, igraph_real_t power, - igraph_integer_t time_window, - igraph_integer_t m, + igraph_int_t time_window, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t zero_appeal, igraph_bool_t directed) { - igraph_integer_t no_of_nodes = nodes; - igraph_integer_t no_of_neighbors = 0; - igraph_integer_t no_of_edges; + igraph_int_t no_of_nodes = nodes; + igraph_int_t no_of_neighbors = 0; + igraph_int_t no_of_edges; igraph_vector_int_t edges; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_psumtree_t sumtree; - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; igraph_vector_t degree; igraph_dqueue_int_t history; @@ -132,7 +132,7 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes /* and the rest */ for (i = 1; i < no_of_nodes; i++) { igraph_real_t sum; - igraph_integer_t to; + igraph_int_t to; if (outseq) { no_of_neighbors = VECTOR(*outseq)[i]; } @@ -162,7 +162,7 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes /* update probabilities */ for (j = 0; j < no_of_neighbors; j++) { - igraph_integer_t nn = VECTOR(edges)[edgeptr - 2 * j - 1]; + igraph_int_t nn = VECTOR(edges)[edgeptr - 2 * j - 1]; IGRAPH_CHECK(igraph_psumtree_update(&sumtree, nn, pow(VECTOR(degree)[nn], power) + zero_appeal)); } if (outpref) { @@ -226,25 +226,25 @@ igraph_error_t igraph_recent_degree_game(igraph_t *graph, igraph_integer_t nodes * of vertices, |E| the number of edges. */ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, - igraph_integer_t nodes, - igraph_integer_t m, + igraph_int_t nodes, + igraph_int_t m, const igraph_vector_int_t *outseq, igraph_bool_t outpref, igraph_real_t pa_exp, igraph_real_t aging_exp, - igraph_integer_t aging_bins, - igraph_integer_t time_window, + igraph_int_t aging_bins, + igraph_int_t time_window, igraph_real_t zero_appeal, igraph_bool_t directed) { - igraph_integer_t no_of_nodes = nodes; - igraph_integer_t no_of_neighbors; - igraph_integer_t binwidth; - igraph_integer_t no_of_edges; + igraph_int_t no_of_nodes = nodes; + igraph_int_t no_of_neighbors; + igraph_int_t binwidth; + igraph_int_t no_of_edges; igraph_vector_int_t edges; - igraph_integer_t i, j, k; + igraph_int_t i, j, k; igraph_psumtree_t sumtree; - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; igraph_vector_t degree; igraph_dqueue_int_t history; @@ -304,7 +304,7 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, /* and the rest */ for (i = 1; i < no_of_nodes; i++) { igraph_real_t sum; - igraph_integer_t to; + igraph_int_t to; if (outseq) { no_of_neighbors = VECTOR(*outseq)[i]; @@ -312,7 +312,7 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, if (i >= time_window) { while ((j = igraph_dqueue_int_pop(&history)) != -1) { - igraph_integer_t age = (i - j) / binwidth; + igraph_int_t age = (i - j) / binwidth; VECTOR(degree)[j] -= 1; IGRAPH_CHECK(igraph_psumtree_update( &sumtree, j, @@ -339,8 +339,8 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, /* update probabilities */ for (j = 0; j < no_of_neighbors; j++) { - igraph_integer_t n = VECTOR(edges)[edgeptr - 2 * j - 1]; - igraph_integer_t age = (i - n) / binwidth; + igraph_int_t n = VECTOR(edges)[edgeptr - 2 * j - 1]; + igraph_int_t age = (i - n) / binwidth; IGRAPH_CHECK(igraph_psumtree_update( &sumtree, n, (pow(VECTOR(degree)[n], pa_exp) + zero_appeal) * pow(age + 1, aging_exp) @@ -358,9 +358,9 @@ igraph_error_t igraph_recent_degree_aging_game(igraph_t *graph, /* aging */ for (k = 1; binwidth * k <= i; k++) { - igraph_integer_t shnode = i - binwidth * k; - igraph_integer_t deg = VECTOR(degree)[shnode]; - igraph_integer_t age = (i - shnode) / binwidth; + igraph_int_t shnode = i - binwidth * k; + igraph_int_t deg = VECTOR(degree)[shnode]; + igraph_int_t age = (i - shnode) / binwidth; IGRAPH_CHECK(igraph_psumtree_update( &sumtree, shnode, (pow(deg, pa_exp) + zero_appeal) * pow(age + 2, aging_exp) diff --git a/src/vendor/cigraph/src/games/sbm.c b/src/vendor/cigraph/src/games/sbm.c index cf3932e0a52..db8b1dd6416 100644 --- a/src/vendor/cigraph/src/games/sbm.c +++ b/src/vendor/cigraph/src/games/sbm.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -25,6 +25,7 @@ #include "core/interruption.h" #include "math/safe_intop.h" +#include "misc/graphicality.h" #include /* for DBL_EPSILON */ #include /* for sqrt and floor */ @@ -33,53 +34,67 @@ * \function igraph_sbm_game * \brief Sample from a stochastic block model. * - * This function samples graphs from a stochastic block - * model by (doing the equivalent of) Bernoulli - * trials for each potential edge with the probabilities - * given by the Bernoulli rate matrix, \p pref_matrix. - * See Faust, K., & Wasserman, S. (1992a). Blockmodels: - * Interpretation and evaluation. Social Networks, 14, 5-–61. + * This function samples graphs from a stochastic block model, a generalization + * of the G(n,p) model where the connection probability p (or expected number + * of edges for multigraphs) is specified separately between and within a given + * group of vertices. * * * The order of the vertex IDs in the generated graph corresponds to * the \p block_sizes argument. * + * + * Reference: + * + * + * Faust, K., & Wasserman, S. (1992a). + * Blockmodels: Interpretation and evaluation. + * Social Networks, 14, 5-–61. + * https://doi.org/10.1016/0378-8733(92)90013-W + * * \param graph The output graph. This should be a pointer to an * uninitialized graph. - * \param n Number of vertices. - * \param pref_matrix The matrix giving the Bernoulli rates. - * This is a KxK matrix, where K is the number of groups. + * \param pref_matrix The matrix giving the connection probabilities + * (or expected edge multiplicities for multigraphs) between groups. + * This is a k-by-k matrix, where k is the number of groups. * The probability of creating an edge between vertices from * groups i and j is given by element (i,j). * \param block_sizes An integer vector giving the number of * vertices in each group. * \param directed Boolean, whether to create a directed graph. If - * this argument is false, then \p pref_matrix must be symmetric. - * \param loops Boolean, whether to create self-loops. + * this argument is \c false, then \p pref_matrix must be symmetric. + * \param allowed_edge_types Controls whether multi-edges and self-loops + * are generated. See \ref igraph_edge_type_sw_t. * \return Error code. * - * Time complexity: O(|V|+|E|+K^2), where |V| is the number of - * vertices, |E| is the number of edges, and K is the number of + * Time complexity: O(|V|+|E|+k^2), where |V| is the number of + * vertices, |E| is the number of edges, and k is the number of * groups. * * \sa \ref igraph_erdos_renyi_game_gnp() for a simple Bernoulli graph. * */ -igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, - const igraph_matrix_t *pref_matrix, - const igraph_vector_int_t *block_sizes, - igraph_bool_t directed, igraph_bool_t loops) { +igraph_error_t igraph_sbm_game( + igraph_t *graph, + const igraph_matrix_t *pref_matrix, + const igraph_vector_int_t *block_sizes, + igraph_bool_t directed, + igraph_edge_type_sw_t allowed_edge_types) { -#define IGRAPH_CHECK_MAXEDGES() \ +#define CHECK_MAXEDGES() \ do {if (maxedges > IGRAPH_MAX_EXACT_REAL) { \ IGRAPH_ERROR("Too many vertices, overflow in maximum number of edges.", IGRAPH_EOVERFLOW); \ }} while (0) - igraph_integer_t no_blocks = igraph_matrix_nrow(pref_matrix); - igraph_integer_t from, to, fromoff = 0; + const igraph_int_t n = igraph_vector_int_sum(block_sizes); + const igraph_int_t no_blocks = igraph_matrix_nrow(pref_matrix); + igraph_int_t from, to, fromoff = 0; igraph_real_t minp, maxp; igraph_vector_int_t edges; + igraph_bool_t loops, multiple; + + IGRAPH_CHECK(igraph_i_edge_type_to_loops_multiple(allowed_edge_types, &loops, &multiple)); /* ------------------------------------------------------------ */ /* Check arguments */ @@ -91,8 +106,16 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, if (no_blocks > 0) { igraph_matrix_minmax(pref_matrix, &minp, &maxp); - if (minp < 0 || maxp > 1) { - IGRAPH_ERROR("Connection probabilities must be in [0,1].", IGRAPH_EINVAL); + if (multiple) { + if (minp < 0.0) { + IGRAPH_ERRORF("Expected edge multiplicities must not be negative " + "for SBM multigraph model, got %g.", + IGRAPH_EINVAL, minp); + } + } else { + if (minp < 0 || maxp > 1) { + IGRAPH_ERROR("Connection probabilities must be in [0,1] for SBM model.", IGRAPH_EINVAL); + } } } @@ -114,22 +137,12 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, } } - if (igraph_vector_int_sum(block_sizes) != n) { - IGRAPH_ERRORF("Sum of the block sizes (%" IGRAPH_PRId ") must equal the number of vertices (%" IGRAPH_PRId ").", - IGRAPH_EINVAL, igraph_vector_int_sum(block_sizes), n); - } - - /* Since the sum of the block sizes should equal the number of vertices, - * and the block sizes are non-negative, the number of vertices is - * guaranteed to be non-negative. This shouldn't be checked separately. - */ - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); for (from = 0; from < no_blocks; from++) { - igraph_integer_t fromsize = VECTOR(*block_sizes)[from]; - igraph_integer_t start = directed ? 0 : from; - igraph_integer_t i, tooff = 0; + igraph_int_t fromsize = VECTOR(*block_sizes)[from]; + igraph_int_t start = directed ? 0 : from; + igraph_int_t i, tooff = 0; IGRAPH_ALLOW_INTERRUPTION(); @@ -137,37 +150,42 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, tooff += VECTOR(*block_sizes)[i]; } for (to = start; to < no_blocks; to++) { - igraph_integer_t tosize = VECTOR(*block_sizes)[to]; + igraph_int_t tosize = VECTOR(*block_sizes)[to]; + igraph_real_t prob = MATRIX(*pref_matrix, from, to); + if (multiple) { + prob = prob / (1 + prob); + } + igraph_real_t maxedges; - igraph_real_t last = RNG_GEOM(prob); /* RNG_GEOM may return NaN so igraph_integer_t is not suitable */ - igraph_integer_t vfrom, vto; + igraph_real_t last = RNG_GEOM(prob); /* RNG_GEOM may return NaN so igraph_int_t is not suitable */ + igraph_int_t vfrom, vto; if (directed && loops) { maxedges = ((igraph_real_t) fromsize) * tosize; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { vto = floor(last / fromsize); vfrom = last - ((igraph_real_t) vto) * fromsize; igraph_vector_int_push_back(&edges, fromoff + vfrom); igraph_vector_int_push_back(&edges, tooff + vto); last += RNG_GEOM(prob); - last += 1; + last += ! multiple; /* 1 for simple graph, 0 for multigraph */; } } else if (directed && !loops && from != to) { maxedges = ((igraph_real_t) fromsize) * tosize; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { vto = floor(last / fromsize); vfrom = last - ((igraph_real_t) vto) * fromsize; igraph_vector_int_push_back(&edges, fromoff + vfrom); igraph_vector_int_push_back(&edges, tooff + vto); last += RNG_GEOM(prob); - last += 1; + last += ! multiple; /* 1 for simple graph, 0 for multigraph */; } } else if (directed && !loops && from == to) { maxedges = ((igraph_real_t) fromsize) * (fromsize - 1.0); - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { vto = floor(last / fromsize); vfrom = last - ((igraph_real_t) vto) * fromsize; @@ -177,51 +195,51 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, igraph_vector_int_push_back(&edges, fromoff + vfrom); igraph_vector_int_push_back(&edges, tooff + vto); last += RNG_GEOM(prob); - last += 1; + last += ! multiple; /* 1 for simple graph, 0 for multigraph */; } } else if (!directed && loops && from != to) { maxedges = ((igraph_real_t) fromsize) * tosize; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { vto = floor(last / fromsize); vfrom = last - ((igraph_real_t) vto) * fromsize; igraph_vector_int_push_back(&edges, fromoff + vfrom); igraph_vector_int_push_back(&edges, tooff + vto); last += RNG_GEOM(prob); - last += 1; + last += ! multiple; /* 1 for simple graph, 0 for multigraph */; } } else if (!directed && loops && from == to) { maxedges = ((igraph_real_t) fromsize) * (fromsize + 1.0) / 2.0; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { vto = floor((sqrt(8 * last + 1) - 1) / 2); vfrom = last - (((igraph_real_t) vto) * (vto + 1.0)) / 2.0; igraph_vector_int_push_back(&edges, fromoff + vfrom); igraph_vector_int_push_back(&edges, tooff + vto); last += RNG_GEOM(prob); - last += 1; + last += ! multiple; /* 1 for simple graph, 0 for multigraph */; } } else if (!directed && !loops && from != to) { maxedges = ((igraph_real_t) fromsize) * tosize; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { vto = floor(last / fromsize); vfrom = last - ((igraph_real_t) vto) * fromsize; igraph_vector_int_push_back(&edges, fromoff + vfrom); igraph_vector_int_push_back(&edges, tooff + vto); last += RNG_GEOM(prob); - last += 1; + last += ! multiple; /* 1 for simple graph, 0 for multigraph */; } } else { /*!directed && !loops && from==to */ maxedges = ((igraph_real_t) fromsize) * (fromsize - 1.0) / 2.0; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { vto = floor((sqrt(8 * last + 1) + 1) / 2); vfrom = last - (((igraph_real_t) vto) * (vto - 1.0)) / 2.0; igraph_vector_int_push_back(&edges, fromoff + vfrom); igraph_vector_int_push_back(&edges, tooff + vto); last += RNG_GEOM(prob); - last += 1; + last += ! multiple; /* 1 for simple graph, 0 for multigraph */; } } @@ -236,7 +254,7 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; -#undef IGRAPH_CHECK_MAXEDGES +#undef CHECK_MAXEDGES } /** @@ -263,20 +281,20 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, * \ref igraph_hsbm_list_game() for a more general version. */ -igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, - igraph_integer_t m, const igraph_vector_t *rho, +igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_int_t n, + igraph_int_t m, const igraph_vector_t *rho, const igraph_matrix_t *C, igraph_real_t p) { -#define IGRAPH_CHECK_MAXEDGES() \ +#define CHECK_MAXEDGES() \ do {if (maxedges > IGRAPH_MAX_EXACT_REAL) { \ IGRAPH_ERROR("Too many vertices, overflow in maximum number of edges.", IGRAPH_EOVERFLOW); \ }} while (0) - igraph_integer_t b, i, k = igraph_vector_size(rho); + igraph_int_t b, i, k = igraph_vector_size(rho); igraph_vector_t csizes; igraph_real_t sq_dbl_epsilon = sqrt(DBL_EPSILON); - igraph_integer_t no_blocks = n / m; + igraph_int_t no_blocks = n / m; igraph_vector_int_t edges; - igraph_integer_t offset = 0; + igraph_int_t offset = 0; if (n < 1) { IGRAPH_ERROR("`n' must be positive for HSBM", IGRAPH_EINVAL); @@ -324,25 +342,25 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, /* Block models first */ for (b = 0; b < no_blocks; b++) { - igraph_integer_t from, to, fromoff = 0; + igraph_int_t from, to, fromoff = 0; for (from = 0; from < k; from++) { - igraph_integer_t fromsize = VECTOR(csizes)[from]; - igraph_integer_t i, tooff = 0; + igraph_int_t fromsize = VECTOR(csizes)[from]; + igraph_int_t i, tooff = 0; for (i = 0; i < from; i++) { tooff += VECTOR(csizes)[i]; } for (to = from; to < k; to++) { - igraph_integer_t tosize = VECTOR(csizes)[to]; + igraph_int_t tosize = VECTOR(csizes)[to]; igraph_real_t prob = MATRIX(*C, from, to); igraph_real_t maxedges; - igraph_real_t last = RNG_GEOM(prob); /* RNG_GEOM may return NaN so igraph_integer_t is not suitable */ + igraph_real_t last = RNG_GEOM(prob); /* RNG_GEOM may return NaN so igraph_int_t is not suitable */ if (from != to) { maxedges = ((igraph_real_t) fromsize) * tosize; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { - igraph_integer_t vto = floor(last / fromsize); - igraph_integer_t vfrom = last - ((igraph_real_t) vto) * fromsize; + igraph_int_t vto = floor(last / fromsize); + igraph_int_t vfrom = last - ((igraph_real_t) vto) * fromsize; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + fromoff + vfrom)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + tooff + vto)); last += RNG_GEOM(prob); @@ -350,10 +368,10 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, } } else { /* from==to */ maxedges = ((igraph_real_t) fromsize) * (fromsize - 1.0) / 2.0; - IGRAPH_CHECK_MAXEDGES(); + CHECK_MAXEDGES(); while (last < maxedges) { - igraph_integer_t vto = floor((sqrt(8 * last + 1) + 1) / 2); - igraph_integer_t vfrom = last - (((igraph_real_t) vto) * (vto - 1.0)) / 2.0; + igraph_int_t vto = floor((sqrt(8 * last + 1) + 1) / 2); + igraph_int_t vfrom = last - (((igraph_real_t) vto) * (vto - 1.0)) / 2.0; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + fromoff + vfrom)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + tooff + vto)); last += RNG_GEOM(prob); @@ -372,11 +390,11 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, /* And now the rest, if not a special case */ if (p == 1) { - igraph_integer_t fromoff = 0, tooff = m; + igraph_int_t fromoff = 0, tooff = m; for (b = 0; b < no_blocks; b++) { - igraph_integer_t fromsize = m; - igraph_integer_t tosize = n - tooff; - igraph_integer_t from, to; + igraph_int_t fromsize = m; + igraph_int_t tosize = n - tooff; + igraph_int_t from, to; for (from = 0; from < fromsize; from++) { for (to = 0; to < tosize; to++) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, fromoff + from)); @@ -387,16 +405,16 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, tooff += m; } } else if (p > 0) { - igraph_integer_t fromoff = 0, tooff = m; + igraph_int_t fromoff = 0, tooff = m; for (b = 0; b < no_blocks; b++) { - igraph_integer_t fromsize = m; - igraph_integer_t tosize = n - tooff; + igraph_int_t fromsize = m; + igraph_int_t tosize = n - tooff; igraph_real_t maxedges = ((igraph_real_t) fromsize) * tosize; - IGRAPH_CHECK_MAXEDGES(); - igraph_real_t last = RNG_GEOM(p); /* RNG_GEOM may return NaN so igraph_integer_t is not suitable */ + CHECK_MAXEDGES(); + igraph_real_t last = RNG_GEOM(p); /* RNG_GEOM may return NaN so igraph_int_t is not suitable */ while (last < maxedges) { - igraph_integer_t vto = floor(last / fromsize); - igraph_integer_t vfrom = last - ((igraph_real_t) vto) * fromsize; + igraph_int_t vto = floor(last / fromsize); + igraph_int_t vfrom = last - ((igraph_real_t) vto) * fromsize; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, fromoff + vfrom)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, tooff + vto)); last += RNG_GEOM(p); @@ -415,7 +433,7 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, IGRAPH_FINALLY_CLEAN(2); return IGRAPH_SUCCESS; -#undef IGRAPH_CHECK_MAXEDGES +#undef CHECK_MAXEDGES } /** @@ -441,17 +459,17 @@ igraph_error_t igraph_hsbm_game(igraph_t *graph, igraph_integer_t n, * \ref igraph_hsbm_game() for a simpler general version. */ -igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, +igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_int_t n, const igraph_vector_int_t *mlist, const igraph_vector_list_t *rholist, const igraph_matrix_list_t *Clist, igraph_real_t p) { - igraph_integer_t i, no_blocks = igraph_vector_list_size(rholist); + igraph_int_t i, no_blocks = igraph_vector_list_size(rholist); igraph_real_t sq_dbl_epsilon = sqrt(DBL_EPSILON); igraph_vector_int_t edges; igraph_vector_t csizes; - igraph_integer_t b, offset = 0; + igraph_int_t b, offset = 0; if (n < 1) { IGRAPH_ERROR("`n' must be positive for HSBM.", IGRAPH_EINVAL); @@ -500,7 +518,7 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, for (i = 0; i < no_blocks; i++) { const igraph_vector_t *rho = igraph_vector_list_get_ptr(rholist, i); const igraph_matrix_t *C = igraph_matrix_list_get_ptr(Clist, i); - igraph_integer_t k = igraph_vector_size(rho); + igraph_int_t k = igraph_vector_size(rho); if (igraph_matrix_nrow(C) != k || igraph_matrix_ncol(C) != k) { IGRAPH_ERROR("All Bernoulli rate matrix dimensions must match `rho' " "dimensions in HSBM.", @@ -511,7 +529,7 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, for (i = 0; i < no_blocks; i++) { const igraph_vector_t *rho = igraph_vector_list_get_ptr(rholist, i); igraph_real_t m = VECTOR(*mlist)[i]; - igraph_integer_t j, k = igraph_vector_size(rho); + igraph_int_t j, k = igraph_vector_size(rho); for (j = 0; j < k; j++) { igraph_real_t s = VECTOR(*rho)[j] * m; if (fabs(round(s) - s) > sq_dbl_epsilon) { @@ -526,11 +544,11 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, /* Block models first */ for (b = 0; b < no_blocks; b++) { - igraph_integer_t from, to, fromoff = 0; + igraph_int_t from, to, fromoff = 0; const igraph_vector_t *rho = igraph_vector_list_get_ptr(rholist, b); const igraph_matrix_t *C = igraph_matrix_list_get_ptr(Clist, b); - igraph_integer_t m = VECTOR(*mlist)[b]; - igraph_integer_t k = igraph_vector_size(rho); + igraph_int_t m = VECTOR(*mlist)[b]; + igraph_int_t k = igraph_vector_size(rho); IGRAPH_CHECK(igraph_vector_resize(&csizes, k)); for (i = 0; i < k; i++) { @@ -538,21 +556,21 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, } for (from = 0; from < k; from++) { - igraph_integer_t fromsize = VECTOR(csizes)[from]; - igraph_integer_t i, tooff = 0; + igraph_int_t fromsize = VECTOR(csizes)[from]; + igraph_int_t i, tooff = 0; for (i = 0; i < from; i++) { tooff += VECTOR(csizes)[i]; } for (to = from; to < k; to++) { - igraph_integer_t tosize = VECTOR(csizes)[to]; + igraph_int_t tosize = VECTOR(csizes)[to]; igraph_real_t prob = MATRIX(*C, from, to); igraph_real_t maxedges; - igraph_real_t last = RNG_GEOM(prob); /* RNG_GEOM may return NaN so igraph_integer_t is not suitable */ + igraph_real_t last = RNG_GEOM(prob); /* RNG_GEOM may return NaN so igraph_int_t is not suitable */ if (from != to) { maxedges = ((igraph_real_t) fromsize) * tosize; while (last < maxedges) { - igraph_integer_t vto = floor(last / fromsize); - igraph_integer_t vfrom = last - ((igraph_real_t) vto) * fromsize; + igraph_int_t vto = floor(last / fromsize); + igraph_int_t vfrom = last - ((igraph_real_t) vto) * fromsize; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + fromoff + vfrom)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + tooff + vto)); last += RNG_GEOM(prob); @@ -561,8 +579,8 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, } else { /* from==to */ maxedges = ((igraph_real_t) fromsize) * (fromsize - 1.0) / 2.0; while (last < maxedges) { - igraph_integer_t vto = floor((sqrt(8 * last + 1) + 1) / 2); - igraph_integer_t vfrom = last - (((igraph_real_t) vto) * (vto - 1.0)) / 2.0; + igraph_int_t vto = floor((sqrt(8 * last + 1) + 1) / 2); + igraph_int_t vfrom = last - (((igraph_real_t) vto) * (vto - 1.0)) / 2.0; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + fromoff + vfrom)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, offset + tooff + vto)); last += RNG_GEOM(prob); @@ -581,11 +599,11 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, /* And now the rest, if not a special case */ if (p == 1) { - igraph_integer_t fromoff = 0, tooff = VECTOR(*mlist)[0]; + igraph_int_t fromoff = 0, tooff = VECTOR(*mlist)[0]; for (b = 0; b < no_blocks; b++) { - igraph_integer_t fromsize = VECTOR(*mlist)[b]; - igraph_integer_t tosize = n - tooff; - igraph_integer_t from, to; + igraph_int_t fromsize = VECTOR(*mlist)[b]; + igraph_int_t tosize = n - tooff; + igraph_int_t from, to; for (from = 0; from < fromsize; from++) { for (to = 0; to < tosize; to++) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, fromoff + from)); @@ -598,15 +616,15 @@ igraph_error_t igraph_hsbm_list_game(igraph_t *graph, igraph_integer_t n, } } } else if (p > 0) { - igraph_integer_t fromoff = 0, tooff = VECTOR(*mlist)[0]; + igraph_int_t fromoff = 0, tooff = VECTOR(*mlist)[0]; for (b = 0; b < no_blocks; b++) { - igraph_integer_t fromsize = VECTOR(*mlist)[b]; - igraph_integer_t tosize = n - tooff; + igraph_int_t fromsize = VECTOR(*mlist)[b]; + igraph_int_t tosize = n - tooff; igraph_real_t maxedges = ((igraph_real_t) fromsize) * tosize; - igraph_real_t last = RNG_GEOM(p); /* RNG_GEOM may return NaN so igraph_integer_t is not suitable */ + igraph_real_t last = RNG_GEOM(p); /* RNG_GEOM may return NaN so igraph_int_t is not suitable */ while (last < maxedges) { - igraph_integer_t vto = floor(last / fromsize); - igraph_integer_t vfrom = last - ((igraph_real_t) vto) * fromsize; + igraph_int_t vto = floor(last / fromsize); + igraph_int_t vfrom = last - ((igraph_real_t) vto) * fromsize; IGRAPH_CHECK(igraph_vector_int_push_back(&edges, fromoff + vfrom)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, tooff + vto)); last += RNG_GEOM(p); diff --git a/src/vendor/cigraph/src/games/static_fitness.c b/src/vendor/cigraph/src/games/static_fitness.c index a87ece9dfab..19177f3d135 100644 --- a/src/vendor/cigraph/src/games/static_fitness.c +++ b/src/vendor/cigraph/src/games/static_fitness.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -30,6 +30,7 @@ #include "core/interruption.h" #include "core/math.h" /* M_SQRT2 */ +#include "misc/graphicality.h" /** * \ingroup generators @@ -93,8 +94,8 @@ * \param fitness_in If \c NULL, the generated graph will be undirected. * If not \c NULL, this argument specifies the in-fitness * of each vertex. - * \param loops Whether to allow loop edges in the generated graph. - * \param multiple Whether to allow multiple edges in the generated graph. + * \param allowed_edge_types Controls whether multi-edges and self-loops + * are allowed in the generated graph. See \ref igraph_edge_type_sw_t. * * \return Error code: * \c IGRAPH_EINVAL: invalid parameter @@ -106,11 +107,11 @@ * * Time complexity: O(|V| + |E| log |E|). */ -igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_of_edges, +igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_int_t no_of_edges, const igraph_vector_t *fitness_out, const igraph_vector_t *fitness_in, - igraph_bool_t loops, igraph_bool_t multiple) { + igraph_edge_type_sw_t allowed_edge_types) { - const igraph_integer_t no_of_nodes = igraph_vector_size(fitness_out); + const igraph_int_t no_of_nodes = igraph_vector_size(fitness_out); const igraph_bool_t directed = (fitness_in != NULL); igraph_vector_int_t edges; igraph_vector_t cum_fitness_in, cum_fitness_out; @@ -118,9 +119,12 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o igraph_real_t x, max_in, max_out; igraph_real_t max_no_of_edges; igraph_real_t num_steps; - igraph_integer_t from, to, pos; + igraph_int_t from, to, pos; + igraph_bool_t loops, multiple; int iter = 0; + IGRAPH_CHECK(igraph_i_edge_type_to_loops_multiple(allowed_edge_types, &loops, &multiple)); + IGRAPH_ASSERT(fitness_out != NULL); if (no_of_edges < 0) { @@ -146,11 +150,11 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o /* Avoid getting into an infinite loop when too many edges are requested. */ { - igraph_integer_t nodes; + igraph_int_t nodes; if (directed) { - igraph_integer_t outnodes, innodes; + igraph_int_t outnodes, innodes; outnodes = innodes = nodes = 0; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(*fitness_out)[i] != 0) { outnodes++; } @@ -164,7 +168,7 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o max_no_of_edges = ((igraph_real_t) outnodes) * innodes - (loops ? 0 : nodes); } else { nodes = 0; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(*fitness_out)[i] != 0) { nodes++; } @@ -224,8 +228,8 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o continue; } - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); + igraph_vector_int_push_back(&edges, from); /* reserved */ + igraph_vector_int_push_back(&edges, to); /* reserved */ no_of_edges--; } @@ -368,8 +372,8 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o * the exponent of the in-degree distribution. If * non-negative but less than 2, an error will be * generated. - * \param loops Whether to allow loop edges in the generated graph. - * \param multiple Whether to allow multiple edges in the generated graph. + * \param allowed_edge_types Controls whether multi-edges and self-loops + * are allowed in the generated graph. See \ref igraph_edge_type_sw_t. * \param finite_size_correction Whether to use the proposed finite size * correction of Cho et al. * @@ -381,9 +385,9 @@ igraph_error_t igraph_static_fitness_game(igraph_t *graph, igraph_integer_t no_o * Time complexity: O(|V| + |E| log |E|). */ igraph_error_t igraph_static_power_law_game(igraph_t *graph, - igraph_integer_t no_of_nodes, igraph_integer_t no_of_edges, + igraph_int_t no_of_nodes, igraph_int_t no_of_edges, igraph_real_t exponent_out, igraph_real_t exponent_in, - igraph_bool_t loops, igraph_bool_t multiple, + igraph_edge_type_sw_t allowed_edge_types, igraph_bool_t finite_size_correction) { igraph_vector_t fitness_out, fitness_in; @@ -414,7 +418,7 @@ igraph_error_t igraph_static_power_law_game(igraph_t *graph, if (j < no_of_nodes) { j = no_of_nodes; } - for (igraph_integer_t i = 0; i < no_of_nodes; i++, j--) { + for (igraph_int_t i = 0; i < no_of_nodes; i++, j--) { VECTOR(fitness_out)[i] = pow(j, alpha_out); } @@ -438,19 +442,19 @@ igraph_error_t igraph_static_power_law_game(igraph_t *graph, if (j < no_of_nodes) { j = no_of_nodes; } - for (igraph_integer_t i = 0; i < no_of_nodes; i++, j--) { + for (igraph_int_t i = 0; i < no_of_nodes; i++, j--) { VECTOR(fitness_in)[i] = pow(j, alpha_in); } igraph_vector_shuffle(&fitness_in); IGRAPH_CHECK(igraph_static_fitness_game(graph, no_of_edges, - &fitness_out, &fitness_in, loops, multiple)); + &fitness_out, &fitness_in, allowed_edge_types)); igraph_vector_destroy(&fitness_in); IGRAPH_FINALLY_CLEAN(1); } else { IGRAPH_CHECK(igraph_static_fitness_game(graph, no_of_edges, - &fitness_out, NULL, loops, multiple)); + &fitness_out, NULL, allowed_edge_types)); } igraph_vector_destroy(&fitness_out); diff --git a/src/vendor/cigraph/src/games/tree.c b/src/vendor/cigraph/src/games/tree.c index 6eedd1f792c..73fc097f2c3 100644 --- a/src/vendor/cigraph/src/games/tree.c +++ b/src/vendor/cigraph/src/games/tree.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -34,7 +34,7 @@ * them to trees. */ -static igraph_error_t igraph_i_tree_game_prufer(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed) { +static igraph_error_t igraph_i_tree_game_prufer(igraph_t *graph, igraph_int_t n, igraph_bool_t directed) { igraph_vector_int_t prufer; if (directed) { @@ -43,7 +43,7 @@ static igraph_error_t igraph_i_tree_game_prufer(igraph_t *graph, igraph_integer_ IGRAPH_VECTOR_INT_INIT_FINALLY(&prufer, n - 2); - for (igraph_integer_t i = 0; i < n - 2; ++i) { + for (igraph_int_t i = 0; i < n - 2; ++i) { VECTOR(prufer)[i] = RNG_INTEGER(0, n - 1); } @@ -63,18 +63,18 @@ static igraph_error_t igraph_i_tree_game_prufer(igraph_t *graph, igraph_integer_ /* swap two elements of a vector_int */ #define SWAP_INT_ELEM(vec, i, j) \ { \ - igraph_integer_t temp; \ + igraph_int_t temp; \ temp = VECTOR(vec)[i]; \ VECTOR(vec)[i] = VECTOR(vec)[j]; \ VECTOR(vec)[j] = temp; \ } -static igraph_error_t igraph_i_tree_game_loop_erased_random_walk(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed) { +static igraph_error_t igraph_i_tree_game_loop_erased_random_walk(igraph_t *graph, igraph_int_t n, igraph_bool_t directed) { igraph_vector_int_t edges; igraph_vector_int_t vertices; igraph_bitset_t visited; - igraph_integer_t i, j; - igraph_integer_t no_edges; + igraph_int_t i, j; + igraph_int_t no_edges; IGRAPH_SAFE_MULT(n - 1, 2, &no_edges); @@ -115,7 +115,7 @@ static igraph_error_t igraph_i_tree_game_loop_erased_random_walk(igraph_t *graph IGRAPH_BIT_SET(visited, i); SWAP_INT_ELEM(vertices, 0, i); - for (igraph_integer_t k = 1; k < n; ++k) { + for (igraph_int_t k = 1; k < n; ++k) { j = RNG_INTEGER(0, n - 1); if (IGRAPH_BIT_TEST(visited, VECTOR(vertices)[j])) { i = VECTOR(vertices)[j]; @@ -173,7 +173,7 @@ static igraph_error_t igraph_i_tree_game_loop_erased_random_walk(igraph_t *graph * */ -igraph_error_t igraph_tree_game(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, igraph_random_tree_t method) { +igraph_error_t igraph_tree_game(igraph_t *graph, igraph_int_t n, igraph_bool_t directed, igraph_random_tree_t method) { if (n < 2) { IGRAPH_CHECK(igraph_empty(graph, n, directed)); return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/games/watts_strogatz.c b/src/vendor/cigraph/src/games/watts_strogatz.c index ad3d64909cd..24eb208e9eb 100644 --- a/src/vendor/cigraph/src/games/watts_strogatz.c +++ b/src/vendor/cigraph/src/games/watts_strogatz.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -60,8 +60,8 @@ * the same as the \p order argument of \ref igraph_connect_neighborhood(). * \param p The rewiring probability. A real number between zero and * one (inclusive). - * \param loops Whether to generate loop edges. - * \param multiple Whether to allow multiple edges in the generated graph. + * \param allowed_edge_types Controls whether multi-edges and self-loops + * are allowed in the generated graph. See \ref igraph_edge_type_sw_t. * \return Error code. * * \sa \ref igraph_square_lattice(), \ref igraph_connect_neighborhood() and @@ -72,10 +72,11 @@ * vertices and edges, d is the average degree, o is the \p nei * argument. */ -igraph_error_t igraph_watts_strogatz_game(igraph_t *graph, igraph_integer_t dim, - igraph_integer_t size, igraph_integer_t nei, - igraph_real_t p, igraph_bool_t loops, - igraph_bool_t multiple) { +igraph_error_t igraph_watts_strogatz_game( + igraph_t *graph, igraph_int_t dim, + igraph_int_t size, igraph_int_t nei, + igraph_real_t p, + igraph_edge_type_sw_t allowed_edge_types) { igraph_vector_int_t dimvector; igraph_vector_bool_t periodic; @@ -110,7 +111,7 @@ igraph_error_t igraph_watts_strogatz_game(igraph_t *graph, igraph_integer_t dim, /* Rewire the edges then */ - IGRAPH_CHECK(igraph_rewire_edges(graph, p, loops, multiple)); + IGRAPH_CHECK(igraph_rewire_edges(graph, p, allowed_edge_types)); IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/graph/adjlist.c b/src/vendor/cigraph/src/graph/adjlist.c index 3a792f6b83a..5bf58943e2c 100644 --- a/src/vendor/cigraph/src/graph/adjlist.c +++ b/src/vendor/cigraph/src/graph/adjlist.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -50,7 +50,7 @@ * there is no loop or multiple edge, only that the function hasn't found one. */ static igraph_error_t igraph_i_simplify_sorted_int_adjacency_vector_in_place( - igraph_vector_int_t *v, igraph_integer_t index, igraph_neimode_t mode, + igraph_vector_int_t *v, igraph_int_t index, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple, igraph_bool_t *has_loops, igraph_bool_t *has_multiple ); @@ -153,7 +153,7 @@ static igraph_error_t igraph_i_simplify_sorted_int_adjacency_vector_in_place( igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degrees; int iter = 0; @@ -199,7 +199,7 @@ igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, * if we are looping over all vertices anyway, and that requires us to query * the neighbors in full */ - for (igraph_integer_t i = 0; i < al->length; i++) { + for (igraph_int_t i = 0; i < al->length; i++) { IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1000); IGRAPH_CHECK(igraph_vector_int_init(&al->adjs[i], VECTOR(degrees)[i])); @@ -252,14 +252,14 @@ igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, * * Time complexity: O(n), linear in the number of vertices. */ -igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_integer_t no_of_nodes) { +igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_int_t no_of_nodes) { al->length = no_of_nodes; al->adjs = IGRAPH_CALLOC(al->length, igraph_vector_int_t); IGRAPH_CHECK_OOM(al->adjs, "Insufficient memory for creating adjlist."); IGRAPH_FINALLY(igraph_adjlist_destroy, al); - for (igraph_integer_t i = 0; i < al->length; i++) { + for (igraph_int_t i = 0; i < al->length; i++) { IGRAPH_CHECK(igraph_vector_int_init(&al->adjs[i], 0)); } @@ -329,7 +329,7 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, IGRAPH_BITSET_INIT_FINALLY(&seen, al->length); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); - for (igraph_integer_t i = 0; i < al->length; i++) { + for (igraph_int_t i = 0; i < al->length; i++) { /* For each vertex, we mark neighbors within the 'seen' bitset. * Then we iterate over 'seen' and record non-marked vertices in * the adjacency list. */ @@ -338,7 +338,7 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, /* Reset neighbor counter and 'seen' vector. */ igraph_bitset_null(&seen); - igraph_integer_t n = al->length; + igraph_int_t n = al->length; IGRAPH_CHECK(igraph_neighbors(graph, &neis, i, mode, loops, IGRAPH_NO_MULTIPLE)); @@ -348,8 +348,8 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, n--; } - igraph_integer_t neis_size = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < neis_size; j++) { + igraph_int_t neis_size = igraph_vector_int_size(&neis); + for (igraph_int_t j = 0; j < neis_size; j++) { if (! IGRAPH_BIT_TEST(seen, VECTOR(neis)[j]) ) { n--; IGRAPH_BIT_SET(seen, VECTOR(neis)[j]); @@ -367,7 +367,7 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, /* Produce "non-neighbor" list in sorted order. */ IGRAPH_CHECK(igraph_vector_int_init(&al->adjs[i], n)); - for (igraph_integer_t j = 0, k = 0; k < n; j++) { + for (igraph_int_t j = 0, k = 0; k < n; j++) { if (!IGRAPH_BIT_TEST(seen, j)) { VECTOR(al->adjs[i])[k++] = j; if (loops == IGRAPH_LOOPS_TWICE && i == j) { @@ -415,8 +415,8 @@ igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, igraph_error_t igraph_adjlist_init_from_inclist( const igraph_t *graph, igraph_adjlist_t *al, const igraph_inclist_t *il) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i, j, num_neis; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i, j, num_neis; igraph_vector_int_t *neis; igraph_vector_int_t *incs; @@ -456,7 +456,7 @@ igraph_error_t igraph_adjlist_init_from_inclist( * Time complexity: O(n), where n is the size of the adjacency list. */ void igraph_adjlist_destroy(igraph_adjlist_t *al) { - for (igraph_integer_t i = 0; i < al->length; i++) { + for (igraph_int_t i = 0; i < al->length; i++) { /* This works if some igraph_vector_int_t's contain NULL, because igraph_vector_int_destroy can handle this. */ igraph_vector_int_destroy(&al->adjs[i]); @@ -476,7 +476,7 @@ void igraph_adjlist_destroy(igraph_adjlist_t *al) { * Time complexity: O(n), where n is the size of the adjacency list. */ void igraph_adjlist_clear(igraph_adjlist_t *al) { - for (igraph_integer_t i = 0; i < al->length; i++) { + for (igraph_int_t i = 0; i < al->length; i++) { igraph_vector_int_clear(&al->adjs[i]); } } @@ -490,7 +490,7 @@ void igraph_adjlist_clear(igraph_adjlist_t *al) { * * Time complexity: O(1). */ -igraph_integer_t igraph_adjlist_size(const igraph_adjlist_t *al) { +igraph_int_t igraph_adjlist_size(const igraph_adjlist_t *al) { return al->length; } @@ -510,7 +510,7 @@ igraph_integer_t igraph_adjlist_size(const igraph_adjlist_t *al) { * in the adjacency list. */ void igraph_adjlist_sort(igraph_adjlist_t *al) { - igraph_integer_t i; + igraph_int_t i; for (i = 0; i < al->length; i++) { igraph_vector_int_sort(&al->adjs[i]); } @@ -533,17 +533,17 @@ void igraph_adjlist_sort(igraph_adjlist_t *al) { * vertices. */ igraph_error_t igraph_adjlist_simplify(igraph_adjlist_t *al) { - igraph_integer_t i; - igraph_integer_t n = al->length; + igraph_int_t i; + igraph_int_t n = al->length; igraph_vector_int_t mark; IGRAPH_VECTOR_INT_INIT_FINALLY(&mark, n); for (i = 0; i < n; i++) { igraph_vector_int_t *v = &al->adjs[i]; - igraph_integer_t j, l = igraph_vector_int_size(v); + igraph_int_t j, l = igraph_vector_int_size(v); VECTOR(mark)[i] = i + 1; for (j = 0; j < l; /* nothing */) { - igraph_integer_t e = VECTOR(*v)[j]; + igraph_int_t e = VECTOR(*v)[j]; if (VECTOR(mark)[e] != i + 1) { VECTOR(mark)[e] = i + 1; j++; @@ -562,8 +562,8 @@ igraph_error_t igraph_adjlist_simplify(igraph_adjlist_t *al) { #ifndef USING_R igraph_error_t igraph_adjlist_print(const igraph_adjlist_t *al) { - igraph_integer_t i; - igraph_integer_t n = al->length; + igraph_int_t i; + igraph_int_t n = al->length; for (i = 0; i < n; i++) { igraph_vector_int_t *v = &al->adjs[i]; igraph_vector_int_print(v); @@ -573,8 +573,8 @@ igraph_error_t igraph_adjlist_print(const igraph_adjlist_t *al) { #endif igraph_error_t igraph_adjlist_fprint(const igraph_adjlist_t *al, FILE *outfile) { - igraph_integer_t i; - igraph_integer_t n = al->length; + igraph_int_t i; + igraph_int_t n = al->length; for (i = 0; i < n; i++) { igraph_vector_int_t *v = &al->adjs[i]; igraph_vector_int_fprint(v, outfile); @@ -584,7 +584,7 @@ igraph_error_t igraph_adjlist_fprint(const igraph_adjlist_t *al, FILE *outfile) #define ADJLIST_CANON_EDGE(from, to, directed) \ do { \ - igraph_integer_t temp; \ + igraph_int_t temp; \ if ((!directed) && from < to) { \ temp = to; \ to = from; \ @@ -605,7 +605,7 @@ igraph_error_t igraph_adjlist_fprint(const igraph_adjlist_t *al, FILE *outfile) igraph_bool_t igraph_adjlist_has_edge( igraph_adjlist_t* al, - igraph_integer_t from, igraph_integer_t to, + igraph_int_t from, igraph_int_t to, igraph_bool_t directed) { const igraph_vector_int_t *fromvec; @@ -616,13 +616,13 @@ igraph_bool_t igraph_adjlist_has_edge( igraph_error_t igraph_adjlist_replace_edge( igraph_adjlist_t* al, - igraph_integer_t from, igraph_integer_t oldto, igraph_integer_t newto, + igraph_int_t from, igraph_int_t oldto, igraph_int_t newto, igraph_bool_t directed) { igraph_vector_int_t *oldfromvec, *newfromvec; igraph_bool_t found_old, found_new; - igraph_integer_t oldpos, newpos; - igraph_integer_t oldfrom = from, newfrom = from; + igraph_int_t oldpos, newpos; + igraph_int_t oldfrom = from, newfrom = from; ADJLIST_CANON_EDGE(oldfrom, oldto, directed); ADJLIST_CANON_EDGE(newfrom, newto, directed); @@ -662,8 +662,8 @@ igraph_error_t igraph_adjlist_replace_edge( #ifndef USING_R igraph_error_t igraph_inclist_print(const igraph_inclist_t *al) { - igraph_integer_t i; - igraph_integer_t n = al->length; + igraph_int_t i; + igraph_int_t n = al->length; for (i = 0; i < n; i++) { igraph_vector_int_t *v = &al->incs[i]; igraph_vector_int_print(v); @@ -673,8 +673,8 @@ igraph_error_t igraph_inclist_print(const igraph_inclist_t *al) { #endif igraph_error_t igraph_inclist_fprint(const igraph_inclist_t *al, FILE *outfile) { - igraph_integer_t i; - igraph_integer_t n = al->length; + igraph_int_t i; + igraph_int_t n = al->length; for (i = 0; i < n; i++) { igraph_vector_int_t *v = &al->incs[i]; igraph_vector_int_fprint(v, outfile); @@ -727,7 +727,7 @@ igraph_error_t igraph_inclist_init(const igraph_t *graph, igraph_inclist_t *il, igraph_neimode_t mode, igraph_loops_t loops) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degrees; int iter = 0; @@ -750,7 +750,7 @@ igraph_error_t igraph_inclist_init(const igraph_t *graph, } IGRAPH_FINALLY(igraph_inclist_destroy, il); - for (igraph_integer_t i = 0; i < il->length; i++) { + for (igraph_int_t i = 0; i < il->length; i++) { IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1000); IGRAPH_CHECK(igraph_vector_int_init(&il->incs[i], VECTOR(degrees)[i])); @@ -778,8 +778,8 @@ igraph_error_t igraph_inclist_init(const igraph_t *graph, * Time complexity: O(n), linear in the number of vertices. */ -igraph_error_t igraph_inclist_init_empty(igraph_inclist_t *il, igraph_integer_t n) { - igraph_integer_t i; +igraph_error_t igraph_inclist_init_empty(igraph_inclist_t *il, igraph_int_t n) { + igraph_int_t i; il->length = n; il->incs = IGRAPH_CALLOC(il->length, igraph_vector_int_t); @@ -806,7 +806,7 @@ igraph_error_t igraph_inclist_init_empty(igraph_inclist_t *il, igraph_integer_t */ void igraph_inclist_destroy(igraph_inclist_t *il) { - for (igraph_integer_t i = 0; i < il->length; i++) { + for (igraph_int_t i = 0; i < il->length; i++) { /* This works if some igraph_vector_int_t's contain NULL, because igraph_vector_int_destroy can handle this. */ igraph_vector_int_destroy(&il->incs[i]); @@ -826,7 +826,7 @@ void igraph_inclist_destroy(igraph_inclist_t *il) { * Time complexity: O(n), where n is the size of the incidence list. */ void igraph_inclist_clear(igraph_inclist_t *il) { - igraph_integer_t i; + igraph_int_t i; for (i = 0; i < il->length; i++) { igraph_vector_int_clear(&il->incs[i]); } @@ -841,13 +841,13 @@ void igraph_inclist_clear(igraph_inclist_t *il) { * * Time complexity: O(1). */ -igraph_integer_t igraph_inclist_size(const igraph_inclist_t *il) { +igraph_int_t igraph_inclist_size(const igraph_inclist_t *il) { return il->length; } /* See the prototype above for a description of this function. */ static igraph_error_t igraph_i_simplify_sorted_int_adjacency_vector_in_place( - igraph_vector_int_t *v, igraph_integer_t index, igraph_neimode_t mode, + igraph_vector_int_t *v, igraph_int_t index, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple, igraph_bool_t *has_loops, igraph_bool_t *has_multiple @@ -859,8 +859,8 @@ static igraph_error_t igraph_i_simplify_sorted_int_adjacency_vector_in_place( if (has_multiple == NULL) { has_multiple = &dummy2; } - igraph_integer_t i, p = 0; - igraph_integer_t n = igraph_vector_int_size(v); + igraph_int_t i, p = 0; + igraph_int_t n = igraph_vector_int_size(v); if ( multiple == IGRAPH_MULTIPLE && @@ -1108,7 +1108,7 @@ void igraph_lazy_adjlist_destroy(igraph_lazy_adjlist_t *al) { * the total number of elements in the adjacency list. */ void igraph_lazy_adjlist_clear(igraph_lazy_adjlist_t *al) { - igraph_integer_t i, n = al->length; + igraph_int_t i, n = al->length; for (i = 0; i < n; i++) { if (al->adjs[i] != 0) { igraph_vector_int_destroy(al->adjs[i]); @@ -1126,11 +1126,11 @@ void igraph_lazy_adjlist_clear(igraph_lazy_adjlist_t *al) { * * Time complexity: O(1). */ -igraph_integer_t igraph_lazy_adjlist_size(const igraph_lazy_adjlist_t *al) { +igraph_int_t igraph_lazy_adjlist_size(const igraph_lazy_adjlist_t *al) { return al->length; } -igraph_vector_int_t *igraph_i_lazy_adjlist_get_real(igraph_lazy_adjlist_t *al, igraph_integer_t no) { +igraph_vector_int_t *igraph_i_lazy_adjlist_get_real(igraph_lazy_adjlist_t *al, igraph_int_t no) { igraph_error_t ret; if (al->adjs[no] == NULL) { @@ -1249,7 +1249,7 @@ void igraph_lazy_inclist_destroy(igraph_lazy_inclist_t *il) { * the total number of elements in the incidence list. */ void igraph_lazy_inclist_clear(igraph_lazy_inclist_t *il) { - igraph_integer_t i, n = il->length; + igraph_int_t i, n = il->length; for (i = 0; i < n; i++) { if (il->incs[i] != 0) { igraph_vector_int_destroy(il->incs[i]); @@ -1267,11 +1267,11 @@ void igraph_lazy_inclist_clear(igraph_lazy_inclist_t *il) { * * Time complexity: O(1). */ -igraph_integer_t igraph_lazy_inclist_size(const igraph_lazy_inclist_t *il) { +igraph_int_t igraph_lazy_inclist_size(const igraph_lazy_inclist_t *il) { return il->length; } -igraph_vector_int_t *igraph_i_lazy_inclist_get_real(igraph_lazy_inclist_t *il, igraph_integer_t no) { +igraph_vector_int_t *igraph_i_lazy_inclist_get_real(igraph_lazy_inclist_t *il, igraph_int_t no) { igraph_error_t ret; if (il->incs[no] == NULL) { diff --git a/src/vendor/cigraph/src/graph/attributes.c b/src/vendor/cigraph/src/graph/attributes.c index 03679a7f832..fd827f67bbd 100644 --- a/src/vendor/cigraph/src/graph/attributes.c +++ b/src/vendor/cigraph/src/graph/attributes.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -290,7 +290,7 @@ igraph_error_t igraph_attribute_record_check_type( * \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_int_t igraph_attribute_record_size(const igraph_attribute_record_t *attr) { IGRAPH_ASSERT(attr != NULL); switch (attr->type) { @@ -326,9 +326,9 @@ igraph_integer_t igraph_attribute_record_size(const igraph_attribute_record_t *a * \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_attribute_record_t *attr, igraph_int_t new_size ) { - igraph_integer_t i; + igraph_int_t i; igraph_vector_t *vec; igraph_vector_bool_t *log; igraph_strvector_t *str; @@ -644,7 +644,7 @@ igraph_error_t igraph_i_attribute_copy(igraph_t *to, const igraph_t *from, igrap } igraph_error_t igraph_i_attribute_add_vertices( - igraph_t *graph, igraph_integer_t nv, const igraph_attribute_record_list_t *attr + igraph_t *graph, igraph_int_t nv, const igraph_attribute_record_list_t *attr ) { if (igraph_i_attribute_table) { return igraph_i_attribute_table->add_vertices(graph, nv, attr); @@ -926,7 +926,7 @@ igraph_error_t igraph_attribute_combination_init(igraph_attribute_combination_t attribute combination list. */ void igraph_attribute_combination_destroy(igraph_attribute_combination_t *comb) { - igraph_integer_t i, n = igraph_vector_ptr_size(&comb->list); + igraph_int_t i, n = igraph_vector_ptr_size(&comb->list); for (i = 0; i < n; i++) { igraph_attribute_combination_record_t *rec = VECTOR(comb->list)[i]; if (rec->name) { @@ -965,7 +965,7 @@ igraph_error_t igraph_attribute_combination_add(igraph_attribute_combination_t * const char *name, igraph_attribute_combination_type_t type, igraph_function_pointer_t func) { - igraph_integer_t i, n = igraph_vector_ptr_size(&comb->list); + igraph_int_t i, n = igraph_vector_ptr_size(&comb->list); /* Search, in case it is already there */ for (i = 0; i < n; i++) { @@ -1025,7 +1025,7 @@ igraph_error_t igraph_attribute_combination_add(igraph_attribute_combination_t * */ igraph_error_t igraph_attribute_combination_remove(igraph_attribute_combination_t *comb, const char *name) { - igraph_integer_t i, n = igraph_vector_ptr_size(&comb->list); + igraph_int_t i, n = igraph_vector_ptr_size(&comb->list); /* Search, in case it is already there */ for (i = 0; i < n; i++) { @@ -1055,7 +1055,7 @@ igraph_error_t igraph_attribute_combination_query(const igraph_attribute_combina const char *name, igraph_attribute_combination_type_t *type, igraph_function_pointer_t *func) { - igraph_integer_t i, def = -1, len = igraph_vector_ptr_size(&comb->list); + igraph_int_t i, def = -1, len = igraph_vector_ptr_size(&comb->list); for (i = 0; i < len; i++) { igraph_attribute_combination_record_t *rec = VECTOR(comb->list)[i]; diff --git a/src/vendor/cigraph/src/graph/attributes.h b/src/vendor/cigraph/src/graph/attributes.h index 257a83d50da..91fdf48144c 100644 --- a/src/vendor/cigraph/src/graph/attributes.h +++ b/src/vendor/cigraph/src/graph/attributes.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,7 +35,7 @@ igraph_error_t igraph_i_attribute_copy( 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, + igraph_t *graph, igraph_int_t nv, const igraph_attribute_record_list_t *attr ); igraph_error_t igraph_i_attribute_permute_vertices(const igraph_t *graph, diff --git a/src/vendor/cigraph/src/graph/basic_query.c b/src/vendor/cigraph/src/graph/basic_query.c index 780fddf9e63..c58d19bd09e 100644 --- a/src/vendor/cigraph/src/graph/basic_query.c +++ b/src/vendor/cigraph/src/graph/basic_query.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -46,11 +46,11 @@ * d1 is the (out-)degree of \p v1 and d2 is the (in-)degree of \p v2. */ igraph_error_t igraph_are_adjacent(const igraph_t *graph, - igraph_integer_t v1, igraph_integer_t v2, + igraph_int_t v1, igraph_int_t v2, igraph_bool_t *res) { - igraph_integer_t nov = igraph_vcount(graph); - igraph_integer_t eid = -1; + igraph_int_t nov = igraph_vcount(graph); + igraph_int_t eid = -1; if (v1 < 0 || v2 < 0 || v1 > nov - 1 || v2 > nov - 1) { IGRAPH_ERROR("Invalid vertex ID when checking if two vertices are connected.", IGRAPH_EINVVID); diff --git a/src/vendor/cigraph/src/graph/caching.c b/src/vendor/cigraph/src/graph/caching.c index e7c4d9595c7..6710bf7d087 100644 --- a/src/vendor/cigraph/src/graph/caching.c +++ b/src/vendor/cigraph/src/graph/caching.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/graph/caching.h b/src/vendor/cigraph/src/graph/caching.h index 52459b8a8b5..d82c926493c 100644 --- a/src/vendor/cigraph/src/graph/caching.h +++ b/src/vendor/cigraph/src/graph/caching.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/graph/cattributes.c b/src/vendor/cigraph/src/graph/cattributes.c index 7ff60db13ff..70031f7beed 100644 --- a/src/vendor/cigraph/src/graph/cattributes.c +++ b/src/vendor/cigraph/src/graph/cattributes.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -44,11 +44,11 @@ typedef struct igraph_i_cattributes_t { * 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( +static igraph_int_t igraph_i_cattribute_find_index( const igraph_attribute_record_list_t *attrs, const char *name ) { - igraph_integer_t n = igraph_attribute_record_list_size(attrs); - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t n = igraph_attribute_record_list_size(attrs); + for (igraph_int_t i = 0; i < n; i++) { const igraph_attribute_record_t *rec = igraph_attribute_record_list_get_ptr(attrs, i); if (!strcmp(rec->name, name)) { return i; @@ -67,7 +67,7 @@ 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_int_t index = igraph_i_cattribute_find_index(attrs, name); igraph_attribute_record_t *rec; if (index >= 0) { @@ -88,7 +88,7 @@ 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_int_t index = igraph_i_cattribute_find_index(attrs, name); const igraph_attribute_record_t *rec; if (index >= 0) { @@ -142,7 +142,7 @@ static igraph_error_t igraph_i_cattribute_find_or_return( 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_int_t length, igraph_attribute_record_t **ptr ) { igraph_attribute_record_t *rec; @@ -176,10 +176,10 @@ static igraph_error_t igraph_i_cattribute_find_or_create( * 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_attribute_record_list_t *attrlist, igraph_int_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_int_t no_of_attrs = igraph_attribute_record_list_size(attrlist); + for (igraph_int_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) { @@ -247,7 +247,7 @@ static igraph_error_t igraph_i_cattribute_copy( alto[1] = &attrto->val; alto[2] = &attrto->eal; - for (igraph_integer_t i = 0; i < 3; i++) { + for (igraph_int_t i = 0; i < 3; i++) { if (copy[i]) { IGRAPH_CHECK(igraph_attribute_record_list_init_copy(alto[i], alfrom[i])); } else { @@ -264,18 +264,18 @@ static igraph_error_t igraph_i_cattribute_copy( 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, + igraph_int_t newlen, igraph_int_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_int_t length; + igraph_int_t nattrno = nattr == NULL ? 0 : igraph_attribute_record_list_size(nattr); + igraph_int_t origlen = newlen - nv; IGRAPH_ASSERT(origlen >= 0); /* Find all the attributes that are newly added, and create new value vectors * for them in the original graph */ - for (igraph_integer_t i = 0; i < nattrno; i++) { + for (igraph_int_t i = 0; i < nattrno; i++) { const igraph_attribute_record_t *nattr_entry = igraph_attribute_record_list_get_ptr(nattr, i); const char *nname = nattr_entry->name; IGRAPH_CHECK(igraph_i_cattribute_find_or_create(val, nname, nattr_entry->type, origlen, NULL)); @@ -283,7 +283,7 @@ static igraph_error_t igraph_i_cattribute_add_vertices_or_edges_inner( /* Now append the new values */ length = igraph_attribute_record_list_size(val); - for (igraph_integer_t i = 0; i < length; i++) { + for (igraph_int_t i = 0; i < length; i++) { 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) @@ -339,10 +339,10 @@ static igraph_error_t igraph_i_cattribute_add_vertices_or_edges_inner( 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, + igraph_int_t newlen, igraph_int_t nv, const igraph_attribute_record_list_t *nattr ) { - igraph_integer_t origlen = newlen - nv; + igraph_int_t origlen = newlen - nv; igraph_error_t err = igraph_i_cattribute_add_vertices_or_edges_inner( val, newlen, nv, nattr ); @@ -368,7 +368,7 @@ static igraph_error_t igraph_i_cattribute_add_vertices_or_edges( } static igraph_error_t igraph_i_cattribute_add_vertices( - igraph_t *graph, igraph_integer_t nv, + igraph_t *graph, igraph_int_t nv, const igraph_attribute_record_list_t *nattr ) { igraph_i_cattributes_t *attr = graph->attr; @@ -379,11 +379,11 @@ typedef struct { igraph_vector_t *numeric; igraph_vector_bool_t *boolean; igraph_vector_ptr_t *strings; - igraph_integer_t length; + igraph_int_t length; } igraph_i_attribute_permutation_work_area_t; static igraph_error_t igraph_i_attribute_permutation_work_area_init( - igraph_i_attribute_permutation_work_area_t *work_area, igraph_integer_t length + igraph_i_attribute_permutation_work_area_t *work_area, igraph_int_t length ) { work_area->length = length; work_area->numeric = NULL; @@ -495,7 +495,7 @@ static igraph_error_t igraph_i_cattribute_permute_attribute_record_list( igraph_attribute_record_list_t *new_attrs, const igraph_vector_int_t *idx ) { - igraph_integer_t no_attrs, idxlen; + igraph_int_t no_attrs, idxlen; no_attrs = igraph_attribute_record_list_size(attrs); @@ -505,7 +505,7 @@ static igraph_error_t igraph_i_cattribute_permute_attribute_record_list( IGRAPH_FINALLY(igraph_attribute_record_list_clear, new_attrs); idxlen = igraph_vector_int_size(idx); - for (igraph_integer_t i = 0; i < no_attrs; i++) { + for (igraph_int_t 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; @@ -548,13 +548,13 @@ static igraph_error_t igraph_i_cattribute_permute_attribute_record_list( 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_int_t no_attrs = igraph_attribute_record_list_size(attrs); 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); + igraph_int_t idx_size = igraph_vector_int_size(idx); /* shortcut: don't allocate anything if there are no attributes */ if (no_attrs == 0) { @@ -566,7 +566,7 @@ static igraph_error_t igraph_i_cattribute_permute_attribute_record_list_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 (igraph_integer_t i = 0; i < no_attrs; i++) { + for (igraph_int_t i = 0; i < no_attrs; i++) { oldrec = igraph_attribute_record_list_get_ptr(attrs, i); switch (oldrec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: @@ -600,7 +600,7 @@ static igraph_error_t igraph_i_cattribute_permute_attribute_record_list_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 (igraph_integer_t i = 0; i < no_attrs; i++) { + for (igraph_int_t 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; @@ -617,7 +617,7 @@ static igraph_error_t igraph_i_cattribute_permute_attribute_record_list_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 (igraph_integer_t i = 0, j = 0; i < no_attrs; i++) { + for (igraph_int_t i = 0, j = 0; i < no_attrs; i++) { oldrec = igraph_attribute_record_list_get_ptr(attrs, i); if (oldrec->type != IGRAPH_ATTRIBUTE_STRING) { continue; @@ -631,7 +631,7 @@ static igraph_error_t igraph_i_cattribute_permute_attribute_record_list_in_place } igraph_i_attribute_permutation_work_area_release_stored_strvectors(&work_area); - for (igraph_integer_t i = 0; i < no_attrs; i++) { + for (igraph_int_t i = 0; i < no_attrs; i++) { oldrec = igraph_attribute_record_list_get_ptr(attrs, i); switch (oldrec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: @@ -689,14 +689,14 @@ static igraph_error_t igraph_i_cattributes_cn_sum(const igraph_attribute_record_ const igraph_vector_int_list_t *merges) { 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { igraph_real_t s = 0.0; const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + igraph_int_t n = igraph_vector_int_size(idx); + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; s += VECTOR(*oldv)[x]; } VECTOR(*newv)[i] = s; @@ -710,14 +710,14 @@ static igraph_error_t igraph_i_cattributes_cn_prod(const igraph_attribute_record const igraph_vector_int_list_t *merges) { 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { igraph_real_t s = 1.0; const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + igraph_int_t n = igraph_vector_int_size(idx); + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; s *= VECTOR(*oldv)[x]; } VECTOR(*newv)[i] = s; @@ -731,14 +731,14 @@ static igraph_error_t igraph_i_cattributes_cn_min(const igraph_attribute_record_ const igraph_vector_int_list_t *merges) { 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); igraph_real_t m = n > 0 ? VECTOR(*oldv)[ VECTOR(*idx)[0] ] : IGRAPH_NAN; - for (igraph_integer_t j = 1; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 1; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; igraph_real_t val = VECTOR(*oldv)[x]; if (val < m) { m = val; @@ -755,14 +755,14 @@ static igraph_error_t igraph_i_cattributes_cn_max(const igraph_attribute_record_ const igraph_vector_int_list_t *merges) { 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); igraph_real_t m = n > 0 ? VECTOR(*oldv)[ VECTOR(*idx)[0] ] : IGRAPH_NAN; - for (igraph_integer_t j = 1; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 1; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; igraph_real_t val = VECTOR(*oldv)[x]; if (val > m) { m = val; @@ -780,17 +780,17 @@ static igraph_error_t igraph_i_cattributes_cn_random(const igraph_attribute_reco 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = IGRAPH_NAN; } else if (n == 1) { VECTOR(*newv)[i] = VECTOR(*oldv)[ VECTOR(*idx)[0] ]; } else { - igraph_integer_t r = RNG_INTEGER(0, n - 1); + igraph_int_t r = RNG_INTEGER(0, n - 1); VECTOR(*newv)[i] = VECTOR(*oldv)[ VECTOR(*idx)[r] ]; } } @@ -804,11 +804,11 @@ static igraph_error_t igraph_i_cattributes_cn_first(const igraph_attribute_recor 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = IGRAPH_NAN; } else { @@ -825,11 +825,11 @@ static igraph_error_t igraph_i_cattributes_cn_last(const igraph_attribute_record 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = IGRAPH_NAN; } else { @@ -845,14 +845,14 @@ static igraph_error_t igraph_i_cattributes_cn_mean(const igraph_attribute_record const igraph_vector_int_list_t *merges) { 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); igraph_real_t s = n > 0 ? 0.0 : IGRAPH_NAN; - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; s += VECTOR(*oldv)[x]; } if (n > 0) { @@ -871,18 +871,18 @@ static igraph_error_t igraph_i_cattributes_cn_func(const igraph_attribute_record 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_int_t newlen = igraph_vector_int_list_size(merges); igraph_vector_t values; IGRAPH_VECTOR_INIT_FINALLY(&values, 0); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); IGRAPH_CHECK(igraph_vector_resize(&values, n)); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; VECTOR(values)[j] = VECTOR(*oldv)[x]; } @@ -903,17 +903,17 @@ static igraph_error_t igraph_i_cattributes_cb_random(const igraph_attribute_reco 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = 0; } else if (n == 1) { VECTOR(*newv)[i] = VECTOR(*oldv)[ VECTOR(*idx)[0] ]; } else { - igraph_integer_t r = RNG_INTEGER(0, n - 1); + igraph_int_t r = RNG_INTEGER(0, n - 1); VECTOR(*newv)[i] = VECTOR(*oldv)[ VECTOR(*idx)[r] ]; } } @@ -927,11 +927,11 @@ static igraph_error_t igraph_i_cattributes_cb_first(const igraph_attribute_recor 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = 0; } else { @@ -948,11 +948,11 @@ static igraph_error_t igraph_i_cattributes_cb_last(const igraph_attribute_record 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { VECTOR(*newv)[i] = 0; } else { @@ -969,14 +969,14 @@ static igraph_error_t igraph_i_cattributes_cb_all_is_true(const igraph_attribute 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); VECTOR(*newv)[i] = 1; - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; if (!VECTOR(*oldv)[x]) { VECTOR(*newv)[i] = 0; break; @@ -993,14 +993,14 @@ static igraph_error_t igraph_i_cattributes_cb_any_is_true(const igraph_attribute 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); VECTOR(*newv)[i] = 0; - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; if (VECTOR(*oldv)[x]) { VECTOR(*newv)[i] = 1; break; @@ -1017,15 +1017,15 @@ static igraph_error_t igraph_i_cattributes_cb_majority(const igraph_attribute_re 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); - igraph_integer_t num_trues = 0; - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + igraph_int_t num_trues = 0; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; if (VECTOR(*oldv)[x]) { num_trues++; } @@ -1052,18 +1052,18 @@ static igraph_error_t igraph_i_cattributes_cb_func(const igraph_attribute_record 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_int_t newlen = igraph_vector_int_list_size(merges); igraph_vector_bool_t values; IGRAPH_VECTOR_BOOL_INIT_FINALLY(&values, 0); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); IGRAPH_CHECK(igraph_vector_bool_resize(&values, n)); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; VECTOR(values)[j] = VECTOR(*oldv)[x]; } @@ -1084,11 +1084,11 @@ static igraph_error_t igraph_i_cattributes_sn_random(const igraph_attribute_reco 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_int_t newlen = igraph_vector_int_list_size(merges); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); const char *tmp; if (n == 0) { IGRAPH_CHECK(igraph_strvector_set(newv, i, "")); @@ -1096,7 +1096,7 @@ static igraph_error_t igraph_i_cattributes_sn_random(const igraph_attribute_reco tmp = igraph_strvector_get(oldv, 0); IGRAPH_CHECK(igraph_strvector_set(newv, i, tmp)); } else { - igraph_integer_t r = RNG_INTEGER(0, n - 1); + igraph_int_t r = RNG_INTEGER(0, n - 1); tmp = igraph_strvector_get(oldv, r); IGRAPH_CHECK(igraph_strvector_set(newv, i, tmp)); } @@ -1110,12 +1110,12 @@ static igraph_error_t igraph_i_cattributes_cs_first(const igraph_attribute_recor const igraph_vector_int_list_t *merges) { const igraph_strvector_t *oldv = oldrec->value.as_strvector; - igraph_integer_t newlen = igraph_vector_int_list_size(merges); + igraph_int_t newlen = igraph_vector_int_list_size(merges); igraph_strvector_t *newv = newrec->value.as_strvector; - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { IGRAPH_CHECK(igraph_strvector_set(newv, i, "")); } else { @@ -1132,12 +1132,12 @@ static igraph_error_t igraph_i_cattributes_cs_last(const igraph_attribute_record const igraph_vector_int_list_t *merges) { const igraph_strvector_t *oldv = oldrec->value.as_strvector; - igraph_integer_t newlen = igraph_vector_int_list_size(merges); + igraph_int_t newlen = igraph_vector_int_list_size(merges); igraph_strvector_t *newv = newrec->value.as_strvector; - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); if (n == 0) { IGRAPH_CHECK(igraph_strvector_set(newv, i, "")); } else { @@ -1154,16 +1154,16 @@ static igraph_error_t igraph_i_cattributes_cs_concat(const igraph_attribute_reco const igraph_vector_int_list_t *merges) { const igraph_strvector_t *oldv = oldrec->value.as_strvector; - igraph_integer_t newlen = igraph_vector_int_list_size(merges); + igraph_int_t newlen = igraph_vector_int_list_size(merges); igraph_strvector_t *newv = newrec->value.as_strvector; - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); size_t len = 0; const char *tmp; char *tmp2; - for (igraph_integer_t j = 0; j < n; j++) { + for (igraph_int_t j = 0; j < n; j++) { tmp = igraph_strvector_get(oldv, j); len += strlen(tmp); } @@ -1171,7 +1171,7 @@ static igraph_error_t igraph_i_cattributes_cs_concat(const igraph_attribute_reco IGRAPH_CHECK_OOM(tmp2, "Cannot combine attributes."); IGRAPH_FINALLY(igraph_free, tmp2); len = 0; - for (igraph_integer_t j = 0; j < n; j++) { + for (igraph_int_t j = 0; j < n; j++) { tmp = igraph_strvector_get(oldv, j); strcpy(tmp2 + len, tmp); len += strlen(tmp); @@ -1192,18 +1192,18 @@ static igraph_error_t igraph_i_cattributes_cs_func(const igraph_attribute_record 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_int_t newlen = igraph_vector_int_list_size(merges); igraph_strvector_t values; IGRAPH_STRVECTOR_INIT_FINALLY(&values, 0); - for (igraph_integer_t i = 0; i < newlen; i++) { + for (igraph_int_t i = 0; i < newlen; i++) { const igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i); - igraph_integer_t n = igraph_vector_int_size(idx); + igraph_int_t n = igraph_vector_int_size(idx); IGRAPH_CHECK(igraph_strvector_resize(&values, n)); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t x = VECTOR(*idx)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t x = VECTOR(*idx)[j]; const char *elem = igraph_strvector_get(oldv, x); IGRAPH_CHECK(igraph_strvector_set(newv, j, elem)); } @@ -1268,7 +1268,7 @@ 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_int_t no_attrs = igraph_attribute_record_list_size(attrs); igraph_attribute_combination_todo_item_t *todo_items; IGRAPH_ASSERT(attrs != new_attrs); @@ -1278,7 +1278,7 @@ static igraph_error_t igraph_i_cattribute_combine_attribute_record_lists( IGRAPH_CHECK_OOM(todo_items, "Cannot combine attributes."); IGRAPH_FINALLY(igraph_free, todo_items); - for (igraph_integer_t i = 0; i < no_attrs; i++) { + for (igraph_int_t i = 0; i < no_attrs; i++) { const igraph_attribute_record_t *oldrec = igraph_attribute_record_list_get_ptr(attrs, i); const char *name = oldrec->name; igraph_attribute_combination_type_t type; @@ -1290,7 +1290,7 @@ static igraph_error_t igraph_i_cattribute_combine_attribute_record_lists( IGRAPH_FINALLY(igraph_attribute_record_list_clear, new_attrs); - for (igraph_integer_t i = 0; i < no_attrs; i++) { + for (igraph_int_t i = 0; i < no_attrs; i++) { const igraph_attribute_record_t *oldrec = igraph_attribute_record_list_get_ptr(attrs, i); igraph_attribute_record_t newrec; const char *name = oldrec->name; @@ -1461,7 +1461,7 @@ 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_int_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); } @@ -1502,11 +1502,11 @@ static igraph_error_t igraph_i_cattribute_get_info(const igraph_t *graph, igraph_i_cattributes_t *at = graph->attr; igraph_attribute_record_list_t *attr[3] = { &at->gal, &at->val, &at->eal }; - for (igraph_integer_t i = 0; i < 3; i++) { + for (igraph_int_t i = 0; i < 3; i++) { igraph_strvector_t *n = names[i]; igraph_vector_int_t *t = types[i]; const igraph_attribute_record_list_t *al = attr[i]; - igraph_integer_t len = igraph_attribute_record_list_size(al); + igraph_int_t len = igraph_attribute_record_list_size(al); if (n) { IGRAPH_CHECK(igraph_strvector_resize(n, len)); @@ -1515,7 +1515,7 @@ static igraph_error_t igraph_i_cattribute_get_info(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(t, len)); } - for (igraph_integer_t j = 0; j < len; j++) { + for (igraph_int_t j = 0; j < len; j++) { const 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; @@ -1634,12 +1634,12 @@ static igraph_error_t igraph_i_cattribute_get_numeric_vertex_attr(const igraph_t IGRAPH_CHECK(igraph_vector_append(value, num)); } else { igraph_vit_t it; - igraph_integer_t i = igraph_vector_size(value); + igraph_int_t i = igraph_vector_size(value); IGRAPH_CHECK(igraph_vit_create(graph, vs, &it)); IGRAPH_FINALLY(igraph_vit_destroy, &it); IGRAPH_CHECK(igraph_vector_resize(value, i + IGRAPH_VIT_SIZE(it))); for (; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) { - igraph_integer_t v = IGRAPH_VIT_GET(it); + igraph_int_t v = IGRAPH_VIT_GET(it); VECTOR(*value)[i] = VECTOR(*num)[v]; } igraph_vit_destroy(&it); @@ -1665,12 +1665,12 @@ static igraph_error_t igraph_i_cattribute_get_bool_vertex_attr(const igraph_t *g IGRAPH_CHECK(igraph_vector_bool_append(value, log)); } else { igraph_vit_t it; - igraph_integer_t i = igraph_vector_bool_size(value); + igraph_int_t i = igraph_vector_bool_size(value); IGRAPH_CHECK(igraph_vit_create(graph, vs, &it)); IGRAPH_FINALLY(igraph_vit_destroy, &it); IGRAPH_CHECK(igraph_vector_bool_resize(value, i + IGRAPH_VIT_SIZE(it))); for (; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) { - igraph_integer_t v = IGRAPH_VIT_GET(it); + igraph_int_t v = IGRAPH_VIT_GET(it); VECTOR(*value)[i] = VECTOR(*log)[v]; } igraph_vit_destroy(&it); @@ -1697,12 +1697,12 @@ static igraph_error_t igraph_i_cattribute_get_string_vertex_attr(const igraph_t IGRAPH_CHECK(igraph_strvector_append(value, str)); } else { igraph_vit_t it; - igraph_integer_t i = igraph_strvector_size(value); + igraph_int_t i = igraph_strvector_size(value); IGRAPH_CHECK(igraph_vit_create(graph, vs, &it)); IGRAPH_FINALLY(igraph_vit_destroy, &it); IGRAPH_CHECK(igraph_strvector_resize(value, i + IGRAPH_VIT_SIZE(it))); for (; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) { - igraph_integer_t v = IGRAPH_VIT_GET(it); + igraph_int_t v = IGRAPH_VIT_GET(it); IGRAPH_CHECK(igraph_strvector_set(value, i, igraph_strvector_get(str, v))); } igraph_vit_destroy(&it); @@ -1727,12 +1727,12 @@ static igraph_error_t igraph_i_cattribute_get_numeric_edge_attr( IGRAPH_CHECK(igraph_vector_append(value, num)); } else { igraph_eit_t it; - igraph_integer_t i = igraph_vector_size(value); + igraph_int_t i = igraph_vector_size(value); IGRAPH_CHECK(igraph_eit_create(graph, es, &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); IGRAPH_CHECK(igraph_vector_resize(value, i + IGRAPH_EIT_SIZE(it))); for (; !IGRAPH_EIT_END(it); IGRAPH_EIT_NEXT(it), i++) { - igraph_integer_t e = IGRAPH_EIT_GET(it); + igraph_int_t e = IGRAPH_EIT_GET(it); VECTOR(*value)[i] = VECTOR(*num)[e]; } igraph_eit_destroy(&it); @@ -1758,12 +1758,12 @@ static igraph_error_t igraph_i_cattribute_get_string_edge_attr( IGRAPH_CHECK(igraph_strvector_append(value, str)); } else { igraph_eit_t it; - igraph_integer_t i = igraph_strvector_size(value); + igraph_int_t i = igraph_strvector_size(value); IGRAPH_CHECK(igraph_eit_create(graph, es, &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); IGRAPH_CHECK(igraph_strvector_resize(value, i + IGRAPH_EIT_SIZE(it))); for (; !IGRAPH_EIT_END(it); IGRAPH_EIT_NEXT(it), i++) { - igraph_integer_t e = IGRAPH_EIT_GET(it); + igraph_int_t e = IGRAPH_EIT_GET(it); IGRAPH_CHECK(igraph_strvector_set(value, i, igraph_strvector_get(str, e))); } igraph_eit_destroy(&it); @@ -1789,12 +1789,12 @@ static igraph_error_t igraph_i_cattribute_get_bool_edge_attr( IGRAPH_CHECK(igraph_vector_bool_append(value, log)); } else { igraph_eit_t it; - igraph_integer_t i = igraph_vector_bool_size(value); + igraph_int_t i = igraph_vector_bool_size(value); IGRAPH_CHECK(igraph_eit_create(graph, es, &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); IGRAPH_CHECK(igraph_vector_bool_resize(value, i + IGRAPH_EIT_SIZE(it))); for (; !IGRAPH_EIT_END(it); IGRAPH_EIT_NEXT(it), i++) { - igraph_integer_t e = IGRAPH_EIT_GET(it); + igraph_int_t e = IGRAPH_EIT_GET(it); VECTOR(*value)[i] = VECTOR(*log)[e]; } igraph_eit_destroy(&it); @@ -1984,7 +1984,7 @@ const char *igraph_cattribute_GAS(const igraph_t *graph, const char *name) { * Time complexity: O(Av), the number of vertex attributes. */ igraph_real_t igraph_cattribute_VAN(const igraph_t *graph, const char *name, - igraph_integer_t vid) { + igraph_int_t vid) { igraph_i_cattributes_t *attr = graph->attr; const igraph_attribute_record_t *rec; const igraph_vector_t *num; @@ -2017,7 +2017,7 @@ igraph_real_t igraph_cattribute_VAN(const igraph_t *graph, const char *name, * Time complexity: O(Av), the number of vertex attributes. */ igraph_bool_t igraph_cattribute_VAB(const igraph_t *graph, const char *name, - igraph_integer_t vid) { + igraph_int_t vid) { igraph_i_cattributes_t *attr = graph->attr; const igraph_attribute_record_t *rec; const igraph_vector_bool_t *log; @@ -2052,7 +2052,7 @@ igraph_bool_t igraph_cattribute_VAB(const igraph_t *graph, const char *name, * Time complexity: O(Av), the number of vertex attributes. */ const char *igraph_cattribute_VAS(const igraph_t *graph, const char *name, - igraph_integer_t vid) { + igraph_int_t vid) { igraph_i_cattributes_t *attr = graph->attr; const igraph_attribute_record_t *rec; const igraph_strvector_t *str; @@ -2085,7 +2085,7 @@ const char *igraph_cattribute_VAS(const igraph_t *graph, const char *name, * Time complexity: O(Ae), the number of edge attributes. */ igraph_real_t igraph_cattribute_EAN(const igraph_t *graph, const char *name, - igraph_integer_t eid) { + igraph_int_t eid) { igraph_i_cattributes_t *attr = graph->attr; const igraph_attribute_record_t *rec; const igraph_vector_t *num; @@ -2118,7 +2118,7 @@ igraph_real_t igraph_cattribute_EAN(const igraph_t *graph, const char *name, * Time complexity: O(Ae), the number of edge attributes. */ igraph_bool_t igraph_cattribute_EAB(const igraph_t *graph, const char *name, - igraph_integer_t eid) { + igraph_int_t eid) { igraph_i_cattributes_t *attr = graph->attr; const igraph_attribute_record_t *rec; const igraph_vector_bool_t *log; @@ -2153,7 +2153,7 @@ igraph_bool_t igraph_cattribute_EAB(const igraph_t *graph, const char *name, * Time complexity: O(Ae), the number of edge attributes. */ const char *igraph_cattribute_EAS(const igraph_t *graph, const char *name, - igraph_integer_t eid) { + igraph_int_t eid) { igraph_i_cattributes_t *attr = graph->attr; const igraph_attribute_record_t *rec; const igraph_strvector_t *str; @@ -2447,7 +2447,7 @@ igraph_error_t igraph_cattribute_GAS_set(igraph_t *graph, const char *name, * new, O(|vid|) otherwise. */ igraph_error_t igraph_cattribute_VAN_set(igraph_t *graph, const char *name, - igraph_integer_t vid, igraph_real_t value) { + igraph_int_t vid, igraph_real_t value) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_t *rec; @@ -2478,7 +2478,7 @@ igraph_error_t igraph_cattribute_VAN_set(igraph_t *graph, const char *name, * new, O(|vid|) otherwise. */ igraph_error_t igraph_cattribute_VAB_set(igraph_t *graph, const char *name, - igraph_integer_t vid, igraph_bool_t value) { + igraph_int_t vid, igraph_bool_t value) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_t *rec; @@ -2510,7 +2510,7 @@ igraph_error_t igraph_cattribute_VAB_set(igraph_t *graph, const char *name, * O(|vid|*l). */ igraph_error_t igraph_cattribute_VAS_set(igraph_t *graph, const char *name, - igraph_integer_t vid, const char *value) { + igraph_int_t vid, const char *value) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_t *rec; @@ -2541,7 +2541,7 @@ igraph_error_t igraph_cattribute_VAS_set(igraph_t *graph, const char *name, * new, O(|eid|) otherwise. */ igraph_error_t igraph_cattribute_EAN_set(igraph_t *graph, const char *name, - igraph_integer_t eid, igraph_real_t value) { + igraph_int_t eid, igraph_real_t value) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_t *rec; @@ -2572,7 +2572,7 @@ igraph_error_t igraph_cattribute_EAN_set(igraph_t *graph, const char *name, * new, O(|eid|) otherwise. */ igraph_error_t igraph_cattribute_EAB_set(igraph_t *graph, const char *name, - igraph_integer_t eid, igraph_bool_t value) { + igraph_int_t eid, igraph_bool_t value) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_t *rec; @@ -2604,7 +2604,7 @@ igraph_error_t igraph_cattribute_EAB_set(igraph_t *graph, const char *name, * O(|eid|*l). */ igraph_error_t igraph_cattribute_EAS_set(igraph_t *graph, const char *name, - igraph_integer_t eid, const char *value) { + igraph_int_t eid, const char *value) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_t *rec; @@ -2636,7 +2636,7 @@ 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_attribute_record_t *rec; - igraph_integer_t nv = igraph_vcount(graph); + igraph_int_t nv = igraph_vcount(graph); /* Check length first */ if (igraph_vector_size(v) != nv) { @@ -2669,7 +2669,7 @@ 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_attribute_record_t *rec; - igraph_integer_t nv = igraph_vcount(graph); + igraph_int_t nv = igraph_vcount(graph); /* Check length first */ if (igraph_vector_bool_size(v) != nv) { @@ -2702,7 +2702,7 @@ 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_attribute_record_t *rec; - igraph_integer_t nv = igraph_vcount(graph); + igraph_int_t nv = igraph_vcount(graph); /* Check length first */ if (igraph_strvector_size(sv) != nv) { @@ -2734,7 +2734,7 @@ 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_attribute_record_t *rec; - igraph_integer_t ne = igraph_ecount(graph); + igraph_int_t ne = igraph_ecount(graph); /* Check length first */ if (igraph_vector_size(v) != ne) { @@ -2766,7 +2766,7 @@ 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_attribute_record_t *rec; - igraph_integer_t ne = igraph_ecount(graph); + igraph_int_t ne = igraph_ecount(graph); /* Check length first */ if (igraph_vector_bool_size(v) != ne) { @@ -2799,7 +2799,7 @@ 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_attribute_record_t *rec; - igraph_integer_t ne = igraph_ecount(graph); + igraph_int_t ne = igraph_ecount(graph); /* Check length first */ if (igraph_strvector_size(sv) != ne) { @@ -2826,7 +2826,7 @@ void igraph_cattribute_remove_g(igraph_t *graph, const char *name) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_list_t *gal = &attr->gal; - igraph_integer_t j = igraph_i_cattribute_find_index(gal, name); + igraph_int_t j = igraph_i_cattribute_find_index(gal, name); if (j >= 0) { igraph_attribute_record_list_discard(gal, j); @@ -2849,7 +2849,7 @@ void igraph_cattribute_remove_v(igraph_t *graph, const char *name) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_list_t *val = &attr->val; - igraph_integer_t j = igraph_i_cattribute_find_index(val, name); + igraph_int_t j = igraph_i_cattribute_find_index(val, name); if (j >= 0) { igraph_attribute_record_list_discard(val, j); @@ -2871,7 +2871,7 @@ void igraph_cattribute_remove_e(igraph_t *graph, const char *name) { igraph_i_cattributes_t *attr = graph->attr; igraph_attribute_record_list_t *eal = &attr->eal; - igraph_integer_t j = igraph_i_cattribute_find_index(eal, name); + igraph_int_t j = igraph_i_cattribute_find_index(eal, name); if (j >= 0) { igraph_attribute_record_list_discard(eal, j); diff --git a/src/vendor/cigraph/src/graph/graph_list.c b/src/vendor/cigraph/src/graph/graph_list.c index 39ecc926526..a96ae6b92bb 100644 --- a/src/vendor/cigraph/src/graph/graph_list.c +++ b/src/vendor/cigraph/src/graph/graph_list.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/graph/internal.h b/src/vendor/cigraph/src/graph/internal.h index 0ab34f5ffc4..7acea1f9014 100644 --- a/src/vendor/cigraph/src/graph/internal.h +++ b/src/vendor/cigraph/src/graph/internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/graph/iterators.c b/src/vendor/cigraph/src/graph/iterators.c index f9aa111912b..d557b309344 100644 --- a/src/vendor/cigraph/src/graph/iterators.c +++ b/src/vendor/cigraph/src/graph/iterators.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -162,7 +162,7 @@ igraph_vs_t igraph_vss_all(void) { */ igraph_error_t igraph_vs_adj( - igraph_vs_t *vs, igraph_integer_t vid, igraph_neimode_t mode, + igraph_vs_t *vs, igraph_int_t vid, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple ) { vs->type = IGRAPH_VS_ADJ; @@ -210,7 +210,7 @@ igraph_error_t igraph_vs_adj( * \example examples/simple/igraph_vs_nonadj.c */ -igraph_error_t igraph_vs_nonadj(igraph_vs_t *vs, igraph_integer_t vid, +igraph_error_t igraph_vs_nonadj(igraph_vs_t *vs, igraph_int_t vid, igraph_neimode_t mode) { vs->type = IGRAPH_VS_NONADJ; vs->data.adj.vid = vid; @@ -270,7 +270,7 @@ igraph_vs_t igraph_vss_none(void) { * Time complexity: O(1). */ -igraph_error_t igraph_vs_1(igraph_vs_t *vs, igraph_integer_t vid) { +igraph_error_t igraph_vs_1(igraph_vs_t *vs, igraph_int_t vid) { vs->type = IGRAPH_VS_1; vs->data.vid = vid; return IGRAPH_SUCCESS; @@ -289,7 +289,7 @@ igraph_error_t igraph_vs_1(igraph_vs_t *vs, igraph_integer_t vid) { * Time complexity: O(1). */ -igraph_vs_t igraph_vss_1(igraph_integer_t vid) { +igraph_vs_t igraph_vss_1(igraph_int_t vid) { igraph_vs_t onevs; onevs.type = IGRAPH_VS_1; onevs.data.vid = vid; @@ -374,7 +374,7 @@ igraph_vs_t igraph_vss_vector(const igraph_vector_int_t *v) { igraph_error_t igraph_vs_vector_small(igraph_vs_t *vs, ...) { va_list ap; - igraph_integer_t i, n = 0; + igraph_int_t i, n = 0; igraph_vector_int_t* vec; vec = IGRAPH_CALLOC(1, igraph_vector_int_t); @@ -463,7 +463,7 @@ igraph_error_t igraph_vs_vector_copy(igraph_vs_t *vs, const igraph_vector_int_t * \example examples/simple/igraph_vs_range.c */ -igraph_error_t igraph_vs_range(igraph_vs_t *vs, igraph_integer_t start, igraph_integer_t end) { +igraph_error_t igraph_vs_range(igraph_vs_t *vs, igraph_int_t start, igraph_int_t end) { *vs = igraph_vss_range(start, end); return IGRAPH_SUCCESS; } @@ -482,7 +482,7 @@ igraph_error_t igraph_vs_range(igraph_vs_t *vs, igraph_integer_t start, igraph_i * Time complexity: O(1). */ -igraph_vs_t igraph_vss_range(igraph_integer_t start, igraph_integer_t end) { +igraph_vs_t igraph_vss_range(igraph_int_t start, igraph_int_t end) { igraph_vs_t vs; vs.type = IGRAPH_VS_RANGE; vs.data.range.start = start; @@ -608,11 +608,11 @@ igraph_vs_type_t igraph_vs_type(const igraph_vs_t *vs) { * \return Error code. */ igraph_error_t igraph_vs_size(const igraph_t *graph, const igraph_vs_t *vs, - igraph_integer_t *result) { + igraph_int_t *result) { igraph_vector_int_t vec; igraph_bool_t *seen; - igraph_integer_t i; - igraph_integer_t vec_len; + igraph_int_t i; + igraph_int_t vec_len; switch (vs->type) { case IGRAPH_VS_NONE: @@ -713,8 +713,8 @@ igraph_error_t igraph_vit_create(const igraph_t *graph, igraph_vs_t vs, igraph_v igraph_vector_int_t vec; igraph_vector_int_t *vec_int; igraph_bool_t *seen; - igraph_integer_t i, j, n; - igraph_integer_t vec_len; + igraph_int_t i, j, n; + igraph_int_t vec_len; switch (vs.type) { case IGRAPH_VS_ALL: @@ -815,7 +815,7 @@ igraph_error_t igraph_vit_create(const igraph_t *graph, igraph_vs_t vs, igraph_v break; case IGRAPH_VS_RANGE: { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (vs.data.range.start < 0 || vs.data.range.start > no_of_nodes || (no_of_nodes > 0 && vs.data.range.start == no_of_nodes)) { @@ -866,7 +866,7 @@ void igraph_vit_destroy(const igraph_vit_t *vit) { } igraph_error_t igraph_vit_as_vector(const igraph_vit_t *vit, igraph_vector_int_t *v) { - igraph_integer_t i; + igraph_int_t i; IGRAPH_CHECK(igraph_vector_int_resize(v, IGRAPH_VIT_SIZE(*vit))); @@ -980,7 +980,7 @@ igraph_es_t igraph_ess_all(igraph_edgeorder_type_t order) { */ igraph_error_t igraph_es_incident( - igraph_es_t *es, igraph_integer_t vid, igraph_neimode_t mode, + igraph_es_t *es, igraph_int_t vid, igraph_neimode_t mode, igraph_loops_t loops ) { es->type = IGRAPH_ES_INCIDENT; @@ -1038,7 +1038,7 @@ igraph_es_t igraph_ess_none(void) { * Time complexity: O(1). */ -igraph_error_t igraph_es_1(igraph_es_t *es, igraph_integer_t eid) { +igraph_error_t igraph_es_1(igraph_es_t *es, igraph_int_t eid) { es->type = IGRAPH_ES_1; es->data.eid = eid; return IGRAPH_SUCCESS; @@ -1055,7 +1055,7 @@ igraph_error_t igraph_es_1(igraph_es_t *es, igraph_integer_t eid) { * Time complexity: O(1). */ -igraph_es_t igraph_ess_1(igraph_integer_t eid) { +igraph_es_t igraph_ess_1(igraph_int_t eid) { igraph_es_t es; es.type = IGRAPH_ES_1; es.data.eid = eid; @@ -1161,7 +1161,7 @@ igraph_es_t igraph_ess_vector(const igraph_vector_int_t *v) { * Time complexity: O(1). */ -igraph_error_t igraph_es_range(igraph_es_t *es, igraph_integer_t start, igraph_integer_t end) { +igraph_error_t igraph_es_range(igraph_es_t *es, igraph_int_t start, igraph_int_t end) { *es = igraph_ess_range(start, end); return IGRAPH_SUCCESS; } @@ -1178,7 +1178,7 @@ igraph_error_t igraph_es_range(igraph_es_t *es, igraph_integer_t start, igraph_i * Time complexity: O(1). */ -igraph_es_t igraph_ess_range(igraph_integer_t start, igraph_integer_t end) { +igraph_es_t igraph_ess_range(igraph_int_t start, igraph_int_t end) { igraph_es_t es; es.type = IGRAPH_ES_RANGE; es.data.range.start = start; @@ -1255,7 +1255,7 @@ igraph_error_t igraph_es_pairs(igraph_es_t *es, const igraph_vector_int_t *v, igraph_error_t igraph_es_pairs_small(igraph_es_t *es, igraph_bool_t directed, int first, ...) { va_list ap; - igraph_integer_t i, n = 0; + igraph_int_t i, n = 0; igraph_vector_int_t *vec; int num; @@ -1328,7 +1328,7 @@ igraph_error_t igraph_es_path(igraph_es_t *es, const igraph_vector_int_t *v, igraph_error_t igraph_es_path_small(igraph_es_t *es, igraph_bool_t directed, int first, ...) { va_list ap; - igraph_integer_t i, n = 0; + igraph_int_t i, n = 0; igraph_vector_int_t *vec; int num; @@ -1382,7 +1382,7 @@ igraph_error_t igraph_es_path_small(igraph_es_t *es, igraph_bool_t directed, int * Time complexity: O(1). */ igraph_error_t igraph_es_all_between( - igraph_es_t *es, igraph_integer_t from, igraph_integer_t to, + igraph_es_t *es, igraph_int_t from, igraph_int_t to, igraph_bool_t directed ) { es->type = IGRAPH_ES_ALL_BETWEEN; @@ -1522,11 +1522,11 @@ igraph_es_type_t igraph_es_type(const igraph_es_t *es) { } static igraph_error_t igraph_i_es_pairs_size(const igraph_t *graph, - const igraph_es_t *es, igraph_integer_t *result); + const igraph_es_t *es, igraph_int_t *result); static igraph_error_t igraph_i_es_path_size(const igraph_t *graph, - const igraph_es_t *es, igraph_integer_t *result); + const igraph_es_t *es, igraph_int_t *result); static igraph_error_t igraph_i_es_all_between_size(const igraph_t *graph, - const igraph_es_t *es, igraph_integer_t *result); + const igraph_es_t *es, igraph_int_t *result); /** * \function igraph_es_size @@ -1541,7 +1541,7 @@ static igraph_error_t igraph_i_es_all_between_size(const igraph_t *graph, * \return Error code. */ igraph_error_t igraph_es_size(const igraph_t *graph, const igraph_es_t *es, - igraph_integer_t *result) { + igraph_int_t *result) { igraph_vector_int_t v; switch (es->type) { @@ -1608,9 +1608,9 @@ igraph_error_t igraph_es_size(const igraph_t *graph, const igraph_es_t *es, } static igraph_error_t igraph_i_es_pairs_size(const igraph_t *graph, - const igraph_es_t *es, igraph_integer_t *result) { - igraph_integer_t i, n = igraph_vector_int_size(es->data.path.ptr); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_es_t *es, igraph_int_t *result) { + igraph_int_t i, n = igraph_vector_int_size(es->data.path.ptr); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (n % 2 != 0) { IGRAPH_ERROR("Cannot calculate edge selector length from odd number of vertices.", @@ -1623,9 +1623,9 @@ static igraph_error_t igraph_i_es_pairs_size(const igraph_t *graph, *result = n / 2; /* Check for the existence of all edges */ for (i = 0; i < *result; i++) { - igraph_integer_t from = VECTOR(*es->data.path.ptr)[2 * i]; - igraph_integer_t to = VECTOR(*es->data.path.ptr)[2 * i + 1]; - igraph_integer_t eid; + igraph_int_t from = VECTOR(*es->data.path.ptr)[2 * i]; + igraph_int_t to = VECTOR(*es->data.path.ptr)[2 * i + 1]; + igraph_int_t eid; IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es->data.path.mode, /*error=*/ 1)); } @@ -1634,9 +1634,9 @@ static igraph_error_t igraph_i_es_pairs_size(const igraph_t *graph, } static igraph_error_t igraph_i_es_path_size(const igraph_t *graph, - const igraph_es_t *es, igraph_integer_t *result) { - igraph_integer_t i, n = igraph_vector_int_size(es->data.path.ptr); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_es_t *es, igraph_int_t *result) { + igraph_int_t i, n = igraph_vector_int_size(es->data.path.ptr); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (!igraph_vector_int_isininterval(es->data.path.ptr, 0, no_of_nodes - 1)) { IGRAPH_ERROR("Cannot calculate selector length.", IGRAPH_EINVVID); @@ -1648,9 +1648,9 @@ static igraph_error_t igraph_i_es_path_size(const igraph_t *graph, *result = n - 1; } for (i = 0; i < *result; i++) { - igraph_integer_t from = VECTOR(*es->data.path.ptr)[i]; - igraph_integer_t to = VECTOR(*es->data.path.ptr)[i + 1]; - igraph_integer_t eid; + igraph_int_t from = VECTOR(*es->data.path.ptr)[i]; + igraph_int_t to = VECTOR(*es->data.path.ptr)[i + 1]; + igraph_int_t eid; IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es->data.path.mode, /*error=*/ 1)); } @@ -1659,10 +1659,10 @@ static igraph_error_t igraph_i_es_path_size(const igraph_t *graph, } static igraph_error_t igraph_i_es_all_between_size(const igraph_t *graph, - const igraph_es_t *es, igraph_integer_t *result) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t from = es->data.between.from; - igraph_integer_t to = es->data.between.to; + const igraph_es_t *es, igraph_int_t *result) { + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t from = es->data.between.from; + igraph_int_t to = es->data.between.to; igraph_bool_t directed = es->data.between.directed; igraph_vector_int_t vec; @@ -1695,8 +1695,8 @@ static igraph_error_t igraph_i_eit_create_allfromto(const igraph_t *graph, igraph_eit_t *eit, igraph_neimode_t mode) { igraph_vector_int_t *vec; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); vec = IGRAPH_CALLOC(1, igraph_vector_int_t); IGRAPH_CHECK_OOM(vec, "Cannot create edge iterator."); @@ -1708,7 +1708,7 @@ static igraph_error_t igraph_i_eit_create_allfromto(const igraph_t *graph, if (igraph_is_directed(graph)) { igraph_vector_int_t adj; IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_incident(graph, &adj, i, mode, IGRAPH_LOOPS)); igraph_vector_int_append(vec, &adj); /* reserved */ } @@ -1721,10 +1721,10 @@ static igraph_error_t igraph_i_eit_create_allfromto(const igraph_t *graph, added = IGRAPH_CALLOC(no_of_edges, igraph_bool_t); IGRAPH_CHECK_OOM(added, "Cannot create edge iterator."); IGRAPH_FINALLY(igraph_free, added); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_incident(graph, &adj, i, IGRAPH_ALL, IGRAPH_LOOPS)); - const igraph_integer_t length = igraph_vector_int_size(&adj); - for (igraph_integer_t j = 0; j < length; j++) { + const igraph_int_t length = igraph_vector_int_size(&adj); + for (igraph_int_t j = 0; j < length; j++) { if (!added[ VECTOR(adj)[j] ]) { igraph_vector_int_push_back(vec, VECTOR(adj)[j]); /* reserved */ added[ VECTOR(adj)[j] ] = true; @@ -1750,7 +1750,7 @@ static igraph_error_t igraph_i_eit_create_incident(const igraph_t* graph, igraph_es_t es, igraph_eit_t *eit) { igraph_vector_int_t vec; igraph_vector_int_t* vec_int; - igraph_integer_t i, n; + igraph_int_t i, n; IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0); IGRAPH_CHECK(igraph_incident( @@ -1783,9 +1783,9 @@ static igraph_error_t igraph_i_eit_create_incident(const igraph_t* graph, static igraph_error_t igraph_i_eit_pairs(const igraph_t *graph, igraph_es_t es, igraph_eit_t *eit) { - igraph_integer_t n = igraph_vector_int_size(es.data.path.ptr); - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i; + igraph_int_t n = igraph_vector_int_size(es.data.path.ptr); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i; igraph_vector_int_t* vec; if (n % 2 != 0) { @@ -1802,9 +1802,9 @@ static igraph_error_t igraph_i_eit_pairs(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(vec, n / 2); for (i = 0; i < n / 2; i++) { - igraph_integer_t from = VECTOR(*es.data.path.ptr)[2 * i]; - igraph_integer_t to = VECTOR(*es.data.path.ptr)[2 * i + 1]; - igraph_integer_t eid; + igraph_int_t from = VECTOR(*es.data.path.ptr)[2 * i]; + igraph_int_t to = VECTOR(*es.data.path.ptr)[2 * i + 1]; + igraph_int_t eid; IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es.data.path.mode, /*error=*/ 1)); VECTOR(*vec)[i] = eid; @@ -1823,9 +1823,9 @@ static igraph_error_t igraph_i_eit_pairs(const igraph_t *graph, static igraph_error_t igraph_i_eit_path(const igraph_t *graph, igraph_es_t es, igraph_eit_t *eit) { - igraph_integer_t n = igraph_vector_int_size(es.data.path.ptr); - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i, len; + igraph_int_t n = igraph_vector_int_size(es.data.path.ptr); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i, len; igraph_vector_int_t* vec; if (!igraph_vector_int_isininterval(es.data.path.ptr, 0, no_of_nodes - 1)) { @@ -1845,9 +1845,9 @@ static igraph_error_t igraph_i_eit_path(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(vec, len); for (i = 0; i < len; i++) { - igraph_integer_t from = VECTOR(*es.data.path.ptr)[i]; - igraph_integer_t to = VECTOR(*es.data.path.ptr)[i + 1]; - igraph_integer_t eid; + igraph_int_t from = VECTOR(*es.data.path.ptr)[i]; + igraph_int_t to = VECTOR(*es.data.path.ptr)[i + 1]; + igraph_int_t eid; IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es.data.path.mode, /*error=*/ 1)); VECTOR(*vec)[i] = eid; @@ -1867,10 +1867,10 @@ static igraph_error_t igraph_i_eit_path(const igraph_t *graph, static igraph_error_t igraph_i_eit_all_between( const igraph_t *graph, igraph_es_t es, igraph_eit_t *eit ) { - igraph_integer_t from = es.data.between.from; - igraph_integer_t to = es.data.between.to; + igraph_int_t from = es.data.between.from; + igraph_int_t to = es.data.between.to; igraph_bool_t directed = es.data.between.directed; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t* vec; if (from < 0 || from >= no_of_nodes || to < 0 || to >= no_of_nodes) { @@ -1964,7 +1964,7 @@ igraph_error_t igraph_eit_create(const igraph_t *graph, igraph_es_t es, igraph_e break; case IGRAPH_ES_RANGE: { - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); if (es.data.range.start < 0 || es.data.range.start > no_of_edges || (no_of_edges > 0 && es.data.range.start == no_of_edges)) { @@ -2022,7 +2022,7 @@ void igraph_eit_destroy(const igraph_eit_t *eit) { igraph_error_t igraph_eit_as_vector(const igraph_eit_t *eit, igraph_vector_int_t *v) { - igraph_integer_t i; + igraph_int_t i; IGRAPH_CHECK(igraph_vector_int_resize(v, IGRAPH_EIT_SIZE(*eit))); diff --git a/src/vendor/cigraph/src/graph/type_common.c b/src/vendor/cigraph/src/graph/type_common.c index dfe921ad2a8..44bf27ac903 100644 --- a/src/vendor/cigraph/src/graph/type_common.c +++ b/src/vendor/cigraph/src/graph/type_common.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -61,7 +61,7 @@ * * \example examples/simple/creation.c */ -igraph_error_t igraph_empty(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed) { +igraph_error_t igraph_empty(igraph_t *graph, igraph_int_t n, igraph_bool_t directed) { return igraph_empty_attrs(graph, n, directed, 0); } @@ -111,9 +111,9 @@ igraph_error_t igraph_delete_vertices_idx( * * \param graph The graph object. * \param eid The edge ID. - * \param from Pointer to an \type igraph_integer_t. The tail (source) of + * \param from Pointer to an \type igraph_int_t. The tail (source) of * the edge will be placed here. - * \param to Pointer to an \type igraph_integer_t. The head (target) of the + * \param to Pointer to an \type igraph_int_t. The head (target) of the * edge will be placed here. * \return Error code. * @@ -127,8 +127,8 @@ igraph_error_t igraph_delete_vertices_idx( * Time complexity: O(1). */ igraph_error_t igraph_edge( - const igraph_t *graph, igraph_integer_t eid, - igraph_integer_t *from, igraph_integer_t *to + const igraph_t *graph, igraph_int_t eid, + igraph_int_t *from, igraph_int_t *to ) { if (eid < 0 || eid >= igraph_ecount(graph)) { @@ -172,7 +172,7 @@ igraph_error_t igraph_edges( igraph_bool_t bycol ) { igraph_eit_t eit; - igraph_integer_t n, ptr = 0, ptr2; + igraph_int_t n, ptr = 0, ptr2; IGRAPH_CHECK(igraph_eit_create(graph, eids, &eit)); IGRAPH_FINALLY(igraph_eit_destroy, &eit); @@ -183,13 +183,13 @@ igraph_error_t igraph_edges( ptr2 = n; if (igraph_is_directed(graph)) { for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); + igraph_int_t e = IGRAPH_EIT_GET(eit); VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); VECTOR(*edges)[ptr2++] = IGRAPH_TO(graph, e); } } else { for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); + igraph_int_t e = IGRAPH_EIT_GET(eit); VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); VECTOR(*edges)[ptr2++] = IGRAPH_FROM(graph, e); } @@ -197,13 +197,13 @@ igraph_error_t igraph_edges( } else { if (igraph_is_directed(graph)) { for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); + igraph_int_t e = IGRAPH_EIT_GET(eit); VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); } } else { for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); + igraph_int_t e = IGRAPH_EIT_GET(eit); VECTOR(*edges)[ptr++] = IGRAPH_TO(graph, e); VECTOR(*edges)[ptr++] = IGRAPH_FROM(graph, e); } diff --git a/src/vendor/cigraph/src/graph/type_indexededgelist.c b/src/vendor/cigraph/src/graph/type_indexededgelist.c index c66088a6ceb..b8c42070ccc 100644 --- a/src/vendor/cigraph/src/graph/type_indexededgelist.c +++ b/src/vendor/cigraph/src/graph/type_indexededgelist.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team 334 Harvard street, Cambridge, MA 02139 USA @@ -33,7 +33,7 @@ static igraph_error_t igraph_i_create_start_vectors( igraph_vector_int_t *res, igraph_vector_int_t *el, - igraph_vector_int_t *index, igraph_integer_t nodes); + igraph_vector_int_t *index, igraph_int_t nodes); /** * \section about_basic_interface @@ -95,7 +95,7 @@ static igraph_error_t igraph_i_create_start_vectors( * |V| vertices (and no edges). */ igraph_error_t igraph_empty_attrs( - igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, + igraph_t *graph, igraph_int_t n, igraph_bool_t directed, const igraph_attribute_record_list_t *attr ) { @@ -253,10 +253,10 @@ 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; - igraph_integer_t i = 0; + igraph_int_t no_of_edges = igraph_vector_int_size(&graph->from); + igraph_int_t edges_to_add = igraph_vector_int_size(edges) / 2; + igraph_int_t new_no_of_edges; + igraph_int_t i = 0; igraph_vector_int_t newoi, newii; igraph_bool_t directed = igraph_is_directed(graph); @@ -385,12 +385,12 @@ igraph_error_t igraph_add_edges( * \example examples/simple/creation.c */ igraph_error_t igraph_add_vertices( - igraph_t *graph, igraph_integer_t nv, const igraph_attribute_record_list_t *attr + igraph_t *graph, igraph_int_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; - igraph_integer_t i; + igraph_int_t ec = igraph_ecount(graph); + igraph_int_t vc = igraph_vcount(graph); + igraph_int_t new_vc; + igraph_int_t i; if (nv < 0) { IGRAPH_ERROR("Cannot add negative number of vertices.", IGRAPH_EINVAL); @@ -496,17 +496,17 @@ igraph_error_t igraph_add_vertices( * \example examples/simple/igraph_delete_edges.c */ igraph_error_t igraph_delete_edges(igraph_t *graph, igraph_es_t edges) { - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t edges_to_remove = 0; - igraph_integer_t remaining_edges; + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t edges_to_remove = 0; + igraph_int_t remaining_edges; igraph_eit_t eit; igraph_vector_int_t newfrom, newto; igraph_vector_int_t newoi, newii; igraph_bool_t *mark; - igraph_integer_t i, j; + igraph_int_t i, j; mark = IGRAPH_CALLOC(no_of_edges, igraph_bool_t); IGRAPH_CHECK_OOM(mark, "Cannot delete edges."); @@ -516,7 +516,7 @@ igraph_error_t igraph_delete_edges(igraph_t *graph, igraph_es_t edges) { IGRAPH_FINALLY(igraph_eit_destroy, &eit); for (IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); + igraph_int_t e = IGRAPH_EIT_GET(eit); if (! mark[e]) { edges_to_remove++; mark[e] = true; @@ -644,14 +644,14 @@ 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); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t edge_recoding, vertex_recoding; igraph_vector_int_t *my_vertex_recoding = &vertex_recoding; igraph_vit_t vit; igraph_t newgraph; - igraph_integer_t i, j; - igraph_integer_t remaining_vertices, remaining_edges; + igraph_int_t i, j; + igraph_int_t remaining_vertices, remaining_edges; if (map) { my_vertex_recoding = map; @@ -668,7 +668,7 @@ igraph_error_t igraph_delete_vertices_map( /* mark the vertices to delete */ for (; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit) ) { - igraph_integer_t vertex = IGRAPH_VIT_GET(vit); + igraph_int_t vertex = IGRAPH_VIT_GET(vit); if (vertex < 0 || vertex >= no_of_nodes) { IGRAPH_ERROR("Cannot delete vertices.", IGRAPH_EINVVID); } @@ -685,8 +685,8 @@ igraph_error_t igraph_delete_vertices_map( } /* 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]; + igraph_int_t from = VECTOR(graph->from)[i]; + igraph_int_t to = VECTOR(graph->to)[i]; if (VECTOR(*my_vertex_recoding)[from] >= 0 && VECTOR(*my_vertex_recoding)[to ] >= 0) { VECTOR(edge_recoding)[i] = remaining_edges + 1; @@ -710,8 +710,8 @@ igraph_error_t igraph_delete_vertices_map( /* Add the edges */ for (i = 0, j = 0; j < remaining_edges; i++) { if (VECTOR(edge_recoding)[i] > 0) { - igraph_integer_t from = VECTOR(graph->from)[i]; - igraph_integer_t to = VECTOR(graph->to )[i]; + igraph_int_t from = VECTOR(graph->from)[i]; + igraph_int_t to = VECTOR(graph->to )[i]; VECTOR(newgraph.from)[j] = VECTOR(*my_vertex_recoding)[from]; VECTOR(newgraph.to )[j] = VECTOR(*my_vertex_recoding)[to]; j++; @@ -749,7 +749,7 @@ igraph_error_t igraph_delete_vertices_map( igraph_vector_int_t iidx; 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]; + igraph_int_t jj = VECTOR(*my_vertex_recoding)[i]; if (jj >= 0) { VECTOR(iidx)[ jj ] = i; } @@ -757,7 +757,7 @@ igraph_error_t igraph_delete_vertices_map( 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]; + igraph_int_t jj = VECTOR(edge_recoding)[i]; if (jj != 0) { VECTOR(iidx)[ jj - 1 ] = i; } @@ -777,7 +777,7 @@ igraph_error_t igraph_delete_vertices_map( 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]; + igraph_int_t newid = VECTOR(*my_vertex_recoding)[i]; if (newid >= 0) { VECTOR(*invmap)[newid] = i; } @@ -824,7 +824,7 @@ igraph_error_t igraph_delete_vertices_map( * * Time complexity: O(1) */ -igraph_integer_t igraph_vcount(const igraph_t *graph) { +igraph_int_t igraph_vcount(const igraph_t *graph) { return graph->n; } @@ -838,7 +838,7 @@ igraph_integer_t igraph_vcount(const igraph_t *graph) { * * Time complexity: O(1) */ -igraph_integer_t igraph_ecount(const igraph_t *graph) { +igraph_int_t igraph_ecount(const igraph_t *graph) { return igraph_vector_int_size(&graph->from); } @@ -887,7 +887,7 @@ igraph_integer_t igraph_ecount(const igraph_t *graph) { * \example examples/simple/igraph_neighbors.c */ igraph_error_t igraph_neighbors( - const igraph_t *graph, igraph_vector_int_t *neis, igraph_integer_t pnode, + const igraph_t *graph, igraph_vector_int_t *neis, igraph_int_t pnode, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple ) { #define DEDUPLICATE_IF_NEEDED(vertex, n) \ @@ -925,11 +925,11 @@ igraph_error_t igraph_neighbors( } - igraph_integer_t length = 0, idx = 0; - igraph_integer_t i, j; + igraph_int_t length = 0, idx = 0; + igraph_int_t i, j; - igraph_integer_t node = pnode; - igraph_integer_t last_added = -1; + igraph_int_t node = pnode; + igraph_int_t last_added = -1; igraph_bool_t should_filter_duplicates; /* seen_loop stores whether we have already seen at least one full loop @@ -990,7 +990,7 @@ igraph_error_t igraph_neighbors( if (mode & IGRAPH_OUT) { j = VECTOR(graph->os)[node + 1]; for (i = VECTOR(graph->os)[node]; i < j; i++) { - igraph_integer_t to = VECTOR(graph->to)[ VECTOR(graph->oi)[i] ]; + igraph_int_t to = VECTOR(graph->to)[ VECTOR(graph->oi)[i] ]; DEDUPLICATE_IF_NEEDED(to, 1); VECTOR(*neis)[idx++] = to; } @@ -999,7 +999,7 @@ igraph_error_t igraph_neighbors( if (mode & IGRAPH_IN) { j = VECTOR(graph->is)[node + 1]; for (i = VECTOR(graph->is)[node]; i < j; i++) { - igraph_integer_t from = VECTOR(graph->from)[ VECTOR(graph->ii)[i] ]; + igraph_int_t from = VECTOR(graph->from)[ VECTOR(graph->ii)[i] ]; DEDUPLICATE_IF_NEEDED(from, 1); VECTOR(*neis)[idx++] = from; } @@ -1008,12 +1008,12 @@ igraph_error_t igraph_neighbors( /* Both in- and out- neighbors in a directed graph, we need to merge the two 'vectors' so the result is correctly ordered. */ - igraph_integer_t j1 = VECTOR(graph->os)[node + 1]; - igraph_integer_t j2 = VECTOR(graph->is)[node + 1]; - igraph_integer_t i1 = VECTOR(graph->os)[node]; - igraph_integer_t i2 = VECTOR(graph->is)[node]; - igraph_integer_t eid1, eid2; - igraph_integer_t n1, n2; + igraph_int_t j1 = VECTOR(graph->os)[node + 1]; + igraph_int_t j2 = VECTOR(graph->is)[node + 1]; + igraph_int_t i1 = VECTOR(graph->os)[node]; + igraph_int_t i2 = VECTOR(graph->is)[node]; + igraph_int_t eid1, eid2; + igraph_int_t n1, n2; should_filter_duplicates = !(multiple == IGRAPH_MULTIPLE && loops == IGRAPH_LOOPS_TWICE); @@ -1043,14 +1043,14 @@ igraph_error_t igraph_neighbors( while (i1 < j1) { eid1 = VECTOR(graph->oi)[i1++]; - igraph_integer_t to = VECTOR(graph->to)[eid1]; + igraph_int_t to = VECTOR(graph->to)[eid1]; DEDUPLICATE_IF_NEEDED(to, 1); VECTOR(*neis)[idx++] = to; } while (i2 < j2) { eid2 = VECTOR(graph->ii)[i2++]; - igraph_integer_t from = VECTOR(graph->from)[eid2]; + igraph_int_t from = VECTOR(graph->from)[eid2]; DEDUPLICATE_IF_NEEDED(from, 1); VECTOR(*neis)[idx++] = from; } @@ -1068,13 +1068,13 @@ igraph_error_t igraph_neighbors( static igraph_error_t igraph_i_create_start_vectors( igraph_vector_int_t *res, igraph_vector_int_t *el, - igraph_vector_int_t *iindex, igraph_integer_t nodes) { + igraph_vector_int_t *iindex, igraph_int_t nodes) { # define EDGE(i) (VECTOR(*el)[ VECTOR(*iindex)[(i)] ]) - igraph_integer_t no_of_nodes; - igraph_integer_t no_of_edges; - igraph_integer_t i, j, idx; + igraph_int_t no_of_nodes; + igraph_int_t no_of_edges; + igraph_int_t i, j, idx; no_of_nodes = nodes; no_of_edges = igraph_vector_int_size(el); @@ -1094,7 +1094,7 @@ static igraph_error_t igraph_i_create_start_vectors( idx++; VECTOR(*res)[idx] = 0; } for (i = 1; i < no_of_edges; i++) { - igraph_integer_t n = EDGE(i) - EDGE(VECTOR(*res)[idx]); + igraph_int_t n = EDGE(i) - EDGE(VECTOR(*res)[idx]); for (j = 0; j < n; j++) { idx++; VECTOR(*res)[idx] = i; } @@ -1155,10 +1155,10 @@ igraph_bool_t igraph_is_directed(const igraph_t *graph) { * O(d) otherwise, where d is the degree. */ igraph_error_t igraph_degree_1( - const igraph_t *graph, igraph_integer_t *deg, igraph_integer_t vid, + const igraph_t *graph, igraph_int_t *deg, igraph_int_t vid, igraph_neimode_t mode, igraph_loops_t loops ) { - igraph_integer_t loop_counter; + igraph_int_t loop_counter; if (!igraph_is_directed(graph)) { mode = IGRAPH_ALL; @@ -1186,14 +1186,14 @@ igraph_error_t igraph_degree_1( * previously computed degree. */ loop_counter = 0; if (mode & IGRAPH_OUT) { - for (igraph_integer_t i = VECTOR(graph->os)[vid]; i < VECTOR(graph->os)[vid + 1]; i++) { + for (igraph_int_t i = VECTOR(graph->os)[vid]; i < VECTOR(graph->os)[vid + 1]; i++) { if (VECTOR(graph->to)[ VECTOR(graph->oi)[i] ] == vid) { loop_counter++; } } } if (mode & IGRAPH_IN) { - for (igraph_integer_t i = VECTOR(graph->is)[vid]; i < VECTOR(graph->is)[vid + 1]; i++) { + for (igraph_int_t i = VECTOR(graph->is)[vid]; i < VECTOR(graph->is)[vid + 1]; i++) { if (VECTOR(graph->from)[ VECTOR(graph->ii)[i] ] == vid) { loop_counter++; } @@ -1221,7 +1221,7 @@ igraph_error_t igraph_degree_1( * specified vertices. * * - * This function returns the result as a vector of \c igraph_integer_t + * This function returns the result as a vector of \c igraph_int_t * values. In applications where \c igraph_real_t is desired, use * \ref igraph_strength() with \c NULL weights. * @@ -1236,10 +1236,11 @@ igraph_error_t igraph_degree_1( * \c IGRAPH_ALL, total degree (sum of the * in- and out-degree). * This parameter is ignored for undirected graphs. - * \param loops Specifies how to treat loop edges when calculating the - * degree. \c IGRAPH_NO_LOOPS ignores loop edges; \c IGRAPH_LOOPS_ONCE - * counts each loop edge only once; \c IGRAPH_LOOPS_TWICE counts each - * loop edge twice in undirected graphs and once in directed graphs. + * \param loops Constant of type \ref igraph_loops_t, specifies how to treat + * loop edges when calculating the degree. \c IGRAPH_NO_LOOPS ignores + * loop edges; \c IGRAPH_LOOPS_ONCE counts each loop edge only once; + * \c IGRAPH_LOOPS_TWICE counts each loop edge twice in undirected + * graphs and once in directed graphs. * \return Error code: * \c IGRAPH_EINVVID: invalid vertex ID. * \c IGRAPH_EINVMODE: invalid mode argument. @@ -1261,8 +1262,8 @@ igraph_error_t igraph_degree( igraph_neimode_t mode, igraph_loops_t loops ) { - igraph_integer_t nodes_to_calc; - igraph_integer_t i, j; + igraph_int_t nodes_to_calc; + igraph_int_t i, j; igraph_vit_t vit; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); @@ -1300,7 +1301,7 @@ igraph_error_t igraph_degree( for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t vid = IGRAPH_VIT_GET(vit); + igraph_int_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->os)[vid + 1] - VECTOR(graph->os)[vid]); } } @@ -1308,7 +1309,7 @@ igraph_error_t igraph_degree( for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t vid = IGRAPH_VIT_GET(vit); + igraph_int_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->is)[vid + 1] - VECTOR(graph->is)[vid]); } } @@ -1320,17 +1321,17 @@ igraph_error_t igraph_degree( if (igraph_vs_is_all(&vids)) { // When calculating degree for all vertices, iterating over edges is faster - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); /* mode & IGRAPH_OUT branch */ - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { - igraph_integer_t from = IGRAPH_FROM(graph, edge); + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { + igraph_int_t from = IGRAPH_FROM(graph, edge); VECTOR(*res)[from]++; } /* mode & IGRAPH_IN branch */ - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { - igraph_integer_t to = IGRAPH_TO(graph, edge); + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { + igraph_int_t to = IGRAPH_TO(graph, edge); if (IGRAPH_FROM(graph, edge) != to) { VECTOR(*res)[to]++; } @@ -1340,7 +1341,7 @@ igraph_error_t igraph_degree( for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t vid = IGRAPH_VIT_GET(vit); + igraph_int_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->os)[vid + 1] - VECTOR(graph->os)[vid]); } @@ -1348,7 +1349,7 @@ igraph_error_t igraph_degree( for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t vid = IGRAPH_VIT_GET(vit); + igraph_int_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->is)[vid + 1] - VECTOR(graph->is)[vid]); for (j = VECTOR(graph->is)[vid]; j < VECTOR(graph->is)[vid + 1]; j++) { @@ -1362,19 +1363,19 @@ igraph_error_t igraph_degree( /* no loops should be counted */ if (igraph_vs_is_all(&vids)) { // When calculating degree for all vertices, iterating over edges is faster - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); if (mode & IGRAPH_OUT) { - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { - igraph_integer_t from = IGRAPH_FROM(graph, edge); + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { + igraph_int_t from = IGRAPH_FROM(graph, edge); if (from != IGRAPH_TO(graph, edge)) { VECTOR(*res)[from]++; } } } if (mode & IGRAPH_IN) { - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { - igraph_integer_t to = IGRAPH_TO(graph, edge); + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { + igraph_int_t to = IGRAPH_TO(graph, edge); if (IGRAPH_FROM(graph, edge) != to) { VECTOR(*res)[to]++; } @@ -1385,7 +1386,7 @@ igraph_error_t igraph_degree( for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t vid = IGRAPH_VIT_GET(vit); + igraph_int_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->os)[vid + 1] - VECTOR(graph->os)[vid]); for (j = VECTOR(graph->os)[vid]; j < VECTOR(graph->os)[vid + 1]; j++) { @@ -1399,7 +1400,7 @@ igraph_error_t igraph_degree( for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t vid = IGRAPH_VIT_GET(vit); + igraph_int_t vid = IGRAPH_VIT_GET(vit); VECTOR(*res)[i] += (VECTOR(graph->is)[vid + 1] - VECTOR(graph->is)[vid]); for (j = VECTOR(graph->is)[vid]; j < VECTOR(graph->is)[vid + 1]; j++) { @@ -1442,8 +1443,8 @@ igraph_error_t igraph_degree( #define BINSEARCH(start, end, value, iindex, edgelist, N, result, result_pos) \ do { \ while ((start) < (end)) { \ - igraph_integer_t mid =(start)+((end)-(start))/2; \ - igraph_integer_t e = VECTOR((iindex))[mid]; \ + igraph_int_t mid =(start)+((end)-(start))/2; \ + igraph_int_t e = VECTOR((iindex))[mid]; \ if (VECTOR((edgelist))[e] < (value)) { \ (start) = mid+1; \ } else { \ @@ -1451,7 +1452,7 @@ igraph_error_t igraph_degree( } \ } \ if ((start) < (N)) { \ - igraph_integer_t e = VECTOR((iindex))[(start)]; \ + igraph_int_t e = VECTOR((iindex))[(start)]; \ if (VECTOR((edgelist))[e] == (value)) { \ *(result) = e; \ if (result_pos != 0) { *(result_pos) = start; } \ @@ -1461,13 +1462,13 @@ igraph_error_t igraph_degree( #define FIND_DIRECTED_EDGE(graph,xfrom,xto,eid) \ do { \ - igraph_integer_t start = VECTOR(graph->os)[xfrom]; \ - igraph_integer_t end = VECTOR(graph->os)[xfrom+1]; \ - igraph_integer_t N = end; \ - igraph_integer_t start2 = VECTOR(graph->is)[xto]; \ - igraph_integer_t end2 = VECTOR(graph->is)[xto+1]; \ - igraph_integer_t N2 = end2; \ - igraph_integer_t *nullpointer = NULL; \ + igraph_int_t start = VECTOR(graph->os)[xfrom]; \ + igraph_int_t end = VECTOR(graph->os)[xfrom+1]; \ + igraph_int_t N = end; \ + igraph_int_t start2 = VECTOR(graph->is)[xto]; \ + igraph_int_t end2 = VECTOR(graph->is)[xto+1]; \ + igraph_int_t N2 = end2; \ + igraph_int_t *nullpointer = NULL; \ if (end-start < end2-start2) { \ BINSEARCH(start, end, xto, graph->oi, graph->to, N, eid, nullpointer); \ } else { \ @@ -1477,8 +1478,8 @@ igraph_error_t igraph_degree( #define FIND_UNDIRECTED_EDGE(graph, from, to, eid) \ do { \ - igraph_integer_t xfrom1 = from > to ? from : to; \ - igraph_integer_t xto1 = from > to ? to : from; \ + igraph_int_t xfrom1 = from > to ? from : to; \ + igraph_int_t xto1 = from > to ? to : from; \ FIND_DIRECTED_EDGE(graph, xfrom1, xto1, eid); \ } while (0) @@ -1513,11 +1514,11 @@ igraph_error_t igraph_degree( * \example examples/simple/igraph_get_eid.c */ -igraph_error_t igraph_get_eid(const igraph_t *graph, igraph_integer_t *eid, - igraph_integer_t from, igraph_integer_t to, +igraph_error_t igraph_get_eid(const igraph_t *graph, igraph_int_t *eid, + igraph_int_t from, igraph_int_t to, igraph_bool_t directed, igraph_bool_t error) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (from < 0 || to < 0 || from >= no_of_nodes || to >= no_of_nodes) { IGRAPH_ERROR("Cannot get edge ID.", IGRAPH_EINVVID); @@ -1595,10 +1596,10 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, const igraph_vector_int_t *pairs, igraph_bool_t directed, igraph_bool_t error) { - igraph_integer_t n = pairs ? igraph_vector_int_size(pairs) : 0; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i; - igraph_integer_t eid = -1; + igraph_int_t n = pairs ? igraph_vector_int_size(pairs) : 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i; + igraph_int_t eid = -1; if (n == 0) { igraph_vector_int_clear(eids); @@ -1618,8 +1619,8 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, if (igraph_is_directed(graph)) { for (i = 0; i < n / 2; i++) { - igraph_integer_t from = VECTOR(*pairs)[2 * i]; - igraph_integer_t to = VECTOR(*pairs)[2 * i + 1]; + igraph_int_t from = VECTOR(*pairs)[2 * i]; + igraph_int_t to = VECTOR(*pairs)[2 * i + 1]; eid = -1; FIND_DIRECTED_EDGE(graph, from, to, &eid); @@ -1634,8 +1635,8 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, } } else { for (i = 0; i < n / 2; i++) { - igraph_integer_t from = VECTOR(*pairs)[2 * i]; - igraph_integer_t to = VECTOR(*pairs)[2 * i + 1]; + igraph_int_t from = VECTOR(*pairs)[2 * i]; + igraph_int_t to = VECTOR(*pairs)[2 * i + 1]; eid = -1; FIND_UNDIRECTED_EDGE(graph, from, to, &eid); @@ -1654,14 +1655,14 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, #define FIND_ALL_DIRECTED_EDGES(graph, xfrom, xto, eidvec) \ do { \ - igraph_integer_t start = VECTOR(graph->os)[xfrom]; \ - igraph_integer_t end = VECTOR(graph->os)[xfrom+1]; \ - igraph_integer_t N = end; \ - igraph_integer_t start2 = VECTOR(graph->is)[xto]; \ - igraph_integer_t end2 = VECTOR(graph->is)[xto+1]; \ - igraph_integer_t N2 = end2; \ - igraph_integer_t eid = -1; \ - igraph_integer_t pos = -1; \ + igraph_int_t start = VECTOR(graph->os)[xfrom]; \ + igraph_int_t end = VECTOR(graph->os)[xfrom+1]; \ + igraph_int_t N = end; \ + igraph_int_t start2 = VECTOR(graph->is)[xto]; \ + igraph_int_t end2 = VECTOR(graph->is)[xto+1]; \ + igraph_int_t N2 = end2; \ + igraph_int_t eid = -1; \ + igraph_int_t pos = -1; \ if (end-start < end2-start2) { \ BINSEARCH(start, end, xto, graph->oi, graph->to, N, &eid, &pos); \ while (pos >= 0 && pos < N) { \ @@ -1681,8 +1682,8 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, #define FIND_ALL_UNDIRECTED_EDGES(graph, from, to, eidvec) \ do { \ - igraph_integer_t xfrom1 = from > to ? from : to; \ - igraph_integer_t xto1 = from > to ? to : from; \ + igraph_int_t xfrom1 = from > to ? from : to; \ + igraph_int_t xto1 = from > to ? to : from; \ FIND_ALL_DIRECTED_EDGES(graph, xfrom1, xto1, eidvec); \ } while (0) @@ -1708,9 +1709,9 @@ igraph_error_t igraph_get_eids(const igraph_t *graph, igraph_vector_int_t *eids, */ igraph_error_t igraph_get_all_eids_between( const igraph_t *graph, igraph_vector_int_t *eids, - igraph_integer_t source, igraph_integer_t target, igraph_bool_t directed + igraph_int_t source, igraph_int_t target, igraph_bool_t directed ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (source < 0 || source >= no_of_nodes) { IGRAPH_ERROR("Cannot get edge IDs, invalid source vertex ID.", IGRAPH_EINVVID); @@ -1767,12 +1768,12 @@ igraph_error_t igraph_get_all_eids_between( */ igraph_error_t igraph_incident( - const igraph_t *graph, igraph_vector_int_t *eids, igraph_integer_t pnode, + const igraph_t *graph, igraph_vector_int_t *eids, igraph_int_t pnode, igraph_neimode_t mode, igraph_loops_t loops ) { - igraph_integer_t length = 0, idx = 0; - igraph_integer_t i, j; - igraph_integer_t node = pnode; + igraph_int_t length = 0, idx = 0; + igraph_int_t i, j; + igraph_int_t node = pnode; igraph_bool_t directed = igraph_is_directed(graph); if (node < 0 || node > igraph_vcount(graph) - 1) { @@ -1820,8 +1821,8 @@ igraph_error_t igraph_incident( if (mode & IGRAPH_OUT) { j = VECTOR(graph->os)[node + 1]; for (i = VECTOR(graph->os)[node]; i < j; i++) { - igraph_integer_t edge = VECTOR(graph->oi)[i]; - igraph_integer_t other = VECTOR(graph->to)[edge]; + igraph_int_t edge = VECTOR(graph->oi)[i]; + igraph_int_t other = VECTOR(graph->to)[edge]; if (loops == IGRAPH_NO_LOOPS && other == pnode) { length--; } else { @@ -1833,8 +1834,8 @@ igraph_error_t igraph_incident( if (mode & IGRAPH_IN) { j = VECTOR(graph->is)[node + 1]; for (i = VECTOR(graph->is)[node]; i < j; i++) { - igraph_integer_t edge = VECTOR(graph->ii)[i]; - igraph_integer_t other = VECTOR(graph->from)[edge]; + igraph_int_t edge = VECTOR(graph->ii)[i]; + igraph_int_t other = VECTOR(graph->from)[edge]; if ((loops == IGRAPH_NO_LOOPS || (loops == IGRAPH_LOOPS_ONCE && !directed)) && other == pnode) { length--; } else { @@ -1845,12 +1846,12 @@ igraph_error_t igraph_incident( } else { /* both in- and out- neighbors in a directed graph, we need to merge the two 'vectors' */ - igraph_integer_t j1 = VECTOR(graph->os)[node + 1]; - igraph_integer_t j2 = VECTOR(graph->is)[node + 1]; - igraph_integer_t i1 = VECTOR(graph->os)[node]; - igraph_integer_t i2 = VECTOR(graph->is)[node]; - igraph_integer_t eid1, eid2; - igraph_integer_t n1, n2; + igraph_int_t j1 = VECTOR(graph->os)[node + 1]; + igraph_int_t j2 = VECTOR(graph->is)[node + 1]; + igraph_int_t i1 = VECTOR(graph->os)[node]; + igraph_int_t i2 = VECTOR(graph->is)[node]; + igraph_int_t eid1, eid2; + igraph_int_t n1, n2; igraph_bool_t seen_loop_edge = false; while (i1 < j1 && i2 < j2) { @@ -1939,11 +1940,11 @@ igraph_error_t igraph_incident( */ igraph_error_t igraph_is_same_graph(const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *res) { - igraph_integer_t nv1 = igraph_vcount(graph1); - igraph_integer_t nv2 = igraph_vcount(graph2); - igraph_integer_t ne1 = igraph_ecount(graph1); - igraph_integer_t ne2 = igraph_ecount(graph2); - igraph_integer_t i, eid1, eid2; + igraph_int_t nv1 = igraph_vcount(graph1); + igraph_int_t nv2 = igraph_vcount(graph2); + igraph_int_t ne1 = igraph_ecount(graph1); + igraph_int_t ne2 = igraph_ecount(graph2); + igraph_int_t i, eid1, eid2; *res = false; /* Assume that the graphs differ */ diff --git a/src/vendor/cigraph/src/graph/visitors.c b/src/vendor/cigraph/src/graph/visitors.c index 93d45403db1..1520d4b021d 100644 --- a/src/vendor/cigraph/src/graph/visitors.c +++ b/src/vendor/cigraph/src/graph/visitors.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -102,7 +102,7 @@ * \example examples/simple/igraph_bfs_callback.c */ igraph_error_t igraph_bfs(const igraph_t *graph, - igraph_integer_t root, const igraph_vector_int_t *roots, + igraph_int_t root, const igraph_vector_int_t *roots, igraph_neimode_t mode, igraph_bool_t unreachable, const igraph_vector_int_t *restricted, igraph_vector_int_t *order, igraph_vector_int_t *rank, @@ -111,21 +111,21 @@ igraph_error_t igraph_bfs(const igraph_t *graph, igraph_vector_int_t *dist, igraph_bfshandler_t *callback, void *extra) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_error_t ret; igraph_dqueue_int_t Q; - igraph_integer_t actroot = 0; + igraph_int_t actroot = 0; igraph_bitset_t added; igraph_lazy_adjlist_t adjlist; - igraph_integer_t act_rank = 0; - igraph_integer_t pred_vec = -1; + igraph_int_t act_rank = 0; + igraph_int_t pred_vec = -1; - igraph_integer_t rootpos = 0; - igraph_integer_t noroots = roots ? igraph_vector_int_size(roots) : 1; + igraph_int_t rootpos = 0; + igraph_int_t noroots = roots ? igraph_vector_int_size(roots) : 1; if (!roots && (root < 0 || root >= no_of_nodes)) { IGRAPH_ERROR("Invalid root vertex in BFS.", IGRAPH_EINVVID); @@ -158,10 +158,10 @@ igraph_error_t igraph_bfs(const igraph_t *graph, found. Special care must be taken for vertices that are not in the restricted set, but are to be used as 'root' vertices. */ if (restricted) { - igraph_integer_t i, n = igraph_vector_int_size(restricted); + igraph_int_t i, n = igraph_vector_int_size(restricted); igraph_bitset_fill(&added, true); for (i = 0; i < n; i++) { - igraph_integer_t v = VECTOR(*restricted)[i]; + igraph_int_t v = VECTOR(*restricted)[i]; IGRAPH_BIT_CLEAR(added, v); } } @@ -220,13 +220,13 @@ igraph_error_t igraph_bfs(const igraph_t *graph, pred_vec = -1; while (!igraph_dqueue_int_empty(&Q)) { - igraph_integer_t actvect = igraph_dqueue_int_pop(&Q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&Q); - igraph_integer_t succ_vec; + igraph_int_t actvect = igraph_dqueue_int_pop(&Q); + igraph_int_t actdist = igraph_dqueue_int_pop(&Q); + igraph_int_t succ_vec; igraph_vector_int_t *neis = igraph_lazy_adjlist_get(&adjlist, actvect); IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); - const igraph_integer_t n = igraph_vector_int_size(neis); + const igraph_int_t n = igraph_vector_int_size(neis); if (pred) { VECTOR(*pred)[actvect] = pred_vec; @@ -241,8 +241,8 @@ igraph_error_t igraph_bfs(const igraph_t *graph, VECTOR(*dist)[actvect] = actdist; } - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t nei = VECTOR(*neis)[i]; if (! IGRAPH_BIT_TEST(added, nei)) { IGRAPH_BIT_SET(added, nei); IGRAPH_CHECK(igraph_dqueue_int_push(&Q, nei)); @@ -326,17 +326,17 @@ igraph_error_t igraph_bfs(const igraph_t *graph, * \example examples/simple/igraph_bfs_simple.c */ igraph_error_t igraph_bfs_simple( - const igraph_t *graph, igraph_integer_t root, igraph_neimode_t mode, + const igraph_t *graph, igraph_int_t root, igraph_neimode_t mode, igraph_vector_int_t *order, igraph_vector_int_t *layers, igraph_vector_int_t *parents ) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; - igraph_integer_t num_visited = 0; + igraph_int_t num_visited = 0; igraph_vector_int_t neis; igraph_bitset_t added; - igraph_integer_t lastlayer = -1; + igraph_int_t lastlayer = -1; if (!igraph_is_directed(graph)) { mode = IGRAPH_ALL; @@ -382,14 +382,14 @@ igraph_error_t igraph_bfs_simple( IGRAPH_BIT_SET(added, root); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actvect = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actvect = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_neighbors( graph, &neis, actvect, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); - igraph_integer_t nei_count = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < nei_count; i++) { - const igraph_integer_t neighbor = VECTOR(neis)[i]; + igraph_int_t nei_count = igraph_vector_int_size(&neis); + for (igraph_int_t i = 0; i < nei_count; i++) { + const igraph_int_t neighbor = VECTOR(neis)[i]; if (! IGRAPH_BIT_TEST(added, neighbor)) { IGRAPH_BIT_SET(added, neighbor); if (parents) { @@ -476,7 +476,7 @@ igraph_error_t igraph_bfs_simple( * edges. */ -igraph_error_t igraph_dfs(const igraph_t *graph, igraph_integer_t root, +igraph_error_t igraph_dfs(const igraph_t *graph, igraph_int_t root, igraph_neimode_t mode, igraph_bool_t unreachable, igraph_vector_int_t *order, igraph_vector_int_t *order_out, igraph_vector_int_t *parents, @@ -484,15 +484,15 @@ igraph_error_t igraph_dfs(const igraph_t *graph, igraph_integer_t root, igraph_dfshandler_t *out_callback, void *extra) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_lazy_adjlist_t adjlist; igraph_stack_int_t stack; igraph_bitset_t added; igraph_vector_int_t nptr; igraph_error_t ret; - igraph_integer_t act_rank = 0; - igraph_integer_t rank_out = 0; - igraph_integer_t act_dist = 0; + igraph_int_t act_rank = 0; + igraph_int_t rank_out = 0; + igraph_int_t act_dist = 0; if (root < 0 || root >= no_of_nodes) { IGRAPH_ERROR("Invalid root vertex for DFS.", IGRAPH_EINVAL); @@ -554,7 +554,7 @@ igraph_error_t igraph_dfs(const igraph_t *graph, igraph_integer_t root, } } - for (igraph_integer_t actroot = 0; actroot < no_of_nodes; ) { + for (igraph_int_t actroot = 0; actroot < no_of_nodes; ) { /* 'root' first, then all other vertices */ if (igraph_stack_int_empty(&stack)) { @@ -589,17 +589,17 @@ igraph_error_t igraph_dfs(const igraph_t *graph, igraph_integer_t root, } while (!igraph_stack_int_empty(&stack)) { - igraph_integer_t actvect = igraph_stack_int_top(&stack); - igraph_integer_t *ptr = igraph_vector_int_get_ptr(&nptr, actvect); + igraph_int_t actvect = igraph_stack_int_top(&stack); + igraph_int_t *ptr = igraph_vector_int_get_ptr(&nptr, actvect); igraph_vector_int_t *neis = igraph_lazy_adjlist_get(&adjlist, actvect); IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); - const igraph_integer_t n = igraph_vector_int_size(neis); + const igraph_int_t n = igraph_vector_int_size(neis); /* Search for a neighbor that was not yet visited */ igraph_bool_t any = false; - igraph_integer_t nei = 0; + igraph_int_t nei = 0; while (!any && (*ptr) < n) { nei = VECTOR(*neis)[(*ptr)]; any = !IGRAPH_BIT_TEST(added, nei); diff --git a/src/vendor/cigraph/src/hrg/dendro.h b/src/vendor/cigraph/src/hrg/dendro.h index 7b66331e816..77d4003a028 100644 --- a/src/vendor/cigraph/src/hrg/dendro.h +++ b/src/vendor/cigraph/src/hrg/dendro.h @@ -1,6 +1,6 @@ /* -*- mode: C++ -*- */ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/hrg/graph.h b/src/vendor/cigraph/src/hrg/graph.h index 4e72b24746e..09f379d1f82 100644 --- a/src/vendor/cigraph/src/hrg/graph.h +++ b/src/vendor/cigraph/src/hrg/graph.h @@ -1,6 +1,6 @@ /* -*- mode: C++ -*- */ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -133,7 +133,7 @@ class graph { // clear all links from graph void resetLinks(); // allocate edge histograms - void setAdjacencyHistograms(igraph_integer_t); + void setAdjacencyHistograms(igraph_int_t); // set name of vertex i bool setName(int, const std::string &); diff --git a/src/vendor/cigraph/src/hrg/graph_simp.h b/src/vendor/cigraph/src/hrg/graph_simp.h index 4ba56824fcd..2d658c425e3 100644 --- a/src/vendor/cigraph/src/hrg/graph_simp.h +++ b/src/vendor/cigraph/src/hrg/graph_simp.h @@ -1,6 +1,6 @@ /* -*- mode: C++ -*- */ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/hrg/hrg.cc b/src/vendor/cigraph/src/hrg/hrg.cc index b4d57936d15..a430d7f0334 100644 --- a/src/vendor/cigraph/src/hrg/hrg.cc +++ b/src/vendor/cigraph/src/hrg/hrg.cc @@ -1,6 +1,6 @@ /* -*- mode: C++ -*- */ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -84,7 +84,7 @@ struct pblock { }; } -static void markovChainMonteCarlo(dendro &d, const igraph_integer_t period, +static void markovChainMonteCarlo(dendro &d, const igraph_int_t period, igraph_hrg_t *hrg) { igraph_real_t bestL = d.getLikelihood(); @@ -103,7 +103,7 @@ static void markovChainMonteCarlo(dendro &d, const igraph_integer_t period, // model averaging sense), you'll need to code that yourself. // do 'period' MCMC moves before doing anything else - for (igraph_integer_t i = 0; i < period; i++) { + for (igraph_int_t i = 0; i < period; i++) { // make a MCMC move d.monteCarloMove(dL, flag_taken, 1.0); @@ -125,7 +125,7 @@ static void markovChainMonteCarlo2(dendro &d, const int num_samples) { bool flag_taken; double dL; const double ptest = 1.0 / (50.0 * static_cast(d.getGraph()->numNodes())); - igraph_integer_t sample_num = 0; + igraph_int_t sample_num = 0; int t = 1; const int thresh = 200 * d.getGraph()->numNodes(); @@ -186,8 +186,8 @@ static void MCMCEquilibrium_Find(dendro &d, igraph_hrg_t *hrg) { } igraph_error_t dendro::setGraph(const igraph_t *igraph) { - igraph_integer_t no_of_nodes = igraph_vcount(igraph); - igraph_integer_t no_of_edges = igraph_ecount(igraph); + igraph_int_t no_of_nodes = igraph_vcount(igraph); + igraph_int_t no_of_edges = igraph_ecount(igraph); if (no_of_nodes > INT_MAX) { IGRAPH_ERROR("Graph too large for the HRG module.", IGRAPH_EOVERFLOW); @@ -203,7 +203,7 @@ igraph_error_t dendro::setGraph(const igraph_t *igraph) { g = new graph(no_of_nodes); // Add edges - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { int from = IGRAPH_FROM(igraph, i); int to = IGRAPH_TO(igraph, i); if (from == to) { @@ -224,10 +224,10 @@ igraph_error_t dendro::setGraph(const igraph_t *igraph) { static std::unique_ptr igraph_i_hrg_getsimplegraph(const igraph_t *igraph, dendro &d, - igraph_integer_t num_bins) { + igraph_int_t num_bins) { - const igraph_integer_t no_of_nodes = igraph_vcount(igraph); - const igraph_integer_t no_of_edges = igraph_ecount(igraph); + const igraph_int_t no_of_nodes = igraph_vcount(igraph); + const igraph_int_t no_of_edges = igraph_ecount(igraph); // TODO replace the following throw's with IGRAPH_ERROR @@ -247,7 +247,7 @@ static std::unique_ptr igraph_i_hrg_getsimplegraph(const igraph_t * std::unique_ptr sg(new simpleGraph(no_of_nodes)); - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { int from = (int) IGRAPH_FROM(igraph, i); int to = (int) IGRAPH_TO(igraph, i); if (from == to) { @@ -288,7 +288,7 @@ static std::unique_ptr igraph_i_hrg_getsimplegraph(const igraph_t * * Time complexity: O(n), the number of vertices in the graph. */ -igraph_error_t igraph_hrg_init(igraph_hrg_t *hrg, igraph_integer_t n) { +igraph_error_t igraph_hrg_init(igraph_hrg_t *hrg, igraph_int_t n) { if (n < 0) { IGRAPH_ERRORF("Number of vertices should not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, n); } @@ -334,7 +334,7 @@ void igraph_hrg_destroy(igraph_hrg_t *hrg) { * Time complexity: O(1). */ -igraph_integer_t igraph_hrg_size(const igraph_hrg_t *hrg) { +igraph_int_t igraph_hrg_size(const igraph_hrg_t *hrg) { return igraph_vector_int_size(&hrg->left) + 1; } @@ -350,8 +350,8 @@ igraph_integer_t igraph_hrg_size(const igraph_hrg_t *hrg) { * Time complexity: O(n), n is the new size. */ -igraph_error_t igraph_hrg_resize(igraph_hrg_t *hrg, igraph_integer_t newsize) { - igraph_integer_t origsize = igraph_hrg_size(hrg); +igraph_error_t igraph_hrg_resize(igraph_hrg_t *hrg, igraph_int_t newsize) { + igraph_int_t origsize = igraph_hrg_size(hrg); /* The data structure must be left in a consistent state if resizing fails. */ @@ -407,11 +407,11 @@ igraph_error_t igraph_hrg_resize(igraph_hrg_t *hrg, igraph_integer_t newsize) { igraph_error_t igraph_hrg_fit(const igraph_t *graph, igraph_hrg_t *hrg, igraph_bool_t start, - igraph_integer_t steps) { + igraph_int_t steps) { IGRAPH_HANDLE_EXCEPTIONS_BEGIN - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); dendro d; @@ -490,7 +490,7 @@ igraph_error_t igraph_hrg_sample(const igraph_hrg_t *hrg, igraph_t *sample) { igraph_error_t igraph_hrg_sample_many( const igraph_hrg_t *hrg, igraph_graph_list_t *samples, - igraph_integer_t num_samples + igraph_int_t num_samples ) { IGRAPH_HANDLE_EXCEPTIONS_BEGIN igraph_t g; @@ -562,11 +562,11 @@ igraph_error_t igraph_hrg_game(igraph_t *graph, igraph_error_t igraph_from_hrg_dendrogram( igraph_t *graph, const igraph_hrg_t *hrg, igraph_vector_t *prob ) { - const igraph_integer_t orig_nodes = igraph_hrg_size(hrg); - const igraph_integer_t no_of_nodes = orig_nodes * 2 - 1; - const igraph_integer_t no_of_edges = no_of_nodes > 0 ? no_of_nodes - 1 : 0; + const igraph_int_t orig_nodes = igraph_hrg_size(hrg); + const igraph_int_t no_of_nodes = orig_nodes * 2 - 1; + const igraph_int_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_int_t i, idx = 0; // Probability labels, for leaf nodes they are IGRAPH_NAN if (prob) { @@ -582,8 +582,8 @@ igraph_error_t igraph_from_hrg_dendrogram( IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); for (i = 0; i < orig_nodes - 1; i++) { - igraph_integer_t left = VECTOR(hrg->left)[i]; - igraph_integer_t right = VECTOR(hrg->right)[i]; + igraph_int_t left = VECTOR(hrg->left)[i]; + igraph_int_t right = VECTOR(hrg->right)[i]; VECTOR(edges)[idx++] = orig_nodes + i; VECTOR(edges)[idx++] = left < 0 ? orig_nodes - left - 1 : left; @@ -619,11 +619,11 @@ igraph_error_t igraph_from_hrg_dendrogram( * \deprecated-by igraph_from_hrg_dendrogram 0.10.5 */ igraph_error_t igraph_hrg_dendrogram(igraph_t *graph, const igraph_hrg_t *hrg) { - const igraph_integer_t orig_nodes = igraph_hrg_size(hrg); - const igraph_integer_t no_of_nodes = orig_nodes * 2 - 1; - const igraph_integer_t no_of_edges = no_of_nodes > 0 ? no_of_nodes - 1 : 0; + const igraph_int_t orig_nodes = igraph_hrg_size(hrg); + const igraph_int_t no_of_nodes = orig_nodes * 2 - 1; + const igraph_int_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_int_t i, idx = 0; igraph_attribute_record_list_t vattrs; igraph_vector_t prob; igraph_attribute_record_t* rec; @@ -647,8 +647,8 @@ igraph_error_t igraph_hrg_dendrogram(igraph_t *graph, const igraph_hrg_t *hrg) { igraph_vector_swap(rec->value.as_vector, &prob); for (i = 0; i < orig_nodes - 1; i++) { - igraph_integer_t left = VECTOR(hrg->left)[i]; - igraph_integer_t right = VECTOR(hrg->right)[i]; + igraph_int_t left = VECTOR(hrg->left)[i]; + igraph_int_t right = VECTOR(hrg->right)[i]; VECTOR(edges)[idx++] = orig_nodes + i; VECTOR(edges)[idx++] = left < 0 ? orig_nodes - left - 1 : left; @@ -702,7 +702,7 @@ igraph_error_t igraph_hrg_consensus(const igraph_t *graph, igraph_vector_t *weights, igraph_hrg_t *hrg, igraph_bool_t start, - igraph_integer_t num_samples) { + igraph_int_t num_samples) { IGRAPH_HANDLE_EXCEPTIONS_BEGIN if (start && !hrg) { @@ -732,7 +732,7 @@ igraph_error_t igraph_hrg_consensus(const igraph_t *graph, IGRAPH_HANDLE_EXCEPTIONS_END } -static void MCMCEquilibrium_Sample(dendro &d, igraph_integer_t num_samples) { +static void MCMCEquilibrium_Sample(dendro &d, igraph_int_t num_samples) { // Because moves in the dendrogram space are chosen (Monte // Carlo) so that we sample dendrograms with probability @@ -747,8 +747,8 @@ static void MCMCEquilibrium_Sample(dendro &d, igraph_integer_t num_samples) { double dL; bool flag_taken; - igraph_integer_t sample_num = 0; - igraph_integer_t t = 1, thresh = 100 * d.getGraph()->numNodes(); + igraph_int_t sample_num = 0; + igraph_int_t t = 1, thresh = 100 * d.getGraph()->numNodes(); double ptest = 1.0 / 10.0 / d.getGraph()->numNodes(); while (sample_num < num_samples) { @@ -762,13 +762,13 @@ static void MCMCEquilibrium_Sample(dendro &d, igraph_integer_t num_samples) { } } -static igraph_integer_t QsortPartition (pblock* array, igraph_integer_t left, igraph_integer_t right, igraph_integer_t index) { +static igraph_int_t QsortPartition (pblock* array, igraph_int_t left, igraph_int_t right, igraph_int_t index) { pblock p_value = array[index]; std::swap(array[right], array[index]); - igraph_integer_t stored = left; - for (igraph_integer_t i = left; i < right; i++) { + igraph_int_t stored = left; + for (igraph_int_t i = left; i < right; i++) { if (array[i].L <= p_value.L) { std::swap(array[i], array[stored]); stored++; @@ -779,10 +779,10 @@ static igraph_integer_t QsortPartition (pblock* array, igraph_integer_t left, ig return stored; } -static void QsortMain (pblock* array, igraph_integer_t left, igraph_integer_t right) { +static void QsortMain (pblock* array, igraph_int_t left, igraph_int_t right) { if (right > left) { - igraph_integer_t pivot = left; - igraph_integer_t part = QsortPartition(array, left, right, pivot); + igraph_int_t pivot = left; + igraph_int_t part = QsortPartition(array, left, right, pivot); QsortMain(array, left, part - 1); QsortMain(array, part + 1, right ); } @@ -852,8 +852,8 @@ igraph_error_t igraph_hrg_predict(const igraph_t *graph, igraph_vector_t *prob, igraph_hrg_t *hrg, igraph_bool_t start, - igraph_integer_t num_samples, - igraph_integer_t num_bins) { + igraph_int_t num_samples, + igraph_int_t num_bins) { IGRAPH_HANDLE_EXCEPTIONS_BEGIN if (start && !hrg) { @@ -911,12 +911,12 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, const igraph_t *graph, const igraph_vector_t *prob) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_internal = no_of_nodes > 0 ? (no_of_nodes - 1) / 2 : 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_internal = no_of_nodes > 0 ? (no_of_nodes - 1) / 2 : 0; igraph_vector_int_t deg, idx; - igraph_integer_t root = 0; - igraph_integer_t d0 = 0, d1 = 0, d2 = 0; - igraph_integer_t ii = 0, il = 0; + igraph_int_t root = 0; + igraph_int_t d0 = 0, d1 = 0, d2 = 0; + igraph_int_t ii = 0, il = 0; igraph_vector_int_t neis; igraph_vector_int_t path; igraph_bool_t simple; @@ -965,8 +965,8 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, // Every vertex, except for the root must have in-degree one. IGRAPH_CHECK(igraph_degree(graph, °, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t d = VECTOR(deg)[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t d = VECTOR(deg)[i]; switch (d) { case 0: d0++; root = i; break; case 1: d1++; break; @@ -986,7 +986,7 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, IGRAPH_CHECK(igraph_degree(graph, °, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS)); for (int i = 0; i < no_of_nodes; i++) { - igraph_integer_t d = VECTOR(deg)[i]; + igraph_int_t d = VECTOR(deg)[i]; switch (d) { case 0: d0++; break; case 2: d2++; break; @@ -1011,8 +1011,8 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, // the internal nodes, then the leaf nodes IGRAPH_VECTOR_INT_INIT_FINALLY(&idx, no_of_nodes); VECTOR(idx)[root] = - (ii++) - 1; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t d = VECTOR(deg)[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t d = VECTOR(deg)[i]; if (i == root) { continue; } @@ -1026,8 +1026,8 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, IGRAPH_CHECK(igraph_hrg_resize(hrg, no_of_internal + 1)); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t ri = VECTOR(idx)[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t ri = VECTOR(idx)[i]; if (ri >= 0) { continue; } @@ -1043,9 +1043,9 @@ igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg, IGRAPH_VECTOR_INT_INIT_FINALLY(&path, 0); IGRAPH_CHECK(igraph_vector_int_push_back(&path, VECTOR(idx)[root])); while (!igraph_vector_int_empty(&path)) { - igraph_integer_t ri = igraph_vector_int_tail(&path); - igraph_integer_t lc = VECTOR(hrg->left)[-ri - 1]; - igraph_integer_t rc = VECTOR(hrg->right)[-ri - 1]; + igraph_int_t ri = igraph_vector_int_tail(&path); + igraph_int_t lc = VECTOR(hrg->left)[-ri - 1]; + igraph_int_t rc = VECTOR(hrg->right)[-ri - 1]; if (lc < 0 && VECTOR(hrg->vertices)[-lc - 1] == 0) { // Go left IGRAPH_CHECK(igraph_vector_int_push_back(&path, lc)); diff --git a/src/vendor/cigraph/src/hrg/hrg_types.cc b/src/vendor/cigraph/src/hrg/hrg_types.cc index e1bbd34dada..0c736af372a 100644 --- a/src/vendor/cigraph/src/hrg/hrg_types.cc +++ b/src/vendor/cigraph/src/hrg/hrg_types.cc @@ -1386,7 +1386,7 @@ double dendro::getSplitTotalWeight() const { // *********************************************************************** bool dendro::importDendrogramStructure(const igraph_hrg_t *hrg) { - igraph_integer_t size = igraph_hrg_size(hrg); + igraph_int_t size = igraph_hrg_size(hrg); if (size > INT_MAX) { throw std::range_error("Hierarchical random graph too large for the HRG module"); @@ -2530,7 +2530,7 @@ void graph::resetLinks() { // ********************************************************************** -void graph::setAdjacencyHistograms(const igraph_integer_t bin_count) { +void graph::setAdjacencyHistograms(const igraph_int_t bin_count) { // For all possible adjacencies, setup an edge histograms num_bins = bin_count + 1; bin_resolution = 1.0 / (double)(bin_count); diff --git a/src/vendor/cigraph/src/hrg/rbtree.h b/src/vendor/cigraph/src/hrg/rbtree.h index 222eba8d31a..309db8fce12 100644 --- a/src/vendor/cigraph/src/hrg/rbtree.h +++ b/src/vendor/cigraph/src/hrg/rbtree.h @@ -1,6 +1,6 @@ /* -*- mode: C++ -*- */ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/hrg/splittree_eq.h b/src/vendor/cigraph/src/hrg/splittree_eq.h index 0c83f853395..28d03b20661 100644 --- a/src/vendor/cigraph/src/hrg/splittree_eq.h +++ b/src/vendor/cigraph/src/hrg/splittree_eq.h @@ -1,6 +1,6 @@ /* -*- mode: C++ -*- */ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/internal/glpk_support.c b/src/vendor/cigraph/src/internal/glpk_support.c index 10d98eb321c..ab0f61ce3da 100644 --- a/src/vendor/cigraph/src/internal/glpk_support.c +++ b/src/vendor/cigraph/src/internal/glpk_support.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/internal/glpk_support.h b/src/vendor/cigraph/src/internal/glpk_support.h index 701bf737f5e..3f05fa7bbfb 100644 --- a/src/vendor/cigraph/src/internal/glpk_support.h +++ b/src/vendor/cigraph/src/internal/glpk_support.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/internal/gmp_internal.h b/src/vendor/cigraph/src/internal/gmp_internal.h index 25f77139d70..e36970bc70e 100644 --- a/src/vendor/cigraph/src/internal/gmp_internal.h +++ b/src/vendor/cigraph/src/internal/gmp_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2020 The igraph development team it under the terms of the GNU General Public License as published by diff --git a/src/vendor/cigraph/src/internal/hacks.c b/src/vendor/cigraph/src/internal/hacks.c index 2b21b370919..18c7ef6a648 100644 --- a/src/vendor/cigraph/src/internal/hacks.c +++ b/src/vendor/cigraph/src/internal/hacks.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/internal/hacks.h b/src/vendor/cigraph/src/internal/hacks.h index 04e57c1402b..270c073624e 100644 --- a/src/vendor/cigraph/src/internal/hacks.h +++ b/src/vendor/cigraph/src/internal/hacks.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/internal/lsap.c b/src/vendor/cigraph/src/internal/lsap.c index 23eb1a08d8e..7494419ef36 100644 --- a/src/vendor/cigraph/src/internal/lsap.c +++ b/src/vendor/cigraph/src/internal/lsap.c @@ -31,25 +31,25 @@ typedef enum reduce_t { } reduce_t; typedef struct { - igraph_integer_t n; /* order of problem */ + igraph_int_t n; /* order of problem */ double **C; /* cost matrix */ double **c; /* reduced cost matrix */ - igraph_integer_t *s; /* assignment */ - igraph_integer_t *f; /* column i is assigned to f[i] */ - igraph_integer_t na; /* number of assigned items; */ - igraph_integer_t runs; /* number of iterations */ + igraph_int_t *s; /* assignment */ + igraph_int_t *f; /* column i is assigned to f[i] */ + igraph_int_t na; /* number of assigned items; */ + igraph_int_t runs; /* number of iterations */ double cost; /* minimum cost */ } AP; /* public interface */ /* constructors and destructor */ -static igraph_error_t ap_create_problem(AP **problem, const double *t, const igraph_integer_t n); +static igraph_error_t ap_create_problem(AP **problem, const double *t, const igraph_int_t n); /* static AP *ap_create_problem_from_matrix(double **t, int n); */ /* static AP *ap_read_problem(char *file); */ static void ap_free(AP *p); -static igraph_integer_t ap_get_result(AP *p, igraph_integer_t *res); +static igraph_int_t ap_get_result(AP *p, igraph_int_t *res); /* static int ap_costmatrix(AP *p, double **m); */ /* static int ap_datamatrix(AP *p, double **m); */ /* static int ap_iterations(AP *p); */ @@ -76,15 +76,15 @@ igraph_error_t ap_hungarian(AP *p) { covered_t *ri; /* covered rows */ covered_t *ci; /* covered columns */ - const igraph_integer_t n = p->n; /* size of problem */ + const igraph_int_t n = p->n; /* size of problem */ p->runs = 0; /* allocate memory */ /* Note: p is already on the finally stack here. */ - p->s = IGRAPH_CALLOC(1 + n, igraph_integer_t); + p->s = IGRAPH_CALLOC(1 + n, igraph_int_t); IGRAPH_CHECK_OOM(p->s, memerr); - p->f = IGRAPH_CALLOC(1 + n, igraph_integer_t); + p->f = IGRAPH_CALLOC(1 + n, igraph_int_t); IGRAPH_CHECK_OOM(p->f, memerr); ri = IGRAPH_CALLOC(1 + n, covered_t); @@ -108,9 +108,9 @@ igraph_error_t ap_hungarian(AP *p) { } /* check if assignment is a permutation of (1..n) */ - for (igraph_integer_t i = 1; i <= n; i++) { - igraph_integer_t ok = 0; - for (igraph_integer_t j = 1; j <= n; j++) + for (igraph_int_t i = 1; i <= n; i++) { + igraph_int_t ok = 0; + for (igraph_int_t j = 1; j <= n; j++) if (p->s[j] == i) { ++ok; } @@ -121,12 +121,12 @@ igraph_error_t ap_hungarian(AP *p) { /* calculate cost of assignment */ p->cost = 0; - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { p->cost += p->C[i][p->s[i]]; } /* reset result back to base-0 indexing */ - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { p->s[i - 1] = p->s[i] - 1; } @@ -140,8 +140,8 @@ igraph_error_t ap_hungarian(AP *p) { } /* abbreviated interface */ -igraph_integer_t ap_get_result(AP *p, igraph_integer_t *res) { - for (igraph_integer_t i = 0; i < p->n; i++) { +igraph_int_t ap_get_result(AP *p, igraph_int_t *res) { + for (igraph_int_t i = 0; i < p->n; i++) { res[i] = p->s[i]; } @@ -284,7 +284,7 @@ AP *ap_create_problem_from_matrix(double **t, int n) { #endif /* read data from vector */ -igraph_error_t ap_create_problem(AP **problem, const double *t, const igraph_integer_t n) { +igraph_error_t ap_create_problem(AP **problem, const double *t, const igraph_int_t n) { *problem = IGRAPH_CALLOC(1, AP); IGRAPH_CHECK_OOM(*problem, memerr); IGRAPH_FINALLY(ap_free, *problem); @@ -299,15 +299,15 @@ igraph_error_t ap_create_problem(AP **problem, const double *t, const igraph_int p->c = IGRAPH_CALLOC(n+1, double *); IGRAPH_CHECK_OOM(p->c, memerr); - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { p->C[i] = IGRAPH_CALLOC(n+1, double); IGRAPH_CHECK_OOM(p->C[i], memerr); p->c[i] = IGRAPH_CALLOC(n+1, double); IGRAPH_CHECK_OOM(p->c[i], memerr); } - for (igraph_integer_t i = 1; i <= n; i++) { - for (igraph_integer_t j = 1; j <= n; j++) { + for (igraph_int_t i = 1; i <= n; i++) { + for (igraph_int_t j = 1; j <= n; j++) { p->C[i][j] = t[n * (j - 1) + i - 1]; p->c[i][j] = t[n * (j - 1) + i - 1]; } @@ -326,7 +326,7 @@ void ap_free(AP *p) { IGRAPH_FREE(p->s); IGRAPH_FREE(p->f); - for (igraph_integer_t i = 1; i <= p->n; i++) { + for (igraph_int_t i = 1; i <= p->n; i++) { IGRAPH_FREE(p->C[i]); IGRAPH_FREE(p->c[i]); } @@ -341,7 +341,7 @@ void ap_free(AP *p) { /* void ap_show_data(AP *p) { - igraph_integer_t i, j; + igraph_int_t i, j; for(i = 1; i <= p->n; i++){ for(j = 1; j <= p->n; j++) @@ -358,7 +358,7 @@ double ap_mincost(AP *p) { return p->cost; } -igraph_integer_t ap_size(AP *p) { +igraph_int_t ap_size(AP *p) { return p->n; } @@ -372,7 +372,7 @@ int ap_iterations(AP *p) { void ap_print_solution(AP *p) { - igraph_integer_t i; + igraph_int_t i; printf("%d itertations, %d secs.\n",p->runs, (int)p->rtime); printf("Min Cost: %10.4f\n",p->cost); @@ -383,7 +383,7 @@ void ap_print_solution(AP *p) } int ap_costmatrix(AP *p, double **m) { - igraph_integer_t i, j; + igraph_int_t i, j; for (i = 0; i < p->n; i++) for (j = 0; j < p->n; j++) { @@ -394,7 +394,7 @@ int ap_costmatrix(AP *p, double **m) { } int ap_datamatrix(AP *p, double **m) { - igraph_integer_t i, j; + igraph_int_t i, j; for (i = 0; i < p->n; i++) for (j = 0; j < p->n; j++) { @@ -422,15 +422,15 @@ void ap_error(char *message) igraph_error_t cover(AP *p, covered_t *ri, covered_t *ci, reduce_t *res) { marked_t *mr; - igraph_integer_t r; + igraph_int_t r; - const igraph_integer_t n = p->n; + const igraph_int_t n = p->n; mr = IGRAPH_CALLOC(1 + p->n, marked_t); IGRAPH_CHECK_OOM(mr, memerr); /* reset cover indices */ - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { if (p->s[i] == UNASSIGNED) { ri[i] = UNCOVERED; mr[i] = MARKED; @@ -443,7 +443,7 @@ igraph_error_t cover(AP *p, covered_t *ri, covered_t *ci, reduce_t *res) { while (true) { /* find marked row */ r = 0; - for (igraph_integer_t i = 1; i <= n; i++) + for (igraph_int_t i = 1; i <= n; i++) if (mr[i] == MARKED) { r = i; break; @@ -452,7 +452,7 @@ igraph_error_t cover(AP *p, covered_t *ri, covered_t *ci, reduce_t *res) { if (r == 0) { break; } - for (igraph_integer_t i = 1; i <= n; i++) + for (igraph_int_t i = 1; i <= n; i++) if (p->c[r][i] == 0 && ci[i] == UNCOVERED) { if (p->f[i]) { ri[p->f[i]] = UNCOVERED; @@ -482,12 +482,12 @@ igraph_error_t cover(AP *p, covered_t *ri, covered_t *ci, reduce_t *res) { void reduce(AP *p, const covered_t *ri, const covered_t *ci) { double min; - const igraph_integer_t n = p->n; + const igraph_int_t n = p->n; /* find minimum in uncovered c-matrix */ min = DBL_MAX; - for (igraph_integer_t i = 1; i <= n; i++) - for (igraph_integer_t j = 1; j <= n; j++) + for (igraph_int_t i = 1; i <= n; i++) + for (igraph_int_t j = 1; j <= n; j++) if (ri[i] == UNCOVERED && ci[j] == UNCOVERED) { if (p->c[i][j] < min) { min = p->c[i][j]; @@ -496,8 +496,8 @@ void reduce(AP *p, const covered_t *ri, const covered_t *ci) { /* subtract min from each uncovered element and add it to each element */ /* which is covered twice */ - for (igraph_integer_t i = 1; i <= n; i++) - for (igraph_integer_t j = 1; j <= n; j++) { + for (igraph_int_t i = 1; i <= n; i++) + for (igraph_int_t j = 1; j <= n; j++) { if (ri[i] == UNCOVERED && ci[j] == UNCOVERED) { p->c[i][j] -= min; } @@ -508,9 +508,9 @@ void reduce(AP *p, const covered_t *ri, const covered_t *ci) { } igraph_error_t preassign(AP *p) { - igraph_integer_t min, r, c, n, count; + igraph_int_t min, r, c, n, count; assigned_t *ri, *ci; - igraph_integer_t *rz, *cz; + igraph_int_t *rz, *cz; n = p->n; p->na = 0; @@ -525,26 +525,26 @@ igraph_error_t preassign(AP *p) { IGRAPH_FINALLY(igraph_free, ci); /* row and column counts of zeroes */ - rz = IGRAPH_CALLOC(1 + n, igraph_integer_t); + rz = IGRAPH_CALLOC(1 + n, igraph_int_t); IGRAPH_CHECK_OOM(rz, memerr); IGRAPH_FINALLY(igraph_free, rz); - cz = IGRAPH_CALLOC(1 + n, igraph_integer_t); + cz = IGRAPH_CALLOC(1 + n, igraph_int_t); IGRAPH_CHECK_OOM(cz, memerr); IGRAPH_FINALLY(igraph_free, cz); - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { count = 0; - for (igraph_integer_t j = 1; j <= n; j++) + for (igraph_int_t j = 1; j <= n; j++) if (p->c[i][j] == 0) { ++count; } rz[i] = count; } - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { count = 0; - for (igraph_integer_t j = 1; j <= n; j++) + for (igraph_int_t j = 1; j <= n; j++) if (p->c[j][i] == 0) { ++count; } @@ -555,7 +555,7 @@ igraph_error_t preassign(AP *p) { /* find unassigned row with least number of zeroes > 0 */ min = IGRAPH_INTEGER_MAX; r = 0; - for (igraph_integer_t i = 1; i <= n; i++) + for (igraph_int_t i = 1; i <= n; i++) if (rz[i] > 0 && rz[i] < min && ri[i] == UNASSIGNED) { min = rz[i]; r = i; @@ -568,7 +568,7 @@ igraph_error_t preassign(AP *p) { /* find unassigned column in row r with least number of zeroes */ c = 0; min = IGRAPH_INTEGER_MAX; - for (igraph_integer_t i = 1; i <= n; i++) + for (igraph_int_t i = 1; i <= n; i++) if (p->c[r][i] == 0 && cz[i] < min && ci[i] == UNASSIGNED) { min = cz[i]; c = i; @@ -584,7 +584,7 @@ igraph_error_t preassign(AP *p) { /* adjust zero counts */ cz[c] = 0; - for (igraph_integer_t i = 1; i <= n; i++) + for (igraph_int_t i = 1; i <= n; i++) if (p->c[i][c] == 0) { --rz[i]; } @@ -603,28 +603,28 @@ igraph_error_t preassign(AP *p) { void preprocess(AP *p) { double min; - const igraph_integer_t n = p->n; + const igraph_int_t n = p->n; /* subtract column minima in each row */ - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { min = p->c[i][1]; - for (igraph_integer_t j = 2; j <= n; j++) + for (igraph_int_t j = 2; j <= n; j++) if (p->c[i][j] < min) { min = p->c[i][j]; } - for (igraph_integer_t j = 1; j <= n; j++) { + for (igraph_int_t j = 1; j <= n; j++) { p->c[i][j] -= min; } } /* subtract row minima in each column */ - for (igraph_integer_t i = 1; i <= n; i++) { + for (igraph_int_t i = 1; i <= n; i++) { min = p->c[1][i]; - for (igraph_integer_t j = 2; j <= n; j++) + for (igraph_int_t j = 2; j <= n; j++) if (p->c[j][i] < min) { min = p->c[j][i]; } - for (igraph_integer_t j = 1; j <= n; j++) { + for (igraph_int_t j = 1; j <= n; j++) { p->c[j][i] -= min; } } @@ -661,7 +661,7 @@ void preprocess(AP *p) { * * Time complexity: O(n^3), where n is the number of agents. */ -igraph_error_t igraph_solve_lsap(const igraph_matrix_t *c, igraph_integer_t n, +igraph_error_t igraph_solve_lsap(const igraph_matrix_t *c, igraph_int_t n, igraph_vector_int_t *p) { AP *ap; diff --git a/src/vendor/cigraph/src/internal/utils.c b/src/vendor/cigraph/src/internal/utils.c index b1553af4195..058bd12fe87 100644 --- a/src/vendor/cigraph/src/internal/utils.c +++ b/src/vendor/cigraph/src/internal/utils.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -17,6 +17,8 @@ */ #include "igraph_interface.h" +#include "igraph_qsort.h" +#include "igraph_random.h" #include "internal/utils.h" @@ -51,9 +53,9 @@ igraph_error_t igraph_i_matrix_subset_vertices( /* Assertion: the size of 'm' agrees with 'graph': */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t ncol = igraph_matrix_ncol(m); - igraph_integer_t nrow = igraph_matrix_nrow(m); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t ncol = igraph_matrix_ncol(m); + igraph_int_t nrow = igraph_matrix_nrow(m); IGRAPH_ASSERT(nrow == no_of_nodes && nrow == ncol); @@ -76,8 +78,8 @@ igraph_error_t igraph_i_matrix_subset_vertices( IGRAPH_MATRIX_INIT_FINALLY(&tmp, IGRAPH_VIT_SIZE(fromvit), IGRAPH_VIT_SIZE(tovit)); - for (igraph_integer_t j=0; ! IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit), j++) { - igraph_integer_t i; + for (igraph_int_t j=0; ! IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit), j++) { + igraph_int_t i; for (IGRAPH_VIT_RESET(fromvit), i=0; ! IGRAPH_VIT_END(fromvit); IGRAPH_VIT_NEXT(fromvit), i++) { MATRIX(tmp, i, j) = MATRIX(*m, IGRAPH_VIT_GET(fromvit), IGRAPH_VIT_GET(tovit)); } @@ -93,3 +95,130 @@ igraph_error_t igraph_i_matrix_subset_vertices( return IGRAPH_SUCCESS; } + + +/* Lexicographic edge comparator, used with igraph_qsort() in igraph_i_simplify_edge_list() */ +static int edge_comparator(const void *a, const void *b) { + igraph_int_t *A = (igraph_int_t *) a; + igraph_int_t *B = (igraph_int_t *) b; + + if (A[0] < B[0]) { + return -1; + } + if (A[0] > B[0]) { + return 1; + } + + /* first are equal */ + if (A[1] < B[1]) { + return -1; + } + if (A[1] > B[1]) { + return 1; + } + + /* second are equal, so the edges must be equal */ + return 0; +} + +/** + * Simplify an edge list in-place. Edges may be reordered by this function. + * + * TODO: Refactor this to take the number of vertices as input and use linear-time radix sort. + * + * \param edges The edge list vector, as a consecutive list of pairs. It will be modified in-place. + * \param self_loops Set to \c false to remove self-loops. + * \param multi_edges Set to \c false to eliminate multi-edges. + * \param directed Whether to treat edges as directed. + */ +void igraph_i_simplify_edge_list( + igraph_vector_int_t *edges, + igraph_bool_t remove_loops, igraph_bool_t remove_multiple, + igraph_bool_t directed) { + + igraph_int_t size = igraph_vector_int_size(edges); + + if (size == 0 || (!remove_loops && !remove_multiple)) { + return; + } + + /* Canonicalize undirected edges. */ + if (!directed) { + for (igraph_int_t i = 0; i < size; i += 2) { + if (VECTOR(*edges)[i] > VECTOR(*edges)[i + 1]) { + igraph_int_t temp = VECTOR(*edges)[i]; + VECTOR(*edges)[i] = VECTOR(*edges)[i + 1]; + VECTOR(*edges)[i + 1] = temp; + } + } + } + + /* Sort edge list. Not needed if multi edges are allowed. */ + if (remove_multiple) { + igraph_qsort(VECTOR(*edges), size / 2, 2 * sizeof(igraph_int_t), + &edge_comparator); + } + + /* Remove self-loops and duplicate edges from the sorted edge list, in place. + * i points to the current edge being examined, j points to the last edge copied. */ + + igraph_int_t j = -2; + for (igraph_int_t i = 0 ; i < size; i += 2) { + if (remove_multiple && + /* If we've already copied some edges, */ + j != -2 && + /* and the current edge is equal to the previously copied one: */ + VECTOR(*edges)[i] == VECTOR(*edges)[j] && + VECTOR(*edges)[i + 1] == VECTOR(*edges)[j + 1]) + { + /* This edge is a duplicate, and should be skipped */ + continue; + } + + if (remove_loops && + VECTOR(*edges)[i] == VECTOR(*edges)[i + 1]) + { + /* This edge is a self loop, and should be skipped */ + continue; + } + + j += 2; + VECTOR(*edges)[j] = VECTOR(*edges)[i]; + VECTOR(*edges)[j + 1] = VECTOR(*edges)[i + 1]; + } + + igraph_vector_int_resize(edges, j + 2); /* shrinks */ +} + +/** + * Shuffle a list of pairs, such as an edge list. + * + * \param pairs Vector of pairs, will be modified in-place. + * \return Error code, when the input is not of even length. + */ +igraph_error_t igraph_i_vector_int_shuffle_pairs(igraph_vector_int_t *pairs) { + igraph_int_t pair_count = igraph_vector_int_size(pairs); + + if (pair_count % 2 == 1) { + IGRAPH_ERROR("A vector of pairs must have an even length.", IGRAPH_EINVAL); + } + + pair_count /= 2; + while (pair_count > 1) { + igraph_int_t dummy, k; + + pair_count--; + k = RNG_INTEGER(0, pair_count); + + dummy = VECTOR(*pairs)[pair_count * 2]; + VECTOR(*pairs)[pair_count * 2] = VECTOR(*pairs)[k * 2]; + + VECTOR(*pairs)[k * 2] = dummy; + dummy = VECTOR(*pairs)[pair_count * 2 + 1]; + + VECTOR(*pairs)[pair_count * 2] = VECTOR(*pairs)[k * 2 + 1]; + VECTOR(*pairs)[k * 2 + 1] = dummy; + } + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/internal/utils.h b/src/vendor/cigraph/src/internal/utils.h index 94be451fc3a..f3be6b2877e 100644 --- a/src/vendor/cigraph/src/internal/utils.h +++ b/src/vendor/cigraph/src/internal/utils.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2008-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,4 +29,11 @@ igraph_error_t igraph_i_matrix_subset_vertices( igraph_vs_t from, igraph_vs_t to); +void igraph_i_simplify_edge_list( + igraph_vector_int_t *edges, + igraph_bool_t self_loops, igraph_bool_t multi_edges, + igraph_bool_t directed); + +igraph_error_t igraph_i_vector_int_shuffle_pairs(igraph_vector_int_t *pairs); + #endif /* IGRAPH_INTERNAL_UTILS_H */ diff --git a/src/vendor/cigraph/src/io/dimacs.c b/src/vendor/cigraph/src/io/dimacs.c index 5b4527da3f5..31543514e37 100644 --- a/src/vendor/cigraph/src/io/dimacs.c +++ b/src/vendor/cigraph/src/io/dimacs.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -107,16 +107,16 @@ igraph_error_t igraph_read_graph_dimacs_flow( igraph_t *graph, FILE *instream, igraph_strvector_t *problem, igraph_vector_int_t *label, - igraph_integer_t *source, - igraph_integer_t *target, + igraph_int_t *source, + igraph_int_t *target, igraph_vector_t *capacity, igraph_bool_t directed) { igraph_vector_int_t edges; - igraph_integer_t no_of_nodes = -1; - igraph_integer_t no_of_edges = -1; - igraph_integer_t tsource = -1; - igraph_integer_t ttarget = -1; + igraph_int_t no_of_nodes = -1; + igraph_int_t no_of_edges = -1; + igraph_int_t tsource = -1; + igraph_int_t ttarget = -1; char prob[21]; enum { PROBLEM_NONE, @@ -141,8 +141,8 @@ igraph_error_t igraph_read_graph_dimacs_flow( } EXPECT(read, 1); switch (str[0]) { - igraph_integer_t tmp, tmp2; - igraph_integer_t from, to; + igraph_int_t tmp, tmp2; + igraph_int_t from, to; igraph_real_t cap; case 'c': @@ -312,13 +312,13 @@ igraph_error_t igraph_read_graph_dimacs_flow( * \sa \ref igraph_read_graph_dimacs_flow() */ igraph_error_t igraph_write_graph_dimacs_flow(const igraph_t *graph, FILE *outstream, - igraph_integer_t source, igraph_integer_t target, + igraph_int_t source, igraph_int_t target, const igraph_vector_t *capacity) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_eit_t it; - igraph_integer_t i = 0; + igraph_int_t i = 0; int ret, ret1, ret2, ret3; if (igraph_vector_size(capacity) != no_of_edges) { @@ -342,7 +342,7 @@ igraph_error_t igraph_write_graph_dimacs_flow(const igraph_t *graph, FILE *outst } while (!IGRAPH_EIT_END(it)) { - igraph_integer_t from, to; + igraph_int_t from, to; igraph_real_t cap; igraph_edge(graph, IGRAPH_EIT_GET(it), &from, &to); cap = VECTOR(*capacity)[i++]; diff --git a/src/vendor/cigraph/src/io/dl-header.h b/src/vendor/cigraph/src/io/dl-header.h index b34910957aa..1da687e9241 100644 --- a/src/vendor/cigraph/src/io/dl-header.h +++ b/src/vendor/cigraph/src/io/dl-header.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -43,8 +43,8 @@ typedef struct { char errmsg[300]; igraph_error_t igraph_errno; int mode; - igraph_integer_t n; - igraph_integer_t from, to; + igraph_int_t n; + igraph_int_t from, to; igraph_vector_int_t edges; igraph_vector_t weights; igraph_strvector_t labels; diff --git a/src/vendor/cigraph/src/io/dl-lexer.l b/src/vendor/cigraph/src/io/dl-lexer.l index e34d8e29db5..8cf0b21af7b 100644 --- a/src/vendor/cigraph/src/io/dl-lexer.l +++ b/src/vendor/cigraph/src/io/dl-lexer.l @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA diff --git a/src/vendor/cigraph/src/io/dl-parser.y b/src/vendor/cigraph/src/io/dl-parser.y index d166f889aff..22923effcbf 100644 --- a/src/vendor/cigraph/src/io/dl-parser.y +++ b/src/vendor/cigraph/src/io/dl-parser.y @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2009-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -54,12 +54,12 @@ int igraph_dl_yyerror(YYLTYPE* locp, igraph_i_dl_parsedata_t* context, const char *s); static igraph_error_t igraph_i_dl_add_str(char *newstr, yy_size_t length, igraph_i_dl_parsedata_t *context); -static igraph_error_t igraph_i_dl_add_edge(igraph_integer_t from, igraph_integer_t to, +static igraph_error_t igraph_i_dl_add_edge(igraph_int_t from, igraph_int_t to, igraph_i_dl_parsedata_t *context); -static igraph_error_t igraph_i_dl_add_edge_w(igraph_integer_t from, igraph_integer_t to, +static igraph_error_t igraph_i_dl_add_edge_w(igraph_int_t from, igraph_int_t to, igraph_real_t weight, igraph_i_dl_parsedata_t *context); -static igraph_error_t igraph_i_dl_check_vid(igraph_integer_t dl_vid); +static igraph_error_t igraph_i_dl_check_vid(igraph_int_t dl_vid); #define scanner context->scanner @@ -76,7 +76,7 @@ static igraph_error_t igraph_i_dl_check_vid(igraph_integer_t dl_vid); %lex-param { void* scanner } %union { - igraph_integer_t integer; + igraph_int_t integer; igraph_real_t real; }; @@ -195,19 +195,19 @@ edgelist1data: {} /* nothing, empty graph */ ; edgelist1dataline: integer integer weight NEWLINE { - igraph_integer_t from = $1, to = $2; + igraph_int_t from = $1, to = $2; IGRAPH_YY_CHECK(igraph_i_dl_check_vid(from)); IGRAPH_YY_CHECK(igraph_i_dl_check_vid(to)); IGRAPH_YY_CHECK(igraph_i_dl_add_edge_w(from-1, to-1, $3, context)); } | integer integer NEWLINE { - igraph_integer_t from = $1, to = $2; + igraph_int_t from = $1, to = $2; IGRAPH_YY_CHECK(igraph_i_dl_check_vid(from)); IGRAPH_YY_CHECK(igraph_i_dl_check_vid(to)); IGRAPH_YY_CHECK(igraph_i_dl_add_edge(from-1, to-1, context)); } ; integer: NUM { - igraph_integer_t val; + igraph_int_t val; IGRAPH_YY_CHECK(igraph_i_parse_integer(igraph_dl_yyget_text(scanner), igraph_dl_yyget_leng(scanner), &val)); @@ -233,11 +233,11 @@ weight: NUM { }; elabel: LABEL { - igraph_integer_t trie_id; + igraph_int_t trie_id; /* Copy label list to trie, if needed */ if (igraph_strvector_size(&context->labels) != 0) { - igraph_integer_t i, id, n=igraph_strvector_size(&context->labels); + igraph_int_t i, id, n=igraph_strvector_size(&context->labels); for (i=0; itrie, igraph_strvector_get(&context->labels, i), &id)); } @@ -274,7 +274,7 @@ from: NUM { } ; tolist: {} | tolist integer { - igraph_integer_t to = $2; + igraph_int_t to = $2; IGRAPH_YY_CHECK(igraph_i_dl_check_vid(to)); IGRAPH_YY_CHECK(igraph_vector_int_push_back(&context->edges, context->from-1)); @@ -314,7 +314,7 @@ static igraph_error_t igraph_i_dl_add_str(char *newstr, yy_size_t length, return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_dl_add_edge(igraph_integer_t from, igraph_integer_t to, +static igraph_error_t igraph_i_dl_add_edge(igraph_int_t from, igraph_int_t to, igraph_i_dl_parsedata_t *context) { //IGRAPH_CHECK(igraph_i_dl_check_vid(from+1)); //IGRAPH_CHECK(igraph_i_dl_check_vid(to+1)); @@ -323,11 +323,11 @@ static igraph_error_t igraph_i_dl_add_edge(igraph_integer_t from, igraph_integer return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_dl_add_edge_w(igraph_integer_t from, igraph_integer_t to, +static igraph_error_t igraph_i_dl_add_edge_w(igraph_int_t from, igraph_int_t to, igraph_real_t weight, igraph_i_dl_parsedata_t *context) { - igraph_integer_t n=igraph_vector_size(&context->weights); - igraph_integer_t n2=igraph_vector_int_size(&context->edges)/2; + igraph_int_t n=igraph_vector_size(&context->weights); + igraph_int_t n2=igraph_vector_int_size(&context->edges)/2; if (n != n2) { IGRAPH_CHECK(igraph_vector_resize(&context->weights, n2)); for (; n" : "--"; igraph_strvector_t gnames, vnames, enames; @@ -198,7 +198,7 @@ igraph_error_t igraph_write_graph_dot(const igraph_t *graph, FILE* outstream) { /* Write the graph attributes */ if (igraph_vector_int_size(>ypes) > 0) { CHECK(fprintf(outstream, " graph [\n")); - for (igraph_integer_t i = 0; i < igraph_vector_int_size(>ypes); i++) { + for (igraph_int_t i = 0; i < igraph_vector_int_size(>ypes); i++) { const char *name; name = igraph_strvector_get(&gnames, i); IGRAPH_CHECK(dot_escape(name, &buf)); @@ -226,9 +226,9 @@ igraph_error_t igraph_write_graph_dot(const igraph_t *graph, FILE* outstream) { /* Write the vertices */ if (igraph_vector_int_size(&vtypes) > 0) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { CHECK(fprintf(outstream, " %" IGRAPH_PRId " [\n", i)); - for (igraph_integer_t j = 0; j < igraph_vector_int_size(&vtypes); j++) { + for (igraph_int_t j = 0; j < igraph_vector_int_size(&vtypes); j++) { const char *name; name = igraph_strvector_get(&vnames, j); IGRAPH_CHECK(dot_escape(name, &buf)); @@ -254,7 +254,7 @@ igraph_error_t igraph_write_graph_dot(const igraph_t *graph, FILE* outstream) { CHECK(fprintf(outstream, " ];\n")); } } else { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { CHECK(fprintf(outstream, " %" IGRAPH_PRId ";\n", i)); } } @@ -262,11 +262,11 @@ igraph_error_t igraph_write_graph_dot(const igraph_t *graph, FILE* outstream) { /* Write the edges */ if (igraph_vector_int_size(&etypes) > 0) { - for (igraph_integer_t i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); + for (igraph_int_t i = 0; i < no_of_edges; i++) { + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); CHECK(fprintf(outstream, " %" IGRAPH_PRId " %s %" IGRAPH_PRId " [\n", from, edgeop, to)); - for (igraph_integer_t j = 0; j < igraph_vector_int_size(&etypes); j++) { + for (igraph_int_t j = 0; j < igraph_vector_int_size(&etypes); j++) { const char *name; name = igraph_strvector_get(&enames, j); IGRAPH_CHECK(dot_escape(name, &buf)); @@ -295,9 +295,9 @@ igraph_error_t igraph_write_graph_dot(const igraph_t *graph, FILE* outstream) { CHECK(fprintf(outstream, " ];\n")); } } else { - for (igraph_integer_t i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); + for (igraph_int_t i = 0; i < no_of_edges; i++) { + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); CHECK(fprintf(outstream, " %" IGRAPH_PRId " %s %" IGRAPH_PRId ";\n", from, edgeop, to)); } } diff --git a/src/vendor/cigraph/src/io/edgelist.c b/src/vendor/cigraph/src/io/edgelist.c index f763ff53691..d0bb089af7c 100644 --- a/src/vendor/cigraph/src/io/edgelist.c +++ b/src/vendor/cigraph/src/io/edgelist.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -75,10 +75,10 @@ * reading an integer requires O(1) time. */ igraph_error_t igraph_read_graph_edgelist(igraph_t *graph, FILE *instream, - igraph_integer_t n, igraph_bool_t directed) { + igraph_int_t n, igraph_bool_t directed) { igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; - igraph_integer_t from, to; + igraph_int_t from, to; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 100)); @@ -142,7 +142,7 @@ igraph_error_t igraph_write_graph_edgelist(const igraph_t *graph, FILE *outstrea IGRAPH_FINALLY(igraph_eit_destroy, &it); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t from, to; + igraph_int_t from, to; int ret; igraph_edge(graph, IGRAPH_EIT_GET(it), &from, &to); ret = fprintf(outstream, "%" IGRAPH_PRId " %" IGRAPH_PRId "\n", diff --git a/src/vendor/cigraph/src/io/gml-header.h b/src/vendor/cigraph/src/io/gml-header.h index b8d590d8068..ef9b5d3f928 100644 --- a/src/vendor/cigraph/src/io/gml-header.h +++ b/src/vendor/cigraph/src/io/gml-header.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2021 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/io/gml-lexer.l b/src/vendor/cigraph/src/io/gml-lexer.l index 375dc6fbca0..7e9c5c6042d 100644 --- a/src/vendor/cigraph/src/io/gml-lexer.l +++ b/src/vendor/cigraph/src/io/gml-lexer.l @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA diff --git a/src/vendor/cigraph/src/io/gml-parser.y b/src/vendor/cigraph/src/io/gml-parser.y index c9ee9454b7c..d11fc4da30b 100644 --- a/src/vendor/cigraph/src/io/gml-parser.y +++ b/src/vendor/cigraph/src/io/gml-parser.y @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2009-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -186,7 +186,7 @@ static igraph_error_t igraph_i_gml_make_numeric(const char *name, IGRAPH_FINALLY(igraph_free, t); /* The GML spec only requires support for 32-bit signed integers, - * but igraph tries to support the same range as igraph_integer_t, + * but igraph tries to support the same range as igraph_int_t, * so that it can read/write all graphs it can represent. * We treat anything out of that range as real. These values end * up as igraph_real_t anyway, as igraph does not currently support diff --git a/src/vendor/cigraph/src/io/gml-tree.c b/src/vendor/cigraph/src/io/gml-tree.c index 59b08077836..05b1d1d6c84 100644 --- a/src/vendor/cigraph/src/io/gml-tree.c +++ b/src/vendor/cigraph/src/io/gml-tree.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,10 +27,10 @@ igraph_error_t igraph_gml_tree_init_integer(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, - igraph_integer_t value) { + igraph_int_t line, + igraph_int_t value) { - igraph_integer_t *p; + igraph_int_t *p; IGRAPH_VECTOR_PTR_INIT_FINALLY(&t->names, 1); IGRAPH_VECTOR_CHAR_INIT_FINALLY(&t->types, 1); @@ -47,7 +47,7 @@ igraph_error_t igraph_gml_tree_init_integer(igraph_gml_tree_t *t, VECTOR(t->types)[0] = IGRAPH_I_GML_TREE_INTEGER; /* children */ - p = IGRAPH_CALLOC(1, igraph_integer_t); + p = IGRAPH_CALLOC(1, igraph_int_t); IGRAPH_CHECK_OOM(p, "Cannot create integer GML tree node."); *p = value; VECTOR(t->children)[0] = p; @@ -58,7 +58,7 @@ igraph_error_t igraph_gml_tree_init_integer(igraph_gml_tree_t *t, igraph_error_t igraph_gml_tree_init_real(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, + igraph_int_t line, igraph_real_t value) { igraph_real_t *p; @@ -89,7 +89,7 @@ igraph_error_t igraph_gml_tree_init_real(igraph_gml_tree_t *t, igraph_error_t igraph_gml_tree_init_string(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, + igraph_int_t line, const char *value) { IGRAPH_VECTOR_PTR_INIT_FINALLY(&t->names, 1); @@ -115,7 +115,7 @@ igraph_error_t igraph_gml_tree_init_string(igraph_gml_tree_t *t, igraph_error_t igraph_gml_tree_init_tree(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, + igraph_int_t line, igraph_gml_tree_t *value) { IGRAPH_VECTOR_PTR_INIT_FINALLY(&t->names, 1); @@ -151,7 +151,7 @@ igraph_error_t igraph_gml_tree_init_empty(igraph_gml_tree_t *t) { /* merge is destructive, the _second_ tree is destroyed */ igraph_error_t igraph_gml_tree_mergedest(igraph_gml_tree_t *t1, igraph_gml_tree_t *t2) { - igraph_integer_t i, n = igraph_vector_ptr_size(&t2->children); + igraph_int_t i, n = igraph_vector_ptr_size(&t2->children); for (i = 0; i < n; i++) { IGRAPH_CHECK(igraph_vector_ptr_push_back(&t1->names, VECTOR(t2->names)[i])); @@ -170,7 +170,7 @@ igraph_error_t igraph_gml_tree_mergedest(igraph_gml_tree_t *t1, igraph_gml_tree_ void igraph_gml_tree_destroy(igraph_gml_tree_t *t) { - igraph_integer_t i, n = igraph_vector_ptr_size(&t->children); + igraph_int_t i, n = igraph_vector_ptr_size(&t->children); for (i = 0; i < n; i++) { igraph_i_gml_tree_type_t type = (igraph_i_gml_tree_type_t) VECTOR(t->types)[i]; switch (type) { @@ -201,14 +201,14 @@ void igraph_gml_tree_destroy(igraph_gml_tree_t *t) { IGRAPH_FREE(t); } -igraph_integer_t igraph_gml_tree_length(const igraph_gml_tree_t *t) { +igraph_int_t igraph_gml_tree_length(const igraph_gml_tree_t *t) { return igraph_vector_ptr_size(&t->names); } -igraph_integer_t igraph_gml_tree_find( - const igraph_gml_tree_t *t, const char *name, igraph_integer_t from +igraph_int_t igraph_gml_tree_find( + const igraph_gml_tree_t *t, const char *name, igraph_int_t from ) { - igraph_integer_t size = igraph_vector_ptr_size(&t->names); + igraph_int_t size = igraph_vector_ptr_size(&t->names); while ( from < size && (! VECTOR(t->names)[from] || strcmp(VECTOR(t->names)[from], name)) ) { from++; @@ -220,8 +220,8 @@ igraph_integer_t igraph_gml_tree_find( return from; } -igraph_integer_t igraph_gml_tree_findback( - const igraph_gml_tree_t *t, const char *name, igraph_integer_t from +igraph_int_t igraph_gml_tree_findback( + const igraph_gml_tree_t *t, const char *name, igraph_int_t from ) { while ( from >= 0 && (! VECTOR(t->names)[from] || strcmp(VECTOR(t->names)[from], name)) ) { @@ -231,43 +231,43 @@ igraph_integer_t igraph_gml_tree_findback( return from; } -igraph_i_gml_tree_type_t igraph_gml_tree_type(const igraph_gml_tree_t *t, igraph_integer_t pos) { +igraph_i_gml_tree_type_t igraph_gml_tree_type(const igraph_gml_tree_t *t, igraph_int_t pos) { return (igraph_i_gml_tree_type_t) VECTOR(t->types)[pos]; } -const char *igraph_gml_tree_name(const igraph_gml_tree_t *t, igraph_integer_t pos) { +const char *igraph_gml_tree_name(const igraph_gml_tree_t *t, igraph_int_t pos) { return VECTOR(t->names)[pos]; } -igraph_integer_t igraph_gml_tree_line(const igraph_gml_tree_t *t, igraph_integer_t pos) { +igraph_int_t igraph_gml_tree_line(const igraph_gml_tree_t *t, igraph_int_t pos) { return VECTOR(t->lines)[pos]; } -igraph_integer_t igraph_gml_tree_get_integer(const igraph_gml_tree_t *t, - igraph_integer_t pos) { - igraph_integer_t *i = VECTOR(t->children)[pos]; +igraph_int_t igraph_gml_tree_get_integer(const igraph_gml_tree_t *t, + igraph_int_t pos) { + igraph_int_t *i = VECTOR(t->children)[pos]; return *i; } igraph_real_t igraph_gml_tree_get_real(const igraph_gml_tree_t *t, - igraph_integer_t pos) { + igraph_int_t pos) { igraph_real_t *d = VECTOR(t->children)[pos]; return *d; } const char *igraph_gml_tree_get_string(const igraph_gml_tree_t *t, - igraph_integer_t pos) { + igraph_int_t pos) { const char *s = VECTOR(t->children)[pos]; return s; } igraph_gml_tree_t *igraph_gml_tree_get_tree(const igraph_gml_tree_t *t, - igraph_integer_t pos) { + igraph_int_t pos) { igraph_gml_tree_t *tree = VECTOR(t->children)[pos]; return tree; } -void igraph_gml_tree_delete(igraph_gml_tree_t *t, igraph_integer_t pos) { +void igraph_gml_tree_delete(igraph_gml_tree_t *t, igraph_int_t pos) { if (VECTOR(t->types)[pos] == IGRAPH_I_GML_TREE_TREE) { igraph_gml_tree_destroy(VECTOR(t->children)[pos]); } diff --git a/src/vendor/cigraph/src/io/gml-tree.h b/src/vendor/cigraph/src/io/gml-tree.h index 93731308f90..fbae24a7b0b 100644 --- a/src/vendor/cigraph/src/io/gml-tree.h +++ b/src/vendor/cigraph/src/io/gml-tree.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -44,43 +44,43 @@ typedef struct igraph_gml_tree_t { igraph_error_t igraph_gml_tree_init_integer(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, - igraph_integer_t value); + igraph_int_t line, + igraph_int_t value); igraph_error_t igraph_gml_tree_init_real(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, + igraph_int_t line, igraph_real_t value); igraph_error_t igraph_gml_tree_init_string(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, + igraph_int_t line, const char *value); igraph_error_t igraph_gml_tree_init_tree(igraph_gml_tree_t *t, const char *name, - igraph_integer_t line, + igraph_int_t line, igraph_gml_tree_t *value); igraph_error_t igraph_gml_tree_init_empty(igraph_gml_tree_t *t); void igraph_gml_tree_destroy(igraph_gml_tree_t *t); -void igraph_gml_tree_delete(igraph_gml_tree_t *t, igraph_integer_t pos); +void igraph_gml_tree_delete(igraph_gml_tree_t *t, igraph_int_t pos); igraph_error_t igraph_gml_tree_mergedest(igraph_gml_tree_t *t1, igraph_gml_tree_t *t2); -IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gml_tree_length(const igraph_gml_tree_t *t); -IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gml_tree_find(const igraph_gml_tree_t *t, - const char *name, igraph_integer_t from); -IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gml_tree_findback(const igraph_gml_tree_t *t, - const char *name, igraph_integer_t from); -IGRAPH_FUNCATTR_PURE igraph_i_gml_tree_type_t igraph_gml_tree_type(const igraph_gml_tree_t *t, igraph_integer_t pos); -IGRAPH_FUNCATTR_PURE const char *igraph_gml_tree_name(const igraph_gml_tree_t *t, igraph_integer_t pos); -IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gml_tree_line(const igraph_gml_tree_t *t, igraph_integer_t pos); -IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_gml_tree_get_integer(const igraph_gml_tree_t *t, - igraph_integer_t pos); +IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gml_tree_length(const igraph_gml_tree_t *t); +IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gml_tree_find(const igraph_gml_tree_t *t, + const char *name, igraph_int_t from); +IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gml_tree_findback(const igraph_gml_tree_t *t, + const char *name, igraph_int_t from); +IGRAPH_FUNCATTR_PURE igraph_i_gml_tree_type_t igraph_gml_tree_type(const igraph_gml_tree_t *t, igraph_int_t pos); +IGRAPH_FUNCATTR_PURE const char *igraph_gml_tree_name(const igraph_gml_tree_t *t, igraph_int_t pos); +IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gml_tree_line(const igraph_gml_tree_t *t, igraph_int_t pos); +IGRAPH_FUNCATTR_PURE igraph_int_t igraph_gml_tree_get_integer(const igraph_gml_tree_t *t, + igraph_int_t pos); IGRAPH_FUNCATTR_PURE igraph_real_t igraph_gml_tree_get_real(const igraph_gml_tree_t *t, - igraph_integer_t pos); + igraph_int_t pos); IGRAPH_FUNCATTR_PURE const char *igraph_gml_tree_get_string(const igraph_gml_tree_t *t, - igraph_integer_t pos); + igraph_int_t pos); IGRAPH_FUNCATTR_PURE igraph_gml_tree_t *igraph_gml_tree_get_tree(const igraph_gml_tree_t *t, - igraph_integer_t pos); + igraph_int_t pos); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/io/gml.c b/src/vendor/cigraph/src/io/gml.c index bad40a80208..85df1fc5eff 100644 --- a/src/vendor/cigraph/src/io/gml.c +++ b/src/vendor/cigraph/src/io/gml.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -65,7 +65,7 @@ static igraph_bool_t needs_coding(const char *str) { * '*dest' must be deallocated by the caller. */ static igraph_error_t entity_encode(const char *src, char **dest, igraph_bool_t only_quot) { - igraph_integer_t destlen = 0; + igraph_int_t destlen = 0; const char *s; char *d; @@ -161,7 +161,7 @@ static igraph_error_t entity_decode(const char *src, char **dest, igraph_bool_t return IGRAPH_SUCCESS; } -static igraph_real_t igraph_i_gml_toreal(igraph_gml_tree_t *node, igraph_integer_t pos) { +static igraph_real_t igraph_i_gml_toreal(igraph_gml_tree_t *node, igraph_int_t pos) { igraph_i_gml_tree_type_t type = igraph_gml_tree_type(node, pos); switch (type) { @@ -178,11 +178,11 @@ static igraph_real_t igraph_i_gml_toreal(igraph_gml_tree_t *node, igraph_integer } } -static const char *igraph_i_gml_tostring(igraph_gml_tree_t *node, igraph_integer_t pos) { +static const char *igraph_i_gml_tostring(igraph_gml_tree_t *node, igraph_int_t pos) { igraph_i_gml_tree_type_t type = igraph_gml_tree_type(node, pos); static char tmp[100]; const char *p = tmp; - igraph_integer_t i; + igraph_int_t i; igraph_real_t d; switch (type) { @@ -234,7 +234,7 @@ 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 igraph_error_t prune_unknown_attributes(igraph_attribute_record_list_t *attrs) { - igraph_integer_t i, n; + igraph_int_t i, n; igraph_vector_int_t to_remove; IGRAPH_VECTOR_INT_INIT_FINALLY(&to_remove, 0); @@ -259,7 +259,7 @@ static igraph_error_t prune_unknown_attributes(igraph_attribute_record_list_t *a } /* Converts an integer id to an optionally prefixed string id. */ -static const char *strid(igraph_integer_t id, const char *prefix) { +static const char *strid(igraph_int_t id, const char *prefix) { static char name[100]; snprintf(name, sizeof(name) / sizeof(char) - 1, "%s%" IGRAPH_PRId, prefix, id); return name; @@ -273,7 +273,7 @@ static igraph_error_t create_or_update_attribute(const char *name, igraph_trie_t *attrnames, igraph_attribute_record_list_t *attrs) { - igraph_integer_t trieid, triesize = igraph_trie_size(attrnames); + igraph_int_t trieid, triesize = igraph_trie_size(attrnames); igraph_attribute_type_t desired_type; IGRAPH_CHECK(igraph_trie_get(attrnames, name, &trieid)); @@ -317,10 +317,10 @@ static igraph_error_t create_or_update_attribute(const char *name, * 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_attribute_record_list_t *attrs, igraph_integer_t no_of_items, + igraph_attribute_record_list_t *attrs, igraph_int_t no_of_items, const char *kind ) { - igraph_integer_t i, n = igraph_attribute_record_list_size(attrs); + igraph_int_t i, 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); @@ -385,21 +385,21 @@ static igraph_error_t allocate_attributes( */ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { - igraph_integer_t i; - igraph_integer_t no_of_nodes = 0, no_of_edges = 0; - igraph_integer_t node_no; + igraph_int_t i; + igraph_int_t no_of_nodes = 0, no_of_edges = 0; + igraph_int_t node_no; igraph_trie_t trie; igraph_vector_int_t edges; igraph_bool_t directed = IGRAPH_UNDIRECTED; igraph_bool_t has_directed = false; igraph_gml_tree_t *gtree; - igraph_integer_t gidx; + igraph_int_t gidx; igraph_trie_t vattrnames; igraph_trie_t eattrnames; igraph_trie_t gattrnames; igraph_attribute_record_list_t gattrs, vattrs, eattrs; igraph_attribute_record_list_t *attrs[3]; - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; igraph_i_gml_parsedata_t context; igraph_bool_t entity_warned = false; /* used to warn at most once about unsupported entities */ @@ -504,14 +504,14 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { } node = igraph_gml_tree_get_tree(gtree, i); hasid = false; - for (igraph_integer_t j = 0; j < igraph_gml_tree_length(node); j++) { + for (igraph_int_t j = 0; j < igraph_gml_tree_length(node); j++) { const char *name = igraph_gml_tree_name(node, j); igraph_i_gml_tree_type_t type = igraph_gml_tree_type(node, j); IGRAPH_CHECK(create_or_update_attribute(name, type, &vattrnames, &vattrs)); /* check id */ if (!strcmp(name, "id")) { - igraph_integer_t id, trie_id; - igraph_integer_t trie_size = igraph_trie_size(&trie); + igraph_int_t id, trie_id; + igraph_int_t trie_size = igraph_trie_size(&trie); if (hasid) { /* A 'node' must not have more than one 'id' field. * This error cannot be relaxed into a warning because all ids we find are @@ -537,7 +537,7 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { if (!hasid) { /* Isolated nodes are allowed not to have an id. * We generate an "n"-prefixed string id to be used in the trie. */ - igraph_integer_t trie_id; + igraph_int_t trie_id; IGRAPH_CHECK(igraph_trie_get(&trie, strid(node_no, "n"), &trie_id)); } } else if (!strcmp(name, "edge")) { @@ -549,7 +549,7 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { igraph_gml_tree_line(gtree, i)); } edge = igraph_gml_tree_get_tree(gtree, i); - for (igraph_integer_t j = 0; j < igraph_gml_tree_length(edge); j++) { + for (igraph_int_t j = 0; j < igraph_gml_tree_length(edge); j++) { const char *name = igraph_gml_tree_name(edge, j); igraph_i_gml_tree_type_t type = igraph_gml_tree_type(edge, j); if (!strcmp(name, "source")) { @@ -602,7 +602,7 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { igraph_gml_tree_line(gtree, i)); } if (igraph_gml_tree_type(gtree, i) == IGRAPH_I_GML_TREE_INTEGER) { - igraph_integer_t dir = igraph_gml_tree_get_integer(gtree, i); + igraph_int_t dir = igraph_gml_tree_get_integer(gtree, i); if (dir != 0 && dir != 1) { IGRAPH_WARNINGF( "Invalid value %" IGRAPH_PRId " for 'directed' attribute on line %" IGRAPH_PRId ", should be 0 or 1.", @@ -641,8 +641,8 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { name = igraph_gml_tree_name(gtree, i); if (!strcmp(name, "node")) { igraph_gml_tree_t *node = igraph_gml_tree_get_tree(gtree, i); - igraph_integer_t iidx = igraph_gml_tree_find(node, "id", 0); - igraph_integer_t trie_id; + igraph_int_t iidx = igraph_gml_tree_find(node, "id", 0); + igraph_int_t trie_id; const char *sid; node_no++; if (iidx < 0) { @@ -652,11 +652,11 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { sid = strid(igraph_gml_tree_get_integer(node, iidx), ""); } IGRAPH_CHECK(igraph_trie_get(&trie, sid, &trie_id)); - for (igraph_integer_t j = 0; j < igraph_gml_tree_length(node); j++) { + for (igraph_int_t j = 0; j < igraph_gml_tree_length(node); j++) { const char *aname = igraph_gml_tree_name(node, j); igraph_attribute_record_t *atrec; igraph_attribute_type_t type; - igraph_integer_t ai; + igraph_int_t ai; IGRAPH_CHECK(igraph_trie_get(&vattrnames, aname, &ai)); atrec = igraph_attribute_record_list_get_ptr(&vattrs, ai); type = atrec->type; @@ -681,17 +681,17 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { } } else if (!strcmp(name, "edge")) { igraph_gml_tree_t *edge; - igraph_integer_t from, to, fromidx = 0, toidx = 0; + igraph_int_t from, to, fromidx = 0, toidx = 0; edge = igraph_gml_tree_get_tree(gtree, i); - for (igraph_integer_t j = 0; j < igraph_gml_tree_length(edge); j++) { + for (igraph_int_t j = 0; j < igraph_gml_tree_length(edge); j++) { const char *aname = igraph_gml_tree_name(edge, j); if (!strcmp(aname, "source")) { fromidx = igraph_gml_tree_find(edge, "source", 0); } else if (!strcmp(aname, "target")) { toidx = igraph_gml_tree_find(edge, "target", 0); } else { - igraph_integer_t edgeid = edgeptr / 2; - igraph_integer_t ai; + igraph_int_t edgeid = edgeptr / 2; + igraph_int_t ai; igraph_attribute_record_t *atrec; igraph_attribute_type_t type; IGRAPH_CHECK(igraph_trie_get(&eattrnames, aname, &ai)); @@ -735,7 +735,7 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { /* Nothing to do for 'directed' field, already handled earlier. */ } else { /* Set the rest as graph attributes */ - igraph_integer_t ai; + igraph_int_t ai; igraph_attribute_record_t *atrec; igraph_attribute_type_t type; IGRAPH_CHECK(igraph_trie_get(&gattrnames, name, &ai)); @@ -820,7 +820,7 @@ static igraph_error_t igraph_i_gml_convert_to_key(const char *orig, char **key) * will not be detected. */ static igraph_error_t igraph_i_vector_is_duplicate_free(const igraph_vector_t *v, igraph_bool_t *res) { igraph_vector_t u; - igraph_integer_t n = igraph_vector_size(v); + igraph_int_t n = igraph_vector_size(v); if (n < 2) { *res = true; @@ -832,7 +832,7 @@ static igraph_error_t igraph_i_vector_is_duplicate_free(const igraph_vector_t *v igraph_vector_sort(&u); *res = true; - for (igraph_integer_t i=1; i < n; i++) { + for (igraph_int_t i=1; i < n; i++) { if (VECTOR(u)[i-1] == VECTOR(u)[i]) { *res = false; break; @@ -932,13 +932,13 @@ igraph_error_t igraph_write_graph_gml(const igraph_t *graph, FILE *outstream, const igraph_vector_t *id, const char *creator) { igraph_strvector_t gnames, vnames, enames; /* attribute names */ igraph_vector_int_t gtypes, vtypes, etypes; /* attribute types */ - igraph_integer_t gattr_no, vattr_no, eattr_no; /* attribute counts */ + igraph_int_t gattr_no, vattr_no, eattr_no; /* attribute counts */ igraph_vector_t numv; igraph_strvector_t strv; igraph_vector_bool_t boolv; - igraph_integer_t i; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t i; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); /* Each element is a bit field used to prevent showing more * than one warning for each vertex or edge attribute. */ @@ -1111,7 +1111,7 @@ igraph_error_t igraph_write_graph_gml(const igraph_t *graph, FILE *outstream, #define SETBIT(k, i) ((k) |= (1 << i)) #define WARN_ONCE(attrno, bit, warn) \ do { \ - igraph_integer_t *p = &VECTOR(warning_shown)[attrno]; \ + igraph_int_t *p = &VECTOR(warning_shown)[attrno]; \ if (! GETBIT(*p, bit)) { \ warn; \ SETBIT(*p, bit); \ @@ -1122,10 +1122,10 @@ igraph_error_t igraph_write_graph_gml(const igraph_t *graph, FILE *outstream, /* Now come the vertices */ IGRAPH_VECTOR_INT_INIT_FINALLY(&warning_shown, vattr_no); for (i = 0; i < no_of_nodes; i++) { - igraph_integer_t j; + igraph_int_t j; CHECK(fprintf(outstream, " node\n [\n")); /* id */ - CHECK(fprintf(outstream, " id %" IGRAPH_PRId "\n", myid ? (igraph_integer_t)VECTOR(*myid)[i] : i)); + CHECK(fprintf(outstream, " id %" IGRAPH_PRId "\n", myid ? (igraph_int_t)VECTOR(*myid)[i] : i)); /* other attributes */ for (j = 0; j < vattr_no; j++) { igraph_attribute_type_t type = (igraph_attribute_type_t) VECTOR(vtypes)[j]; @@ -1193,15 +1193,15 @@ igraph_error_t igraph_write_graph_gml(const igraph_t *graph, FILE *outstream, IGRAPH_CHECK(igraph_vector_int_resize(&warning_shown, eattr_no)); igraph_vector_int_null(&warning_shown); for (i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); - igraph_integer_t j; + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); + igraph_int_t j; CHECK(fprintf(outstream, " edge\n [\n")); /* source and target */ CHECK(fprintf(outstream, " source %" IGRAPH_PRId "\n", - myid ? (igraph_integer_t)VECTOR(*myid)[from] : from)); + myid ? (igraph_int_t)VECTOR(*myid)[from] : from)); CHECK(fprintf(outstream, " target %" IGRAPH_PRId "\n", - myid ? (igraph_integer_t)VECTOR(*myid)[to] : to)); + myid ? (igraph_int_t)VECTOR(*myid)[to] : to)); /* other attributes */ for (j = 0; j < eattr_no; j++) { diff --git a/src/vendor/cigraph/src/io/graphdb.c b/src/vendor/cigraph/src/io/graphdb.c index 5c67af7de0e..63d52a52d61 100644 --- a/src/vendor/cigraph/src/io/graphdb.c +++ b/src/vendor/cigraph/src/io/graphdb.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -109,7 +109,7 @@ static igraph_error_t handle_input_error(FILE *instream) { igraph_error_t igraph_read_graph_graphdb(igraph_t *graph, FILE *instream, igraph_bool_t directed) { - const igraph_integer_t nodes = igraph_i_read_graph_graphdb_getword(instream); + const igraph_int_t nodes = igraph_i_read_graph_graphdb_getword(instream); if (nodes < 0) { IGRAPH_CHECK(handle_input_error(instream)); } @@ -118,13 +118,13 @@ igraph_error_t igraph_read_graph_graphdb(igraph_t *graph, FILE *instream, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 100); igraph_vector_int_clear(&edges); - for (igraph_integer_t i = 0; i < nodes; i++) { - igraph_integer_t len = igraph_i_read_graph_graphdb_getword(instream); + for (igraph_int_t i = 0; i < nodes; i++) { + igraph_int_t len = igraph_i_read_graph_graphdb_getword(instream); if (len < 0) { IGRAPH_CHECK(handle_input_error(instream)); } - for (igraph_integer_t j = 0; j < len; j++) { - igraph_integer_t to = igraph_i_read_graph_graphdb_getword(instream); + for (igraph_int_t j = 0; j < len; j++) { + igraph_int_t to = igraph_i_read_graph_graphdb_getword(instream); if (to < 0) { IGRAPH_CHECK(handle_input_error(instream)); } diff --git a/src/vendor/cigraph/src/io/graphml.c b/src/vendor/cigraph/src/io/graphml.c index 1b42b626637..05630b267cf 100644 --- a/src/vendor/cigraph/src/io/graphml.c +++ b/src/vendor/cigraph/src/io/graphml.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -110,7 +110,7 @@ struct igraph_i_graphml_parser_state { igraph_vector_int_t edgelist; igraph_vector_int_t prev_state_stack; unsigned int unknown_depth; - igraph_integer_t index; + igraph_int_t index; igraph_bool_t successful; igraph_bool_t edges_directed; igraph_trie_t v_attr_ids; @@ -124,7 +124,7 @@ struct igraph_i_graphml_parser_state { igraph_attribute_elemtype_t data_type; char *error_message; igraph_vector_char_t data_char; - igraph_integer_t act_node; + igraph_int_t act_node; igraph_bool_t ignore_namespaces; }; @@ -158,7 +158,7 @@ static igraph_error_t igraph_i_graphml_parse_numeric( static igraph_error_t igraph_i_graphml_parse_boolean( const char* char_data, igraph_bool_t* result, igraph_bool_t default_value ) { - igraph_integer_t value; + igraph_int_t value; const char* trimmed; size_t trimmed_length; @@ -218,7 +218,7 @@ static void igraph_i_graphml_attribute_record_destroy(igraph_i_graphml_attribute 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) { +static igraph_error_t igraph_i_graphml_parser_state_init(struct igraph_i_graphml_parser_state* state, igraph_t* graph, igraph_int_t index) { memset(state, 0, sizeof(struct igraph_i_graphml_parser_state)); state->g = graph; @@ -387,7 +387,7 @@ 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; + igraph_int_t i; const char *idstr = "id"; igraph_bool_t already_has_vertex_id = false, already_has_edge_id = false; igraph_attribute_record_list_t vattr, eattr, gattr; @@ -559,8 +559,8 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( xmlChar *localname; igraph_trie_t *trie = NULL; igraph_vector_ptr_t *ptrvector = NULL; - igraph_integer_t i, n; - igraph_integer_t id; + igraph_int_t i, n; + igraph_int_t id; igraph_i_graphml_attribute_record_t *rec = NULL; char *attr_name; igraph_attribute_type_t igraph_attr_type; @@ -778,7 +778,8 @@ static igraph_error_t igraph_i_graphml_attribute_data_setup( static igraph_error_t igraph_i_graphml_append_to_data_char( struct igraph_i_graphml_parser_state *state, const xmlChar *data, int len ) { - igraph_vector_char_t data_vec; + const igraph_vector_char_t data_vec = + igraph_vector_char_view((char *) data, len); if (!state->successful) { return IGRAPH_SUCCESS; @@ -787,7 +788,7 @@ static igraph_error_t igraph_i_graphml_append_to_data_char( IGRAPH_STATIC_ASSERT(sizeof(char) == sizeof(xmlChar)); IGRAPH_CHECK(igraph_vector_char_append( &state->data_char, - igraph_vector_char_view(&data_vec, (char *) data, len) + &data_vec )); return IGRAPH_SUCCESS; @@ -800,7 +801,7 @@ static igraph_error_t igraph_i_graphml_attribute_data_finish(struct igraph_i_gra igraph_vector_ptr_t *ptrvector = NULL; igraph_i_graphml_attribute_record_t *graphmlrec; igraph_attribute_record_t *rec; - igraph_integer_t recid, id = 0; + igraph_int_t recid, id = 0; igraph_error_t result = IGRAPH_SUCCESS; switch (type) { @@ -945,7 +946,7 @@ static igraph_error_t igraph_i_graphml_sax_handler_start_element_ns_inner( int nb_attributes, int nb_defaulted, const xmlChar** attributes) { xmlChar** it; xmlChar* attr_value = 0; - igraph_integer_t id1, id2; + igraph_int_t id1, id2; int i; igraph_bool_t tag_is_unknown = false; @@ -1079,8 +1080,8 @@ static igraph_error_t igraph_i_graphml_sax_handler_start_element_ns_inner( xmlFree(attr_value); attr_value = NULL; IGRAPH_FINALLY_CLEAN(1); } else if (xmlStrEqual(*it, toXmlChar("id"))) { - igraph_integer_t edges = igraph_vector_int_size(&state->edgelist) / 2 + 1; - igraph_integer_t origsize = igraph_strvector_size(&state->edgeids); + igraph_int_t edges = igraph_vector_int_size(&state->edgelist) / 2 + 1; + igraph_int_t origsize = igraph_strvector_size(&state->edgeids); attr_value = xmlStrndup(XML_ATTR_VALUE(it)); if (attr_value == 0) { @@ -1368,7 +1369,7 @@ static xmlSAXHandler igraph_i_graphml_sax_handler = { * \return Error code. */ static igraph_error_t igraph_i_xml_escape(const char *src, char **dest, const char *what) { - igraph_integer_t destlen = 0; + igraph_int_t destlen = 0; const char *s; char *d; unsigned char ch; @@ -1467,7 +1468,7 @@ static void igraph_i_libxml_structured_error_handler(void* ctx, const xmlError * * * \example examples/simple/graphml.c */ -igraph_error_t igraph_read_graph_graphml(igraph_t *graph, FILE *instream, igraph_integer_t index) { +igraph_error_t igraph_read_graph_graphml(igraph_t *graph, FILE *instream, igraph_int_t index) { #if HAVE_LIBXML == 1 xmlParserCtxtPtr ctxt; @@ -1647,11 +1648,11 @@ igraph_error_t igraph_read_graph_graphml(igraph_t *graph, FILE *instream, igraph igraph_error_t igraph_write_graph_graphml(const igraph_t *graph, FILE *outstream, igraph_bool_t prefixattr) { int ret; - igraph_integer_t l, vc; + igraph_int_t l, vc; igraph_eit_t it; igraph_strvector_t gnames, vnames, enames; igraph_vector_int_t gtypes, vtypes, etypes; - igraph_integer_t i; + igraph_int_t i; igraph_vector_t numv; igraph_strvector_t strv; igraph_vector_bool_t boolv; @@ -1925,9 +1926,9 @@ igraph_error_t igraph_write_graph_graphml(const igraph_t *graph, FILE *outstream IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t from, to; + igraph_int_t from, to; const char *name; char *name_escaped; - igraph_integer_t edge = IGRAPH_EIT_GET(it); + igraph_int_t edge = IGRAPH_EIT_GET(it); igraph_edge(graph, edge, &from, &to); ret = fprintf(outstream, " \n", from, to); diff --git a/src/vendor/cigraph/src/io/leda.c b/src/vendor/cigraph/src/io/leda.c index 48a2f6c5535..465cf65a7b0 100644 --- a/src/vendor/cigraph/src/io/leda.c +++ b/src/vendor/cigraph/src/io/leda.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -64,13 +64,13 @@ igraph_error_t igraph_write_graph_leda(const igraph_t *graph, FILE *outstream, const char *vertex_attr_name, const char *edge_attr_name) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_eit_t it; - igraph_integer_t i = 0; + igraph_int_t i = 0; igraph_attribute_type_t vertex_attr_type = IGRAPH_ATTRIBUTE_UNSPECIFIED; igraph_attribute_type_t edge_attr_type = IGRAPH_ATTRIBUTE_UNSPECIFIED; - igraph_integer_t from, to, rev; + igraph_int_t from, to, rev; IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(IGRAPH_EDGEORDER_FROM), &it)); IGRAPH_FINALLY(igraph_eit_destroy, &it); @@ -220,7 +220,7 @@ igraph_error_t igraph_write_graph_leda(const igraph_t *graph, FILE *outstream, IGRAPH_CHECK(igraph_i_attribute_get_numeric_edge_attr( graph, edge_attr_name, igraph_ess_all(IGRAPH_EDGEORDER_ID), &values)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t eid = IGRAPH_EIT_GET(it); + igraph_int_t eid = IGRAPH_EIT_GET(it); igraph_edge(graph, eid, &from, &to); igraph_get_eid(graph, &rev, to, from, IGRAPH_DIRECTED, false); if (rev == IGRAPH_EIT_GET(it)) { @@ -243,7 +243,7 @@ igraph_error_t igraph_write_graph_leda(const igraph_t *graph, FILE *outstream, IGRAPH_CHECK(igraph_i_attribute_get_string_edge_attr( graph, edge_attr_name, igraph_ess_all(IGRAPH_EDGEORDER_ID), &values)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t eid = IGRAPH_EIT_GET(it); + igraph_int_t eid = IGRAPH_EIT_GET(it); const char *str = igraph_strvector_get(&values, eid); igraph_edge(graph, eid, &from, &to); igraph_get_eid(graph, &rev, to, from, IGRAPH_DIRECTED, false); @@ -270,7 +270,7 @@ igraph_error_t igraph_write_graph_leda(const igraph_t *graph, FILE *outstream, graph, vertex_attr_name, igraph_ess_all(IGRAPH_EDGEORDER_ID), &values)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t eid = IGRAPH_EIT_GET(it); + igraph_int_t eid = IGRAPH_EIT_GET(it); igraph_edge(graph, eid, &from, &to); igraph_get_eid(graph, &rev, to, from, IGRAPH_DIRECTED, false); if (rev == IGRAPH_EIT_GET(it)) { diff --git a/src/vendor/cigraph/src/io/lgl-header.h b/src/vendor/cigraph/src/io/lgl-header.h index f8579e4a7a0..b67e7725f60 100644 --- a/src/vendor/cigraph/src/io/lgl-header.h +++ b/src/vendor/cigraph/src/io/lgl-header.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge MA, 02139 USA @@ -33,5 +33,5 @@ typedef struct { igraph_vector_int_t *vector; igraph_vector_t *weights; igraph_trie_t *trie; - igraph_integer_t actvertex; + igraph_int_t actvertex; } igraph_i_lgl_parsedata_t; diff --git a/src/vendor/cigraph/src/io/lgl-lexer.l b/src/vendor/cigraph/src/io/lgl-lexer.l index 64802df0e93..8b9fd06b8ac 100644 --- a/src/vendor/cigraph/src/io/lgl-lexer.l +++ b/src/vendor/cigraph/src/io/lgl-lexer.l @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA diff --git a/src/vendor/cigraph/src/io/lgl-parser.y b/src/vendor/cigraph/src/io/lgl-parser.y index 5d439f3ff7e..2a6459ac802 100644 --- a/src/vendor/cigraph/src/io/lgl-parser.y +++ b/src/vendor/cigraph/src/io/lgl-parser.y @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -74,7 +74,7 @@ int igraph_lgl_yyerror(YYLTYPE* locp, igraph_i_lgl_parsedata_t *context, %lex-param { void *scanner } %union { - igraph_integer_t edgenum; + igraph_int_t edgenum; igraph_real_t weightnum; } @@ -115,7 +115,7 @@ edge : edgeid NEWLINE { edgeid : ALNUM { - igraph_integer_t trie_id; + igraph_int_t trie_id; IGRAPH_YY_CHECK(igraph_trie_get_len(context->trie, igraph_lgl_yyget_text(scanner), igraph_lgl_yyget_leng(scanner), diff --git a/src/vendor/cigraph/src/io/lgl.c b/src/vendor/cigraph/src/io/lgl.c index 1c1a00d07db..e6ad1e263af 100644 --- a/src/vendor/cigraph/src/io/lgl.c +++ b/src/vendor/cigraph/src/io/lgl.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -270,9 +270,9 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, const char *names, const char *weights, igraph_bool_t isolates) { igraph_eit_t it; - igraph_integer_t actvertex = -1; + igraph_int_t actvertex = -1; igraph_attribute_type_t nametype, weighttype; - const igraph_integer_t vcount = igraph_vcount(graph), ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph), ecount = igraph_ecount(graph); IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(IGRAPH_EDGEORDER_FROM), &it)); @@ -310,7 +310,7 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, if (names == NULL && weights == NULL) { /* No names, no weights */ while (!IGRAPH_EIT_END(it)) { - igraph_integer_t from, to; + igraph_int_t from, to; int ret; igraph_edge(graph, IGRAPH_EIT_GET(it), &from, &to); if (from == actvertex) { @@ -332,8 +332,8 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, igraph_vss_all(), &nvec)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t edge = IGRAPH_EIT_GET(it); - igraph_integer_t from, to; + igraph_int_t edge = IGRAPH_EIT_GET(it); + igraph_int_t from, to; int ret = 0; const char *str1, *str2; igraph_edge(graph, edge, &from, &to); @@ -363,8 +363,8 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, igraph_ess_all(IGRAPH_EDGEORDER_ID), &wvec)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t edge = IGRAPH_EIT_GET(it); - igraph_integer_t from, to; + igraph_int_t edge = IGRAPH_EIT_GET(it); + igraph_int_t from, to; int ret1, ret2, ret3; igraph_edge(graph, edge, &from, &to); if (from == actvertex) { @@ -395,8 +395,8 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, igraph_vss_all(), &nvec)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t edge = IGRAPH_EIT_GET(it); - igraph_integer_t from, to; + igraph_int_t edge = IGRAPH_EIT_GET(it); + igraph_int_t from, to; int ret = 0, ret2; const char *str1, *str2; igraph_edge(graph, edge, &from, &to); @@ -427,10 +427,10 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, } if (isolates) { - igraph_integer_t nov = vcount; - igraph_integer_t i; + igraph_int_t nov = vcount; + igraph_int_t i; int ret = 0; - igraph_integer_t deg; + igraph_int_t deg; igraph_strvector_t nvec; const char *str; diff --git a/src/vendor/cigraph/src/io/ncol-header.h b/src/vendor/cigraph/src/io/ncol-header.h index 655ef2e7277..230a995b5f8 100644 --- a/src/vendor/cigraph/src/io/ncol-header.h +++ b/src/vendor/cigraph/src/io/ncol-header.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge MA, 02139 USA diff --git a/src/vendor/cigraph/src/io/ncol-lexer.l b/src/vendor/cigraph/src/io/ncol-lexer.l index b668b48cc60..9851a7c8737 100644 --- a/src/vendor/cigraph/src/io/ncol-lexer.l +++ b/src/vendor/cigraph/src/io/ncol-lexer.l @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA diff --git a/src/vendor/cigraph/src/io/ncol-parser.y b/src/vendor/cigraph/src/io/ncol-parser.y index e5bff3be2ec..0af69d284b0 100644 --- a/src/vendor/cigraph/src/io/ncol-parser.y +++ b/src/vendor/cigraph/src/io/ncol-parser.y @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -75,7 +75,7 @@ int igraph_ncol_yyerror(YYLTYPE* locp, %lex-param { void *scanner } %union { - igraph_integer_t edgenum; + igraph_int_t edgenum; igraph_real_t weightnum; } @@ -109,7 +109,7 @@ endpoints : edgeid edgeid { }; edgeid : ALNUM { - igraph_integer_t trie_id; + igraph_int_t trie_id; IGRAPH_YY_CHECK(igraph_trie_get_len(context->trie, igraph_ncol_yyget_text(scanner), igraph_ncol_yyget_leng(scanner), diff --git a/src/vendor/cigraph/src/io/ncol.c b/src/vendor/cigraph/src/io/ncol.c index be600851c57..0804f92ec48 100644 --- a/src/vendor/cigraph/src/io/ncol.c +++ b/src/vendor/cigraph/src/io/ncol.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -112,8 +112,8 @@ igraph_error_t igraph_read_graph_ncol(igraph_t *graph, FILE *instream, igraph_vector_int_t edges; igraph_vector_t ws; igraph_trie_t trie = IGRAPH_TRIE_NULL; - igraph_integer_t no_of_nodes; - igraph_integer_t no_predefined = 0; + igraph_int_t no_of_nodes; + igraph_int_t no_predefined = 0; igraph_attribute_record_list_t name, weight; igraph_attribute_record_list_t *pname = NULL, *pweight = NULL; igraph_attribute_record_t *namerec, *weightrec; @@ -127,7 +127,7 @@ igraph_error_t igraph_read_graph_ncol(igraph_t *graph, FILE *instream, /* Add the predefined names, if any */ if (predefnames != 0) { - igraph_integer_t i, id, n; + igraph_int_t i, id, n; const char *key; n = no_predefined = igraph_strvector_size(predefnames); for (i = 0; i < n; i++) { @@ -340,7 +340,7 @@ igraph_error_t igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream, if (names == NULL && weights == NULL) { /* No names, no weights */ while (!IGRAPH_EIT_END(it)) { - igraph_integer_t from, to; + igraph_int_t from, to; int ret; igraph_edge(graph, IGRAPH_EIT_GET(it), &from, &to); ret = fprintf(outstream, "%" IGRAPH_PRId " %" IGRAPH_PRId "\n", from, to); @@ -358,8 +358,8 @@ igraph_error_t igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream, igraph_vss_all(), &nvec)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t edge = IGRAPH_EIT_GET(it); - igraph_integer_t from, to; + igraph_int_t edge = IGRAPH_EIT_GET(it); + igraph_int_t from, to; int ret = 0; const char *str1, *str2; igraph_edge(graph, edge, &from, &to); @@ -383,8 +383,8 @@ igraph_error_t igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream, igraph_ess_all(IGRAPH_EDGEORDER_ID), &wvec)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t edge = IGRAPH_EIT_GET(it); - igraph_integer_t from, to; + igraph_int_t edge = IGRAPH_EIT_GET(it); + igraph_int_t from, to; int ret1, ret2, ret3; igraph_edge(graph, edge, &from, &to); ret1 = fprintf(outstream, "%" IGRAPH_PRId " %" IGRAPH_PRId " ", from, to); @@ -411,8 +411,8 @@ igraph_error_t igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream, igraph_vss_all(), &nvec)); while (!IGRAPH_EIT_END(it)) { - igraph_integer_t edge = IGRAPH_EIT_GET(it); - igraph_integer_t from, to; + igraph_int_t edge = IGRAPH_EIT_GET(it); + igraph_int_t from, to; int ret = 0, ret2 = 0; const char *str1, *str2; igraph_edge(graph, edge, &from, &to); diff --git a/src/vendor/cigraph/src/io/pajek-header.h b/src/vendor/cigraph/src/io/pajek-header.h index 0dc37976d6e..d6d16dd0615 100644 --- a/src/vendor/cigraph/src/io/pajek-header.h +++ b/src/vendor/cigraph/src/io/pajek-header.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2012 Gabor Csardi 334 Harvard street, Cambridge MA, 02139 USA @@ -51,14 +51,14 @@ typedef struct { igraph_vector_int_t *vector; igraph_bitset_t *seen; igraph_bool_t directed; - igraph_integer_t vcount, vcount2; - igraph_integer_t actfrom; - igraph_integer_t actto; + igraph_int_t vcount, vcount2; + igraph_int_t actfrom; + igraph_int_t actto; igraph_trie_t *vertex_attribute_names; igraph_attribute_record_list_t *vertex_attributes; igraph_trie_t *edge_attribute_names; igraph_attribute_record_list_t *edge_attributes; - igraph_integer_t vertexid; - igraph_integer_t actvertex; - igraph_integer_t actedge; + igraph_int_t vertexid; + igraph_int_t actvertex; + igraph_int_t actedge; } igraph_i_pajek_parsedata_t; diff --git a/src/vendor/cigraph/src/io/pajek-lexer.l b/src/vendor/cigraph/src/io/pajek-lexer.l index fdb4ac82a2a..8453bef4f01 100644 --- a/src/vendor/cigraph/src/io/pajek-lexer.l +++ b/src/vendor/cigraph/src/io/pajek-lexer.l @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA diff --git a/src/vendor/cigraph/src/io/pajek-parser.y b/src/vendor/cigraph/src/io/pajek-parser.y index 4933acd1f56..b253aee8e8a 100644 --- a/src/vendor/cigraph/src/io/pajek-parser.y +++ b/src/vendor/cigraph/src/io/pajek-parser.y @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -23,7 +23,7 @@ %{ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard st, Cambridge, MA, 02138 USA @@ -79,19 +79,19 @@ static igraph_error_t add_numeric_edge_attribute(const char *name, igraph_i_pajek_parsedata_t *context); static igraph_error_t add_numeric_attribute(igraph_trie_t *names, igraph_attribute_record_list_t *attrs, - igraph_integer_t count, + igraph_int_t count, const char *attrname, igraph_real_t default_value, - igraph_integer_t vid, + igraph_int_t vid, igraph_real_t number); static igraph_error_t add_string_attribute(igraph_trie_t *names, igraph_attribute_record_list_t *attrs, - igraph_integer_t count, + igraph_int_t count, const char *attrname, const char *default_value, - igraph_integer_t vid, + igraph_int_t vid, const char *str, - igraph_integer_t str_len); + igraph_int_t str_len); static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context); static igraph_error_t check_bipartite(igraph_i_pajek_parsedata_t *context); @@ -120,7 +120,7 @@ static const char* get_default_value_for_string_eattr(const char *attrname); %lex-param { void *scanner } %union { - igraph_integer_t intnum; + igraph_int_t intnum; igraph_real_t realnum; struct { char *str; @@ -242,7 +242,7 @@ vertdefs: /* empty */ | vertdefs vertexline; vertexline: vertex NEWLINE | vertex { context->actvertex=$1; } vertexid vertexcoords shape vertparams NEWLINE { - igraph_integer_t v = $1-1; /* zero-based vertex ID */ + igraph_int_t v = $1-1; /* zero-based vertex ID */ if (IGRAPH_BIT_TEST(*context->seen, v)) { IGRAPH_WARNINGF("Vertex ID %" IGRAPH_PRId " appears twice in Pajek file. Duplicate attributes will be overwritten.", v+1); } else { @@ -252,7 +252,7 @@ vertexline: vertex NEWLINE | ; vertex: integer { - igraph_integer_t v = $1; + igraph_int_t v = $1; /* Per feedback from Pajek's authors, negative signs should be ignored for vertex IDs. * See https://nascol.discourse.group/t/pajek-arcslist-edgelist-format/44/2 * This applies to all of *Edges, *Arcs, *Edgeslist, *Arcslist and *Vertices section. @@ -528,7 +528,7 @@ adjmatrixentry: number { /* -----------------------------------------------------*/ integer: NUM { - igraph_integer_t val; + igraph_int_t val; IGRAPH_YY_CHECK(igraph_i_parse_integer(igraph_pajek_yyget_text(scanner), igraph_pajek_yyget_leng(scanner), &val)); @@ -571,13 +571,13 @@ int igraph_pajek_yyerror(YYLTYPE* locp, static igraph_error_t add_numeric_attribute(igraph_trie_t *names, igraph_attribute_record_list_t *attrs, - igraph_integer_t count, + igraph_int_t count, const char *attrname, igraph_real_t default_value, - igraph_integer_t elem_id, + igraph_int_t elem_id, igraph_real_t number) { - igraph_integer_t attrsize = igraph_trie_size(names); - igraph_integer_t id; + igraph_int_t attrsize = igraph_trie_size(names); + igraph_int_t id; igraph_vector_t *na; igraph_attribute_record_t *prec; @@ -618,14 +618,14 @@ static igraph_error_t make_dynstr(const char *src, size_t len, char **res) { static igraph_error_t add_string_attribute(igraph_trie_t *names, igraph_attribute_record_list_t *attrs, - igraph_integer_t count, + igraph_int_t count, const char *attrname, const char *default_value, - igraph_integer_t elem_id, + igraph_int_t elem_id, const char *str, - igraph_integer_t str_len) { - igraph_integer_t attrsize=igraph_trie_size(names); - igraph_integer_t id; + igraph_int_t str_len) { + igraph_int_t attrsize=igraph_trie_size(names); + igraph_int_t id; igraph_strvector_t *na; igraph_attribute_record_t *prec; @@ -726,8 +726,8 @@ 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_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_int_t n=context->vcount, n1=context->vcount2; + igraph_int_t attrid, attrsize = igraph_trie_size(names); igraph_attribute_record_t* rec; igraph_vector_bool_t *na; @@ -749,7 +749,7 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) { IGRAPH_CHECK(igraph_attribute_record_resize(rec, n)); na = rec->value.as_vector_bool; - for (igraph_integer_t i = n1; i < n; i++) { + for (igraph_int_t i = n1; i < n; i++) { VECTOR(*na)[i] = true; } @@ -758,12 +758,12 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) { static igraph_error_t check_bipartite(igraph_i_pajek_parsedata_t *context) { const igraph_vector_int_t *edges=context->vector; - igraph_integer_t n1=context->vcount2; - igraph_integer_t ne=igraph_vector_int_size(edges); + igraph_int_t n1=context->vcount2; + igraph_int_t ne=igraph_vector_int_size(edges); - for (igraph_integer_t i=0; i n1 && v2 > n1) ) { IGRAPH_WARNING("Invalid edge in bipartite graph."); } diff --git a/src/vendor/cigraph/src/io/pajek.c b/src/vendor/cigraph/src/io/pajek.c index be554f95337..0b59398d79f 100644 --- a/src/vendor/cigraph/src/io/pajek.c +++ b/src/vendor/cigraph/src/io/pajek.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -147,7 +147,7 @@ igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream) { igraph_attribute_record_list_t vattrs; igraph_trie_t eattrnames; igraph_attribute_record_list_t eattrs; - igraph_integer_t i; + igraph_int_t i; igraph_i_pajek_parsedata_t context; igraph_bitset_t seen; /* used to mark already seen vertex IDs */ @@ -215,7 +215,7 @@ igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream) { IGRAPH_FINALLY_CLEAN(2); /* Prepare attributes */ - const igraph_integer_t eattr_count = igraph_attribute_record_list_size(&eattrs); + const igraph_int_t eattr_count = igraph_attribute_record_list_size(&eattrs); for (i = 0; i < eattr_count; i++) { igraph_attribute_record_t *rec = igraph_attribute_record_list_get_ptr(&eattrs, i); IGRAPH_CHECK(igraph_attribute_record_resize(rec, context.actedge)); @@ -268,7 +268,7 @@ igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream) { /* Pajek encodes newlines as \n, and any unicode character can be encoded * in the form &#hhhh;. Therefore we encode quotation marks as " */ static igraph_error_t pajek_escape(const char* src, char** dest) { - igraph_integer_t destlen = 0; + igraph_int_t destlen = 0; igraph_bool_t need_escape = false; /* Determine whether the string contains characters to be escaped */ @@ -395,7 +395,7 @@ static igraph_error_t pajek_escape(const char* src, char** dest) { */ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_attribute_type_t vtypes[V_LAST], etypes[E_LAST]; igraph_bool_t write_vertex_attrs = false; @@ -470,7 +470,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) igraph_bool_t bipartite = false; igraph_vector_int_t bip_index, bip_index2; igraph_vector_bool_t bvec; - igraph_integer_t notop = 0, nobottom = 0; + igraph_int_t notop = 0, nobottom = 0; IGRAPH_VECTOR_INIT_FINALLY(&numv, 1); IGRAPH_STRVECTOR_INIT_FINALLY(&strv, 1); @@ -491,7 +491,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) IGRAPH_VECTOR_INT_INIT_FINALLY(&bip_index, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&bip_index2, no_of_nodes); IGRAPH_VECTOR_BOOL_INIT_FINALLY(&bvec, 1); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_i_attribute_get_bool_vertex_attr(graph, "type", igraph_vss_1(i), &bvec)); if (VECTOR(bvec)[0]) { @@ -500,7 +500,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) nobottom++; } } - for (igraph_integer_t i = 0, bptr = 0, tptr = nobottom; i < no_of_nodes; i++) { + for (igraph_int_t i = 0, bptr = 0, tptr = nobottom; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_i_attribute_get_bool_vertex_attr(graph, "type", igraph_vss_1(i), &bvec)); if (VECTOR(bvec)[0]) { @@ -532,7 +532,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) /* Check the vertex attributes, and determine if we need to write them. */ memset(vtypes, 0, sizeof(vtypes[0])*V_LAST); - for (igraph_integer_t i = 0; i < V_LAST; i++) { + for (igraph_int_t i = 0; i < V_LAST; i++) { if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_VERTEX, vnames[i])) { IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &vtypes[i], IGRAPH_ATTRIBUTE_VERTEX, vnames[i])); @@ -541,7 +541,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) vtypes[i] = (igraph_attribute_type_t) -1; } } - for (igraph_integer_t i = 0; i < (igraph_integer_t) (sizeof(vnumnames) / sizeof(vnumnames[0])); i++) { + for (igraph_int_t i = 0; i < (igraph_int_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_get_type( @@ -551,7 +551,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++) { + for (igraph_int_t i = 0; i < (igraph_int_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_get_type( @@ -564,8 +564,8 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) /* Write vertices */ if (write_vertex_attrs) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t id = bipartite ? VECTOR(bip_index)[i] : i; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t id = bipartite ? VECTOR(bip_index)[i] : i; /* vertex ID */ fprintf(outstream, "%" IGRAPH_PRId, i + 1); @@ -616,8 +616,8 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) } /* numeric parameters */ - for (igraph_integer_t j = 0; j < igraph_vector_int_size(&vx_numa); j++) { - igraph_integer_t idx = VECTOR(vx_numa)[j]; + for (igraph_int_t j = 0; j < igraph_vector_int_size(&vx_numa); j++) { + igraph_int_t idx = VECTOR(vx_numa)[j]; IGRAPH_CHECK(igraph_i_attribute_get_numeric_vertex_attr( graph, vnumnames[idx], igraph_vss_1(id), &numv)); fprintf(outstream, " %s ", vnumnames2[idx]); @@ -625,8 +625,8 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) } /* string parameters */ - for (igraph_integer_t j = 0; j < igraph_vector_int_size(&vx_stra); j++) { - igraph_integer_t idx = VECTOR(vx_stra)[j]; + for (igraph_int_t j = 0; j < igraph_vector_int_size(&vx_stra); j++) { + igraph_int_t idx = VECTOR(vx_stra)[j]; IGRAPH_CHECK(igraph_i_attribute_get_string_vertex_attr( graph, vstrnames[idx], igraph_vss_1(id), &strv)); s = igraph_strvector_get(&strv, 0); @@ -654,7 +654,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) /* Check edge attributes */ /* TODO: refactor and simplify since only "weight" is relevant */ - for (igraph_integer_t i = 0; i < E_LAST; i++) { + for (igraph_int_t i = 0; i < E_LAST; i++) { if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_EDGE, enames[i])) { IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &etypes[i], IGRAPH_ATTRIBUTE_EDGE, enames[i])); @@ -662,7 +662,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) etypes[i] = (igraph_attribute_type_t) -1; } } - for (igraph_integer_t i = 0; i < (igraph_integer_t) (sizeof(enumnames) / sizeof(enumnames[0])); i++) { + for (igraph_int_t i = 0; i < (igraph_int_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_get_type( @@ -672,7 +672,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++) { + for (igraph_int_t i = 0; i < (igraph_int_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_get_type( @@ -683,9 +683,9 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) } } - for (igraph_integer_t i = 0; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit), i++) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); - igraph_integer_t from, to; + for (igraph_int_t i = 0; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit), i++) { + igraph_int_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t from, to; igraph_edge(graph, edge, &from, &to); if (bipartite) { from = VECTOR(bip_index2)[from]; @@ -702,8 +702,8 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) } /* numeric parameters */ - for (igraph_integer_t j = 0; j < igraph_vector_int_size(&ex_numa); j++) { - igraph_integer_t idx = VECTOR(ex_numa)[j]; + for (igraph_int_t j = 0; j < igraph_vector_int_size(&ex_numa); j++) { + igraph_int_t idx = VECTOR(ex_numa)[j]; IGRAPH_CHECK(igraph_i_attribute_get_numeric_edge_attr( graph, enumnames[idx], igraph_ess_1(edge), &numv)); fprintf(outstream, " %s ", enumnames2[idx]); @@ -711,8 +711,8 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) } /* string parameters */ - for (igraph_integer_t j = 0; j < igraph_vector_int_size(&ex_stra); j++) { - igraph_integer_t idx = VECTOR(ex_stra)[j]; + for (igraph_int_t j = 0; j < igraph_vector_int_size(&ex_stra); j++) { + igraph_int_t idx = VECTOR(ex_stra)[j]; IGRAPH_CHECK(igraph_i_attribute_get_string_edge_attr( graph, estrnames[idx], igraph_ess_1(edge), &strv)); s = igraph_strvector_get(&strv, 0); diff --git a/src/vendor/cigraph/src/io/parse_utils.c b/src/vendor/cigraph/src/io/parse_utils.c index 9bd24c0a79a..6be36aaab9a 100644 --- a/src/vendor/cigraph/src/io/parse_utils.c +++ b/src/vendor/cigraph/src/io/parse_utils.c @@ -49,7 +49,7 @@ void igraph_i_trim_whitespace(const char *str, size_t str_len, const char **res, * * An error is returned if the input is an empty string. */ -igraph_error_t igraph_i_parse_integer(const char *str, size_t length, igraph_integer_t *value) { +igraph_error_t igraph_i_parse_integer(const char *str, size_t length, igraph_int_t *value) { char buffer[128]; char *tmp, *end; char last_char; @@ -73,12 +73,12 @@ igraph_error_t igraph_i_parse_integer(const char *str, size_t length, igraph_int tmp[length]='\0'; /* To avoid having to choose the appropriate strto?() function based on - * the definition of igraph_integer_t, we first use a long long variable - * which should be at least as large as igraph_integer_t on any platform. */ + * the definition of igraph_int_t, we first use a long long variable + * which should be at least as large as igraph_int_t on any platform. */ errno = 0; val = strtoll(tmp, &end, 10); out_of_range = errno == ERANGE; - *value = (igraph_integer_t) val; + *value = (igraph_int_t) val; last_char = *end; if (*value != val) { out_of_range = true; @@ -178,7 +178,7 @@ igraph_error_t igraph_i_fskip_whitespace(FILE *file) { * This function assumes that the number is followed by whitespace or the end of the file. * If this is not the case, an error will be raised. */ -igraph_error_t igraph_i_fget_integer(FILE *file, igraph_integer_t *value) { +igraph_error_t igraph_i_fget_integer(FILE *file, igraph_int_t *value) { /* The value requiring the most characters on 64-bit is -2^63, i.e. "-9223372036854775808". * This is 20 characters long, plus one for the null terminator, requiring a buffer of * at least 21 characters. We use a slightly larger buffer to allow for leading zeros and diff --git a/src/vendor/cigraph/src/io/parse_utils.h b/src/vendor/cigraph/src/io/parse_utils.h index 49a23d03a2a..b94a3b13d63 100644 --- a/src/vendor/cigraph/src/io/parse_utils.h +++ b/src/vendor/cigraph/src/io/parse_utils.h @@ -32,10 +32,10 @@ void igraph_i_trim_whitespace(const char *str, size_t str_len, const char **res, igraph_error_t igraph_i_fskip_whitespace(FILE *file); -igraph_error_t igraph_i_parse_integer(const char *str, size_t length, igraph_integer_t *value); +igraph_error_t igraph_i_parse_integer(const char *str, size_t length, igraph_int_t *value); igraph_error_t igraph_i_parse_real(const char *str, size_t length, igraph_real_t *value); -igraph_error_t igraph_i_fget_integer(FILE *file, igraph_integer_t *value); +igraph_error_t igraph_i_fget_integer(FILE *file, igraph_int_t *value); igraph_error_t igraph_i_fget_real(FILE *file, igraph_real_t *value); #endif /* IGRAPH_PARSE_UTILS_H */ diff --git a/src/vendor/cigraph/src/isomorphism/bliss.cc b/src/vendor/cigraph/src/isomorphism/bliss.cc index 541a5b17947..d4c66f56dcf 100644 --- a/src/vendor/cigraph/src/isomorphism/bliss.cc +++ b/src/vendor/cigraph/src/isomorphism/bliss.cc @@ -77,8 +77,8 @@ using namespace std; namespace { // unnamed namespace inline AbstractGraph *bliss_from_igraph(const igraph_t *graph) { - igraph_integer_t nof_vertices = igraph_vcount(graph); - igraph_integer_t nof_edges = igraph_ecount(graph); + igraph_int_t nof_vertices = igraph_vcount(graph); + igraph_int_t nof_edges = igraph_ecount(graph); if (nof_vertices > UINT_MAX || nof_edges > UINT_MAX) { throw std::runtime_error("Graph too large for BLISS"); @@ -149,7 +149,7 @@ inline igraph_error_t bliss_set_colors(AbstractGraph *g, const igraph_vector_int IGRAPH_ERROR("Invalid vertex color vector length.", IGRAPH_EINVAL); } for (int i = 0; i < n; ++i) { - igraph_integer_t color = VECTOR(*colors)[i]; + igraph_int_t color = VECTOR(*colors)[i]; if (color < INT_MIN || color > INT_MAX) { IGRAPH_ERRORF("Invalid vertex color index %" IGRAPH_PRId " for vertex %d.", IGRAPH_EOVERFLOW, color, i); } @@ -218,7 +218,7 @@ class AutCollector { throw bad_alloc(); } - copy(aut, aut + n, VECTOR(newvector)); // takes care of unsigned int -> igraph_integer_t conversion + copy(aut, aut + n, VECTOR(newvector)); // takes care of unsigned int -> igraph_int_t conversion err = igraph_vector_int_list_push_back(generators, &newvector); if (err != IGRAPH_SUCCESS) { @@ -537,7 +537,7 @@ igraph_error_t igraph_automorphism_group_bliss( /* The following license notice applies to the rest of this file */ /* - IGraph library. + igraph library. Copyright (C) 2006-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -603,14 +603,14 @@ igraph_error_t igraph_isomorphic_bliss(const igraph_t *graph1, const igraph_t *g igraph_vector_int_t *map21, igraph_bliss_sh_t sh, igraph_bliss_info_t *info1, igraph_bliss_info_t *info2) { - igraph_integer_t no_of_nodes = igraph_vcount(graph1); - igraph_integer_t no_of_edges = igraph_ecount(graph1); + igraph_int_t no_of_nodes = igraph_vcount(graph1); + igraph_int_t no_of_edges = igraph_ecount(graph1); igraph_vector_int_t perm1, perm2; igraph_vector_int_t vmap12, *mymap12 = &vmap12; igraph_vector_int_t from, to, index; igraph_vector_int_t from2, to2, index2; igraph_bool_t directed; - igraph_integer_t i, j; + igraph_int_t i, j; *iso = 0; if (info1) { @@ -688,7 +688,7 @@ igraph_error_t igraph_isomorphic_bliss(const igraph_t *graph1, const igraph_t *g VECTOR(from)[i] = VECTOR(*mymap12)[ IGRAPH_FROM(graph1, i) ]; VECTOR(to)[i] = VECTOR(*mymap12)[ IGRAPH_TO (graph1, i) ]; if (! directed && VECTOR(from)[i] < VECTOR(to)[i]) { - igraph_integer_t tmp = VECTOR(from)[i]; + igraph_int_t tmp = VECTOR(from)[i]; VECTOR(from)[i] = VECTOR(to)[i]; VECTOR(to)[i] = tmp; } @@ -699,7 +699,7 @@ igraph_error_t igraph_isomorphic_bliss(const igraph_t *graph1, const igraph_t *g for (i = 0, j = no_of_edges; i < no_of_edges; i++, j++) { VECTOR(to2)[i] = VECTOR(from2)[j]; if (! directed && VECTOR(from2)[i] < VECTOR(to2)[i]) { - igraph_integer_t tmp = VECTOR(from2)[i]; + igraph_int_t tmp = VECTOR(from2)[i]; VECTOR(from2)[i] = VECTOR(to2)[i]; VECTOR(to2)[i] = tmp; } @@ -709,8 +709,8 @@ igraph_error_t igraph_isomorphic_bliss(const igraph_t *graph1, const igraph_t *g *iso = 1; for (i = 0; i < no_of_edges; i++) { - igraph_integer_t i1 = VECTOR(index)[i]; - igraph_integer_t i2 = VECTOR(index2)[i]; + igraph_int_t i1 = VECTOR(index)[i]; + igraph_int_t i2 = VECTOR(index2)[i]; if (VECTOR(from)[i1] != VECTOR(from2)[i2] || VECTOR(to)[i1] != VECTOR(to2)[i2]) { *iso = 0; diff --git a/src/vendor/cigraph/src/isomorphism/isoclasses.c b/src/vendor/cigraph/src/isomorphism/isoclasses.c index e75a418f2f9..a3259539b5f 100644 --- a/src/vendor/cigraph/src/isomorphism/isoclasses.c +++ b/src/vendor/cigraph/src/isomorphism/isoclasses.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -2547,10 +2547,10 @@ const unsigned int igraph_i_classedges_6u[] = { 4, 5, 3, 5, 2, 5, 1, 5, 0, 5, 3, * * Time complexity: O(|E|), the number of edges in the graph. */ -igraph_error_t igraph_isoclass(const igraph_t *graph, igraph_integer_t *isoclass) { - igraph_integer_t e; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); +igraph_error_t igraph_isoclass(const igraph_t *graph, igraph_int_t *isoclass) { + igraph_int_t e; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); unsigned int idx, mul; const unsigned int *arr_idx, *arr_code; unsigned int code; @@ -2605,7 +2605,7 @@ igraph_error_t igraph_isoclass(const igraph_t *graph, igraph_integer_t *isoclass code |= arr_idx[idx]; } - *isoclass = (igraph_integer_t) arr_code[code]; + *isoclass = (igraph_int_t) arr_code[code]; return IGRAPH_SUCCESS; } @@ -2625,8 +2625,7 @@ igraph_error_t igraph_isoclass(const igraph_t *graph, igraph_integer_t *isoclass * Multi-edges and self-loops are ignored by this function. * * \param graph The graph object. - * \param vids A vector containing the vertex IDs to be considered as - * a subgraph. Each vertex ID should be included at most once. + * \param vids The vertices of the subgraph. Each vertex must be included at most once. * \param isoclass Pointer to an integer, this will be set to the * isomorphism class. * \return Error code. @@ -2636,16 +2635,18 @@ igraph_error_t igraph_isoclass(const igraph_t *graph, igraph_integer_t *isoclass * Time complexity: O((d+n)*n), d is the average degree in the network, * and n is the number of vertices in \c vids. */ -igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, const igraph_vector_int_t *vids, - igraph_integer_t *isoclass) { - igraph_integer_t subgraph_size = igraph_vector_int_size(vids); - igraph_vector_int_t neis; +igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, igraph_vs_t vids, + igraph_int_t *isoclass) { + igraph_int_t subgraph_size; + igraph_vector_int_t vertices, neis; unsigned int mul, idx; const unsigned int *arr_idx, *arr_code; unsigned int code = 0; - igraph_integer_t i, j, s; + IGRAPH_VECTOR_INT_INIT_FINALLY(&vertices, 0); + IGRAPH_CHECK(igraph_vs_as_vector(graph, vids, &vertices)); + subgraph_size = igraph_vector_int_size(&vertices); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); @@ -2693,15 +2694,15 @@ igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, const igraph_vect } } - for (i = 0; i < subgraph_size; i++) { - igraph_integer_t from = VECTOR(*vids)[i]; + for (igraph_int_t i = 0; i < subgraph_size; i++) { + igraph_int_t from = VECTOR(vertices)[i]; IGRAPH_CHECK(igraph_neighbors( graph, &neis, from, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); - s = igraph_vector_int_size(&neis); - for (j = 0; j < s; j++) { - igraph_integer_t nei = VECTOR(neis)[j], to; - if (igraph_vector_int_search(vids, 0, nei, &to)) { + const igraph_int_t s = igraph_vector_int_size(&neis); + for (igraph_int_t j = 0; j < s; j++) { + igraph_int_t nei = VECTOR(neis)[j], to; + if (igraph_vector_int_search(&vertices, 0, nei, &to)) { idx = (mul * i + to); code |= arr_idx[idx]; } @@ -2710,7 +2711,8 @@ igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, const igraph_vect *isoclass = arr_code[code]; igraph_vector_int_destroy(&neis); - IGRAPH_FINALLY_CLEAN(1); + igraph_vector_int_destroy(&vertices); + IGRAPH_FINALLY_CLEAN(2); return IGRAPH_SUCCESS; } @@ -2747,12 +2749,12 @@ igraph_error_t igraph_isoclass_subgraph(const igraph_t *graph, const igraph_vect * Time complexity: O(|V|+|E|), the number of vertices plus the number * of edges in the graph to create. */ -igraph_error_t igraph_isoclass_create(igraph_t *graph, igraph_integer_t size, - igraph_integer_t number, igraph_bool_t directed) { +igraph_error_t igraph_isoclass_create(igraph_t *graph, igraph_int_t size, + igraph_int_t number, igraph_bool_t directed) { igraph_vector_int_t edges; const unsigned int *classedges; - igraph_integer_t graphcount; - igraph_integer_t pos; + igraph_int_t graphcount; + igraph_int_t pos; unsigned int power; unsigned int code; @@ -2878,7 +2880,7 @@ igraph_error_t igraph_isoclass_create(igraph_t *graph, igraph_integer_t size, } /* https://oeis.org/A000088 */ -static igraph_integer_t undirected_graph_counts[] = { +static igraph_int_t undirected_graph_counts[] = { 1, 1, 2, 4, 11, 34, 156, 1044, 12346, 274668, 12005168, 1018997864, #if IGRAPH_INTEGER_SIZE == 64 165091172592, 50502031367952, 29054155657235488 @@ -2886,7 +2888,7 @@ static igraph_integer_t undirected_graph_counts[] = { }; /* https://oeis.org/A000273 */ -static igraph_integer_t directed_graph_counts[] = { +static igraph_int_t directed_graph_counts[] = { 1, 1, 3, 16, 218, 9608, 1540944, 882033440, #if IGRAPH_INTEGER_SIZE == 64 1793359192848, 13027956824399552 @@ -2903,7 +2905,7 @@ static igraph_integer_t directed_graph_counts[] = { * * This function is meant to be used in conjunction with isoclass and motif finder * functions. It will only work for small \p n values for which the result is - * represetable in an \type igraph_integer_t. For larger \p n values, an overflow + * represetable in an \type igraph_int_t. For larger \p n values, an overflow * error is raised. * * \param n The number of vertices. @@ -2915,17 +2917,17 @@ static igraph_integer_t directed_graph_counts[] = { * * Time complexity: O(1). */ -igraph_error_t igraph_graph_count(igraph_integer_t n, igraph_bool_t directed, igraph_integer_t *count) { +igraph_error_t igraph_graph_count(igraph_int_t n, igraph_bool_t directed, igraph_int_t *count) { if (n < 0) { IGRAPH_ERROR("Graph size must not be negative.", IGRAPH_EINVAL); } if (directed) { - if (n >= (igraph_integer_t) (sizeof directed_graph_counts / sizeof directed_graph_counts[0])) { + if (n >= (igraph_int_t) (sizeof directed_graph_counts / sizeof directed_graph_counts[0])) { IGRAPH_ERRORF("Graph size of % " IGRAPH_PRId " too large.", IGRAPH_EOVERFLOW, n); } *count = directed_graph_counts[n]; } else { - if (n >= (igraph_integer_t) (sizeof undirected_graph_counts / sizeof undirected_graph_counts[0])) { + if (n >= (igraph_int_t) (sizeof undirected_graph_counts / sizeof undirected_graph_counts[0])) { IGRAPH_ERRORF("Graph size of % " IGRAPH_PRId " too large.", IGRAPH_EOVERFLOW, n); } *count = undirected_graph_counts[n]; diff --git a/src/vendor/cigraph/src/isomorphism/isoclasses.h b/src/vendor/cigraph/src/isomorphism/isoclasses.h index 40c38d3b0a8..9d543b6d1a7 100644 --- a/src/vendor/cigraph/src/isomorphism/isoclasses.h +++ b/src/vendor/cigraph/src/isomorphism/isoclasses.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2008-2020 The igraph development team 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c b/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c index c0e5e3007c9..7133e81a9c0 100644 --- a/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c +++ b/src/vendor/cigraph/src/isomorphism/isomorphism_misc.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -57,10 +57,10 @@ igraph_error_t igraph_simplify_and_colorize( igraph_es_t es; igraph_eit_t eit; igraph_vector_int_t edges; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t pto = -1, pfrom = -1; - igraph_integer_t i; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t pto = -1, pfrom = -1; + igraph_int_t i; IGRAPH_CHECK(igraph_es_all(&es, IGRAPH_EDGEORDER_FROM)); IGRAPH_FINALLY(igraph_es_destroy, &es); @@ -78,9 +78,9 @@ igraph_error_t igraph_simplify_and_colorize( i = -1; for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); + igraph_int_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t from = IGRAPH_FROM(graph, edge); + igraph_int_t to = IGRAPH_TO(graph, edge); if (to == from) { VECTOR(*vertex_color)[to]++; diff --git a/src/vendor/cigraph/src/isomorphism/lad.c b/src/vendor/cigraph/src/isomorphism/lad.c index 2ab5c09cce0..3c2cc4009a2 100644 --- a/src/vendor/cigraph/src/isomorphism/lad.c +++ b/src/vendor/cigraph/src/isomorphism/lad.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -89,15 +89,15 @@ #define SETEDGE(G, i, j) IGRAPH_BIT_SET(G->isEdge, i * G->nbVertices + j) typedef struct { - igraph_integer_t nbVertices; /* Number of vertices */ + igraph_int_t nbVertices; /* Number of vertices */ igraph_vector_int_t nbSucc; igraph_adjlist_t succ; igraph_bitset_t isEdge; } Tgraph; static igraph_error_t igraph_i_lad_createGraph(const igraph_t *igraph, Tgraph* graph) { - igraph_integer_t i, j, n; - igraph_integer_t no_of_nodes = igraph_vcount(igraph); + igraph_int_t i, j, n; + igraph_int_t no_of_nodes = igraph_vcount(igraph); igraph_vector_int_t *neis; graph->nbVertices = no_of_nodes; @@ -116,7 +116,7 @@ static igraph_error_t igraph_i_lad_createGraph(const igraph_t *igraph, Tgraph* g neis = igraph_adjlist_get(&graph->succ, i); n = igraph_vector_int_size(neis); for (j = 0; j < n; j++) { - igraph_integer_t v = VECTOR(*neis)[j]; + igraph_int_t v = VECTOR(*neis)[j]; if (ISEDGE(graph, i, v)) { IGRAPH_ERROR("LAD functions do not support graphs with multi-edges.", IGRAPH_EINVAL); } @@ -150,17 +150,17 @@ typedef struct { /* If v in D[u] then firstVal[u] <= posInVal[u][v] < firstVal[u]+nbVal[u] and val[posInVal[u][v]] = v otherwise posInVal[u][v] >= firstVal[u]+nbVal[u] */ - igraph_integer_t valSize; /* size of val */ + igraph_int_t valSize; /* size of val */ igraph_matrix_int_t firstMatch; /* firstMatch[u][v] = pos in match of the first vertex of the covering matching of G_(u, v) */ igraph_vector_int_t matching; /* matching[firstMatch[u][v]..firstMatch[u][v]+nbSucc[u]-1] = covering matching of G_(u, v) */ - igraph_integer_t nextOutToFilter; /* position in toFilter of the next pattern node whose + igraph_int_t nextOutToFilter; /* position in toFilter of the next pattern node whose domain should be filtered (-1 if no domain to filter) */ - igraph_integer_t lastInToFilter; /* position in toFilter of the last pattern node whose + igraph_int_t lastInToFilter; /* position in toFilter of the last pattern node whose domain should be filtered */ igraph_vector_int_t toFilter; /* contain all pattern nodes whose domain should be filtered */ @@ -185,11 +185,11 @@ static void igraph_i_lad_resetToFilter(Tdomain *D) { } -static igraph_integer_t igraph_i_lad_nextToFilter(Tdomain* D, igraph_integer_t size) { +static igraph_int_t igraph_i_lad_nextToFilter(Tdomain* D, igraph_int_t size) { /* precondition: emptyToFilter = false remove a node from toFilter (FIFO) unmark this node and return it */ - igraph_integer_t u = VECTOR(D->toFilter)[D->nextOutToFilter]; + igraph_int_t u = VECTOR(D->toFilter)[D->nextOutToFilter]; IGRAPH_BIT_CLEAR(D->markedToFilter, u); if (D->nextOutToFilter == D->lastInToFilter) { /* u was the last node in tofilter */ @@ -202,7 +202,7 @@ static igraph_integer_t igraph_i_lad_nextToFilter(Tdomain* D, igraph_integer_t s return u; } -static void igraph_i_lad_addToFilter(igraph_integer_t u, Tdomain* D, igraph_integer_t size) { +static void igraph_i_lad_addToFilter(igraph_int_t u, Tdomain* D, igraph_int_t size) { /* if u is not marked, then add it to toFilter and mark it */ if (IGRAPH_BIT_TEST(D->markedToFilter, u)) { return; @@ -219,29 +219,29 @@ static void igraph_i_lad_addToFilter(igraph_integer_t u, Tdomain* D, igraph_inte VECTOR(D->toFilter)[D->lastInToFilter] = u; } -static bool igraph_i_lad_isInD(igraph_integer_t u, igraph_integer_t v, Tdomain* D) { +static bool igraph_i_lad_isInD(igraph_int_t u, igraph_int_t v, Tdomain* D) { /* returns true if v belongs to D(u); false otherwise */ return (MATRIX(D->posInVal, u, v) < VECTOR(D->firstVal)[u] + VECTOR(D->nbVal)[u]); } -static igraph_error_t igraph_i_lad_augmentingPath(igraph_integer_t u, Tdomain* D, igraph_integer_t nbV, bool* result) { +static igraph_error_t igraph_i_lad_augmentingPath(igraph_int_t u, Tdomain* D, igraph_int_t nbV, bool* result) { /* return true if there exists an augmenting path starting from u and ending on a free vertex v in the bipartite directed graph G=(U, V, E) such that U=pattern nodes, V=target nodes, and E={(u, v), v in D(u)} U {(v, u), D->globalMatchingP[u]=v} update D-globalMatchingP and D->globalMatchingT consequently */ - igraph_integer_t *fifo, *pred; + igraph_int_t *fifo, *pred; igraph_bitset_t marked; - igraph_integer_t nextIn = 0; - igraph_integer_t nextOut = 0; - igraph_integer_t i, v, v2, u2; + igraph_int_t nextIn = 0; + igraph_int_t nextOut = 0; + igraph_int_t i, v, v2, u2; *result = false; /* Allocate memory */ - ALLOC_ARRAY(fifo, nbV, igraph_integer_t); - ALLOC_ARRAY(pred, nbV, igraph_integer_t); + ALLOC_ARRAY(fifo, nbV, igraph_int_t); + ALLOC_ARRAY(pred, nbV, igraph_int_t); IGRAPH_BITSET_INIT_FINALLY(&marked, nbV); for (i = 0; i < VECTOR(D->nbVal)[u]; i++) { @@ -293,14 +293,14 @@ static igraph_error_t igraph_i_lad_augmentingPath(igraph_integer_t u, Tdomain* D return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_lad_removeAllValuesButOne(igraph_integer_t u, igraph_integer_t v, Tdomain* D, Tgraph* Gp, +static igraph_error_t igraph_i_lad_removeAllValuesButOne(igraph_int_t u, igraph_int_t v, Tdomain* D, Tgraph* Gp, Tgraph* Gt, bool* result) { /* remove all values but v from D(u) and add all successors of u in toFilter return false if an inconsistency is detected wrt to global all diff */ - igraph_integer_t j, oldPos, newPos; + igraph_int_t j, oldPos, newPos; igraph_vector_int_t *uneis = igraph_adjlist_get(&Gp->succ, u); - igraph_integer_t n = igraph_vector_int_size(uneis); + igraph_int_t n = igraph_vector_int_size(uneis); /* add all successors of u in toFilter */ for (j = 0; j < n; j++) { igraph_i_lad_addToFilter(VECTOR(*uneis)[j], D, @@ -327,14 +327,14 @@ static igraph_error_t igraph_i_lad_removeAllValuesButOne(igraph_integer_t u, igr } -static igraph_error_t igraph_i_lad_removeValue(igraph_integer_t u, igraph_integer_t v, Tdomain* D, Tgraph* Gp, +static igraph_error_t igraph_i_lad_removeValue(igraph_int_t u, igraph_int_t v, Tdomain* D, Tgraph* Gp, Tgraph* Gt, bool* result) { /* remove v from D(u) and add all successors of u in toFilter return false if an inconsistency is detected wrt global all diff */ - igraph_integer_t j; + igraph_int_t j; igraph_vector_int_t *uneis = igraph_adjlist_get(&Gp->succ, u); - igraph_integer_t n = igraph_vector_int_size(uneis); - igraph_integer_t oldPos, newPos; + igraph_int_t n = igraph_vector_int_size(uneis); + igraph_int_t oldPos, newPos; /* add all successors of u in toFilter */ for (j = 0; j < n; j++) { @@ -362,7 +362,7 @@ static igraph_error_t igraph_i_lad_removeValue(igraph_integer_t u, igraph_intege } -static igraph_error_t igraph_i_lad_matchVertices(igraph_integer_t nb, igraph_vector_int_t* toBeMatched, +static igraph_error_t igraph_i_lad_matchVertices(igraph_int_t nb, igraph_vector_int_t* toBeMatched, bool induced, Tdomain* D, Tgraph* Gp, Tgraph* Gt, igraph_bool_t *invalid) { /* for each u in toBeMatched[0..nb-1], match u to @@ -372,7 +372,7 @@ static igraph_error_t igraph_i_lad_matchVertices(igraph_integer_t nb, igraph_vec FC(diff), but this speeds up the solution process). return false if an inconsistency is detected by FC(Edges) or FC(diff); true otherwise; */ - igraph_integer_t j, u, v, u2, oldNbVal; + igraph_int_t j, u, v, u2, oldNbVal; igraph_vector_int_t *vneis; bool result = false; @@ -447,7 +447,7 @@ static igraph_error_t igraph_i_lad_matchVertices(igraph_integer_t nb, igraph_vec } -static bool igraph_i_lad_matchVertex(igraph_integer_t u, bool induced, Tdomain* D, Tgraph* Gp, +static bool igraph_i_lad_matchVertex(igraph_int_t u, bool induced, Tdomain* D, Tgraph* Gp, Tgraph *Gt) { igraph_bool_t invalid; /* match u to D->val[D->firstVal[u]] and filter domains of other non @@ -470,7 +470,7 @@ static bool igraph_i_lad_matchVertex(igraph_integer_t u, bool induced, Tdomain* static int igraph_i_lad_qcompare (void const *a, void const *b) { /* function used by the qsort function */ - igraph_integer_t pa = ((*((igraph_integer_t*)a) - *((igraph_integer_t*)b))); + igraph_int_t pa = ((*((igraph_int_t*)a) - *((igraph_int_t*)b))); if (pa < 0) { return -1; } else if (pa > 0) { @@ -479,11 +479,11 @@ static int igraph_i_lad_qcompare (void const *a, void const *b) { return 0; } -static bool igraph_i_lad_compare(igraph_integer_t size_mu, igraph_integer_t* mu, igraph_integer_t size_mv, igraph_integer_t* mv) { +static bool igraph_i_lad_compare(igraph_int_t size_mu, igraph_int_t* mu, igraph_int_t size_mv, igraph_int_t* mv) { /* return true if for every element u of mu there exists a different element v of mv such that u <= v; return false otherwise */ - igraph_integer_t i, j; + igraph_int_t i, j; igraph_qsort(mu, (size_t) size_mu, sizeof(mu[0]), igraph_i_lad_qcompare); igraph_qsort(mv, (size_t) size_mv, sizeof(mv[0]), igraph_i_lad_qcompare); i = size_mv - 1; @@ -505,13 +505,13 @@ static igraph_error_t igraph_i_lad_initDomains(bool initialDomains, if initialDomains, then filter initial domains wrt compatibilities given in file return false if a domain is empty and true otherwise */ - igraph_integer_t *val; + igraph_int_t *val; igraph_bitset_t dom; - igraph_integer_t *mu, *mv; - igraph_integer_t matchingSize, u, v, i, j; + igraph_int_t *mu, *mv; + igraph_int_t matchingSize, u, v, i, j; igraph_vector_int_t *vec; - ALLOC_ARRAY(val, Gp->nbVertices * Gt->nbVertices, igraph_integer_t); + ALLOC_ARRAY(val, Gp->nbVertices * Gt->nbVertices, igraph_int_t); IGRAPH_BITSET_INIT_FINALLY(&dom, Gt->nbVertices); IGRAPH_VECTOR_INT_INIT_FINALLY(&D->globalMatchingP, Gp->nbVertices); @@ -557,11 +557,11 @@ static igraph_error_t igraph_i_lad_initDomains(bool initialDomains, MATRIX(D->firstMatch, u, v) = matchingSize; matchingSize += VECTOR(Gp->nbSucc)[u]; if (VECTOR(Gp->nbSucc)[u] <= VECTOR(Gt->nbSucc)[v]) { - mu = IGRAPH_CALLOC(VECTOR(Gp->nbSucc)[u], igraph_integer_t); + mu = IGRAPH_CALLOC(VECTOR(Gp->nbSucc)[u], igraph_int_t); IGRAPH_CHECK_OOM(mu, "Insufficient memory for subisomorphism search with LAD."); IGRAPH_FINALLY(igraph_free, mu); - mv = IGRAPH_CALLOC(VECTOR(Gt->nbSucc)[v], igraph_integer_t); + mv = IGRAPH_CALLOC(VECTOR(Gt->nbSucc)[v], igraph_int_t); IGRAPH_CHECK_OOM(mu, "Insufficient memory for subisomorphism search with LAD."); IGRAPH_FINALLY(igraph_free, mv); @@ -649,14 +649,14 @@ static void igraph_i_lad_destroyDomains(Tdomain *D) { #define toBeDeleted 3 #define deleted 4 -static void igraph_i_lad_addToDelete(igraph_integer_t u, igraph_integer_t* list, igraph_integer_t* nb, igraph_integer_t* marked) { +static void igraph_i_lad_addToDelete(igraph_int_t u, igraph_int_t* list, igraph_int_t* nb, igraph_int_t* marked) { if (marked[u] < toBeDeleted) { list[(*nb)++] = u; marked[u] = toBeDeleted; } } -static igraph_error_t igraph_i_lad_updateMatching(igraph_integer_t sizeOfU, igraph_integer_t sizeOfV, +static igraph_error_t igraph_i_lad_updateMatching(igraph_int_t sizeOfU, igraph_int_t sizeOfV, igraph_vector_int_t *degree, igraph_vector_int_t *firstAdj, igraph_vector_int_t *adj, @@ -676,27 +676,27 @@ static igraph_error_t igraph_i_lad_updateMatching(igraph_integer_t sizeOfU, igra for every u in 0..nbU-1, there exists a different v in 0..nb-1 such that v is adjacent to u; returns false otherwise */ - igraph_integer_t *matchedWithV; /* matchedWithV[matchedWithU[u]]=u */ - igraph_integer_t *nbPred; /* nbPred[i] = nb of predecessors of the ith + igraph_int_t *matchedWithV; /* matchedWithV[matchedWithU[u]]=u */ + igraph_int_t *nbPred; /* nbPred[i] = nb of predecessors of the ith vertex of V in the DAG */ - igraph_integer_t *pred; /* pred[i][j] = jth predecessor the ith + igraph_int_t *pred; /* pred[i][j] = jth predecessor the ith vertex of V in the DAG */ - igraph_integer_t *nbSucc; /* nbSucc[i] = nb of successors of the ith + igraph_int_t *nbSucc; /* nbSucc[i] = nb of successors of the ith vertex of U in the DAG */ - igraph_integer_t *succ; /* succ[i][j] = jth successor of the ith + igraph_int_t *succ; /* succ[i][j] = jth successor of the ith vertex of U in the DAG */ - igraph_integer_t *listV, *listU, *listDV, *listDU; - igraph_integer_t nbV, nbU, nbDV, nbDU; - igraph_integer_t i, j, k, stop, u, v; - igraph_integer_t *markedV, *markedU; + igraph_int_t *listV, *listU, *listDV, *listDU; + igraph_int_t nbV, nbU, nbDV, nbDU; + igraph_int_t i, j, k, stop, u, v; + igraph_int_t *markedV, *markedU; /* markedX[i]=white if X[i] is not in the DAG markedX[i]=grey if X[i] has been added to the DAG, but not its successors markedX[i]=black if X[i] and its successors have been added to the DAG markedX[i]=toBeDeleted if X[i] must be deleted from the DAG markedX[i]=deleted if X[i] has been deleted from the DAG */ - igraph_integer_t nbUnmatched = 0; /* number of vertices of U that are not matched */ - igraph_integer_t *unmatched; /* vertices of U that are not matched */ - igraph_integer_t *posInUnmatched; /* unmatched[posInUnmatched[u]]=u */ + igraph_int_t nbUnmatched = 0; /* number of vertices of U that are not matched */ + igraph_int_t *unmatched; /* vertices of U that are not matched */ + igraph_int_t *posInUnmatched; /* unmatched[posInUnmatched[u]]=u */ igraph_vector_int_t path; if (sizeOfU > sizeOfV) { @@ -704,19 +704,19 @@ static igraph_error_t igraph_i_lad_updateMatching(igraph_integer_t sizeOfU, igra return IGRAPH_SUCCESS; } - ALLOC_ARRAY(matchedWithV, sizeOfV, igraph_integer_t); - ALLOC_ARRAY(nbPred, sizeOfV, igraph_integer_t); - ALLOC_ARRAY(pred, sizeOfV * sizeOfU, igraph_integer_t); - ALLOC_ARRAY(nbSucc, sizeOfU, igraph_integer_t); - ALLOC_ARRAY(succ, sizeOfU * sizeOfV, igraph_integer_t); - ALLOC_ARRAY(listV, sizeOfV, igraph_integer_t); - ALLOC_ARRAY(listU, sizeOfU, igraph_integer_t); - ALLOC_ARRAY(listDV, sizeOfV, igraph_integer_t); - ALLOC_ARRAY(listDU, sizeOfU, igraph_integer_t); - ALLOC_ARRAY(markedV, sizeOfV, igraph_integer_t); - ALLOC_ARRAY(markedU, sizeOfU, igraph_integer_t); - ALLOC_ARRAY(unmatched, sizeOfU, igraph_integer_t); - ALLOC_ARRAY(posInUnmatched, sizeOfU, igraph_integer_t); + ALLOC_ARRAY(matchedWithV, sizeOfV, igraph_int_t); + ALLOC_ARRAY(nbPred, sizeOfV, igraph_int_t); + ALLOC_ARRAY(pred, sizeOfV * sizeOfU, igraph_int_t); + ALLOC_ARRAY(nbSucc, sizeOfU, igraph_int_t); + ALLOC_ARRAY(succ, sizeOfU * sizeOfV, igraph_int_t); + ALLOC_ARRAY(listV, sizeOfV, igraph_int_t); + ALLOC_ARRAY(listU, sizeOfU, igraph_int_t); + ALLOC_ARRAY(listDV, sizeOfV, igraph_int_t); + ALLOC_ARRAY(listDU, sizeOfU, igraph_int_t); + ALLOC_ARRAY(markedV, sizeOfV, igraph_int_t); + ALLOC_ARRAY(markedU, sizeOfU, igraph_int_t); + ALLOC_ARRAY(unmatched, sizeOfU, igraph_int_t); + ALLOC_ARRAY(posInUnmatched, sizeOfU, igraph_int_t); IGRAPH_VECTOR_INT_INIT_FINALLY(&path, 0); @@ -906,9 +906,9 @@ static igraph_error_t igraph_i_lad_updateMatching(igraph_integer_t sizeOfU, igra return IGRAPH_SUCCESS; } -static void igraph_i_lad_DFS(igraph_integer_t nbU, igraph_integer_t nbV, igraph_integer_t u, igraph_bitset_t *marked, igraph_integer_t* nbSucc, - igraph_integer_t* succ, igraph_vector_int_t * matchedWithU, - igraph_integer_t* order, igraph_integer_t* nb) { +static void igraph_i_lad_DFS(igraph_int_t nbU, igraph_int_t nbV, igraph_int_t u, igraph_bitset_t *marked, igraph_int_t* nbSucc, + igraph_int_t* succ, igraph_vector_int_t * matchedWithU, + igraph_int_t* order, igraph_int_t* nb) { /* perform a depth first search, starting from u, in the bipartite graph Go=(U, V, E) such that U = vertices of Gp @@ -919,8 +919,8 @@ static void igraph_i_lad_DFS(igraph_integer_t nbU, igraph_integer_t nbV, igraph_ Given a vertex v of Gt, nbSucc[v]=number of successors of v and succ[v]=list of successors of v. order[nb^out+1..nb^in] contains the vertices discovered by the DFS */ - igraph_integer_t i; - igraph_integer_t v = VECTOR(*matchedWithU)[u]; /* the only one predecessor of v is u */ + igraph_int_t i; + igraph_int_t v = VECTOR(*matchedWithU)[u]; /* the only one predecessor of v is u */ IGRAPH_BIT_SET(*marked, u); if (v >= 0) { for (i = 0; i < nbSucc[v]; i++) { @@ -934,9 +934,9 @@ static void igraph_i_lad_DFS(igraph_integer_t nbU, igraph_integer_t nbV, igraph_ order[*nb] = u; (*nb)--; } -static igraph_error_t igraph_i_lad_SCC(igraph_integer_t nbU, igraph_integer_t nbV, igraph_integer_t* numV, igraph_integer_t* numU, - igraph_integer_t* nbSucc, igraph_integer_t* succ, - igraph_integer_t* nbPred, igraph_integer_t* pred, +static igraph_error_t igraph_i_lad_SCC(igraph_int_t nbU, igraph_int_t nbV, igraph_int_t* numV, igraph_int_t* numU, + igraph_int_t* nbSucc, igraph_int_t* succ, + igraph_int_t* nbPred, igraph_int_t* pred, igraph_vector_int_t * matchedWithU, igraph_vector_int_t * matchedWithV) { /* postrelation: numV[v]==numU[u] iff they belong to the same @@ -949,15 +949,15 @@ static igraph_error_t igraph_i_lad_SCC(igraph_integer_t nbU, igraph_integer_t nb Given a vertex v of Gt, nbSucc[v]=number of sucessors of v and succ[v]=list of successors of v */ - igraph_integer_t *order; + igraph_int_t *order; igraph_bitset_t marked; - igraph_integer_t *fifo; - igraph_integer_t u, v, i, j, k, nbSCC, nb; + igraph_int_t *fifo; + igraph_int_t u, v, i, j, k, nbSCC, nb; /* Allocate memory */ - ALLOC_ARRAY(order, nbU, igraph_integer_t); + ALLOC_ARRAY(order, nbU, igraph_int_t); IGRAPH_BITSET_INIT_FINALLY(&marked, nbU); - ALLOC_ARRAY(fifo, nbV, igraph_integer_t); + ALLOC_ARRAY(fifo, nbV, igraph_int_t); /* Order vertices of Gp wrt DFS */ nb = nbU - 1; @@ -1021,29 +1021,29 @@ static igraph_error_t igraph_i_lad_ensureGACallDiff(bool induced, Tgraph* Gp, Tg v=D->globalMatchingP[u])} U { (v, u) / v is a vertex of Gt which is in D(u) but is not matched to u} */ - igraph_integer_t *nbPred; /* nbPred[u] = nb of predecessors of u in Go */ - igraph_integer_t *pred; /* pred[u][i] = ith + igraph_int_t *nbPred; /* nbPred[u] = nb of predecessors of u in Go */ + igraph_int_t *pred; /* pred[u][i] = ith predecessor of u in Go */ - igraph_integer_t *nbSucc; /* nbSucc[v] = nb of successors of v in Go */ - igraph_integer_t *succ; /* succ[v][i] = ith + igraph_int_t *nbSucc; /* nbSucc[v] = nb of successors of v in Go */ + igraph_int_t *succ; /* succ[v][i] = ith successor of v in Go */ - igraph_integer_t u, v, i, w, oldNbVal, nbToMatch; - igraph_integer_t *numV, *numU; + igraph_int_t u, v, i, w, oldNbVal, nbToMatch; + igraph_int_t *numV, *numU; igraph_vector_int_t toMatch; igraph_bitset_t used; - igraph_integer_t *list; - igraph_integer_t nb = 0; + igraph_int_t *list; + igraph_int_t nb = 0; bool result; /* Allocate memory */ - ALLOC_ARRAY(nbPred, Gp->nbVertices, igraph_integer_t); - ALLOC_ARRAY(pred, Gp->nbVertices * Gt->nbVertices, igraph_integer_t); - ALLOC_ARRAY(nbSucc, Gt->nbVertices, igraph_integer_t); - ALLOC_ARRAY(succ, Gt->nbVertices * Gp->nbVertices, igraph_integer_t); - ALLOC_ARRAY(numV, Gt->nbVertices, igraph_integer_t); - ALLOC_ARRAY(numU, Gp->nbVertices, igraph_integer_t); + ALLOC_ARRAY(nbPred, Gp->nbVertices, igraph_int_t); + ALLOC_ARRAY(pred, Gp->nbVertices * Gt->nbVertices, igraph_int_t); + ALLOC_ARRAY(nbSucc, Gt->nbVertices, igraph_int_t); + ALLOC_ARRAY(succ, Gt->nbVertices * Gp->nbVertices, igraph_int_t); + ALLOC_ARRAY(numV, Gt->nbVertices, igraph_int_t); + ALLOC_ARRAY(numU, Gp->nbVertices, igraph_int_t); IGRAPH_BITSET_INIT_FINALLY(&used, Gp->nbVertices * Gt->nbVertices); - ALLOC_ARRAY(list, Gt->nbVertices, igraph_integer_t); + ALLOC_ARRAY(list, Gt->nbVertices, igraph_int_t); IGRAPH_VECTOR_INT_INIT_FINALLY(&toMatch, Gp->nbVertices); for (u = 0; u < Gp->nbVertices; u++) { @@ -1135,20 +1135,20 @@ static igraph_error_t igraph_i_lad_ensureGACallDiff(bool induced, Tgraph* Gp, Tg /* Coming from lad.c */ /* ---------------------------------------------------------*/ -static igraph_error_t igraph_i_lad_checkLAD(igraph_integer_t u, igraph_integer_t v, Tdomain* D, Tgraph* Gp, Tgraph* Gt, +static igraph_error_t igraph_i_lad_checkLAD(igraph_int_t u, igraph_int_t v, Tdomain* D, Tgraph* Gp, Tgraph* Gt, bool *result) { /* return true if G_(u, v) has a adj(u)-covering matching; false otherwise */ - igraph_integer_t u2, v2, i, j; - igraph_integer_t nbMatched = 0; + igraph_int_t u2, v2, i, j; + igraph_int_t nbMatched = 0; igraph_vector_int_t *Gp_uneis = igraph_adjlist_get(&Gp->succ, u); - igraph_integer_t *num, *numInv; + igraph_int_t *num, *numInv; igraph_vector_int_t nbComp; igraph_vector_int_t firstComp; igraph_vector_int_t comp; - igraph_integer_t nbNum = 0; - igraph_integer_t posInComp = 0; + igraph_int_t nbNum = 0; + igraph_int_t posInComp = 0; igraph_vector_int_t matchedWithU; igraph_bool_t invalid; @@ -1191,8 +1191,8 @@ static igraph_error_t igraph_i_lad_checkLAD(igraph_integer_t u, igraph_integer_t } /* The matching still covers adj(u) */ /* Allocate memory */ - ALLOC_ARRAY(num, Gt->nbVertices, igraph_integer_t); - ALLOC_ARRAY(numInv, Gt->nbVertices, igraph_integer_t); + ALLOC_ARRAY(num, Gt->nbVertices, igraph_int_t); + ALLOC_ARRAY(numInv, Gt->nbVertices, igraph_int_t); /* Build the bipartite graph let U be the set of nodes adjacent to u @@ -1286,7 +1286,7 @@ static igraph_error_t igraph_i_lad_filter(bool induced, Tdomain* D, Tgraph* Gp, /* filter domains of all vertices in D->toFilter wrt LAD and ensure GAC(allDiff) return false if some domain becomes empty; true otherwise */ - igraph_integer_t u, v, i, oldNbVal; + igraph_int_t u, v, i, oldNbVal; igraph_bool_t invalid; bool result2; while (!igraph_i_lad_toFilterEmpty(D)) { @@ -1335,7 +1335,7 @@ static igraph_error_t igraph_i_lad_solve(bool firstSol, bool induced, Tdomain* D, Tgraph* Gp, Tgraph* Gt, igraph_bool_t *invalid, igraph_bool_t *iso, igraph_vector_int_t *vec, igraph_vector_int_t *map, igraph_vector_int_list_t *maps, - igraph_integer_t *nbNodes, igraph_integer_t *nbFail, igraph_integer_t *nbSol, + igraph_int_t *nbNodes, igraph_int_t *nbFail, igraph_int_t *nbSol, clock_t *begin, igraph_vector_ptr_t *alloc_history) { /* if firstSol then search for the first solution; otherwise search for all solutions if induced then search for induced subgraphs; @@ -1343,17 +1343,17 @@ static igraph_error_t igraph_i_lad_solve(bool firstSol, bool induced, return false if CPU time limit exceeded before the search is completed, return true otherwise */ - igraph_integer_t u, v, minDom, i; - igraph_integer_t* nbVal; - igraph_integer_t* globalMatching; - igraph_integer_t* val; + igraph_int_t u, v, minDom, i; + igraph_int_t* nbVal; + igraph_int_t* globalMatching; + igraph_int_t* val; bool result; (*nbNodes)++; /* Allocate memory */ - ALLOC_ARRAY_IN_HISTORY(nbVal, Gp->nbVertices, igraph_integer_t, alloc_history); - ALLOC_ARRAY_IN_HISTORY(globalMatching, Gp->nbVertices, igraph_integer_t, alloc_history); + ALLOC_ARRAY_IN_HISTORY(nbVal, Gp->nbVertices, igraph_int_t, alloc_history); + ALLOC_ARRAY_IN_HISTORY(globalMatching, Gp->nbVertices, igraph_int_t, alloc_history); IGRAPH_CHECK(igraph_i_lad_filter(induced, D, Gp, Gt, &result)); if (!result) { @@ -1401,7 +1401,7 @@ static igraph_error_t igraph_i_lad_solve(bool firstSol, bool induced, } /* save the domain of minDom to iterate on its values */ - ALLOC_ARRAY_IN_HISTORY(val, VECTOR(D->nbVal)[minDom], igraph_integer_t, alloc_history); + ALLOC_ARRAY_IN_HISTORY(val, VECTOR(D->nbVal)[minDom], igraph_int_t, alloc_history); for (i = 0; i < VECTOR(D->nbVal)[minDom]; i++) { val[i] = VECTOR(D->val)[ VECTOR(D->firstVal)[minDom] + i ]; } @@ -1522,16 +1522,16 @@ igraph_error_t igraph_subisomorphic_lad(const igraph_t *pattern, const igraph_t Tgraph Gp, Gt; Tdomain D; igraph_bool_t invalidDomain; - igraph_integer_t u, nbToMatch = 0; + igraph_int_t u, nbToMatch = 0; igraph_vector_int_t toMatch; /* Helper vector in which we build the current subisomorphism mapping */ igraph_vector_int_t vec; /* Number of nodes in the search tree */ - igraph_integer_t nbNodes = 0; + igraph_int_t nbNodes = 0; /* number of failed nodes in the search tree */ - igraph_integer_t nbFail = 0; + igraph_int_t nbFail = 0; /* number of solutions found */ - igraph_integer_t nbSol = 0; + igraph_int_t nbSol = 0; /* reusable structure to get CPU time usage */ clock_t begin = clock(); /* Stack to store memory blocks that are allocated during igraph_i_lad_solve */ diff --git a/src/vendor/cigraph/src/isomorphism/queries.c b/src/vendor/cigraph/src/isomorphism/queries.c index d693bcb3978..c6329600d48 100644 --- a/src/vendor/cigraph/src/isomorphism/queries.c +++ b/src/vendor/cigraph/src/isomorphism/queries.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -100,8 +100,8 @@ static igraph_error_t igraph_i_isomorphic_small( igraph_error_t igraph_isomorphic(const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *iso) { - igraph_integer_t nodes1 = igraph_vcount(graph1), nodes2 = igraph_vcount(graph2); - igraph_integer_t edges1 = igraph_ecount(graph1), edges2 = igraph_ecount(graph2); + igraph_int_t nodes1 = igraph_vcount(graph1), nodes2 = igraph_vcount(graph2); + igraph_int_t edges1 = igraph_ecount(graph1), edges2 = igraph_ecount(graph2); igraph_bool_t dir1 = igraph_is_directed(graph1), dir2 = igraph_is_directed(graph2); igraph_bool_t loop1, loop2, multi1, multi2; @@ -180,7 +180,7 @@ igraph_error_t igraph_isomorphic(const igraph_t *graph1, const igraph_t *graph2, igraph_error_t igraph_i_isomorphic_small( const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *iso ) { - igraph_integer_t class1, class2; + igraph_int_t class1, class2; IGRAPH_CHECK(igraph_isoclass(graph1, &class1)); IGRAPH_CHECK(igraph_isoclass(graph2, &class2)); *iso = (class1 == class2); diff --git a/src/vendor/cigraph/src/isomorphism/vf2.c b/src/vendor/cigraph/src/isomorphism/vf2.c index 85a4e3811bc..7f3075fca64 100644 --- a/src/vendor/cigraph/src/isomorphism/vf2.c +++ b/src/vendor/cigraph/src/isomorphism/vf2.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -143,20 +143,20 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( igraph_isocompat_t *edge_compat_fn, void *arg ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph1); - igraph_integer_t no_of_edges = igraph_ecount(graph1); + igraph_int_t no_of_nodes = igraph_vcount(graph1); + igraph_int_t no_of_edges = igraph_ecount(graph1); igraph_vector_int_t mycore_1, mycore_2, *core_1 = &mycore_1, *core_2 = &mycore_2; igraph_vector_int_t in_1, in_2, out_1, out_2; - igraph_integer_t in_1_size = 0, in_2_size = 0, out_1_size = 0, out_2_size = 0; + igraph_int_t in_1_size = 0, in_2_size = 0, out_1_size = 0, out_2_size = 0; igraph_vector_int_t *inneis_1, *inneis_2, *outneis_1, *outneis_2; - igraph_integer_t matched_nodes = 0; - igraph_integer_t depth; - igraph_integer_t cand1, cand2; - igraph_integer_t last1, last2; + igraph_int_t matched_nodes = 0; + igraph_int_t depth; + igraph_int_t cand1, cand2; + igraph_int_t last1, last2; igraph_stack_int_t path; igraph_lazy_adjlist_t inadj1, inadj2, outadj1, outadj2; igraph_vector_int_t indeg1, indeg2, outdeg1, outdeg2; - igraph_integer_t vsize; + igraph_int_t vsize; IGRAPH_CHECK(igraph_i_perform_vf2_pre_checks(graph1, graph2)); @@ -274,7 +274,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( depth = 0; last1 = -1; last2 = -1; while (depth >= 0) { - igraph_integer_t i; + igraph_int_t i; IGRAPH_ALLOW_INTERRUPTION(); @@ -380,7 +380,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_1)[i]; + igraph_int_t node = VECTOR(*inneis_1)[i]; if (VECTOR(in_1)[node] == depth) { VECTOR(in_1)[node] = 0; in_1_size -= 1; @@ -392,7 +392,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_1)[i]; + igraph_int_t node = VECTOR(*outneis_1)[i]; if (VECTOR(out_1)[node] == depth) { VECTOR(out_1)[node] = 0; out_1_size -= 1; @@ -404,7 +404,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_2)[i]; + igraph_int_t node = VECTOR(*inneis_2)[i]; if (VECTOR(in_2)[node] == depth) { VECTOR(in_2)[node] = 0; in_2_size -= 1; @@ -416,7 +416,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_2)[i]; + igraph_int_t node = VECTOR(*outneis_2)[i]; if (VECTOR(out_2)[node] == depth) { VECTOR(out_2)[node] = 0; out_2_size -= 1; @@ -430,7 +430,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( } else { /**************************************************************/ /* step forward if worth, check if worth first */ - igraph_integer_t xin1 = 0, xin2 = 0, xout1 = 0, xout2 = 0; + igraph_int_t xin1 = 0, xin2 = 0, xout1 = 0, xout2 = 0; igraph_bool_t end = false; inneis_1 = igraph_lazy_adjlist_get(&inadj1, cand1); @@ -455,14 +455,14 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_1); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_1)[i]; + igraph_int_t node = VECTOR(*inneis_1)[i]; if (VECTOR(*core_1)[node] >= 0) { - igraph_integer_t node2 = VECTOR(*core_1)[node]; + igraph_int_t node2 = VECTOR(*core_1)[node]; /* check if there is a node2->cand2 edge */ if (!igraph_vector_int_contains_sorted(inneis_2, node2)) { end = true; } else if (edge_color1 || edge_compat_fn) { - igraph_integer_t eid1, eid2; + igraph_int_t eid1, eid2; igraph_get_eid(graph1, &eid1, node, cand1, IGRAPH_DIRECTED, /*error=*/ true); igraph_get_eid(graph2, &eid2, node2, cand2, IGRAPH_DIRECTED, @@ -487,14 +487,14 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( } vsize = igraph_vector_int_size(outneis_1); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_1)[i]; + igraph_int_t node = VECTOR(*outneis_1)[i]; if (VECTOR(*core_1)[node] >= 0) { - igraph_integer_t node2 = VECTOR(*core_1)[node]; + igraph_int_t node2 = VECTOR(*core_1)[node]; /* check if there is a cand2->node2 edge */ if (!igraph_vector_int_contains_sorted(outneis_2, node2)) { end = true; } else if (edge_color1 || edge_compat_fn) { - igraph_integer_t eid1, eid2; + igraph_int_t eid1, eid2; igraph_get_eid(graph1, &eid1, cand1, node, IGRAPH_DIRECTED, /*error=*/ true); igraph_get_eid(graph2, &eid2, cand2, node2, IGRAPH_DIRECTED, @@ -519,14 +519,14 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( } vsize = igraph_vector_int_size(inneis_2); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_2)[i]; + igraph_int_t node = VECTOR(*inneis_2)[i]; if (VECTOR(*core_2)[node] >= 0) { - igraph_integer_t node2 = VECTOR(*core_2)[node]; + igraph_int_t node2 = VECTOR(*core_2)[node]; /* check if there is a node2->cand1 edge */ if (!igraph_vector_int_contains_sorted(inneis_1, node2)) { end = true; } else if (edge_color1 || edge_compat_fn) { - igraph_integer_t eid1, eid2; + igraph_int_t eid1, eid2; igraph_get_eid(graph1, &eid1, node2, cand1, IGRAPH_DIRECTED, /*error=*/ true); igraph_get_eid(graph2, &eid2, node, cand2, IGRAPH_DIRECTED, @@ -551,14 +551,14 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( } vsize = igraph_vector_int_size(outneis_2); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_2)[i]; + igraph_int_t node = VECTOR(*outneis_2)[i]; if (VECTOR(*core_2)[node] >= 0) { - igraph_integer_t node2 = VECTOR(*core_2)[node]; + igraph_int_t node2 = VECTOR(*core_2)[node]; /* check if there is a cand1->node2 edge */ if (!igraph_vector_int_contains_sorted(outneis_1, node2)) { end = true; } else if (edge_color1 || edge_compat_fn) { - igraph_integer_t eid1, eid2; + igraph_int_t eid1, eid2; igraph_get_eid(graph1, &eid1, cand1, node2, IGRAPH_DIRECTED, /*error=*/ true); igraph_get_eid(graph2, &eid2, cand2, node, IGRAPH_DIRECTED, @@ -610,7 +610,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_1)[i]; + igraph_int_t node = VECTOR(*inneis_1)[i]; if (VECTOR(in_1)[node] == 0 && VECTOR(*core_1)[node] < 0) { VECTOR(in_1)[node] = depth; in_1_size += 1; @@ -622,7 +622,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_1)[i]; + igraph_int_t node = VECTOR(*outneis_1)[i]; if (VECTOR(out_1)[node] == 0 && VECTOR(*core_1)[node] < 0) { VECTOR(out_1)[node] = depth; out_1_size += 1; @@ -634,7 +634,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_2)[i]; + igraph_int_t node = VECTOR(*inneis_2)[i]; if (VECTOR(in_2)[node] == 0 && VECTOR(*core_2)[node] < 0) { VECTOR(in_2)[node] = depth; in_2_size += 1; @@ -646,7 +646,7 @@ igraph_error_t igraph_get_isomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_2)[i]; + igraph_int_t node = VECTOR(*outneis_2)[i]; if (VECTOR(out_2)[node] == 0 && VECTOR(*core_2)[node] < 0) { VECTOR(out_2)[node] = depth; out_2_size += 1; @@ -704,8 +704,8 @@ typedef struct { static igraph_bool_t igraph_i_isocompat_node_cb( const igraph_t *graph1, const igraph_t *graph2, - const igraph_integer_t g1_num, - const igraph_integer_t g2_num, + const igraph_int_t g1_num, + const igraph_int_t g2_num, void *arg) { igraph_i_iso_cb_data_t *data = arg; return data->node_compat_fn(graph1, graph2, g1_num, g2_num, data->carg); @@ -714,8 +714,8 @@ static igraph_bool_t igraph_i_isocompat_node_cb( static igraph_bool_t igraph_i_isocompat_edge_cb( const igraph_t *graph1, const igraph_t *graph2, - const igraph_integer_t g1_num, - const igraph_integer_t g2_num, + const igraph_int_t g1_num, + const igraph_int_t g2_num, void *arg) { igraph_i_iso_cb_data_t *data = arg; return data->edge_compat_fn(graph1, graph2, g1_num, g2_num, data->carg); @@ -824,7 +824,7 @@ static igraph_error_t igraph_i_count_isomorphisms_vf2_cb( void *arg ) { igraph_i_iso_cb_data_t *data = arg; - igraph_integer_t *count = data->arg; + igraph_int_t *count = data->arg; IGRAPH_UNUSED(map12); IGRAPH_UNUSED(map21); *count += 1; return IGRAPH_SUCCESS; @@ -874,7 +874,7 @@ igraph_error_t igraph_count_isomorphisms_vf2(const igraph_t *graph1, const igrap const igraph_vector_int_t *vertex_color2, const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_integer_t *count, + igraph_int_t *count, igraph_isocompat_t *node_compat_fn, igraph_isocompat_t *edge_compat_fn, void *arg) { @@ -1029,22 +1029,22 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( igraph_isocompat_t *edge_compat_fn, void *arg ) { - igraph_integer_t no_of_nodes1 = igraph_vcount(graph1), + igraph_int_t no_of_nodes1 = igraph_vcount(graph1), no_of_nodes2 = igraph_vcount(graph2); - igraph_integer_t no_of_edges1 = igraph_ecount(graph1), + igraph_int_t no_of_edges1 = igraph_ecount(graph1), no_of_edges2 = igraph_ecount(graph2); igraph_vector_int_t mycore_1, mycore_2, *core_1 = &mycore_1, *core_2 = &mycore_2; igraph_vector_int_t in_1, in_2, out_1, out_2; - igraph_integer_t in_1_size = 0, in_2_size = 0, out_1_size = 0, out_2_size = 0; + igraph_int_t in_1_size = 0, in_2_size = 0, out_1_size = 0, out_2_size = 0; igraph_vector_int_t *inneis_1, *inneis_2, *outneis_1, *outneis_2; - igraph_integer_t matched_nodes = 0; - igraph_integer_t depth; - igraph_integer_t cand1, cand2; - igraph_integer_t last1, last2; + igraph_int_t matched_nodes = 0; + igraph_int_t depth; + igraph_int_t cand1, cand2; + igraph_int_t last1, last2; igraph_stack_int_t path; igraph_lazy_adjlist_t inadj1, inadj2, outadj1, outadj2; igraph_vector_int_t indeg1, indeg2, outdeg1, outdeg2; - igraph_integer_t vsize; + igraph_int_t vsize; IGRAPH_CHECK(igraph_i_perform_vf2_pre_checks(graph1, graph2)); @@ -1131,7 +1131,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( depth = 0; last1 = -1; last2 = -1; while (depth >= 0) { - igraph_integer_t i; + igraph_int_t i; IGRAPH_ALLOW_INTERRUPTION(); @@ -1237,7 +1237,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_1)[i]; + igraph_int_t node = VECTOR(*inneis_1)[i]; if (VECTOR(in_1)[node] == depth) { VECTOR(in_1)[node] = 0; in_1_size -= 1; @@ -1249,7 +1249,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_1)[i]; + igraph_int_t node = VECTOR(*outneis_1)[i]; if (VECTOR(out_1)[node] == depth) { VECTOR(out_1)[node] = 0; out_1_size -= 1; @@ -1261,7 +1261,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_2)[i]; + igraph_int_t node = VECTOR(*inneis_2)[i]; if (VECTOR(in_2)[node] == depth) { VECTOR(in_2)[node] = 0; in_2_size -= 1; @@ -1273,7 +1273,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_2)[i]; + igraph_int_t node = VECTOR(*outneis_2)[i]; if (VECTOR(out_2)[node] == depth) { VECTOR(out_2)[node] = 0; out_2_size -= 1; @@ -1287,7 +1287,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( } else { /**************************************************************/ /* step forward if worth, check if worth first */ - igraph_integer_t xin1 = 0, xin2 = 0, xout1 = 0, xout2 = 0; + igraph_int_t xin1 = 0, xin2 = 0, xout1 = 0, xout2 = 0; igraph_bool_t end = false; inneis_1 = igraph_lazy_adjlist_get(&inadj1, cand1); @@ -1312,7 +1312,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_1); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_1)[i]; + igraph_int_t node = VECTOR(*inneis_1)[i]; if (VECTOR(*core_1)[node] < 0) { if (VECTOR(in_1)[node] != 0) { xin1++; @@ -1324,7 +1324,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( } vsize = igraph_vector_int_size(outneis_1); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_1)[i]; + igraph_int_t node = VECTOR(*outneis_1)[i]; if (VECTOR(*core_1)[node] < 0) { if (VECTOR(in_1)[node] != 0) { xin1++; @@ -1336,14 +1336,14 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( } vsize = igraph_vector_int_size(inneis_2); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_2)[i]; + igraph_int_t node = VECTOR(*inneis_2)[i]; if (VECTOR(*core_2)[node] >= 0) { - igraph_integer_t node2 = VECTOR(*core_2)[node]; + igraph_int_t node2 = VECTOR(*core_2)[node]; /* check if there is a node2->cand1 edge */ if (!igraph_vector_int_contains_sorted(inneis_1, node2)) { end = true; } else if (edge_color1 || edge_compat_fn) { - igraph_integer_t eid1, eid2; + igraph_int_t eid1, eid2; igraph_get_eid(graph1, &eid1, node2, cand1, IGRAPH_DIRECTED, /*error=*/ true); igraph_get_eid(graph2, &eid2, node, cand2, IGRAPH_DIRECTED, @@ -1368,14 +1368,14 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( } vsize = igraph_vector_int_size(outneis_2); for (i = 0; !end && i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_2)[i]; + igraph_int_t node = VECTOR(*outneis_2)[i]; if (VECTOR(*core_2)[node] >= 0) { - igraph_integer_t node2 = VECTOR(*core_2)[node]; + igraph_int_t node2 = VECTOR(*core_2)[node]; /* check if there is a cand1->node2 edge */ if (!igraph_vector_int_contains_sorted(outneis_1, node2)) { end = true; } else if (edge_color1 || edge_compat_fn) { - igraph_integer_t eid1, eid2; + igraph_int_t eid1, eid2; igraph_get_eid(graph1, &eid1, cand1, node2, IGRAPH_DIRECTED, /*error=*/ true); igraph_get_eid(graph2, &eid2, cand2, node, IGRAPH_DIRECTED, @@ -1427,7 +1427,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_1)[i]; + igraph_int_t node = VECTOR(*inneis_1)[i]; if (VECTOR(in_1)[node] == 0 && VECTOR(*core_1)[node] < 0) { VECTOR(in_1)[node] = depth; in_1_size += 1; @@ -1439,7 +1439,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_1); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_1)[i]; + igraph_int_t node = VECTOR(*outneis_1)[i]; if (VECTOR(out_1)[node] == 0 && VECTOR(*core_1)[node] < 0) { VECTOR(out_1)[node] = depth; out_1_size += 1; @@ -1451,7 +1451,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(inneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*inneis_2)[i]; + igraph_int_t node = VECTOR(*inneis_2)[i]; if (VECTOR(in_2)[node] == 0 && VECTOR(*core_2)[node] < 0) { VECTOR(in_2)[node] = depth; in_2_size += 1; @@ -1463,7 +1463,7 @@ igraph_error_t igraph_get_subisomorphisms_vf2_callback( vsize = igraph_vector_int_size(outneis_2); for (i = 0; i < vsize; i++) { - igraph_integer_t node = VECTOR(*outneis_2)[i]; + igraph_int_t node = VECTOR(*outneis_2)[i]; if (VECTOR(out_2)[node] == 0 && VECTOR(*core_2)[node] < 0) { VECTOR(out_2)[node] = depth; out_2_size += 1; @@ -1605,7 +1605,7 @@ static igraph_error_t igraph_i_count_subisomorphisms_vf2_cb( void *arg ) { igraph_i_iso_cb_data_t *data = arg; - igraph_integer_t *count = data->arg; + igraph_int_t *count = data->arg; IGRAPH_UNUSED(map12); IGRAPH_UNUSED(map21); *count += 1; return IGRAPH_SUCCESS; @@ -1654,7 +1654,7 @@ igraph_error_t igraph_count_subisomorphisms_vf2(const igraph_t *graph1, const ig const igraph_vector_int_t *vertex_color2, const igraph_vector_int_t *edge_color1, const igraph_vector_int_t *edge_color2, - igraph_integer_t *count, + igraph_int_t *count, igraph_isocompat_t *node_compat_fn, igraph_isocompat_t *edge_compat_fn, void *arg) { diff --git a/src/vendor/cigraph/src/layout/align.c b/src/vendor/cigraph/src/layout/align.c index 0888a9b63f5..7496b68a545 100644 --- a/src/vendor/cigraph/src/layout/align.c +++ b/src/vendor/cigraph/src/layout/align.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -30,8 +30,6 @@ * \function igraph_layout_align * \brief Aligns a graph layout with the coordinate axes. * - * \experimental - * * This function centers a vertex layout on the coordinate system origin and * rotates the layout to achieve a visually pleasing alignment with the coordinate * axes. Doing this is particularly useful with force-directed layouts such as @@ -47,9 +45,9 @@ */ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layout) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); - const igraph_integer_t dim = igraph_matrix_ncol(layout); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); + const igraph_int_t dim = igraph_matrix_ncol(layout); igraph_matrix_t M, Q; /* nematic tensor */ igraph_real_t norm2_sum; /* sum of squared norms of alignment vectors */ igraph_matrix_t R; /* rotation matrix consisting of Q's eigenvectors */ @@ -114,8 +112,8 @@ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layou IGRAPH_CHECK(igraph_matrix_colsum(layout, ¢er)); igraph_vector_scale(¢er, 1.0 / vcount); - for (igraph_integer_t j=0; j < dim; j++) { - for (igraph_integer_t i=0; i < vcount; i++) { + for (igraph_int_t j=0; j < dim; j++) { + for (igraph_int_t i=0; i < vcount; i++) { MATRIX(*layout, i, j) -= VECTOR(center)[j]; } } @@ -138,18 +136,18 @@ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layou IGRAPH_VECTOR_INIT_FINALLY(&edge_vec, dim); norm2_sum = 0; - for (igraph_integer_t eid=0; eid < ecount; eid++) { - const igraph_integer_t from = IGRAPH_FROM(graph, eid); - const igraph_integer_t to = IGRAPH_TO(graph, eid); + for (igraph_int_t eid=0; eid < ecount; eid++) { + const igraph_int_t from = IGRAPH_FROM(graph, eid); + const igraph_int_t to = IGRAPH_TO(graph, eid); if (from == to) continue; /* skip self-loops */ - for (igraph_integer_t i=0; i < dim; i++) { + for (igraph_int_t i=0; i < dim; i++) { VECTOR(edge_vec)[i] = MATRIX(*layout, from, i) - MATRIX(*layout, to, i); } - for (igraph_integer_t i=0; i < dim; i++) { - for (igraph_integer_t j=0; j < dim; j++) { + for (igraph_int_t i=0; i < dim; i++) { + for (igraph_int_t j=0; j < dim; j++) { igraph_real_t m = VECTOR(edge_vec)[i] * VECTOR(edge_vec)[j]; MATRIX(M, i, j) += m; if (i == j) { @@ -178,9 +176,9 @@ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layou * to compute M_ij. Note that the layout has already been centered. */ if (norm2_sum == 0) { /* If norm2_sum == 0 then M is also all-zero, no need to null it explicitly. */ - for (igraph_integer_t vid=0; vid < vcount; vid++) { - for (igraph_integer_t i=0; i < dim; i++) { - for (igraph_integer_t j=0; j < dim; j++) { + for (igraph_int_t vid=0; vid < vcount; vid++) { + for (igraph_int_t i=0; i < dim; i++) { + for (igraph_int_t j=0; j < dim; j++) { igraph_real_t m = MATRIX(*layout, vid, i) * MATRIX(*layout, vid, j); MATRIX(M, i, j) += m; if (i == j) { @@ -218,7 +216,7 @@ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layou * Q_ij = M_ij / norm2 - delta_ij / d. */ IGRAPH_CHECK(igraph_matrix_update(&Q, &M)); igraph_matrix_scale(&Q, 1.0 / norm2_sum); - for (igraph_integer_t i=0; i < dim; i++) { + for (igraph_int_t i=0; i < dim; i++) { MATRIX(Q, i, i) -= 1.0 / dim; } @@ -239,7 +237,7 @@ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layou /* Compute the matrix norm, i.e. the largest eigenvalue magnitude, * to determine if the nematic tensor Q is close to zero. */ igraph_real_t matrix_norm = 0; - for (igraph_integer_t i=0; i < dim; i++) { + for (igraph_int_t i=0; i < dim; i++) { igraph_real_t magnitude = fabs(VECTOR(lambda)[i]); if (magnitude > matrix_norm) { matrix_norm = magnitude; @@ -285,9 +283,9 @@ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layou IGRAPH_VECTOR_INIT_FINALLY(&extent, dim); IGRAPH_VECTOR_INT_INIT_FINALLY(&permutation, dim); - for (igraph_integer_t j=0; j < dim; j++) { + for (igraph_int_t j=0; j < dim; j++) { igraph_real_t min = IGRAPH_INFINITY, max = -IGRAPH_INFINITY; - for (igraph_integer_t i=0; i < vcount; i++) { + for (igraph_int_t i=0; i < vcount; i++) { igraph_real_t c = MATRIX(temp_layout, i, j); if (c < min) min = c; if (c > max) max = c; @@ -296,8 +294,8 @@ igraph_error_t igraph_layout_align(const igraph_t *graph, igraph_matrix_t *layou } IGRAPH_CHECK(igraph_vector_sort_ind(&extent, &permutation, IGRAPH_DESCENDING)); - for (igraph_integer_t j=0; j < dim; j++) { - for (igraph_integer_t i=0; i < vcount; i++) { + for (igraph_int_t j=0; j < dim; j++) { + for (igraph_int_t i=0; i < vcount; i++) { MATRIX(*layout, i, j) = MATRIX(temp_layout, i, VECTOR(permutation)[j]); } } diff --git a/src/vendor/cigraph/src/layout/circular.c b/src/vendor/cigraph/src/layout/circular.c index 029ced2eaac..5a474de8579 100644 --- a/src/vendor/cigraph/src/layout/circular.c +++ b/src/vendor/cigraph/src/layout/circular.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -45,8 +45,8 @@ igraph_error_t igraph_layout_circle(const igraph_t *graph, igraph_matrix_t *res, igraph_vs_t order) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t vs_size; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t vs_size; igraph_vit_t vit; IGRAPH_CHECK(igraph_vs_size(graph, &order, &vs_size)); @@ -55,9 +55,9 @@ igraph_error_t igraph_layout_circle(const igraph_t *graph, igraph_matrix_t *res, igraph_matrix_null(res); IGRAPH_CHECK(igraph_vit_create(graph, order, &vit)); - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + for (igraph_int_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { igraph_real_t phi = 2 * M_PI / vs_size * i; - igraph_integer_t idx = IGRAPH_VIT_GET(vit); + igraph_int_t idx = IGRAPH_VIT_GET(vit); MATRIX(*res, idx, 0) = cos(phi); MATRIX(*res, idx, 1) = sin(phi); } @@ -87,9 +87,9 @@ igraph_error_t igraph_layout_circle(const igraph_t *graph, igraph_matrix_t *res, * \sa \ref igraph_layout_circle() and other layout generators. */ igraph_error_t igraph_layout_star(const igraph_t *graph, igraph_matrix_t *res, - igraph_integer_t center, const igraph_vector_int_t *order) { + igraph_int_t center, const igraph_vector_int_t *order) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); if (no_of_nodes > 0 && (center < 0 || center >= no_of_nodes)) { IGRAPH_ERROR("The given center is not a vertex of the graph.", IGRAPH_EINVAL); @@ -104,8 +104,8 @@ igraph_error_t igraph_layout_star(const igraph_t *graph, igraph_matrix_t *res, MATRIX(*res, 0, 0) = MATRIX(*res, 0, 1) = 0.0; } else if (no_of_nodes > 1) { igraph_real_t phi = 0.0; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t node = order ? VECTOR(*order)[i] : i; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t node = order ? VECTOR(*order)[i] : i; if (order && (node < 0 || node >= no_of_nodes)) { IGRAPH_ERROR("Elements in the order vector are not all vertices of the graph.", IGRAPH_EINVAL); } @@ -150,13 +150,13 @@ igraph_error_t igraph_layout_star(const igraph_t *graph, igraph_matrix_t *res, */ igraph_error_t igraph_layout_sphere(const igraph_t *graph, igraph_matrix_t *res) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); const igraph_real_t sqrt_no_of_nodes = sqrt(no_of_nodes); IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3)); igraph_real_t phi = 0; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_real_t r, z; /* The first and last point are handled separately to avoid diff --git a/src/vendor/cigraph/src/layout/davidson_harel.c b/src/vendor/cigraph/src/layout/davidson_harel.c index 7e54763bc43..2b24b06cac3 100644 --- a/src/vendor/cigraph/src/layout/davidson_harel.c +++ b/src/vendor/cigraph/src/layout/davidson_harel.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -139,15 +139,15 @@ igraph_real_t igraph_i_layout_point_segment_dist2(igraph_real_t v_x, igraph_real */ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, - igraph_integer_t fineiter, igraph_real_t cool_fact, + igraph_bool_t use_seed, igraph_int_t maxiter, + igraph_int_t fineiter, igraph_real_t cool_fact, igraph_real_t weight_node_dist, igraph_real_t weight_border, igraph_real_t weight_edge_lengths, igraph_real_t weight_edge_crossings, igraph_real_t weight_node_edge_dist) { - igraph_integer_t no_nodes = igraph_vcount(graph); - igraph_integer_t no_edges = igraph_ecount(graph); + igraph_int_t no_nodes = igraph_vcount(graph); + igraph_int_t no_edges = igraph_ecount(graph); igraph_real_t width = sqrt(no_nodes) * 10, height = width; igraph_vector_int_t perm; igraph_bool_t fine_tuning = false; @@ -158,7 +158,7 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix igraph_vector_int_t neis; igraph_real_t min_x = width / 2, max_x = -width / 2, min_y = height / 2, max_y = -height / 2; - igraph_integer_t no_tries = 30; + igraph_int_t no_tries = 30; igraph_real_t w_node_dist = weight_node_dist ; /* 1.0 */ igraph_real_t w_borderlines = weight_border; /* 0.0 */ igraph_real_t w_edge_lengths = weight_edge_lengths; /* 0.0001; */ @@ -196,7 +196,7 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 100); if (!use_seed) { - for (igraph_integer_t i = 0; i < no_nodes; i++) { + for (igraph_int_t i = 0; i < no_nodes; i++) { igraph_real_t x, y; x = MATRIX(*res, i, 0) = RNG_UNIF(-width / 2, width / 2); y = MATRIX(*res, i, 1) = RNG_UNIF(-height / 2, height / 2); @@ -214,7 +214,7 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix } else { min_x = IGRAPH_INFINITY; max_x = -IGRAPH_INFINITY; min_y = IGRAPH_INFINITY; max_y = -IGRAPH_INFINITY; - for (igraph_integer_t i = 0; i < no_nodes; i++) { + for (igraph_int_t i = 0; i < no_nodes; i++) { igraph_real_t x = MATRIX(*res, i, 0); igraph_real_t y = MATRIX(*res, i, 1); if (x < min_x) { @@ -230,13 +230,13 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix } } - for (igraph_integer_t i = 0; i < no_tries; i++) { + for (igraph_int_t i = 0; i < no_tries; i++) { double phi = 2 * M_PI / no_tries * i; VECTOR(try_x)[i] = cos(phi); VECTOR(try_y)[i] = sin(phi); } - for (igraph_integer_t round = 0; round < maxiter + fineiter; round++) { + for (igraph_int_t round = 0; round < maxiter + fineiter; round++) { IGRAPH_ALLOW_INTERRUPTION(); igraph_vector_int_shuffle(&perm); @@ -248,13 +248,13 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix move_radius = fx < fy ? fx : fy; } - for (igraph_integer_t p = 0; p < no_nodes; p++) { - igraph_integer_t v = VECTOR(perm)[p]; + for (igraph_int_t p = 0; p < no_nodes; p++) { + igraph_int_t v = VECTOR(perm)[p]; igraph_vector_int_shuffle(&try_idx); - for (igraph_integer_t t = 0; t < no_tries; t++) { + for (igraph_int_t t = 0; t < no_tries; t++) { igraph_real_t diff_energy = 0.0; - igraph_integer_t ti = VECTOR(try_idx)[t]; + igraph_int_t ti = VECTOR(try_idx)[t]; /* Try moving it */ igraph_real_t old_x = MATRIX(*res, v, 0); @@ -276,7 +276,7 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix } if (w_node_dist != 0) { - for (igraph_integer_t u = 0; u < no_nodes; u++) { + for (igraph_int_t u = 0; u < no_nodes; u++) { igraph_real_t odx, ody, odist2, dx, dy, dist2; if (u == v) { continue; @@ -328,9 +328,9 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix IGRAPH_CHECK(igraph_neighbors( graph, &neis, v, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE )); - igraph_integer_t len = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < len; j++) { - igraph_integer_t u = VECTOR(neis)[j]; + igraph_int_t len = igraph_vector_int_size(&neis); + for (igraph_int_t j = 0; j < len; j++) { + igraph_int_t u = VECTOR(neis)[j]; igraph_real_t odx = old_x - MATRIX(*res, u, 0); igraph_real_t ody = old_y - MATRIX(*res, u, 1); igraph_real_t odist2 = odx * odx + ody * ody; @@ -342,20 +342,20 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix } if (w_edge_crossings != 0) { - igraph_integer_t no = 0; + igraph_int_t no = 0; IGRAPH_CHECK(igraph_neighbors( graph, &neis, v, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE )); - igraph_integer_t len = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < len; j++) { - igraph_integer_t u = VECTOR(neis)[j]; + igraph_int_t len = igraph_vector_int_size(&neis); + for (igraph_int_t j = 0; j < len; j++) { + igraph_int_t u = VECTOR(neis)[j]; igraph_real_t u_x = MATRIX(*res, u, 0); igraph_real_t u_y = MATRIX(*res, u, 1); - igraph_integer_t e; + igraph_int_t e; for (e = 0; e < no_edges; e++) { - igraph_integer_t u1 = IGRAPH_FROM(graph, e); - igraph_integer_t u2 = IGRAPH_TO(graph, e); + igraph_int_t u1 = IGRAPH_FROM(graph, e); + igraph_int_t u2 = IGRAPH_TO(graph, e); igraph_real_t u1_x, u1_y, u2_x, u2_y; if (u1 == v || u2 == v || u1 == u || u2 == u) { continue; @@ -375,9 +375,9 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix if (w_node_edge_dist != 0 && fine_tuning) { /* All non-incident edges from the moved 'v' */ - for (igraph_integer_t e = 0; e < no_edges; e++) { - igraph_integer_t u1 = IGRAPH_FROM(graph, e); - igraph_integer_t u2 = IGRAPH_TO(graph, e); + for (igraph_int_t e = 0; e < no_edges; e++) { + igraph_int_t u1 = IGRAPH_FROM(graph, e); + igraph_int_t u2 = IGRAPH_TO(graph, e); igraph_real_t u1_x, u1_y, u2_x, u2_y, d_ev; if (u1 == v || u2 == v) { continue; @@ -396,13 +396,13 @@ igraph_error_t igraph_layout_davidson_harel(const igraph_t *graph, igraph_matrix /* All other nodes from all of v's incident edges */ IGRAPH_CHECK(igraph_incident(graph, &neis, v, IGRAPH_ALL, IGRAPH_NO_LOOPS)); - igraph_integer_t no = igraph_vector_int_size(&neis); - for (igraph_integer_t e = 0; e < no; e++) { - igraph_integer_t mye = VECTOR(neis)[e]; - igraph_integer_t u = IGRAPH_OTHER(graph, mye, v); + igraph_int_t no = igraph_vector_int_size(&neis); + for (igraph_int_t e = 0; e < no; e++) { + igraph_int_t mye = VECTOR(neis)[e]; + igraph_int_t u = IGRAPH_OTHER(graph, mye, v); igraph_real_t u_x = MATRIX(*res, u, 0); igraph_real_t u_y = MATRIX(*res, u, 1); - for (igraph_integer_t w = 0; w < no_nodes; w++) { + for (igraph_int_t w = 0; w < no_nodes; w++) { igraph_real_t w_x, w_y, d_ev; if (w == v || w == u) { continue; diff --git a/src/vendor/cigraph/src/layout/drl/drl_Node.h b/src/vendor/cigraph/src/layout/drl/drl_Node.h index 387bbb293c8..f7a6cceb01c 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_Node.h +++ b/src/vendor/cigraph/src/layout/drl/drl_Node.h @@ -48,7 +48,7 @@ class Node { public: bool fixed; // if true do not change the - igraph_integer_t id; + igraph_int_t id; // position of this node float x, y; @@ -57,7 +57,7 @@ class Node { public: - Node( igraph_integer_t node_id ) { + Node( igraph_int_t node_id ) { x = y = 0.0; fixed = false; id = node_id; } diff --git a/src/vendor/cigraph/src/layout/drl/drl_Node_3d.h b/src/vendor/cigraph/src/layout/drl/drl_Node_3d.h index 250e934a366..4be0eab9b46 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_Node_3d.h +++ b/src/vendor/cigraph/src/layout/drl/drl_Node_3d.h @@ -48,7 +48,7 @@ class Node { public: bool fixed; // if true do not change the - igraph_integer_t id; + igraph_int_t id; // position of this node float x, y, z; @@ -57,7 +57,7 @@ class Node { public: - Node( igraph_integer_t node_id ) { + Node( igraph_int_t node_id ) { x = y = z = 0.0; fixed = false; id = node_id; } diff --git a/src/vendor/cigraph/src/layout/drl/drl_graph.cpp b/src/vendor/cigraph/src/layout/drl/drl_graph.cpp index 1707163cdde..64028a6fc63 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_graph.cpp +++ b/src/vendor/cigraph/src/layout/drl/drl_graph.cpp @@ -172,11 +172,11 @@ graph::graph(const igraph_t *igraph, // scan .int file for node info highest_sim = 1.0; num_nodes = igraph_vcount(igraph); - igraph_integer_t no_of_edges = igraph_ecount(igraph); - for (igraph_integer_t i = 0; i < num_nodes; i++) { + igraph_int_t no_of_edges = igraph_ecount(igraph); + for (igraph_int_t i = 0; i < num_nodes; i++) { id_catalog[i] = 1; } - map::iterator cat_iter; + map::iterator cat_iter; for ( cat_iter = id_catalog.begin(); cat_iter != id_catalog.end(); cat_iter++) { cat_iter->second = cat_iter->first; @@ -191,9 +191,9 @@ graph::graph(const igraph_t *igraph, } // read .int file for graph info - igraph_integer_t node_1, node_2; + igraph_int_t node_1, node_2; igraph_real_t weight; - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { node_1 = IGRAPH_FROM(igraph, i); node_2 = IGRAPH_TO(igraph, i); weight = weights ? VECTOR(*weights)[i] : 1.0 ; @@ -392,17 +392,17 @@ void graph::init_parms ( int rand_seed, float edge_cut, float real_parm ) { cut_rate = ( cut_length_start - cut_length_end ) / 400.0; // finally set the number of iterations to leave .real coords fixed - igraph_integer_t full_comp_iters; + igraph_int_t full_comp_iters; full_comp_iters = liquid.iterations + expansion.iterations + cooldown.iterations + crunch.iterations + 3; // adjust real parm to iterations (do not enter simmer halfway) if ( real_parm < 0 ) { - real_iterations = (igraph_integer_t)real_parm; + real_iterations = (igraph_int_t)real_parm; } else if ( real_parm == 1) { real_iterations = full_comp_iters + simmer.iterations + 100; } else { - real_iterations = (igraph_integer_t)(real_parm * full_comp_iters); + real_iterations = (igraph_int_t)(real_parm * full_comp_iters); } tot_iterations = 0; @@ -486,8 +486,8 @@ void graph::init_parms(const igraph_layout_drl_options_t *options) { // } int graph::read_real(const igraph_matrix_t *real_mat) { - igraph_integer_t n = igraph_matrix_nrow(real_mat); - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t n = igraph_matrix_nrow(real_mat); + for (igraph_int_t i = 0; i < n; i++) { positions[id_catalog[i]].x = MATRIX(*real_mat, i, 0); positions[id_catalog[i]].y = MATRIX(*real_mat, i, 1); positions[id_catalog[i]].fixed = false; @@ -815,7 +815,7 @@ int graph::ReCompute( ) { void graph::update_nodes ( ) { - vector node_indices; // node list of nodes currently being updated + vector node_indices; // node list of nodes currently being updated float old_positions[2 * MAX_PROCS]; // positions before update float new_positions[2 * MAX_PROCS]; // positions after update @@ -828,9 +828,9 @@ void graph::update_nodes ( ) { // next we calculate the number of nodes there would be if the // num_nodes by num_procs schedule grid were perfectly square - igraph_integer_t square_num_nodes = (igraph_integer_t)(num_procs + num_procs * floor ((float)(num_nodes - 1) / (float)num_procs )); + igraph_int_t square_num_nodes = (igraph_int_t)(num_procs + num_procs * floor ((float)(num_nodes - 1) / (float)num_procs )); - for ( igraph_integer_t i = myid; i < square_num_nodes; i += num_procs ) { + for ( igraph_int_t i = myid; i < square_num_nodes; i += num_procs ) { // get old positions get_positions ( node_indices, old_positions ); @@ -890,7 +890,7 @@ void graph::update_nodes ( ) { // The get_positions function takes the node_indices list // and returns the corresponding positions in an array. -void graph::get_positions ( vector &node_indices, +void graph::get_positions ( vector &node_indices, float return_positions[2 * MAX_PROCS] ) { // fill positions @@ -906,7 +906,7 @@ void graph::get_positions ( vector &node_indices, // of active processes at this level for use by the random number // generators. -void graph::update_node_pos ( igraph_integer_t node_ind, +void graph::update_node_pos ( igraph_int_t node_ind, float old_positions[2 * MAX_PROCS], float new_positions[2 * MAX_PROCS] ) { @@ -978,7 +978,7 @@ void graph::update_node_pos ( igraph_integer_t node_ind, // updates the positions by subtracting the old positions and adding the // new positions to the density grid. -void graph::update_density ( vector &node_indices, +void graph::update_density ( vector &node_indices, float old_positions[2 * MAX_PROCS], float new_positions[2 * MAX_PROCS] ) { @@ -1004,13 +1004,13 @@ void graph::update_density ( vector &node_indices, * original code by B. Wylie. * *********************************************/ -float graph::Compute_Node_Energy( igraph_integer_t node_ind ) { +float graph::Compute_Node_Energy( igraph_int_t node_ind ) { /* Want to expand 4th power range of attraction */ float attraction_factor = attraction * attraction * attraction * attraction * 2e-2; - map ::iterator EI; + map ::iterator EI; float x_dis, y_dis; float energy_distance, weight; float node_energy = 0; @@ -1061,9 +1061,9 @@ float graph::Compute_Node_Energy( igraph_integer_t node_ind ) { * originally written by B. Wylie * *********************************************/ -void graph::Solve_Analytic( igraph_integer_t node_ind, float &pos_x, float &pos_y ) { +void graph::Solve_Analytic( igraph_int_t node_ind, float &pos_x, float &pos_y ) { - map ::iterator EI; + map ::iterator EI; float total_weight = 0; float x_dis, y_dis, x_cen = 0, y_cen = 0; float x = 0, y = 0, dis; @@ -1104,7 +1104,7 @@ void graph::Solve_Analytic( igraph_integer_t node_ind, float &pos_x, float &pos_ float num_connections = sqrt((double)neighbors[node_ind].size()); float maxLength = 0; - map::iterator maxIndex; + map::iterator maxIndex; // Go through nodes edges... cutting if necessary for (EI = maxIndex = neighbors[node_ind].begin(); @@ -1258,9 +1258,9 @@ igraph_error_t graph::draw_graph(igraph_matrix_t *res) { while (ReCompute()) { IGRAPH_ALLOW_INTERRUPTION(); } - igraph_integer_t n = positions.size(); + igraph_int_t n = positions.size(); IGRAPH_CHECK(igraph_matrix_resize(res, n, 2)); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { MATRIX(*res, i, 0) = positions[i].x; MATRIX(*res, i, 1) = positions[i].y; } diff --git a/src/vendor/cigraph/src/layout/drl/drl_graph.h b/src/vendor/cigraph/src/layout/drl/drl_graph.h index 3fc68337950..0ff95b5485c 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_graph.h +++ b/src/vendor/cigraph/src/layout/drl/drl_graph.h @@ -45,7 +45,7 @@ namespace drl { // layout schedule information struct layout_schedule { - igraph_integer_t iterations; + igraph_int_t iterations; float temperature; float attraction; float damping_mult; @@ -82,13 +82,13 @@ class graph { // Methods int ReCompute ( ); void update_nodes ( ); - float Compute_Node_Energy ( igraph_integer_t node_ind ); - void Solve_Analytic ( igraph_integer_t node_ind, float &pos_x, float &pos_y ); - void get_positions ( std::vector &node_indices, float return_positions[2 * MAX_PROCS] ); - void update_density ( std::vector &node_indices, + float Compute_Node_Energy ( igraph_int_t node_ind ); + void Solve_Analytic ( igraph_int_t node_ind, float &pos_x, float &pos_y ); + void get_positions ( std::vector &node_indices, float return_positions[2 * MAX_PROCS] ); + void update_density ( std::vector &node_indices, float old_positions[2 * MAX_PROCS], float new_positions[2 * MAX_PROCS] ); - void update_node_pos ( igraph_integer_t node_ind, + void update_node_pos ( igraph_int_t node_ind, float old_positions[2 * MAX_PROCS], float new_positions[2 * MAX_PROCS] ); @@ -96,10 +96,10 @@ class graph { int myid, num_procs; // graph decomposition information - igraph_integer_t num_nodes; // number of nodes in graph + igraph_int_t num_nodes; // number of nodes in graph float highest_sim; // highest sim for normalization - std::map id_catalog; // id_catalog[file id] = internal id - std::map > neighbors; // neighbors of nodes on this proc. + std::map id_catalog; // id_catalog[file id] = internal id + std::map > neighbors; // neighbors of nodes on this proc. // graph layout information std::vector positions; @@ -107,7 +107,7 @@ class graph { // original VxOrd information int STAGE; - igraph_integer_t iterations; + igraph_int_t iterations; float temperature, attraction, damping_mult; float min_edges, CUT_END, cut_length_end, cut_off_length, cut_rate; bool first_add, fine_first_add, fineDensity; @@ -123,9 +123,9 @@ class graph { time_t start_time, stop_time; // online clustering information - igraph_integer_t real_iterations; // number of iterations to hold .real input fixed - igraph_integer_t tot_iterations; - igraph_integer_t tot_expected_iterations; // for progress bar + igraph_int_t real_iterations; // number of iterations to hold .real input fixed + igraph_int_t tot_iterations; + igraph_int_t tot_expected_iterations; // for progress bar bool real_fixed; }; diff --git a/src/vendor/cigraph/src/layout/drl/drl_graph_3d.cpp b/src/vendor/cigraph/src/layout/drl/drl_graph_3d.cpp index b64fd957c5b..0600fc532e6 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_graph_3d.cpp +++ b/src/vendor/cigraph/src/layout/drl/drl_graph_3d.cpp @@ -95,11 +95,11 @@ graph::graph(const igraph_t *igraph, // scan .int file for node info highest_sim = 1.0; num_nodes = igraph_vcount(igraph); - igraph_integer_t no_of_edges = igraph_ecount(igraph); - for (igraph_integer_t i = 0; i < num_nodes; i++) { + igraph_int_t no_of_edges = igraph_ecount(igraph); + for (igraph_int_t i = 0; i < num_nodes; i++) { id_catalog[i] = 1; } - map< igraph_integer_t, igraph_integer_t>::iterator cat_iter; + map< igraph_int_t, igraph_int_t>::iterator cat_iter; for ( cat_iter = id_catalog.begin(); cat_iter != id_catalog.end(); cat_iter++) { cat_iter->second = cat_iter->first; @@ -114,9 +114,9 @@ graph::graph(const igraph_t *igraph, } // read .int file for graph info - igraph_integer_t node_1, node_2; + igraph_int_t node_1, node_2; igraph_real_t weight; - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { node_1 = IGRAPH_FROM(igraph, i); node_2 = IGRAPH_TO(igraph, i); weight = weights ? VECTOR(*weights)[i] : 1.0 ; @@ -153,7 +153,7 @@ void graph::init_parms ( int rand_seed, float edge_cut, float real_parm ) { cut_rate = ( cut_length_start - cut_length_end ) / 400.0; // finally set the number of iterations to leave .real coords fixed - igraph_integer_t full_comp_iters; + igraph_int_t full_comp_iters; full_comp_iters = liquid.iterations + expansion.iterations + cooldown.iterations + crunch.iterations + 3; @@ -198,8 +198,8 @@ void graph::init_parms(const igraph_layout_drl_options_t *options) { } int graph::read_real(const igraph_matrix_t *real_mat) { - igraph_integer_t n = igraph_matrix_nrow(real_mat); - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t n = igraph_matrix_nrow(real_mat); + for (igraph_int_t i = 0; i < n; i++) { positions[id_catalog[i]].x = MATRIX(*real_mat, i, 0); positions[id_catalog[i]].y = MATRIX(*real_mat, i, 1); positions[id_catalog[i]].z = MATRIX(*real_mat, i, 2); @@ -466,7 +466,7 @@ int graph::ReCompute( ) { void graph::update_nodes ( ) { - vector node_indices; // node list of nodes currently being updated + vector node_indices; // node list of nodes currently being updated float old_positions[2 * MAX_PROCS]; // positions before update float new_positions[2 * MAX_PROCS]; // positions after update @@ -479,9 +479,9 @@ void graph::update_nodes ( ) { // next we calculate the number of nodes there would be if the // num_nodes by num_procs schedule grid were perfectly square - igraph_integer_t square_num_nodes = (igraph_integer_t)(num_procs + num_procs * floor ((float)(num_nodes - 1) / (float)num_procs )); + igraph_int_t square_num_nodes = (igraph_int_t)(num_procs + num_procs * floor ((float)(num_nodes - 1) / (float)num_procs )); - for ( igraph_integer_t i = myid; i < square_num_nodes; i += num_procs ) { + for ( igraph_int_t i = myid; i < square_num_nodes; i += num_procs ) { // get old positions get_positions ( node_indices, old_positions ); @@ -541,7 +541,7 @@ void graph::update_nodes ( ) { // The get_positions function takes the node_indices list // and returns the corresponding positions in an array. -void graph::get_positions ( vector &node_indices, +void graph::get_positions ( vector &node_indices, float return_positions[3 * MAX_PROCS] ) { // fill positions @@ -558,7 +558,7 @@ void graph::get_positions ( vector &node_indices, // of active processes at this level for use by the random number // generators. -void graph::update_node_pos ( igraph_integer_t node_ind, +void graph::update_node_pos ( igraph_int_t node_ind, float old_positions[3 * MAX_PROCS], float new_positions[3 * MAX_PROCS] ) { @@ -636,7 +636,7 @@ void graph::update_node_pos ( igraph_integer_t node_ind, // updates the positions by subtracting the old positions and adding the // new positions to the density grid. -void graph::update_density ( vector &node_indices, +void graph::update_density ( vector &node_indices, float old_positions[3 * MAX_PROCS], float new_positions[3 * MAX_PROCS] ) { @@ -664,13 +664,13 @@ void graph::update_density ( vector &node_indices, * original code by B. Wylie. * *********************************************/ -float graph::Compute_Node_Energy( igraph_integer_t node_ind ) { +float graph::Compute_Node_Energy( igraph_int_t node_ind ) { /* Want to expand 4th power range of attraction */ float attraction_factor = attraction * attraction * attraction * attraction * 2e-2; - map ::iterator EI; + map ::iterator EI; float x_dis, y_dis, z_dis; float energy_distance, weight; float node_energy = 0; @@ -722,10 +722,10 @@ float graph::Compute_Node_Energy( igraph_integer_t node_ind ) { * originally written by B. Wylie * *********************************************/ -void graph::Solve_Analytic( igraph_integer_t node_ind, float &pos_x, float &pos_y, +void graph::Solve_Analytic( igraph_int_t node_ind, float &pos_x, float &pos_y, float &pos_z) { - map ::iterator EI; + map ::iterator EI; float total_weight = 0; float x_dis, y_dis, z_dis, x_cen = 0, y_cen = 0, z_cen = 0; float x = 0, y = 0, z = 0, dis; @@ -766,7 +766,7 @@ void graph::Solve_Analytic( igraph_integer_t node_ind, float &pos_x, float &pos_ float num_connections = (float)sqrt((float)neighbors[node_ind].size()); float maxLength = 0; - map::iterator maxIndex; + map::iterator maxIndex; // Go through nodes edges... cutting if necessary for (EI = maxIndex = neighbors[node_ind].begin(); diff --git a/src/vendor/cigraph/src/layout/drl/drl_graph_3d.h b/src/vendor/cigraph/src/layout/drl/drl_graph_3d.h index ffaad8e4835..18e7e39124b 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_graph_3d.h +++ b/src/vendor/cigraph/src/layout/drl/drl_graph_3d.h @@ -45,7 +45,7 @@ namespace drl3d { // layout schedule information struct layout_schedule { - igraph_integer_t iterations; + igraph_int_t iterations; float temperature; float attraction; float damping_mult; @@ -74,13 +74,13 @@ class graph { // Methods int ReCompute ( ); void update_nodes ( ); - float Compute_Node_Energy ( igraph_integer_t node_ind ); - void Solve_Analytic ( igraph_integer_t node_ind, float &pos_x, float &pos_y, float &pos_z ); - void get_positions ( std::vector &node_indices, float return_positions[3 * MAX_PROCS] ); - void update_density ( std::vector &node_indices, + float Compute_Node_Energy ( igraph_int_t node_ind ); + void Solve_Analytic ( igraph_int_t node_ind, float &pos_x, float &pos_y, float &pos_z ); + void get_positions ( std::vector &node_indices, float return_positions[3 * MAX_PROCS] ); + void update_density ( std::vector &node_indices, float old_positions[3 * MAX_PROCS], float new_positions[3 * MAX_PROCS] ); - void update_node_pos ( igraph_integer_t node_ind, + void update_node_pos ( igraph_int_t node_ind, float old_positions[3 * MAX_PROCS], float new_positions[3 * MAX_PROCS] ); @@ -88,10 +88,10 @@ class graph { int myid, num_procs; // graph decomposition information - igraph_integer_t num_nodes; // number of nodes in graph + igraph_int_t num_nodes; // number of nodes in graph float highest_sim; // highest sim for normalization - std::map id_catalog; // id_catalog[file id] = internal id - std::map > neighbors; // neighbors of nodes on this proc. + std::map id_catalog; // id_catalog[file id] = internal id + std::map > neighbors; // neighbors of nodes on this proc. // graph layout information std::vector positions; @@ -99,7 +99,7 @@ class graph { // original VxOrd information int STAGE; - igraph_integer_t iterations; + igraph_int_t iterations; float temperature, attraction, damping_mult; float min_edges, CUT_END, cut_length_end, cut_off_length, cut_rate; bool first_add, fine_first_add, fineDensity; @@ -115,9 +115,9 @@ class graph { time_t start_time, stop_time; // online clustering information - igraph_integer_t real_iterations; // number of iterations to hold .real input fixed - igraph_integer_t tot_iterations; - igraph_integer_t tot_expected_iterations; // for progress bar + igraph_int_t real_iterations; // number of iterations to hold .real input fixed + igraph_int_t tot_iterations; + igraph_int_t tot_expected_iterations; // for progress bar bool real_fixed; }; diff --git a/src/vendor/cigraph/src/layout/drl/drl_layout.cpp b/src/vendor/cigraph/src/layout/drl/drl_layout.cpp index 79c09474750..f998fc6aba9 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_layout.cpp +++ b/src/vendor/cigraph/src/layout/drl/drl_layout.cpp @@ -458,7 +458,7 @@ igraph_error_t igraph_layout_drl(const igraph_t *graph, igraph_matrix_t *res, } if (weights) { - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERROR("Length of weight vector does not match number of edges.", IGRAPH_EINVAL); } diff --git a/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp b/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp index 9400659e2b5..3f8008d0b5f 100644 --- a/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp +++ b/src/vendor/cigraph/src/layout/drl/drl_layout_3d.cpp @@ -109,7 +109,7 @@ igraph_error_t igraph_layout_drl_3d(const igraph_t *graph, igraph_matrix_t *res, } if (weights) { - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); if (igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERROR("Length of weight vector does not match number of edges.", IGRAPH_EINVAL); } diff --git a/src/vendor/cigraph/src/layout/fruchterman_reingold.c b/src/vendor/cigraph/src/layout/fruchterman_reingold.c index f4fb9637408..0b2abfa6a76 100644 --- a/src/vendor/cigraph/src/layout/fruchterman_reingold.c +++ b/src/vendor/cigraph/src/layout/fruchterman_reingold.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, - igraph_integer_t niter, + igraph_int_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, @@ -37,8 +37,8 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, const igraph_vector_t *miny, const igraph_vector_t *maxy) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_vector_t dispx, dispy; igraph_real_t temp = start_temp; igraph_real_t difftemp = start_temp / niter; @@ -57,7 +57,7 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&dispx, vcount); IGRAPH_VECTOR_INIT_FINALLY(&dispy, vcount); - for (igraph_integer_t i = 0; i < niter; i++) { + for (igraph_int_t i = 0; i < niter; i++) { IGRAPH_ALLOW_INTERRUPTION(); /* calculate repulsive forces, we have a special version @@ -65,8 +65,8 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, igraph_vector_null(&dispx); igraph_vector_null(&dispy); if (conn) { - for (igraph_integer_t v = 0; v < vcount; v++) { - for (igraph_integer_t u = v + 1; u < vcount; u++) { + for (igraph_int_t v = 0; v < vcount; v++) { + for (igraph_int_t u = v + 1; u < vcount; u++) { igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dlen = dx * dx + dy * dy; @@ -84,8 +84,8 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, } } } else { - for (igraph_integer_t v = 0; v < vcount; v++) { - for (igraph_integer_t u = v + 1; u < vcount; u++) { + for (igraph_int_t v = 0; v < vcount; v++) { + for (igraph_int_t u = v + 1; u < vcount; u++) { igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dlen, rdlen; @@ -108,10 +108,10 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, } /* calculate attractive forces */ - for (igraph_integer_t e = 0; e < ecount; e++) { + for (igraph_int_t e = 0; e < ecount; e++) { /* each edge is an ordered pair of vertices v and u */ - igraph_integer_t v = IGRAPH_FROM(graph, e); - igraph_integer_t u = IGRAPH_TO(graph, e); + igraph_int_t v = IGRAPH_FROM(graph, e); + igraph_int_t u = IGRAPH_TO(graph, e); igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t w = weight ? VECTOR(*weight)[e] : 1.0; @@ -124,7 +124,7 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, /* limit max displacement to temperature t and prevent from displacement outside frame */ - for (igraph_integer_t v = 0; v < vcount; v++) { + for (igraph_int_t v = 0; v < vcount; v++) { igraph_real_t dx = VECTOR(dispx)[v] + RNG_UNIF(-1e-9, 1e-9); igraph_real_t dy = VECTOR(dispy)[v] + RNG_UNIF(-1e-9, 1e-9); igraph_real_t displen = sqrt(dx * dx + dy * dy); @@ -165,13 +165,13 @@ static igraph_error_t igraph_layout_i_fr(const igraph_t *graph, static igraph_error_t igraph_layout_i_grid_fr( const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, - igraph_integer_t niter, igraph_real_t start_temp, + igraph_int_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); const igraph_real_t width = sqrt(vcount), height = width; igraph_2dgrid_t grid; igraph_vector_t dispx, dispy; @@ -190,15 +190,15 @@ static igraph_error_t igraph_layout_i_grid_fr( IGRAPH_FINALLY(igraph_2dgrid_destroy, &grid); /* place vertices on grid */ - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { igraph_2dgrid_add2(&grid, i); } IGRAPH_VECTOR_INIT_FINALLY(&dispx, vcount); IGRAPH_VECTOR_INIT_FINALLY(&dispy, vcount); - for (igraph_integer_t i = 0; i < niter; i++) { - igraph_integer_t v, u; + for (igraph_int_t i = 0; i < niter; i++) { + igraph_int_t v, u; IGRAPH_ALLOW_INTERRUPTION(); @@ -227,9 +227,9 @@ static igraph_error_t igraph_layout_i_grid_fr( } /* attraction */ - for (igraph_integer_t e = 0; e < ecount; e++) { - igraph_integer_t v = IGRAPH_FROM(graph, e); - igraph_integer_t u = IGRAPH_TO(graph, e); + for (igraph_int_t e = 0; e < ecount; e++) { + igraph_int_t v = IGRAPH_FROM(graph, e); + igraph_int_t u = IGRAPH_TO(graph, e); igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t w = weight ? VECTOR(*weight)[e] : 1.0; @@ -353,7 +353,7 @@ static igraph_error_t igraph_layout_i_grid_fr( igraph_error_t igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, - igraph_integer_t niter, + igraph_int_t niter, igraph_real_t start_temp, igraph_layout_grid_t grid, const igraph_vector_t *weights, @@ -362,8 +362,8 @@ igraph_error_t igraph_layout_fruchterman_reingold(const igraph_t *graph, const igraph_vector_t *miny, const igraph_vector_t *maxy) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); if (niter < 0) { IGRAPH_ERROR("Number of iterations must be non-negative in " @@ -471,7 +471,7 @@ igraph_error_t igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, - igraph_integer_t niter, + igraph_int_t niter, igraph_real_t start_temp, const igraph_vector_t *weights, const igraph_vector_t *minx, @@ -481,8 +481,8 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, const igraph_vector_t *minz, const igraph_vector_t *maxz) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_vector_t dispx, dispy, dispz; igraph_real_t temp = start_temp; igraph_real_t difftemp = start_temp / niter; @@ -548,7 +548,7 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&dispy, vcount); IGRAPH_VECTOR_INIT_FINALLY(&dispz, vcount); - for (igraph_integer_t i = 0; i < niter; i++) { + for (igraph_int_t i = 0; i < niter; i++) { IGRAPH_ALLOW_INTERRUPTION(); /* calculate repulsive forces, we have a special version @@ -557,8 +557,8 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, igraph_vector_null(&dispy); igraph_vector_null(&dispz); if (conn) { - for (igraph_integer_t v = 0; v < vcount; v++) { - for (igraph_integer_t u = v + 1; u < vcount; u++) { + for (igraph_int_t v = 0; v < vcount; v++) { + for (igraph_int_t u = v + 1; u < vcount; u++) { igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dz = MATRIX(*res, v, 2) - MATRIX(*res, u, 2); @@ -580,8 +580,8 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, } } } else { - for (igraph_integer_t v = 0; v < vcount; v++) { - for (igraph_integer_t u = v + 1; u < vcount; u++) { + for (igraph_int_t v = 0; v < vcount; v++) { + for (igraph_int_t u = v + 1; u < vcount; u++) { igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dz = MATRIX(*res, v, 2) - MATRIX(*res, u, 2); @@ -608,10 +608,10 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, } /* calculate attractive forces */ - for (igraph_integer_t e = 0; e < ecount; e++) { + for (igraph_int_t e = 0; e < ecount; e++) { /* each edges is an ordered pair of vertices v and u */ - igraph_integer_t v = IGRAPH_FROM(graph, e); - igraph_integer_t u = IGRAPH_TO(graph, e); + igraph_int_t v = IGRAPH_FROM(graph, e); + igraph_int_t u = IGRAPH_TO(graph, e); igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dz = MATRIX(*res, v, 2) - MATRIX(*res, u, 2); @@ -627,7 +627,7 @@ igraph_error_t igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, /* limit max displacement to temperature t and prevent from displacement outside frame */ - for (igraph_integer_t v = 0; v < vcount; v++) { + for (igraph_int_t v = 0; v < vcount; v++) { igraph_real_t dx = VECTOR(dispx)[v] + RNG_UNIF(-1e-9, 1e-9); igraph_real_t dy = VECTOR(dispy)[v] + RNG_UNIF(-1e-9, 1e-9); igraph_real_t dz = VECTOR(dispz)[v] + RNG_UNIF(-1e-9, 1e-9); diff --git a/src/vendor/cigraph/src/layout/gem.c b/src/vendor/cigraph/src/layout/gem.c index a2345d62d2b..866e5c6235a 100644 --- a/src/vendor/cigraph/src/layout/gem.c +++ b/src/vendor/cigraph/src/layout/gem.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -65,16 +65,16 @@ */ igraph_error_t igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, + igraph_bool_t use_seed, igraph_int_t maxiter, igraph_real_t temp_max, igraph_real_t temp_min, igraph_real_t temp_init) { - igraph_integer_t no_nodes = igraph_vcount(graph); + igraph_int_t no_nodes = igraph_vcount(graph); igraph_vector_int_t perm; igraph_vector_t impulse_x, impulse_y, temp, skew_gauge; - igraph_integer_t i; + igraph_int_t i; igraph_real_t temp_global; - igraph_integer_t perm_pointer = 0; + igraph_int_t perm_pointer = 0; igraph_real_t barycenter_x = 0, barycenter_y = 0; igraph_vector_t phi; igraph_vector_int_t neis; @@ -153,7 +153,7 @@ igraph_error_t igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, temp_global = temp_init * no_nodes; while (temp_global > temp_min * no_nodes && maxiter > 0) { - igraph_integer_t u, v, nlen, j; + igraph_int_t u, v, nlen, j; igraph_real_t px, py, pvx, pvy; IGRAPH_ALLOW_INTERRUPTION(); @@ -190,7 +190,7 @@ igraph_error_t igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, )); nlen = igraph_vector_int_size(&neis); for (j = 0; j < nlen; j++) { - igraph_integer_t u = VECTOR(neis)[j]; + igraph_int_t u = VECTOR(neis)[j]; igraph_real_t dx = MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy = MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dist2 = dx * dx + dy * dy; diff --git a/src/vendor/cigraph/src/layout/graphopt.c b/src/vendor/cigraph/src/layout/graphopt.c index b0b74b5a9f4..16e11b192a6 100644 --- a/src/vendor/cigraph/src/layout/graphopt.c +++ b/src/vendor/cigraph/src/layout/graphopt.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -31,7 +31,7 @@ static igraph_real_t igraph_i_distance_between( const igraph_matrix_t *c, - igraph_integer_t a, igraph_integer_t b); + igraph_int_t a, igraph_int_t b); static void igraph_i_determine_electric_axal_forces( const igraph_matrix_t *pos, @@ -39,14 +39,14 @@ static void igraph_i_determine_electric_axal_forces( igraph_real_t *y, igraph_real_t directed_force, igraph_real_t distance, - igraph_integer_t other_node, - igraph_integer_t this_node); + igraph_int_t other_node, + igraph_int_t this_node); static void igraph_i_apply_electrical_force( const igraph_matrix_t *pos, igraph_vector_t *pending_forces_x, igraph_vector_t *pending_forces_y, - igraph_integer_t other_node, igraph_integer_t this_node, + igraph_int_t other_node, igraph_int_t this_node, igraph_real_t node_charge, igraph_real_t distance); @@ -56,15 +56,15 @@ static void igraph_i_determine_spring_axal_forces( igraph_real_t directed_force, igraph_real_t distance, igraph_real_t spring_length, - igraph_integer_t other_node, - igraph_integer_t this_node); + igraph_int_t other_node, + igraph_int_t this_node); static void igraph_i_apply_spring_force( const igraph_matrix_t *pos, igraph_vector_t *pending_forces_x, igraph_vector_t *pending_forces_y, - igraph_integer_t other_node, - igraph_integer_t this_node, igraph_real_t spring_length, + igraph_int_t other_node, + igraph_int_t this_node, igraph_real_t spring_length, igraph_real_t spring_constant); static void igraph_i_move_nodes( @@ -76,7 +76,7 @@ static void igraph_i_move_nodes( static igraph_real_t igraph_i_distance_between( const igraph_matrix_t *c, - igraph_integer_t a, igraph_integer_t b) { + igraph_int_t a, igraph_int_t b) { igraph_real_t diffx = MATRIX(*c, a, 0) - MATRIX(*c, b, 0); igraph_real_t diffy = MATRIX(*c, a, 1) - MATRIX(*c, b, 1); return sqrt(diffx*diffx + diffy*diffy); @@ -87,8 +87,8 @@ static void igraph_i_determine_electric_axal_forces(const igraph_matrix_t *pos, igraph_real_t *y, igraph_real_t directed_force, igraph_real_t distance, - igraph_integer_t other_node, - igraph_integer_t this_node) { + igraph_int_t other_node, + igraph_int_t this_node) { // We know what the directed force is. We now need to translate it // into the appropriate x and y components. @@ -137,7 +137,7 @@ static void igraph_i_apply_electrical_force( const igraph_matrix_t *pos, igraph_vector_t *pending_forces_x, igraph_vector_t *pending_forces_y, - igraph_integer_t other_node, igraph_integer_t this_node, + igraph_int_t other_node, igraph_int_t this_node, igraph_real_t node_charge, igraph_real_t distance) { @@ -161,7 +161,7 @@ static void igraph_i_determine_spring_axal_forces( igraph_real_t directed_force, igraph_real_t distance, igraph_real_t spring_length, - igraph_integer_t other_node, igraph_integer_t this_node) { + igraph_int_t other_node, igraph_int_t this_node) { // if the spring is just the right size, the forces will be 0, so we can // skip the computation. @@ -196,8 +196,8 @@ static void igraph_i_apply_spring_force( const igraph_matrix_t *pos, igraph_vector_t *pending_forces_x, igraph_vector_t *pending_forces_y, - igraph_integer_t other_node, - igraph_integer_t this_node, igraph_real_t spring_length, + igraph_int_t other_node, + igraph_int_t this_node, igraph_real_t spring_length, igraph_real_t spring_constant) { // determined using Hooke's Law: @@ -258,7 +258,7 @@ static void igraph_i_move_nodes( // velocity = force / mass // displacement = force / mass - igraph_integer_t this_node, no_of_nodes = igraph_vector_size(pending_forces_x); + igraph_int_t this_node, no_of_nodes = igraph_vector_size(pending_forces_x); for (this_node = 0; this_node < no_of_nodes; this_node++) { @@ -339,23 +339,23 @@ static void igraph_i_move_nodes( * of edges. If \p node_charge is zero then it is only O(n|E|). */ igraph_error_t igraph_layout_graphopt(const igraph_t *graph, igraph_matrix_t *res, - igraph_integer_t niter, + igraph_int_t niter, igraph_real_t node_charge, igraph_real_t node_mass, igraph_real_t spring_length, igraph_real_t spring_constant, igraph_real_t max_sa_movement, igraph_bool_t use_seed) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_t pending_forces_x, pending_forces_y; /* Set a flag to calculate (or not) the electrical forces that the nodes */ /* apply on each other based on if both node types' charges are zero. */ igraph_bool_t apply_electric_charges = (node_charge != 0); - igraph_integer_t this_node, other_node, edge; + igraph_int_t this_node, other_node, edge; igraph_real_t distance; - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INIT_FINALLY(&pending_forces_x, no_of_nodes); IGRAPH_VECTOR_INIT_FINALLY(&pending_forces_y, no_of_nodes); @@ -414,8 +414,8 @@ igraph_error_t igraph_layout_graphopt(const igraph_t *graph, igraph_matrix_t *re // Apply force from springs for (edge = 0; edge < no_of_edges; edge++) { - igraph_integer_t tthis_node = IGRAPH_FROM(graph, edge); - igraph_integer_t oother_node = IGRAPH_TO(graph, edge); + igraph_int_t tthis_node = IGRAPH_FROM(graph, edge); + igraph_int_t oother_node = IGRAPH_TO(graph, edge); // Apply spring force on both nodes igraph_i_apply_spring_force(res, &pending_forces_x, &pending_forces_y, oother_node, tthis_node, spring_length, diff --git a/src/vendor/cigraph/src/layout/kamada_kawai.c b/src/vendor/cigraph/src/layout/kamada_kawai.c index 7b1012166b6..d7b7085f3d2 100644 --- a/src/vendor/cigraph/src/layout/kamada_kawai.c +++ b/src/vendor/cigraph/src/layout/kamada_kawai.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -103,19 +103,19 @@ */ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, + igraph_bool_t use_seed, igraph_int_t maxiter, igraph_real_t epsilon, igraph_real_t kkconst, const igraph_vector_t *weights, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy) { - igraph_integer_t vcount = igraph_vcount(graph); - igraph_integer_t ecount = igraph_ecount(graph); + igraph_int_t vcount = igraph_vcount(graph); + igraph_int_t ecount = igraph_ecount(graph); igraph_real_t L, L0 = sqrt(vcount); igraph_matrix_t dij, lij, kij; igraph_real_t max_dij; igraph_vector_t D1, D2; - igraph_integer_t m; + igraph_int_t m; if (maxiter < 0) { IGRAPH_ERROR("Number of iterations must be non-negative in " @@ -183,8 +183,8 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t /* Find largest finite distance */ max_dij = 0.0; - for (igraph_integer_t j = 0; j < vcount; j++) { - for (igraph_integer_t i = j + 1; i < vcount; i++) { + for (igraph_int_t j = 0; j < vcount; j++) { + for (igraph_int_t i = j + 1; i < vcount; i++) { if (!isfinite(MATRIX(dij, i, j))) { continue; } @@ -196,8 +196,8 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t /* Replace infinite distances by the largest finite distance, * effectively making the graph connected. */ - for (igraph_integer_t j = 0; j < vcount; j++) { - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t j = 0; j < vcount; j++) { + for (igraph_int_t i = 0; i < vcount; i++) { if (MATRIX(dij, i, j) > max_dij) { MATRIX(dij, i, j) = max_dij; } @@ -205,8 +205,8 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t } L = L0 / max_dij; - for (igraph_integer_t j = 0; j < vcount; j++) { - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t j = 0; j < vcount; j++) { + for (igraph_int_t i = 0; i < vcount; i++) { if (i == j) { continue; } @@ -219,7 +219,7 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t /* Initialize delta */ IGRAPH_VECTOR_INIT_FINALLY(&D1, vcount); IGRAPH_VECTOR_INIT_FINALLY(&D2, vcount); - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { for (m = 0; m < vcount; m++) { igraph_real_t dx, dy, mi_dist; if (i == m) { @@ -233,7 +233,7 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t } } - for (igraph_integer_t j = 0; j < maxiter; j++) { + for (igraph_int_t j = 0; j < maxiter; j++) { igraph_real_t myD1, myD2, A, B, C; igraph_real_t max_delta, delta_x, delta_y; igraph_real_t old_x, old_y, new_x, new_y; @@ -244,7 +244,7 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t /* Select maximal delta */ m = 0; max_delta = -1; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { igraph_real_t delta = (VECTOR(D1)[i] * VECTOR(D1)[i] + VECTOR(D2)[i] * VECTOR(D2)[i]); if (delta > max_delta) { @@ -258,7 +258,7 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t old_y = MATRIX(*res, m, 1); /* Calculate D1 and D2, A, B, C */ - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { igraph_real_t dx, dy, dist, den; if (i == m) { continue; @@ -313,7 +313,7 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t /* Update delta, only with/for the affected node */ VECTOR(D1)[m] = VECTOR(D2)[m] = 0.0; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { igraph_real_t old_dx, old_dy, new_dx, new_dy, new_mi_dist, old_mi_dist; if (i == m) { continue; @@ -412,20 +412,20 @@ igraph_error_t igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t */ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matrix_t *res, - igraph_bool_t use_seed, igraph_integer_t maxiter, + igraph_bool_t use_seed, igraph_int_t maxiter, igraph_real_t epsilon, igraph_real_t kkconst, const igraph_vector_t *weights, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy, const igraph_vector_t *minz, const igraph_vector_t *maxz) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_real_t L, L0 = sqrt(vcount); igraph_matrix_t dij, lij, kij; igraph_real_t max_dij; igraph_vector_t D1, D2, D3; - igraph_integer_t m; + igraph_int_t m; if (maxiter < 0) { IGRAPH_ERROR("Number of iterations must be non-negative in " @@ -499,8 +499,8 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri igraph_vss_all(), weights, IGRAPH_ALL)); max_dij = 0.0; - for (igraph_integer_t i = 0; i < vcount; i++) { - for (igraph_integer_t j = i + 1; j < vcount; j++) { + for (igraph_int_t i = 0; i < vcount; i++) { + for (igraph_int_t j = i + 1; j < vcount; j++) { if (!isfinite(MATRIX(dij, i, j))) { continue; } @@ -509,8 +509,8 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri } } } - for (igraph_integer_t i = 0; i < vcount; i++) { - for (igraph_integer_t j = 0; j < vcount; j++) { + for (igraph_int_t i = 0; i < vcount; i++) { + for (igraph_int_t j = 0; j < vcount; j++) { if (MATRIX(dij, i, j) > max_dij) { MATRIX(dij, i, j) = max_dij; } @@ -518,8 +518,8 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri } L = L0 / max_dij; - for (igraph_integer_t i = 0; i < vcount; i++) { - for (igraph_integer_t j = 0; j < vcount; j++) { + for (igraph_int_t i = 0; i < vcount; i++) { + for (igraph_int_t j = 0; j < vcount; j++) { igraph_real_t tmp = MATRIX(dij, i, j) * MATRIX(dij, i, j); if (i == j) { continue; @@ -536,7 +536,7 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri for (m = 0; m < vcount; m++) { igraph_real_t dx, dy, dz, mi_dist; igraph_real_t myD1 = 0.0, myD2 = 0.0, myD3 = 0.0; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { if (i == m) { continue; } @@ -553,7 +553,7 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri VECTOR(D3)[m] = myD3; } - for (igraph_integer_t j = 0; j < maxiter; j++) { + for (igraph_int_t j = 0; j < maxiter; j++) { igraph_real_t Ax = 0.0, Ay = 0.0, Az = 0.0; igraph_real_t Axx = 0.0, Axy = 0.0, Axz = 0.0, Ayy = 0.0, Ayz = 0.0, Azz = 0.0; @@ -564,7 +564,7 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri /* Select maximal delta */ m = 0; max_delta = -1; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { igraph_real_t delta = (VECTOR(D1)[i] * VECTOR(D1)[i] + VECTOR(D2)[i] * VECTOR(D2)[i] + VECTOR(D3)[i] * VECTOR(D3)[i]); @@ -580,7 +580,7 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri old_z = MATRIX(*res, m, 2); /* Calculate D1, D2 and D3, and other coefficients */ - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { igraph_real_t dx, dy, dz, dist, den, k_mi, l_mi; if (i == m) { continue; @@ -646,7 +646,7 @@ igraph_error_t igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matri /* Update delta, only with/for the affected node */ VECTOR(D1)[m] = VECTOR(D2)[m] = VECTOR(D3)[m] = 0.0; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { igraph_real_t old_dx, old_dy, old_dz, old_mi_dist, new_dx, new_dy, new_dz, new_mi_dist; if (i == m) { continue; diff --git a/src/vendor/cigraph/src/layout/large_graph.c b/src/vendor/cigraph/src/layout/large_graph.c index 756186f4c92..27ae2ee9291 100644 --- a/src/vendor/cigraph/src/layout/large_graph.c +++ b/src/vendor/cigraph/src/layout/large_graph.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -86,16 +86,16 @@ static void igraph_i_norm2d(igraph_real_t *x, igraph_real_t *y) { */ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, - igraph_integer_t maxit, igraph_real_t maxdelta, + igraph_int_t maxit, igraph_real_t maxdelta, igraph_real_t area, igraph_real_t coolexp, igraph_real_t repulserad, igraph_real_t cellsize, - igraph_integer_t proot) { + igraph_int_t proot) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t root; - igraph_integer_t no_of_layers, actlayer = 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t root; + igraph_int_t no_of_layers, actlayer = 0; igraph_vector_int_t vids; igraph_vector_int_t layers; igraph_vector_int_t parents; @@ -201,15 +201,15 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, for (actlayer = 1; actlayer < no_of_layers; actlayer++) { igraph_real_t c = 1; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_real_t massx, massy; igraph_real_t px, py; igraph_real_t sx, sy; - igraph_integer_t it = 0; + igraph_int_t it = 0; igraph_real_t epsilon = 10e-6; igraph_real_t maxchange = epsilon + 1; - /* igraph_integer_t pairs; */ + /* igraph_int_t pairs; */ igraph_real_t sconst = sqrt(area / M_PI) / H_n; igraph_2dgrid_iterator_t vidit; @@ -223,8 +223,8 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, for (i = VECTOR(layers)[actlayer - 1]; i < VECTOR(layers)[actlayer]; i++) { - igraph_integer_t vid = VECTOR(vids)[i]; - igraph_integer_t par = VECTOR(parents)[vid]; + igraph_int_t vid = VECTOR(vids)[i]; + igraph_int_t par = VECTOR(parents)[vid]; if (par < 0) { if (par == -1) { @@ -271,16 +271,16 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, for (j = VECTOR(layers)[actlayer]; j < VECTOR(layers)[actlayer + 1]; j++) { - igraph_integer_t vid = VECTOR(vids)[j]; - igraph_integer_t k; + igraph_int_t vid = VECTOR(vids)[j]; + igraph_int_t k; IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_incident(graph, &eids, vid, IGRAPH_ALL, IGRAPH_LOOPS)); for (k = 0; k < igraph_vector_int_size(&eids); k++) { - igraph_integer_t eid = VECTOR(eids)[k]; - igraph_integer_t from = IGRAPH_FROM(graph, eid), to = IGRAPH_TO(graph, eid); + igraph_int_t eid = VECTOR(eids)[k]; + igraph_int_t from = IGRAPH_FROM(graph, eid), to = IGRAPH_TO(graph, eid); if ((from != vid && igraph_2dgrid_in(&grid, from)) || (to != vid && igraph_2dgrid_in(&grid, to))) { - igraph_vector_int_push_back(&edges, eid); + igraph_vector_int_push_back(&edges, eid); /* reserved */ } } } @@ -291,9 +291,9 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, maxchange = epsilon + 1; while (it < maxit && maxchange > epsilon) { - igraph_integer_t jj; + igraph_int_t jj; igraph_real_t t = maxdelta * pow((maxit - it) / (igraph_real_t) maxit, coolexp); - igraph_integer_t vid, nei; + igraph_int_t vid, nei; IGRAPH_PROGRESS("Large graph layout", 100.0 * ((actlayer - 1.0) / (no_of_layers - 1.0) + (it) / (maxit * (no_of_layers - 1.0))), @@ -306,8 +306,8 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, /* attractive "forces" along the edges */ for (jj = 0; jj < igraph_vector_int_size(&edges); jj++) { - igraph_integer_t from = IGRAPH_FROM(graph, VECTOR(edges)[jj]); - igraph_integer_t to = IGRAPH_TO(graph, VECTOR(edges)[jj]); + igraph_int_t from = IGRAPH_FROM(graph, VECTOR(edges)[jj]); + igraph_int_t to = IGRAPH_TO(graph, VECTOR(edges)[jj]); igraph_real_t xd, yd, dist, force; IGRAPH_ALLOW_INTERRUPTION(); xd = MATRIX(*res, from, 0) - MATRIX(*res, to, 0); @@ -353,7 +353,7 @@ igraph_error_t igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res, /* apply the changes */ for (jj = 0; jj < VECTOR(layers)[actlayer + 1]; jj++) { - igraph_integer_t vvid = VECTOR(vids)[jj]; + igraph_int_t vvid = VECTOR(vids)[jj]; igraph_real_t fx = VECTOR(forcex)[vvid]; igraph_real_t fy = VECTOR(forcey)[vvid]; igraph_real_t ded = sqrt(fx*fx + fy*fy); diff --git a/src/vendor/cigraph/src/layout/layout_bipartite.c b/src/vendor/cigraph/src/layout/layout_bipartite.c index 59de88917f3..6e92102e0f6 100644 --- a/src/vendor/cigraph/src/layout/layout_bipartite.c +++ b/src/vendor/cigraph/src/layout/layout_bipartite.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -50,9 +50,9 @@ igraph_error_t igraph_layout_bipartite(const igraph_t *graph, const igraph_vector_bool_t *types, igraph_matrix_t *res, igraph_real_t hgap, - igraph_real_t vgap, igraph_integer_t maxiter) { + igraph_real_t vgap, igraph_int_t maxiter) { - igraph_integer_t i, no_of_nodes = igraph_vcount(graph); + igraph_int_t i, no_of_nodes = igraph_vcount(graph); igraph_vector_int_t layers; if (igraph_vector_bool_size(types) != no_of_nodes) { @@ -68,9 +68,8 @@ igraph_error_t igraph_layout_bipartite(const igraph_t *graph, VECTOR(layers)[i] = VECTOR(*types)[i] ? 0 : 1; } - IGRAPH_CHECK(igraph_layout_sugiyama(graph, res, /*extd_graph=*/ 0, - /*extd_to_orig_eids=*/ 0, &layers, hgap, - vgap, maxiter, /*weights=*/ 0)); + IGRAPH_CHECK(igraph_layout_sugiyama(graph, res, /* routing= */ 0, + &layers, hgap, vgap, maxiter, /* weights= */ 0)); igraph_vector_int_destroy(&layers); IGRAPH_FINALLY_CLEAN(1); diff --git a/src/vendor/cigraph/src/layout/layout_grid.c b/src/vendor/cigraph/src/layout/layout_grid.c index d8edad23dea..ab35e0c2a07 100644 --- a/src/vendor/cigraph/src/layout/layout_grid.c +++ b/src/vendor/cigraph/src/layout/layout_grid.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -39,8 +39,8 @@ * * Time complexity: O(|V|), the number of vertices. */ -igraph_error_t igraph_layout_grid(const igraph_t *graph, igraph_matrix_t *res, igraph_integer_t width) { - igraph_integer_t i, no_of_nodes = igraph_vcount(graph); +igraph_error_t igraph_layout_grid(const igraph_t *graph, igraph_matrix_t *res, igraph_int_t width) { + igraph_int_t i, no_of_nodes = igraph_vcount(graph); igraph_real_t x, y; IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2)); @@ -80,8 +80,8 @@ igraph_error_t igraph_layout_grid(const igraph_t *graph, igraph_matrix_t *res, i * Time complexity: O(|V|), the number of vertices. */ igraph_error_t igraph_layout_grid_3d(const igraph_t *graph, igraph_matrix_t *res, - igraph_integer_t width, igraph_integer_t height) { - igraph_integer_t i, no_of_nodes = igraph_vcount(graph); + igraph_int_t width, igraph_int_t height) { + igraph_int_t i, no_of_nodes = igraph_vcount(graph); igraph_real_t x, y, z; IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3)); diff --git a/src/vendor/cigraph/src/layout/layout_internal.h b/src/vendor/cigraph/src/layout/layout_internal.h index d68c97e6e80..72aeaae5be3 100644 --- a/src/vendor/cigraph/src/layout/layout_internal.h +++ b/src/vendor/cigraph/src/layout/layout_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -33,7 +33,7 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_layout_merge_dla(igraph_i_layout_mergegrid_t *grid, - igraph_integer_t actg, igraph_real_t *x, igraph_real_t *y, igraph_real_t r, + igraph_int_t actg, igraph_real_t *x, igraph_real_t *y, igraph_real_t r, igraph_real_t cx, igraph_real_t cy, igraph_real_t startr, igraph_real_t killr); diff --git a/src/vendor/cigraph/src/layout/layout_random.c b/src/vendor/cigraph/src/layout/layout_random.c index 45fd0e1f7d4..499b103826e 100644 --- a/src/vendor/cigraph/src/layout/layout_random.c +++ b/src/vendor/cigraph/src/layout/layout_random.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,27 +29,28 @@ /** * \ingroup layout * \function igraph_layout_random - * \brief Places the vertices uniform randomly on a plane. + * \brief Places the vertices uniformly randomly within a square. + * + * Vertex coordinates range from -1 to 1, and are placed in two columns + * of a matrix, with a row for each vertex. * * \param graph Pointer to an initialized graph object. * \param res Pointer to an initialized matrix object. This will * contain the result and will be resized as needed. - * \return Error code. The current implementation always returns with - * success. + * \return Error code. * - * Time complexity: O(|V|), the - * number of vertices. + * Time complexity: O(|V|), the number of vertices. */ igraph_error_t igraph_layout_random(const igraph_t *graph, igraph_matrix_t *res) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i; + const igraph_int_t vcount = igraph_vcount(graph); - IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2)); + IGRAPH_CHECK(igraph_matrix_resize(res, vcount, 2)); - for (i = 0; i < no_of_nodes; i++) { - MATRIX(*res, i, 0) = RNG_UNIF(-1, 1); - MATRIX(*res, i, 1) = RNG_UNIF(-1, 1); + for (igraph_int_t j = 0; j < 2; j++) { + for (igraph_int_t i = 0; i < vcount; i++) { + MATRIX(*res, i, j) = RNG_UNIF(-1, 1); + } } return IGRAPH_SUCCESS; @@ -57,17 +58,15 @@ igraph_error_t igraph_layout_random(const igraph_t *graph, igraph_matrix_t *res) /** * \function igraph_layout_random_3d - * \brief Places the vertices uniform randomly in a cube. + * \brief Places the vertices uniformly randomly in a cube. * - * - * Vertex coordinates range from -1 to 1, and are placed in 3 columns + * Vertex coordinates range from -1 to 1, and are placed in three columns * of a matrix, with a row for each vertex. * * \param graph The graph to place. * \param res Pointer to an initialized matrix object. It will be * resized to hold the result. - * \return Error code. The current implementation always returns with - * success. + * \return Error code. * * Added in version 0.2. * @@ -75,15 +74,14 @@ igraph_error_t igraph_layout_random(const igraph_t *graph, igraph_matrix_t *res) */ igraph_error_t igraph_layout_random_3d(const igraph_t *graph, igraph_matrix_t *res) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i; + const igraph_int_t vcount = igraph_vcount(graph); - IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3)); + IGRAPH_CHECK(igraph_matrix_resize(res, vcount, 3)); - for (i = 0; i < no_of_nodes; i++) { - MATRIX(*res, i, 0) = RNG_UNIF(-1, 1); - MATRIX(*res, i, 1) = RNG_UNIF(-1, 1); - MATRIX(*res, i, 2) = RNG_UNIF(-1, 1); + for (igraph_int_t j = 0; j < 3; j++) { + for (igraph_int_t i = 0; i < vcount; i++) { + MATRIX(*res, i, j) = RNG_UNIF(-1, 1); + } } return IGRAPH_SUCCESS; @@ -99,7 +97,7 @@ igraph_error_t igraph_i_layout_random_bounded( const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy) { - const igraph_integer_t no_nodes = igraph_vcount(graph); + const igraph_int_t no_nodes = igraph_vcount(graph); const igraph_real_t width = sqrt(no_nodes), height = width; igraph_real_t dminx = -width/2, dmaxx = width/2, @@ -145,7 +143,7 @@ igraph_error_t igraph_i_layout_random_bounded( } IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2)); - for (igraph_integer_t i = 0; i < no_nodes; i++) { + for (igraph_int_t i = 0; i < no_nodes; i++) { igraph_real_t x1 = minx ? VECTOR(*minx)[i] : dminx; igraph_real_t x2 = maxx ? VECTOR(*maxx)[i] : dmaxx; igraph_real_t y1 = miny ? VECTOR(*miny)[i] : dminy; @@ -175,7 +173,7 @@ igraph_error_t igraph_i_layout_random_bounded_3d( const igraph_vector_t *miny, const igraph_vector_t *maxy, const igraph_vector_t *minz, const igraph_vector_t *maxz) { - const igraph_integer_t no_nodes = igraph_vcount(graph); + const igraph_int_t no_nodes = igraph_vcount(graph); const igraph_real_t width = sqrt(no_nodes), height = width, depth = width; igraph_real_t dminx = -width/2, dmaxx = width/2, @@ -240,7 +238,7 @@ igraph_error_t igraph_i_layout_random_bounded_3d( } IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 3)); - for (igraph_integer_t i = 0; i < no_nodes; i++) { + for (igraph_int_t i = 0; i < no_nodes; i++) { igraph_real_t x1 = minx ? VECTOR(*minx)[i] : dminx; igraph_real_t x2 = maxx ? VECTOR(*maxx)[i] : dmaxx; igraph_real_t y1 = miny ? VECTOR(*miny)[i] : dminy; diff --git a/src/vendor/cigraph/src/layout/mds.c b/src/vendor/cigraph/src/layout/mds.c index d26eef3d22e..5cdc87cfb62 100644 --- a/src/vendor/cigraph/src/layout/mds.c +++ b/src/vendor/cigraph/src/layout/mds.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -37,7 +37,7 @@ static igraph_error_t igraph_i_layout_mds_step(igraph_real_t *to, const igraph_r int n, void *extra); static igraph_error_t igraph_i_layout_mds_single(const igraph_t* graph, igraph_matrix_t *res, - igraph_matrix_t *dist, igraph_integer_t dim); + igraph_matrix_t *dist, igraph_int_t dim); static igraph_error_t igraph_i_layout_mds_step(igraph_real_t *to, const igraph_real_t *from, int n, void *extra) { @@ -50,14 +50,14 @@ static igraph_error_t igraph_i_layout_mds_step(igraph_real_t *to, const igraph_r /* MDS layout for a connected graph, with no error checking on the * input parameters. The distance matrix will be modified in-place. */ igraph_error_t igraph_i_layout_mds_single(const igraph_t* graph, igraph_matrix_t *res, - igraph_matrix_t *dist, igraph_integer_t dim) { + igraph_matrix_t *dist, igraph_int_t dim) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t nev = dim; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t nev = dim; igraph_matrix_t vectors; igraph_vector_t values, row_means; igraph_real_t grand_mean; - igraph_integer_t i, j, k; + igraph_int_t i, j, k; igraph_eigen_which_t which; if (no_of_nodes > INT_MAX) { @@ -186,9 +186,9 @@ igraph_error_t igraph_i_layout_mds_single(const igraph_t* graph, igraph_matrix_t */ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, - const igraph_matrix_t *dist, igraph_integer_t dim) { + const igraph_matrix_t *dist, igraph_int_t dim) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_matrix_t m; igraph_bool_t conn; @@ -215,7 +215,7 @@ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, IGRAPH_CHECK(igraph_matrix_init_copy(&m, dist)); IGRAPH_FINALLY(igraph_matrix_destroy, &m); /* Make sure that the diagonal contains zeroes only */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { MATRIX(m, i, i) = 0.0; } } @@ -234,7 +234,7 @@ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, igraph_matrix_t layout; igraph_matrix_t dist_submatrix; igraph_bitset_t seen_vertices; - igraph_integer_t n, processed_vertex_count = 0; + igraph_int_t n, processed_vertex_count = 0; IGRAPH_VECTOR_INT_INIT_FINALLY(&comp, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&vertex_order, no_of_nodes); @@ -247,7 +247,7 @@ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, IGRAPH_BITSET_INIT_FINALLY(&seen_vertices, no_of_nodes); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (IGRAPH_BIT_TEST(seen_vertices, i)) { continue; } @@ -269,7 +269,7 @@ igraph_error_t igraph_layout_mds(const igraph_t *graph, igraph_matrix_t *res, IGRAPH_FINALLY_CLEAN(1); /* Mark all the vertices in the component as visited */ n = igraph_vector_int_size(&comp); - for (igraph_integer_t j = 0; j < n; j++) { + for (igraph_int_t j = 0; j < n; j++) { IGRAPH_BIT_SET(seen_vertices, VECTOR(comp)[j]); VECTOR(vertex_order)[VECTOR(comp)[j]] = processed_vertex_count++; } diff --git a/src/vendor/cigraph/src/layout/merge_dla.c b/src/vendor/cigraph/src/layout/merge_dla.c index cedf495fce6..93a0287f8bd 100644 --- a/src/vendor/cigraph/src/layout/merge_dla.c +++ b/src/vendor/cigraph/src/layout/merge_dla.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -30,13 +30,13 @@ #include "layout/layout_internal.h" static igraph_error_t vector_order(igraph_vector_t *v) { - const igraph_integer_t n = igraph_vector_size(v); + const igraph_int_t n = igraph_vector_size(v); igraph_vector_int_t ind; IGRAPH_VECTOR_INT_INIT_FINALLY(&ind, n); IGRAPH_CHECK(igraph_vector_sort_ind(v, &ind, IGRAPH_DESCENDING)); - for (igraph_integer_t i=0; i < n; i++) { + for (igraph_int_t i=0; i < n; i++) { VECTOR(*v)[i] = VECTOR(ind)[i]; } @@ -72,19 +72,19 @@ igraph_error_t igraph_layout_merge_dla( const igraph_vector_ptr_t *thegraphs, const igraph_matrix_list_t *coords, igraph_matrix_t *res ) { - igraph_integer_t coords_len = igraph_matrix_list_size(coords); + igraph_int_t coords_len = igraph_matrix_list_size(coords); igraph_vector_t sizes; igraph_vector_t x, y, r; igraph_vector_t nx, ny, nr; - igraph_integer_t allnodes = 0; - igraph_integer_t i, j; - igraph_integer_t actg; + igraph_int_t allnodes = 0; + igraph_int_t i, j; + igraph_int_t actg; igraph_i_layout_mergegrid_t grid; - igraph_integer_t jpos = 0; + igraph_int_t jpos = 0; igraph_real_t minx, maxx, miny, maxy; igraph_real_t area = 0; igraph_real_t maxr = 0; - igraph_integer_t respos; + igraph_int_t respos; /* Graphs are currently not used, only the coordinates */ IGRAPH_UNUSED(thegraphs); @@ -99,7 +99,7 @@ igraph_error_t igraph_layout_merge_dla( for (i = 0; i < coords_len; i++) { igraph_matrix_t *mat = igraph_matrix_list_get_ptr(coords, i); - igraph_integer_t size = igraph_matrix_nrow(mat); + igraph_int_t size = igraph_matrix_nrow(mat); if (igraph_matrix_ncol(mat) != 2) { IGRAPH_ERROR("igraph_layout_merge_dla works for 2D layouts only", @@ -160,7 +160,7 @@ igraph_error_t igraph_layout_merge_dla( respos = 0; for (i = 0; i < coords_len; i++) { igraph_matrix_t *mat = igraph_matrix_list_get_ptr(coords, i); - igraph_integer_t size = igraph_matrix_nrow(mat); + igraph_int_t size = igraph_matrix_nrow(mat); igraph_real_t xx = VECTOR(x)[i]; igraph_real_t yy = VECTOR(y)[i]; igraph_real_t rr = VECTOR(r)[i] / VECTOR(nr)[i]; @@ -192,8 +192,8 @@ igraph_error_t igraph_layout_merge_dla( igraph_error_t igraph_i_layout_sphere_2d(igraph_matrix_t *coords, igraph_real_t *x, igraph_real_t *y, igraph_real_t *r) { - igraph_integer_t nodes = igraph_matrix_nrow(coords); - igraph_integer_t i; + igraph_int_t nodes = igraph_matrix_nrow(coords); + igraph_int_t i; igraph_real_t xmin, xmax, ymin, ymax; xmin = xmax = MATRIX(*coords, 0, 0); @@ -224,8 +224,8 @@ igraph_error_t igraph_i_layout_sphere_2d(igraph_matrix_t *coords, igraph_error_t igraph_i_layout_sphere_3d(igraph_matrix_t *coords, igraph_real_t *x, igraph_real_t *y, igraph_real_t *z, igraph_real_t *r) { - igraph_integer_t nodes = igraph_matrix_nrow(coords); - igraph_integer_t i; + igraph_int_t nodes = igraph_matrix_nrow(coords); + igraph_int_t i; igraph_real_t xmin, xmax, ymin, ymax, zmin, zmax; xmin = xmax = MATRIX(*coords, 0, 0); @@ -265,10 +265,10 @@ igraph_error_t igraph_i_layout_sphere_3d(igraph_matrix_t *coords, #define DIST(x,y) (sqrt(pow((x)-cx,2)+pow((y)-cy,2))) igraph_error_t igraph_i_layout_merge_dla(igraph_i_layout_mergegrid_t *grid, - igraph_integer_t actg, igraph_real_t *x, igraph_real_t *y, igraph_real_t r, + igraph_int_t actg, igraph_real_t *x, igraph_real_t *y, igraph_real_t r, igraph_real_t cx, igraph_real_t cy, igraph_real_t startr, igraph_real_t killr) { - igraph_integer_t sp = -1; + igraph_int_t sp = -1; igraph_real_t angle, len; /* The graph is not used, only its coordinates */ diff --git a/src/vendor/cigraph/src/layout/merge_grid.c b/src/vendor/cigraph/src/layout/merge_grid.c index a037a111a80..b56f38a4ac9 100644 --- a/src/vendor/cigraph/src/layout/merge_grid.c +++ b/src/vendor/cigraph/src/layout/merge_grid.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -23,7 +23,7 @@ static igraph_error_t igraph_i_layout_mergegrid_which(igraph_i_layout_mergegrid_t *grid, igraph_real_t xc, igraph_real_t yc, - igraph_integer_t *x, igraph_integer_t *y) { + igraph_int_t *x, igraph_int_t *y) { if (xc <= grid->minx) { *x = 0; } else if (xc >= grid->maxx) { @@ -44,8 +44,8 @@ static igraph_error_t igraph_i_layout_mergegrid_which(igraph_i_layout_mergegrid_ } igraph_error_t igraph_i_layout_mergegrid_init(igraph_i_layout_mergegrid_t *grid, - igraph_real_t minx, igraph_real_t maxx, igraph_integer_t stepsx, - igraph_real_t miny, igraph_real_t maxy, igraph_integer_t stepsy) { + igraph_real_t minx, igraph_real_t maxx, igraph_int_t stepsx, + igraph_real_t miny, igraph_real_t maxy, igraph_int_t stepsy) { grid->minx = minx; grid->maxx = maxx; grid->stepsx = stepsx; @@ -55,7 +55,7 @@ igraph_error_t igraph_i_layout_mergegrid_init(igraph_i_layout_mergegrid_t *grid, grid->stepsy = stepsy; grid->deltay = (maxy - miny) / stepsy; - grid->data = IGRAPH_CALLOC(stepsx * stepsy, igraph_integer_t); + grid->data = IGRAPH_CALLOC(stepsx * stepsy, igraph_int_t); if (grid->data == 0) { IGRAPH_ERROR("Cannot create grid", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -71,9 +71,9 @@ void igraph_i_layout_mergegrid_destroy(igraph_i_layout_mergegrid_t *grid) { igraph_error_t igraph_i_layout_merge_place_sphere(igraph_i_layout_mergegrid_t *grid, igraph_real_t x, igraph_real_t y, igraph_real_t r, - igraph_integer_t id) { - igraph_integer_t cx, cy; - igraph_integer_t i, j; + igraph_int_t id) { + igraph_int_t cx, cy; + igraph_int_t i, j; igraph_i_layout_mergegrid_which(grid, x, y, &cx, &cy); @@ -124,10 +124,10 @@ igraph_error_t igraph_i_layout_merge_place_sphere(igraph_i_layout_mergegrid_t *g return IGRAPH_SUCCESS; } -igraph_integer_t igraph_i_layout_mergegrid_get(igraph_i_layout_mergegrid_t *grid, +igraph_int_t igraph_i_layout_mergegrid_get(igraph_i_layout_mergegrid_t *grid, igraph_real_t x, igraph_real_t y) { - igraph_integer_t cx, cy; - igraph_integer_t res; + igraph_int_t cx, cy; + igraph_int_t res; if (x <= grid->minx || x >= grid->maxx || y <= grid->miny || y >= grid->maxy) { @@ -142,11 +142,11 @@ igraph_integer_t igraph_i_layout_mergegrid_get(igraph_i_layout_mergegrid_t *grid #define DIST2(x2,y2) (sqrt(pow(x-(x2),2)+pow(y-(y2), 2))) -igraph_integer_t igraph_i_layout_mergegrid_get_sphere(igraph_i_layout_mergegrid_t *grid, +igraph_int_t igraph_i_layout_mergegrid_get_sphere(igraph_i_layout_mergegrid_t *grid, igraph_real_t x, igraph_real_t y, igraph_real_t r) { - igraph_integer_t cx, cy; - igraph_integer_t i, j; - igraph_integer_t ret; + igraph_int_t cx, cy; + igraph_int_t i, j; + igraph_int_t ret; if (x - r <= grid->minx || x + r >= grid->maxx || y - r <= grid->miny || y + r >= grid->maxy) { diff --git a/src/vendor/cigraph/src/layout/merge_grid.h b/src/vendor/cigraph/src/layout/merge_grid.h index 48d08e9041d..333b4738b19 100644 --- a/src/vendor/cigraph/src/layout/merge_grid.h +++ b/src/vendor/cigraph/src/layout/merge_grid.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2009-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,26 +28,26 @@ IGRAPH_BEGIN_C_DECLS /* A type of grid used for merging layouts; each cell is owned by exactly one graph */ typedef struct igraph_i_layout_mergegrid_t { - igraph_integer_t *data; - igraph_integer_t stepsx, stepsy; + igraph_int_t *data; + igraph_int_t stepsx, stepsy; igraph_real_t minx, maxx, deltax; igraph_real_t miny, maxy, deltay; } igraph_i_layout_mergegrid_t; IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_layout_mergegrid_init(igraph_i_layout_mergegrid_t *grid, - igraph_real_t minx, igraph_real_t maxx, igraph_integer_t stepsx, - igraph_real_t miny, igraph_real_t maxy, igraph_integer_t stepsy); + igraph_real_t minx, igraph_real_t maxx, igraph_int_t stepsx, + igraph_real_t miny, igraph_real_t maxy, igraph_int_t stepsy); IGRAPH_PRIVATE_EXPORT void igraph_i_layout_mergegrid_destroy(igraph_i_layout_mergegrid_t *grid); IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_layout_merge_place_sphere(igraph_i_layout_mergegrid_t *grid, igraph_real_t x, igraph_real_t y, igraph_real_t r, - igraph_integer_t id); + igraph_int_t id); -igraph_integer_t igraph_i_layout_mergegrid_get(igraph_i_layout_mergegrid_t *grid, +igraph_int_t igraph_i_layout_mergegrid_get(igraph_i_layout_mergegrid_t *grid, igraph_real_t x, igraph_real_t y); -igraph_integer_t igraph_i_layout_mergegrid_get_sphere(igraph_i_layout_mergegrid_t *g, +igraph_int_t igraph_i_layout_mergegrid_get_sphere(igraph_i_layout_mergegrid_t *g, igraph_real_t x, igraph_real_t y, igraph_real_t r); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/layout/reingold_tilford.c b/src/vendor/cigraph/src/layout/reingold_tilford.c index fc1e98f3aea..e1e28ad2ca9 100644 --- a/src/vendor/cigraph/src/layout/reingold_tilford.c +++ b/src/vendor/cigraph/src/layout/reingold_tilford.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,13 +35,13 @@ static igraph_error_t layout_reingold_tilford_unreachable( const igraph_t *graph, igraph_neimode_t mode, - igraph_integer_t real_root, - igraph_integer_t no_of_nodes, + igraph_int_t real_root, + igraph_int_t no_of_nodes, igraph_vector_int_t *pnewedges) { - igraph_integer_t no_of_newedges; + igraph_int_t no_of_newedges; igraph_vector_bool_t visited; - igraph_integer_t i, j, n; + igraph_int_t i, j, n; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; igraph_adjlist_t allneis; igraph_vector_int_t *neis; @@ -59,12 +59,12 @@ static igraph_error_t layout_reingold_tilford_unreachable( /* start from real_root and go BFS */ IGRAPH_CHECK(igraph_dqueue_int_push(&q, real_root)); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); neis = igraph_adjlist_get(&allneis, actnode); n = igraph_vector_int_size(neis); VECTOR(visited)[actnode] = true; for (j = 0; j < n; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + igraph_int_t neighbor = VECTOR(*neis)[j]; if (!VECTOR(visited)[neighbor]) { IGRAPH_CHECK(igraph_dqueue_int_push(&q, neighbor)); } @@ -105,26 +105,26 @@ static igraph_error_t layout_reingold_tilford_unreachable( /* Internal structure for Reingold-Tilford layout */ struct reingold_tilford_vertex { - igraph_integer_t parent; /* Parent node index */ - igraph_integer_t level; /* Level of the node */ + igraph_int_t parent; /* Parent node index */ + igraph_int_t level; /* Level of the node */ igraph_real_t offset; /* X offset from parent node */ - igraph_integer_t left_contour; /* Next left node of the contour + igraph_int_t left_contour; /* Next left node of the contour of the subtree rooted at this node */ - igraph_integer_t right_contour; /* Next right node of the contour + igraph_int_t right_contour; /* Next right node of the contour of the subtree rooted at this node */ igraph_real_t offset_to_left_contour; /* X offset when following the left contour */ igraph_real_t offset_to_right_contour; /* X offset when following the right contour */ - igraph_integer_t left_extreme; /* Leftmost node on the deepest layer of the subtree rooted at this node */ - igraph_integer_t right_extreme; /* Rightmost node on the deepest layer of the subtree rooted at this node */ + igraph_int_t left_extreme; /* Leftmost node on the deepest layer of the subtree rooted at this node */ + igraph_int_t right_extreme; /* Rightmost node on the deepest layer of the subtree rooted at this node */ igraph_real_t offset_to_left_extreme; /* X offset when jumping to the left extreme node */ igraph_real_t offset_to_right_extreme; /* X offset when jumping to the right extreme node */ }; static void layout_reingold_tilford_postorder(struct reingold_tilford_vertex *vdata, - igraph_integer_t node, igraph_integer_t vcount); + igraph_int_t node, igraph_int_t vcount); static void layout_reingold_tilford_calc_coords(struct reingold_tilford_vertex *vdata, - igraph_matrix_t *res, igraph_integer_t node, - igraph_integer_t vcount, igraph_real_t xpos); + igraph_matrix_t *res, igraph_int_t node, + igraph_int_t vcount, igraph_real_t xpos); /* uncomment the next line for debugging the Reingold-Tilford layout */ /* #define LAYOUT_RT_DEBUG 1 */ @@ -132,9 +132,9 @@ static void layout_reingold_tilford_calc_coords(struct reingold_tilford_vertex * static igraph_error_t layout_reingold_tilford(const igraph_t *graph, igraph_matrix_t *res, igraph_neimode_t mode, - igraph_integer_t root) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i, n, j; + igraph_int_t root) { + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i, n, j; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; igraph_adjlist_t allneis; igraph_vector_int_t *neis; @@ -173,13 +173,13 @@ static igraph_error_t layout_reingold_tilford(const igraph_t *graph, IGRAPH_CHECK(igraph_dqueue_int_push(&q, root)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); neis = igraph_adjlist_get(&allneis, actnode); n = igraph_vector_int_size(neis); for (j = 0; j < n; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + igraph_int_t neighbor = VECTOR(*neis)[j]; if (vdata[neighbor].parent >= 0) { continue; } @@ -228,11 +228,11 @@ static igraph_error_t layout_reingold_tilford(const igraph_t *graph, static void layout_reingold_tilford_calc_coords( struct reingold_tilford_vertex *vdata, - igraph_matrix_t *res, igraph_integer_t node, - igraph_integer_t vcount, igraph_real_t xpos) { + igraph_matrix_t *res, igraph_int_t node, + igraph_int_t vcount, igraph_real_t xpos) { MATRIX(*res, node, 0) = xpos; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { if (i == node) { continue; } @@ -245,9 +245,9 @@ static void layout_reingold_tilford_calc_coords( static void layout_reingold_tilford_postorder( struct reingold_tilford_vertex *vdata, - igraph_integer_t node, igraph_integer_t vcount) { + igraph_int_t node, igraph_int_t vcount) { - igraph_integer_t childcount, leftroot, leftrootidx; + igraph_int_t childcount, leftroot, leftrootidx; const igraph_real_t minsep = 1; igraph_real_t avg; @@ -257,7 +257,7 @@ static void layout_reingold_tilford_postorder( /* Check whether this node is a leaf node */ childcount = 0; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { if (i == node) { continue; } @@ -285,7 +285,7 @@ static void layout_reingold_tilford_postorder( #ifdef LAYOUT_RT_DEBUG printf("Visited node %" IGRAPH_PRId " and arranged its subtrees\n", node); #endif - for (igraph_integer_t i = 0, j = 0; i < vcount; i++) { + for (igraph_int_t i = 0, j = 0; i < vcount; i++) { if (i == node) { continue; } @@ -293,7 +293,7 @@ static void layout_reingold_tilford_postorder( if (leftroot >= 0) { /* Now we will follow the right contour of leftroot and the * left contour of the subtree rooted at i */ - igraph_integer_t lnode, rnode, auxnode; + igraph_int_t lnode, rnode, auxnode; igraph_real_t loffset, roffset, rootsep, newoffset; #ifdef LAYOUT_RT_DEBUG @@ -432,7 +432,7 @@ static void layout_reingold_tilford_postorder( vdata[node].offset_to_right_contour -= avg; vdata[node].offset_to_left_extreme -= avg; vdata[node].offset_to_right_extreme -= avg; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { if (i == node) { continue; } @@ -448,7 +448,7 @@ static void layout_reingold_tilford_postorder( static igraph_error_t layout_reingold_tilford_cluster_degrees_directed( const igraph_t *graph, const igraph_vector_int_t *membership, - igraph_integer_t no_comps, + igraph_int_t no_comps, igraph_neimode_t mode, igraph_vector_int_t *degrees) { @@ -465,15 +465,15 @@ static igraph_error_t layout_reingold_tilford_cluster_degrees_directed( IGRAPH_FINALLY(igraph_eit_destroy, &eit); for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t eid = IGRAPH_EIT_GET(eit); + igraph_int_t eid = IGRAPH_EIT_GET(eit); - igraph_integer_t from = IGRAPH_FROM(graph, eid); - igraph_integer_t to = IGRAPH_TO(graph, eid); + igraph_int_t from = IGRAPH_FROM(graph, eid); + igraph_int_t to = IGRAPH_TO(graph, eid); - igraph_integer_t from_cl = VECTOR(*membership)[from]; - igraph_integer_t to_cl = VECTOR(*membership)[to]; + igraph_int_t from_cl = VECTOR(*membership)[from]; + igraph_int_t to_cl = VECTOR(*membership)[to]; - igraph_integer_t cl = mode == IGRAPH_OUT ? from_cl : to_cl; + igraph_int_t cl = mode == IGRAPH_OUT ? from_cl : to_cl; if (from_cl != to_cl) { VECTOR(*degrees)[cl] += 1; @@ -539,10 +539,10 @@ igraph_error_t igraph_roots_for_tree_layout( igraph_vector_int_t *roots, igraph_root_choice_t heuristic) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t order, membership; - igraph_integer_t no_comps; - igraph_integer_t i, j; + igraph_int_t no_comps; + igraph_int_t i, j; igraph_bool_t use_eccentricity; switch (heuristic) { @@ -611,8 +611,8 @@ igraph_error_t igraph_roots_for_tree_layout( * and record largest degree node in each strongly-connected component * which has no incoming (outgoing) edges. */ for (i = 0; i < no_of_nodes; ++i) { - igraph_integer_t v = VECTOR(order)[i]; - igraph_integer_t cl = VECTOR(membership)[v]; + igraph_int_t v = VECTOR(order)[i]; + igraph_int_t cl = VECTOR(membership)[v]; if (VECTOR(cluster_degrees)[cl] == 0 && VECTOR(*roots)[cl] == -1) { VECTOR(*roots)[cl] = v; } @@ -637,11 +637,11 @@ igraph_error_t igraph_roots_for_tree_layout( * Select the highest degree node from each component. */ - igraph_integer_t no_seen = 0; + igraph_int_t no_seen = 0; for (i=0; i < no_of_nodes; ++i) { - igraph_integer_t v = VECTOR(order)[i]; - igraph_integer_t cl = VECTOR(membership)[v]; + igraph_int_t v = VECTOR(order)[i]; + igraph_int_t cl = VECTOR(membership)[v]; if (VECTOR(*roots)[cl] == -1) { no_seen += 1; VECTOR(*roots)[cl] = v; @@ -716,9 +716,9 @@ igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, const igraph_vector_int_t *roots, const igraph_vector_int_t *rootlevel) { - const igraph_integer_t no_of_nodes_orig = igraph_vcount(graph); - igraph_integer_t no_of_nodes = no_of_nodes_orig; - igraph_integer_t real_root; + const igraph_int_t no_of_nodes_orig = igraph_vcount(graph); + igraph_int_t no_of_nodes = no_of_nodes_orig; + igraph_int_t real_root; igraph_t extended; const igraph_t *pextended = graph; igraph_vector_int_t myroots; @@ -760,7 +760,7 @@ igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, /* ----------------------------------------------------------------------- */ /* Many roots were given to us, check 'rootlevel' */ - igraph_integer_t plus_levels = 0; + igraph_int_t plus_levels = 0; if (igraph_vector_int_size(roots) != igraph_vector_int_size(rootlevel)) { IGRAPH_ERROR("Reingold-Tilford: 'roots' and 'rootlevel' lengths differ", @@ -768,13 +768,13 @@ igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, } /* count the rootlevels that are not zero */ - for (igraph_integer_t i = 0; i < igraph_vector_int_size(roots); i++) { + for (igraph_int_t i = 0; i < igraph_vector_int_size(roots); i++) { plus_levels += VECTOR(*rootlevel)[i]; } /* make copy of graph, add vertices/edges */ if (plus_levels != 0) { - igraph_integer_t edgeptr = 0; + igraph_int_t edgeptr = 0; pextended = &extended; IGRAPH_CHECK(igraph_copy(&extended, graph)); @@ -783,10 +783,10 @@ igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_resize(&newedges, plus_levels * 2)); - for (igraph_integer_t i = 0; i < igraph_vector_int_size(roots); i++) { - igraph_integer_t rl = VECTOR(*rootlevel)[i]; - igraph_integer_t rn = VECTOR(*roots)[i]; - igraph_integer_t j; + for (igraph_int_t i = 0; i < igraph_vector_int_size(roots); i++) { + igraph_int_t rl = VECTOR(*rootlevel)[i]; + igraph_int_t rn = VECTOR(*roots)[i]; + igraph_int_t j; /* zero-level roots don't get anything special */ if (rl == 0) { @@ -858,7 +858,7 @@ igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, /* else, we need to make real_root */ } else { - igraph_integer_t no_of_newedges; + igraph_int_t no_of_newedges; /* Make copy of the graph unless it exists already */ if (pextended == graph) { @@ -875,7 +875,7 @@ igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, /* add edges from the roots to real_root */ no_of_newedges = igraph_vector_int_size(proots); IGRAPH_CHECK(igraph_vector_int_resize(&newedges, no_of_newedges * 2)); - for (igraph_integer_t i = 0; i < no_of_newedges; i++) { + for (igraph_int_t i = 0; i < no_of_newedges; i++) { VECTOR(newedges)[2 * i] = no_of_nodes - 1; VECTOR(newedges)[2 * i + 1] = VECTOR(*proots)[i]; } @@ -909,7 +909,7 @@ igraph_error_t igraph_layout_reingold_tilford(const igraph_t *graph, IGRAPH_CHECK(igraph_matrix_remove_row(res, no_of_nodes_orig)); } else { igraph_matrix_t tmp; - igraph_integer_t i; + igraph_int_t i; IGRAPH_MATRIX_INIT_FINALLY(&tmp, no_of_nodes_orig, 2); for (i = 0; i < no_of_nodes_orig; i++) { MATRIX(tmp, i, 0) = MATRIX(*res, i, 0); @@ -975,7 +975,7 @@ igraph_error_t igraph_layout_reingold_tilford_circular(const igraph_t *graph, const igraph_vector_int_t *roots, const igraph_vector_int_t *rootlevel) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_real_t ratio; igraph_real_t minx, maxx; @@ -988,7 +988,7 @@ igraph_error_t igraph_layout_reingold_tilford_circular(const igraph_t *graph, ratio = 2 * M_PI * (no_of_nodes - 1.0) / no_of_nodes; minx = maxx = MATRIX(*res, 0, 0); - for (igraph_integer_t i = 1; i < no_of_nodes; i++) { + for (igraph_int_t i = 1; i < no_of_nodes; i++) { if (MATRIX(*res, i, 0) > maxx) { maxx = MATRIX(*res, i, 0); } @@ -999,7 +999,7 @@ igraph_error_t igraph_layout_reingold_tilford_circular(const igraph_t *graph, if (maxx > minx) { ratio /= (maxx - minx); } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_real_t phi = (MATRIX(*res, i, 0) - minx) * ratio; igraph_real_t r = MATRIX(*res, i, 1); MATRIX(*res, i, 0) = r * cos(phi); diff --git a/src/vendor/cigraph/src/layout/sugiyama.c b/src/vendor/cigraph/src/layout/sugiyama.c index dc59ffd1df5..d30c8d969ab 100644 --- a/src/vendor/cigraph/src/layout/sugiyama.c +++ b/src/vendor/cigraph/src/layout/sugiyama.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -33,7 +33,7 @@ #include "igraph_types.h" #include "internal/glpk_support.h" -#include "misc/feedback_arc_set.h" +#include "cycles/feedback_sets.h" #include @@ -147,7 +147,7 @@ typedef struct { */ static igraph_error_t igraph_i_layering_init(igraph_i_layering_t* layering, const igraph_vector_int_t* membership) { - igraph_integer_t i, n, num_layers; + igraph_int_t i, n, num_layers; if (igraph_vector_int_size(membership) == 0) { num_layers = 0; @@ -159,7 +159,7 @@ static igraph_error_t igraph_i_layering_init(igraph_i_layering_t* layering, n = igraph_vector_int_size(membership); for (i = 0; i < n; i++) { - igraph_integer_t l = VECTOR(*membership)[i]; + igraph_int_t l = VECTOR(*membership)[i]; igraph_vector_int_t* vec = igraph_vector_int_list_get_ptr(&layering->layers, l); IGRAPH_CHECK(igraph_vector_int_push_back(vec, i)); } @@ -179,7 +179,7 @@ static void igraph_i_layering_destroy(igraph_i_layering_t* layering) { /** * Returns the number of layers in a layering. */ -static igraph_integer_t igraph_i_layering_num_layers(const igraph_i_layering_t* layering) { +static igraph_int_t igraph_i_layering_num_layers(const igraph_i_layering_t* layering) { return igraph_vector_int_list_size(&layering->layers); } @@ -187,7 +187,7 @@ static igraph_integer_t igraph_i_layering_num_layers(const igraph_i_layering_t* * Returns the list of vertices in a given layer */ static igraph_vector_int_t* igraph_i_layering_get(const igraph_i_layering_t* layering, - igraph_integer_t index) { + igraph_int_t index) { return igraph_vector_int_list_get_ptr(&layering->layers, index); } @@ -200,10 +200,10 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_vertically(const igra const igraph_vector_t* weights, igraph_vector_int_t* membership); static igraph_error_t igraph_i_layout_sugiyama_order_nodes_horizontally(const igraph_t* graph, igraph_matrix_t* layout, const igraph_i_layering_t* layering, - igraph_integer_t maxiter); + igraph_int_t maxiter); static igraph_error_t igraph_i_layout_sugiyama_place_nodes_horizontally(const igraph_t* graph, igraph_matrix_t* layout, const igraph_i_layering_t* layering, - igraph_real_t hgap, igraph_integer_t no_of_real_nodes); + igraph_real_t hgap, igraph_int_t no_of_real_nodes); /** * Calculated the median of four numbers (not necessarily sorted). @@ -211,8 +211,7 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_horizontally(const ig static INLINE igraph_real_t igraph_i_median_4(igraph_real_t x1, igraph_real_t x2, igraph_real_t x3, igraph_real_t x4) { igraph_real_t arr[4] = { x1, x2, x3, x4 }; - igraph_vector_t vec; - igraph_vector_view(&vec, arr, 4); + igraph_vector_t vec = igraph_vector_view(arr, 4); igraph_vector_sort(&vec); return (arr[1] + arr[2]) / 2.0; } @@ -238,15 +237,13 @@ static INLINE igraph_real_t igraph_i_median_4(igraph_real_t x1, * * * The Sugiyama layout may introduce "bends" on the edges in order to obtain a - * visually more pleasing layout. This is achieved by adding dummy nodes to - * edges spanning more than one layer. The resulting layout assigns coordinates - * not only to the nodes of the original graph but also to the dummy nodes. - * The layout algorithm will also return the extended graph with the dummy nodes. - * An edge in the original graph may either be mapped to a single edge in the - * extended graph or a \em path that starts and ends in the original - * source and target vertex and passes through multiple dummy vertices. In - * such cases, the user may also request the mapping of the edges of the extended - * graph back to the edges of the original graph. + * visually more pleasing layout. The additional control points of the edges are + * returned in a separate list of matrices, one matrix per edge in the original + * graph. If an edge requires no additional control points, the corresponding + * matrix will be empty, otherwise the matrix will contain the coordinates of + * the control points, one point per row. When drawing the graph, edges should + * be drawn in a way that the curve representing the edge passes through the + * control points. * * * For more details, see K. Sugiyama, S. Tagawa and M. Toda, "Methods for Visual @@ -255,21 +252,16 @@ static INLINE igraph_real_t igraph_i_median_4(igraph_real_t x1, * * \param graph Pointer to an initialized graph object. * \param res Pointer to an initialized matrix object. This will contain - * the result and will be resized as needed. The first |V| rows - * of the layout will contain the coordinates of the original graph, - * the remaining rows contain the positions of the dummy nodes. - * Therefore, you can use the result both with \p graph or with - * \p extended_graph. - * \param extd_graph Pointer to an uninitialized graph object or \c NULL. - * The extended graph with the added dummy nodes will be - * returned here. In this graph, each edge points downwards - * to lower layers, spans exactly one layer and the first - * |V| vertices coincide with the vertices of the - * original graph. - * \param extd_to_orig_eids Pointer to a vector or \c NULL. If not \c NULL, the - * mapping from the edge IDs of the extended graph back - * to the edge IDs of the original graph will be stored - * here. + * the result and will be resized as needed. The coordinates of the + * vertices in the layout will be stored in the rows of the matrix, + * one row per vertex. + * \param routing Pointer to an uninitialized list of matrices or \c NULL. + * When not \c NULL, the list will be resized as needed such + * that there will be one matrix for each edge of the graph, + * and the matrix will hold the additional control points that + * the edge must pass through, starting from the source vertex + * of the edge and ending at the target vertex. The matrix will + * have zero rows if an edge does not require control points. * \param layers The layer index for each vertex or \c NULL if the layers should * be determined automatically by igraph. * \param hgap The preferred minimum horizontal gap between vertices in the same @@ -283,37 +275,39 @@ static INLINE igraph_real_t igraph_i_median_4(igraph_real_t x1, * weights when breaking the cycles. * \return Error code. */ -igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *res, - igraph_t *extd_graph, igraph_vector_int_t *extd_to_orig_eids, - const igraph_vector_int_t* layers, igraph_real_t hgap, igraph_real_t vgap, - igraph_integer_t maxiter, const igraph_vector_t *weights) { - igraph_integer_t i, j, k, l, m, nei; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t comp_idx; - igraph_integer_t next_extd_vertex_id = no_of_nodes; +igraph_error_t igraph_layout_sugiyama( + const igraph_t *graph, igraph_matrix_t *res, igraph_matrix_list_t *routing, + const igraph_vector_int_t* layers, igraph_real_t hgap, igraph_real_t vgap, + igraph_int_t maxiter, const igraph_vector_t *weights +) { + igraph_int_t i, j, k, l, nei; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t comp_idx; igraph_bool_t directed = igraph_is_directed(graph); - igraph_integer_t no_of_components; /* number of components of the original graph */ + igraph_int_t no_of_components; /* number of components of the original graph */ igraph_vector_int_t membership; /* components of the original graph */ - igraph_vector_int_t extd_edgelist; /* edge list of the extended graph */ igraph_vector_int_t layers_own; /* layer indices after having eliminated empty layers */ - igraph_real_t dx = 0, dx2 = 0; /* displacement of the current component on the X axis */ + igraph_real_t dx = 0; /* displacement of the current component on the X axis */ igraph_vector_t layer_to_y; /* mapping from layer indices to final Y coordinates */ + igraph_matrix_t *control_points; if (layers && igraph_vector_int_size(layers) != no_of_nodes) { IGRAPH_ERROR("layer vector too short or too long", IGRAPH_EINVAL); } - if (extd_graph != 0) { - IGRAPH_VECTOR_INT_INIT_FINALLY(&extd_edgelist, 0); - if (extd_to_orig_eids != 0) { - igraph_vector_int_clear(extd_to_orig_eids); - } - } - IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2)); IGRAPH_VECTOR_INT_INIT_FINALLY(&membership, 0); IGRAPH_VECTOR_INIT_FINALLY(&layer_to_y, 0); + if (routing != 0) { + IGRAPH_CHECK(igraph_matrix_list_resize(routing, no_of_edges)); + for (i = 0; i < no_of_edges; i++) { + control_points = igraph_matrix_list_get_ptr(routing, i); + IGRAPH_CHECK(igraph_matrix_resize(control_points, 0, 2)); + } + } + /* 1. Find a feedback arc set if we don't have a layering yet. If we do have * a layering, we can leave all the edges as is as they will be re-oriented * to point downwards only anyway. */ @@ -353,9 +347,10 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re for (comp_idx = 0; comp_idx < no_of_components; comp_idx++) { /* Extract the edges of the comp_idx'th component and add dummy nodes for edges * spanning more than one layer. */ - igraph_integer_t component_size, next_new_vertex_id; + igraph_int_t component_size, next_new_vertex_id; igraph_vector_int_t old2new_vertex_ids; igraph_vector_int_t new2old_vertex_ids; + igraph_vector_int_t new_vertex_id_to_edge_id; igraph_vector_int_t new_layers; igraph_vector_int_t edgelist; igraph_vector_int_t neis; @@ -364,9 +359,11 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&new2old_vertex_ids, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&old2new_vertex_ids, no_of_nodes); + IGRAPH_VECTOR_INT_INIT_FINALLY(&new_vertex_id_to_edge_id, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&new_layers, 0); igraph_vector_int_fill(&old2new_vertex_ids, -1); + igraph_vector_int_fill(&new_vertex_id_to_edge_id, -1); /* Construct a mapping from the old vertex IDs to the new ones */ for (i = 0, next_new_vertex_id = 0; i < no_of_nodes; i++) { @@ -391,7 +388,7 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re IGRAPH_CHECK(igraph_incident(graph, &neis, i, IGRAPH_OUT, IGRAPH_LOOPS)); j = igraph_vector_int_size(&neis); for (k = 0; k < j; k++) { - igraph_integer_t eid = VECTOR(neis)[k]; + igraph_int_t eid = VECTOR(neis)[k]; if (directed) { nei = IGRAPH_TO(graph, eid); } else { @@ -402,16 +399,11 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re } if (VECTOR(layers_own)[i] == VECTOR(layers_own)[nei]) { /* Edge goes within the same layer, we don't need this in the - * layered graph, but we need it in the extended graph */ - if (extd_graph != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, i)); - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, nei)); - if (extd_to_orig_eids != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(extd_to_orig_eids, eid)); - } - } + * layered graph */ } else if (VECTOR(layers_own)[i] > VECTOR(layers_own)[nei]) { - /* Edge goes upwards, we have to flip it */ + /* Edge goes upwards, we have to flip it and then later on we need to traverse + * its control points in reverse order. We remember that we need to flip it + * by storing -eid-1 in `new_vertex_id_to_edge_id` instead of eid */ IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, VECTOR(old2new_vertex_ids)[nei])); for (l = VECTOR(layers_own)[nei] + 1; @@ -419,27 +411,10 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re IGRAPH_CHECK(igraph_vector_int_push_back(&new_layers, l)); IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, next_new_vertex_id)); IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, next_new_vertex_id++)); + IGRAPH_CHECK(igraph_vector_int_push_back(&new_vertex_id_to_edge_id, -eid-1)); } IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, VECTOR(old2new_vertex_ids)[i])); - /* Also add the edge to the extended graph if needed, but this time - * with the proper orientation */ - if (extd_graph != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, i)); - next_extd_vertex_id += VECTOR(layers_own)[i] - VECTOR(layers_own)[nei] - 1; - for (l = VECTOR(layers_own)[i] - 1, m = 1; - l > VECTOR(layers_own)[nei]; l--, m++) { - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, next_extd_vertex_id - m)); - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, next_extd_vertex_id - m)); - if (extd_to_orig_eids != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(extd_to_orig_eids, eid)); - } - } - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, nei)); - if (extd_to_orig_eids != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(extd_to_orig_eids, eid)); - } - } } else { /* Edge goes downwards */ IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, @@ -449,25 +424,10 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re IGRAPH_CHECK(igraph_vector_int_push_back(&new_layers, l)); IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, next_new_vertex_id)); IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, next_new_vertex_id++)); + IGRAPH_CHECK(igraph_vector_int_push_back(&new_vertex_id_to_edge_id, eid)); } IGRAPH_CHECK(igraph_vector_int_push_back(&edgelist, VECTOR(old2new_vertex_ids)[nei])); - /* Also add the edge to the extended graph */ - if (extd_graph != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, i)); - for (l = VECTOR(layers_own)[i] + 1; - l < VECTOR(layers_own)[nei]; l++) { - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, next_extd_vertex_id)); - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, next_extd_vertex_id++)); - if (extd_to_orig_eids != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(extd_to_orig_eids, eid)); - } - } - IGRAPH_CHECK(igraph_vector_int_push_back(&extd_edgelist, nei)); - if (extd_to_orig_eids != 0) { - IGRAPH_CHECK(igraph_vector_int_push_back(extd_to_orig_eids, eid)); - } - } } } } @@ -478,6 +438,10 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re igraph_matrix_t layout; igraph_i_layering_t layering; igraph_t subgraph; + igraph_int_t eid; + igraph_real_t max_x; + igraph_bool_t flipped; + igraph_matrix_t *control_points; IGRAPH_CHECK(igraph_matrix_init(&layout, next_new_vertex_id, 2)); IGRAPH_FINALLY(igraph_matrix_destroy, &layout); @@ -507,29 +471,60 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re IGRAPH_CHECK(igraph_i_layout_sugiyama_place_nodes_horizontally(&subgraph, &layout, &layering, hgap, component_size)); - /* Re-assign rows into the result matrix, and at the same time, */ + /* Arrange rows of the layout into the result matrix, and at the same time, */ /* adjust dx so that the next component does not overlap this one */ - j = next_new_vertex_id - component_size; - k = igraph_matrix_nrow(res); - IGRAPH_CHECK(igraph_matrix_add_rows(res, j)); - dx2 = dx; + + /* First we arrange the "real" vertices */ for (i = 0; i < component_size; i++) { - l = VECTOR(new2old_vertex_ids)[i]; - MATRIX(*res, l, 0) = MATRIX(layout, i, 0) + dx; - MATRIX(*res, l, 1) = VECTOR(layer_to_y)[(igraph_integer_t) MATRIX(layout, i, 1)]; - if (dx2 < MATRIX(*res, l, 0)) { - dx2 = MATRIX(*res, l, 0); + k = VECTOR(new2old_vertex_ids)[i]; + MATRIX(*res, k, 0) = MATRIX(layout, i, 0) + dx; + MATRIX(*res, k, 1) = VECTOR(layer_to_y)[(igraph_int_t) MATRIX(layout, i, 1)]; + } + + /* Next we arrange the "dummy" vertices that become control points in the + * routing matrix list. Note that the dummy vertices were added in a way that + * the vertices that will become control points on an edge with a particular ID + * are always consecutive in `new_vertex_id_to_edge_id` so we can count the number + * of waypoints in an edg easily */ + if (routing) { + IGRAPH_CHECK(igraph_vector_int_push_back(&new_vertex_id_to_edge_id, -1)); /* sentinel */ + while (i < next_new_vertex_id) { + eid = VECTOR(new_vertex_id_to_edge_id)[i]; + + /* Find out how many control points we have for this edge */ + for (j = i; VECTOR(new_vertex_id_to_edge_id)[j] == eid; j++); + + /* Is this edge flipped in the layered graph? If so, recover the original eid */ + flipped = eid < 0; + if (flipped) { + eid = -eid-1; + } + + control_points = igraph_matrix_list_get_ptr(routing, eid); + IGRAPH_CHECK(igraph_matrix_resize(control_points, j - i, 2)); + + if (flipped) { + for (k = j - i - 1; i < j; k--, i++) { + MATRIX(*control_points, k, 0) = MATRIX(layout, i, 0) + dx; + MATRIX(*control_points, k, 1) = VECTOR(layer_to_y)[(igraph_int_t) MATRIX(layout, i, 1)]; + } + } else { + for (k = 0; i < j; k++, i++) { + MATRIX(*control_points, k, 0) = MATRIX(layout, i, 0) + dx; + MATRIX(*control_points, k, 1) = VECTOR(layer_to_y)[(igraph_int_t) MATRIX(layout, i, 1)]; + } + } } } - for (i = component_size; i < next_new_vertex_id; i++) { - MATRIX(*res, k, 0) = MATRIX(layout, i, 0) + dx; - MATRIX(*res, k, 1) = VECTOR(layer_to_y)[(igraph_integer_t) MATRIX(layout, i, 1)]; - if (dx2 < MATRIX(*res, k, 0)) { - dx2 = MATRIX(*res, k, 0); + + /* Update the left margin for the next component */ + max_x = 0; + for (i = 0; i < next_new_vertex_id; i++) { + if (MATRIX(layout, i, 0) > max_x) { + max_x = MATRIX(layout, i, 0); } - k++; } - dx = dx2 + hgap; + dx += max_x + hgap; igraph_destroy(&subgraph); igraph_i_layering_destroy(&layering); @@ -538,11 +533,12 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re } igraph_vector_int_destroy(&new_layers); + igraph_vector_int_destroy(&new_vertex_id_to_edge_id); igraph_vector_int_destroy(&old2new_vertex_ids); igraph_vector_int_destroy(&new2old_vertex_ids); igraph_vector_int_destroy(&edgelist); igraph_vector_int_destroy(&neis); - IGRAPH_FINALLY_CLEAN(5); + IGRAPH_FINALLY_CLEAN(6); } igraph_vector_int_destroy(&layers_own); @@ -550,19 +546,13 @@ igraph_error_t igraph_layout_sugiyama(const igraph_t *graph, igraph_matrix_t *re igraph_vector_int_destroy(&membership); IGRAPH_FINALLY_CLEAN(3); - if (extd_graph != 0) { - IGRAPH_CHECK(igraph_create(extd_graph, &extd_edgelist, next_extd_vertex_id, igraph_is_directed(graph))); - igraph_vector_int_destroy(&extd_edgelist); - IGRAPH_FINALLY_CLEAN(1); - } - return IGRAPH_SUCCESS; } static igraph_error_t igraph_i_layout_sugiyama_place_nodes_vertically(const igraph_t* graph, const igraph_vector_t* weights, igraph_vector_int_t* membership) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); IGRAPH_CHECK(igraph_vector_int_resize(membership, no_of_nodes)); if (no_of_edges == 0) { @@ -574,7 +564,7 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_vertically(const igra if (igraph_is_directed(graph) && no_of_nodes <= 1000) { /* Network simplex algorithm of Gansner et al, using the original linear * programming formulation */ - igraph_integer_t i, j; + igraph_int_t i, j; igraph_vector_t outdegs, indegs; igraph_vector_int_t feedback_edges; glp_prob *ip; @@ -602,9 +592,9 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_vertically(const igra IGRAPH_IN, IGRAPH_LOOPS, weights)); j = igraph_vector_int_size(&feedback_edges); for (i = 0; i < j; i++) { - igraph_integer_t eid = VECTOR(feedback_edges)[i]; - igraph_integer_t from = IGRAPH_FROM(graph, eid); - igraph_integer_t to = IGRAPH_TO(graph, eid); + igraph_int_t eid = VECTOR(feedback_edges)[i]; + igraph_int_t from = IGRAPH_FROM(graph, eid); + igraph_int_t to = IGRAPH_TO(graph, eid); VECTOR(outdegs)[from] -= weights ? VECTOR(*weights)[eid] : 1; VECTOR(indegs)[to] -= weights ? VECTOR(*weights)[eid] : 1; } @@ -685,10 +675,10 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_vertically(const igra } static igraph_error_t igraph_i_layout_sugiyama_calculate_barycenters(const igraph_t* graph, - const igraph_i_layering_t* layering, igraph_integer_t layer_index, + const igraph_i_layering_t* layering, igraph_int_t layer_index, igraph_neimode_t direction, const igraph_matrix_t* layout, igraph_vector_t* barycenters) { - igraph_integer_t i, j, m, n; + igraph_int_t i, j, m, n; igraph_vector_int_t* layer_members = igraph_i_layering_get(layering, layer_index); igraph_vector_int_t neis; @@ -728,11 +718,11 @@ static igraph_error_t igraph_i_layout_sugiyama_calculate_barycenters(const igrap */ static igraph_error_t igraph_i_layout_sugiyama_order_nodes_horizontally(const igraph_t* graph, igraph_matrix_t* layout, const igraph_i_layering_t* layering, - igraph_integer_t maxiter) { - igraph_integer_t i, n, nei; - igraph_integer_t no_of_vertices = igraph_vcount(graph); - igraph_integer_t no_of_layers = igraph_i_layering_num_layers(layering); - igraph_integer_t iter, layer_index; + igraph_int_t maxiter) { + igraph_int_t i, n, nei; + igraph_int_t no_of_vertices = igraph_vcount(graph); + igraph_int_t no_of_layers = igraph_i_layering_num_layers(layering); + igraph_int_t iter, layer_index; igraph_vector_int_t* layer_members; igraph_vector_int_t new_layer_members; igraph_vector_int_t neis; @@ -743,10 +733,10 @@ static igraph_error_t igraph_i_layout_sugiyama_order_nodes_horizontally(const ig /* The first column of the matrix will serve as the ordering */ /* Start with a first-seen ordering within each layer */ { - igraph_integer_t *xs = IGRAPH_CALLOC(no_of_layers, igraph_integer_t); + igraph_int_t *xs = IGRAPH_CALLOC(no_of_layers, igraph_int_t); IGRAPH_CHECK_OOM(xs, "Cannot order nodes horizontally during Sugiyama layout."); for (i = 0; i < no_of_vertices; i++) { - MATRIX(*layout, i, 0) = xs[(igraph_integer_t)MATRIX(*layout, i, 1)]++; + MATRIX(*layout, i, 0) = xs[(igraph_int_t)MATRIX(*layout, i, 1)]++; } free(xs); } @@ -859,7 +849,7 @@ static igraph_error_t igraph_i_layout_sugiyama_horizontal_compaction(const igrap const igraph_vector_int_t* vertex_to_the_left, const igraph_vector_int_t* roots, const igraph_vector_int_t* align, igraph_real_t hgap, igraph_vector_t* xs); -static void igraph_i_layout_sugiyama_horizontal_compaction_place_block(igraph_integer_t v, +static void igraph_i_layout_sugiyama_horizontal_compaction_place_block(igraph_int_t v, const igraph_vector_int_t* vertex_to_the_left, const igraph_vector_int_t* roots, const igraph_vector_int_t* align, igraph_vector_int_t* sinks, igraph_vector_t* shifts, @@ -867,12 +857,12 @@ static void igraph_i_layout_sugiyama_horizontal_compaction_place_block(igraph_in static igraph_error_t igraph_i_layout_sugiyama_place_nodes_horizontally(const igraph_t* graph, igraph_matrix_t* layout, const igraph_i_layering_t* layering, - igraph_real_t hgap, igraph_integer_t no_of_real_nodes) { + igraph_real_t hgap, igraph_int_t no_of_real_nodes) { - igraph_integer_t i, j, k, l, n; - igraph_integer_t no_of_layers = igraph_i_layering_num_layers(layering); - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t i, j, k, l, n; + igraph_int_t no_of_layers = igraph_i_layering_num_layers(layering); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t neis1, neis2; igraph_vector_t xs[4]; igraph_vector_int_t roots, align; @@ -923,14 +913,14 @@ static igraph_error_t igraph_i_layout_sugiyama_place_nodes_horizontally(const ig * conflict */ n = igraph_vector_int_size(&neis1); for (j = 0; j < n; j++) { - igraph_integer_t u = IGRAPH_FROM(graph, j); - igraph_integer_t v = IGRAPH_TO(graph, j); + igraph_int_t u = IGRAPH_FROM(graph, j); + igraph_int_t v = IGRAPH_TO(graph, j); igraph_bool_t j_inner = IS_INNER_SEGMENT(u, v); igraph_bool_t crossing; for (k = j + 1; k < n; k++) { - igraph_integer_t w = IGRAPH_FROM(graph, k); - igraph_integer_t x = IGRAPH_TO(graph, k); + igraph_int_t w = IGRAPH_FROM(graph, k); + igraph_int_t x = IGRAPH_TO(graph, k); if (IS_INNER_SEGMENT(w, x) == j_inner) { continue; } @@ -1061,9 +1051,9 @@ static igraph_error_t igraph_i_layout_sugiyama_vertical_alignment(const igraph_t const igraph_vector_bool_t* ignored_edges, igraph_bool_t reverse, igraph_bool_t align_right, igraph_vector_int_t* roots, igraph_vector_int_t* align) { - igraph_integer_t i, j, k, n, di, dj, i_limit, j_limit, r; - igraph_integer_t no_of_layers = igraph_i_layering_num_layers(layering); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i, j, k, n, di, dj, i_limit, j_limit, r; + igraph_int_t no_of_layers = igraph_i_layering_num_layers(layering); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_neimode_t neimode = (reverse ? IGRAPH_OUT : IGRAPH_IN); igraph_vector_int_t neis; igraph_vector_t xs; @@ -1099,9 +1089,9 @@ static igraph_error_t igraph_i_layout_sugiyama_vertical_alignment(const igraph_t dj = align_right ? -1 : 1; j_limit = align_right ? -1 : igraph_vector_int_size(layer); for (; j != j_limit; j += dj) { - igraph_integer_t medians[2]; - igraph_integer_t vertex = VECTOR(*layer)[j]; - igraph_integer_t pos; + igraph_int_t medians[2]; + igraph_int_t vertex = VECTOR(*layer)[j]; + igraph_int_t pos; if (VECTOR(*align)[vertex] != vertex) /* This vertex is already aligned with some other vertex, @@ -1153,7 +1143,7 @@ static igraph_error_t igraph_i_layout_sugiyama_vertical_alignment(const igraph_t /* Try aligning with the medians */ for (k = 0; k < 2; k++) { - igraph_integer_t eid; + igraph_int_t eid; if (medians[k] < 0) { continue; } @@ -1201,8 +1191,8 @@ static igraph_error_t igraph_i_layout_sugiyama_horizontal_compaction(const igrap const igraph_vector_int_t* vertex_to_the_left, const igraph_vector_int_t* roots, const igraph_vector_int_t* align, igraph_real_t hgap, igraph_vector_t* xs) { - igraph_integer_t i; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i; + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_t shifts, old_xs; igraph_vector_int_t sinks; igraph_real_t shift; @@ -1240,7 +1230,7 @@ static igraph_error_t igraph_i_layout_sugiyama_horizontal_compaction(const igrap /* Calculate the absolute coordinates */ IGRAPH_CHECK(igraph_vector_update(&old_xs, xs)); for (i = 0; i < no_of_nodes; i++) { - igraph_integer_t root = VECTOR(*roots)[i]; + igraph_int_t root = VECTOR(*roots)[i]; VECTOR(*xs)[i] = VECTOR(old_xs)[root]; shift = VECTOR(shifts)[VECTOR(sinks)[root]]; if (shift < IGRAPH_INFINITY) { @@ -1256,13 +1246,13 @@ static igraph_error_t igraph_i_layout_sugiyama_horizontal_compaction(const igrap return IGRAPH_SUCCESS; } -static void igraph_i_layout_sugiyama_horizontal_compaction_place_block(igraph_integer_t v, +static void igraph_i_layout_sugiyama_horizontal_compaction_place_block(igraph_int_t v, const igraph_vector_int_t* vertex_to_the_left, const igraph_vector_int_t* roots, const igraph_vector_int_t* align, igraph_vector_int_t* sinks, igraph_vector_t* shifts, igraph_real_t hgap, igraph_vector_t* xs) { - igraph_integer_t u, w; - igraph_integer_t u_sink, v_sink; + igraph_int_t u, w; + igraph_int_t u_sink, v_sink; if (VECTOR(*xs)[v] >= 0) { return; diff --git a/src/vendor/cigraph/src/layout/umap.c b/src/vendor/cigraph/src/layout/umap.c index 247518e9d71..de5627e306c 100644 --- a/src/vendor/cigraph/src/layout/umap.c +++ b/src/vendor/cigraph/src/layout/umap.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -101,16 +101,16 @@ static igraph_error_t igraph_i_umap_find_sigma(const igraph_vector_t *distances, igraph_real_t sigma = 1; igraph_real_t sum; igraph_real_t tol = 0.01; - igraph_integer_t maxiter = 100; - igraph_integer_t no_of_neis = igraph_vector_int_size(eids); - igraph_integer_t eid; + igraph_int_t maxiter = 100; + igraph_int_t no_of_neis = igraph_vector_int_size(eids); + igraph_int_t eid; igraph_real_t step = sigma; - igraph_integer_t seen_max = 0; + igraph_int_t seen_max = 0; /* Binary search */ - for (igraph_integer_t iter = 0; iter < maxiter; iter++) { + for (igraph_int_t iter = 0; iter < maxiter; iter++) { sum = 0; - for (igraph_integer_t j = 0; j < no_of_neis; j++) { + for (igraph_int_t j = 0; j < no_of_neis; j++) { eid = VECTOR(*eids)[j]; sum += exp(-(VECTOR(*distances)[eid] - rho) / sigma); } @@ -219,9 +219,9 @@ igraph_error_t igraph_layout_umap_compute_weights( const igraph_vector_t *distances, igraph_vector_t *weights) { - igraph_integer_t no_of_vertices = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_neis; + igraph_int_t no_of_vertices = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_neis; igraph_vector_int_t eids; igraph_vector_int_list_t neighbors_seen; igraph_vector_list_t weights_seen; @@ -253,7 +253,7 @@ igraph_error_t igraph_layout_umap_compute_weights( IGRAPH_VECTOR_LIST_INIT_FINALLY(&weights_seen, no_of_vertices); /* Iterate over vertices x, like in the paper */ - for (igraph_integer_t i = 0; i < no_of_vertices; i++) { + for (igraph_int_t i = 0; i < no_of_vertices; i++) { /* Edges out of this vertex, e.g. to its k-nearest neighbors */ IGRAPH_CHECK(igraph_incident(graph, &eids, i, IGRAPH_OUT, IGRAPH_LOOPS)); no_of_neis = igraph_vector_int_size(&eids); @@ -267,8 +267,8 @@ igraph_error_t igraph_layout_umap_compute_weights( if (distances != NULL) { rho = VECTOR(*distances)[VECTOR(eids)[0]]; dist_max = rho; - for (igraph_integer_t j = 1; j < no_of_neis; j++) { - const igraph_integer_t eid = VECTOR(eids)[j]; + for (igraph_int_t j = 1; j < no_of_neis; j++) { + const igraph_int_t eid = VECTOR(eids)[j]; dist = VECTOR(*distances)[eid]; rho = fmin(rho, dist); dist_max = fmax(dist_max, dist); @@ -292,8 +292,8 @@ igraph_error_t igraph_layout_umap_compute_weights( } /* Convert to weights */ - for (igraph_integer_t j = 0; j < no_of_neis; j++) { - const igraph_integer_t eid = VECTOR(eids)[j]; + for (igraph_int_t j = 0; j < no_of_neis; j++) { + const igraph_int_t eid = VECTOR(eids)[j]; /* Basically, nodes closer than rho have probability 1, the rest is * exponentially penalized keeping rough cardinality */ @@ -306,7 +306,7 @@ igraph_error_t igraph_layout_umap_compute_weights( #endif /* Store in vector lists for later symmetrization */ - const igraph_integer_t k = IGRAPH_OTHER(graph, eid, i); + const igraph_int_t k = IGRAPH_OTHER(graph, eid, i); if (k == i) { IGRAPH_ERROR("Input graph must contain no self-loops.", IGRAPH_EINVAL); } @@ -323,9 +323,9 @@ igraph_error_t igraph_layout_umap_compute_weights( /* Symmetrize the weights. UMAP weights are probabilities of that edge being a * "real" connection. Unlike the distances, which can represent a directed graph, * weights are usually symmetric. We symmetrize via fuzzy union. */ - for (igraph_integer_t eid=0; eid < no_of_edges; eid++) { - const igraph_integer_t i = IGRAPH_FROM(graph, eid); - const igraph_integer_t k = IGRAPH_TO(graph, eid); + for (igraph_int_t eid=0; eid < no_of_edges; eid++) { + const igraph_int_t i = IGRAPH_FROM(graph, eid); + const igraph_int_t k = IGRAPH_TO(graph, eid); /* Direct weight, if found */ /* NOTE: this and the subsequent loop could be faster if we sorted the vectors @@ -334,7 +334,7 @@ igraph_error_t igraph_layout_umap_compute_weights( neighbors_seen_elt = igraph_vector_int_list_get_ptr(&neighbors_seen, i); weights_seen_elt = igraph_vector_list_get_ptr(&weights_seen, i); no_of_neis = igraph_vector_int_size(neighbors_seen_elt); - for (igraph_integer_t l=0; l < no_of_neis; l++) { + for (igraph_int_t l=0; l < no_of_neis; l++) { if (VECTOR(*neighbors_seen_elt)[l] == k) { weight = VECTOR(*weights_seen_elt)[l]; /* Tag this weight so we can ignore it later on if the opposite @@ -355,7 +355,7 @@ igraph_error_t igraph_layout_umap_compute_weights( neighbors_seen_elt = igraph_vector_int_list_get_ptr(&neighbors_seen, k); weights_seen_elt = igraph_vector_list_get_ptr(&weights_seen, k); no_of_neis = igraph_vector_int_size(neighbors_seen_elt); - for (igraph_integer_t l=0; l < no_of_neis; l++) { + for (igraph_int_t l=0; l < no_of_neis; l++) { if (VECTOR(*neighbors_seen_elt)[l] == i) { weight_inv = VECTOR(*weights_seen_elt)[l]; /* Tag this weight so we can ignore it later on if the opposite @@ -386,13 +386,13 @@ igraph_error_t igraph_layout_umap_compute_weights( /* Helper function to compute a and b parameters (smoothing probability metric in embedding space) */ static igraph_error_t igraph_i_umap_get_ab_residuals(igraph_vector_t *residuals, - igraph_real_t *squared_sum_res, igraph_integer_t nr_points, igraph_real_t a, + igraph_real_t *squared_sum_res, igraph_int_t nr_points, igraph_real_t a, igraph_real_t b, igraph_vector_t *powb, const igraph_vector_t *x, igraph_real_t min_dist) { igraph_real_t tmp; *squared_sum_res = 0; - for (igraph_integer_t i = 0; i < nr_points; i++) { + for (igraph_int_t i = 0; i < nr_points; i++) { /* The ideal probability is: * * P(d) = d < min_dist ? 1 : e^{-(d - min_dist)} @@ -470,7 +470,7 @@ igraph_error_t igraph_i_umap_fit_ab(igraph_real_t min_dist, igraph_real_t *a_p, /* Make a lattice from 0 to 3 * sigma with 300 points. This is what * umap.umap_.fit_ab_params does, but sigma is fixed to 1.0 here since * that's the default value used in scanpy and by virtually everyone */ - igraph_integer_t nr_points = 300; + igraph_int_t nr_points = 300; igraph_real_t end_point = 3.0; /* Initial values takes as reasonable assumptions from typical min_dist values */ igraph_real_t b = 0.8; @@ -502,7 +502,7 @@ igraph_error_t igraph_i_umap_fit_ab(igraph_real_t min_dist, igraph_real_t *a_p, IGRAPH_VECTOR_INIT_FINALLY(&powb, nr_points); /* Distance |x-y| (this is a lattice, there are no actual x and y) */ - for (igraph_integer_t i = 0; i < nr_points; i++) { + for (igraph_int_t i = 0; i < nr_points; i++) { VECTOR(x)[i] = (end_point / nr_points) * i + 0.001; /* added a 0.001 to prevent NaNs */ } @@ -513,7 +513,7 @@ igraph_error_t igraph_i_umap_fit_ab(igraph_real_t min_dist, igraph_real_t *a_p, #ifdef UMAP_DEBUG printf("start fit_ab\n"); #endif - for (igraph_integer_t iter = 0; iter < maxiter; iter++) { + for (igraph_int_t iter = 0; iter < maxiter; iter++) { IGRAPH_CHECK(igraph_i_umap_get_ab_residuals(&residuals, &squared_sum_res, nr_points, a, b, &powb, &x, min_dist)); @@ -533,7 +533,7 @@ igraph_error_t igraph_i_umap_fit_ab(igraph_real_t min_dist, igraph_real_t *a_p, } /* Jacobian (first derivatives) of squared residuals at (a, b) */ - for (igraph_integer_t i = 0; i < nr_points; i++) { + for (igraph_int_t i = 0; i < nr_points; i++) { tmp = 1 + a * VECTOR(powb)[i]; MATRIX(jacobian, i, 0) = - 2 * VECTOR(powb)[i] / tmp / tmp; MATRIX(jacobian, i, 1) = MATRIX(jacobian, i, 0) * a * log(VECTOR(x)[i]) * 2; @@ -562,9 +562,9 @@ igraph_error_t igraph_i_umap_fit_ab(igraph_real_t min_dist, igraph_real_t *a_p, /* Compute A and B, i.e. J^T @ J and J^T @ r */ MATRIX(jTj, 0, 0) = MATRIX(jTj, 0, 1) = MATRIX(jTj, 1, 0) = MATRIX(jTj, 1, 1) = 0; MATRIX(jTr, 0, 0) = MATRIX(jTr, 1, 0) = 0; - for (igraph_integer_t i = 0; i < nr_points; i++) { - for (igraph_integer_t j1 = 0; j1 < 2; j1++) { - for (igraph_integer_t j2 = 0; j2 < 2; j2++) { + for (igraph_int_t i = 0; i < nr_points; i++) { + for (igraph_int_t j1 = 0; j1 < 2; j1++) { + for (igraph_int_t j2 = 0; j2 < 2; j2++) { MATRIX(jTj, j1, j2) += MATRIX(jacobian, i, j1) * MATRIX(jacobian, i, j2); } MATRIX(jTr, j1, 0) += MATRIX(jacobian, i, j1) * VECTOR(residuals)[i]; @@ -592,7 +592,7 @@ igraph_error_t igraph_i_umap_fit_ab(igraph_real_t min_dist, igraph_real_t *a_p, printf("start line search, SSR before delta: %g, current SSR:, %g\n", squared_sum_res_old, squared_sum_res); #endif - for (igraph_integer_t k = 0; k < 30; k++) { + for (igraph_int_t k = 0; k < 30; k++) { /* Try new parameters */ da /= 2.0; db /= 2.0; @@ -648,9 +648,9 @@ static igraph_error_t igraph_i_umap_compute_cross_entropy(const igraph_t *graph, igraph_real_t *cross_entropy) { igraph_real_t mu, nu, xd, yd, sqd; - igraph_integer_t from, to; - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_vertices = igraph_vcount(graph); + igraph_int_t from, to; + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_vertices = igraph_vcount(graph); igraph_matrix_t edge_seen; IGRAPH_MATRIX_INIT_FINALLY(&edge_seen, no_of_vertices, no_of_vertices); @@ -663,7 +663,7 @@ static igraph_error_t igraph_i_umap_compute_cross_entropy(const igraph_t *graph, * repelling unconnected edges. * */ *cross_entropy = 0; - for (igraph_integer_t eid = 0; eid < no_of_edges; eid++) { + for (igraph_int_t eid = 0; eid < no_of_edges; eid++) { mu = VECTOR(*umap_weights)[eid]; /* Find vertices */ @@ -686,8 +686,8 @@ static igraph_error_t igraph_i_umap_compute_cross_entropy(const igraph_t *graph, MATRIX(edge_seen, from, to) = MATRIX(edge_seen, to, from) = 1; } /* Add the entropy from the missing edges */ - for (igraph_integer_t from = 0; from < no_of_vertices; from++) { - for (igraph_integer_t to = 0; to < from; to++) { + for (igraph_int_t from = 0; from < no_of_vertices; from++) { + for (igraph_int_t to = 0; to < from; to++) { if (MATRIX(edge_seen, from, to) > 0) { continue; } @@ -746,20 +746,20 @@ static igraph_error_t igraph_i_umap_apply_forces( igraph_real_t b, igraph_real_t learning_rate, igraph_bool_t avoid_neighbor_repulsion, - igraph_integer_t negative_sampling_rate, - igraph_integer_t epoch, + igraph_int_t negative_sampling_rate, + igraph_int_t epoch, igraph_vector_t *next_epoch_sample_per_edge) { - const igraph_integer_t no_of_vertices = igraph_matrix_nrow(layout); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - const igraph_integer_t ndim = igraph_matrix_ncol(layout); + const igraph_int_t no_of_vertices = igraph_matrix_nrow(layout); + const igraph_int_t no_of_edges = igraph_ecount(graph); + const igraph_int_t ndim = igraph_matrix_ncol(layout); igraph_vector_t from_emb, to_emb, delta; /* The following is only used for small graphs, to avoid repelling your neighbors * For large sparse graphs, it's not necessary. For large dense graphs, you should * not be doing UMAP. */ igraph_vector_int_t neis, negative_vertices; - const igraph_integer_t n_negative_vertices = + const igraph_int_t n_negative_vertices = (no_of_vertices - 1 < negative_sampling_rate) ? (no_of_vertices - 1) : negative_sampling_rate; /* Initialize vectors */ @@ -772,8 +772,8 @@ static igraph_error_t igraph_i_umap_apply_forces( } /* Iterate over edges. Stronger edges are sampled more often */ - for (igraph_integer_t eid = 0; eid < no_of_edges; eid++) { - igraph_integer_t from, to; + for (igraph_int_t eid = 0; eid < no_of_edges; eid++) { + igraph_int_t from, to; igraph_real_t force, dsq, force_d; /* Zero-weight edges do not affect vertex positions. They can @@ -810,7 +810,7 @@ static igraph_error_t igraph_i_umap_apply_forces( /* Current coordinates of both vertices */ dsq = 0; - for (igraph_integer_t d = 0; d != ndim; d++) { + for (igraph_int_t d = 0; d != ndim; d++) { VECTOR(from_emb)[d] = MATRIX(*layout, from, d); VECTOR(to_emb)[d] = MATRIX(*layout, to, d); VECTOR(delta)[d] = MATRIX(*layout, from, d) - MATRIX(*layout, to, d); @@ -821,7 +821,7 @@ static igraph_error_t igraph_i_umap_apply_forces( /* NOTE: If they are already together, no force needed */ if (dsq >= UMAP_MIN_DISTANCE_ATTRACTION * UMAP_MIN_DISTANCE_ATTRACTION) { force = igraph_i_umap_attract(dsq, a, b); - for (igraph_integer_t d = 0; d != ndim; d++) { + for (igraph_int_t d = 0; d != ndim; d++) { force_d = force * VECTOR(delta)[d]; /* clip force to avoid too rapid change */ force_d = igraph_i_umap_clip_force(force_d, UMAP_FORCE_LIMIT); @@ -837,7 +837,7 @@ static igraph_error_t igraph_i_umap_apply_forces( /* Random other nodes repel the focal vertex */ IGRAPH_CHECK(igraph_random_sample(&negative_vertices, 0, no_of_vertices - 2, n_negative_vertices)); - for (igraph_integer_t j = 0; j < n_negative_vertices; j++) { + for (igraph_int_t j = 0; j < n_negative_vertices; j++) { IGRAPH_ALLOW_INTERRUPTION(); @@ -855,10 +855,10 @@ static igraph_error_t igraph_i_umap_apply_forces( * should be only used for small graphs anyway, so it's fine */ igraph_bool_t skip = false; IGRAPH_CHECK(igraph_incident(graph, &neis, from, IGRAPH_ALL, IGRAPH_LOOPS)); - const igraph_integer_t nneis = igraph_vector_int_size(&neis); - for (igraph_integer_t k = 0; k < nneis; k++) { - igraph_integer_t eid2 = VECTOR(neis)[k]; - igraph_integer_t from2, to2; + const igraph_int_t nneis = igraph_vector_int_size(&neis); + for (igraph_int_t k = 0; k < nneis; k++) { + igraph_int_t eid2 = VECTOR(neis)[k]; + igraph_int_t from2, to2; from2 = IGRAPH_FROM(graph, eid2); to2 = IGRAPH_TO(graph, eid2); if (((from2 == from) && (to2 == to)) || ((from2 == to) && (from == to2))) { @@ -873,7 +873,7 @@ static igraph_error_t igraph_i_umap_apply_forces( /* Get layout of random neighbor and gradient in embedding */ dsq = 0; - for (igraph_integer_t d = 0; d != ndim; d++) { + for (igraph_int_t d = 0; d != ndim; d++) { VECTOR(to_emb)[d] = MATRIX(*layout, to, d); VECTOR(delta)[d] = MATRIX(*layout, from, d) - MATRIX(*layout, to, d); dsq += VECTOR(delta)[d] * VECTOR(delta)[d]; @@ -883,7 +883,7 @@ static igraph_error_t igraph_i_umap_apply_forces( * that is no weight, no edge */ force = igraph_i_umap_repel(dsq, a, b); /* The repulsive force is already *away* from the other (non-neighbor) vertex */ - for (igraph_integer_t d = 0; d != ndim; d++) { + for (igraph_int_t d = 0; d != ndim; d++) { force_d = force * VECTOR(delta)[d]; /* clip force to avoid too rapid change */ @@ -926,11 +926,11 @@ static igraph_error_t igraph_i_umap_optimize_layout_stochastic_gradient( igraph_real_t a, igraph_real_t b, igraph_matrix_t *layout, - igraph_integer_t epochs, - igraph_integer_t negative_sampling_rate) { + igraph_int_t epochs, + igraph_int_t negative_sampling_rate) { igraph_real_t learning_rate = 1; - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_t next_epoch_sample_per_edge; #ifdef UMAP_DEBUG @@ -963,7 +963,7 @@ static igraph_error_t igraph_i_umap_optimize_layout_stochastic_gradient( graph, umap_weights, layout, a, b, &cross_entropy); #endif - for (igraph_integer_t e = 0; e < epochs; e++) { + for (igraph_int_t e = 0; e < epochs; e++) { /* Apply (stochastic) forces */ IGRAPH_CHECK(igraph_i_umap_apply_forces( graph, @@ -997,11 +997,11 @@ static igraph_error_t igraph_i_umap_optimize_layout_stochastic_gradient( /* Center 2D layout around (0,0) at the end, just for convenience */ static void igraph_i_umap_center_layout(igraph_matrix_t *layout) { - igraph_integer_t no_of_vertices = igraph_matrix_nrow(layout); + igraph_int_t no_of_vertices = igraph_matrix_nrow(layout); igraph_real_t xm = 0, ym = 0; /* Compute center */ - for (igraph_integer_t i = 0; i < no_of_vertices; i++) { + for (igraph_int_t i = 0; i < no_of_vertices; i++) { xm += MATRIX(*layout, i, 0); ym += MATRIX(*layout, i, 1); } @@ -1009,7 +1009,7 @@ static void igraph_i_umap_center_layout(igraph_matrix_t *layout) { ym /= no_of_vertices; /* Shift vertices */ - for (igraph_integer_t i = 0; i < no_of_vertices; i++) { + for (igraph_int_t i = 0; i < no_of_vertices; i++) { MATRIX(*layout, i, 0) -= xm; MATRIX(*layout, i, 1) -= ym; } @@ -1017,11 +1017,11 @@ static void igraph_i_umap_center_layout(igraph_matrix_t *layout) { /* Center 3D layout around (0,0,0) at the end, just for convenience */ static void igraph_i_umap_center_layout_3d(igraph_matrix_t *layout) { - igraph_integer_t no_of_vertices = igraph_matrix_nrow(layout); + igraph_int_t no_of_vertices = igraph_matrix_nrow(layout); igraph_real_t xm = 0, ym = 0, zm = 0; /* Compute center */ - for (igraph_integer_t i = 0; i < no_of_vertices; i++) { + for (igraph_int_t i = 0; i < no_of_vertices; i++) { xm += MATRIX(*layout, i, 0); ym += MATRIX(*layout, i, 1); zm += MATRIX(*layout, i, 2); @@ -1031,7 +1031,7 @@ static void igraph_i_umap_center_layout_3d(igraph_matrix_t *layout) { zm /= no_of_vertices; /* Shift vertices */ - for (igraph_integer_t i = 0; i < no_of_vertices; i++) { + for (igraph_int_t i = 0; i < no_of_vertices; i++) { MATRIX(*layout, i, 0) -= xm; MATRIX(*layout, i, 1) -= ym; MATRIX(*layout, i, 2) -= zm; @@ -1047,19 +1047,19 @@ static igraph_error_t igraph_i_layout_umap( igraph_bool_t use_seed, const igraph_vector_t *distances, igraph_real_t min_dist, - igraph_integer_t epochs, - igraph_integer_t ndim, + igraph_int_t epochs, + igraph_int_t ndim, igraph_bool_t distances_are_weights) { - const igraph_integer_t no_of_edges = igraph_ecount(graph); - const igraph_integer_t no_of_vertices = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_vertices = igraph_vcount(graph); /* probabilities of each edge being a real connection */ igraph_vector_t weights; igraph_vector_t *weightsp; /* The smoothing parameters given min_dist */ igraph_real_t a, b; /* How many repulsions for each attraction */ - igraph_integer_t negative_sampling_rate = 5; + igraph_int_t negative_sampling_rate = 5; /* Check input arguments */ if (min_dist < 0) { @@ -1233,7 +1233,7 @@ igraph_error_t igraph_layout_umap(const igraph_t *graph, igraph_bool_t use_seed, const igraph_vector_t *distances, igraph_real_t min_dist, - igraph_integer_t epochs, + igraph_int_t epochs, igraph_bool_t distances_are_weights) { return igraph_i_layout_umap(graph, res, use_seed, distances, min_dist, epochs, 2, distances_are_weights); @@ -1278,7 +1278,7 @@ igraph_error_t igraph_layout_umap_3d(const igraph_t *graph, igraph_bool_t use_seed, const igraph_vector_t *distances, igraph_real_t min_dist, - igraph_integer_t epochs, + igraph_int_t epochs, igraph_bool_t distances_are_weights) { return igraph_i_layout_umap(graph, res, use_seed, distances, min_dist, epochs, 3, distances_are_weights); diff --git a/src/vendor/cigraph/src/linalg/arpack.c b/src/vendor/cigraph/src/linalg/arpack.c index f3157a9e311..0877d08c583 100644 --- a/src/vendor/cigraph/src/linalg/arpack.c +++ b/src/vendor/cigraph/src/linalg/arpack.c @@ -1,6 +1,6 @@ /* vim:set ts=4 sw=4 sts=4 noet: */ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -183,8 +183,8 @@ igraph_arpack_options_t* igraph_arpack_options_get_default(void) { * Time complexity: O(maxncv*(maxldv+maxn)). */ -igraph_error_t igraph_arpack_storage_init(igraph_arpack_storage_t *s, igraph_integer_t maxn, - igraph_integer_t maxncv, igraph_integer_t maxldv, +igraph_error_t igraph_arpack_storage_init(igraph_arpack_storage_t *s, igraph_int_t maxn, + igraph_int_t maxncv, igraph_int_t maxldv, igraph_bool_t symm) { /* TODO: check arguments */ @@ -1406,12 +1406,12 @@ igraph_error_t igraph_arpack_rnsolve(igraph_arpack_function_t *fun, void *extra, */ igraph_error_t igraph_arpack_unpack_complex(igraph_matrix_t *vectors, igraph_matrix_t *values, - igraph_integer_t nev) { + igraph_int_t nev) { - igraph_integer_t nodes = igraph_matrix_nrow(vectors); - igraph_integer_t no_evs = igraph_matrix_nrow(values); - igraph_integer_t i, j; - igraph_integer_t new_vector_pos, vector_pos; + igraph_int_t nodes = igraph_matrix_nrow(vectors); + igraph_int_t no_evs = igraph_matrix_nrow(values); + igraph_int_t i, j; + igraph_int_t new_vector_pos, vector_pos; igraph_matrix_t new_vectors; /* Error checks */ diff --git a/src/vendor/cigraph/src/linalg/arpack_internal.h b/src/vendor/cigraph/src/linalg/arpack_internal.h index 1d90481b1b4..c7f7e54c135 100644 --- a/src/vendor/cigraph/src/linalg/arpack_internal.h +++ b/src/vendor/cigraph/src/linalg/arpack_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/linalg/blas.c b/src/vendor/cigraph/src/linalg/blas.c index 0eb0c8bcc96..3e46ee1a69e 100644 --- a/src/vendor/cigraph/src/linalg/blas.c +++ b/src/vendor/cigraph/src/linalg/blas.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -113,10 +113,10 @@ igraph_error_t igraph_blas_dgemm(igraph_bool_t transpose_a, igraph_bool_t transp char trans_a = transpose_a ? 'T' : 'N'; char trans_b = transpose_b ? 'T' : 'N'; int m, n, k, lda, ldb, ldc; - igraph_integer_t nrow_oa = transpose_a ? igraph_matrix_ncol(a) : igraph_matrix_nrow(a); - igraph_integer_t ncol_oa = transpose_a ? igraph_matrix_nrow(a) : igraph_matrix_ncol(a); - igraph_integer_t nrow_ob = transpose_b ? igraph_matrix_ncol(b) : igraph_matrix_nrow(b); - igraph_integer_t ncol_ob = transpose_b ? igraph_matrix_nrow(b) : igraph_matrix_ncol(b); + igraph_int_t nrow_oa = transpose_a ? igraph_matrix_ncol(a) : igraph_matrix_nrow(a); + igraph_int_t ncol_oa = transpose_a ? igraph_matrix_nrow(a) : igraph_matrix_ncol(a); + igraph_int_t nrow_ob = transpose_b ? igraph_matrix_ncol(b) : igraph_matrix_nrow(b); + igraph_int_t ncol_ob = transpose_b ? igraph_matrix_nrow(b) : igraph_matrix_ncol(b); if (ncol_oa != nrow_ob) { IGRAPH_ERRORF("%" IGRAPH_PRId "-by-%" IGRAPH_PRId " and %" IGRAPH_PRId "-by-%" IGRAPH_PRId diff --git a/src/vendor/cigraph/src/linalg/blas_internal.h b/src/vendor/cigraph/src/linalg/blas_internal.h index df1d4fdf49a..485fcad53a1 100644 --- a/src/vendor/cigraph/src/linalg/blas_internal.h +++ b/src/vendor/cigraph/src/linalg/blas_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/linalg/eigen.c b/src/vendor/cigraph/src/linalg/eigen.c index af70fafcbda..d999d0a8ff2 100644 --- a/src/vendor/cigraph/src/linalg/eigen.c +++ b/src/vendor/cigraph/src/linalg/eigen.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -481,9 +481,8 @@ static igraph_error_t igraph_i_eigen_matrix_sym_arpack_cb(igraph_real_t *to, IGRAPH_CHECK(igraph_blas_dgemv_array(/*transpose=*/ 0, /*alpha=*/ 1.0, data->A, from, /*beta=*/ 0.0, to)); } else { /* data->sA */ - igraph_vector_t vto, vfrom; - igraph_vector_view(&vto, to, n); - igraph_vector_view(&vfrom, from, n); + const igraph_vector_t vfrom = igraph_vector_view(from, n); + igraph_vector_t vto = igraph_vector_view(to, n); igraph_vector_null(&vto); igraph_sparsemat_gaxpy(data->sA, &vfrom, &vto); } @@ -673,8 +672,8 @@ typedef struct igraph_i_eml_cmp_t { static int igraph_i_eigen_matrix_lapack_cmp_lm(void *extra, const void *a, const void *b) { igraph_i_eml_cmp_t *myextra = (igraph_i_eml_cmp_t *) extra; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t a_m = VECTOR(*myextra->mag)[*aa]; igraph_real_t b_m = VECTOR(*myextra->mag)[*bb]; @@ -719,8 +718,8 @@ static int igraph_i_eigen_matrix_lapack_cmp_lm(void *extra, const void *a, static int igraph_i_eigen_matrix_lapack_cmp_sm(void *extra, const void *a, const void *b) { igraph_i_eml_cmp_t *myextra = (igraph_i_eml_cmp_t *) extra; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t a_m = VECTOR(*myextra->mag)[*aa]; igraph_real_t b_m = VECTOR(*myextra->mag)[*bb]; @@ -764,8 +763,8 @@ static int igraph_i_eigen_matrix_lapack_cmp_lr(void *extra, const void *a, const void *b) { igraph_i_eml_cmp_t *myextra = (igraph_i_eml_cmp_t *) extra; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t a_r = VECTOR(*myextra->real)[*aa]; igraph_real_t b_r = VECTOR(*myextra->real)[*bb]; @@ -804,8 +803,8 @@ static int igraph_i_eigen_matrix_lapack_cmp_sr(void *extra, const void *a, const void *b) { igraph_i_eml_cmp_t *myextra = (igraph_i_eml_cmp_t *) extra; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t a_r = VECTOR(*myextra->real)[*aa]; igraph_real_t b_r = VECTOR(*myextra->real)[*bb]; @@ -842,8 +841,8 @@ static int igraph_i_eigen_matrix_lapack_cmp_li(void *extra, const void *a, const void *b) { igraph_i_eml_cmp_t *myextra = (igraph_i_eml_cmp_t *) extra; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t a_i = VECTOR(*myextra->imag)[*aa]; igraph_real_t b_i = VECTOR(*myextra->imag)[*bb]; @@ -881,8 +880,8 @@ static int igraph_i_eigen_matrix_lapack_cmp_si(void *extra, const void *a, const void *b) { igraph_i_eml_cmp_t *myextra = (igraph_i_eml_cmp_t *) extra; - igraph_integer_t *aa = (igraph_integer_t*) a; - igraph_integer_t *bb = (igraph_integer_t*) b; + igraph_int_t *aa = (igraph_int_t*) a; + igraph_int_t *bb = (igraph_int_t*) b; igraph_real_t a_i = VECTOR(*myextra->imag)[*aa]; igraph_real_t b_i = VECTOR(*myextra->imag)[*bb]; @@ -938,7 +937,7 @@ static igraph_error_t igraph_i_eigen_matrix_lapack_reorder(const igraph_vector_t igraph_bool_t hasmag = false; int nev; int howmany = 0, start = 0; - igraph_integer_t i; + igraph_int_t i; igraph_i_eigen_matrix_lapack_cmp_t cmpfunc = 0; igraph_i_eml_cmp_t vextra; void *extra; @@ -1012,17 +1011,17 @@ static igraph_error_t igraph_i_eigen_matrix_lapack_reorder(const igraph_vector_t if (values) { IGRAPH_CHECK(igraph_vector_complex_resize(values, howmany)); for (i = 0; i < howmany; i++) { - igraph_integer_t x = VECTOR(idx)[start + i]; + igraph_int_t x = VECTOR(idx)[start + i]; VECTOR(*values)[i] = igraph_complex(VECTOR(*real)[x], VECTOR(*imag)[x]); } } if (vectors) { - igraph_integer_t n = igraph_matrix_nrow(compressed); + igraph_int_t n = igraph_matrix_nrow(compressed); IGRAPH_CHECK(igraph_matrix_complex_resize(vectors, n, howmany)); for (i = 0; i < howmany; i++) { - igraph_integer_t j, x = VECTOR(idx)[start + i]; + igraph_int_t j, x = VECTOR(idx)[start + i]; if (VECTOR(*imag)[x] == 0) { /* real eigenvalue */ for (j = 0; j < n; j++) { @@ -1058,7 +1057,7 @@ static igraph_error_t igraph_i_eigen_matrix_lapack_common(const igraph_matrix_t igraph_vector_t valuesreal, valuesimag; igraph_matrix_t vectorsright, *myvectors = vectors ? &vectorsright : 0; - igraph_integer_t n = igraph_matrix_nrow(A); + igraph_int_t n = igraph_matrix_nrow(A); int info = 1; IGRAPH_VECTOR_INIT_FINALLY(&valuesreal, n); @@ -1285,14 +1284,14 @@ static igraph_error_t igraph_i_eigen_adjacency_arpack_sym_cb(igraph_real_t *to, int n, void *extra) { igraph_adjlist_t *adjlist = (igraph_adjlist_t *) extra; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; for (i = 0; i < n; i++) { neis = igraph_adjlist_get(adjlist, i); nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += from[nei]; } } @@ -1314,7 +1313,7 @@ static igraph_error_t igraph_i_eigen_adjacency_arpack(const igraph_t *graph, igraph_adjlist_t adjlist; void *extra = (void*) &adjlist; - igraph_integer_t n = igraph_vcount(graph); + igraph_int_t n = igraph_vcount(graph); if (!options) { IGRAPH_ERROR("`options' must be given for ARPACK algorithm", diff --git a/src/vendor/cigraph/src/linalg/lapack.c b/src/vendor/cigraph/src/linalg/lapack.c index 80de98a76f2..aa6f9c34df3 100644 --- a/src/vendor/cigraph/src/linalg/lapack.c +++ b/src/vendor/cigraph/src/linalg/lapack.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -37,11 +37,11 @@ static igraph_error_t igraph_vector_int_update_from_fortran( igraph_vector_int_t* vec, const igraph_vector_fortran_int_t* fortran_vec ) { - igraph_integer_t size = igraph_vector_fortran_int_size(fortran_vec); + igraph_int_t size = igraph_vector_fortran_int_size(fortran_vec); IGRAPH_CHECK(igraph_vector_int_resize(vec, size)); - for (igraph_integer_t i = 0; i < size; i++) { + for (igraph_int_t i = 0; i < size; i++) { VECTOR(*vec)[i] = VECTOR(*fortran_vec)[i]; } @@ -52,7 +52,7 @@ static igraph_error_t igraph_vector_int_update_from_fortran( static igraph_error_t igraph_vector_int_copy_to_fortran( const igraph_vector_int_t* vec, igraph_vector_fortran_int_t* fortran_vec ) { - igraph_integer_t i, size = igraph_vector_int_size(vec); + igraph_int_t i, size = igraph_vector_int_size(vec); IGRAPH_CHECK(igraph_vector_fortran_int_resize(fortran_vec, size)); diff --git a/src/vendor/cigraph/src/linalg/lapack_internal.h b/src/vendor/cigraph/src/linalg/lapack_internal.h index a6dd3feeabe..459a64c451e 100644 --- a/src/vendor/cigraph/src/linalg/lapack_internal.h +++ b/src/vendor/cigraph/src/linalg/lapack_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/math/complex.c b/src/vendor/cigraph/src/math/complex.c index ef3efaffc2f..60f96e87c85 100644 --- a/src/vendor/cigraph/src/math/complex.c +++ b/src/vendor/cigraph/src/math/complex.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2010-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/math/safe_intop.c b/src/vendor/cigraph/src/math/safe_intop.c index 15ac4e4d1fb..f1aefbff66d 100644 --- a/src/vendor/cigraph/src/math/safe_intop.c +++ b/src/vendor/cigraph/src/math/safe_intop.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team it under the terms of the GNU General Public License as published by @@ -20,22 +20,22 @@ #include "math/safe_intop.h" /* Use IGRAPH_SAFE_ADD() instead unless there is a need to intercept errors. */ -igraph_error_t igraph_i_safe_add(igraph_integer_t a, igraph_integer_t b, igraph_integer_t *res) { +igraph_error_t igraph_i_safe_add(igraph_int_t a, igraph_int_t b, igraph_int_t *res) { IGRAPH_SAFE_ADD(a, b, res); return IGRAPH_SUCCESS; } /* Use IGRAPH_SAFE_MULT() instead unless there is a need to intercept errors. */ -igraph_error_t igraph_i_safe_mult(igraph_integer_t a, igraph_integer_t b, igraph_integer_t *res) { +igraph_error_t igraph_i_safe_mult(igraph_int_t a, igraph_int_t b, igraph_int_t *res) { IGRAPH_SAFE_MULT(a, b, res); return IGRAPH_SUCCESS; } /* Overflow-safe sum of integer vector elements. */ -igraph_error_t igraph_i_safe_vector_int_sum(const igraph_vector_int_t *vec, igraph_integer_t *res) { - const igraph_integer_t n = igraph_vector_int_size(vec); - igraph_integer_t sum = 0; - for (igraph_integer_t i=0; i < n; ++i) { +igraph_error_t igraph_i_safe_vector_int_sum(const igraph_vector_int_t *vec, igraph_int_t *res) { + const igraph_int_t n = igraph_vector_int_size(vec); + igraph_int_t sum = 0; + for (igraph_int_t i=0; i < n; ++i) { IGRAPH_SAFE_ADD(sum, VECTOR(*vec)[i], &sum); } *res = sum; @@ -43,10 +43,10 @@ igraph_error_t igraph_i_safe_vector_int_sum(const igraph_vector_int_t *vec, igra } /* Overflow-safe product of integer vector elements. */ -igraph_error_t igraph_i_safe_vector_int_prod(const igraph_vector_int_t *vec, igraph_integer_t *res) { - const igraph_integer_t n = igraph_vector_int_size(vec); - igraph_integer_t prod = 1; - for (igraph_integer_t i=0; i < n; ++i) { +igraph_error_t igraph_i_safe_vector_int_prod(const igraph_vector_int_t *vec, igraph_int_t *res) { + const igraph_int_t n = igraph_vector_int_size(vec); + igraph_int_t prod = 1; + for (igraph_int_t i=0; i < n; ++i) { IGRAPH_SAFE_MULT(prod, VECTOR(*vec)[i], &prod); } *res = prod; @@ -59,7 +59,7 @@ igraph_error_t igraph_i_safe_vector_int_prod(const igraph_vector_int_t *vec, igr * This function must not be called with negative input. * Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */ -igraph_error_t igraph_i_safe_next_pow_2(igraph_integer_t k, igraph_integer_t *res) { +igraph_error_t igraph_i_safe_next_pow_2(igraph_int_t k, igraph_int_t *res) { IGRAPH_ASSERT(k >= 0); if (k == 0) { *res = 0; @@ -93,18 +93,18 @@ igraph_error_t igraph_i_safe_next_pow_2(igraph_integer_t k, igraph_integer_t *re * Computes 2^k as an integer, with overflow check. * This function must not be called with negative input. */ -igraph_error_t igraph_i_safe_exp2(igraph_integer_t k, igraph_integer_t *res) { +igraph_error_t igraph_i_safe_exp2(igraph_int_t k, igraph_int_t *res) { IGRAPH_ASSERT(k >= 0); if (k > IGRAPH_INTEGER_SIZE-2) { IGRAPH_ERRORF("Overflow when raising 2 to power %" IGRAPH_PRId ".", IGRAPH_EOVERFLOW, k); } - *res = (igraph_integer_t) 1 << k; + *res = (igraph_int_t) 1 << k; return IGRAPH_SUCCESS; } /** - * Checks if an igraph_real_t with no fractional part is representable as an igraph_integer_t. + * Checks if an igraph_real_t with no fractional part is representable as an igraph_int_t. * Avoids invoking undefined behaviour. * Must not be called with an input that has a non-zero fractional part. */ @@ -129,13 +129,13 @@ igraph_bool_t igraph_i_is_real_representable_as_integer(igraph_real_t value) { } /** - * Converts an igraph_real_t into an igraph_integer_t with range checks to + * Converts an igraph_real_t into an igraph_int_t with range checks to * protect from undefined behaviour. The input value is assumed to have no * fractional part. */ -static igraph_error_t igraph_i_safe_real_to_int(igraph_real_t value, igraph_integer_t *result) { +static igraph_error_t igraph_i_safe_real_to_int(igraph_real_t value, igraph_int_t *result) { if (igraph_i_is_real_representable_as_integer(value)) { - *result = (igraph_integer_t) value; + *result = (igraph_int_t) value; return IGRAPH_SUCCESS; } else if (isnan(value)) { IGRAPH_ERROR("NaN cannot be converted to an integer.", IGRAPH_EINVAL); @@ -146,41 +146,41 @@ static igraph_error_t igraph_i_safe_real_to_int(igraph_real_t value, igraph_inte } /** - * Converts an igraph_real_t into an igraph_integer_t with range checks to + * Converts an igraph_real_t into an igraph_int_t with range checks to * protect from undefined behaviour. The input value is converted into an * integer with ceil(). */ -igraph_error_t igraph_i_safe_ceil(igraph_real_t value, igraph_integer_t *result) { +igraph_error_t igraph_i_safe_ceil(igraph_real_t value, igraph_int_t *result) { return igraph_i_safe_real_to_int(ceil(value), result); } /** - * Converts an igraph_real_t into an igraph_integer_t with range checks to + * Converts an igraph_real_t into an igraph_int_t with range checks to * protect from undefined behaviour. The input value is converted into an * integer with floor(). */ -igraph_error_t igraph_i_safe_floor(igraph_real_t value, igraph_integer_t *result) { +igraph_error_t igraph_i_safe_floor(igraph_real_t value, igraph_int_t *result) { return igraph_i_safe_real_to_int(floor(value), result); } /** - * Converts an igraph_real_t into an igraph_integer_t with range checks to + * Converts an igraph_real_t into an igraph_int_t with range checks to * protect from undefined behaviour. The input value is converted into an * integer with round(). * * This is typically the slowest of this set of functions. */ -igraph_error_t igraph_i_safe_round(igraph_real_t value, igraph_integer_t* result) { +igraph_error_t igraph_i_safe_round(igraph_real_t value, igraph_int_t* result) { return igraph_i_safe_real_to_int(round(value), result); } /** - * Converts an igraph_real_t into an igraph_integer_t with range checks to + * Converts an igraph_real_t into an igraph_int_t with range checks to * protect from undefined behaviour. The input value is converted into an * integer with trunc(). * * This is typically the fastest of this set of functions. */ -igraph_error_t igraph_i_safe_trunc(igraph_real_t value, igraph_integer_t* result) { +igraph_error_t igraph_i_safe_trunc(igraph_real_t value, igraph_int_t* result) { return igraph_i_safe_real_to_int(trunc(value), result); } diff --git a/src/vendor/cigraph/src/math/safe_intop.h b/src/vendor/cigraph/src/math/safe_intop.h index e8b3605f697..ed917233170 100644 --- a/src/vendor/cigraph/src/math/safe_intop.h +++ b/src/vendor/cigraph/src/math/safe_intop.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2020 The igraph development team it under the terms of the GNU General Public License as published by @@ -45,8 +45,8 @@ IGRAPH_BEGIN_C_DECLS #define IGRAPH_SAFE_ADD(a, b, res) \ do { \ - igraph_integer_t _safe_a = (a), _safe_b = (b); \ - igraph_integer_t _safe_sum; \ + igraph_int_t _safe_a = (a), _safe_b = (b); \ + igraph_int_t _safe_sum; \ if (__builtin_add_overflow(_safe_a, _safe_b, &_safe_sum)) { \ IGRAPH_ERRORF("Overflow when adding %" IGRAPH_PRId " and %" IGRAPH_PRId ".", IGRAPH_EOVERFLOW, _safe_a, _safe_b); \ } \ @@ -55,8 +55,8 @@ IGRAPH_BEGIN_C_DECLS #define IGRAPH_SAFE_MULT(a, b, res) \ do { \ - igraph_integer_t _safe_a = (a), _safe_b = (b); \ - igraph_integer_t _safe_prod; \ + igraph_int_t _safe_a = (a), _safe_b = (b); \ + igraph_int_t _safe_prod; \ if (__builtin_mul_overflow(_safe_a, _safe_b, &_safe_prod)) { \ IGRAPH_ERRORF("Overflow when multiplying %" IGRAPH_PRId " and %" IGRAPH_PRId ".", IGRAPH_EOVERFLOW, _safe_a, _safe_b); \ } \ @@ -67,8 +67,8 @@ IGRAPH_BEGIN_C_DECLS #define IGRAPH_SAFE_ADD(a, b, res) \ do { \ - igraph_integer_t _safe_a = (a), _safe_b = (b); \ - igraph_integer_t _safe_sum; \ + igraph_int_t _safe_a = (a), _safe_b = (b); \ + igraph_int_t _safe_sum; \ if (((_safe_b > 0) && (_safe_a > (IGRAPH_INTEGER_MAX - _safe_b))) || \ ((_safe_b < 0) && (_safe_a < (IGRAPH_INTEGER_MIN - _safe_b)))) { \ IGRAPH_ERRORF("Overflow when adding %" IGRAPH_PRId " and %" IGRAPH_PRId ".", IGRAPH_EOVERFLOW, _safe_a, _safe_b); \ @@ -79,8 +79,8 @@ IGRAPH_BEGIN_C_DECLS #define IGRAPH_SAFE_MULT(a, b, res) \ do { \ - igraph_integer_t _safe_a = (a), _safe_b = (b); \ - igraph_integer_t _safe_prod; \ + igraph_int_t _safe_a = (a), _safe_b = (b); \ + igraph_int_t _safe_prod; \ int err=0; \ if (_safe_a > 0) { /* _safe_a is positive */ \ if (_safe_b > 0) { /* _safe_a and _safe_b are positive */ \ @@ -115,24 +115,24 @@ IGRAPH_BEGIN_C_DECLS /* Overflow-safe calculation of "n choose 2" = n*(n-1) / 2, assuming that n >= 0. */ #define IGRAPH_SAFE_N_CHOOSE_2(n, res) \ do { \ - igraph_integer_t _safe_n = (n); \ + igraph_int_t _safe_n = (n); \ if (_safe_n % 2 == 0) IGRAPH_SAFE_MULT(_safe_n / 2, _safe_n - 1, res); \ else IGRAPH_SAFE_MULT(_safe_n, (_safe_n - 1) / 2, res); \ } while (0) IGRAPH_FUNCATTR_CONST igraph_bool_t igraph_i_is_real_representable_as_integer(igraph_real_t value); -igraph_error_t igraph_i_safe_ceil(igraph_real_t value, igraph_integer_t* result); -igraph_error_t igraph_i_safe_floor(igraph_real_t value, igraph_integer_t* result); -igraph_error_t igraph_i_safe_round(igraph_real_t value, igraph_integer_t* result); -igraph_error_t igraph_i_safe_trunc(igraph_real_t value, igraph_integer_t* result); - -igraph_error_t igraph_i_safe_next_pow_2(igraph_integer_t k, igraph_integer_t *res); -igraph_error_t igraph_i_safe_exp2(igraph_integer_t k, igraph_integer_t *res); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_safe_add(igraph_integer_t a, igraph_integer_t b, igraph_integer_t *res); -IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_safe_mult(igraph_integer_t a, igraph_integer_t b, igraph_integer_t *res); -igraph_error_t igraph_i_safe_vector_int_sum(const igraph_vector_int_t *vec, igraph_integer_t *res); -igraph_error_t igraph_i_safe_vector_int_prod(const igraph_vector_int_t *vec, igraph_integer_t *res); +igraph_error_t igraph_i_safe_ceil(igraph_real_t value, igraph_int_t* result); +igraph_error_t igraph_i_safe_floor(igraph_real_t value, igraph_int_t* result); +igraph_error_t igraph_i_safe_round(igraph_real_t value, igraph_int_t* result); +igraph_error_t igraph_i_safe_trunc(igraph_real_t value, igraph_int_t* result); + +igraph_error_t igraph_i_safe_next_pow_2(igraph_int_t k, igraph_int_t *res); +igraph_error_t igraph_i_safe_exp2(igraph_int_t k, igraph_int_t *res); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_safe_add(igraph_int_t a, igraph_int_t b, igraph_int_t *res); +IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_safe_mult(igraph_int_t a, igraph_int_t b, igraph_int_t *res); +igraph_error_t igraph_i_safe_vector_int_sum(const igraph_vector_int_t *vec, igraph_int_t *res); +igraph_error_t igraph_i_safe_vector_int_prod(const igraph_vector_int_t *vec, igraph_int_t *res); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/math/utils.c b/src/vendor/cigraph/src/math/utils.c index 9b64c184f73..48d822def0c 100644 --- a/src/vendor/cigraph/src/math/utils.c +++ b/src/vendor/cigraph/src/math/utils.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2007-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/misc/bipartite.c b/src/vendor/cigraph/src/misc/bipartite.c index 95ea1111791..83bcbab8a4b 100644 --- a/src/vendor/cigraph/src/misc/bipartite.c +++ b/src/vendor/cigraph/src/misc/bipartite.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2008-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -30,8 +30,10 @@ #include "core/interruption.h" #include "graph/attributes.h" -#include "random/random_internal.h" +#include "internal/utils.h" #include "math/safe_intop.h" +#include "misc/graphicality.h" +#include "random/random_internal.h" /** * \section about_bipartite Bipartite networks in igraph @@ -67,16 +69,16 @@ * * \param graph The input graph. * \param types Boolean vector giving the vertex types of the graph. - * \param vcount1 Pointer to an \c igraph_integer_t, the number of + * \param vcount1 Pointer to an \c igraph_int_t, the number of * vertices in the first projection is stored here. May be \c NULL * if not needed. - * \param ecount1 Pointer to an \c igraph_integer_t, the number of + * \param ecount1 Pointer to an \c igraph_int_t, the number of * edges in the first projection is stored here. May be \c NULL * if not needed. - * \param vcount2 Pointer to an \c igraph_integer_t, the number of + * \param vcount2 Pointer to an \c igraph_int_t, the number of * vertices in the second projection is stored here. May be \c NULL * if not needed. - * \param ecount2 Pointer to an \c igraph_integer_t, the number of + * \param ecount2 Pointer to an \c igraph_int_t, the number of * edges in the second projection is stored here. May be \c NULL * if not needed. * \return Error code. @@ -91,13 +93,13 @@ igraph_error_t igraph_bipartite_projection_size(const igraph_t *graph, const igraph_vector_bool_t *types, - igraph_integer_t *vcount1, - igraph_integer_t *ecount1, - igraph_integer_t *vcount2, - igraph_integer_t *ecount2) { + igraph_int_t *vcount1, + igraph_int_t *ecount1, + igraph_int_t *vcount2, + igraph_int_t *ecount2) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t vc1 = 0, ec1 = 0, vc2 = 0, ec2 = 0; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t vc1 = 0, ec1 = 0, vc2 = 0, ec2 = 0; igraph_adjlist_t adjlist; igraph_vector_int_t added; @@ -110,10 +112,10 @@ igraph_error_t igraph_bipartite_projection_size(const igraph_t *graph, IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_vector_int_t *neis1; - igraph_integer_t neilen1; - igraph_integer_t *ecptr; + igraph_int_t neilen1; + igraph_int_t *ecptr; if (VECTOR(*types)[i]) { vc2++; ecptr = &ec2; @@ -123,16 +125,16 @@ igraph_error_t igraph_bipartite_projection_size(const igraph_t *graph, } neis1 = igraph_adjlist_get(&adjlist, i); neilen1 = igraph_vector_int_size(neis1); - for (igraph_integer_t j = 0; j < neilen1; j++) { - igraph_integer_t neilen2, nei = VECTOR(*neis1)[j]; + for (igraph_int_t j = 0; j < neilen1; j++) { + igraph_int_t neilen2, nei = VECTOR(*neis1)[j]; const igraph_vector_int_t *neis2 = igraph_adjlist_get(&adjlist, nei); if (IGRAPH_UNLIKELY(VECTOR(*types)[i] == VECTOR(*types)[nei])) { IGRAPH_ERROR("Non-bipartite edge found in bipartite projection.", IGRAPH_EINVAL); } neilen2 = igraph_vector_int_size(neis2); - for (igraph_integer_t k = 0; k < neilen2; k++) { - igraph_integer_t nei2 = VECTOR(*neis2)[k]; + for (igraph_int_t k = 0; k < neilen2; k++) { + igraph_int_t nei2 = VECTOR(*neis2)[k]; if (nei2 <= i) { continue; } @@ -174,13 +176,13 @@ static igraph_error_t igraph_i_bipartite_projection(const igraph_t *graph, int which, igraph_vector_int_t *multiplicity) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t remaining_nodes = 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t remaining_nodes = 0; igraph_vector_int_t vertex_perm, vertex_index; igraph_vector_int_t edges; igraph_adjlist_t adjlist; const igraph_vector_int_t *neis1, *neis2; - igraph_integer_t neilen1, neilen2; + igraph_int_t neilen1, neilen2; igraph_vector_int_t added; igraph_vector_int_t mult; @@ -205,28 +207,28 @@ static igraph_error_t igraph_i_bipartite_projection(const igraph_t *graph, igraph_vector_int_clear(multiplicity); } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(*types)[i] == which) { VECTOR(vertex_index)[i] = remaining_nodes++; - igraph_vector_int_push_back(&vertex_perm, i); + igraph_vector_int_push_back(&vertex_perm, i); /* reserved */ } } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(*types)[i] == which) { - igraph_integer_t new_i = VECTOR(vertex_index)[i]; - igraph_integer_t iedges = 0; + igraph_int_t new_i = VECTOR(vertex_index)[i]; + igraph_int_t iedges = 0; neis1 = igraph_adjlist_get(&adjlist, i); neilen1 = igraph_vector_int_size(neis1); - for (igraph_integer_t j = 0; j < neilen1; j++) { - igraph_integer_t nei = VECTOR(*neis1)[j]; + for (igraph_int_t j = 0; j < neilen1; j++) { + igraph_int_t nei = VECTOR(*neis1)[j]; if (IGRAPH_UNLIKELY(VECTOR(*types)[i] == VECTOR(*types)[nei])) { IGRAPH_ERROR("Non-bipartite edge found in bipartite projection.", IGRAPH_EINVAL); } neis2 = igraph_adjlist_get(&adjlist, nei); neilen2 = igraph_vector_int_size(neis2); - for (igraph_integer_t k = 0; k < neilen2; k++) { - igraph_integer_t nei2 = VECTOR(*neis2)[k], new_nei2; + for (igraph_int_t k = 0; k < neilen2; k++) { + igraph_int_t nei2 = VECTOR(*neis2)[k], new_nei2; if (nei2 <= i) { continue; } @@ -256,12 +258,12 @@ static igraph_error_t igraph_i_bipartite_projection(const igraph_t *graph, if (multiplicity) { /* OK, we need to go through all the edges added for vertex new_i and check their multiplicity */ - igraph_integer_t now = igraph_vector_int_size(&edges); - igraph_integer_t from = now - iedges * 2; - for (igraph_integer_t j = from; j < now; j += 2) { - igraph_integer_t nei2 = VECTOR(edges)[j + 1]; - igraph_integer_t new_nei2 = VECTOR(vertex_index)[nei2]; - igraph_integer_t m = VECTOR(mult)[nei2]; + igraph_int_t now = igraph_vector_int_size(&edges); + igraph_int_t from = now - iedges * 2; + for (igraph_int_t j = from; j < now; j += 2) { + igraph_int_t nei2 = VECTOR(edges)[j + 1]; + igraph_int_t new_nei2 = VECTOR(vertex_index)[nei2]; + igraph_int_t m = VECTOR(mult)[nei2]; VECTOR(edges)[j + 1] = new_nei2; IGRAPH_CHECK(igraph_vector_int_push_back(multiplicity, m)); } @@ -351,9 +353,9 @@ igraph_error_t igraph_bipartite_projection(const igraph_t *graph, igraph_t *proj2, igraph_vector_int_t *multiplicity1, igraph_vector_int_t *multiplicity2, - igraph_integer_t probe1) { + igraph_int_t probe1) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); /* t1 is -1 if proj1 is omitted, it is 0 if it belongs to type zero, it is 1 if it belongs to type one. The same for t2 */ @@ -445,13 +447,13 @@ igraph_error_t igraph_bipartite_projection(const igraph_t *graph, igraph_error_t igraph_full_bipartite(igraph_t *graph, igraph_vector_bool_t *types, - igraph_integer_t n1, igraph_integer_t n2, + igraph_int_t n1, igraph_int_t n2, igraph_bool_t directed, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes, no_of_edges; + igraph_int_t no_of_nodes, no_of_edges; igraph_vector_int_t edges; - igraph_integer_t ptr; + igraph_int_t ptr; if (n1 < 0 || n2 < 0) { IGRAPH_ERROR("Invalid number of vertices for bipartite graph.", IGRAPH_EINVAL); @@ -479,8 +481,8 @@ igraph_error_t igraph_full_bipartite(igraph_t *graph, if (!directed || mode == IGRAPH_OUT) { - for (igraph_integer_t i = 0; i < n1; i++) { - for (igraph_integer_t j = 0; j < n2; j++) { + for (igraph_int_t i = 0; i < n1; i++) { + for (igraph_int_t j = 0; j < n2; j++) { VECTOR(edges)[ptr++] = i; VECTOR(edges)[ptr++] = n1 + j; } @@ -488,8 +490,8 @@ igraph_error_t igraph_full_bipartite(igraph_t *graph, } else if (mode == IGRAPH_IN) { - for (igraph_integer_t i = 0; i < n1; i++) { - for (igraph_integer_t j = 0; j < n2; j++) { + for (igraph_int_t i = 0; i < n1; i++) { + for (igraph_int_t j = 0; j < n2; j++) { VECTOR(edges)[ptr++] = n1 + j; VECTOR(edges)[ptr++] = i; } @@ -497,8 +499,8 @@ igraph_error_t igraph_full_bipartite(igraph_t *graph, } else { - for (igraph_integer_t i = 0; i < n1; i++) { - for (igraph_integer_t j = 0; j < n2; j++) { + for (igraph_int_t i = 0; i < n1; i++) { + for (igraph_int_t j = 0; j < n2; j++) { VECTOR(edges)[ptr++] = i; VECTOR(edges)[ptr++] = n1 + j; VECTOR(edges)[ptr++] = n1 + j; @@ -515,7 +517,7 @@ igraph_error_t igraph_full_bipartite(igraph_t *graph, if (types) { IGRAPH_CHECK(igraph_vector_bool_resize(types, no_of_nodes)); igraph_vector_bool_null(types); - for (igraph_integer_t i = n1; i < no_of_nodes; i++) { + for (igraph_int_t i = n1; i < no_of_nodes; i++) { VECTOR(*types)[i] = true; } } @@ -555,9 +557,9 @@ igraph_error_t igraph_create_bipartite(igraph_t *graph, const igraph_vector_bool const igraph_vector_int_t *edges, igraph_bool_t directed) { - igraph_integer_t no_of_nodes = igraph_vector_bool_size(types); - igraph_integer_t no_of_edges = igraph_vector_int_size(edges); - igraph_integer_t i; + igraph_int_t no_of_nodes = igraph_vector_bool_size(types); + igraph_int_t no_of_edges = igraph_vector_int_size(edges); + igraph_int_t i; if (no_of_edges % 2 != 0) { IGRAPH_ERROR("Invalid (odd) edges vector", IGRAPH_EINVAL); @@ -570,8 +572,8 @@ igraph_error_t igraph_create_bipartite(igraph_t *graph, const igraph_vector_bool /* Check bipartiteness */ for (i = 0; i < no_of_edges * 2; i += 2) { - igraph_integer_t from = VECTOR(*edges)[i]; - igraph_integer_t to = VECTOR(*edges)[i + 1]; + igraph_int_t from = VECTOR(*edges)[i]; + igraph_int_t to = VECTOR(*edges)[i + 1]; igraph_bool_t t1 = VECTOR(*types)[from]; igraph_bool_t t2 = VECTOR(*types)[to]; if ( (t1 && t2) || (!t1 && !t2) ) { @@ -635,9 +637,9 @@ igraph_error_t igraph_biadjacency( igraph_neimode_t mode, igraph_bool_t multiple) { - const igraph_integer_t n1 = igraph_matrix_nrow(biadjmatrix); - const igraph_integer_t n2 = igraph_matrix_ncol(biadjmatrix); - const igraph_integer_t no_of_nodes = n1 + n2; + const igraph_int_t n1 = igraph_matrix_nrow(biadjmatrix); + const igraph_int_t n2 = igraph_matrix_ncol(biadjmatrix); + const igraph_int_t no_of_nodes = n1 + n2; igraph_vector_int_t edges; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); @@ -651,10 +653,10 @@ igraph_error_t igraph_biadjacency( ); } - for (igraph_integer_t j = 0; j < n2; j++) { - for (igraph_integer_t i = 0; i < n1; i++) { - igraph_integer_t elem = MATRIX(*biadjmatrix, i, j); - igraph_integer_t from, to; + for (igraph_int_t j = 0; j < n2; j++) { + for (igraph_int_t i = 0; i < n1; i++) { + igraph_int_t elem = MATRIX(*biadjmatrix, i, j); + igraph_int_t from, to; if (elem == 0) { continue; @@ -669,12 +671,12 @@ igraph_error_t igraph_biadjacency( } if (mode != IGRAPH_ALL || !directed) { - for (igraph_integer_t k = 0; k < elem; k++) { + for (igraph_int_t k = 0; k < elem; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); } } else { - for (igraph_integer_t k = 0; k < elem; k++) { + for (igraph_int_t k = 0; k < elem; k++) { IGRAPH_CHECK(igraph_vector_int_push_back(&edges, from)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, to)); @@ -686,9 +688,9 @@ igraph_error_t igraph_biadjacency( } else { - for (igraph_integer_t j = 0; j < n2; j++) { - for (igraph_integer_t i = 0; i < n1; i++) { - igraph_integer_t from, to; + for (igraph_int_t j = 0; j < n2; j++) { + for (igraph_int_t i = 0; i < n1; i++) { + igraph_int_t from, to; if (MATRIX(*biadjmatrix, i, j) != 0) { if (mode == IGRAPH_IN) { @@ -722,7 +724,7 @@ igraph_error_t igraph_biadjacency( if (types) { IGRAPH_CHECK(igraph_vector_bool_resize(types, no_of_nodes)); igraph_vector_bool_null(types); - for (igraph_integer_t i = n1; i < no_of_nodes; i++) { + for (igraph_int_t i = n1; i < no_of_nodes; i++) { VECTOR(*types)[i] = true; } } @@ -771,18 +773,18 @@ igraph_error_t igraph_weighted_biadjacency( igraph_bool_t directed, igraph_neimode_t mode) { - const igraph_integer_t n1 = igraph_matrix_nrow(biadjmatrix); - const igraph_integer_t n2 = igraph_matrix_ncol(biadjmatrix); - const igraph_integer_t no_of_nodes = n1 + n2; + const igraph_int_t n1 = igraph_matrix_nrow(biadjmatrix); + const igraph_int_t n2 = igraph_matrix_ncol(biadjmatrix); + const igraph_int_t no_of_nodes = n1 + n2; igraph_vector_int_t edges; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); igraph_vector_clear(weights); - for (igraph_integer_t j = 0; j < n2; j++) { - for (igraph_integer_t i = 0; i < n1; i++) { + for (igraph_int_t j = 0; j < n2; j++) { + for (igraph_int_t i = 0; i < n1; i++) { igraph_real_t weight = MATRIX(*biadjmatrix, i, j); - igraph_integer_t from, to; + igraph_int_t from, to; if (weight != 0) { if (mode == IGRAPH_IN) { @@ -818,7 +820,7 @@ igraph_error_t igraph_weighted_biadjacency( if (types) { IGRAPH_CHECK(igraph_vector_bool_resize(types, no_of_nodes)); igraph_vector_bool_null(types); - for (igraph_integer_t i = n1; i < no_of_nodes; i++) { + for (igraph_int_t i = n1; i < no_of_nodes; i++) { VECTOR(*types)[i] = true; } } @@ -874,10 +876,10 @@ igraph_error_t igraph_get_biadjacency( igraph_vector_int_t *col_ids ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t n1 = 0, n2 = 0; - igraph_integer_t ignored_edges = 0; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t n1 = 0, n2 = 0; + igraph_int_t ignored_edges = 0; igraph_vector_int_t perm; if (igraph_vector_bool_size(types) != no_of_nodes) { @@ -892,24 +894,24 @@ igraph_error_t igraph_get_biadjacency( } } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { n1 += VECTOR(*types)[i] == false ? 1 : 0; } n2 = no_of_nodes - n1; IGRAPH_VECTOR_INT_INIT_FINALLY(&perm, no_of_nodes); - for (igraph_integer_t i = 0, p1 = 0, p2 = n1; i < no_of_nodes; i++) { + for (igraph_int_t i = 0, p1 = 0, p2 = n1; i < no_of_nodes; i++) { VECTOR(perm)[i] = VECTOR(*types)[i] ? p2++ : p1++; } IGRAPH_CHECK(igraph_matrix_resize(res, n1, n2)); igraph_matrix_null(res); - for (igraph_integer_t i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); - igraph_integer_t from2 = VECTOR(perm)[from]; - igraph_integer_t to2 = VECTOR(perm)[to]; + for (igraph_int_t i = 0; i < no_of_edges; i++) { + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); + igraph_int_t from2 = VECTOR(perm)[from]; + igraph_int_t to2 = VECTOR(perm)[to]; if (VECTOR(*types)[from] == VECTOR(*types)[to]) { ignored_edges++; } else if (! VECTOR(*types)[from]) { @@ -930,15 +932,15 @@ igraph_error_t igraph_get_biadjacency( IGRAPH_CHECK(igraph_vector_int_resize(col_ids, n2)); } if (row_ids || col_ids) { - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (! VECTOR(*types)[i]) { if (row_ids) { - igraph_integer_t i2 = VECTOR(perm)[i]; + igraph_int_t i2 = VECTOR(perm)[i]; VECTOR(*row_ids)[i2] = i; } } else { if (col_ids) { - igraph_integer_t i2 = VECTOR(perm)[i]; + igraph_int_t i2 = VECTOR(perm)[i]; VECTOR(*col_ids)[i2 - n1] = i; } } @@ -980,7 +982,7 @@ igraph_error_t igraph_get_biadjacency( * Time complexity: O(|V|+|E|), linear in the number of vertices and * edges. * - * \sa igraph_is_bipartite_coloring() do determine if all edges connect + * \sa igraph_is_bipartite_coloring() to determine if all edges connect * vertices of different types, given a specific type vector. */ @@ -996,7 +998,7 @@ igraph_error_t igraph_is_bipartite(const igraph_t *graph, 2 means type 2. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_char_t seen; igraph_dqueue_int_t Q; igraph_vector_int_t neis; @@ -1026,7 +1028,7 @@ igraph_error_t igraph_is_bipartite(const igraph_t *graph, IGRAPH_DQUEUE_INT_INIT_FINALLY(&Q, 100); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); - for (igraph_integer_t i = 0; bi && i < no_of_nodes; i++) { + for (igraph_int_t i = 0; bi && i < no_of_nodes; i++) { if (VECTOR(seen)[i]) { continue; @@ -1036,8 +1038,8 @@ igraph_error_t igraph_is_bipartite(const igraph_t *graph, VECTOR(seen)[i] = 1; while (bi && !igraph_dqueue_int_empty(&Q)) { - igraph_integer_t n, j; - igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); + igraph_int_t n, j; + igraph_int_t actnode = igraph_dqueue_int_pop(&Q); char acttype = VECTOR(seen)[actnode]; IGRAPH_CHECK(igraph_neighbors( @@ -1045,7 +1047,7 @@ igraph_error_t igraph_is_bipartite(const igraph_t *graph, )); n = igraph_vector_int_size(&neis); for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + igraph_int_t nei = VECTOR(neis)[j]; if (VECTOR(seen)[nei]) { char neitype = VECTOR(seen)[nei]; if (neitype == acttype) { @@ -1076,7 +1078,7 @@ igraph_error_t igraph_is_bipartite(const igraph_t *graph, if (types && bi) { IGRAPH_CHECK(igraph_vector_bool_resize(types, no_of_nodes)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(*types)[i] = VECTOR(seen)[i] - 1; } } @@ -1087,72 +1089,142 @@ igraph_error_t igraph_is_bipartite(const igraph_t *graph, return IGRAPH_SUCCESS; } -/* This implementation is used only with very large vertex counts, when the - * default implementation would fail due to overflow. While this version - * avoids overflow and uses less memory, it is also slower than the default - * implementation. */ -static igraph_error_t gnp_bipartite_large( + +static igraph_error_t bipartite_iea_game( igraph_t *graph, - igraph_integer_t n1, igraph_integer_t n2, - igraph_real_t p, - igraph_bool_t directed, igraph_neimode_t mode, - igraph_integer_t ecount_estimate) { + igraph_int_t n1, igraph_int_t n2, + igraph_int_t m, + igraph_bool_t directed, igraph_neimode_t mode) { igraph_vector_int_t edges; - int iter = 0; + igraph_int_t n = n1 + n2; /* overflow checked by caller */ + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); + + for (igraph_int_t i = 0; i < m; i++) { + igraph_int_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_BOOL())) { + igraph_vector_int_push_back(&edges, to); /* reserved */ + igraph_vector_int_push_back(&edges, from); /* reserved */ + } else { + igraph_vector_int_push_back(&edges, from); /* reserved */ + igraph_vector_int_push_back(&edges, to); /* reserved */ + } - /* Necessitated by floating point arithmetic used in the implementation. */ - if (n1 >= IGRAPH_MAX_EXACT_REAL || n2 >= IGRAPH_MAX_EXACT_REAL) { - IGRAPH_ERROR("Number of vertices is too large.", IGRAPH_EOVERFLOW); } - if (ecount_estimate > IGRAPH_ECOUNT_MAX) { - ecount_estimate = IGRAPH_ECOUNT_MAX; + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + +static igraph_error_t bipartite_gnm_multi( + igraph_t *graph, + igraph_int_t n1, igraph_int_t n2, + igraph_int_t m, + igraph_bool_t directed, igraph_neimode_t mode) { + + /* See igraph_erdos_renyi_game_gnm() for how the sampling works. */ + + igraph_vector_int_t edges; + igraph_int_t nrow, ncol; + igraph_int_t last; + igraph_int_t offset1 = 0, offset2 = n1; + igraph_int_t n = n1 + n2; /* overflow checked by caller */ + + /* The larger partition is associated with columns, the smaller + * with rows. This setup helps avoid integer overflow. We swap + * n1 and n2 so that n1 is smaller. */ + if (n1 > n2) { + igraph_int_t tmp = n1; + n1 = n2; + n2 = tmp; + + offset1 = n2; offset2 = 0; + + mode = IGRAPH_REVERSE_MODE(mode); } - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount_estimate)); + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2*m); - for (igraph_integer_t i = 0; i < n1; i++) { - igraph_integer_t j = 0; + if (!directed || mode != IGRAPH_ALL) { + nrow = n1; + ncol = n2; + last = ncol-1; + for (igraph_int_t i=0; i < m; i++) { + while (true) { + igraph_int_t r = RNG_INTEGER(0, nrow-1); + igraph_int_t c = RNG_INTEGER(0, ncol-1); - while (true) { - igraph_real_t gap = RNG_GEOM(p); + if (r >= n1) { + igraph_int_t j = (r - n1) * ncol + c; + if (j >= i) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; + } else { + if (directed && mode == IGRAPH_IN) { + VECTOR(edges)[2*i] = c + offset2; + VECTOR(edges)[2*i+1] = r + offset1; + } else { + VECTOR(edges)[2*i] = r + offset1; + VECTOR(edges)[2*i+1] = c + offset2; + } + } + + last += 1; + if (last >= ncol) { + last -= ncol; + nrow++; + } - if (gap >= n2 - j) { break; } + } + } else /* directed, mutual allowed */ { + nrow = 2*n1; + ncol = n2; + last = ncol-1; + for (igraph_int_t i=0; i < m; i++) { + while (true) { + igraph_int_t r = RNG_INTEGER(0, nrow-1); + igraph_int_t c = RNG_INTEGER(0, ncol-1); - j += gap; - - if (!directed) { - /* Undirected graph */ - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); - } else if (mode == IGRAPH_IN) { - /* Incoming edges */ - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); - } else if (mode == IGRAPH_OUT) { - /* Outgoing edges */ - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); - } else { - /* Both directions for IGRAPH_ALL */ - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); - IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); - } + if (r >= 2*n1) { + igraph_int_t j = (r - 2*n1) * ncol + c; + if (j >= i) continue; /* rejection sampling */ + VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; + VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; + } else { + if (r < n1) { + VECTOR(edges)[2*i] = r + offset1; + VECTOR(edges)[2*i+1] = c + offset2; + } else { + VECTOR(edges)[2*i] = c + offset2; + VECTOR(edges)[2*i+1] = r - n1 + offset1; + } + } - j++; + last += 1; + if (last >= ncol) { + last -= ncol; + nrow++; + } - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + break; + } } } - /* n1 + n2 has already been checked for overflow in the caller function. */ - IGRAPH_CHECK(igraph_create(graph, &edges, n1 + n2, directed)); + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); igraph_vector_int_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); @@ -1160,114 +1232,42 @@ static igraph_error_t gnp_bipartite_large( return IGRAPH_SUCCESS; } -/** - * \function igraph_bipartite_game_gnp - * \brief Generates a random bipartite graph with a fixed connection probability. - * - * In the G(n1, n2, p) model, every possible edge between the \p n1 - * bottom vertices and \p n2 top vertices is realized independently with - * probability \p p. - * - * \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 \c NULL, then the vertex types are stored - * here. Bottom vertices come first, \p n1 of them, then \p n2 top - * vertices. - * \param n1 The number of bottom vertices. - * \param n2 The number of top vertices. - * \param p The connection probability. - * \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_gnp() for the unipartite version, - * \ref igraph_bipartite_game_gnm() for the G(n1, n2, m) model. - * - * Time complexity: O(|V|+|E|), linear in the number of vertices and - * edges. - */ - -igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t *types, - igraph_integer_t n1, igraph_integer_t n2, - igraph_real_t p, igraph_bool_t directed, - igraph_neimode_t mode) { +static igraph_error_t bipartite_gnm_simple( + igraph_t *graph, + igraph_int_t n1, igraph_int_t n2, + igraph_int_t m, + igraph_bool_t directed, igraph_neimode_t mode, + igraph_bool_t edge_labeled) { igraph_vector_int_t edges; igraph_vector_t s; - igraph_integer_t n; igraph_real_t n1_real = (igraph_real_t) n1, n2_real = (igraph_real_t) n2; /* for floating-point operations */ + igraph_int_t n = n1 + n2; /* overflow checked by caller */ + igraph_real_t maxedges; int iter = 0; - if (n1 < 0 || n2 < 0) { - IGRAPH_ERROR("Invalid number of vertices for bipartite G(n,p) model.", IGRAPH_EINVAL); - } - - if (p < 0.0 || p > 1.0) { - IGRAPH_ERROR("Invalid connection probability for bipartite G(n,p) model.", IGRAPH_EINVAL); - } - - if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { - IGRAPH_ERROR("Invalid mode for bipartite G(n,p) model.", IGRAPH_EINVAL); + if (!directed || mode != IGRAPH_ALL) { + maxedges = n1_real * n2_real; + } else { + maxedges = 2.0 * n1_real * n2_real; } - IGRAPH_SAFE_ADD(n1, n2, &n); - - if (types) { - IGRAPH_CHECK(igraph_vector_bool_resize(types, n)); - igraph_vector_bool_null(types); - for (igraph_integer_t i = n1; i < n; i++) { - VECTOR(*types)[i] = true; - } + if (m > maxedges) { + IGRAPH_ERROR("Too many edges requested compared to the number of vertices.", IGRAPH_EINVAL); } - if (p == 0 || n1 == 0 || n2 == 0) { - IGRAPH_CHECK(igraph_empty(graph, n, directed)); - } else if (p == 1.0) { - IGRAPH_CHECK(igraph_full_bipartite(graph, types, n1, n2, directed, mode)); + if (maxedges == m && ! edge_labeled) { + /* TODO: Cannot use igraph_full_bipartite() when edge_labeled as we must shuffle edges. */ + IGRAPH_CHECK(igraph_full_bipartite(graph, NULL, n1, n2, directed, mode)); } else { - - igraph_integer_t to, from, slen; - igraph_real_t maxedges, last; - igraph_integer_t ecount_estimate; - - if (!directed || mode != IGRAPH_ALL) { - maxedges = n1_real * n2_real; - } else { - maxedges = 2.0 * n1_real * n2_real; - } - - IGRAPH_CHECK(igraph_i_safe_floor(maxedges * p * 1.1, &ecount_estimate)); - - if (maxedges > IGRAPH_MAX_EXACT_REAL) { - /* Use a slightly slower, but overflow-free implementation. */ - return gnp_bipartite_large(graph, n1, n2, p, directed, mode, ecount_estimate); - } + igraph_int_t to, from; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_VECTOR_INIT_FINALLY(&s, 0); - IGRAPH_CHECK(igraph_vector_reserve(&s, ecount_estimate)); - - last = RNG_GEOM(p); - while (last < maxedges) { - IGRAPH_CHECK(igraph_vector_push_back(&s, last)); - last += RNG_GEOM(p); - last += 1; - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); - } - - slen = igraph_vector_size(&s); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, slen * 2)); + IGRAPH_CHECK(igraph_i_random_sample_real(&s, 0, maxedges - 1, m)); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); - for (igraph_integer_t i = 0; i < slen; i++) { + for (igraph_int_t i = 0; i < m; i++) { if (!directed || mode != IGRAPH_ALL) { to = trunc(VECTOR(s)[i] / n1_real); from = VECTOR(s)[i] - to * n1_real; @@ -1299,7 +1299,12 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * igraph_vector_destroy(&s); IGRAPH_FINALLY_CLEAN(1); + if (edge_labeled) { + IGRAPH_CHECK(igraph_i_vector_int_shuffle_pairs(&edges)); + } + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); } @@ -1308,45 +1313,22 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * } /** - * \function igraph_bipartite_iea_game - * \brief Generates a random bipartite multigraph through independent edge assignment. - * - * \experimental - * - * This model generates random multigraphs with \p n1 bottom vertices, - * \p n2 top vertices and \p m edges through independent edge assignment (IEA). - * Each of the \p m edges is assigned uniformly at random to a vertex pair, - * independently of each other. - * - * - * This model does not sample multigraphs uniformly. Undirected graphs are - * generated with probability proportional to - * - * - * (prod_(i<j) A_ij !)^(-1), - * - * - * where \c A denotes the adjacency matrix. The corresponding expression for - * directed graphs is - * - * - * (prod_(i,j) A_ij !)^(-1). + * \function igraph_bipartite_game_gnm + * \brief Generate a random bipartite graph with a fixed number of edges. * - * - * Thus the probability of all simple graphs (which only have 0s and 1s in the - * adjacency matrix) is the same, while that of non-simple ones depends on - * their edge and self-loop multiplicities. + * The G(n1, n2, m) model uniformly samples bipartite graphs with + * \p n1 bottom vertices and \p n2 top vertices, and precisely \p m edges. * * \param graph Pointer to an uninitialized igraph graph, the result * is stored here. - * \param types Pointer to an initialized boolean vector, or a \c NULL - * pointer. If not \c NULL, then the vertex types are stored + * \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, \p n1 of them, then \p 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 Whether to generate a directed graph. See + * \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 @@ -1356,41 +1338,58 @@ 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 allowed_edge_types The types of edges to allow in the graph. + * \clist + * \cli IGRAPH_SIMPLE_SW + * simple graph (i.e. no multi-edges allowed). + * \cli IGRAPH_MULTI_SW + * multi-edges are allowed + * \endclist + * \param edge_labeled If true, the sampling is done uniformly from the set + * of ordered edge lists. See \ref igraph_bipartite_iea_game() for more + * information. Set this to \c false to select the classic Erdős-Rényi model. + * The constants \c IGRAPH_EDGE_UNLABELED and \c IGRAPH_EDGE_LABELED + * may be used instead of \c false and \c true for better readability. * \return Error code. * - * \sa \ref igraph_iea_game() for the unipartite version; - * \ref igraph_bipartite_game_gnm() to uniformly sample bipartite graphs - * with a given number of vertices and edges. + * \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. */ -igraph_error_t igraph_bipartite_iea_game( - 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_error_t igraph_bipartite_game_gnm( + igraph_t *graph, + igraph_vector_bool_t *types, + igraph_int_t n1, igraph_int_t n2, igraph_int_t m, + igraph_bool_t directed, igraph_neimode_t mode, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled) { - igraph_integer_t n; - igraph_vector_int_t edges; + igraph_int_t n; + igraph_bool_t loops, multiple; if (n1 < 0 || n2 < 0) { - IGRAPH_ERROR("Invalid number of vertices for bipartite IEA model.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of vertices for bipartite G(n,m) model.", IGRAPH_EINVAL); } if (m < 0 || m > IGRAPH_ECOUNT_MAX) { - IGRAPH_ERROR("Invalid number of edges for bipartite IEA model.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of edges for bipartite G(n,m) model.", IGRAPH_EINVAL); } if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { - IGRAPH_ERROR("Invalid mode for bipartite IEA model.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid mode for bipartite G(n,m) model.", IGRAPH_EINVAL); } - IGRAPH_SAFE_ADD(n1, n2, &n); + /* Bipartite graphs cannot have self-loops. We ignore them. */ + IGRAPH_CHECK(igraph_i_edge_type_to_loops_multiple(allowed_edge_types, &loops, &multiple)); + + IGRAPH_SAFE_ADD(n1, n2, &n); /* overflow check */ if (types) { - igraph_integer_t i; IGRAPH_CHECK(igraph_vector_bool_resize(types, n)); igraph_vector_bool_null(types); - for (i = n1; i < n; i++) { + for (igraph_int_t i = n1; i < n; i++) { VECTOR(*types)[i] = true; } } @@ -1399,137 +1398,188 @@ igraph_error_t igraph_bipartite_iea_game( if (m > 0) { IGRAPH_ERROR("Too many edges requested compared to the number of vertices.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_empty(graph, n, directed)); - return IGRAPH_SUCCESS; + return igraph_empty(graph, n, directed); + } else if (multiple) { + if (edge_labeled) { + return bipartite_iea_game(graph, n1, n2, m, directed, mode); + } else { + return bipartite_gnm_multi(graph, n1, n2, m, directed, mode); + } + } else { + return bipartite_gnm_simple(graph, n1, n2, m, directed, mode, edge_labeled); } - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); + return IGRAPH_SUCCESS; +} - for (igraph_integer_t i = 0; i < m; i++) { - igraph_integer_t to, from; +/** + * \function igraph_bipartite_iea_game + * \brief Generates a random bipartite multigraph through independent edge assignment. + * + * \experimental + * + * This model generates random multigraphs with \p n1 bottom vertices, + * \p n2 top vertices and \p m edges through independent edge assignment (IEA). + * Each of the \p m edges is assigned uniformly at random to a vertex pair, + * independently of each other. + * + * + * This model does not sample multigraphs uniformly. Undirected graphs are + * generated with probability proportional to + * + * + * (prod_(i<j) A_ij !)^(-1), + * + * + * where \c A denotes the adjacency matrix. The corresponding expression for + * directed graphs is + * + * + * (prod_(i,j) A_ij !)^(-1). + * + * + * Thus the probability of all simple graphs (which only have 0s and 1s in the + * adjacency matrix) is the same, while that of non-simple ones depends on + * their edge and self-loop multiplicities. + * + * \param graph Pointer to an uninitialized igraph graph, the result + * is stored here. + * \param types Pointer to an initialized boolean vector, or a \c NULL + * pointer. If not \c NULL, then the vertex types are stored + * here. Bottom vertices come first, \p n1 of them, then \p 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 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_iea_game() for the unipartite version; + * \ref igraph_bipartite_game_gnm() to uniformly sample bipartite graphs + * with a given number of vertices and edges. + * + * Time complexity: O(|V|+|E|), linear in the number of vertices and + * edges. + */ - to = RNG_INTEGER(n1, n - 1); - from = RNG_INTEGER(0, n1 - 1); +igraph_error_t igraph_bipartite_iea_game( + igraph_t *graph, igraph_vector_bool_t *types, + igraph_int_t n1, igraph_int_t n2, igraph_int_t m, + igraph_bool_t directed, igraph_neimode_t mode) { - /* flip unconditionally for IGRAPH_IN, - * or with probability 0.5 for IGRAPH_ALL */ - if (mode == IGRAPH_IN || (mode == IGRAPH_ALL && RNG_BOOL())) { - igraph_vector_int_push_back(&edges, to); - igraph_vector_int_push_back(&edges, from); + return igraph_bipartite_game_gnm( + graph, types, n1, n2, m, directed, mode, + IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED); +} + + +static igraph_error_t bipartite_gnp_edge_labeled( + igraph_t *graph, + igraph_int_t n1, igraph_int_t n2, igraph_real_t p, + igraph_bool_t directed, igraph_neimode_t mode, + igraph_bool_t multiple) { + + if (multiple) { + igraph_real_t maxedges; + + if (!directed || mode != IGRAPH_ALL) { + maxedges = (igraph_real_t) n1 * (igraph_real_t) n2; } else { - igraph_vector_int_push_back(&edges, from); - igraph_vector_int_push_back(&edges, to); + maxedges = 2.0 * (igraph_real_t) n1 * (igraph_real_t) n2; } - } - - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); + igraph_real_t m; + do { + m = RNG_GEOM( 1.0 / (1.0 + maxedges * p) ); + } while (m > (igraph_real_t) IGRAPH_INTEGER_MAX); - return IGRAPH_SUCCESS; + return bipartite_iea_game(graph, n1, n2, m, directed, mode); + } else { + IGRAPH_ERROR("The edge-labeled bipartite G(n,p) model is not yet implemented for graphs without multi-edges.", + IGRAPH_UNIMPLEMENTED); + } } -static igraph_error_t bipartite_gnm_multi( +/* This implementation is used only with very large vertex counts, when the + * default implementation would fail due to overflow. While this version + * avoids overflow and uses less memory, it is also slower than the default + * implementation. + * + * This function expects that when multiple=true, the p parameter has already + * been transformed by p = p / (1 + p). This is currently done by the caller. + */ +static igraph_error_t gnp_bipartite_large( igraph_t *graph, - igraph_integer_t n1, igraph_integer_t n2, igraph_integer_t m, - igraph_bool_t directed, igraph_neimode_t mode) { - - /* See igraph_erdos_renyi_game_gnm() for how the sampling works. */ + igraph_int_t n1, igraph_int_t n2, + igraph_real_t p, + igraph_bool_t directed, igraph_neimode_t mode, + igraph_bool_t multiple, + igraph_int_t ecount_estimate) { igraph_vector_int_t edges; - igraph_integer_t n; - igraph_integer_t nrow, ncol; - igraph_integer_t last; - igraph_integer_t offset1 = 0, offset2 = n1; - - IGRAPH_SAFE_ADD(n1, n2, &n); - - /* The larger partition is associated with collumns, the smaller - * with rows. This setup helps avoid integer overflow. We swap - * n1 and n2 so that n1 is smaller. */ - if (n1 > n2) { - igraph_integer_t tmp = n1; - n1 = n2; - n2 = tmp; + int iter = 0; - offset1 = n2; offset2 = 0; + /* Necessitated by floating point arithmetic used in the implementation. */ + if (n1 >= IGRAPH_MAX_EXACT_REAL || n2 >= IGRAPH_MAX_EXACT_REAL) { + IGRAPH_ERROR("Number of vertices is too large.", IGRAPH_EOVERFLOW); + } - mode = IGRAPH_REVERSE_MODE(mode); + if (ecount_estimate > IGRAPH_ECOUNT_MAX) { + ecount_estimate = IGRAPH_ECOUNT_MAX; } - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2*m); + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, 2*ecount_estimate)); - if (!directed || mode != IGRAPH_ALL) { - nrow = n1; - ncol = n2; - last = ncol-1; - for (igraph_integer_t i=0; i < m; i++) { - while (true) { - igraph_integer_t r = RNG_INTEGER(0, nrow-1); - igraph_integer_t c = RNG_INTEGER(0, ncol-1); + for (igraph_int_t i = 0; i < n1; i++) { + igraph_int_t j = 0; - if (r >= n1) { - igraph_integer_t j = (r - n1) * ncol + c; - if (j >= i) continue; /* rejection sampling */ - VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; - VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; - } else { - if (directed && mode == IGRAPH_IN) { - VECTOR(edges)[2*i] = c + offset2; - VECTOR(edges)[2*i+1] = r + offset1; - } else { - VECTOR(edges)[2*i] = r + offset1; - VECTOR(edges)[2*i+1] = c + offset2; - } - } - - last += 1; - if (last >= ncol) { - last -= ncol; - nrow++; - } + while (true) { + igraph_real_t gap = RNG_GEOM(p); + if (gap >= n2 - j) { break; } - } - } else /* directed, mutual allowed */ { - nrow = 2*n1; - ncol = n2; - last = ncol-1; - for (igraph_integer_t i=0; i < m; i++) { - while (true) { - igraph_integer_t r = RNG_INTEGER(0, nrow-1); - igraph_integer_t c = RNG_INTEGER(0, ncol-1); - - if (r >= 2*n1) { - igraph_integer_t j = (r - 2*n1) * ncol + c; - if (j >= i) continue; /* rejection sampling */ - VECTOR(edges)[2*i] = VECTOR(edges)[2*j]; - VECTOR(edges)[2*i+1] = VECTOR(edges)[2*j+1]; - } else { - if (r < n1) { - VECTOR(edges)[2*i] = r + offset1; - VECTOR(edges)[2*i+1] = c + offset2; - } else { - VECTOR(edges)[2*i] = c + offset2; - VECTOR(edges)[2*i+1] = r - n1 + offset1; - } - } - last += 1; - if (last >= ncol) { - last -= ncol; - nrow++; - } + j += gap; - break; + if (!directed) { + /* Undirected graph */ + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); + } else if (mode == IGRAPH_IN) { + /* Incoming edges */ + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); + } else if (mode == IGRAPH_OUT) { + /* Outgoing edges */ + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); + } else { + /* Both directions for IGRAPH_ALL */ + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, j + n1)); + IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); } + + j += ! multiple; /* 1 for simple graph, 0 for multigraph */ + + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } } - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + /* n1 + n2 has already been checked for overflow in the caller function. */ + IGRAPH_CHECK(igraph_create(graph, &edges, n1 + n2, directed)); igraph_vector_int_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); @@ -1538,23 +1588,30 @@ static igraph_error_t bipartite_gnm_multi( } /** - * \function igraph_bipartite_game_gnm - * \brief Generate a random bipartite graph with a fixed number of edges. + * \function igraph_bipartite_game_gnp + * \brief Generates a random bipartite graph with a fixed connection probability. * - * The G(n1, n2, m) model uniformly samples bipartite graphs with - * \p n1 bottom vertices and \p n2 top vertices, and precisely \p m edges. + * In the G(n1, n2, p) model, every possible edge between the \p n1 + * bottom vertices and \p n2 top vertices is realized independently with + * probability \p p. This is equivalent to a maximum entropy model with + * a constraint on the \em expected total edge count. This view allows + * a multigraph extension, in which case \p is interpreted as the expected + * number of edges between any vertex pair. See \ref igraph_erdos_renyi_game_gnp() + * for more details. * * \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 + * pointer. If not \c NULL, then the vertex types are stored * here. Bottom vertices come first, \p n1 of them, then \p 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 p The expected number of edges between any vertex pair. + * When multi-edges are disallowed, this is equivalent to the probability + * of having a connection between any two vertices. + * \param directed 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 @@ -1563,60 +1620,98 @@ static igraph_error_t bipartite_gnm_multi( * \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. +* \param allowed_edge_types The types of edges to allow in the graph. + * \clist + * \cli IGRAPH_SIMPLE_SW + * simple graph (i.e. no multi-edges allowed). + * \cli IGRAPH_MULTI_SW + * multi-edges are allowed + * \endclist + * \param edge_labeled If true, the model is defined over the set of ordered + * edge lists, i.e. over the set of edge-labeled graphs. Set it to + * \c false to select the classic bipartite Erdős-Rényi model. + * The constants \c IGRAPH_EDGE_UNLABELED and \c IGRAPH_EDGE_LABELED + * may be used instead of \c false and \c true for better readability. * \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. + * \sa \ref igraph_erdos_renyi_game_gnp() for the unipartite version, + * \ref igraph_bipartite_game_gnm() for the G(n1, n2, m) model. * * Time complexity: O(|V|+|E|), linear in the number of vertices and * edges. */ -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_bool_t multiple) { +igraph_error_t igraph_bipartite_game_gnp( + igraph_t *graph, + igraph_vector_bool_t *types, + igraph_int_t n1, igraph_int_t n2, igraph_real_t p, + igraph_bool_t directed, igraph_neimode_t mode, + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t edge_labeled) { + igraph_vector_int_t edges; igraph_vector_t s; - igraph_integer_t n; + igraph_int_t n; igraph_real_t n1_real = (igraph_real_t) n1, n2_real = (igraph_real_t) n2; /* for floating-point operations */ + igraph_bool_t loops, multiple; int iter = 0; if (n1 < 0 || n2 < 0) { - IGRAPH_ERROR("Invalid number of vertices for bipartite G(n,m) model.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid number of vertices for bipartite G(n,p) model.", IGRAPH_EINVAL); } - if (m < 0 || m > IGRAPH_ECOUNT_MAX) { - IGRAPH_ERROR("Invalid number of edges for bipartite G(n,m) model.", IGRAPH_EINVAL); + + /* Bipartite graphs cannot have self-loops. We ignore them. */ + IGRAPH_CHECK(igraph_i_edge_type_to_loops_multiple(allowed_edge_types, &loops, &multiple)); + + if (multiple) { + if (p < 0.0) { + IGRAPH_ERROR( + "Invalid expected edge multiplicity given for " + "bipartite G(n,p) multigraph model.", + IGRAPH_EINVAL); + } + } else { + if (p < 0.0 || p > 1.0) { + IGRAPH_ERROR( + "Invalid connection probability given for bipartite G(n,p) model.", + IGRAPH_EINVAL); + } } + if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { - IGRAPH_ERROR("Invalid mode for bipartite G(n,m) model.", IGRAPH_EINVAL); + IGRAPH_ERROR("Invalid mode for bipartite G(n,p) model.", IGRAPH_EINVAL); } IGRAPH_SAFE_ADD(n1, n2, &n); if (types) { - igraph_integer_t i; IGRAPH_CHECK(igraph_vector_bool_resize(types, n)); igraph_vector_bool_null(types); - for (i = n1; i < n; i++) { + for (igraph_int_t i = n1; i < n; i++) { VECTOR(*types)[i] = true; } } - if (m == 0 || n1 == 0 || n2 == 0) { - if (m > 0) { - IGRAPH_ERROR("Too many edges requested compared to the number of vertices.", IGRAPH_EINVAL); - } + if (edge_labeled) { + return bipartite_gnp_edge_labeled(graph, n1, n2, p, directed, mode, multiple); + } + + if (multiple) { + /* Convert the expected edge count to the appropriate probability parameter + * of the geometric distribution when sampling lengths of runs of 0s in the + * adjacency matrix. */ + p = p / (1 + p); + } + + if (p == 0 || n1 == 0 || n2 == 0) { IGRAPH_CHECK(igraph_empty(graph, n, directed)); - } else if (multiple) { - IGRAPH_CHECK(bipartite_gnm_multi(graph, n1, n2, m, directed, mode)); + } else if (p == 1.0) { + IGRAPH_CHECK(igraph_full_bipartite(graph, types, n1, n2, directed, mode)); } else { - igraph_integer_t i; - igraph_real_t maxedges; + igraph_int_t to, from, slen; + igraph_real_t maxedges, last; + igraph_int_t ecount_estimate; if (!directed || mode != IGRAPH_ALL) { maxedges = n1_real * n2_real; @@ -1624,56 +1719,63 @@ igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t * maxedges = 2.0 * n1_real * n2_real; } - if (m > maxedges) { - IGRAPH_ERROR("Too many edges requested compared to the number of vertices.", IGRAPH_EINVAL); + IGRAPH_CHECK(igraph_i_safe_floor(maxedges * p * 1.1, &ecount_estimate)); + + if (maxedges > IGRAPH_MAX_EXACT_REAL) { + /* Use a slightly slower, but overflow-free implementation. */ + return gnp_bipartite_large(graph, n1, n2, p, directed, mode, multiple, ecount_estimate); } - if (maxedges == m) { - IGRAPH_CHECK(igraph_full_bipartite(graph, types, n1, n2, directed, mode)); - } else { + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_VECTOR_INIT_FINALLY(&s, 0); + IGRAPH_CHECK(igraph_vector_reserve(&s, ecount_estimate)); - igraph_integer_t to, from; + last = RNG_GEOM(p); + while (last < maxedges) { + IGRAPH_CHECK(igraph_vector_push_back(&s, last)); + last += RNG_GEOM(p); + last += ! multiple; /* 1 for simple graph, 0 for multigraph */ + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } - IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - IGRAPH_VECTOR_INIT_FINALLY(&s, 0); - IGRAPH_CHECK(igraph_i_random_sample_real(&s, 0, maxedges - 1, m)); - IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); + slen = igraph_vector_size(&s); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, slen * 2)); - for (i = 0; i < m; i++) { - if (!directed || mode != IGRAPH_ALL) { - to = floor(VECTOR(s)[i] / n1_real); + for (igraph_int_t i = 0; i < slen; i++) { + if (!directed || mode != IGRAPH_ALL) { + to = trunc(VECTOR(s)[i] / n1_real); + from = VECTOR(s)[i] - to * n1_real; + to += n1; + } else { + igraph_real_t n1n2 = n1_real * n2_real; + if (VECTOR(s)[i] < n1n2) { + to = trunc(VECTOR(s)[i] / n1_real); from = VECTOR(s)[i] - to * n1_real; to += n1; } else { - igraph_real_t n1n2 = n1_real * n2_real; - if (VECTOR(s)[i] < n1n2) { - to = floor(VECTOR(s)[i] / n1_real); - from = VECTOR(s)[i] - to * n1_real; - to += n1; - } else { - to = floor((VECTOR(s)[i] - n1n2) / n2_real); - from = VECTOR(s)[i] - n1n2 - to * n2_real; - from += n1; - } - } - - if (mode != IGRAPH_IN) { - igraph_vector_int_push_back(&edges, from); /* reserved */ - igraph_vector_int_push_back(&edges, to); /* reserved */ - } else { - igraph_vector_int_push_back(&edges, to); /* reserved */ - igraph_vector_int_push_back(&edges, from); /* reserved */ + to = trunc((VECTOR(s)[i] - n1n2) / n2_real); + from = VECTOR(s)[i] - n1n2 - to * n2_real; + from += n1; } + } - IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + if (mode != IGRAPH_IN) { + igraph_vector_int_push_back(&edges, from); /* reserved */ + igraph_vector_int_push_back(&edges, to); /* reserved */ + } else { + igraph_vector_int_push_back(&edges, to); /* reserved */ + igraph_vector_int_push_back(&edges, from); /* reserved */ } - igraph_vector_destroy(&s); - IGRAPH_FINALLY_CLEAN(1); - IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); - igraph_vector_int_destroy(&edges); - IGRAPH_FINALLY_CLEAN(1); + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); } + + igraph_vector_destroy(&s); + IGRAPH_FINALLY_CLEAN(1); + + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); } return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/misc/chordality.c b/src/vendor/cigraph/src/misc/chordality.c index 1dcfbad9161..ff90cb7aec8 100644 --- a/src/vendor/cigraph/src/misc/chordality.c +++ b/src/vendor/cigraph/src/misc/chordality.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2008-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -68,17 +68,17 @@ igraph_error_t igraph_maximum_cardinality_search(const igraph_t *graph, igraph_vector_int_t *alpha, igraph_vector_int_t *alpham1) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t size; igraph_vector_int_t head, next, prev; /* doubly linked list with head */ - igraph_integer_t i; + igraph_int_t i; igraph_adjlist_t adjlist; /***************/ /* local j, v; */ /***************/ - igraph_integer_t j, v; + igraph_int_t j, v; if (no_of_nodes == 0) { igraph_vector_int_clear(alpha); @@ -130,7 +130,7 @@ igraph_error_t igraph_maximum_cardinality_search(const igraph_t *graph, /**************/ while (i >= 1) { - igraph_integer_t x, k, len; + igraph_int_t x, k, len; igraph_vector_int_t *neis; /********************************/ @@ -161,16 +161,16 @@ igraph_error_t igraph_maximum_cardinality_search(const igraph_t *graph, neis = igraph_adjlist_get(&adjlist, v); len = igraph_vector_int_size(neis); for (k = 0; k < len; k++) { - igraph_integer_t w = VECTOR(*neis)[k]; - igraph_integer_t ws = VECTOR(size)[w]; + igraph_int_t w = VECTOR(*neis)[k]; + igraph_int_t ws = VECTOR(size)[w]; if (ws >= 0) { /******************************/ /* delete w from set(size(w)) */ /******************************/ - igraph_integer_t nw = VECTOR(next)[w]; - igraph_integer_t pw = VECTOR(prev)[w]; + igraph_int_t nw = VECTOR(next)[w]; + igraph_int_t pw = VECTOR(prev)[w]; if (nw != 0) { VECTOR(prev)[nw - 1] = pw; } @@ -278,11 +278,11 @@ igraph_error_t igraph_is_chordal(const igraph_t *graph, igraph_vector_int_t *fill_in, igraph_t *newgraph) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); const igraph_vector_int_t *my_alpha = alpha, *my_alpham1 = alpham1; igraph_vector_int_t v_alpha, v_alpham1; igraph_vector_int_t f, index; - igraph_integer_t i; + igraph_int_t i; igraph_adjlist_t adjlist; igraph_vector_int_t mark; igraph_bool_t calc_edges = fill_in || newgraph; @@ -292,7 +292,7 @@ igraph_error_t igraph_is_chordal(const igraph_t *graph, /* local v, w, x */ /*****************/ - igraph_integer_t v, w, x; + igraph_int_t v, w, x; if (alpha && (igraph_vector_int_size(alpha) != no_of_nodes)) { IGRAPH_ERRORF("Alpha vector size (%" IGRAPH_PRId ") not equal to number of nodes (%" IGRAPH_PRId ").", @@ -320,15 +320,15 @@ igraph_error_t igraph_is_chordal(const igraph_t *graph, } else if (alpha && !alpham1) { IGRAPH_VECTOR_INT_INIT_FINALLY(&v_alpham1, no_of_nodes); my_alpham1 = &v_alpham1; - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { - igraph_integer_t i = VECTOR(*my_alpha)[v]; + for (igraph_int_t v = 0; v < no_of_nodes; v++) { + igraph_int_t i = VECTOR(*my_alpha)[v]; VECTOR(*my_alpham1)[i] = v; } } else if (!alpha && alpham1) { IGRAPH_VECTOR_INT_INIT_FINALLY(&v_alpha, no_of_nodes); my_alpha = &v_alpha; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t v = VECTOR(*my_alpham1)[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t v = VECTOR(*my_alpham1)[i]; VECTOR(*my_alpha)[v] = i; } } @@ -357,7 +357,7 @@ igraph_error_t igraph_is_chordal(const igraph_t *graph, for (i = 0; i < no_of_nodes; i++) { igraph_vector_int_t *neis; - igraph_integer_t j, len; + igraph_int_t j, len; /**********************************************/ /* w := alpham1(i); f(w) := w; index(w) := i; */ diff --git a/src/vendor/cigraph/src/misc/cocitation.c b/src/vendor/cigraph/src/misc/cocitation.c index 5545f3737b3..9eb4586ab9e 100644 --- a/src/vendor/cigraph/src/misc/cocitation.c +++ b/src/vendor/cigraph/src/misc/cocitation.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -170,7 +170,7 @@ igraph_error_t igraph_similarity_inverse_log_weighted(const igraph_t *graph, igraph_vector_t weights; igraph_vector_int_t degrees; igraph_neimode_t mode0 = IGRAPH_REVERSE_MODE(mode); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { IGRAPH_ERROR("Invalid mode for inverse log weighted similarity.", IGRAPH_EINVMODE); @@ -179,7 +179,7 @@ igraph_error_t igraph_similarity_inverse_log_weighted(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&weights, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), mode0, IGRAPH_LOOPS)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(weights)[i] = VECTOR(degrees)[i]; if (VECTOR(weights)[i] > 1) { VECTOR(weights)[i] = 1.0 / log(VECTOR(weights)[i]); @@ -199,9 +199,9 @@ static igraph_error_t igraph_i_cocitation_real(const igraph_t *graph, igraph_mat igraph_neimode_t mode, igraph_vector_t *weights) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_vids; - igraph_integer_t i; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_vids; + igraph_int_t i; igraph_vector_int_t neis; igraph_vector_int_t vid_reverse_index; igraph_vit_t vit; @@ -216,7 +216,7 @@ static igraph_error_t igraph_i_cocitation_real(const igraph_t *graph, igraph_mat IGRAPH_VECTOR_INT_INIT_FINALLY(&vid_reverse_index, no_of_nodes); igraph_vector_int_fill(&vid_reverse_index, -1); for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t v = IGRAPH_VIT_GET(vit); + igraph_int_t v = IGRAPH_VIT_GET(vit); if (v < 0 || v >= no_of_nodes) { IGRAPH_ERROR("Invalid vertex ID in vertex selector.", IGRAPH_EINVVID); } @@ -229,20 +229,20 @@ static igraph_error_t igraph_i_cocitation_real(const igraph_t *graph, igraph_mat /* The result */ - for (igraph_integer_t from = 0; from < no_of_nodes; from++) { + for (igraph_int_t from = 0; from < no_of_nodes; from++) { IGRAPH_ALLOW_INTERRUPTION(); const igraph_real_t weight = weights ? VECTOR(*weights)[from] : 1; IGRAPH_CHECK(igraph_neighbors(graph, &neis, from, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); - const igraph_integer_t nei_count = igraph_vector_int_size(&neis); + const igraph_int_t nei_count = igraph_vector_int_size(&neis); for (i = 0; i < nei_count - 1; i++) { - igraph_integer_t u = VECTOR(neis)[i]; - igraph_integer_t k = VECTOR(vid_reverse_index)[u]; - for (igraph_integer_t j = i + 1; j < nei_count; j++) { - igraph_integer_t v = VECTOR(neis)[j]; - igraph_integer_t l = VECTOR(vid_reverse_index)[v]; + igraph_int_t u = VECTOR(neis)[i]; + igraph_int_t k = VECTOR(vid_reverse_index)[u]; + for (igraph_int_t j = i + 1; j < nei_count; j++) { + igraph_int_t v = VECTOR(neis)[j]; + igraph_int_t l = VECTOR(vid_reverse_index)[v]; if (k != -1) { MATRIX(*res, k, v) += weight; } @@ -265,10 +265,10 @@ static igraph_error_t igraph_i_cocitation_real(const igraph_t *graph, igraph_mat static igraph_error_t igraph_i_neisets_intersect( const igraph_vector_int_t *v1, const igraph_vector_int_t *v2, - igraph_integer_t *len_union, igraph_integer_t *len_intersection + igraph_int_t *len_union, igraph_int_t *len_intersection ) { /* ASSERT: v1 and v2 are sorted */ - igraph_integer_t n1 = igraph_vector_int_size(v1), n2 = igraph_vector_int_size(v2); + igraph_int_t n1 = igraph_vector_int_size(v1), n2 = igraph_vector_int_size(v2); *len_intersection = igraph_vector_int_intersection_size_sorted(v1, v2); *len_union = n1 + n2 - *len_intersection; return IGRAPH_SUCCESS; @@ -287,7 +287,7 @@ 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 vit_from and \p vit_to, respectively. + * as the number of vertex IDs in \p from and \p to, respectively. * \param from The vertex IDs of the first set of vertices of the * pairs for which the calculation will be done. * \param to The vertex IDs of the second set of vertices of the @@ -328,10 +328,10 @@ igraph_error_t igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t 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_from, vit_to; - igraph_integer_t i, j; - igraph_integer_t len_union, len_intersection; + igraph_int_t i, j; + igraph_int_t len_union, len_intersection; igraph_vector_int_t *v1, *v2; - igraph_integer_t k; + igraph_int_t k; IGRAPH_CHECK(igraph_vit_create(graph, from, &vit_from)); IGRAPH_FINALLY(igraph_vit_destroy, &vit_from); @@ -439,13 +439,13 @@ igraph_error_t igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t */ 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_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_lazy_adjlist_t al; - igraph_integer_t u, v; - igraph_integer_t len_union, len_intersection; + igraph_int_t u, v; + igraph_int_t len_union, len_intersection; igraph_vector_int_t *v1, *v2; - igraph_integer_t k = igraph_vector_int_size(pairs); + igraph_int_t k = igraph_vector_int_size(pairs); if (k % 2 != 0) { IGRAPH_ERROR("Number of elements in `pairs' must be even.", IGRAPH_EINVAL); } @@ -463,8 +463,8 @@ igraph_error_t igraph_similarity_jaccard_pairs(const igraph_t *graph, igraph_vec igraph_bitset_t seen; IGRAPH_BITSET_INIT_FINALLY(&seen, no_of_nodes); - for (igraph_integer_t i = 0; i < k; i++) { - igraph_integer_t j = VECTOR(*pairs)[i]; + for (igraph_int_t i = 0; i < k; i++) { + igraph_int_t j = VECTOR(*pairs)[i]; if (IGRAPH_BIT_TEST(seen, j)) { continue; } @@ -480,7 +480,7 @@ igraph_error_t igraph_similarity_jaccard_pairs(const igraph_t *graph, igraph_vec IGRAPH_FINALLY_CLEAN(1); } - for (igraph_integer_t i = 0, j = 0; i < k; i += 2, j++) { + for (igraph_int_t i = 0, j = 0; i < k; i += 2, j++) { u = VECTOR(*pairs)[i]; v = VECTOR(*pairs)[i + 1]; @@ -585,10 +585,10 @@ 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 vit_from and \p vit_to, respectively. - * \param vit_from The vertex IDs of the first vertices of the + * as the number of vertex IDs in \p from and \p to, respectively. + * \param 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 + * \param 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: @@ -623,15 +623,15 @@ 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 vit_from, const igraph_vs_t vit_to, + const igraph_vs_t from, const igraph_vs_t to, igraph_neimode_t mode, igraph_bool_t loops) { - IGRAPH_CHECK(igraph_similarity_jaccard(graph, res, vit_from, vit_to, mode, loops)); + IGRAPH_CHECK(igraph_similarity_jaccard(graph, res, from, to, mode, loops)); - igraph_integer_t nr = igraph_matrix_nrow(res); - igraph_integer_t nc = igraph_matrix_ncol(res); - for (igraph_integer_t i = 0; i < nr; i++) { - for (igraph_integer_t j = 0; j < nc; j++) { + igraph_int_t nr = igraph_matrix_nrow(res); + igraph_int_t nc = igraph_matrix_ncol(res); + for (igraph_int_t i = 0; i < nr; i++) { + for (igraph_int_t j = 0; j < nc; j++) { igraph_real_t x = MATRIX(*res, i, j); MATRIX(*res, i, j) = 2 * x / (1 + x); } @@ -694,8 +694,8 @@ igraph_error_t igraph_similarity_dice_pairs(const igraph_t *graph, igraph_vector const igraph_vector_int_t *pairs, igraph_neimode_t mode, igraph_bool_t loops) { IGRAPH_CHECK(igraph_similarity_jaccard_pairs(graph, res, pairs, mode, loops)); - igraph_integer_t n = igraph_vector_size(res); - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t n = igraph_vector_size(res); + for (igraph_int_t i = 0; i < n; i++) { igraph_real_t x = VECTOR(*res)[i]; VECTOR(*res)[i] = 2 * x / (1 + x); } @@ -757,8 +757,8 @@ igraph_error_t igraph_similarity_dice_es(const igraph_t *graph, igraph_vector_t const igraph_es_t es, igraph_neimode_t mode, igraph_bool_t loops) { IGRAPH_CHECK(igraph_similarity_jaccard_es(graph, res, es, mode, loops)); - igraph_integer_t n = igraph_vector_size(res); - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t n = igraph_vector_size(res); + for (igraph_int_t i = 0; i < n; i++) { igraph_real_t x = VECTOR(*res)[i]; VECTOR(*res)[i] = 2 * x / (1 + x); } diff --git a/src/vendor/cigraph/src/misc/coloring.c b/src/vendor/cigraph/src/misc/coloring.c index e62c467c18d..a4081e8d37e 100644 --- a/src/vendor/cigraph/src/misc/coloring.c +++ b/src/vendor/cigraph/src/misc/coloring.c @@ -30,8 +30,8 @@ /* COLORED_NEIGHBORS: Choose vertices based on the number of already coloured neighbours. */ static igraph_error_t igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, igraph_vector_int_t *colors) { - igraph_integer_t i, vertex, maxdeg; - igraph_integer_t vc = igraph_vcount(graph); + igraph_int_t i, vertex, maxdeg; + igraph_int_t vc = igraph_vcount(graph); igraph_2wheap_t cn; /* indexed heap storing number of already coloured neighbours */ igraph_vector_int_t neighbors, nei_colors; @@ -80,14 +80,14 @@ static igraph_error_t igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, * Colors will be decremented to start at 0 later. */ while (true) { IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, vertex, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); - igraph_integer_t nei_count = igraph_vector_int_size(&neighbors); + igraph_int_t nei_count = igraph_vector_int_size(&neighbors); /* Colour current vertex by finding the smallest available non-0 color. * Note that self-loops are effectively skipped as they merely prevent * the current vertex from being colored with the color value it presently * has, which is 0 (meaning uncolored). */ { - igraph_integer_t col; + igraph_int_t col; IGRAPH_CHECK(igraph_vector_int_resize(&nei_colors, nei_count)); for (i = 0; i < nei_count; ++i) { @@ -109,7 +109,7 @@ static igraph_error_t igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, /* increment number of coloured neighbours for each neighbour of vertex */ for (i = 0; i < nei_count; ++i) { - igraph_integer_t idx = VECTOR(neighbors)[i]; + igraph_int_t idx = VECTOR(neighbors)[i]; if (igraph_2wheap_has_elem(&cn, idx)) { igraph_2wheap_modify(&cn, idx, igraph_2wheap_get(&cn, idx) + 1); } @@ -140,8 +140,8 @@ static igraph_error_t igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, /* DSATUR: Choose vertices based on the number of adjacent colours, i.e. "saturation degree" */ typedef struct { - igraph_integer_t saturation_degree; /* number of colors used by neighbors */ - igraph_integer_t edge_degree; /* degree in the subgraph induced by uncolored vertices */ + igraph_int_t saturation_degree; /* number of colors used by neighbors */ + igraph_int_t edge_degree; /* degree in the subgraph induced by uncolored vertices */ } dsatur_t; static int dsatur_t_compare(const void *left, const void *right) { @@ -160,13 +160,13 @@ static int dsatur_t_compare(const void *left, const void *right) { } static igraph_bool_t dsatur_is_color_used_by_neighbour( - const igraph_vector_int_t *colors, igraph_integer_t color, + const igraph_vector_int_t *colors, igraph_int_t color, const igraph_vector_int_t *neighbors ) { - igraph_integer_t nei_count = igraph_vector_int_size(neighbors); + igraph_int_t nei_count = igraph_vector_int_size(neighbors); - for (igraph_integer_t i=0; i < nei_count; i++) { - igraph_integer_t nei = VECTOR(*neighbors)[i]; + for (igraph_int_t i=0; i < nei_count; i++) { + igraph_int_t nei = VECTOR(*neighbors)[i]; if (VECTOR(*colors)[nei] == color) { return true; } @@ -178,12 +178,12 @@ static igraph_bool_t dsatur_is_color_used_by_neighbour( static void dsatur_update_heap( const igraph_adjlist_t *adjlist, igraph_gen2wheap_t *node_degrees_heap, const igraph_vector_int_t *neighbors, const igraph_vector_int_t *colors, - igraph_integer_t color + igraph_int_t color ) { igraph_gen2wheap_delete_max(node_degrees_heap); - igraph_integer_t nei_count = igraph_vector_int_size(neighbors); - for (igraph_integer_t i=0; i < nei_count; i++) { - igraph_integer_t nei = VECTOR(*neighbors)[i]; + igraph_int_t nei_count = igraph_vector_int_size(neighbors); + for (igraph_int_t i=0; i < nei_count; i++) { + igraph_int_t nei = VECTOR(*neighbors)[i]; if (!igraph_gen2wheap_has_elem(node_degrees_heap, nei)) { continue; } @@ -196,10 +196,10 @@ static void dsatur_update_heap( } } -static igraph_integer_t dsatur_get_first_viable_color(const igraph_vector_int_t *used_colors_sorted) { - igraph_integer_t color_count = igraph_vector_int_size(used_colors_sorted); - igraph_integer_t i = 0; - igraph_integer_t col = 0; +static igraph_int_t dsatur_get_first_viable_color(const igraph_vector_int_t *used_colors_sorted) { + igraph_int_t color_count = igraph_vector_int_size(used_colors_sorted); + igraph_int_t i = 0; + igraph_int_t col = 0; while (i < color_count && VECTOR(*used_colors_sorted)[i] == col) { while (i < color_count && VECTOR(*used_colors_sorted)[i] == col) { i++; @@ -212,7 +212,7 @@ static igraph_integer_t dsatur_get_first_viable_color(const igraph_vector_int_t static igraph_error_t igraph_i_vertex_coloring_dsatur( const igraph_t *graph, igraph_vector_int_t *colors ) { - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t vcount = igraph_vcount(graph); IGRAPH_CHECK(igraph_vector_int_resize(colors, vcount)); if (vcount == 0) { @@ -236,7 +236,7 @@ static igraph_error_t igraph_i_vertex_coloring_dsatur( IGRAPH_CHECK(igraph_gen2wheap_init(&node_degrees_heap, dsatur_t_compare, sizeof(dsatur_t), vcount)); IGRAPH_FINALLY(igraph_gen2wheap_destroy, &node_degrees_heap); - for (igraph_integer_t vertex = 0; vertex < vcount; vertex++) { + for (igraph_int_t vertex = 0; vertex < vcount; vertex++) { dsatur_t dsatur; dsatur.saturation_degree = 0; dsatur.edge_degree = igraph_vector_int_size(igraph_adjlist_get(&adjlist, vertex)); @@ -247,18 +247,18 @@ static igraph_error_t igraph_i_vertex_coloring_dsatur( IGRAPH_VECTOR_INT_INIT_FINALLY(&used_colors_sorted, 0); while (! igraph_gen2wheap_empty(&node_degrees_heap)) { - igraph_integer_t node_to_color = igraph_gen2wheap_max_index(&node_degrees_heap); + igraph_int_t node_to_color = igraph_gen2wheap_max_index(&node_degrees_heap); igraph_vector_int_t *neighbors = igraph_adjlist_get(&adjlist, node_to_color); - igraph_integer_t nei_count = igraph_vector_int_size(neighbors); + igraph_int_t nei_count = igraph_vector_int_size(neighbors); igraph_vector_int_clear(&used_colors_sorted); - for (igraph_integer_t i=0; i < nei_count; i++) { - igraph_integer_t nei = VECTOR(*neighbors)[i]; + for (igraph_int_t i=0; i < nei_count; i++) { + igraph_int_t nei = VECTOR(*neighbors)[i]; if (VECTOR(*colors)[nei] != -1) { IGRAPH_CHECK(igraph_vector_int_push_back(&used_colors_sorted, VECTOR(*colors)[nei])); } } igraph_vector_int_sort(&used_colors_sorted); - igraph_integer_t color = dsatur_get_first_viable_color(&used_colors_sorted); + igraph_int_t color = dsatur_get_first_viable_color(&used_colors_sorted); dsatur_update_heap(&adjlist, &node_degrees_heap, neighbors, colors, color); VECTOR(*colors)[node_to_color] = color; @@ -314,8 +314,6 @@ igraph_error_t igraph_vertex_coloring_greedy(const igraph_t *graph, igraph_vecto * \function igraph_is_vertex_coloring * \brief Checks whether a vertex coloring is valid. * - * \experimental - * * This function checks whether the given vertex type/color assignment is a valid * vertex coloring, i.e., no two adjacent vertices have the same color. * Self-loops are ignored. @@ -326,14 +324,16 @@ igraph_error_t igraph_vertex_coloring_greedy(const igraph_t *graph, igraph_vecto * \return Error code. * * Time complexity: O(|E|), linear in the number of edges. + * + * \example examples/simple/coloring.c */ igraph_error_t igraph_is_vertex_coloring( const igraph_t *graph, const igraph_vector_int_t *types, igraph_bool_t *res) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); int iter = 0; if (igraph_vector_int_size(types) != vcount) { @@ -342,9 +342,9 @@ igraph_error_t igraph_is_vertex_coloring( *res = true; - for (igraph_integer_t e = 0; e < ecount; e++) { - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); + for (igraph_int_t e = 0; e < ecount; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); /* Skip self-loops */ if (from == to) { @@ -366,8 +366,6 @@ igraph_error_t igraph_is_vertex_coloring( * \function igraph_is_bipartite_coloring * \brief Checks whether a bipartite vertex coloring is valid. * - * \experimental - * * This function checks whether the given vertex type assignment is a valid * bipartite coloring, i.e., no two adjacent vertices have the same type. * Additionally, for directed graphs, it determines the mode of edge directions. @@ -393,8 +391,8 @@ igraph_error_t igraph_is_bipartite_coloring( igraph_bool_t *res, igraph_neimode_t *mode) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); int iter = 0; if (igraph_vector_bool_size(types) != vcount) { @@ -410,9 +408,9 @@ igraph_error_t igraph_is_bipartite_coloring( igraph_bool_t has_false_to_true = false; igraph_bool_t has_true_to_false = false; - for (igraph_integer_t e = 0; e < ecount; e++) { - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); + for (igraph_int_t e = 0; e < ecount; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); /* Skip self-loops */ if (from == to) { @@ -458,8 +456,6 @@ igraph_error_t igraph_is_bipartite_coloring( * \function igraph_is_edge_coloring * \brief Checks whether an edge coloring is valid. * - * \experimental - * * This function checks whether the given edge color assignment is a valid * edge coloring, i.e., no two adjacent edges have the same color. * @@ -479,8 +475,8 @@ igraph_error_t igraph_is_edge_coloring( const igraph_vector_int_t *types, igraph_bool_t *res) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_vector_int_t edges, edge_colors; int iter = 0; @@ -495,7 +491,7 @@ igraph_error_t igraph_is_edge_coloring( IGRAPH_VECTOR_INT_INIT_FINALLY(&edge_colors, 0); /* For each vertex, check that all incident edges have different colors */ - for (igraph_integer_t v = 0; v < vcount; v++) { + for (igraph_int_t v = 0; v < vcount; v++) { IGRAPH_CHECK(igraph_incident(graph, &edges, v, IGRAPH_ALL, IGRAPH_LOOPS_ONCE)); /* Get sorted edge color list */ @@ -503,8 +499,8 @@ igraph_error_t igraph_is_edge_coloring( igraph_vector_int_sort(&edge_colors); /* Look for consecutive duplicates in edge color list */ - igraph_integer_t edge_color_count = igraph_vector_int_size(&edge_colors); - for (igraph_integer_t i = 0; i < edge_color_count - 1; i++) { + igraph_int_t edge_color_count = igraph_vector_int_size(&edge_colors); + for (igraph_int_t i = 0; i < edge_color_count - 1; i++) { if (VECTOR(edge_colors)[i] == VECTOR(edge_colors)[i + 1]) { *res = false; goto done; diff --git a/src/vendor/cigraph/src/misc/conversion.c b/src/vendor/cigraph/src/misc/conversion.c index e277652f07d..364fc8378b3 100644 --- a/src/vendor/cigraph/src/misc/conversion.c +++ b/src/vendor/cigraph/src/misc/conversion.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -94,10 +94,10 @@ igraph_error_t igraph_get_adjacency( const igraph_t *graph, igraph_matrix_t *res, igraph_get_adjacency_t type, const igraph_vector_t *weights, igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); - igraph_integer_t i, from, to; + igraph_int_t i, from, to; IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, no_of_nodes)); igraph_matrix_null(res); @@ -211,11 +211,11 @@ igraph_error_t igraph_get_adjacency_sparse( const igraph_vector_t *weights, igraph_loops_t loops ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); - igraph_integer_t nzmax = directed ? no_of_edges : no_of_edges * 2; - igraph_integer_t i, from, to; + igraph_int_t nzmax = directed ? no_of_edges : no_of_edges * 2; + igraph_int_t i, from, to; IGRAPH_CHECK(igraph_sparsemat_resize(res, no_of_nodes, no_of_nodes, nzmax)); @@ -361,8 +361,8 @@ igraph_error_t igraph_get_edgelist(const igraph_t *graph, igraph_vector_int_t *r igraph_error_t igraph_to_directed(igraph_t *graph, igraph_to_directed_t mode) { - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (igraph_is_directed(graph)) { return IGRAPH_SUCCESS; @@ -375,15 +375,15 @@ igraph_error_t igraph_to_directed(igraph_t *graph, { igraph_t newgraph; igraph_vector_int_t edges; - igraph_integer_t size = no_of_edges * 2; + igraph_int_t size = no_of_edges * 2; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, size); IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0)); if (mode == IGRAPH_TO_DIRECTED_RANDOM) { - for (igraph_integer_t i=0; i < no_of_edges; ++i) { + for (igraph_int_t i=0; i < no_of_edges; ++i) { if (RNG_INTEGER(0,1)) { - igraph_integer_t temp = VECTOR(edges)[2*i]; + igraph_int_t temp = VECTOR(edges)[2*i]; VECTOR(edges)[2*i] = VECTOR(edges)[2*i+1]; VECTOR(edges)[2*i+1] = temp; } @@ -396,9 +396,9 @@ igraph_error_t igraph_to_directed(igraph_t *graph, the implementation of the minimal API in type_indexededgelist.c. Therefore, we order the edge endpoints anyway in the following loop: */ - for (igraph_integer_t i=0; i < no_of_edges; ++i) { + for (igraph_int_t i=0; i < no_of_edges; ++i) { if (VECTOR(edges)[2*i] > VECTOR(edges)[2*i+1]) { - igraph_integer_t temp = VECTOR(edges)[2*i]; + igraph_int_t temp = VECTOR(edges)[2*i]; VECTOR(edges)[2*i] = VECTOR(edges)[2*i+1]; VECTOR(edges)[2*i+1] = temp; } @@ -423,7 +423,7 @@ igraph_error_t igraph_to_directed(igraph_t *graph, igraph_t newgraph; igraph_vector_int_t edges; igraph_vector_int_t index; - igraph_integer_t size; + igraph_int_t size; IGRAPH_SAFE_MULT(no_of_edges, 4, &size); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); @@ -431,7 +431,7 @@ igraph_error_t igraph_to_directed(igraph_t *graph, IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0)); IGRAPH_CHECK(igraph_vector_int_resize(&edges, size)); IGRAPH_VECTOR_INT_INIT_FINALLY(&index, no_of_edges * 2); - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { VECTOR(edges)[no_of_edges * 2 + i * 2] = VECTOR(edges)[i * 2 + 1]; VECTOR(edges)[no_of_edges * 2 + i * 2 + 1] = VECTOR(edges)[i * 2]; VECTOR(index)[i] = VECTOR(index)[no_of_edges + i] = i; @@ -497,8 +497,8 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, igraph_to_undirected_t mode, const igraph_attribute_combination_t *edge_comb) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t edges; igraph_t newgraph; igraph_bool_t attr = edge_comb && igraph_has_attribute_table(); @@ -526,7 +526,7 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, IGRAPH_FINALLY(igraph_eit_destroy, &eit); while (!IGRAPH_EIT_END(eit)) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t edge = IGRAPH_EIT_GET(eit); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, IGRAPH_FROM(graph, edge))); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, IGRAPH_TO(graph, edge))); IGRAPH_EIT_NEXT(eit); @@ -549,7 +549,7 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, } else if (mode == IGRAPH_TO_UNDIRECTED_COLLAPSE) { igraph_vector_int_t inadj, outadj; igraph_vector_int_t mergeinto; - igraph_integer_t actedge = 0; + igraph_int_t actedge = 0; if (attr) { IGRAPH_VECTOR_INT_INIT_FINALLY(&mergeinto, no_of_edges); @@ -559,10 +559,10 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&inadj, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&outadj, 0); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t n_out, n_in; - igraph_integer_t p1 = -1, p2 = -1; - igraph_integer_t e1 = 0, e2 = 0, n1 = 0, n2 = 0, last; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t n_out, n_in; + igraph_int_t p1 = -1, p2 = -1; + igraph_int_t e1 = 0, e2 = 0, n1 = 0, n2 = 0, last; IGRAPH_CHECK(igraph_incident(graph, &outadj, i, IGRAPH_OUT, IGRAPH_LOOPS)); IGRAPH_CHECK(igraph_incident(graph, &inadj, i, IGRAPH_IN, IGRAPH_LOOPS)); n_out = igraph_vector_int_size(&outadj); @@ -662,7 +662,7 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, } else if (mode == IGRAPH_TO_UNDIRECTED_MUTUAL) { igraph_vector_int_t inadj, outadj; igraph_vector_int_t mergeinto; - igraph_integer_t actedge = 0; + igraph_int_t actedge = 0; if (attr) { IGRAPH_VECTOR_INT_INIT_FINALLY(&mergeinto, no_of_edges); @@ -673,10 +673,10 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&inadj, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&outadj, 0); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t n_out, n_in; - igraph_integer_t p1 = -1, p2 = -1; - igraph_integer_t e1 = 0, e2 = 0, n1 = 0, n2 = 0; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t n_out, n_in; + igraph_int_t p1 = -1, p2 = -1; + igraph_int_t e1 = 0, e2 = 0, n1 = 0, n2 = 0; IGRAPH_CHECK(igraph_incident(graph, &outadj, i, IGRAPH_OUT, IGRAPH_LOOPS)); IGRAPH_CHECK(igraph_incident(graph, &inadj, i, IGRAPH_IN, IGRAPH_LOOPS)); n_out = igraph_vector_int_size(&outadj); @@ -790,10 +790,10 @@ igraph_error_t igraph_get_stochastic( const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t column_wise, const igraph_vector_t *weights ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); - igraph_integer_t from, to; + igraph_int_t from, to; igraph_vector_t sums; igraph_real_t sum; @@ -811,7 +811,7 @@ igraph_error_t igraph_get_stochastic( IGRAPH_LOOPS, weights )); - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { from = IGRAPH_FROM(graph, i); to = IGRAPH_TO(graph, i); sum = VECTOR(sums)[column_wise ? to : from]; @@ -825,7 +825,7 @@ igraph_error_t igraph_get_stochastic( IGRAPH_LOOPS, weights )); - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { from = IGRAPH_FROM(graph, i); to = IGRAPH_TO(graph, i); MATRIX(*res, from, to) += WEIGHT_OF(i) / VECTOR(sums)[column_wise ? to : from]; @@ -912,11 +912,11 @@ igraph_error_t igraph_to_prufer(const igraph_t *graph, igraph_vector_int_t* pruf If u is a leaf, we remove it and add its unique neighbor to the Prüfer sequence. If the removal of u turns the neighbor into a leaf which is < u, we repeat the procedure for the new leaf and so on. */ - igraph_integer_t u; + igraph_int_t u; igraph_vector_int_t degrees; igraph_vector_int_t neighbors; - igraph_integer_t prufer_index = 0; - igraph_integer_t n = igraph_vcount(graph); + igraph_int_t prufer_index = 0; + igraph_int_t n = igraph_vcount(graph); igraph_bool_t is_tree = false; IGRAPH_CHECK(igraph_is_tree(graph, &is_tree, NULL, IGRAPH_ALL)); @@ -936,12 +936,12 @@ igraph_error_t igraph_to_prufer(const igraph_t *graph, igraph_vector_int_t* pruf IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_NO_LOOPS)); for (u = 0; u < n; ++u) { - igraph_integer_t degree = VECTOR(degrees)[u]; - igraph_integer_t leaf = u; + igraph_int_t degree = VECTOR(degrees)[u]; + igraph_int_t leaf = u; while (degree == 1 && leaf <= u) { - igraph_integer_t neighbor = 0; - igraph_integer_t neighbor_count = 0; + igraph_int_t neighbor = 0; + igraph_int_t neighbor_count = 0; VECTOR(degrees)[leaf] = 0; /* mark leaf v as deleted */ @@ -951,7 +951,7 @@ igraph_error_t igraph_to_prufer(const igraph_t *graph, igraph_vector_int_t* pruf /* Find the unique remaining neighbor of the leaf */ neighbor_count = igraph_vector_int_size(&neighbors); - for (igraph_integer_t i = 0; i < neighbor_count; i++) { + for (igraph_int_t i = 0; i < neighbor_count; i++) { neighbor = VECTOR(neighbors)[i]; if (VECTOR(degrees)[neighbor] > 0) { break; diff --git a/src/vendor/cigraph/src/misc/degree_sequence.cpp b/src/vendor/cigraph/src/misc/degree_sequence.cpp index 2aa829bb23a..5907383d97a 100644 --- a/src/vendor/cigraph/src/misc/degree_sequence.cpp +++ b/src/vendor/cigraph/src/misc/degree_sequence.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Constructing realizations of degree sequences and bi-degree sequences. Copyright (C) 2018-2024 The igraph development team @@ -27,6 +27,8 @@ #include #include #include +#include +#include /******************************/ /***** Helper constructs ******/ @@ -34,21 +36,22 @@ // (vertex, degree) pair struct vd_pair { - igraph_integer_t vertex; - igraph_integer_t degree; + igraph_int_t vertex; + igraph_int_t degree; - vd_pair(igraph_integer_t vertex, igraph_integer_t degree) : vertex(vertex), degree(degree) {} + vd_pair() = default; + vd_pair(igraph_int_t vertex, igraph_int_t degree) : vertex(vertex), degree(degree) {} }; // (indegree, outdegree) -typedef std::pair bidegree; +typedef std::pair bidegree; // (vertex, bidegree) pair struct vbd_pair { - igraph_integer_t vertex; + igraph_int_t vertex; bidegree degree; - vbd_pair(igraph_integer_t vertex, bidegree degree) : vertex(vertex), degree(degree) {} + vbd_pair(igraph_int_t vertex, bidegree degree) : vertex(vertex), degree(degree) {} }; // Comparison function for vertex-degree pairs. @@ -66,123 +69,323 @@ template inline bool degree_less(const T &a, const T &b) { /***** Undirected simple graphs ******/ /*************************************/ -// Generate simple undirected realization as edge-list. -// If largest=true, always choose the vertex with the largest remaining degree to connect up next. -// Otherwise, always choose the one with the smallest remaining degree. -static igraph_error_t igraph_i_havel_hakimi(const igraph_vector_int_t *deg, igraph_vector_int_t *edges, bool largest) { - igraph_integer_t n = igraph_vector_int_size(deg); +// "Bucket Node" for nodes of the same degree +struct BNode { + igraph_int_t count = 0; + std::stack nodes; + igraph_int_t next; // next bucket (higher degree) + igraph_int_t prev; // prev bucket (lower degree) - igraph_integer_t ec = 0; // number of edges added so far + bool is_empty() const { return count == 0; } +}; - std::vector vertices; - vertices.reserve(n); - for (igraph_integer_t i = 0; i < n; ++i) { - vertices.push_back(vd_pair(i, VECTOR(*deg)[i])); - } +struct HavelHakimiList { + igraph_int_t n_buckets; // no of buckets, INCLUDING sentinels + std::vector buckets; - while (! vertices.empty()) { - if (largest) { - std::stable_sort(vertices.begin(), vertices.end(), degree_less); - } else { - std::stable_sort(vertices.begin(), vertices.end(), degree_greater); - } - - // take the next vertex to be connected up - vd_pair vd = vertices.back(); - vertices.pop_back(); + // Given degree sequence, sets up linked list of BNodes (degree buckets) + // sentinel BNode [0] and [N] as bookends + // O(N) + explicit HavelHakimiList(const igraph_vector_int_t *degseq) : + n_buckets(igraph_vector_int_size(degseq)+1), buckets(n_buckets) + { + igraph_int_t n_nodes = igraph_vector_int_size(degseq); + for (igraph_int_t i = 0; i <= n_nodes; i++) { + if (i == 0) { + buckets[i].prev = -1; + } else { + buckets[i].prev = i - 1; + } - if (vd.degree == 0) { - continue; + if (i == n_nodes) { + buckets[i].next = -1; + } else { + buckets[i].next = i + 1; + } } - if (vertices.size() < size_t(vd.degree)) { - goto fail; + for (igraph_int_t i = 0; i < n_nodes; i++) { + igraph_int_t degree = VECTOR(*degseq)[i]; + buckets[degree].nodes.push(vd_pair{i, degree}); + buckets[degree].count++; } + } - if (largest) { - for (igraph_integer_t i = 0; i < vd.degree; ++i) { - if (--(vertices[vertices.size() - 1 - i].degree) < 0) { - goto fail; - } + // ----- O(1) convenience functions ----- // + const BNode & head() const { return buckets.front(); } + const BNode & tail() const { return buckets.back(); } + + // gets the largest non-empty bucket below 'degree', + // or 0 if one does not exist + igraph_int_t get_prev(igraph_int_t degree) { + assert(0 < degree && degree <= n_buckets - 1); // upper sentinel allowed as input + igraph_int_t curr = buckets[degree].prev; + while (curr > 0 && buckets[curr].is_empty()) { + remove_bucket(curr); + curr = buckets[degree].prev; + } + return curr; + } - VECTOR(*edges)[2 * (ec + i)] = vd.vertex; - VECTOR(*edges)[2 * (ec + i) + 1] = vertices[vertices.size() - 1 - i].vertex; - } - } else { - // this loop can only be reached if all zero-degree nodes have already been removed - // therefore decrementing remaining degrees is safe - for (igraph_integer_t i = 0; i < vd.degree; ++i) { - vertices[i].degree--; + // returns max degree non-empty bucket, + // or 0 (sentinel) if all buckets are empty + igraph_int_t get_max_bucket() { + // TODO: either change get_prev to take a BNode, or change + // head()/tail() to return integers + return get_prev(n_buckets - 1); + } - VECTOR(*edges)[2 * (ec + i)] = vd.vertex; - VECTOR(*edges)[2 * (ec + i) + 1] = vertices[i].vertex; - } + // returns min degree non-empty bucket, + // or n_buckets - 1 (sentinel) if all buckets are empty + igraph_int_t get_min_bucket() { + igraph_int_t curr = head().next; + while (curr < n_buckets - 1 && buckets[curr].is_empty()) { + remove_bucket(curr); + curr = head().next; } + return curr; + } + + void remove_bucket(igraph_int_t degree) { + // bounds check and prevent accidental removal of sentinels + assert(0 < degree && degree < n_buckets - 1); - ec += vd.degree; + igraph_int_t &prev_idx = buckets[degree].prev; + igraph_int_t &next_idx = buckets[degree].next; + if (prev_idx != -1) buckets[prev_idx].next = next_idx; + if (next_idx != -1) buckets[next_idx].prev = prev_idx; + + prev_idx = -1; + next_idx = -1; } - return IGRAPH_SUCCESS; + void insert_bucket(igraph_int_t degree) { + assert(0 <= degree && degree < n_buckets - 1); // can insert into zero-degree bucket -fail: - IGRAPH_ERROR("The given degree sequence cannot be realized as a simple graph.", IGRAPH_EINVAL); -} + igraph_int_t &prev_idx = buckets[degree].prev; + igraph_int_t &next_idx = buckets[degree].next; + if (prev_idx == -1 && next_idx == -1) { + next_idx = degree + 1; + prev_idx = buckets[next_idx].prev; -// Choose vertices in the order of their IDs. -static igraph_error_t igraph_i_havel_hakimi_index(const igraph_vector_int_t *deg, igraph_vector_int_t *edges) { - igraph_integer_t n = igraph_vector_int_size(deg); + buckets[next_idx].prev = degree; + buckets[prev_idx].next = degree; + } + } - igraph_integer_t ec = 0; // number of edges added so far + void insert_node(vd_pair node) { + insert_bucket(node.degree); // does nothing if already exists + buckets[node.degree].nodes.push(vd_pair{node.vertex, node.degree}); + buckets[node.degree].count++; + } - typedef std::list vlist; - vlist vertices; - for (igraph_integer_t i = 0; i < n; ++i) { - vertices.push_back(vd_pair(i, VECTOR(*deg)[i])); + bool get_max_node(vd_pair &max_node) { + igraph_int_t max_bucket = get_max_bucket(); + if (max_bucket <= 0) { + return false; + } + max_node = buckets[max_bucket].nodes.top(); + return true; } - std::vector pointers; - pointers.reserve(n); - for (auto it = vertices.begin(); it != vertices.end(); ++it) { - pointers.push_back(it); + void remove_max_node() { + igraph_int_t max_bucket = get_max_bucket(); + if (max_bucket <= 0) return; + buckets[max_bucket].nodes.pop(); + buckets[max_bucket].count--; } - for (const auto &pt : pointers) { - vertices.sort(degree_greater); + bool get_min_node(vd_pair &min_node) { + igraph_int_t min_bucket = get_min_bucket(); + if (min_bucket >= n_buckets - 1) { + return false; + } + min_node = buckets[min_bucket].nodes.top(); + return true; + } - vd_pair vd = *pt; - vertices.erase(pt); + void remove_min_node() { + igraph_int_t min_bucket = get_min_bucket(); + if (min_bucket >= n_buckets - 1) return; + buckets[min_bucket].nodes.pop(); + buckets[min_bucket].count--; + } - if (vd.degree == 0) { - continue; + // Given degree of selected "hub" node, returns degree many "spoke" nodes to connect to + // amortized O(alpha(n)) + igraph_error_t get_spokes(igraph_int_t degree, const igraph_vector_int_t &seq, + igraph_vector_int_t &spokes) { + std::stack buckets_req; // stack of needed degree buckets + igraph_int_t num_nodes = 0; + igraph_int_t curr = get_max_bucket(); // starts with max_bucket + + igraph_vector_int_clear(&spokes); + IGRAPH_CHECK(igraph_vector_int_reserve(&spokes, degree)); + + while (num_nodes < degree && curr > 0) { + num_nodes += buckets[curr].count; + buckets_req.push(curr); + curr = get_prev(curr); // gets next smallest NON-EMPTY bucket + } + if (num_nodes < degree) { // not enough spokes for hub degree + IGRAPH_ERROR("The given degree sequence cannot be realized as a simple graph.", IGRAPH_EINVAL); } - igraph_integer_t k; - vlist::iterator it; - for (it = vertices.begin(), k = 0; - k != vd.degree && it != vertices.end(); - ++it, ++k) { - if (--(it->degree) < 0) { - goto fail; + igraph_int_t num_skip = num_nodes - degree; + while (!buckets_req.empty()) { // starting from the smallest degree + igraph_int_t bucket = buckets_req.top(); + buckets_req.pop(); + + igraph_int_t to_get = buckets[bucket].count - num_skip; + while (to_get > 0) { + vd_pair node = buckets[bucket].nodes.top(); + if (VECTOR(seq)[node.vertex] != 0) { // if "not marked for removal" + IGRAPH_CHECK(igraph_vector_int_push_back(&spokes, node.vertex)); // add as spoke + + node.degree--; + insert_node(node); // first, insert into bucket below + + buckets[bucket].count--; + to_get--; + } + buckets[bucket].nodes.pop(); // then pop from original bucket } + num_skip = 0; + } + return IGRAPH_SUCCESS; + } +}; - VECTOR(*edges)[2 * (ec + k)] = vd.vertex; - VECTOR(*edges)[2 * (ec + k) + 1] = it->vertex; +/* + * This implementation works by grouping nodes by their remaining "stubs" (degrees) into an + * array of "degree buckets" (see struct HavelHakimiList above) - i.e. each bucket holds + * all nodes with that degree. The array runs from index 0 to index N, with 0 and N as + * sentinel buckets (since any graphical sequence for a simple graph will not have degrees + * greater than N - 1, and nodes with degree 0 can be ignored). Thus, only O(V) time is + * needed to allocate each node to its starting degree bucket, after which no re-sorting is + * done - if a node is used up as a "hub", it is simply removed (or lazy deleted if not + * immediately accessible), and if it is chosen as a "spoke", it will only shift down one + * bucket (constant operation). + * + * Additionally, each degree bucket keeps track of its next largest and next smallest degree + * bucket via their index in the array. This makes it very time efficient to find the + * largest and/or smallest nodes as needed for both "hub" and "spoke" nodes (specifically, + * amortized near-constant time). + * + * Below is an example run-through using the degree sequence [3, 2, 3, 1, 1] and the + * IGRAPH_REALIZE_DEGSEQ_SMALLEST method: + * + * Initial list + * [0][1][2][3][4][5] <- degree buckets + * 4 1 2 <- node ID (index in the degseq) in each bucket + * 3 0 + * + * By the smallest first method, we must first choose a node with the smallest degree to + * serve as the "hub". get_min_node() retrieves a node from bucket [1], which sentinel [0] + * indicates as its next largest non-empty bucket in its .next field. + * [0][1][2][3][4][5] 4 <- retrieved "hub" node. It is removed from the bucket + * 3 1 2 + * 0 + * + * Node 4 has degree 1, therefore we need to select 1 "spoke" node to connect it to. Using + * get_max_node(), we go to retrieve a node from bucket [4], which sentinel [5] indicates + * as its next smallest non-empty bucket. Finding [4] empty, the bucket is removed, and + * node 2 is finally retrieved from bucket [3]. + * [0][1][2][3][5] 4-2 <- an edge is formed between them + * 3 1 0 + * + * After one "stub"/degree of node 2 is used up, it gets shifted down one bucket. + * [0][1][2][3][5] 4-2 + * 3 2 0 + * 1 + * + * The process repeats. We look at the smallest degree bucket for a "hub" and remove it. + * [0][1][2][3][5] 4-2 + * 2 0 3 + * 1 + * + * Node 3 has degree 1, so we pick 1 "spoke", and replace it into the bucket below. + * [0][1][2][3][5] 4-2 + * 0 3-0 + * 2 + * 1 + * + * The process continues until we are unable to find either a non-zero "hub" node + * (algorithm complete and sequence is graphical) or enough non-zero "spoke" nodes once a + * hub has been selected (sequence is non-graphical). + */ +static igraph_error_t igraph_i_havel_hakimi(const igraph_vector_int_t *degseq, + igraph_vector_int_t *edges, + igraph_realize_degseq_t method) { + igraph_int_t n_nodes = igraph_vector_int_size(degseq); + + // ----- upfront error/graphicality checks ----- // + if (n_nodes == 0 || (n_nodes == 1 && VECTOR(*degseq)[0] == 0)) { + return IGRAPH_SUCCESS; + } + + for (igraph_int_t i = 0; i < n_nodes; i++) { + igraph_int_t deg = VECTOR(*degseq)[i]; + if (deg >= n_nodes) { + IGRAPH_ERROR("The given degree sequence cannot be realized as a simple graph.", IGRAPH_EINVAL); } - if (it == vertices.end() && k < vd.degree) { - goto fail; + } + + // ----- main Havel-Hakimi loop ----- // + // O(V + alpha(V) * E) + // O(V + E) for the LARGEST_FIRST method + igraph_vector_int_t seq; + IGRAPH_CHECK(igraph_vector_int_init_copy(&seq, degseq)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &seq); + + HavelHakimiList vault(&seq); + + igraph_int_t n_edges_added = 0; + igraph_vector_int_t spokes; + IGRAPH_VECTOR_INT_INIT_FINALLY(&spokes, 0); + + for (igraph_int_t i = 0; i < n_nodes; i++) { + // hub node selection + vd_pair hub; + if (method == IGRAPH_REALIZE_DEGSEQ_SMALLEST) { + if (!vault.get_min_node(/* out param */hub)) break; + vault.remove_min_node(); + } + else if (method == IGRAPH_REALIZE_DEGSEQ_LARGEST) { + if (!vault.get_max_node(/* out param */hub)) break; + vault.remove_max_node(); } + else if (method == IGRAPH_REALIZE_DEGSEQ_INDEX) { + igraph_int_t degree = VECTOR(seq)[i]; + hub = vd_pair{i, degree}; + vault.buckets[degree].count--; + } else { + // The fatal error is effectively an assertion that this line + // should not be reachable: + IGRAPH_FATAL("Invalid degree sequence realization method."); + } + VECTOR(seq)[hub.vertex] = 0; - ec += vd.degree; - } + // spoke nodes selection + IGRAPH_CHECK(vault.get_spokes(hub.degree, seq, spokes)); - return IGRAPH_SUCCESS; + igraph_int_t n_spokes = igraph_vector_int_size(&spokes); + for (igraph_int_t j = 0; j < n_spokes; j++) { + igraph_int_t spoke_idx = VECTOR(spokes)[j]; + VECTOR(*edges)[2*n_edges_added] = hub.vertex; + VECTOR(*edges)[2*n_edges_added + 1] = spoke_idx; + n_edges_added++; -fail: - IGRAPH_ERROR("The given degree sequence cannot be realized as a simple graph.", IGRAPH_EINVAL); + VECTOR(seq)[spoke_idx]--; + } + } + igraph_vector_int_destroy(&spokes); + igraph_vector_int_destroy(&seq); + IGRAPH_FINALLY_CLEAN(2); + return IGRAPH_SUCCESS; } - /***********************************/ /***** Undirected multigraphs ******/ /***********************************/ @@ -214,8 +417,9 @@ static void bubble_up(It first, It last, Compare comp) { // by adding loops on the last vertex. // If largest=false, and the degree sequence was potentially connected, the resulting // graph will be connected. +// O(V * E + V log V) static igraph_error_t igraph_i_realize_undirected_multi(const igraph_vector_int_t *deg, igraph_vector_int_t *edges, bool loops, bool largest) { - igraph_integer_t vcount = igraph_vector_int_size(deg); + igraph_int_t vcount = igraph_vector_int_size(deg); if (vcount == 0) { return IGRAPH_SUCCESS; @@ -223,15 +427,16 @@ static igraph_error_t igraph_i_realize_undirected_multi(const igraph_vector_int_ std::vector vertices; vertices.reserve(vcount); - for (igraph_integer_t i = 0; i < vcount; ++i) { - igraph_integer_t d = VECTOR(*deg)[i]; + for (igraph_int_t i = 0; i < vcount; ++i) { + igraph_int_t d = VECTOR(*deg)[i]; vertices.push_back(vd_pair(i, d)); } // Initial sort in non-increasing order. + // O (V log V) std::stable_sort(vertices.begin(), vertices.end(), degree_greater); - igraph_integer_t ec = 0; + igraph_int_t ec = 0; while (! vertices.empty()) { // Remove any zero degrees, and error on negative ones. @@ -247,7 +452,7 @@ static igraph_error_t igraph_i_realize_undirected_multi(const igraph_vector_int_ // or throw an error, depending on the 'loops' setting. if (vertices.size() == 1) { if (loops) { - for (igraph_integer_t i = 0; i < w.degree / 2; ++i) { + for (igraph_int_t i = 0; i < w.degree / 2; ++i) { VECTOR(*edges)[2 * ec] = w.vertex; VECTOR(*edges)[2 * ec + 1] = w.vertex; ec++; @@ -288,9 +493,9 @@ static igraph_error_t igraph_i_realize_undirected_multi(const igraph_vector_int_ return IGRAPH_SUCCESS; } - +// O(V * E + V log V) static igraph_error_t igraph_i_realize_undirected_multi_index(const igraph_vector_int_t *deg, igraph_vector_int_t *edges, bool loops) { - igraph_integer_t vcount = igraph_vector_int_size(deg); + igraph_int_t vcount = igraph_vector_int_size(deg); if (vcount == 0) { return IGRAPH_SUCCESS; @@ -298,7 +503,7 @@ static igraph_error_t igraph_i_realize_undirected_multi_index(const igraph_vecto typedef std::list vlist; vlist vertices; - for (igraph_integer_t i = 0; i < vcount; ++i) { + for (igraph_int_t i = 0; i < vcount; ++i) { vertices.push_back(vd_pair(i, VECTOR(*deg)[i])); } @@ -311,7 +516,7 @@ static igraph_error_t igraph_i_realize_undirected_multi_index(const igraph_vecto // Initial sort vertices.sort(degree_greater); - igraph_integer_t ec = 0; + igraph_int_t ec = 0; for (const auto &pt : pointers) { vd_pair vd = *pt; vertices.erase(pt); @@ -322,7 +527,7 @@ static igraph_error_t igraph_i_realize_undirected_multi_index(const igraph_vecto if (vertices.empty() || uit->degree == 0) { // We are out of non-zero degree vertices to connect to. if (loops) { - for (igraph_integer_t i = 0; i < vd.degree / 2; ++i) { + for (igraph_int_t i = 0; i < vd.degree / 2; ++i) { VECTOR(*edges)[2 * ec] = vd.vertex; VECTOR(*edges)[2 * ec + 1] = vd.vertex; ec++; @@ -372,19 +577,21 @@ inline bool is_nonzero_outdeg(const vbd_pair &vd) { // Realize bi-degree sequence as edge list // If smallest=true, always choose the vertex with "smallest" bi-degree for connecting up next, // otherwise choose the "largest" (based on lexicographic bi-degree ordering). +// O(E + V^2 log V) static igraph_error_t igraph_i_kleitman_wang(const igraph_vector_int_t *outdeg, const igraph_vector_int_t *indeg, igraph_vector_int_t *edges, bool smallest) { - igraph_integer_t n = igraph_vector_int_size(indeg); // number of vertices + igraph_int_t n = igraph_vector_int_size(indeg); // number of vertices - igraph_integer_t ec = 0; // number of edges added so far + igraph_int_t ec = 0; // number of edges added so far std::vector vertices; vertices.reserve(n); - for (igraph_integer_t i = 0; i < n; ++i) { + for (igraph_int_t i = 0; i < n; ++i) { vertices.push_back(vbd_pair(i, bidegree(VECTOR(*indeg)[i], VECTOR(*outdeg)[i]))); } while (true) { // sort vertices by (in, out) degree pairs in decreasing order + // O(V log V) std::stable_sort(vertices.begin(), vertices.end(), degree_greater); // remove (0,0)-degree vertices @@ -402,6 +609,7 @@ static igraph_error_t igraph_i_kleitman_wang(const igraph_vector_int_t *outdeg, // because there are _some_ non-zero degrees and the sum of in- and out-degrees // is the same vbd_pair *vdp; + // O(V) if (smallest) { vdp = &*std::find_if(vertices.rbegin(), vertices.rend(), is_nonzero_outdeg); } else { @@ -409,12 +617,12 @@ static igraph_error_t igraph_i_kleitman_wang(const igraph_vector_int_t *outdeg, } // are there a sufficient number of other vertices to connect to? - if (static_cast(vertices.size()) - 1 < vdp->degree.second) { + if (static_cast(vertices.size()) - 1 < vdp->degree.second) { goto fail; } // create the connections - igraph_integer_t k = 0; + igraph_int_t k = 0; for (auto it = vertices.begin(); k < vdp->degree.second; ++it) { @@ -443,14 +651,15 @@ static igraph_error_t igraph_i_kleitman_wang(const igraph_vector_int_t *outdeg, // Choose vertices in the order of their IDs. +// O(E + V^2 log V) static igraph_error_t igraph_i_kleitman_wang_index(const igraph_vector_int_t *outdeg, const igraph_vector_int_t *indeg, igraph_vector_int_t *edges) { - igraph_integer_t n = igraph_vector_int_size(indeg); // number of vertices + igraph_int_t n = igraph_vector_int_size(indeg); // number of vertices - igraph_integer_t ec = 0; // number of edges added so far + igraph_int_t ec = 0; // number of edges added so far typedef std::list vlist; vlist vertices; - for (igraph_integer_t i = 0; i < n; ++i) { + for (igraph_int_t i = 0; i < n; ++i) { vertices.push_back(vbd_pair(i, bidegree(VECTOR(*indeg)[i], VECTOR(*outdeg)[i]))); } @@ -472,7 +681,7 @@ static igraph_error_t igraph_i_kleitman_wang_index(const igraph_vector_int_t *ou continue; } - igraph_integer_t k = 0; + igraph_int_t k = 0; vlist::iterator it; for (it = vertices.begin(); k != vd.degree.second && it != vertices.end(); @@ -514,8 +723,8 @@ static igraph_error_t igraph_i_realize_undirected_degree_sequence( const igraph_vector_int_t *deg, igraph_edge_type_sw_t allowed_edge_types, igraph_realize_degseq_t method) { - igraph_integer_t node_count = igraph_vector_int_size(deg); - igraph_integer_t deg_sum; + igraph_int_t node_count = igraph_vector_int_size(deg); + igraph_int_t deg_sum; IGRAPH_CHECK(igraph_i_safe_vector_int_sum(deg, °_sum)); @@ -571,13 +780,13 @@ static igraph_error_t igraph_i_realize_undirected_degree_sequence( { switch (method) { case IGRAPH_REALIZE_DEGSEQ_SMALLEST: - IGRAPH_CHECK(igraph_i_havel_hakimi(deg, &edges, false)); + IGRAPH_CHECK(igraph_i_havel_hakimi(deg, &edges, IGRAPH_REALIZE_DEGSEQ_SMALLEST)); break; case IGRAPH_REALIZE_DEGSEQ_LARGEST: - IGRAPH_CHECK(igraph_i_havel_hakimi(deg, &edges, true)); + IGRAPH_CHECK(igraph_i_havel_hakimi(deg, &edges, IGRAPH_REALIZE_DEGSEQ_LARGEST)); break; case IGRAPH_REALIZE_DEGSEQ_INDEX: - IGRAPH_CHECK(igraph_i_havel_hakimi_index(deg, &edges)); + IGRAPH_CHECK(igraph_i_havel_hakimi(deg, &edges, IGRAPH_REALIZE_DEGSEQ_INDEX)); break; default: IGRAPH_ERROR("Invalid degree sequence realization method.", IGRAPH_EINVAL); @@ -585,7 +794,7 @@ static igraph_error_t igraph_i_realize_undirected_degree_sequence( } else { - /* Remainig cases: + /* Remaining cases: * - At most one self-loop per vertex but multi-edges between distinct vertices allowed. * - At most one edge between distinct vertices but multi-self-loops allowed. * These cases cannot currently be requested through the documented API, @@ -609,8 +818,8 @@ static igraph_error_t igraph_i_realize_directed_degree_sequence( const igraph_vector_int_t *indeg, igraph_edge_type_sw_t allowed_edge_types, igraph_realize_degseq_t method) { - igraph_integer_t node_count = igraph_vector_int_size(outdeg); - igraph_integer_t edge_count, edge_count2, indeg_sum; + igraph_int_t node_count = igraph_vector_int_size(outdeg); + igraph_int_t edge_count, edge_count2, indeg_sum; IGRAPH_CHECK(igraph_i_safe_vector_int_sum(outdeg, &edge_count)); @@ -693,6 +902,11 @@ static igraph_error_t igraph_i_realize_directed_degree_sequence( * for constructing trees with a given degree sequence. * * + * For a undirected simple graph, the time complexity is O(V + alpha(V) * E). + * For an undirected multi graph, the time complexity is O(V * E + V log V). + * For a directed graph, the time complexity is O(E + V^2 log V). + * + * * References: * * @@ -728,8 +942,9 @@ static igraph_error_t igraph_i_realize_directed_degree_sequence( * or the out-degree sequence of a directed graph (if \p indeg is given). * \param indeg The in-degree sequence of a directed graph. Pass \c NULL to * generate an undirected graph. - * \param allowed_edge_types The types of edges to allow in the graph. For - * directed graphs, only \c IGRAPH_SIMPLE_SW is implemented at this moment. + * \param allowed_edge_types The types of edges to allow in the graph. See \ref + * igraph_edge_type_sw_t. For directed graphs, only \c IGRAPH_SIMPLE_SW is + * implemented at this moment. * For undirected graphs, the following values are valid: * \clist * \cli IGRAPH_SIMPLE_SW @@ -763,7 +978,7 @@ static igraph_error_t igraph_i_realize_directed_degree_sequence( * the \c INDEX method is not equivalent to the \c SMALLEST method above, * as \c SMALLEST uses the smallest \em remaining degree for selecting * vertices, not the smallest \em initial degree. - * \endclist + * \endclist * \return Error code: * \clist * \cli IGRAPH_UNIMPLEMENTED @@ -813,12 +1028,12 @@ static igraph_error_t igraph_i_realize_undirected_bipartite_index( const igraph_vector_int_t *degree1, const igraph_vector_int_t *degree2, igraph_bool_t multiedges ) { - igraph_integer_t ec = 0; // The number of edges added so far - igraph_integer_t n1 = igraph_vector_int_size(degree1); - igraph_integer_t n2 = igraph_vector_int_size(degree2); + igraph_int_t ec = 0; // The number of edges added so far + igraph_int_t n1 = igraph_vector_int_size(degree1); + igraph_int_t n2 = igraph_vector_int_size(degree2); igraph_vector_int_t edges; - igraph_integer_t ds1_sum; - igraph_integer_t ds2_sum; + igraph_int_t ds1_sum; + igraph_int_t ds2_sum; std::vector vertices1; std::vector vertices2; @@ -842,10 +1057,10 @@ static igraph_error_t igraph_i_realize_undirected_bipartite_index( vertices1.reserve(n1); vertices2.reserve(n2); - for (igraph_integer_t i = 0; i < n1; i++) { + for (igraph_int_t i = 0; i < n1; i++) { vertices1.push_back(vd_pair(i, VECTOR(*degree1)[i])); } - for (igraph_integer_t i = 0; i < n2; i++) { + for (igraph_int_t i = 0; i < n2; i++) { vertices2.push_back(vd_pair(i + n1, VECTOR(*degree2)[i])); } @@ -869,7 +1084,7 @@ static igraph_error_t igraph_i_realize_undirected_bipartite_index( goto fail; } - for (igraph_integer_t i = 0; i < vd_src.degree; i++) { + for (igraph_int_t i = 0; i < vd_src.degree; i++) { if ((*dest_vs)[i].degree == 0) { // Not enough non-zero remaining degree vertices in opposite partition. // Not graphical. @@ -926,8 +1141,6 @@ static igraph_error_t igraph_i_realize_undirected_bipartite_index( * \function igraph_realize_bipartite_degree_sequence * \brief Generates a bipartite graph with the given bidegree sequence. * - * \experimental - * * This function generates a bipartite graph with the given bidegree sequence, * using a Havel-Hakimi-like construction algorithm. The order in which vertices * are connected up is controlled by the \p method parameter. When using the @@ -974,12 +1187,12 @@ igraph_error_t igraph_realize_bipartite_degree_sequence( ) { IGRAPH_HANDLE_EXCEPTIONS_BEGIN; - igraph_integer_t ec = 0; // The number of edges added so far - igraph_integer_t n1 = igraph_vector_int_size(degrees1); - igraph_integer_t n2 = igraph_vector_int_size(degrees2); + igraph_int_t ec = 0; // The number of edges added so far + igraph_int_t n1 = igraph_vector_int_size(degrees1); + igraph_int_t n2 = igraph_vector_int_size(degrees2); igraph_vector_int_t edges; - igraph_integer_t ds1_sum; - igraph_integer_t ds2_sum; + igraph_int_t ds1_sum; + igraph_int_t ds2_sum; igraph_bool_t multiedges; igraph_bool_t largest; std::vector vertices1; @@ -1025,10 +1238,10 @@ igraph_error_t igraph_realize_bipartite_degree_sequence( vertices1.reserve(n1); vertices2.reserve(n2); - for (igraph_integer_t i = 0; i < n1; i++) { + for (igraph_int_t i = 0; i < n1; i++) { vertices1.push_back(vd_pair(i, VECTOR(*degrees1)[i])); } - for (igraph_integer_t i = 0; i < n2; i++) { + for (igraph_int_t i = 0; i < n2; i++) { vertices2.push_back(vd_pair(i + n1, VECTOR(*degrees2)[i])); } @@ -1092,7 +1305,7 @@ igraph_error_t igraph_realize_bipartite_degree_sequence( if (dest_vs->size() < size_t(vd_src.degree)) { goto fail; } - for (igraph_integer_t i = 0; i < vd_src.degree; i++) { + for (igraph_int_t i = 0; i < vd_src.degree; i++) { // Decrement the degree of the delta largest vertices in the opposite partition if ((*dest_vs)[i].degree == 0) { diff --git a/src/vendor/cigraph/src/misc/embedding.c b/src/vendor/cigraph/src/misc/embedding.c index 74a60683fac..2b427572a79 100644 --- a/src/vendor/cigraph/src/misc/embedding.c +++ b/src/vendor/cigraph/src/misc/embedding.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -48,7 +48,7 @@ static igraph_error_t igraph_i_asembeddingu(igraph_real_t *to, const igraph_real igraph_adjlist_t *outlist = data->outlist; const igraph_vector_t *cvec = data->cvec; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = (A+cD) from */ for (i = 0; i < n; i++) { @@ -56,7 +56,7 @@ static igraph_error_t igraph_i_asembeddingu(igraph_real_t *to, const igraph_real nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += from[nei]; } to[i] += VECTOR(*cvec)[i] * from[i]; @@ -75,7 +75,7 @@ static igraph_error_t igraph_i_asembeddinguw(igraph_real_t *to, const igraph_rea const igraph_vector_t *weights = data->weights; const igraph_t *graph = data->graph; igraph_vector_int_t *incs; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = (A+cD) from */ for (i = 0; i < n; i++) { @@ -83,8 +83,8 @@ static igraph_error_t igraph_i_asembeddinguw(igraph_real_t *to, const igraph_rea nlen = igraph_vector_int_size(incs); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*incs)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*incs)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; to[i] += w * from[nei]; } @@ -103,7 +103,7 @@ static igraph_error_t igraph_i_asembedding(igraph_real_t *to, const igraph_real_ const igraph_vector_t *cvec = data->cvec; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* tmp = (A+cD)' from */ for (i = 0; i < n; i++) { @@ -111,7 +111,7 @@ static igraph_error_t igraph_i_asembedding(igraph_real_t *to, const igraph_real_ nlen = igraph_vector_int_size(neis); VECTOR(*tmp)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; VECTOR(*tmp)[i] += from[nei]; } VECTOR(*tmp)[i] += VECTOR(*cvec)[i] * from[i]; @@ -123,7 +123,7 @@ static igraph_error_t igraph_i_asembedding(igraph_real_t *to, const igraph_real_ nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += VECTOR(*tmp)[nei]; } to[i] += VECTOR(*cvec)[i] * VECTOR(*tmp)[i]; @@ -139,7 +139,7 @@ static igraph_error_t igraph_i_asembedding_right(igraph_real_t *to, const igraph igraph_adjlist_t *inlist = data->inlist; const igraph_vector_t *cvec = data->cvec; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = (A+cD)' from */ for (i = 0; i < n; i++) { @@ -147,7 +147,7 @@ static igraph_error_t igraph_i_asembedding_right(igraph_real_t *to, const igraph nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += from[nei]; } to[i] += VECTOR(*cvec)[i] * from[i]; @@ -167,7 +167,7 @@ static igraph_error_t igraph_i_asembeddingw(igraph_real_t *to, const igraph_real const igraph_t *graph = data->graph; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *incs; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* tmp = (A+cD)' from */ for (i = 0; i < n; i++) { @@ -175,8 +175,8 @@ static igraph_error_t igraph_i_asembeddingw(igraph_real_t *to, const igraph_real nlen = igraph_vector_int_size(incs); VECTOR(*tmp)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*incs)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*incs)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; VECTOR(*tmp)[i] += w * from[nei]; } @@ -189,8 +189,8 @@ static igraph_error_t igraph_i_asembeddingw(igraph_real_t *to, const igraph_real nlen = igraph_vector_int_size(incs); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*incs)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*incs)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; to[i] += w * VECTOR(*tmp)[nei]; } @@ -209,7 +209,7 @@ static igraph_error_t igraph_i_asembeddingw_right(igraph_real_t *to, const igrap const igraph_vector_t *weights = data->weights; const igraph_t *graph = data->graph; igraph_vector_int_t *incs; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = (A+cD)' from */ for (i = 0; i < n; i++) { @@ -217,8 +217,8 @@ static igraph_error_t igraph_i_asembeddingw_right(igraph_real_t *to, const igrap nlen = igraph_vector_int_size(incs); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*incs)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*incs)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; to[i] += w * from[nei]; } @@ -235,7 +235,7 @@ static igraph_error_t igraph_i_lsembedding_da(igraph_real_t *to, const igraph_re igraph_adjlist_t *outlist = data->outlist; const igraph_vector_t *cvec = data->cvec; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = (D-A) from */ for (i = 0; i < n; i++) { @@ -243,7 +243,7 @@ static igraph_error_t igraph_i_lsembedding_da(igraph_real_t *to, const igraph_re nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] -= from[nei]; } to[i] += VECTOR(*cvec)[i] * from[i]; @@ -261,7 +261,7 @@ static igraph_error_t igraph_i_lsembedding_daw(igraph_real_t *to, const igraph_r const igraph_vector_t *weights = data->weights; const igraph_t *graph = data->graph; igraph_vector_int_t *incs; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = (D-A) from */ for (i = 0; i < n; i++) { @@ -269,8 +269,8 @@ static igraph_error_t igraph_i_lsembedding_daw(igraph_real_t *to, const igraph_r nlen = igraph_vector_int_size(incs); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*incs)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*incs)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; to[i] -= w * from[nei]; } @@ -289,7 +289,7 @@ static igraph_error_t igraph_i_lsembedding_dad(igraph_real_t *to, const igraph_r const igraph_vector_t *cvec = data->cvec; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = D^1/2 from */ for (i = 0; i < n; i++) { @@ -302,7 +302,7 @@ static igraph_error_t igraph_i_lsembedding_dad(igraph_real_t *to, const igraph_r nlen = igraph_vector_int_size(neis); VECTOR(*tmp)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; VECTOR(*tmp)[i] += to[nei]; } } @@ -325,7 +325,7 @@ static igraph_error_t igraph_i_lsembedding_dadw(igraph_real_t *to, const igraph_ const igraph_t *graph = data->graph; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *incs; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = D^-1/2 from */ for (i = 0; i < n; i++) { @@ -338,8 +338,8 @@ static igraph_error_t igraph_i_lsembedding_dadw(igraph_real_t *to, const igraph_ nlen = igraph_vector_int_size(incs); VECTOR(*tmp)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*incs)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*incs)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; VECTOR(*tmp)[i] += w * to[nei]; } @@ -356,8 +356,8 @@ static igraph_error_t igraph_i_lsembedding_dadw(igraph_real_t *to, const igraph_ nlen = igraph_vector_int_size(incs); VECTOR(*tmp)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*incs)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, i); + igraph_int_t edge = VECTOR(*incs)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, i); igraph_real_t w = VECTOR(*weights)[edge]; VECTOR(*tmp)[i] += w * to[nei]; } @@ -405,7 +405,7 @@ static igraph_error_t igraph_i_lseembedding_oap(igraph_real_t *to, const igraph_ const igraph_vector_t *deg_out = data->cvec2; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* tmp = O' from */ for (i = 0; i < n; i++) { @@ -418,7 +418,7 @@ static igraph_error_t igraph_i_lseembedding_oap(igraph_real_t *to, const igraph_ nlen = igraph_vector_int_size(neis); to[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; to[i] += VECTOR(*tmp)[nei]; } } @@ -439,7 +439,7 @@ static igraph_error_t igraph_i_lseembedding_oap(igraph_real_t *to, const igraph_ nlen = igraph_vector_int_size(neis); VECTOR(*tmp)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; VECTOR(*tmp)[i] += to[nei]; } } @@ -462,7 +462,7 @@ static igraph_error_t igraph_i_lseembedding_oap_right(igraph_real_t *to, const igraph_vector_t *deg_out = data->cvec2; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; + igraph_int_t i, j, nlen; /* to = O' from */ for (i = 0; i < n; i++) { @@ -475,7 +475,7 @@ static igraph_error_t igraph_i_lseembedding_oap_right(igraph_real_t *to, nlen = igraph_vector_int_size(neis); VECTOR(*tmp)[i] = 0.0; for (j = 0; j < nlen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; VECTOR(*tmp)[i] += to[nei]; } } @@ -501,8 +501,8 @@ static igraph_error_t igraph_i_lseembedding_oapw(igraph_real_t *to, const igraph const igraph_t *graph = data->graph; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; - igraph_integer_t edge, nei; + igraph_int_t i, j, nlen; + igraph_int_t edge, nei; igraph_real_t w; /* tmp = O' from */ @@ -566,8 +566,8 @@ static igraph_error_t igraph_i_lseembedding_oapw_right(igraph_real_t *to, const igraph_t *graph = data->graph; igraph_vector_t *tmp = data->tmp; igraph_vector_int_t *neis; - igraph_integer_t i, j, nlen; - igraph_integer_t edge, nei; + igraph_int_t i, j, nlen; + igraph_int_t edge, nei; igraph_real_t w; /* to = O' from */ @@ -597,7 +597,7 @@ static igraph_error_t igraph_i_lseembedding_oapw_right(igraph_real_t *to, } static igraph_error_t igraph_i_spectral_embedding(const igraph_t *graph, - igraph_integer_t no, + igraph_int_t no, const igraph_vector_t *weights, igraph_eigen_which_position_t which, igraph_bool_t scaled, @@ -613,11 +613,11 @@ static igraph_error_t igraph_i_spectral_embedding(const igraph_t *graph, igraph_bool_t eigen, igraph_bool_t zapsmall) { - igraph_integer_t vc = igraph_vcount(graph); + igraph_int_t vc = igraph_vcount(graph); igraph_vector_t tmp; igraph_adjlist_t outlist, inlist; igraph_inclist_t eoutlist, einlist; - igraph_integer_t i, j, cveclen = igraph_vector_size(cvec); + igraph_int_t i, j, cveclen = igraph_vector_size(cvec); igraph_i_asembedding_data_t data; igraph_vector_t tmpD; @@ -729,9 +729,8 @@ static igraph_error_t igraph_i_spectral_embedding(const igraph_t *graph, IGRAPH_CHECK(igraph_matrix_resize(Y, vc, no)); for (i = 0; i < no; i++) { igraph_real_t norm; - igraph_vector_t v; + igraph_vector_t v = igraph_vector_view(&MATRIX(*Y, 0, i), vc); callback_right(&MATRIX(*Y, 0, i), &MATRIX(*X, 0, i), (int) vc, &data); - igraph_vector_view(&v, &MATRIX(*Y, 0, i), vc); norm = 1.0 / igraph_blas_dnrm2(&v); igraph_vector_scale(&v, norm); } @@ -871,7 +870,7 @@ static igraph_error_t igraph_i_spectral_embedding(const igraph_t *graph, */ igraph_error_t igraph_adjacency_spectral_embedding(const igraph_t *graph, - igraph_integer_t n, + igraph_int_t n, const igraph_vector_t *weights, igraph_eigen_which_position_t which, igraph_bool_t scaled, @@ -905,7 +904,7 @@ igraph_error_t igraph_adjacency_spectral_embedding(const igraph_t *graph, } static igraph_error_t igraph_i_lse_und(const igraph_t *graph, - igraph_integer_t no, + igraph_int_t no, const igraph_vector_t *weights, igraph_eigen_which_position_t which, igraph_laplacian_spectral_embedding_type_t type, @@ -942,7 +941,7 @@ static igraph_error_t igraph_i_lse_und(const igraph_t *graph, break; case IGRAPH_EMBEDDING_DAD: case IGRAPH_EMBEDDING_I_DAD: { - igraph_integer_t i, n = igraph_vector_size(°); + igraph_int_t i, n = igraph_vector_size(°); for (i = 0; i < n; i++) { VECTOR(deg)[i] = 1.0 / sqrt(VECTOR(deg)[i]); } @@ -964,7 +963,7 @@ static igraph_error_t igraph_i_lse_und(const igraph_t *graph, } static igraph_error_t igraph_i_lse_dir(const igraph_t *graph, - igraph_integer_t no, + igraph_int_t no, const igraph_vector_t *weights, igraph_eigen_which_position_t which, igraph_laplacian_spectral_embedding_type_t type, @@ -980,7 +979,7 @@ static igraph_error_t igraph_i_lse_dir(const igraph_t *graph, weights ? igraph_i_lseembedding_oapw_right : igraph_i_lseembedding_oap_right; igraph_vector_t deg_in, deg_out; - igraph_integer_t i, n = igraph_vcount(graph); + igraph_int_t i, n = igraph_vcount(graph); if (type != IGRAPH_EMBEDDING_OAP) { IGRAPH_ERROR("Invalid Laplacian spectral embedding type", IGRAPH_EINVAL); @@ -1070,7 +1069,7 @@ static igraph_error_t igraph_i_lse_dir(const igraph_t *graph, */ igraph_error_t igraph_laplacian_spectral_embedding(const igraph_t *graph, - igraph_integer_t n, + igraph_int_t n, const igraph_vector_t *weights, igraph_eigen_which_position_t which, igraph_laplacian_spectral_embedding_type_t type, @@ -1128,9 +1127,9 @@ igraph_error_t igraph_laplacian_spectral_embedding(const igraph_t *graph, * \sa \ref igraph_adjacency_spectral_embedding(). */ -igraph_error_t igraph_dim_select(const igraph_vector_t *sv, igraph_integer_t *dim) { +igraph_error_t igraph_dim_select(const igraph_vector_t *sv, igraph_int_t *dim) { - igraph_integer_t i, n = igraph_vector_size(sv); + igraph_int_t i, n = igraph_vector_size(sv); igraph_real_t x, x2, sum1 = 0.0, sum2 = igraph_vector_sum(sv); igraph_real_t sumsq1 = 0.0, sumsq2 = 0.0; /* to be set */ igraph_real_t oldmean1, oldmean2, mean1 = 0.0, mean2 = sum2 / n; @@ -1154,7 +1153,7 @@ igraph_error_t igraph_dim_select(const igraph_vector_t *sv, igraph_integer_t *di } for (i = 0; i < n - 1; i++) { - igraph_integer_t n1 = i + 1, n2 = n - i - 1, n1m1 = n1 - 1, n2m1 = n2 - 1; + igraph_int_t n1 = i + 1, n2 = n - i - 1, n1m1 = n1 - 1, n2m1 = n2 - 1; x = VECTOR(*sv)[i]; x2 = x * x; sum1 += x; sum2 -= x; sumsq1 += x2; sumsq2 -= x2; diff --git a/src/vendor/cigraph/src/misc/graphicality.c b/src/vendor/cigraph/src/misc/graphicality.c index 7dffa73cd2b..30412a74d78 100644 --- a/src/vendor/cigraph/src/misc/graphicality.c +++ b/src/vendor/cigraph/src/misc/graphicality.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -20,6 +20,26 @@ #include "misc/graphicality.h" + +igraph_error_t igraph_i_edge_type_to_loops_multiple( + igraph_edge_type_sw_t allowed_edge_types, + igraph_bool_t *loops, igraph_bool_t *multiple) { + + *loops = (allowed_edge_types & IGRAPH_LOOPS_SW) ? true : false; + *multiple = (allowed_edge_types & IGRAPH_I_MULTI_EDGES_SW) ? true : false; + + if (*loops) { + igraph_bool_t multi_loops = (allowed_edge_types & IGRAPH_I_MULTI_LOOPS_SW); + if (*multiple != multi_loops) { + IGRAPH_ERROR("Either both multi-edges and multi-loops should be allowed or neither.", + IGRAPH_EINVAL); + } + } + + return IGRAPH_SUCCESS; +} + + static igraph_error_t igraph_i_is_graphical_undirected_multi_loops(const igraph_vector_int_t *degrees, igraph_bool_t *res); static igraph_error_t igraph_i_is_graphical_undirected_loopless_multi(const igraph_vector_int_t *degrees, igraph_bool_t *res); static igraph_error_t igraph_i_is_graphical_undirected_loopy_simple(const igraph_vector_int_t *degrees, igraph_bool_t *res); @@ -87,7 +107,8 @@ static igraph_error_t igraph_i_is_bigraphical_simple(const igraph_vector_int_t * * undirected graphs or the out-degree sequence for directed graphs. * \param in_degrees A vector of integers specifying the in-degree sequence for * directed graphs. For undirected graphs, it must be \c NULL. - * \param allowed_edge_types The types of edges to allow in the graph: + * \param allowed_edge_types The types of edges to allow in the graph. See + * \ref igraph_edge_type_sw_t for details. * \clist * \cli IGRAPH_SIMPLE_SW * simple graphs (i.e. no self-loops or multi-edges allowed). @@ -236,12 +257,12 @@ igraph_error_t igraph_is_bigraphical(const igraph_vector_int_t *degrees1, * These conditions are valid regardless of whether multi-edges are allowed between distinct vertices. */ static igraph_error_t igraph_i_is_graphical_undirected_multi_loops(const igraph_vector_int_t *degrees, igraph_bool_t *res) { - igraph_integer_t sum_parity = 0; /* 0 if the degree sum is even, 1 if it is odd */ - igraph_integer_t n = igraph_vector_int_size(degrees); - igraph_integer_t i; + igraph_int_t sum_parity = 0; /* 0 if the degree sum is even, 1 if it is odd */ + igraph_int_t n = igraph_vector_int_size(degrees); + igraph_int_t i; for (i = 0; i < n; ++i) { - igraph_integer_t d = VECTOR(*degrees)[i]; + igraph_int_t d = VECTOR(*degrees)[i]; if (d < 0) { *res = false; @@ -262,9 +283,9 @@ static igraph_error_t igraph_i_is_graphical_undirected_multi_loops(const igraph_ * - The sum of degrees must be no smaller than 2*d_max. */ static igraph_error_t igraph_i_is_graphical_undirected_loopless_multi(const igraph_vector_int_t *degrees, igraph_bool_t *res) { - igraph_integer_t i; - igraph_integer_t n = igraph_vector_int_size(degrees); - igraph_integer_t dsum, dmax; + igraph_int_t i; + igraph_int_t n = igraph_vector_int_size(degrees); + igraph_int_t dsum, dmax; /* Zero-length sequences are considered graphical. */ if (n == 0) { @@ -274,7 +295,7 @@ static igraph_error_t igraph_i_is_graphical_undirected_loopless_multi(const igra dsum = 0; dmax = 0; for (i = 0; i < n; ++i) { - igraph_integer_t d = VECTOR(*degrees)[i]; + igraph_int_t d = VECTOR(*degrees)[i]; if (d < 0) { *res = false; @@ -299,7 +320,7 @@ static igraph_error_t igraph_i_is_graphical_undirected_loopless_multi(const igra */ static igraph_error_t igraph_i_is_graphical_undirected_loopy_simple(const igraph_vector_int_t *degrees, igraph_bool_t *res) { igraph_vector_int_t num_degs; - igraph_integer_t w, b, s, c, n, k, wd, kd; + igraph_int_t w, b, s, c, n, k, wd, kd; n = igraph_vector_int_size(degrees); @@ -341,8 +362,8 @@ static igraph_error_t igraph_i_is_graphical_undirected_loopy_simple(const igraph IGRAPH_VECTOR_INT_INIT_FINALLY(&num_degs, n+2); - for (igraph_integer_t i = 0; i < n; ++i) { - igraph_integer_t degree = VECTOR(*degrees)[i]; + for (igraph_int_t i = 0; i < n; ++i) { + igraph_int_t degree = VECTOR(*degrees)[i]; /* Negative degrees are already checked in igraph_i_is_graphical_undirected_multi_loops() */ if (degree > n+1) { @@ -354,7 +375,7 @@ static igraph_error_t igraph_i_is_graphical_undirected_loopy_simple(const igraph } /* Convert num_degs to a cumulative sum array. */ - for (igraph_integer_t d = n; d >= 0; --d) { + for (igraph_int_t d = n; d >= 0; --d) { VECTOR(num_degs)[d] += VECTOR(num_degs)[d+1]; } @@ -400,12 +421,12 @@ static igraph_error_t igraph_i_is_graphical_undirected_loopy_simple(const igraph */ static igraph_error_t igraph_i_is_graphical_undirected_simple(const igraph_vector_int_t *degrees, igraph_bool_t *res) { igraph_vector_int_t num_degs; /* num_degs[d] is the # of vertices with degree d */ - const igraph_integer_t p = igraph_vector_int_size(degrees); - igraph_integer_t dmin, dmax, dsum; - igraph_integer_t n; /* number of non-zero degrees */ - igraph_integer_t k, sum_deg, sum_ni, sum_ini; - igraph_integer_t i, dk; - igraph_integer_t zverovich_bound; + const igraph_int_t p = igraph_vector_int_size(degrees); + igraph_int_t dmin, dmax, dsum; + igraph_int_t n; /* number of non-zero degrees */ + igraph_int_t k, sum_deg, sum_ni, sum_ini; + igraph_int_t i, dk; + igraph_int_t zverovich_bound; if (p == 0) { *res = true; @@ -426,7 +447,7 @@ static igraph_error_t igraph_i_is_graphical_undirected_simple(const igraph_vecto dmin = p; dmax = 0; dsum = 0; n = 0; for (i = 0; i < p; ++i) { - igraph_integer_t d = VECTOR(*degrees)[i]; + igraph_int_t d = VECTOR(*degrees)[i]; if (d < 0 || d >= p) { *res = false; @@ -482,7 +503,7 @@ static igraph_error_t igraph_i_is_graphical_undirected_simple(const igraph_vecto k = 0; sum_deg = 0; sum_ni = 0; sum_ini = 0; for (dk = dmax; dk >= dmin; --dk) { - igraph_integer_t run_size, v; + igraph_int_t run_size, v; if (dk < k+1) { *res = true; @@ -524,16 +545,16 @@ static igraph_error_t igraph_i_is_graphical_undirected_simple(const igraph_vecto * - The sum of in- and out-degrees must be the same. */ static igraph_error_t igraph_i_is_graphical_directed_loopy_multi(const igraph_vector_int_t *out_degrees, const igraph_vector_int_t *in_degrees, igraph_bool_t *res) { - igraph_integer_t sumdiff; /* difference between sum of in- and out-degrees */ - igraph_integer_t n = igraph_vector_int_size(out_degrees); - igraph_integer_t i; + igraph_int_t sumdiff; /* difference between sum of in- and out-degrees */ + igraph_int_t n = igraph_vector_int_size(out_degrees); + igraph_int_t i; IGRAPH_ASSERT(igraph_vector_int_size(in_degrees) == n); sumdiff = 0; for (i = 0; i < n; ++i) { - igraph_integer_t dout = VECTOR(*out_degrees)[i]; - igraph_integer_t din = VECTOR(*in_degrees)[i]; + igraph_int_t dout = VECTOR(*out_degrees)[i]; + igraph_int_t din = VECTOR(*in_degrees)[i]; if (dout < 0 || din < 0) { *res = false; @@ -556,17 +577,17 @@ static igraph_error_t igraph_i_is_graphical_directed_loopy_multi(const igraph_ve * where d_max is the largest total degree. */ static igraph_error_t igraph_i_is_graphical_directed_loopless_multi(const igraph_vector_int_t *out_degrees, const igraph_vector_int_t *in_degrees, igraph_bool_t *res) { - igraph_integer_t i, sumin, sumout, dmax; - igraph_integer_t n = igraph_vector_int_size(out_degrees); + igraph_int_t i, sumin, sumout, dmax; + igraph_int_t n = igraph_vector_int_size(out_degrees); IGRAPH_ASSERT(igraph_vector_int_size(in_degrees) == n); sumin = 0; sumout = 0; dmax = 0; for (i = 0; i < n; ++i) { - igraph_integer_t dout = VECTOR(*out_degrees)[i]; - igraph_integer_t din = VECTOR(*in_degrees)[i]; - igraph_integer_t d = dout + din; + igraph_int_t dout = VECTOR(*out_degrees)[i]; + igraph_int_t din = VECTOR(*in_degrees)[i]; + igraph_int_t d = dout + din; if (dout < 0 || din < 0) { *res = false; @@ -604,7 +625,7 @@ static igraph_error_t igraph_i_is_graphical_directed_simple(const igraph_vector_ igraph_vector_int_t in_degree_cumcounts, in_degree_counts; igraph_vector_int_t sorted_in_degrees, sorted_out_degrees; igraph_vector_int_t left_pq, right_pq; - igraph_integer_t lhs, rhs, left_pq_size, right_pq_size, left_i, right_i, left_sum, right_sum; + igraph_int_t lhs, rhs, left_pq_size, right_pq_size, left_i, right_i, left_sum, right_sum; /* The conditions from the loopy multigraph case are necessary here as well. */ IGRAPH_CHECK(igraph_i_is_graphical_directed_loopy_multi(out_degrees, in_degrees, res)); @@ -612,7 +633,7 @@ static igraph_error_t igraph_i_is_graphical_directed_simple(const igraph_vector_ return IGRAPH_SUCCESS; } - const igraph_integer_t vcount = igraph_vector_int_size(out_degrees); + const igraph_int_t vcount = igraph_vector_int_size(out_degrees); if (vcount == 0) { *res = true; return IGRAPH_SUCCESS; @@ -622,9 +643,9 @@ static igraph_error_t igraph_i_is_graphical_directed_simple(const igraph_vector_ IGRAPH_VECTOR_INT_INIT_FINALLY(&in_degree_cumcounts, vcount+1); /* Compute in_degree_cumcounts[d+1] to be the no. of in-degrees == d */ - for (igraph_integer_t v = 0; v < vcount; v++) { - igraph_integer_t indeg = VECTOR(*in_degrees)[v]; - igraph_integer_t outdeg = VECTOR(*out_degrees)[v]; + for (igraph_int_t v = 0; v < vcount; v++) { + igraph_int_t indeg = VECTOR(*in_degrees)[v]; + igraph_int_t outdeg = VECTOR(*out_degrees)[v]; if (indeg >= vcount || outdeg >= vcount) { *res = false; igraph_vector_int_destroy(&in_degree_cumcounts); @@ -635,7 +656,7 @@ static igraph_error_t igraph_i_is_graphical_directed_simple(const igraph_vector_ } /* Compute in_degree_cumcounts[d] to be the no. of in-degrees < d */ - for (igraph_integer_t indeg = 0; indeg < vcount; indeg++) { + for (igraph_int_t indeg = 0; indeg < vcount; indeg++) { VECTOR(in_degree_cumcounts)[indeg+1] += VECTOR(in_degree_cumcounts)[indeg]; } @@ -646,10 +667,10 @@ static igraph_error_t igraph_i_is_graphical_directed_simple(const igraph_vector_ * with in-degree d that were already placed. */ IGRAPH_VECTOR_INT_INIT_FINALLY(&in_degree_counts, vcount); - for (igraph_integer_t v = 0; v < vcount; v++) { - igraph_integer_t outdeg = VECTOR(*out_degrees)[v]; - igraph_integer_t indeg = VECTOR(*in_degrees)[v]; - igraph_integer_t idx = VECTOR(in_degree_cumcounts)[indeg] + VECTOR(in_degree_counts)[indeg]; + for (igraph_int_t v = 0; v < vcount; v++) { + igraph_int_t outdeg = VECTOR(*out_degrees)[v]; + igraph_int_t indeg = VECTOR(*in_degrees)[v]; + igraph_int_t idx = VECTOR(in_degree_cumcounts)[indeg] + VECTOR(in_degree_counts)[indeg]; VECTOR(sorted_out_degrees)[vcount - idx - 1] = outdeg; VECTOR(sorted_in_degrees)[vcount - idx - 1] = indeg; VECTOR(in_degree_counts)[indeg]++; @@ -680,14 +701,14 @@ static igraph_error_t igraph_i_is_graphical_directed_simple(const igraph_vector_ right_i = 0; left_sum = 0; right_sum = 0; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { VECTOR(right_pq)[OUTDEGREE(i)]++; } *res = true; lhs = 0; rhs = 0; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { lhs += INDEGREE(i); /* It is enough to check for indexes where the in-degree is about to @@ -755,13 +776,13 @@ static igraph_error_t igraph_i_is_graphical_directed_simple(const igraph_vector_ * - Sum of degrees must be the same in the two partitions. */ static igraph_error_t igraph_i_is_bigraphical_multi(const igraph_vector_int_t *degrees1, const igraph_vector_int_t *degrees2, igraph_bool_t *res) { - igraph_integer_t i; - igraph_integer_t sum1, sum2; - igraph_integer_t n1 = igraph_vector_int_size(degrees1), n2 = igraph_vector_int_size(degrees2); + igraph_int_t i; + igraph_int_t sum1, sum2; + igraph_int_t n1 = igraph_vector_int_size(degrees1), n2 = igraph_vector_int_size(degrees2); sum1 = 0; for (i = 0; i < n1; ++i) { - igraph_integer_t d = VECTOR(*degrees1)[i]; + igraph_int_t d = VECTOR(*degrees1)[i]; if (d < 0) { *res = false; @@ -773,7 +794,7 @@ static igraph_error_t igraph_i_is_bigraphical_multi(const igraph_vector_int_t *d sum2 = 0; for (i = 0; i < n2; ++i) { - igraph_integer_t d = VECTOR(*degrees2)[i]; + igraph_int_t d = VECTOR(*degrees2)[i]; if (d < 0) { *res = false; @@ -795,10 +816,10 @@ static igraph_error_t igraph_i_is_bigraphical_multi(const igraph_vector_int_t *d * - Use the Gale-Ryser theorem. */ static igraph_error_t igraph_i_is_bigraphical_simple(const igraph_vector_int_t *degrees1, const igraph_vector_int_t *degrees2, igraph_bool_t *res) { - igraph_integer_t n1 = igraph_vector_int_size(degrees1), n2 = igraph_vector_int_size(degrees2); + igraph_int_t n1 = igraph_vector_int_size(degrees1), n2 = igraph_vector_int_size(degrees2); igraph_vector_int_t deg_freq1, deg_freq2; - igraph_integer_t lhs_sum, partial_rhs_sum, partial_rhs_count; - igraph_integer_t a, b, k; + igraph_int_t lhs_sum, partial_rhs_sum, partial_rhs_count; + igraph_int_t a, b, k; if (n1 == 0 && n2 == 0) { *res = true; @@ -814,7 +835,7 @@ static igraph_error_t igraph_i_is_bigraphical_simple(const igraph_vector_int_t * /* Ensure that degrees1 is the shorter vector as a minor optimization: */ if (n2 < n1) { const igraph_vector_int_t *tmp; - igraph_integer_t n; + igraph_int_t n; tmp = degrees1; degrees1 = degrees2; @@ -830,16 +851,16 @@ static igraph_error_t igraph_i_is_bigraphical_simple(const igraph_vector_int_t * IGRAPH_VECTOR_INT_INIT_FINALLY(°_freq1, n2+1); IGRAPH_VECTOR_INT_INIT_FINALLY(°_freq2, n1+1); - for (igraph_integer_t i = 0; i < n1; ++i) { - igraph_integer_t degree = VECTOR(*degrees1)[i]; + for (igraph_int_t i = 0; i < n1; ++i) { + igraph_int_t degree = VECTOR(*degrees1)[i]; if (degree > n2) { *res = false; goto bigraphical_simple_done; } ++VECTOR(deg_freq1)[degree]; } - for (igraph_integer_t i = 0; i < n2; ++i) { - igraph_integer_t degree = VECTOR(*degrees2)[i]; + for (igraph_int_t i = 0; i < n2; ++i) { + igraph_int_t degree = VECTOR(*degrees2)[i]; if (degree > n1) { *res = false; goto bigraphical_simple_done; @@ -879,12 +900,12 @@ static igraph_error_t igraph_i_is_bigraphical_simple(const igraph_vector_int_t * b = 0; /* index in deg_freq2 */ k = -1; for (a = n2; a >= 0; --a) { - igraph_integer_t acount = VECTOR(deg_freq1)[a]; + igraph_int_t acount = VECTOR(deg_freq1)[a]; lhs_sum += a * acount; k += acount; while (b <= k + 1) { - igraph_integer_t bcount = VECTOR(deg_freq2)[b]; + igraph_int_t bcount = VECTOR(deg_freq2)[b]; partial_rhs_sum += b * bcount; partial_rhs_count += bcount; diff --git a/src/vendor/cigraph/src/misc/graphicality.h b/src/vendor/cigraph/src/misc/graphicality.h index c200e32c8a4..eedb6d52bf0 100644 --- a/src/vendor/cigraph/src/misc/graphicality.h +++ b/src/vendor/cigraph/src/misc/graphicality.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -19,9 +19,18 @@ #ifndef IGRAPH_MISC_GRAPHICALITY_H #define IGRAPH_MISC_GRAPHICALITY_H +#include "igraph_decls.h" #include "igraph_graphicality.h" #define IGRAPH_I_MULTI_EDGES_SW 0x02 /* 010, more than one edge allowed between distinct vertices */ #define IGRAPH_I_MULTI_LOOPS_SW 0x04 /* 100, more than one self-loop allowed on the same vertex */ +IGRAPH_BEGIN_C_DECLS + +igraph_error_t igraph_i_edge_type_to_loops_multiple( + igraph_edge_type_sw_t allowed_edge_type, + igraph_bool_t *loops, igraph_bool_t *multiple); + +IGRAPH_END_C_DECLS + #endif /* IGRAPH_MISC_GRAPHICALITY_H */ diff --git a/src/vendor/cigraph/src/misc/matching.c b/src/vendor/cigraph/src/misc/matching.c index bab4f61f906..6b8e1794bd7 100644 --- a/src/vendor/cigraph/src/misc/matching.c +++ b/src/vendor/cigraph/src/misc/matching.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2012 Tamas Nepusz This program is free software; you can redistribute it and/or modify @@ -71,7 +71,7 @@ igraph_error_t igraph_is_matching(const igraph_t *graph, const igraph_vector_bool_t *types, const igraph_vector_int_t *matching, igraph_bool_t *result) { - igraph_integer_t i, j, no_of_nodes = igraph_vcount(graph); + igraph_int_t i, j, no_of_nodes = igraph_vcount(graph); igraph_bool_t conn; /* Checking match vector length */ @@ -155,7 +155,7 @@ igraph_error_t igraph_is_maximal_matching(const igraph_t *graph, const igraph_vector_bool_t *types, const igraph_vector_int_t *matching, igraph_bool_t *result) { - igraph_integer_t i, j, n, no_of_nodes = igraph_vcount(graph); + igraph_int_t i, j, n, no_of_nodes = igraph_vcount(graph); igraph_vector_int_t neis; igraph_bool_t valid; @@ -196,12 +196,12 @@ igraph_error_t igraph_is_maximal_matching(const igraph_t *graph, static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted( const igraph_t *graph, - const igraph_vector_bool_t *types, igraph_integer_t *matching_size, + const igraph_vector_bool_t *types, igraph_int_t *matching_size, igraph_vector_int_t *matching); static igraph_error_t igraph_i_maximum_bipartite_matching_weighted( const igraph_t *graph, - const igraph_vector_bool_t *types, igraph_integer_t *matching_size, + const igraph_vector_bool_t *types, igraph_int_t *matching_size, igraph_real_t *matching_weight, igraph_vector_int_t *matching, const igraph_vector_t *weights, igraph_real_t eps); @@ -270,7 +270,7 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_weighted( * \example examples/simple/igraph_maximum_bipartite_matching.c */ igraph_error_t igraph_maximum_bipartite_matching(const igraph_t *graph, - const igraph_vector_bool_t *types, igraph_integer_t *matching_size, + const igraph_vector_bool_t *types, igraph_int_t *matching_size, igraph_real_t *matching_weight, igraph_vector_int_t *matching, const igraph_vector_t *weights, igraph_real_t eps) { @@ -316,17 +316,17 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted_relabel( */ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted( const igraph_t *graph, - const igraph_vector_bool_t *types, igraph_integer_t *matching_size, + const igraph_vector_bool_t *types, igraph_int_t *matching_size, igraph_vector_int_t *matching) { - igraph_integer_t i, j, k, n, no_of_nodes = igraph_vcount(graph); - igraph_integer_t num_matched; /* number of matched vertex pairs */ + igraph_int_t i, j, k, n, no_of_nodes = igraph_vcount(graph); + igraph_int_t num_matched; /* number of matched vertex pairs */ igraph_vector_int_t match; /* will store the matching */ igraph_vector_int_t labels; /* will store the labels */ igraph_vector_int_t neis; /* used to retrieve the neighbors of a node */ igraph_dqueue_int_t q; /* a FIFO for push ordering */ igraph_bool_t smaller_set; /* denotes which part of the bipartite graph is smaller */ - igraph_integer_t label_changed = 0; /* Counter to decide when to run a global relabeling */ - igraph_integer_t relabeling_freq = no_of_nodes / 2; + igraph_int_t label_changed = 0; /* Counter to decide when to run a global relabeling */ + igraph_int_t relabeling_freq = no_of_nodes / 2; /* We will use: * - FIFO push ordering @@ -389,9 +389,9 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted( /* (6) Main loop from the referenced tech report -- lines 4--13 */ label_changed = 0; while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t v = igraph_dqueue_int_pop(&q); /* Line 13 */ - igraph_integer_t u = -1, label_u = 2 * no_of_nodes; - igraph_integer_t w; + igraph_int_t v = igraph_dqueue_int_pop(&q); /* Line 13 */ + igraph_int_t u = -1, label_u = 2 * no_of_nodes; + igraph_int_t w; if (label_changed >= relabeling_freq) { /* Run global relabeling */ @@ -458,7 +458,7 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted_relabel( const igraph_t *graph, const igraph_vector_bool_t *types, igraph_vector_int_t *labels, igraph_vector_int_t *match, igraph_bool_t smaller_set) { - igraph_integer_t i, j, n, no_of_nodes = igraph_vcount(graph), matched_to; + igraph_int_t i, j, n, no_of_nodes = igraph_vcount(graph), matched_to; igraph_dqueue_int_t q; igraph_vector_int_t neis; @@ -483,8 +483,8 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted_relabel( /* Run the BFS */ while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t v = igraph_dqueue_int_pop(&q); - igraph_integer_t w; + igraph_int_t v = igraph_dqueue_int_pop(&q); + igraph_int_t w; IGRAPH_CHECK(igraph_neighbors( graph, &neis, v, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE @@ -527,11 +527,11 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_unweighted_relabel( */ static igraph_error_t igraph_i_maximum_bipartite_matching_weighted( const igraph_t *graph, - const igraph_vector_bool_t *types, igraph_integer_t *matching_size, + const igraph_vector_bool_t *types, igraph_int_t *matching_size, igraph_real_t *matching_weight, igraph_vector_int_t *matching, const igraph_vector_t *weights, igraph_real_t eps) { - igraph_integer_t i, j, k, n, no_of_nodes, no_of_edges; - igraph_integer_t u, v, w, msize; + igraph_int_t i, j, k, n, no_of_nodes, no_of_edges; + igraph_int_t u, v, w, msize; igraph_t newgraph; igraph_vector_int_t match; /* will store the matching */ igraph_vector_t slack; /* will store the slack on each edge */ @@ -542,12 +542,12 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_weighted( igraph_bool_t smaller_set_type; /* denotes which part of the bipartite graph is smaller */ igraph_vector_t smaller_set; /* stores the vertex IDs of the smaller set */ igraph_vector_t larger_set; /* stores the vertex IDs of the larger set */ - igraph_integer_t smaller_set_size; /* size of the smaller set */ - igraph_integer_t larger_set_size; /* size of the larger set */ + igraph_int_t smaller_set_size; /* size of the smaller set */ + igraph_int_t larger_set_size; /* size of the larger set */ igraph_real_t dual; /* solution of the dual problem */ IGRAPH_UNUSED(dual); /* We mark it as unused to prevent warnings about unused-but-set-variables. */ igraph_adjlist_t tight_phantom_edges; /* adjacency list to manage tight phantom edges */ - igraph_integer_t alternating_path_endpoint; + igraph_int_t alternating_path_endpoint; igraph_vector_int_t* neis; igraph_vector_int_t *neis2; igraph_inclist_t inclist; /* incidence list of the original graph */ @@ -659,7 +659,7 @@ static igraph_error_t igraph_i_maximum_bipartite_matching_weighted( /* (5) Main loop until the matching becomes maximal */ while (msize < smaller_set_size) { igraph_real_t min_slack, min_slack_2; - igraph_integer_t min_slack_u, min_slack_v; + igraph_int_t min_slack_u, min_slack_v; /* mark min_slack_u as unused; it is actually used when debugging, but * gcc complains when we are not debugging */ diff --git a/src/vendor/cigraph/src/misc/mixing.c b/src/vendor/cigraph/src/misc/mixing.c index 445e3fe2097..dffc7635988 100644 --- a/src/vendor/cigraph/src/misc/mixing.c +++ b/src/vendor/cigraph/src/misc/mixing.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2009-2023 The igraph development team + igraph library. + Copyright (C) 2009-2025 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 @@ -72,6 +72,8 @@ * https://doi.org/10.1093/acprof%3Aoso/9780199206650.001.0001. * * \param graph The input graph, it can be directed or undirected. + * \param weights Weighted nominal assortativity is not currently implemented. + * Pass \c NULL to ignore. * \param types Integer vector giving the vertex categories. The types * are represented by integers starting at zero. * \param res Pointer to a real variable, the result is stored here. @@ -94,19 +96,24 @@ * \example examples/simple/igraph_assortativity_nominal.c */ -igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, - const igraph_vector_int_t *types, - igraph_real_t *res, - igraph_bool_t directed, - igraph_bool_t normalized) { +igraph_error_t igraph_assortativity_nominal( + const igraph_t *graph, const igraph_vector_t *weights, + const igraph_vector_int_t *types, + igraph_real_t *res, + igraph_bool_t directed, igraph_bool_t normalized) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_real_t no_of_edges_real = no_of_edges; /* for divisions */ - igraph_integer_t no_of_types; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_real_t no_of_edges_real = (igraph_real_t) no_of_edges; /* for divisions */ + igraph_int_t no_of_types; igraph_vector_int_t ai, bi, eii; igraph_real_t sumaibi = 0.0, sumeii = 0.0; + if (weights) { + IGRAPH_ERROR("Weighted nominal assortativity is not yet implemented.", + IGRAPH_UNIMPLEMENTED); + } + if (igraph_vector_int_size(types) != no_of_nodes) { IGRAPH_ERROR("Invalid types vector length.", IGRAPH_EINVAL); } @@ -128,11 +135,11 @@ igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&bi, no_of_types); IGRAPH_VECTOR_INT_INIT_FINALLY(&eii, no_of_types); - for (igraph_integer_t e = 0; e < no_of_edges; e++) { - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); - igraph_integer_t from_type = VECTOR(*types)[from]; - igraph_integer_t to_type = VECTOR(*types)[to]; + for (igraph_int_t e = 0; e < no_of_edges; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); + igraph_int_t from_type = VECTOR(*types)[from]; + igraph_int_t to_type = VECTOR(*types)[to]; VECTOR(ai)[from_type] += 1; VECTOR(bi)[to_type] += 1; @@ -148,7 +155,7 @@ igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, } } - for (igraph_integer_t i = 0; i < no_of_types; i++) { + for (igraph_int_t i = 0; i < no_of_types; i++) { sumaibi += (VECTOR(ai)[i] / no_of_edges_real) * (VECTOR(bi)[i] / no_of_edges_real); sumeii += (VECTOR(eii)[i] / no_of_edges_real); } @@ -207,6 +214,12 @@ igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, * undirected graphs. * * + * When edge weights are given, they are effectively treated as edge multiplicities. + * The above formulas are valid for weighted graph as well when \c m is interpreted + * as the total edge weight (instead of the edge count) and \c k as vertex strengths + * (instead of degrees). + * + * * References: * * @@ -230,6 +243,8 @@ igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, * https://doi.org/10.1093/acprof%3Aoso/9780199206650.001.0001. * * \param graph The input graph, it can be directed or undirected. + * \param weights The edge weights. Pass \c NULL to compute unweighed + * assortativity, which in effect assumes all weights to be 1. * \param values The vertex values, these can be arbitrary numeric * values. * \param values_in A second value vector to be used for the incoming @@ -255,18 +270,24 @@ igraph_error_t igraph_assortativity_nominal(const igraph_t *graph, * based on vertex degrees. */ -igraph_error_t igraph_assortativity(const igraph_t *graph, - const igraph_vector_t *values, - const igraph_vector_t *values_in, - igraph_real_t *res, - igraph_bool_t directed, - igraph_bool_t normalized) { +igraph_error_t igraph_assortativity( + const igraph_t *graph, const igraph_vector_t *weights, + const igraph_vector_t *values, const igraph_vector_t *values_in, + igraph_real_t *res, + igraph_bool_t directed, igraph_bool_t normalized) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_real_t total_weight; directed = directed && igraph_is_directed(graph); + if (weights && igraph_vector_size(weights) != no_of_edges) { + IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, + igraph_vector_size(weights), no_of_edges); + } + if (!directed && values_in) { IGRAPH_WARNING( "Incoming vertex values are ignored when calculating undirected assortativity."); @@ -280,27 +301,45 @@ igraph_error_t igraph_assortativity(const igraph_t *graph, IGRAPH_ERROR("Invalid incoming vertex values vector length.", IGRAPH_EINVAL); } + total_weight = weights ? igraph_vector_sum(weights) : no_of_edges; + if (!directed) { igraph_real_t num1 = 0.0, num2 = 0.0, den1 = 0.0; - for (igraph_integer_t e = 0; e < no_of_edges; e++) { - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); - igraph_real_t from_value = VECTOR(*values)[from]; - igraph_real_t to_value = VECTOR(*values)[to]; - - num1 += from_value * to_value; - num2 += from_value + to_value; - if (normalized) { - den1 += from_value * from_value + to_value * to_value; + if (weights) { + for (igraph_int_t e = 0; e < no_of_edges; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); + igraph_real_t from_value = VECTOR(*values)[from]; + igraph_real_t to_value = VECTOR(*values)[to]; + igraph_real_t w = VECTOR(*weights)[e]; + + num1 += w * from_value * to_value; + num2 += w * (from_value + to_value); + if (normalized) { + den1 += w * (from_value * from_value + to_value * to_value); + } + } + } else { + for (igraph_int_t e = 0; e < no_of_edges; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); + igraph_real_t from_value = VECTOR(*values)[from]; + igraph_real_t to_value = VECTOR(*values)[to]; + + num1 += from_value * to_value; + num2 += from_value + to_value; + if (normalized) { + den1 += from_value * from_value + to_value * to_value; + } } } - num1 /= no_of_edges; + num1 /= total_weight; if (normalized) { - den1 /= no_of_edges * 2.0; + den1 /= total_weight * 2.0; } - num2 /= no_of_edges * 2.0; + num2 /= total_weight * 2.0; num2 = num2 * num2; if (normalized) { @@ -318,29 +357,47 @@ igraph_error_t igraph_assortativity(const igraph_t *graph, values_in = values; } - for (igraph_integer_t e = 0; e < no_of_edges; e++) { - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); - igraph_real_t from_value = VECTOR(*values)[from]; - igraph_real_t to_value = VECTOR(*values_in)[to]; - - num1 += from_value * to_value; - num2 += from_value; - num3 += to_value; - if (normalized) { - den1 += from_value * from_value; - den2 += to_value * to_value; + if (weights) { + for (igraph_int_t e = 0; e < no_of_edges; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); + igraph_real_t from_value = VECTOR(*values)[from]; + igraph_real_t to_value = VECTOR(*values_in)[to]; + igraph_real_t w = VECTOR(*weights)[e]; + + num1 += w * from_value * to_value; + num2 += w * from_value; + num3 += w * to_value; + if (normalized) { + den1 += w * (from_value * from_value); + den2 += w * (to_value * to_value); + } + } + } else { + for (igraph_int_t e = 0; e < no_of_edges; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); + igraph_real_t from_value = VECTOR(*values)[from]; + igraph_real_t to_value = VECTOR(*values_in)[to]; + + num1 += from_value * to_value; + num2 += from_value; + num3 += to_value; + if (normalized) { + den1 += from_value * from_value; + den2 += to_value * to_value; + } } } - num = num1 - num2 * num3 / no_of_edges; + num = num1 - num2 * num3 / total_weight; if (normalized) { - den = sqrt(den1 - num2 * num2 / no_of_edges) * - sqrt(den2 - num3 * num3 / no_of_edges); + den = sqrt(den1 - num2 * num2 / total_weight) * + sqrt(den2 - num3 * num3 / total_weight); *res = num / den; } else { - *res = num / no_of_edges; + *res = num / total_weight; } } @@ -388,7 +445,7 @@ igraph_error_t igraph_assortativity_degree(const igraph_t *graph, igraph_bool_t directed) { directed = directed && igraph_is_directed(graph); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); /* This function uses igraph_strength() instead of igraph_degree() in order to obtain * a vector of reals instead of a vector of integers. */ @@ -398,7 +455,7 @@ igraph_error_t igraph_assortativity_degree(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&outdegree, no_of_nodes); IGRAPH_CHECK(igraph_strength(graph, &indegree, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS, NULL)); IGRAPH_CHECK(igraph_strength(graph, &outdegree, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, NULL)); - IGRAPH_CHECK(igraph_assortativity(graph, &outdegree, &indegree, res, /* directed */ true, /* normalized */ true)); + IGRAPH_CHECK(igraph_assortativity(graph, NULL, &outdegree, &indegree, res, /* directed */ true, /* normalized */ true)); igraph_vector_destroy(&indegree); igraph_vector_destroy(&outdegree); IGRAPH_FINALLY_CLEAN(2); @@ -406,7 +463,7 @@ igraph_error_t igraph_assortativity_degree(const igraph_t *graph, igraph_vector_t degree; IGRAPH_VECTOR_INIT_FINALLY(°ree, no_of_nodes); IGRAPH_CHECK(igraph_strength(graph, °ree, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, NULL)); - IGRAPH_CHECK(igraph_assortativity(graph, °ree, 0, res, /* directed */ false, /* normalized */ true)); + IGRAPH_CHECK(igraph_assortativity(graph, NULL, °ree, 0, res, /* directed */ false, /* normalized */ true)); igraph_vector_destroy(°ree); IGRAPH_FINALLY_CLEAN(1); } @@ -455,11 +512,11 @@ igraph_error_t igraph_assortativity_degree(const igraph_t *graph, * \param jdm A pointer to an initialized matrix that will be resized. The values * will be written here. * \param max_out_degree Number of rows in the result, i.e. the largest (out-)degree - * to consider. If negative, the largest (out-)degree of the graph will - * be used. + * to consider. If negative or \ref IGRAPH_UNLIMITED, the largest (out-)degree + * of the graph will be used. * \param max_in_degree Number of columns in the result, i.e. the largest (in-)degree - * to consider. If negative, the largest (in-)degree of the graph will - * be used. + * to consider. If negative or \ref IGRAPH_UNLIMITED, the largest (in-)degree + * of the graph will be used. * \return Error code. * * \sa \ref igraph_joint_degree_distribution() to count ordered vertex pairs instead of @@ -471,16 +528,16 @@ igraph_error_t igraph_assortativity_degree(const igraph_t *graph, igraph_error_t igraph_joint_degree_matrix( const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *jdm, - igraph_integer_t max_out_degree, igraph_integer_t max_in_degree) { + igraph_int_t max_out_degree, igraph_int_t max_in_degree) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_eit_t eit; - igraph_integer_t eid; - igraph_integer_t v1id; - igraph_integer_t v2id; - igraph_integer_t v1deg; - igraph_integer_t v2deg; + igraph_int_t eid; + igraph_int_t v1id; + igraph_int_t v2id; + igraph_int_t v1deg; + igraph_int_t v2deg; if (weights && igraph_vector_size(weights) != no_of_edges) { IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", @@ -529,7 +586,7 @@ igraph_error_t igraph_joint_degree_matrix( } else { igraph_vector_int_t degrees; - igraph_integer_t maxdeg; + igraph_int_t maxdeg; IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); @@ -594,12 +651,12 @@ static igraph_error_t mixing_matrix( igraph_matrix_t *p, const igraph_vector_int_t *from_types, const igraph_vector_int_t *to_types, igraph_bool_t directed_neighbors, igraph_bool_t normalized, - igraph_integer_t max_from_type, igraph_integer_t max_to_type, + igraph_int_t max_from_type, igraph_int_t max_to_type, igraph_bool_t check_types) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t nrow, ncol; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t nrow, ncol; igraph_real_t sum; igraph_bool_t negative_weight; @@ -642,7 +699,7 @@ static igraph_error_t mixing_matrix( } if (check_types && no_of_nodes > 0) { - igraph_integer_t min; + igraph_int_t min; min = igraph_vector_int_min(from_types); if (min < 0) { @@ -662,11 +719,11 @@ static igraph_error_t mixing_matrix( sum = 0; negative_weight = false; - for (igraph_integer_t eid=0; eid < no_of_edges; eid++) { - igraph_integer_t from = IGRAPH_FROM(graph, eid); - igraph_integer_t to = IGRAPH_TO(graph, eid); - igraph_integer_t from_type = VECTOR(*from_types)[from]; - igraph_integer_t to_type = VECTOR(*to_types)[to]; + for (igraph_int_t eid=0; eid < no_of_edges; eid++) { + igraph_int_t from = IGRAPH_FROM(graph, eid); + igraph_int_t to = IGRAPH_TO(graph, eid); + igraph_int_t from_type = VECTOR(*from_types)[from]; + igraph_int_t to_type = VECTOR(*to_types)[to]; igraph_real_t w = weights ? VECTOR(*weights)[eid] : 1; if (from_type >= nrow || to_type >= ncol) { @@ -777,12 +834,12 @@ static igraph_error_t mixing_matrix( * \param normalized Whether to normalize the matrix so that entries sum to 1.0. * If false, matrix entries will be connection counts. Normalization is not * meaningful if some edge weights are negative. - * \param max_from_degree The largest source vertex degree to consider. If negative, - * the largest source degree will be used. The row count of the result matrix - * is one larger than this value. - * \param max_to_degree The largest target vertex degree to consider. If negative, - * the largest target degree will be used. The column count of the result matrix - * is one larger than this value. + * \param max_from_degree The largest source vertex degree to consider. If + * negative or \ref IGRAPH_UNLIMITED, the largest source degree will be used. + * The row count of the result matrix is one larger than this value. + * \param max_to_degree The largest target vertex degree to consider. If + * negative or \ref IGRAPH_UNLIMITED, the largest target degree will be used. + * The column count of the result matrix is one larger than this value. * \return Error code. * * \sa \ref igraph_joint_degree_matrix() for computing the joint degree matrix; @@ -798,9 +855,9 @@ igraph_error_t igraph_joint_degree_distribution( igraph_neimode_t from_mode, igraph_neimode_t to_mode, igraph_bool_t directed_neighbors, igraph_bool_t normalized, - igraph_integer_t max_from_degree, igraph_integer_t max_to_degree) { + igraph_int_t max_from_degree, igraph_int_t max_to_degree) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t *deg_from, *deg_to, deg_out, deg_in, deg_all; /* Make sure directionality parameters are consistent for undirected graphs. */ diff --git a/src/vendor/cigraph/src/misc/motifs.c b/src/vendor/cigraph/src/misc/motifs.c index fb174c8e62b..d12e16c8bb3 100644 --- a/src/vendor/cigraph/src/misc/motifs.c +++ b/src/vendor/cigraph/src/misc/motifs.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -39,7 +39,9 @@ */ static igraph_error_t igraph_i_motifs_randesu_update_hist( const igraph_t *graph, - igraph_vector_int_t *vids, igraph_integer_t isoclass, void* extra) { + const igraph_vector_int_t *vids, + igraph_int_t isoclass, void* extra) { + igraph_vector_t *hist = (igraph_vector_t*)extra; IGRAPH_UNUSED(graph); IGRAPH_UNUSED(vids); VECTOR(*hist)[isoclass]++; @@ -114,9 +116,9 @@ static igraph_error_t igraph_i_motifs_randesu_update_hist( * \example examples/simple/igraph_motifs_randesu.c */ igraph_error_t igraph_motifs_randesu(const igraph_t *graph, igraph_vector_t *hist, - igraph_integer_t size, const igraph_vector_t *cut_prob) { + igraph_int_t size, const igraph_vector_t *cut_prob) { igraph_bool_t directed = igraph_is_directed(graph); - igraph_integer_t histlen; + igraph_int_t histlen; if (directed) { switch (size) { @@ -236,22 +238,23 @@ igraph_error_t igraph_motifs_randesu(const igraph_t *graph, igraph_vector_t *his * \example examples/simple/igraph_motifs_randesu.c */ -igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_integer_t size, - const igraph_vector_t *cut_prob, igraph_motifs_handler_t *callback, - void* extra) { +igraph_error_t igraph_motifs_randesu_callback( + const igraph_t *graph, + igraph_int_t size, const igraph_vector_t *cut_prob, + igraph_motifs_handler_t *callback, void* extra) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_adjlist_t allneis, alloutneis; igraph_vector_int_t *neis; - igraph_integer_t father; - igraph_integer_t i, j, s; - igraph_integer_t motifs = 0; + igraph_int_t parent; + igraph_int_t i, j, s; + igraph_int_t motifs = 0; IGRAPH_UNUSED(motifs); /* We mark it as unused to prevent warnings about unused-but-set-variables. */ igraph_vector_int_t vids; /* this is G */ igraph_vector_int_t adjverts; /* this is V_E */ igraph_stack_int_t stack; /* this is S */ - igraph_integer_t *added; + igraph_int_t *added; char *subg; const unsigned int *arr_idx, *arr_code; @@ -309,7 +312,7 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte IGRAPH_EINVAL, igraph_vector_size(cut_prob), size); } - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Insufficient memory to find motifs."); IGRAPH_FINALLY(igraph_free, added); @@ -327,8 +330,8 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte IGRAPH_CHECK(igraph_stack_int_init(&stack, 0)); IGRAPH_FINALLY(igraph_stack_int_destroy, &stack); - for (father = 0; father < no_of_nodes; father++) { - igraph_integer_t level; + for (parent = 0; parent < no_of_nodes; parent++) { + igraph_int_t level; IGRAPH_ALLOW_INTERRUPTION(); @@ -340,18 +343,18 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte /* init G */ igraph_vector_int_clear(&vids); level = 0; - IGRAPH_CHECK(igraph_vector_int_push_back(&vids, father)); - subg[father] = 1; added[father] += 1; level += 1; + IGRAPH_CHECK(igraph_vector_int_push_back(&vids, parent)); + subg[parent] = 1; added[parent] += 1; level += 1; /* init V_E */ igraph_vector_int_clear(&adjverts); - neis = igraph_adjlist_get(&allneis, father); + neis = igraph_adjlist_get(&allneis, parent); s = igraph_vector_int_size(neis); for (i = 0; i < s; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; - if (!added[nei] && nei > father) { + igraph_int_t nei = VECTOR(*neis)[i]; + if (!added[nei] && nei > parent) { IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); - IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, father)); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, parent)); } added[nei] += 1; } @@ -365,8 +368,8 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte if (level == size - 1) { s = igraph_vector_int_size(&adjverts) / 2; for (i = 0; i < s; i++) { - igraph_integer_t k, s2; - igraph_integer_t last; + igraph_int_t k, s2; + igraph_int_t last; igraph_error_t ret; if (cp != 0 && RNG_UNIF01() < cp) { @@ -380,11 +383,11 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte code = 0; idx = 0; for (k = 0; k < size; k++) { - igraph_integer_t from = VECTOR(vids)[k]; + igraph_int_t from = VECTOR(vids)[k]; neis = igraph_adjlist_get(&alloutneis, from); s2 = igraph_vector_int_size(neis); for (j = 0; j < s2; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; if (subg[nei] && k != subg[nei] - 1) { idx = (unsigned char) (mul * k + (subg[nei] - 1)); code |= arr_idx[idx]; @@ -416,23 +419,23 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte if (level < size - 1 && !igraph_vector_int_empty(&adjverts)) { /* we might step down */ - igraph_integer_t neifather = igraph_vector_int_pop_back(&adjverts); - igraph_integer_t nei = igraph_vector_int_pop_back(&adjverts); + igraph_int_t neiparent = igraph_vector_int_pop_back(&adjverts); + igraph_int_t nei = igraph_vector_int_pop_back(&adjverts); if (cp == 0 || RNG_UNIF01() > cp) { /* yes, step down */ IGRAPH_CHECK(igraph_vector_int_push_back(&vids, nei)); subg[nei] = (char) level + 1; added[nei] += 1; level += 1; - IGRAPH_CHECK(igraph_stack_int_push(&stack, neifather)); + IGRAPH_CHECK(igraph_stack_int_push(&stack, neiparent)); IGRAPH_CHECK(igraph_stack_int_push(&stack, nei)); IGRAPH_CHECK(igraph_stack_int_push(&stack, level)); neis = igraph_adjlist_get(&allneis, nei); s = igraph_vector_int_size(neis); for (i = 0; i < s; i++) { - igraph_integer_t nei2 = VECTOR(*neis)[i]; - if (!added[nei2] && nei2 > father) { + igraph_int_t nei2 = VECTOR(*neis)[i]; + if (!added[nei2] && nei2 > parent) { IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei2)); IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); } @@ -441,14 +444,14 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte } } else { /* no, step back */ - igraph_integer_t nei, neifather; + igraph_int_t nei, neiparent; while (!igraph_stack_int_empty(&stack) && level == igraph_stack_int_top(&stack) - 1) { igraph_stack_int_pop(&stack); nei = igraph_stack_int_pop(&stack); - neifather = igraph_stack_int_pop(&stack); - igraph_vector_int_push_back(&adjverts, nei); - igraph_vector_int_push_back(&adjverts, neifather); + neiparent = igraph_stack_int_pop(&stack); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, neiparent)); } nei = igraph_vector_int_pop_back(&vids); @@ -473,15 +476,15 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte } /* clear the added vector */ - added[father] -= 1; - subg[father] = 0; - neis = igraph_adjlist_get(&allneis, father); + added[parent] -= 1; + subg[parent] = 0; + neis = igraph_adjlist_get(&allneis, parent); s = igraph_vector_int_size(neis); for (i = 0; i < s; i++) { added[ VECTOR(*neis)[i] ] -= 1; } - } /* for father */ + } /* for parent */ IGRAPH_FREE(added); IGRAPH_FREE(subg); @@ -543,20 +546,20 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte */ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real_t *est, - igraph_integer_t size, const igraph_vector_t *cut_prob, - igraph_integer_t sample_size, + igraph_int_t size, const igraph_vector_t *cut_prob, + igraph_int_t sample_size, const igraph_vector_int_t *parsample) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t neis; igraph_vector_int_t vids; /* this is G */ igraph_vector_int_t adjverts; /* this is V_E */ igraph_stack_int_t stack; /* this is S */ - igraph_integer_t *added; + igraph_int_t *added; igraph_vector_int_t *sample; - igraph_integer_t sam; - igraph_integer_t i; + igraph_int_t sam; + igraph_int_t i; if (size < 3) { IGRAPH_ERRORF("Motif size must be at least 3, received %" IGRAPH_PRId ".", @@ -577,7 +580,7 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real return IGRAPH_SUCCESS; } - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Insufficient memory to count motifs."); IGRAPH_FINALLY(igraph_free, added); @@ -607,8 +610,8 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real *est = 0; for (sam = 0; sam < sample_size; sam++) { - igraph_integer_t father = VECTOR(*sample)[sam]; - igraph_integer_t level, s; + igraph_int_t parent = VECTOR(*sample)[sam]; + igraph_int_t level, s; IGRAPH_ALLOW_INTERRUPTION(); @@ -620,20 +623,20 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real /* init G */ igraph_vector_int_clear(&vids); level = 0; - IGRAPH_CHECK(igraph_vector_int_push_back(&vids, father)); - added[father] += 1; level += 1; + IGRAPH_CHECK(igraph_vector_int_push_back(&vids, parent)); + added[parent] += 1; level += 1; /* init V_E */ igraph_vector_int_clear(&adjverts); IGRAPH_CHECK(igraph_neighbors( - graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + graph, &neis, parent, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { - igraph_integer_t nei = VECTOR(neis)[i]; - if (!added[nei] && nei > father) { + igraph_int_t nei = VECTOR(neis)[i]; + if (!added[nei] && nei > parent) { IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); - IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, father)); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, parent)); } added[nei] += 1; } @@ -657,15 +660,15 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real if (level < size - 1 && !igraph_vector_int_empty(&adjverts)) { /* We might step down */ - igraph_integer_t neifather = igraph_vector_int_pop_back(&adjverts); - igraph_integer_t nei = igraph_vector_int_pop_back(&adjverts); + igraph_int_t neiparent = igraph_vector_int_pop_back(&adjverts); + igraph_int_t nei = igraph_vector_int_pop_back(&adjverts); if (cp == 0 || RNG_UNIF01() > cp) { /* Yes, step down */ IGRAPH_CHECK(igraph_vector_int_push_back(&vids, nei)); added[nei] += 1; level += 1; - IGRAPH_CHECK(igraph_stack_int_push(&stack, neifather)); + IGRAPH_CHECK(igraph_stack_int_push(&stack, neiparent)); IGRAPH_CHECK(igraph_stack_int_push(&stack, nei)); IGRAPH_CHECK(igraph_stack_int_push(&stack, level)); @@ -674,8 +677,8 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { - igraph_integer_t nei2 = VECTOR(neis)[i]; - if (!added[nei2] && nei2 > father) { + igraph_int_t nei2 = VECTOR(neis)[i]; + if (!added[nei2] && nei2 > parent) { IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei2)); IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); } @@ -684,14 +687,14 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real } } else { /* no, step back */ - igraph_integer_t nei, neifather; + igraph_int_t nei, neiparent; while (!igraph_stack_int_empty(&stack) && level == igraph_stack_int_top(&stack) - 1) { igraph_stack_int_pop(&stack); nei = igraph_stack_int_pop(&stack); - neifather = igraph_stack_int_pop(&stack); - igraph_vector_int_push_back(&adjverts, nei); - igraph_vector_int_push_back(&adjverts, neifather); + neiparent = igraph_stack_int_pop(&stack); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, neiparent)); } nei = igraph_vector_int_pop_back(&vids); @@ -713,16 +716,16 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real } /* while */ /* clear the added vector */ - added[father] -= 1; + added[parent] -= 1; IGRAPH_CHECK(igraph_neighbors( - graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + graph, &neis, parent, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { added[ VECTOR(neis)[i] ] -= 1; } - } /* for father */ + } /* for parent */ (*est) *= ((igraph_real_t) no_of_nodes / sample_size); @@ -768,18 +771,18 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_real */ igraph_error_t igraph_motifs_randesu_no( - const igraph_t *graph, igraph_real_t *no, igraph_integer_t size, + const igraph_t *graph, igraph_real_t *no, igraph_int_t size, const igraph_vector_t *cut_prob ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t neis; igraph_vector_int_t vids; /* this is G */ igraph_vector_int_t adjverts; /* this is V_E */ igraph_stack_int_t stack; /* this is S */ - igraph_integer_t *added; - igraph_integer_t father; - igraph_integer_t i; + igraph_int_t *added; + igraph_int_t parent; + igraph_int_t i; if (size < 3) { IGRAPH_ERRORF("Motif size must be at least 3, received %" IGRAPH_PRId ".", @@ -790,7 +793,7 @@ igraph_error_t igraph_motifs_randesu_no( IGRAPH_ERRORF("Cut probability vector size (%" IGRAPH_PRId ") must agree with motif size (%" IGRAPH_PRId ").", IGRAPH_EINVAL, igraph_vector_size(cut_prob), size); } - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Insufficient memory to count motifs."); IGRAPH_FINALLY(igraph_free, added); @@ -802,8 +805,8 @@ igraph_error_t igraph_motifs_randesu_no( *no = 0; - for (father = 0; father < no_of_nodes; father++) { - igraph_integer_t level, s; + for (parent = 0; parent < no_of_nodes; parent++) { + igraph_int_t level, s; IGRAPH_ALLOW_INTERRUPTION(); @@ -815,20 +818,20 @@ igraph_error_t igraph_motifs_randesu_no( /* init G */ igraph_vector_int_clear(&vids); level = 0; - IGRAPH_CHECK(igraph_vector_int_push_back(&vids, father)); - added[father] += 1; level += 1; + IGRAPH_CHECK(igraph_vector_int_push_back(&vids, parent)); + added[parent] += 1; level += 1; /* init V_E */ igraph_vector_int_clear(&adjverts); IGRAPH_CHECK(igraph_neighbors( - graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + graph, &neis, parent, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { - igraph_integer_t nei = VECTOR(neis)[i]; - if (!added[nei] && nei > father) { + igraph_int_t nei = VECTOR(neis)[i]; + if (!added[nei] && nei > parent) { IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); - IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, father)); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, parent)); } added[nei] += 1; } @@ -852,15 +855,15 @@ igraph_error_t igraph_motifs_randesu_no( if (level < size - 1 && !igraph_vector_int_empty(&adjverts)) { /* We might step down */ - igraph_integer_t neifather = igraph_vector_int_pop_back(&adjverts); - igraph_integer_t nei = igraph_vector_int_pop_back(&adjverts); + igraph_int_t neiparent = igraph_vector_int_pop_back(&adjverts); + igraph_int_t nei = igraph_vector_int_pop_back(&adjverts); if (cp == 0 || RNG_UNIF01() > cp) { /* Yes, step down */ IGRAPH_CHECK(igraph_vector_int_push_back(&vids, nei)); added[nei] += 1; level += 1; - IGRAPH_CHECK(igraph_stack_int_push(&stack, neifather)); + IGRAPH_CHECK(igraph_stack_int_push(&stack, neiparent)); IGRAPH_CHECK(igraph_stack_int_push(&stack, nei)); IGRAPH_CHECK(igraph_stack_int_push(&stack, level)); @@ -869,8 +872,8 @@ igraph_error_t igraph_motifs_randesu_no( )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { - igraph_integer_t nei2 = VECTOR(neis)[i]; - if (!added[nei2] && nei2 > father) { + igraph_int_t nei2 = VECTOR(neis)[i]; + if (!added[nei2] && nei2 > parent) { IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei2)); IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); } @@ -879,14 +882,14 @@ igraph_error_t igraph_motifs_randesu_no( } } else { /* no, step back */ - igraph_integer_t nei, neifather; + igraph_int_t nei, neiparent; while (!igraph_stack_int_empty(&stack) && level == igraph_stack_int_top(&stack) - 1) { igraph_stack_int_pop(&stack); nei = igraph_stack_int_pop(&stack); - neifather = igraph_stack_int_pop(&stack); - igraph_vector_int_push_back(&adjverts, nei); - igraph_vector_int_push_back(&adjverts, neifather); + neiparent = igraph_stack_int_pop(&stack); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, nei)); + IGRAPH_CHECK(igraph_vector_int_push_back(&adjverts, neiparent)); } nei = igraph_vector_int_pop_back(&vids); @@ -908,16 +911,16 @@ igraph_error_t igraph_motifs_randesu_no( } /* while */ /* clear the added vector */ - added[father] -= 1; + added[parent] -= 1; IGRAPH_CHECK(igraph_neighbors( - graph, &neis, father, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE + graph, &neis, parent, IGRAPH_ALL, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); s = igraph_vector_int_size(&neis); for (i = 0; i < s; i++) { added[ VECTOR(neis)[i] ] -= 1; } - } /* for father */ + } /* for parent */ IGRAPH_FREE(added); igraph_vector_int_destroy(&vids); @@ -967,15 +970,15 @@ igraph_error_t igraph_dyad_census(const igraph_t *graph, igraph_real_t *mut, igraph_real_t nonrec = 0, rec = 0; igraph_vector_int_t inneis, outneis; - igraph_integer_t vc = igraph_vcount(graph); - igraph_integer_t i; + igraph_int_t vc = igraph_vcount(graph); + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&inneis, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&outneis, 0); for (i = 0; i < vc; i++) { - igraph_integer_t ideg, odeg; - igraph_integer_t ip, op; + igraph_int_t ideg, odeg; + igraph_int_t ip, op; IGRAPH_CHECK(igraph_neighbors(graph, &inneis, i, IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); IGRAPH_CHECK(igraph_neighbors(graph, &outneis, i, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); @@ -1016,10 +1019,10 @@ static igraph_error_t igraph_i_triad_census_24(const igraph_t *graph, igraph_real_t *res2, igraph_real_t *res4) { - const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_int_t vcount = igraph_vcount(graph); igraph_vector_int_t seen; igraph_vector_int_t *neis, *neis2; - igraph_integer_t s, neilen, neilen2, ign; + igraph_int_t s, neilen, neilen2, ign; igraph_adjlist_t adjlist; int iter = 0; @@ -1028,7 +1031,7 @@ static igraph_error_t igraph_i_triad_census_24(const igraph_t *graph, IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); *res2 = *res4 = 0; - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 12); neis = igraph_adjlist_get(&adjlist, i); @@ -1036,8 +1039,8 @@ static igraph_error_t igraph_i_triad_census_24(const igraph_t *graph, /* mark neighbors of i & i itself */ VECTOR(seen)[i] = i + 1; ign = 0; - for (igraph_integer_t j = 0; j < neilen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < neilen; j++) { + igraph_int_t nei = VECTOR(*neis)[j]; if (VECTOR(seen)[nei] == i + 1 || VECTOR(seen)[nei] == -(i + 1)) { /* multiple edges or loop edge */ VECTOR(seen)[nei] = -(i + 1); @@ -1047,16 +1050,16 @@ static igraph_error_t igraph_i_triad_census_24(const igraph_t *graph, } } - for (igraph_integer_t j = 0; j < neilen; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < neilen; j++) { + igraph_int_t nei = VECTOR(*neis)[j]; if (nei <= i || (j > 0 && nei == VECTOR(*neis)[j - 1])) { continue; } neis2 = igraph_adjlist_get(&adjlist, nei); neilen2 = igraph_vector_int_size(neis2); s = 0; - for (igraph_integer_t k = 0; k < neilen2; k++) { - igraph_integer_t nei2 = VECTOR(*neis2)[k]; + for (igraph_int_t k = 0; k < neilen2; k++) { + igraph_int_t nei2 = VECTOR(*neis2)[k]; if (k > 0 && nei2 == VECTOR(*neis2)[k - 1]) { continue; } @@ -1158,7 +1161,7 @@ static igraph_error_t igraph_i_triad_census_24(const igraph_t *graph, igraph_error_t igraph_triad_census(const igraph_t *graph, igraph_vector_t *res) { - const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_int_t vcount = igraph_vcount(graph); igraph_vector_t cut_prob, tmp; igraph_real_t m2, m4; igraph_real_t total; diff --git a/src/vendor/cigraph/src/misc/other.c b/src/vendor/cigraph/src/misc/other.c index 7b0d35025e2..845145ac05f 100644 --- a/src/vendor/cigraph/src/misc/other.c +++ b/src/vendor/cigraph/src/misc/other.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -48,10 +48,10 @@ */ igraph_error_t igraph_running_mean(const igraph_vector_t *data, igraph_vector_t *res, - igraph_integer_t binwidth) { + igraph_int_t binwidth) { double sum = 0; - igraph_integer_t i; + igraph_int_t i; /* Check */ if (igraph_vector_size(data) < binwidth) { @@ -83,175 +83,6 @@ igraph_error_t igraph_running_mean(const igraph_vector_t *data, igraph_vector_t } -/** - * \ingroup nongraph - * \function igraph_convex_hull - * \brief Determines the convex hull of a given set of points in the 2D plane. - * - * - * The convex hull is determined by the Graham scan algorithm. - * See the following reference for details: - * - * - * Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford - * Stein. Introduction to Algorithms, Second Edition. MIT Press and - * McGraw-Hill, 2001. ISBN 0262032937. Pages 949-955 of section 33.3: - * Finding the convex hull. - * - * \param data vector containing the coordinates. The length of the - * vector must be even, since it contains X-Y coordinate pairs. - * \param resverts the vector containing the result, e.g. the vector of - * vertex indices used as the corners of the convex hull. Supply - * \c NULL here if you are only interested in the coordinates of - * the convex hull corners. - * \param rescoords the matrix containing the coordinates of the selected - * corner vertices. Supply \c NULL here if you are only interested in - * the vertex indices. - * \return Error code: - * \c IGRAPH_ENOMEM: not enough memory - * - * Time complexity: O(n log(n)) where n is the number of vertices. - */ -igraph_error_t igraph_convex_hull( - const igraph_matrix_t *data, igraph_vector_int_t *resverts, - igraph_matrix_t *rescoords -) { - igraph_integer_t no_of_nodes; - igraph_integer_t i, pivot_idx = 0, last_idx, before_last_idx, next_idx, j; - igraph_vector_t angles; - igraph_vector_int_t order, stack; - igraph_real_t px, py, cp; - - no_of_nodes = igraph_matrix_nrow(data); - if (igraph_matrix_ncol(data) != 2) { - IGRAPH_ERROR("Only two-dimensional point sets are supports, matrix must have two columns.", IGRAPH_EINVAL); - } - if (no_of_nodes == 0) { - if (resverts) { - igraph_vector_int_clear(resverts); - } - if (rescoords) { - IGRAPH_CHECK(igraph_matrix_resize(rescoords, 0, 2)); - } - /**************************** this is an exit here *********/ - return IGRAPH_SUCCESS; - } - - IGRAPH_VECTOR_INIT_FINALLY(&angles, no_of_nodes); - IGRAPH_VECTOR_INT_INIT_FINALLY(&stack, 0); - - /* Search for the pivot vertex */ - for (i = 1; i < no_of_nodes; i++) { - if (MATRIX(*data, i, 1) < MATRIX(*data, pivot_idx, 1)) { - pivot_idx = i; - } else if (MATRIX(*data, i, 1) == MATRIX(*data, pivot_idx, 1) && - MATRIX(*data, i, 0) < MATRIX(*data, pivot_idx, 0)) { - pivot_idx = i; - } - } - px = MATRIX(*data, pivot_idx, 0); - py = MATRIX(*data, pivot_idx, 1); - - /* Create angle array */ - for (i = 0; i < no_of_nodes; i++) { - if (i == pivot_idx) { - /* We can't calculate the angle of the pivot point with itself, - * so we use 10 here. This way, after sorting the angle vector, - * the pivot point will always be the first one, since the range - * of atan2 is -3.14..3.14 */ - VECTOR(angles)[i] = 10; - } else { - VECTOR(angles)[i] = atan2(MATRIX(*data, i, 1) - py, MATRIX(*data, i, 0) - px); - } - } - - /* Sort points by angles */ - IGRAPH_VECTOR_INT_INIT_FINALLY(&order, no_of_nodes); - IGRAPH_CHECK(igraph_vector_sort_ind(&angles, &order, IGRAPH_ASCENDING)); - - /* Check if two points have the same angle. If so, keep only the point that - * is farthest from the pivot */ - j = 0; - last_idx = VECTOR(order)[0]; - pivot_idx = VECTOR(order)[no_of_nodes - 1]; - for (i = 1; i < no_of_nodes; i++) { - next_idx = VECTOR(order)[i]; - if (VECTOR(angles)[last_idx] == VECTOR(angles)[next_idx]) { - /* Keep the vertex that is farther from the pivot, drop the one that is - * closer */ - px = pow(MATRIX(*data, last_idx, 0) - MATRIX(*data, pivot_idx, 0), 2) + - pow(MATRIX(*data, last_idx, 1) - MATRIX(*data, pivot_idx, 1), 2); - py = pow(MATRIX(*data, next_idx, 0) - MATRIX(*data, pivot_idx, 0), 2) + - pow(MATRIX(*data, next_idx, 1) - MATRIX(*data, pivot_idx, 1), 2); - if (px > py) { - VECTOR(order)[i] = -1; - } else { - VECTOR(order)[j] = -1; - last_idx = next_idx; - j = i; - } - } else { - last_idx = next_idx; - j = i; - } - } - - j = 0; - last_idx = -1; - before_last_idx = -1; - while (!igraph_vector_int_empty(&order)) { - next_idx = igraph_vector_int_tail(&order); - if (next_idx < 0) { - /* This vertex should be skipped; was excluded in an earlier step */ - igraph_vector_int_pop_back(&order); - continue; - } - /* Determine whether we are at a left or right turn */ - if (j < 2) { - /* Pretend that we are turning into the right direction if we have less - * than two items in the stack */ - cp = -1; - } else { - cp = (MATRIX(*data, last_idx, 0) - MATRIX(*data, before_last_idx, 0)) * - (MATRIX(*data, next_idx, 1) - MATRIX(*data, before_last_idx, 1)) - - (MATRIX(*data, next_idx, 0) - MATRIX(*data, before_last_idx, 0)) * - (MATRIX(*data, last_idx, 1) - MATRIX(*data, before_last_idx, 1)); - } - - if (cp < 0) { - /* We are turning into the right direction */ - igraph_vector_int_pop_back(&order); - IGRAPH_CHECK(igraph_vector_int_push_back(&stack, next_idx)); - before_last_idx = last_idx; - last_idx = next_idx; - j++; - } else { - /* No, skip back and try again in the next iteration */ - igraph_vector_int_pop_back(&stack); - j--; - last_idx = before_last_idx; - before_last_idx = (j >= 2) ? VECTOR(stack)[j - 2] : -1; - } - } - - /* Create result vector */ - if (resverts != 0) { - igraph_vector_int_clear(resverts); - IGRAPH_CHECK(igraph_vector_int_append(resverts, &stack)); - } - if (rescoords != 0) { - igraph_matrix_select_rows(data, rescoords, &stack); - } - - /* Free everything */ - igraph_vector_int_destroy(&order); - igraph_vector_int_destroy(&stack); - igraph_vector_destroy(&angles); - IGRAPH_FINALLY_CLEAN(3); - - return IGRAPH_SUCCESS; -} - /** * \function igraph_expand_path_to_pairs * \brief Helper function to convert a sequence of vertex IDs describing a path into a "pairs" vector. @@ -270,8 +101,8 @@ igraph_error_t igraph_convex_hull( * the vector. */ igraph_error_t igraph_expand_path_to_pairs(igraph_vector_int_t* path) { - igraph_integer_t no_of_vertices = igraph_vector_int_size(path); - igraph_integer_t i, j, no_of_items = (no_of_vertices - 1) * 2; + igraph_int_t no_of_vertices = igraph_vector_int_size(path); + igraph_int_t i, j, no_of_items = (no_of_vertices - 1) * 2; if (no_of_vertices <= 1) { igraph_vector_int_clear(path); @@ -331,11 +162,11 @@ igraph_error_t igraph_expand_path_to_pairs(igraph_vector_int_t* path) { * Time complexity: O(n) where n is the length of the walk. */ igraph_error_t igraph_vertex_path_from_edge_path( - const igraph_t *graph, igraph_integer_t start, + const igraph_t *graph, igraph_int_t start, const igraph_vector_int_t *edge_path, igraph_vector_int_t *vertex_path, igraph_neimode_t mode ) { - const igraph_integer_t no_of_edges = igraph_vector_int_size(edge_path); + const igraph_int_t no_of_edges = igraph_vector_int_size(edge_path); igraph_vector_int_clear(vertex_path); IGRAPH_CHECK(igraph_vector_int_reserve(vertex_path, no_of_edges + 1)); @@ -350,7 +181,7 @@ igraph_error_t igraph_vertex_path_from_edge_path( IGRAPH_ERROR("The path must contain at least one edge in order to " "determine its starting vertex automatically.", IGRAPH_EINVAL); } - const igraph_integer_t edge = VECTOR(*edge_path)[0]; + const igraph_int_t edge = VECTOR(*edge_path)[0]; switch (mode) { case IGRAPH_OUT: start = IGRAPH_FROM(graph, edge); @@ -360,9 +191,9 @@ igraph_error_t igraph_vertex_path_from_edge_path( break; case IGRAPH_ALL: if (no_of_edges > 1) { - const igraph_integer_t from = IGRAPH_FROM(graph, edge); - const igraph_integer_t to = IGRAPH_TO(graph, edge); - const igraph_integer_t next_edge = VECTOR(*edge_path)[1]; + const igraph_int_t from = IGRAPH_FROM(graph, edge); + const igraph_int_t to = IGRAPH_TO(graph, edge); + const igraph_int_t next_edge = VECTOR(*edge_path)[1]; if (to == IGRAPH_FROM(graph, next_edge) || to == IGRAPH_TO(graph, next_edge)) { start = from; } else { @@ -381,12 +212,12 @@ igraph_error_t igraph_vertex_path_from_edge_path( IGRAPH_ERROR("Invalid start vertex.", IGRAPH_EINVVID); } - for (igraph_integer_t i = 0; i < no_of_edges; i++) { - const igraph_integer_t edge = VECTOR(*edge_path)[i]; - const igraph_integer_t from = IGRAPH_FROM(graph, edge); - const igraph_integer_t to = IGRAPH_TO(graph, edge); + for (igraph_int_t i = 0; i < no_of_edges; i++) { + const igraph_int_t edge = VECTOR(*edge_path)[i]; + const igraph_int_t from = IGRAPH_FROM(graph, edge); + const igraph_int_t to = IGRAPH_TO(graph, edge); igraph_bool_t next_edge_ok; - igraph_integer_t next_start; + igraph_int_t next_start; igraph_vector_int_push_back(vertex_path, start); /* reserved */ diff --git a/src/vendor/cigraph/src/misc/power_law_fit.c b/src/vendor/cigraph/src/misc/power_law_fit.c index 8aebfcf4b42..1f206205274 100644 --- a/src/vendor/cigraph/src/misc/power_law_fit.c +++ b/src/vendor/cigraph/src/misc/power_law_fit.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/misc/scan.c b/src/vendor/cigraph/src/misc/scan.c index f054b2fe4e8..dc24b67556e 100644 --- a/src/vendor/cigraph/src/misc/scan.c +++ b/src/vendor/cigraph/src/misc/scan.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2013 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -73,9 +73,9 @@ static igraph_error_t igraph_i_local_scan_1_directed(const igraph_t *graph, const igraph_vector_t *weights, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_inclist_t incs; - igraph_integer_t i, node; + igraph_int_t i, node; igraph_vector_int_t neis; @@ -89,15 +89,15 @@ static igraph_error_t igraph_i_local_scan_1_directed(const igraph_t *graph, for (node = 0; node < no_of_nodes; node++) { igraph_vector_int_t *edges1 = igraph_inclist_get(&incs, node); - igraph_integer_t edgeslen1 = igraph_vector_int_size(edges1); + igraph_int_t edgeslen1 = igraph_vector_int_size(edges1); IGRAPH_ALLOW_INTERRUPTION(); /* Mark neighbors and self */ VECTOR(neis)[node] = node + 1; for (i = 0; i < edgeslen1; i++) { - igraph_integer_t e = VECTOR(*edges1)[i]; - igraph_integer_t nei = IGRAPH_OTHER(graph, e, node); + igraph_int_t e = VECTOR(*edges1)[i]; + igraph_int_t nei = IGRAPH_OTHER(graph, e, node); igraph_real_t w = weights ? VECTOR(*weights)[e] : 1; VECTOR(neis)[nei] = node + 1; VECTOR(*res)[node] += w; @@ -105,16 +105,16 @@ static igraph_error_t igraph_i_local_scan_1_directed(const igraph_t *graph, /* Crawl neighbors */ for (i = 0; i < edgeslen1; i++) { - igraph_integer_t e2 = VECTOR(*edges1)[i]; - igraph_integer_t nei = IGRAPH_OTHER(graph, e2, node); + igraph_int_t e2 = VECTOR(*edges1)[i]; + igraph_int_t nei = IGRAPH_OTHER(graph, e2, node); if (nei == node) { break; } igraph_vector_int_t *edges2 = igraph_inclist_get(&incs, nei); - igraph_integer_t j, edgeslen2 = igraph_vector_int_size(edges2); + igraph_int_t j, edgeslen2 = igraph_vector_int_size(edges2); for (j = 0; j < edgeslen2; j++) { - igraph_integer_t e2 = VECTOR(*edges2)[j]; - igraph_integer_t nei2 = IGRAPH_OTHER(graph, e2, nei); + igraph_int_t e2 = VECTOR(*edges2)[j]; + igraph_int_t nei2 = IGRAPH_OTHER(graph, e2, nei); igraph_real_t w2 = weights ? VECTOR(*weights)[e2] : 1; if (VECTOR(neis)[nei2] == node + 1) { VECTOR(*res)[node] += w2; @@ -135,9 +135,9 @@ static igraph_error_t igraph_i_local_scan_1_directed_all(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_t *weights) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_inclist_t incs; - igraph_integer_t i, node; + igraph_int_t i, node; igraph_vector_int_t neis; @@ -151,7 +151,7 @@ static igraph_error_t igraph_i_local_scan_1_directed_all(const igraph_t *graph, for (node = 0; node < no_of_nodes; node++) { igraph_vector_int_t *edges1 = igraph_inclist_get(&incs, node); - igraph_integer_t edgeslen1 = igraph_vector_int_size(edges1); + igraph_int_t edgeslen1 = igraph_vector_int_size(edges1); IGRAPH_ALLOW_INTERRUPTION(); @@ -160,8 +160,8 @@ static igraph_error_t igraph_i_local_scan_1_directed_all(const igraph_t *graph, double count its incident edges later, when we are going over the incident edges of ego's neighbors. */ for (i = 0; i < edgeslen1; i++) { - igraph_integer_t e = VECTOR(*edges1)[i]; - igraph_integer_t nei = IGRAPH_OTHER(graph, e, node); + igraph_int_t e = VECTOR(*edges1)[i]; + igraph_int_t nei = IGRAPH_OTHER(graph, e, node); igraph_real_t w = weights ? VECTOR(*weights)[e] : 1; VECTOR(neis)[nei] = node + 1; VECTOR(*res)[node] += w; @@ -174,18 +174,18 @@ static igraph_error_t igraph_i_local_scan_1_directed_all(const igraph_t *graph, only crawled once. We count all qualifying edges of ego, and then unmark ego to avoid double counting. */ for (i = 0; i < edgeslen1; i++) { - igraph_integer_t e2 = VECTOR(*edges1)[i]; - igraph_integer_t nei = IGRAPH_OTHER(graph, e2, node); + igraph_int_t e2 = VECTOR(*edges1)[i]; + igraph_int_t nei = IGRAPH_OTHER(graph, e2, node); igraph_vector_int_t *edges2; - igraph_integer_t j, edgeslen2; + igraph_int_t j, edgeslen2; if (VECTOR(neis)[nei] != node + 1) { continue; } edges2 = igraph_inclist_get(&incs, nei); edgeslen2 = igraph_vector_int_size(edges2); for (j = 0; j < edgeslen2; j++) { - igraph_integer_t e2 = VECTOR(*edges2)[j]; - igraph_integer_t nei2 = IGRAPH_OTHER(graph, e2, nei); + igraph_int_t e2 = VECTOR(*edges2)[j]; + igraph_int_t nei2 = IGRAPH_OTHER(graph, e2, nei); igraph_real_t w2 = weights ? VECTOR(*weights)[e2] : 1; if (VECTOR(neis)[nei2] == node + 1) { VECTOR(*res)[node] += w2; @@ -243,7 +243,7 @@ static igraph_error_t igraph_i_local_scan_0_them_w(const igraph_t *us, const igr igraph_t is; igraph_vector_int_t map2; igraph_vector_t weights; - igraph_integer_t i, m; + igraph_int_t i, m; if (!weights_them) { IGRAPH_ERROR("Edge weights not given for weighted scan-0", @@ -346,11 +346,11 @@ igraph_error_t igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_ const igraph_vector_t *weights_them, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(us); + igraph_int_t no_of_nodes = igraph_vcount(us); igraph_adjlist_t adj_us; igraph_inclist_t incs_them; igraph_vector_int_t neis; - igraph_integer_t node; + igraph_int_t node; if (igraph_vcount(them) != no_of_nodes) { IGRAPH_ERROR("Number of vertices must match in scan-1", IGRAPH_EINVAL); @@ -379,23 +379,23 @@ igraph_error_t igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_ for (node = 0; node < no_of_nodes; node++) { igraph_vector_int_t *neis_us = igraph_adjlist_get(&adj_us, node); igraph_vector_int_t *edges1_them = igraph_inclist_get(&incs_them, node); - igraph_integer_t len1_us = igraph_vector_int_size(neis_us); - igraph_integer_t len1_them = igraph_vector_int_size(edges1_them); - igraph_integer_t i; + igraph_int_t len1_us = igraph_vector_int_size(neis_us); + igraph_int_t len1_them = igraph_vector_int_size(edges1_them); + igraph_int_t i; IGRAPH_ALLOW_INTERRUPTION(); /* Mark neighbors and self in us */ VECTOR(neis)[node] = node + 1; for (i = 0; i < len1_us; i++) { - igraph_integer_t nei = VECTOR(*neis_us)[i]; + igraph_int_t nei = VECTOR(*neis_us)[i]; VECTOR(neis)[nei] = node + 1; } /* Crawl neighbors in them, first ego */ for (i = 0; i < len1_them; i++) { - igraph_integer_t e = VECTOR(*edges1_them)[i]; - igraph_integer_t nei = IGRAPH_OTHER(them, e, node); + igraph_int_t e = VECTOR(*edges1_them)[i]; + igraph_int_t nei = IGRAPH_OTHER(them, e, node); if (VECTOR(neis)[nei] == node + 1) { igraph_real_t w = weights_them ? VECTOR(*weights_them)[e] : 1; VECTOR(*res)[node] += w; @@ -403,12 +403,12 @@ igraph_error_t igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_ } /* Then the rest */ for (i = 0; i < len1_us; i++) { - igraph_integer_t nei = VECTOR(*neis_us)[i]; + igraph_int_t nei = VECTOR(*neis_us)[i]; igraph_vector_int_t *edges2_them = igraph_inclist_get(&incs_them, nei); - igraph_integer_t j, len2_them = igraph_vector_int_size(edges2_them); + igraph_int_t j, len2_them = igraph_vector_int_size(edges2_them); for (j = 0; j < len2_them; j++) { - igraph_integer_t e2 = VECTOR(*edges2_them)[j]; - igraph_integer_t nei2 = IGRAPH_OTHER(them, e2, nei); + igraph_int_t e2 = VECTOR(*edges2_them)[j]; + igraph_int_t nei2 = IGRAPH_OTHER(them, e2, nei); if (VECTOR(neis)[nei2] == node + 1) { igraph_real_t w = weights_them ? VECTOR(*weights_them)[e2] : 1; VECTOR(*res)[node] += w; @@ -447,13 +447,13 @@ igraph_error_t igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_ * */ -igraph_error_t igraph_local_scan_k_ecount(const igraph_t *graph, igraph_integer_t k, +igraph_error_t igraph_local_scan_k_ecount(const igraph_t *graph, igraph_int_t k, igraph_vector_t *res, const igraph_vector_t *weights, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t node; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t node; igraph_dqueue_int_t Q; igraph_vector_int_t marked; igraph_inclist_t incs; @@ -492,13 +492,13 @@ igraph_error_t igraph_local_scan_k_ecount(const igraph_t *graph, igraph_integer_ IGRAPH_CHECK(igraph_dqueue_int_push(&Q, 0)); VECTOR(marked)[node] = node + 1; while (!igraph_dqueue_int_empty(&Q)) { - igraph_integer_t act = igraph_dqueue_int_pop(&Q); - igraph_integer_t dist = igraph_dqueue_int_pop(&Q) + 1; + igraph_int_t act = igraph_dqueue_int_pop(&Q); + igraph_int_t dist = igraph_dqueue_int_pop(&Q) + 1; igraph_vector_int_t *edges = igraph_inclist_get(&incs, act); - igraph_integer_t i, edgeslen = igraph_vector_int_size(edges); + igraph_int_t i, edgeslen = igraph_vector_int_size(edges); for (i = 0; i < edgeslen; i++) { - igraph_integer_t edge = VECTOR(*edges)[i]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, act); + igraph_int_t edge = VECTOR(*edges)[i]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, act); if (dist <= k || VECTOR(marked)[nei] == node + 1) { igraph_real_t w = weights ? VECTOR(*weights)[edge] : 1; VECTOR(*res)[node] += w; @@ -547,12 +547,12 @@ igraph_error_t igraph_local_scan_k_ecount(const igraph_t *graph, igraph_integer_ */ igraph_error_t igraph_local_scan_k_ecount_them(const igraph_t *us, const igraph_t *them, - igraph_integer_t k, igraph_vector_t *res, + igraph_int_t k, igraph_vector_t *res, const igraph_vector_t *weights_them, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(us); - igraph_integer_t node; + igraph_int_t no_of_nodes = igraph_vcount(us); + igraph_int_t node; igraph_dqueue_int_t Q; igraph_vector_int_t marked; igraph_stack_int_t ST; @@ -610,13 +610,13 @@ igraph_error_t igraph_local_scan_k_ecount_them(const igraph_t *us, const igraph_ IGRAPH_CHECK(igraph_stack_int_push(&ST, node)); VECTOR(marked)[node] = node + 1; while (!igraph_dqueue_int_empty(&Q)) { - igraph_integer_t act = igraph_dqueue_int_pop(&Q); - igraph_integer_t dist = igraph_dqueue_int_pop(&Q) + 1; + igraph_int_t act = igraph_dqueue_int_pop(&Q); + igraph_int_t dist = igraph_dqueue_int_pop(&Q) + 1; igraph_vector_int_t *edges = igraph_inclist_get(&incs_us, act); - igraph_integer_t i, edgeslen = igraph_vector_int_size(edges); + igraph_int_t i, edgeslen = igraph_vector_int_size(edges); for (i = 0; i < edgeslen; i++) { - igraph_integer_t edge = VECTOR(*edges)[i]; - igraph_integer_t nei = IGRAPH_OTHER(us, edge, act); + igraph_int_t edge = VECTOR(*edges)[i]; + igraph_int_t nei = IGRAPH_OTHER(us, edge, act); if (dist <= k && VECTOR(marked)[nei] != node + 1) { IGRAPH_CHECK(igraph_dqueue_int_push(&Q, nei)); IGRAPH_CHECK(igraph_dqueue_int_push(&Q, dist)); @@ -628,12 +628,12 @@ igraph_error_t igraph_local_scan_k_ecount_them(const igraph_t *us, const igraph_ /* Now check the edges of all nodes in THEM */ while (!igraph_stack_int_empty(&ST)) { - igraph_integer_t act = igraph_stack_int_pop(&ST); + igraph_int_t act = igraph_stack_int_pop(&ST); igraph_vector_int_t *edges = igraph_inclist_get(&incs_them, act); - igraph_integer_t i, edgeslen = igraph_vector_int_size(edges); + igraph_int_t i, edgeslen = igraph_vector_int_size(edges); for (i = 0; i < edgeslen; i++) { - igraph_integer_t edge = VECTOR(*edges)[i]; - igraph_integer_t nei = IGRAPH_OTHER(them, edge, act); + igraph_int_t edge = VECTOR(*edges)[i]; + igraph_int_t nei = IGRAPH_OTHER(them, edge, act); if (VECTOR(marked)[nei] == node + 1) { igraph_real_t w = weights_them ? VECTOR(*weights_them)[edge] : 1; VECTOR(*res)[node] += w; @@ -677,8 +677,8 @@ igraph_error_t igraph_local_scan_subset_ecount(const igraph_t *graph, const igraph_vector_t *weights, const igraph_vector_int_list_t *subsets) { - igraph_integer_t subset, no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_subsets = igraph_vector_int_list_size(subsets); + igraph_int_t subset, no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_subsets = igraph_vector_int_list_size(subsets); igraph_inclist_t incs; igraph_vector_int_t marked; igraph_bool_t directed = igraph_is_directed(graph); @@ -696,9 +696,9 @@ igraph_error_t igraph_local_scan_subset_ecount(const igraph_t *graph, for (subset = 0; subset < no_of_subsets; subset++) { igraph_vector_int_t *nei = igraph_vector_int_list_get_ptr(subsets, subset); - igraph_integer_t i, neilen = igraph_vector_int_size(nei); + igraph_int_t i, neilen = igraph_vector_int_size(nei); for (i = 0; i < neilen; i++) { - igraph_integer_t vertex = VECTOR(*nei)[i]; + igraph_int_t vertex = VECTOR(*nei)[i]; if (vertex < 0 || vertex >= no_of_nodes) { IGRAPH_ERROR("Invalid vertex ID in neighborhood list in local scan.", IGRAPH_EINVAL); @@ -707,12 +707,12 @@ igraph_error_t igraph_local_scan_subset_ecount(const igraph_t *graph, } for (i = 0; i < neilen; i++) { - igraph_integer_t vertex = VECTOR(*nei)[i]; + igraph_int_t vertex = VECTOR(*nei)[i]; igraph_vector_int_t *edges = igraph_inclist_get(&incs, vertex); - igraph_integer_t j, edgeslen = igraph_vector_int_size(edges); + igraph_int_t j, edgeslen = igraph_vector_int_size(edges); for (j = 0; j < edgeslen; j++) { - igraph_integer_t edge = VECTOR(*edges)[j]; - igraph_integer_t nei2 = IGRAPH_OTHER(graph, edge, vertex); + igraph_int_t edge = VECTOR(*edges)[j]; + igraph_int_t nei2 = IGRAPH_OTHER(graph, edge, vertex); if (VECTOR(marked)[nei2] == subset + 1) { igraph_real_t w = weights ? VECTOR(*weights)[edge] : 1; VECTOR(*res)[subset] += w; @@ -755,7 +755,7 @@ igraph_error_t igraph_local_scan_neighborhood_ecount(const igraph_t *graph, const igraph_vector_t *weights, const igraph_vector_int_list_t *neighborhoods) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (igraph_vector_int_list_size(neighborhoods) != no_of_nodes) { IGRAPH_ERROR("Invalid neighborhood list length in local scan.", diff --git a/src/vendor/cigraph/src/misc/sir.c b/src/vendor/cigraph/src/misc/sir.c index d635f67aa30..6800c32a264 100644 --- a/src/vendor/cigraph/src/misc/sir.c +++ b/src/vendor/cigraph/src/misc/sir.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2014 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -58,7 +58,7 @@ void igraph_sir_destroy(igraph_sir_t *sir) { } static void igraph_i_sir_destroy(igraph_vector_ptr_t *v) { - igraph_integer_t i, n = igraph_vector_ptr_size(v); + igraph_int_t i, n = igraph_vector_ptr_size(v); for (i = 0; i < n; i++) { if ( VECTOR(*v)[i] ) { igraph_sir_destroy( VECTOR(*v)[i]) ; @@ -109,18 +109,18 @@ static void igraph_i_sir_destroy(igraph_vector_ptr_t *v) { */ igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, - igraph_real_t gamma, igraph_integer_t no_sim, + igraph_real_t gamma, igraph_int_t no_sim, igraph_vector_ptr_t *result) { - igraph_integer_t infected; + igraph_int_t infected; igraph_vector_int_t status; igraph_adjlist_t adjlist; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t i, j, ns, ni, nr; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t i, j, ns, ni, nr; igraph_vector_int_t *neis; igraph_psumtree_t tree; igraph_real_t psum; - igraph_integer_t neilen; + igraph_int_t neilen; igraph_bool_t simple; if (no_of_nodes == 0) { @@ -196,14 +196,14 @@ igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, neis = igraph_adjlist_get(&adjlist, infected); neilen = igraph_vector_int_size(neis); for (i = 0; i < neilen; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; + igraph_int_t nei = VECTOR(*neis)[i]; IGRAPH_CHECK(igraph_psumtree_update(&tree, nei, beta)); } while (ni > 0) { igraph_real_t tt; igraph_real_t r; - igraph_integer_t vchange; + igraph_int_t vchange; IGRAPH_ALLOW_INTERRUPTION(); @@ -220,7 +220,7 @@ igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, ni--; nr++; IGRAPH_CHECK(igraph_psumtree_update(&tree, vchange, 0.0)); for (i = 0; i < neilen; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; + igraph_int_t nei = VECTOR(*neis)[i]; if (VECTOR(status)[nei] == S_S) { igraph_real_t rate = igraph_psumtree_get(&tree, nei); rate -= beta; @@ -238,7 +238,7 @@ igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta, ns--; ni++; IGRAPH_CHECK(igraph_psumtree_update(&tree, vchange, gamma)); for (i = 0; i < neilen; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; + igraph_int_t nei = VECTOR(*neis)[i]; if (VECTOR(status)[nei] == S_S) { igraph_real_t rate = igraph_psumtree_get(&tree, nei); rate += beta; diff --git a/src/vendor/cigraph/src/misc/spanning_trees.c b/src/vendor/cigraph/src/misc/spanning_trees.c index 06089d65cb0..95c8516d167 100644 --- a/src/vendor/cigraph/src/misc/spanning_trees.c +++ b/src/vendor/cigraph/src/misc/spanning_trees.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,7 +27,7 @@ #include "core/indheap.h" #include "core/interruption.h" -static igraph_integer_t max_tree_edges(igraph_integer_t no_of_nodes, igraph_integer_t no_of_edges) { +static igraph_int_t max_tree_edges(igraph_int_t no_of_nodes, igraph_int_t no_of_edges) { if (no_of_nodes == 0) return 0; if (no_of_edges < no_of_nodes) return no_of_edges; return no_of_nodes - 1; @@ -71,8 +71,8 @@ static igraph_error_t igraph_i_minimum_spanning_tree_unweighted( const igraph_t* graph, igraph_vector_int_t* res) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bitset_t already_added, added_edges; igraph_dqueue_int_t q; @@ -87,7 +87,7 @@ static igraph_error_t igraph_i_minimum_spanning_tree_unweighted( IGRAPH_CHECK(igraph_vector_int_reserve(res, max_tree_edges(no_of_nodes, no_of_edges))); /* Perform a BFS */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (IGRAPH_BIT_TEST(already_added, i)) { continue; } @@ -97,14 +97,14 @@ static igraph_error_t igraph_i_minimum_spanning_tree_unweighted( IGRAPH_BIT_SET(already_added, i); IGRAPH_CHECK(igraph_dqueue_int_push(&q, i)); while (! igraph_dqueue_int_empty(&q)) { - igraph_integer_t eids_size; - igraph_integer_t act_node = igraph_dqueue_int_pop(&q); + igraph_int_t eids_size; + igraph_int_t act_node = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_incident(graph, &eids, act_node, IGRAPH_ALL, IGRAPH_LOOPS)); eids_size = igraph_vector_int_size(&eids); - for (igraph_integer_t j = 0; j < eids_size; j++) { - igraph_integer_t edge = VECTOR(eids)[j]; + for (igraph_int_t j = 0; j < eids_size; j++) { + igraph_int_t edge = VECTOR(eids)[j]; if (! IGRAPH_BIT_TEST(added_edges, edge)) { - igraph_integer_t to = IGRAPH_OTHER(graph, edge, act_node); + igraph_int_t to = IGRAPH_OTHER(graph, edge, act_node); if (! IGRAPH_BIT_TEST(already_added, to)) { IGRAPH_BIT_SET(already_added, to); IGRAPH_BIT_SET(added_edges, edge); @@ -178,8 +178,8 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( igraph_vector_int_t* res, const igraph_vector_t *weights) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bitset_t already_added, added_edges; igraph_d_indheap_t heap; @@ -208,8 +208,8 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t adj_size; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t adj_size; if (IGRAPH_BIT_TEST(already_added, i)) { continue; } @@ -219,9 +219,9 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( /* add all edges of the first vertex */ IGRAPH_CHECK(igraph_incident(graph, &adj, i, IGRAPH_ALL, IGRAPH_LOOPS)); adj_size = igraph_vector_int_size(&adj); - for (igraph_integer_t j = 0; j < adj_size; j++) { - igraph_integer_t edgeno = VECTOR(adj)[j]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, edgeno, i); + for (igraph_int_t j = 0; j < adj_size; j++) { + igraph_int_t edgeno = VECTOR(adj)[j]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, edgeno, i); if (! IGRAPH_BIT_TEST(already_added, neighbor)) { IGRAPH_CHECK(igraph_d_indheap_push(&heap, -VECTOR(*weights)[edgeno], i, edgeno)); } @@ -229,7 +229,7 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( while (! igraph_d_indheap_empty(&heap)) { /* Get minimal edge */ - igraph_integer_t from, edge; + igraph_int_t from, edge; igraph_d_indheap_max_index(&heap, &from, &edge); /* Erase it */ @@ -237,7 +237,7 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( /* Is this edge already included? */ if (! IGRAPH_BIT_TEST(added_edges, edge)) { - const igraph_integer_t to = IGRAPH_OTHER(graph, edge, from); + const igraph_int_t to = IGRAPH_OTHER(graph, edge, from); /* Does it point to a visited node? */ if (! IGRAPH_BIT_TEST(already_added, to)) { @@ -247,9 +247,9 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( /* add all outgoing edges */ IGRAPH_CHECK(igraph_incident(graph, &adj, to, IGRAPH_ALL, IGRAPH_LOOPS)); adj_size = igraph_vector_int_size(&adj); - for (igraph_integer_t j = 0; j < adj_size; j++) { - const igraph_integer_t edgeno = VECTOR(adj)[j]; - const igraph_integer_t neighbor = IGRAPH_OTHER(graph, edgeno, to); + for (igraph_int_t j = 0; j < adj_size; j++) { + const igraph_int_t edgeno = VECTOR(adj)[j]; + const igraph_int_t neighbor = IGRAPH_OTHER(graph, edgeno, to); if (! IGRAPH_BIT_TEST(already_added, neighbor)) { IGRAPH_CHECK(igraph_d_indheap_push(&heap, -VECTOR(*weights)[edgeno], to, edgeno)); } @@ -271,10 +271,10 @@ static igraph_error_t igraph_i_minimum_spanning_tree_prim( /* Kruskal's algorithm */ -static igraph_integer_t get_comp(igraph_vector_int_t *comp, igraph_integer_t i) { - igraph_integer_t k = i; +static igraph_int_t get_comp(igraph_vector_int_t *comp, igraph_int_t i) { + igraph_int_t k = i; for (;;) { - igraph_integer_t next = VECTOR(*comp)[k]; + igraph_int_t next = VECTOR(*comp)[k]; if (next == k) { VECTOR(*comp)[i] = k; return k; @@ -284,9 +284,9 @@ static igraph_integer_t get_comp(igraph_vector_int_t *comp, igraph_integer_t i) } } -static void merge_comp(igraph_vector_int_t *comp, igraph_integer_t i, igraph_integer_t j) { - igraph_integer_t ci = get_comp(comp, i); - igraph_integer_t cj = get_comp(comp, j); +static void merge_comp(igraph_vector_int_t *comp, igraph_int_t i, igraph_int_t j) { + igraph_int_t ci = get_comp(comp, i); + igraph_int_t cj = get_comp(comp, j); VECTOR(*comp)[ci] = cj; } @@ -339,10 +339,10 @@ static igraph_error_t igraph_i_minimum_spanning_tree_kruskal( igraph_vector_int_t *res, const igraph_vector_t *weights) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t idx, comp; - igraph_integer_t tree_edge_count; + igraph_int_t tree_edge_count; int iter = 0; if (weights == NULL) { @@ -367,13 +367,13 @@ static igraph_error_t igraph_i_minimum_spanning_tree_kruskal( IGRAPH_CHECK(igraph_vector_int_reserve(res, max_tree_edges(no_of_nodes, no_of_edges))); tree_edge_count = 0; - for (igraph_integer_t i=0; i < no_of_edges; i++) { - igraph_integer_t edge = VECTOR(idx)[i]; - igraph_integer_t u = IGRAPH_FROM(graph, edge); - igraph_integer_t v = IGRAPH_TO(graph, edge); + for (igraph_int_t i=0; i < no_of_edges; i++) { + igraph_int_t edge = VECTOR(idx)[i]; + igraph_int_t u = IGRAPH_FROM(graph, edge); + igraph_int_t v = IGRAPH_TO(graph, edge); - igraph_integer_t cu = get_comp(&comp, u); - igraph_integer_t cv = get_comp(&comp, v); + igraph_int_t cu = get_comp(&comp, u); + igraph_int_t cv = get_comp(&comp, v); if (cu != cv) { merge_comp(&comp, u, v); @@ -493,9 +493,9 @@ igraph_error_t igraph_minimum_spanning_tree( * The walk is started from vertex start. comp_size must be the size of the connected * component containing start. */ -static igraph_error_t igraph_i_lerw(const igraph_t *graph, igraph_vector_int_t *res, igraph_integer_t start, - igraph_integer_t comp_size, igraph_vector_bool_t *visited, const igraph_inclist_t *il) { - igraph_integer_t visited_count; +static igraph_error_t igraph_i_lerw(const igraph_t *graph, igraph_vector_int_t *res, igraph_int_t start, + igraph_int_t comp_size, igraph_vector_bool_t *visited, const igraph_inclist_t *il) { + igraph_int_t visited_count; IGRAPH_CHECK(igraph_vector_int_reserve(res, igraph_vector_int_size(res) + comp_size - 1)); @@ -503,7 +503,7 @@ static igraph_error_t igraph_i_lerw(const igraph_t *graph, igraph_vector_int_t * visited_count = 1; while (visited_count < comp_size) { - igraph_integer_t degree, edge; + igraph_int_t degree, edge; igraph_vector_int_t *edges; edges = igraph_inclist_get(il, start); @@ -558,10 +558,10 @@ static igraph_error_t igraph_i_lerw(const igraph_t *graph, igraph_vector_int_t * * \sa \ref igraph_minimum_spanning_tree(), \ref igraph_random_walk() * */ -igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_int_t *res, igraph_integer_t vid) { +igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_int_t *res, igraph_int_t vid) { igraph_inclist_t il; igraph_vector_bool_t visited; - igraph_integer_t vcount = igraph_vcount(graph); + igraph_int_t vcount = igraph_vcount(graph); if (vid >= vcount) { IGRAPH_ERROR("Invalid vertex ID given for random spanning tree.", IGRAPH_EINVVID); @@ -577,7 +577,7 @@ igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_ if (vid < 0) { /* generate random spanning forest: consider each component separately */ igraph_vector_int_t membership, csize; - igraph_integer_t comp_count; + igraph_int_t comp_count; IGRAPH_VECTOR_INT_INIT_FINALLY(&membership, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&csize, 0); @@ -585,9 +585,9 @@ igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_ IGRAPH_CHECK(igraph_connected_components(graph, &membership, &csize, &comp_count, IGRAPH_WEAK)); /* for each component ... */ - for (igraph_integer_t i = 0; i < comp_count; ++i) { + for (igraph_int_t i = 0; i < comp_count; ++i) { /* ... find a vertex to start the LERW from */ - igraph_integer_t j = 0; + igraph_int_t j = 0; while (VECTOR(membership)[j] != i) { ++j; } @@ -600,7 +600,7 @@ igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_ IGRAPH_FINALLY_CLEAN(2); } else { /* consider the component containing vid */ igraph_vector_int_t comp_vertices; - igraph_integer_t comp_size; + igraph_int_t comp_size; /* we measure the size of the component */ IGRAPH_VECTOR_INT_INIT_FINALLY(&comp_vertices, 0); diff --git a/src/vendor/cigraph/src/operators/add_edge.c b/src/vendor/cigraph/src/operators/add_edge.c index b0f179fe97b..5c993b8efa8 100644 --- a/src/vendor/cigraph/src/operators/add_edge.c +++ b/src/vendor/cigraph/src/operators/add_edge.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -46,7 +46,7 @@ * Time complexity: O(|V|+|E|), the number of edges plus the number of * vertices. */ -igraph_error_t igraph_add_edge(igraph_t *graph, igraph_integer_t from, igraph_integer_t to) { +igraph_error_t igraph_add_edge(igraph_t *graph, igraph_int_t from, igraph_int_t to) { igraph_vector_int_t edges; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2); diff --git a/src/vendor/cigraph/src/operators/complementer.c b/src/vendor/cigraph/src/operators/complementer.c index 3324d881368..6bbf9f19135 100644 --- a/src/vendor/cigraph/src/operators/complementer.c +++ b/src/vendor/cigraph/src/operators/complementer.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -50,11 +50,11 @@ igraph_error_t igraph_complementer(igraph_t *res, const igraph_t *graph, igraph_bool_t loops) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t edges; igraph_vector_int_t neis; - igraph_integer_t i, j; - igraph_integer_t zero = 0, *limit; + igraph_int_t i, j; + igraph_int_t zero = 0, *limit; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); diff --git a/src/vendor/cigraph/src/operators/compose.c b/src/vendor/cigraph/src/operators/compose.c index ab5681f413f..3063c585d8c 100644 --- a/src/vendor/cigraph/src/operators/compose.c +++ b/src/vendor/cigraph/src/operators/compose.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -69,10 +69,10 @@ igraph_error_t igraph_compose(igraph_t *res, igraph_vector_int_t *edge_map1, igraph_vector_int_t *edge_map2) { - const igraph_integer_t no_of_nodes_left = igraph_vcount(g1); - const igraph_integer_t no_of_nodes_right = igraph_vcount(g2); + const igraph_int_t no_of_nodes_left = igraph_vcount(g1); + const igraph_int_t no_of_nodes_right = igraph_vcount(g2); const igraph_bool_t directed = igraph_is_directed(g1); - const igraph_integer_t no_of_nodes = no_of_nodes_left > no_of_nodes_right ? + const igraph_int_t no_of_nodes = no_of_nodes_left > no_of_nodes_right ? no_of_nodes_left : no_of_nodes_right; igraph_vector_int_t edges; igraph_vector_int_t neis1, neis2; @@ -93,20 +93,20 @@ igraph_error_t igraph_compose(igraph_t *res, igraph_vector_int_clear(edge_map2); } - for (igraph_integer_t i = 0; i < no_of_nodes_left; i++) { + for (igraph_int_t i = 0; i < no_of_nodes_left; i++) { IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_CHECK(igraph_incident(g1, &neis1, i, IGRAPH_OUT, IGRAPH_LOOPS)); while (!igraph_vector_int_empty(&neis1)) { - const igraph_integer_t con = igraph_vector_int_pop_back(&neis1); - const igraph_integer_t v1 = IGRAPH_OTHER(g1, con, i); + const igraph_int_t con = igraph_vector_int_pop_back(&neis1); + const igraph_int_t v1 = IGRAPH_OTHER(g1, con, i); if (v1 < no_of_nodes_right) { IGRAPH_CHECK(igraph_incident(g2, &neis2, v1, IGRAPH_OUT, IGRAPH_LOOPS)); } else { continue; } while (!igraph_vector_int_empty(&neis2)) { - const igraph_integer_t con2 = igraph_vector_int_pop_back(&neis2); - const igraph_integer_t v2 = IGRAPH_OTHER(g2, con2, v1); + const igraph_int_t con2 = igraph_vector_int_pop_back(&neis2); + const igraph_int_t v2 = IGRAPH_OTHER(g2, con2, v1); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, i)); IGRAPH_CHECK(igraph_vector_int_push_back(&edges, v2)); if (edge_map1) { diff --git a/src/vendor/cigraph/src/operators/connect_neighborhood.c b/src/vendor/cigraph/src/operators/connect_neighborhood.c index d9172968d1f..06978614a19 100644 --- a/src/vendor/cigraph/src/operators/connect_neighborhood.c +++ b/src/vendor/cigraph/src/operators/connect_neighborhood.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -65,14 +65,14 @@ * Time complexity: O(|V|*d^k), |V| is the number of vertices in the * graph, d is the average degree and k is the \p order argument. */ -igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t order, +igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_int_t order, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; igraph_vector_int_t edges; - igraph_integer_t i, j, in; - igraph_integer_t *added; + igraph_int_t i, j, in; + igraph_int_t *added; igraph_vector_int_t neis; if (order < 0) { @@ -89,7 +89,7 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Cannot connect neighborhood."); IGRAPH_FINALLY(igraph_free, added); @@ -102,7 +102,7 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord in = igraph_vector_int_size(&neis); if (order > 1) { for (j = 0; j < in; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + igraph_int_t nei = VECTOR(neis)[j]; added[nei] = i + 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 1)); @@ -110,15 +110,15 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord } while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); - igraph_integer_t n; + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t n; IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); n = igraph_vector_int_size(&neis); if (actdist < order - 1) { for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); @@ -136,7 +136,7 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord } } else { for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; if (mode != IGRAPH_ALL || i < nei) { @@ -200,10 +200,10 @@ igraph_error_t igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t ord * graph, d is the average degree and k is the \p order argument. */ igraph_error_t igraph_graph_power(const igraph_t *graph, igraph_t *res, - igraph_integer_t order, igraph_bool_t directed) { + igraph_int_t order, igraph_bool_t directed) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t edges; igraph_adjlist_t al; igraph_bool_t dir = igraph_is_directed(graph) && directed; @@ -229,12 +229,12 @@ igraph_error_t igraph_graph_power(const igraph_t *graph, igraph_t *res, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges); igraph_vector_int_clear(&edges); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_vector_int_t *tmp = igraph_adjlist_get(&al, i); - for (igraph_integer_t j = 0; j < igraph_vector_int_size(tmp); j++) { + for (igraph_int_t j = 0; j < igraph_vector_int_size(tmp); j++) { if (dir || i < VECTOR(*tmp)[j]) { - igraph_vector_int_push_back(&edges, i); - igraph_vector_int_push_back(&edges, VECTOR(*tmp)[j]); + igraph_vector_int_push_back(&edges, i); /* initial space reserved */ + igraph_vector_int_push_back(&edges, VECTOR(*tmp)[j]); /* initial space reserved */ } } } @@ -242,39 +242,39 @@ igraph_error_t igraph_graph_power(const igraph_t *graph, igraph_t *res, if (order > 1) { /* order > 1, so add more edges. */ - igraph_integer_t d_i, d_actnode; - igraph_integer_t *added; + igraph_int_t d_i, d_actnode; + igraph_int_t *added; const igraph_vector_int_t *neis; igraph_dqueue_int_t q; - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Insufficient memory for graph power."); IGRAPH_FINALLY(igraph_free, added); IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { added[i] = i + 1; neis = igraph_adjlist_get(&al, i); d_i = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < d_i; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < d_i; j++) { + igraph_int_t nei = VECTOR(*neis)[j]; added[nei] = i + 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 1)); } while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); neis = igraph_adjlist_get(&al, actnode); d_actnode = igraph_vector_int_size(neis); if (actdist < order - 1) { - for (igraph_integer_t j = 0; j < d_actnode; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < d_actnode; j++) { + igraph_int_t nei = VECTOR(*neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); @@ -286,8 +286,8 @@ igraph_error_t igraph_graph_power(const igraph_t *graph, igraph_t *res, } } } else { - for (igraph_integer_t j = 0; j < d_actnode; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < d_actnode; j++) { + igraph_int_t nei = VECTOR(*neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; if (dir || i < nei) { diff --git a/src/vendor/cigraph/src/operators/contract.c b/src/vendor/cigraph/src/operators/contract.c index 3d285e6bc71..1b32de544e0 100644 --- a/src/vendor/cigraph/src/operators/contract.c +++ b/src/vendor/cigraph/src/operators/contract.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -63,12 +63,12 @@ igraph_error_t igraph_contract_vertices(igraph_t *graph, const igraph_vector_int_t *mapping, const igraph_attribute_combination_t *vertex_comb) { igraph_vector_int_t edges; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t vattr = vertex_comb && igraph_has_attribute_table(); igraph_t res; - igraph_integer_t last; - igraph_integer_t no_new_vertices; + igraph_int_t last; + igraph_int_t no_new_vertices; if (igraph_vector_int_size(mapping) != no_of_nodes) { IGRAPH_ERRORF("Mapping vector length (%" IGRAPH_PRId ") " @@ -87,15 +87,15 @@ igraph_error_t igraph_contract_vertices(igraph_t *graph, last = -1; } - for (igraph_integer_t edge = 0; edge < no_of_edges; edge++) { - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); + for (igraph_int_t edge = 0; edge < no_of_edges; edge++) { + igraph_int_t from = IGRAPH_FROM(graph, edge); + igraph_int_t to = IGRAPH_TO(graph, edge); - igraph_integer_t nfrom = VECTOR(*mapping)[from]; - igraph_integer_t nto = VECTOR(*mapping)[to]; + igraph_int_t nfrom = VECTOR(*mapping)[from]; + igraph_int_t nto = VECTOR(*mapping)[to]; - igraph_vector_int_push_back(&edges, nfrom); - igraph_vector_int_push_back(&edges, nto); + igraph_vector_int_push_back(&edges, nfrom); /* reserved */ + igraph_vector_int_push_back(&edges, nto); /* reserved */ if (nfrom > last) { last = nfrom; @@ -124,8 +124,8 @@ igraph_error_t igraph_contract_vertices(igraph_t *graph, IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(&merges, no_new_vertices); IGRAPH_VECTOR_INT_INIT_FINALLY(&sizes, no_new_vertices); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t to = VECTOR(*mapping)[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t to = VECTOR(*mapping)[i]; igraph_vector_int_t *v = igraph_vector_int_list_get_ptr(&merges, to); VECTOR(sizes)[to] += 1; IGRAPH_CHECK(igraph_vector_int_push_back(v, i)); diff --git a/src/vendor/cigraph/src/operators/difference.c b/src/vendor/cigraph/src/operators/difference.c index adadd3bcf64..ac6517de994 100644 --- a/src/vendor/cigraph/src/operators/difference.c +++ b/src/vendor/cigraph/src/operators/difference.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -58,17 +58,17 @@ igraph_error_t igraph_difference(igraph_t *res, contains the vertices according to the order of the vertex IDs at the "other" end of the edge. */ - igraph_integer_t no_of_nodes_orig = igraph_vcount(orig); - igraph_integer_t no_of_nodes_sub = igraph_vcount(sub); - igraph_integer_t no_of_nodes = no_of_nodes_orig; - igraph_integer_t smaller_nodes; + igraph_int_t no_of_nodes_orig = igraph_vcount(orig); + igraph_int_t no_of_nodes_sub = igraph_vcount(sub); + igraph_int_t no_of_nodes = no_of_nodes_orig; + igraph_int_t smaller_nodes; igraph_bool_t directed = igraph_is_directed(orig); igraph_vector_int_t edges; igraph_vector_int_t edge_ids; igraph_vector_int_t *nei1, *nei2; igraph_inclist_t inc_orig, inc_sub; - igraph_integer_t i; - igraph_integer_t v1, v2; + igraph_int_t i; + igraph_int_t v1, v2; if (directed != igraph_is_directed(sub)) { IGRAPH_ERROR("Cannot subtract directed and undirected graphs.", @@ -86,7 +86,7 @@ igraph_error_t igraph_difference(igraph_t *res, no_of_nodes_sub : no_of_nodes_orig; for (i = 0; i < smaller_nodes; i++) { - igraph_integer_t n1, n2, e1, e2; + igraph_int_t n1, n2, e1, e2; IGRAPH_ALLOW_INTERRUPTION(); nei1 = igraph_inclist_get(&inc_orig, i); nei2 = igraph_inclist_get(&inc_sub, i); @@ -139,7 +139,7 @@ igraph_error_t igraph_difference(igraph_t *res, /* copy remaining edges, use the previous value of 'i' */ for (; i < no_of_nodes_orig; i++) { - igraph_integer_t n1, e1; + igraph_int_t n1, e1; nei1 = igraph_inclist_get(&inc_orig, i); n1 = igraph_vector_int_size(nei1) - 1; while (n1 >= 0) { diff --git a/src/vendor/cigraph/src/operators/disjoint_union.c b/src/vendor/cigraph/src/operators/disjoint_union.c index 6c012638bbc..f288925545e 100644 --- a/src/vendor/cigraph/src/operators/disjoint_union.c +++ b/src/vendor/cigraph/src/operators/disjoint_union.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -69,15 +69,15 @@ igraph_error_t igraph_disjoint_union(igraph_t *res, const igraph_t *left, const igraph_t *right) { - const igraph_integer_t no_of_nodes_left = igraph_vcount(left); - const igraph_integer_t no_of_nodes_right = igraph_vcount(right); - const igraph_integer_t no_of_edges_left = igraph_ecount(left); - const igraph_integer_t no_of_edges_right = igraph_ecount(right); - igraph_integer_t no_of_nodes; /* vertex count of the result */ - igraph_integer_t no_of_edges2; /* twice the edge count of the result */ + const igraph_int_t no_of_nodes_left = igraph_vcount(left); + const igraph_int_t no_of_nodes_right = igraph_vcount(right); + const igraph_int_t no_of_edges_left = igraph_ecount(left); + const igraph_int_t no_of_edges_right = igraph_ecount(right); + igraph_int_t no_of_nodes; /* vertex count of the result */ + igraph_int_t no_of_edges2; /* twice the edge count of the result */ igraph_vector_int_t edges; igraph_bool_t directed_left = igraph_is_directed(left); - igraph_integer_t from, to; + igraph_int_t from, to; if (directed_left != igraph_is_directed(right)) { IGRAPH_ERROR("Cannot create disjoint union of directed and undirected graphs.", @@ -90,13 +90,13 @@ igraph_error_t igraph_disjoint_union(igraph_t *res, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); - for (igraph_integer_t i = 0; i < no_of_edges_left; i++) { + for (igraph_int_t i = 0; i < no_of_edges_left; i++) { from = IGRAPH_FROM(left, i); to = IGRAPH_TO(left, i); igraph_vector_int_push_back(&edges, from); /* reserved */ igraph_vector_int_push_back(&edges, to); /* reserved */ } - for (igraph_integer_t i = 0; i < no_of_edges_right; i++) { + for (igraph_int_t i = 0; i < no_of_edges_right; i++) { from = IGRAPH_FROM(right, i); to = IGRAPH_TO(right, i); igraph_vector_int_push_back(&edges, from + no_of_nodes_left); /* reserved */ @@ -149,18 +149,18 @@ igraph_error_t igraph_disjoint_union(igraph_t *res, */ igraph_error_t igraph_disjoint_union_many(igraph_t *res, const igraph_vector_ptr_t *graphs) { - igraph_integer_t no_of_graphs = igraph_vector_ptr_size(graphs); + igraph_int_t no_of_graphs = igraph_vector_ptr_size(graphs); igraph_bool_t directed = true; igraph_vector_int_t edges; - igraph_integer_t no_of_edges2 = 0; /* twice the edge count of the result */ - igraph_integer_t shift = 0; + igraph_int_t no_of_edges2 = 0; /* twice the edge count of the result */ + igraph_int_t shift = 0; igraph_t *graph; - igraph_integer_t from, to; + igraph_int_t from, to; if (no_of_graphs != 0) { graph = VECTOR(*graphs)[0]; directed = igraph_is_directed(graph); - for (igraph_integer_t i = 0; i < no_of_graphs; i++) { + for (igraph_int_t i = 0; i < no_of_graphs; i++) { graph = VECTOR(*graphs)[i]; IGRAPH_SAFE_ADD(no_of_edges2, 2*igraph_ecount(graph), &no_of_edges2); if (directed != igraph_is_directed(graph)) { @@ -173,11 +173,11 @@ igraph_error_t igraph_disjoint_union_many(igraph_t *res, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_CHECK(igraph_vector_int_reserve(&edges, no_of_edges2)); - for (igraph_integer_t i = 0; i < no_of_graphs; i++) { - igraph_integer_t ec; + for (igraph_int_t i = 0; i < no_of_graphs; i++) { + igraph_int_t ec; graph = VECTOR(*graphs)[i]; ec = igraph_ecount(graph); - for (igraph_integer_t j = 0; j < ec; j++) { + for (igraph_int_t j = 0; j < ec; j++) { from = IGRAPH_FROM(graph, j); to = IGRAPH_TO(graph, j); igraph_vector_int_push_back(&edges, from + shift); /* reserved */ diff --git a/src/vendor/cigraph/src/operators/intersection.c b/src/vendor/cigraph/src/operators/intersection.c index 2cade98cfd9..dc936ab750d 100644 --- a/src/vendor/cigraph/src/operators/intersection.c +++ b/src/vendor/cigraph/src/operators/intersection.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -122,16 +122,16 @@ igraph_error_t igraph_intersection_many( igraph_vector_int_list_t *edgemaps ) { - igraph_integer_t no_of_graphs = igraph_vector_ptr_size(graphs); - igraph_integer_t no_of_nodes = 0; + igraph_int_t no_of_graphs = igraph_vector_ptr_size(graphs); + igraph_int_t no_of_nodes = 0; igraph_bool_t directed = true; igraph_vector_int_t edges; igraph_vector_int_list_t edge_vects, order_vects; - igraph_integer_t i, j, tailfrom = no_of_graphs > 0 ? 0 : -1, tailto = -1; + igraph_int_t i, j, tailfrom = no_of_graphs > 0 ? 0 : -1, tailto = -1; igraph_vector_int_t no_edges; igraph_bool_t allne = no_of_graphs > 0; igraph_bool_t allsame = false; - igraph_integer_t idx = 0; + igraph_int_t idx = 0; /* Check directedness */ if (no_of_graphs != 0) { @@ -150,7 +150,7 @@ igraph_error_t igraph_intersection_many( /* Calculate number of nodes, query number of edges */ for (i = 0; i < no_of_graphs; i++) { - igraph_integer_t n = igraph_vcount(VECTOR(*graphs)[i]); + igraph_int_t n = igraph_vcount(VECTOR(*graphs)[i]); if (n > no_of_nodes) { no_of_nodes = n; } @@ -173,14 +173,14 @@ igraph_error_t igraph_intersection_many( /* Query and sort the edge lists */ for (i = 0; i < no_of_graphs; i++) { - igraph_integer_t k, j, n = VECTOR(no_edges)[i]; + igraph_int_t k, j, n = VECTOR(no_edges)[i]; igraph_vector_int_t *ev = igraph_vector_int_list_get_ptr(&edge_vects, i); igraph_vector_int_t *order = igraph_vector_int_list_get_ptr(&order_vects, i); IGRAPH_CHECK(igraph_get_edgelist(VECTOR(*graphs)[i], ev, /*bycol=*/ false)); if (!directed) { for (k = 0, j = 0; k < n; k++, j += 2) { if (VECTOR(*ev)[j] > VECTOR(*ev)[j + 1]) { - igraph_integer_t tmp = VECTOR(*ev)[j]; + igraph_int_t tmp = VECTOR(*ev)[j]; VECTOR(*ev)[j] = VECTOR(*ev)[j + 1]; VECTOR(*ev)[j + 1] = tmp; } @@ -206,9 +206,9 @@ igraph_error_t igraph_intersection_many( for (j = 0, tailfrom = IGRAPH_INTEGER_MAX, tailto = IGRAPH_INTEGER_MAX; j < no_of_graphs; j++) { igraph_vector_int_t *order = igraph_vector_int_list_get_ptr(&order_vects, j); igraph_vector_int_t *ev = igraph_vector_int_list_get_ptr(&edge_vects, j); - igraph_integer_t edge = igraph_vector_int_tail(order); - igraph_integer_t from = VECTOR(*ev)[2 * edge]; - igraph_integer_t to = VECTOR(*ev)[2 * edge + 1]; + igraph_int_t edge = igraph_vector_int_tail(order); + igraph_int_t from = VECTOR(*ev)[2 * edge]; + igraph_int_t to = VECTOR(*ev)[2 * edge + 1]; if (from < tailfrom || (from == tailfrom && to < tailto)) { tailfrom = from; tailto = to; } @@ -217,10 +217,10 @@ igraph_error_t igraph_intersection_many( /* OK, now remove all elements from the tail(s) that are bigger than the smallest tail element. */ for (j = 0, allsame = true; j < no_of_graphs; j++) { - igraph_integer_t from = -1, to = -1; + igraph_int_t from = -1, to = -1; igraph_vector_int_t *order = igraph_vector_int_list_get_ptr(&order_vects, j); while (true) { - igraph_integer_t edge = igraph_vector_int_tail(order); + igraph_int_t edge = igraph_vector_int_tail(order); igraph_vector_int_t *ev = igraph_vector_int_list_get_ptr(&edge_vects, j); from = VECTOR(*ev)[2 * edge]; to = VECTOR(*ev)[2 * edge + 1]; @@ -251,10 +251,10 @@ igraph_error_t igraph_intersection_many( if (allne) { for (j = 0; j < no_of_graphs; j++) { igraph_vector_int_t *order = igraph_vector_int_list_get_ptr(&order_vects, j); - igraph_integer_t edge = igraph_vector_int_tail(order); + igraph_int_t edge = igraph_vector_int_tail(order); igraph_vector_int_t *ev = igraph_vector_int_list_get_ptr(&edge_vects, j); - igraph_integer_t from = VECTOR(*ev)[2 * edge]; - igraph_integer_t to = VECTOR(*ev)[2 * edge + 1]; + igraph_int_t from = VECTOR(*ev)[2 * edge]; + igraph_int_t to = VECTOR(*ev)[2 * edge + 1]; if (from == tailfrom && to == tailto) { igraph_vector_int_pop_back(order); if (igraph_vector_int_empty(order)) { diff --git a/src/vendor/cigraph/src/operators/join.c b/src/vendor/cigraph/src/operators/join.c index cbedae4e25d..7570b753b9d 100644 --- a/src/vendor/cigraph/src/operators/join.c +++ b/src/vendor/cigraph/src/operators/join.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -64,13 +64,13 @@ igraph_error_t igraph_join(igraph_t *res, const igraph_t *left, const igraph_t *right) { - igraph_integer_t no_of_nodes_left = igraph_vcount(left); - igraph_integer_t no_of_nodes_right = igraph_vcount(right); - igraph_integer_t no_of_new_edges; + igraph_int_t no_of_nodes_left = igraph_vcount(left); + igraph_int_t no_of_nodes_right = igraph_vcount(right); + igraph_int_t no_of_new_edges; igraph_vector_int_t new_edges; igraph_bool_t directed_left = igraph_is_directed(left); - igraph_integer_t i; - igraph_integer_t j; + igraph_int_t i; + igraph_int_t j; if (directed_left != igraph_is_directed(right)) { IGRAPH_ERROR("Cannot create join of directed and undirected graphs.", diff --git a/src/vendor/cigraph/src/operators/misc_internal.c b/src/vendor/cigraph/src/operators/misc_internal.c index 9ff882bd704..f525afbeb9a 100644 --- a/src/vendor/cigraph/src/operators/misc_internal.c +++ b/src/vendor/cigraph/src/operators/misc_internal.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,17 +28,17 @@ int igraph_i_order_edgelist_cmp(void *edges, const void *e1, const void *e2) { igraph_vector_int_t *edgelist = edges; - igraph_integer_t edge1 = (*(const igraph_integer_t*) e1) * 2; - igraph_integer_t edge2 = (*(const igraph_integer_t*) e2) * 2; - igraph_integer_t from1 = VECTOR(*edgelist)[edge1]; - igraph_integer_t from2 = VECTOR(*edgelist)[edge2]; + igraph_int_t edge1 = (*(const igraph_int_t*) e1) * 2; + igraph_int_t edge2 = (*(const igraph_int_t*) e2) * 2; + igraph_int_t from1 = VECTOR(*edgelist)[edge1]; + igraph_int_t from2 = VECTOR(*edgelist)[edge2]; if (from1 < from2) { return -1; } else if (from1 > from2) { return 1; } else { - igraph_integer_t to1 = VECTOR(*edgelist)[edge1 + 1]; - igraph_integer_t to2 = VECTOR(*edgelist)[edge2 + 1]; + igraph_int_t to1 = VECTOR(*edgelist)[edge1 + 1]; + igraph_int_t to2 = VECTOR(*edgelist)[edge2 + 1]; if (to1 < to2) { return -1; } else if (to1 > to2) { @@ -53,17 +53,17 @@ igraph_error_t igraph_i_merge(igraph_t *res, igraph_i_merge_mode_t mode, const igraph_t *left, const igraph_t *right, igraph_vector_int_t *edge_map1, igraph_vector_int_t *edge_map2) { - igraph_integer_t no_of_nodes_left = igraph_vcount(left); - igraph_integer_t no_of_nodes_right = igraph_vcount(right); - igraph_integer_t no_of_nodes; - igraph_integer_t no_edges_left = igraph_ecount(left); - igraph_integer_t no_edges_right = igraph_ecount(right); + igraph_int_t no_of_nodes_left = igraph_vcount(left); + igraph_int_t no_of_nodes_right = igraph_vcount(right); + igraph_int_t no_of_nodes; + igraph_int_t no_edges_left = igraph_ecount(left); + igraph_int_t no_edges_right = igraph_ecount(right); igraph_bool_t directed = igraph_is_directed(left); igraph_vector_int_t edges; igraph_vector_int_t edges1, edges2; igraph_vector_int_t order1, order2; - igraph_integer_t i, j, eptr = 0; - igraph_integer_t idx1, idx2, edge1 = -1, edge2 = -1, from1 = -1, from2 = -1, to1 = -1, to2 = -1; + igraph_int_t i, j, eptr = 0; + igraph_int_t idx1, idx2, edge1 = -1, edge2 = -1, from1 = -1, from2 = -1, to1 = -1, to2 = -1; igraph_bool_t l; if (directed != igraph_is_directed(right)) { @@ -116,14 +116,14 @@ igraph_error_t igraph_i_merge(igraph_t *res, igraph_i_merge_mode_t mode, if (!directed) { for (i = 0, j = 0; i < no_edges_left; i++, j += 2) { if (VECTOR(edges1)[j] > VECTOR(edges1)[j + 1]) { - igraph_integer_t tmp = VECTOR(edges1)[j]; + igraph_int_t tmp = VECTOR(edges1)[j]; VECTOR(edges1)[j] = VECTOR(edges1)[j + 1]; VECTOR(edges1)[j + 1] = tmp; } } for (i = 0, j = 0; i < no_edges_right; i++, j += 2) { if (VECTOR(edges2)[j] > VECTOR(edges2)[j + 1]) { - igraph_integer_t tmp = VECTOR(edges2)[j]; + igraph_int_t tmp = VECTOR(edges2)[j]; VECTOR(edges2)[j] = VECTOR(edges2)[j + 1]; VECTOR(edges2)[j + 1] = tmp; } diff --git a/src/vendor/cigraph/src/operators/misc_internal.h b/src/vendor/cigraph/src/operators/misc_internal.h index 878a41b5379..49d780f987b 100644 --- a/src/vendor/cigraph/src/operators/misc_internal.h +++ b/src/vendor/cigraph/src/operators/misc_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2020 The igraph development team 334 Harvard street, Cambridge, MA 02139 USA diff --git a/src/vendor/cigraph/src/operators/permute.c b/src/vendor/cigraph/src/operators/permute.c index cb72aea1751..a0f6fbb2fa6 100644 --- a/src/vendor/cigraph/src/operators/permute.c +++ b/src/vendor/cigraph/src/operators/permute.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -37,13 +37,13 @@ * \return Error code. */ igraph_error_t igraph_invert_permutation(const igraph_vector_int_t *permutation, igraph_vector_int_t *inverse) { - const igraph_integer_t n = igraph_vector_int_size(permutation); + const igraph_int_t n = igraph_vector_int_size(permutation); IGRAPH_CHECK(igraph_vector_int_resize(inverse, n)); igraph_vector_int_fill(inverse, -1); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t j = VECTOR(*permutation)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t j = VECTOR(*permutation)[i]; if (j < 0 || j >= n) { IGRAPH_ERROR("Invalid index in permutation vector.", IGRAPH_EINVAL); } @@ -80,11 +80,11 @@ igraph_error_t igraph_invert_permutation(const igraph_vector_int_t *permutation, igraph_error_t igraph_permute_vertices(const igraph_t *graph, igraph_t *res, const igraph_vector_int_t *permutation) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vector_int_t edges; igraph_vector_int_t index; - igraph_integer_t p; + igraph_int_t p; if (igraph_vector_int_size(permutation) != no_of_nodes) { IGRAPH_ERROR("Permute vertices: invalid permutation vector size.", IGRAPH_EINVAL); @@ -98,7 +98,7 @@ igraph_error_t igraph_permute_vertices(const igraph_t *graph, igraph_t *res, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); p = 0; - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { VECTOR(edges)[p++] = VECTOR(index)[ IGRAPH_FROM(graph, i) ]; VECTOR(edges)[p++] = VECTOR(index)[ IGRAPH_TO(graph, i) ]; } diff --git a/src/vendor/cigraph/src/operators/products.c b/src/vendor/cigraph/src/operators/products.c index ac84006ed77..a7dc109b8a0 100644 --- a/src/vendor/cigraph/src/operators/products.c +++ b/src/vendor/cigraph/src/operators/products.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,12 +35,12 @@ static igraph_error_t cartesian_product(igraph_t *res, IGRAPH_EINVAL); } - const igraph_integer_t vcount1 = igraph_vcount(g1); - const igraph_integer_t vcount2 = igraph_vcount(g2); - const igraph_integer_t ecount1 = igraph_ecount(g1); - const igraph_integer_t ecount2 = igraph_ecount(g2); - igraph_integer_t vcount; - igraph_integer_t ecount, ecount_double; + const igraph_int_t vcount1 = igraph_vcount(g1); + const igraph_int_t vcount2 = igraph_vcount(g2); + const igraph_int_t ecount1 = igraph_ecount(g1); + const igraph_int_t ecount2 = igraph_ecount(g2); + igraph_int_t vcount; + igraph_int_t ecount, ecount_double; igraph_vector_int_t edges; // New vertex count = vcount1 * vcount2 @@ -48,7 +48,7 @@ static igraph_error_t cartesian_product(igraph_t *res, { // New edge count = vcount1*ecount2 + vcount2*ecount1 - igraph_integer_t temp; + igraph_int_t temp; IGRAPH_SAFE_MULT(vcount1, ecount2, &ecount); IGRAPH_SAFE_MULT(vcount2, ecount1, &temp); IGRAPH_SAFE_ADD(ecount, temp, &ecount); @@ -60,29 +60,29 @@ static igraph_error_t cartesian_product(igraph_t *res, // Vertex ((i, j)) with i from g1, and j from g2 // will have new vertex id: i * vcount2 + j - igraph_integer_t edge_index = 0; + igraph_int_t edge_index = 0; // Edges from g1 - for (igraph_integer_t i = 0; i < ecount1; ++i) { - igraph_integer_t from = IGRAPH_FROM(g1, i); - igraph_integer_t to = IGRAPH_TO(g1, i); + for (igraph_int_t i = 0; i < ecount1; ++i) { + igraph_int_t from = IGRAPH_FROM(g1, i); + igraph_int_t to = IGRAPH_TO(g1, i); // For all edges (from, to) in g1, add edge from ((from, j)) to ((to, j)) // for all vertex j in g2 - for (igraph_integer_t j = 0; j < vcount2; ++j) { + for (igraph_int_t j = 0; j < vcount2; ++j) { VECTOR(edges)[edge_index++] = from * vcount2 + j; // ((from, j)) VECTOR(edges)[edge_index++] = to * vcount2 + j; // ((to, j)) } } // Edges from g2 - for (igraph_integer_t i = 0; i < ecount2; ++i) { - igraph_integer_t from = IGRAPH_FROM(g2, i); - igraph_integer_t to = IGRAPH_TO(g2, i); + for (igraph_int_t i = 0; i < ecount2; ++i) { + igraph_int_t from = IGRAPH_FROM(g2, i); + igraph_int_t to = IGRAPH_TO(g2, i); // For all edges (from, to) in g2, add edge from (j, from) to (j, to) // for all vertex j in g1 - for (igraph_integer_t j = 0; j < vcount1; ++j) { + for (igraph_int_t j = 0; j < vcount1; ++j) { VECTOR(edges)[edge_index++] = j * vcount2 + from; // ((j, from)) VECTOR(edges)[edge_index++] = j * vcount2 + to; // ((j, to)) } @@ -106,12 +106,12 @@ static igraph_error_t lexicographic_product(igraph_t *res, IGRAPH_EINVAL); } - const igraph_integer_t vcount1 = igraph_vcount(g1); - const igraph_integer_t vcount2 = igraph_vcount(g2); - const igraph_integer_t ecount1 = igraph_ecount(g1); - const igraph_integer_t ecount2 = igraph_ecount(g2); - igraph_integer_t vcount; - igraph_integer_t ecount, ecount_double; + const igraph_int_t vcount1 = igraph_vcount(g1); + const igraph_int_t vcount2 = igraph_vcount(g2); + const igraph_int_t ecount1 = igraph_ecount(g1); + const igraph_int_t ecount2 = igraph_ecount(g2); + igraph_int_t vcount; + igraph_int_t ecount, ecount_double; igraph_vector_int_t edges; // New vertex count = vcount1 * vcount2 @@ -119,7 +119,7 @@ static igraph_error_t lexicographic_product(igraph_t *res, { // New edge count = vcount1*ecount2 + (vcount2^2)*ecount1 - igraph_integer_t temp; + igraph_int_t temp; IGRAPH_SAFE_MULT(vcount1, ecount2, &ecount); IGRAPH_SAFE_MULT(vcount2, vcount2, &temp); IGRAPH_SAFE_MULT(temp, ecount1, &temp); @@ -132,29 +132,29 @@ static igraph_error_t lexicographic_product(igraph_t *res, // Vertex ((i, j)) with i from g1, and j from g2 // will have new vertex id: i * vcount2 + j - igraph_integer_t edge_index = 0; + igraph_int_t edge_index = 0; // edges of form u1=u2 and v1~v2 - for (igraph_integer_t i = 0; i < ecount2; ++i) { - igraph_integer_t from = IGRAPH_FROM(g2, i); - igraph_integer_t to = IGRAPH_TO(g2, i); + for (igraph_int_t i = 0; i < ecount2; ++i) { + igraph_int_t from = IGRAPH_FROM(g2, i); + igraph_int_t to = IGRAPH_TO(g2, i); // For all edges (from, to) in g2, add edge from (j, from) to (j, to) // for all vertex j in g1 - for (igraph_integer_t j = 0; j < vcount1; ++j) { + for (igraph_int_t j = 0; j < vcount1; ++j) { VECTOR(edges)[edge_index++] = j * vcount2 + from; // ((j, from)) VECTOR(edges)[edge_index++] = j * vcount2 + to; // ((j, to)) } } // edges of form u1~u2 - for (igraph_integer_t i = 0; i < ecount1; ++i) { - igraph_integer_t from1 = IGRAPH_FROM(g1, i); - igraph_integer_t to1 = IGRAPH_TO(g1, i); + for (igraph_int_t i = 0; i < ecount1; ++i) { + igraph_int_t from1 = IGRAPH_FROM(g1, i); + igraph_int_t to1 = IGRAPH_TO(g1, i); // each vertex pair irrespective of their connectivity - for (igraph_integer_t from2 = 0; from2 < vcount2; ++from2) { - for (igraph_integer_t to2 = 0; to2 < vcount2; ++to2) { + for (igraph_int_t from2 = 0; from2 < vcount2; ++from2) { + for (igraph_int_t to2 = 0; to2 < vcount2; ++to2) { // ((from1, from2)) to ((to1, to2)) VECTOR(edges)[edge_index++] = from1 * vcount2 + from2; // ((from1, from2)) VECTOR(edges)[edge_index++] = to1 * vcount2 + to2; // ((to1, to2)) @@ -180,12 +180,12 @@ static igraph_error_t strong_product(igraph_t *res, IGRAPH_EINVAL); } - const igraph_integer_t vcount1 = igraph_vcount(g1); - const igraph_integer_t vcount2 = igraph_vcount(g2); - const igraph_integer_t ecount1 = igraph_ecount(g1); - const igraph_integer_t ecount2 = igraph_ecount(g2); - igraph_integer_t vcount; - igraph_integer_t ecount, ecount_double; + const igraph_int_t vcount1 = igraph_vcount(g1); + const igraph_int_t vcount2 = igraph_vcount(g2); + const igraph_int_t ecount1 = igraph_ecount(g1); + const igraph_int_t ecount2 = igraph_ecount(g2); + igraph_int_t vcount; + igraph_int_t ecount, ecount_double; igraph_vector_int_t edges; // New vertex count = vcount1 * vcount2 @@ -194,7 +194,7 @@ static igraph_error_t strong_product(igraph_t *res, { // New edge count = vcount1*ecount2 + vcount2*ecount1 + 2*e1*e2 for undirected graph // = vcount1*ecount2 + vcount2*ecount1 + e1*e2 for directed graph - igraph_integer_t temp; + igraph_int_t temp; IGRAPH_SAFE_MULT(vcount1, ecount2, &ecount); IGRAPH_SAFE_MULT(vcount2, ecount1, &temp); IGRAPH_SAFE_ADD(ecount, temp, &ecount); @@ -209,18 +209,18 @@ static igraph_error_t strong_product(igraph_t *res, IGRAPH_SAFE_MULT(ecount, 2, &ecount_double); IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, ecount_double); - igraph_integer_t edge_index = 0; + igraph_int_t edge_index = 0; // Strong graph product contains all the edges from both cartesian and tensor product // Edges of type cartesian products: v1=v2 and u1~u2; v1~v2 and u1=u2 // v1=v2 and u1~u2 - for (igraph_integer_t i = 0; i < ecount1; ++i) { - igraph_integer_t from = IGRAPH_FROM(g1, i); - igraph_integer_t to = IGRAPH_TO(g1, i); + for (igraph_int_t i = 0; i < ecount1; ++i) { + igraph_int_t from = IGRAPH_FROM(g1, i); + igraph_int_t to = IGRAPH_TO(g1, i); // For all edges (from, to) in g1, add edge from ((from, j)) to ((to, j)) // for all vertex j in g2 - for (igraph_integer_t j = 0; j < vcount2; ++j) { + for (igraph_int_t j = 0; j < vcount2; ++j) { // SAFE MULT and SAFE ADD not needed as < vcount VECTOR(edges)[edge_index++] = from * vcount2 + j; // ((from, j)) VECTOR(edges)[edge_index++] = to * vcount2 + j; // ((to, j)) @@ -228,13 +228,13 @@ static igraph_error_t strong_product(igraph_t *res, } // v1~v2 and u1=u2 - for (igraph_integer_t i = 0; i < ecount2; ++i) { - igraph_integer_t from = IGRAPH_FROM(g2, i); - igraph_integer_t to = IGRAPH_TO(g2, i); + for (igraph_int_t i = 0; i < ecount2; ++i) { + igraph_int_t from = IGRAPH_FROM(g2, i); + igraph_int_t to = IGRAPH_TO(g2, i); // For all edges (from, to) in g2, add edge from (j, from) to (j, to) // for all vertex j in g1 - for (igraph_integer_t j = 0; j < vcount1; ++j) { + for (igraph_int_t j = 0; j < vcount1; ++j) { VECTOR(edges)[edge_index++] = j * vcount2 + from; // ((j, from)) VECTOR(edges)[edge_index++] = j * vcount2 + to; // ((j, to)) } @@ -242,13 +242,13 @@ static igraph_error_t strong_product(igraph_t *res, // Edges of type tensor product // u1 ~ u2 and v1 ~ v2 - for (igraph_integer_t i = 0; i < ecount1; ++i) { - igraph_integer_t from1 = IGRAPH_FROM(g1, i); - igraph_integer_t to1 = IGRAPH_TO(g1, i); + for (igraph_int_t i = 0; i < ecount1; ++i) { + igraph_int_t from1 = IGRAPH_FROM(g1, i); + igraph_int_t to1 = IGRAPH_TO(g1, i); - for (igraph_integer_t j = 0; j < ecount2; ++j) { - igraph_integer_t from2 = IGRAPH_FROM(g2, j); - igraph_integer_t to2 = IGRAPH_TO(g2, j); + for (igraph_int_t j = 0; j < ecount2; ++j) { + igraph_int_t from2 = IGRAPH_FROM(g2, j); + igraph_int_t to2 = IGRAPH_TO(g2, j); // Create edge between ((from1, from2)) to ((to1, to2)) VECTOR(edges)[edge_index++] = from1 * vcount2 + from2; // ((from1, from2)) @@ -281,12 +281,12 @@ static igraph_error_t tensor_product(igraph_t *res, IGRAPH_EINVAL); } - const igraph_integer_t vcount1 = igraph_vcount(g1); - const igraph_integer_t vcount2 = igraph_vcount(g2); - const igraph_integer_t ecount1 = igraph_ecount(g1); - const igraph_integer_t ecount2 = igraph_ecount(g2); - igraph_integer_t vcount; - igraph_integer_t ecount, ecount_double; + const igraph_int_t vcount1 = igraph_vcount(g1); + const igraph_int_t vcount2 = igraph_vcount(g2); + const igraph_int_t ecount1 = igraph_ecount(g1); + const igraph_int_t ecount2 = igraph_ecount(g2); + igraph_int_t vcount; + igraph_int_t ecount, ecount_double; igraph_vector_int_t edges; IGRAPH_SAFE_MULT(vcount1, vcount2, &vcount); @@ -302,15 +302,15 @@ static igraph_error_t tensor_product(igraph_t *res, // Vertex ((i, j)) with i from g1, and j from g2 // will have new vertex id: i * vcount2 + j - igraph_integer_t edge_index = 0; + igraph_int_t edge_index = 0; - for (igraph_integer_t i = 0; i < ecount1; ++i) { - igraph_integer_t from1 = IGRAPH_FROM(g1, i); - igraph_integer_t to1 = IGRAPH_TO(g1, i); + for (igraph_int_t i = 0; i < ecount1; ++i) { + igraph_int_t from1 = IGRAPH_FROM(g1, i); + igraph_int_t to1 = IGRAPH_TO(g1, i); - for (igraph_integer_t j = 0; j < ecount2; ++j) { - igraph_integer_t from2 = IGRAPH_FROM(g2, j); - igraph_integer_t to2 = IGRAPH_TO(g2, j); + for (igraph_int_t j = 0; j < ecount2; ++j) { + igraph_int_t from2 = IGRAPH_FROM(g2, j); + igraph_int_t to2 = IGRAPH_TO(g2, j); // Create edge between ((from1, from2)) to ((to1, to2)) VECTOR(edges)[edge_index++] = from1 * vcount2 + from2; // ((from1, from2)) @@ -585,7 +585,7 @@ igraph_error_t igraph_product(igraph_t *res, igraph_error_t igraph_rooted_product(igraph_t *res, const igraph_t *g1, const igraph_t *g2, - const igraph_integer_t root) { + igraph_int_t root) { const igraph_bool_t directed = igraph_is_directed(g1); @@ -594,17 +594,17 @@ igraph_error_t igraph_rooted_product(igraph_t *res, IGRAPH_EINVAL); } - const igraph_integer_t vcount1 = igraph_vcount(g1); - const igraph_integer_t vcount2 = igraph_vcount(g2); + const igraph_int_t vcount1 = igraph_vcount(g1); + const igraph_int_t vcount2 = igraph_vcount(g2); if (root < 0 || root >= vcount2) { // root must be in range [0, vcount2-1] IGRAPH_ERROR("The given root vertex is not present in the second graph.", IGRAPH_EINVVID); } - const igraph_integer_t ecount1 = igraph_ecount(g1); - const igraph_integer_t ecount2 = igraph_ecount(g2); - igraph_integer_t vcount; - igraph_integer_t ecount, ecount_double; + const igraph_int_t ecount1 = igraph_ecount(g1); + const igraph_int_t ecount2 = igraph_ecount(g2); + igraph_int_t vcount; + igraph_int_t ecount, ecount_double; igraph_vector_int_t edges; // New vertex count = vcount1 * vcount2 @@ -620,12 +620,12 @@ igraph_error_t igraph_rooted_product(igraph_t *res, // Vertex ((i, j)) with i from g1, and j from g2 // will have new vertex id: i * vcount2 + j - igraph_integer_t edge_index = 0; + igraph_int_t edge_index = 0; // Edges of form ((u, root)) - ((v, root)) - for (igraph_integer_t i = 0; i < ecount1; ++i) { - igraph_integer_t from = IGRAPH_FROM(g1, i); - igraph_integer_t to = IGRAPH_TO(g1, i); + for (igraph_int_t i = 0; i < ecount1; ++i) { + igraph_int_t from = IGRAPH_FROM(g1, i); + igraph_int_t to = IGRAPH_TO(g1, i); VECTOR(edges)[edge_index++] = from * vcount2 + root; // ((from, root)) VECTOR(edges)[edge_index++] = to * vcount2 + root; // ((to, root)) @@ -633,11 +633,11 @@ igraph_error_t igraph_rooted_product(igraph_t *res, // For all edges (from, to) in g2, add edge from ((j, from)) to ((j, to)) // for all vertex j in g1 - for (igraph_integer_t i = 0; i < ecount2; ++i) { - igraph_integer_t from = IGRAPH_FROM(g2, i); - igraph_integer_t to = IGRAPH_TO(g2, i); + for (igraph_int_t i = 0; i < ecount2; ++i) { + igraph_int_t from = IGRAPH_FROM(g2, i); + igraph_int_t to = IGRAPH_TO(g2, i); - for (igraph_integer_t j = 0; j < vcount1; ++j) { + for (igraph_int_t j = 0; j < vcount1; ++j) { VECTOR(edges)[edge_index++] = j * vcount2 + from; // ((j, from)) VECTOR(edges)[edge_index++] = j * vcount2 + to; // ((j, to)) } diff --git a/src/vendor/cigraph/src/operators/reverse.c b/src/vendor/cigraph/src/operators/reverse.c index 943b03619bf..1fd8e016188 100644 --- a/src/vendor/cigraph/src/operators/reverse.c +++ b/src/vendor/cigraph/src/operators/reverse.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -52,8 +52,8 @@ * O(|E|) where |E| is the number of edges in the graph. */ igraph_error_t igraph_reverse_edges(igraph_t *graph, const igraph_es_t eids) { - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t edges; igraph_eit_t eit; igraph_t new_graph; @@ -78,8 +78,8 @@ igraph_error_t igraph_reverse_edges(igraph_t *graph, const igraph_es_t eids) { IGRAPH_FINALLY(igraph_eit_destroy, &eit); for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t eid = IGRAPH_EIT_GET(eit); - igraph_integer_t tmp = VECTOR(edges)[2*eid]; + igraph_int_t eid = IGRAPH_EIT_GET(eit); + igraph_int_t tmp = VECTOR(edges)[2*eid]; VECTOR(edges)[2*eid] = VECTOR(edges)[2*eid + 1]; VECTOR(edges)[2*eid + 1] = tmp; } diff --git a/src/vendor/cigraph/src/operators/rewire.c b/src/vendor/cigraph/src/operators/rewire.c index 2ce5c874d6a..f964f0457db 100644 --- a/src/vendor/cigraph/src/operators/rewire.c +++ b/src/vendor/cigraph/src/operators/rewire.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -33,15 +33,17 @@ #include "misc/graphicality.h" #include "operators/rewire_internal.h" +#include /* memset */ + /* Threshold that defines when to switch over to using adjacency lists during * rewiring */ #define REWIRE_ADJLIST_THRESHOLD 10 /* Not declared static so that the testsuite can use it, but not part of the public API. */ -igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_bool_t loops, igraph_bool_t use_adjlist) { - const igraph_integer_t no_of_edges = igraph_ecount(graph); +igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_int_t n, igraph_bool_t loops, igraph_bool_t use_adjlist, igraph_rewiring_stats_t *stats) { + const igraph_int_t no_of_edges = igraph_ecount(graph); char message[256]; - igraph_integer_t a, b, c, d, dummy, num_swaps, num_successful_swaps; + igraph_int_t a, b, c, d, dummy, num_swaps, num_successful_swaps; igraph_vector_int_t eids; igraph_vector_int_t edgevec, alledges; const igraph_bool_t directed = igraph_is_directed(graph); @@ -202,6 +204,11 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_bool_ igraph_vector_int_destroy(&eids); IGRAPH_FINALLY_CLEAN(use_adjlist ? 3 : 2); + if (stats) { + memset(stats, 0, sizeof(igraph_rewiring_stats_t)); + stats->successful_swaps = num_successful_swaps; + } + return IGRAPH_SUCCESS; } @@ -226,6 +233,7 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_bool_ * \param graph The graph object to be rewired. * \param n Number of rewiring trials to perform. * \param allowed_edge_types The types of edges that rewiring may create in the graph. + * See \ref igraph_edge_type_sw_t for details. * Currently, the following are implemented: * \clist * \cli IGRAPH_SIMPLE_SW @@ -234,6 +242,8 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_bool_ * single self-loops are allowed, but not multi-edges. * \endclist * Multigraphs are not yet supported. + * \param stats Counts of the number of different operations + * performed by the algorithm are stored here. * * \return Error code: * \clist @@ -245,7 +255,7 @@ igraph_error_t igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_bool_ * * Time complexity: TODO. */ -igraph_error_t igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_edge_type_sw_t allowed_edge_types) { +igraph_error_t igraph_rewire(igraph_t *graph, igraph_int_t n, igraph_edge_type_sw_t allowed_edge_types, igraph_rewiring_stats_t *stats) { igraph_bool_t use_adjlist = n >= REWIRE_ADJLIST_THRESHOLD; if ((allowed_edge_types & IGRAPH_I_MULTI_EDGES_SW) || @@ -253,5 +263,5 @@ igraph_error_t igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_edge_ty IGRAPH_ERROR("Rewiring multigraphs is not yet implemented.", IGRAPH_UNIMPLEMENTED); } - return igraph_i_rewire(graph, n, allowed_edge_types & IGRAPH_LOOPS_SW, use_adjlist); + return igraph_i_rewire(graph, n, allowed_edge_types & IGRAPH_LOOPS_SW, use_adjlist, stats); } diff --git a/src/vendor/cigraph/src/operators/rewire_edges.c b/src/vendor/cigraph/src/operators/rewire_edges.c index 10999288f48..aa7a61b6575 100644 --- a/src/vendor/cigraph/src/operators/rewire_edges.c +++ b/src/vendor/cigraph/src/operators/rewire_edges.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -27,16 +27,17 @@ #include "igraph_random.h" #include "graph/attributes.h" +#include "misc/graphicality.h" static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_real_t prob, igraph_bool_t loops, igraph_vector_int_t *edges) { - igraph_integer_t no_verts = igraph_vcount(graph); - igraph_integer_t no_edges = igraph_ecount(graph); + igraph_int_t no_verts = igraph_vcount(graph); + igraph_int_t no_edges = igraph_ecount(graph); igraph_vector_int_t eorder, tmp; igraph_vector_int_t first, next, prev, marked; - igraph_integer_t i, to_rewire, last_other = -1; + igraph_int_t i, to_rewire, last_other = -1; /* Create our special graph representation */ @@ -61,9 +62,9 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ } while (0) # define MARK_NEIGHBORS(vertex) do { \ - igraph_integer_t xxx_ =VECTOR(first)[(vertex)]; \ + igraph_int_t xxx_ =VECTOR(first)[(vertex)]; \ while (xxx_) { \ - igraph_integer_t o= VECTOR(*edges)[xxx_ % 2 ? xxx_ : xxx_-2]; \ + igraph_int_t o= VECTOR(*edges)[xxx_ % 2 ? xxx_ : xxx_-2]; \ VECTOR(marked)[o]=other+1; \ xxx_=VECTOR(next)[xxx_-1]; \ } \ @@ -79,9 +80,9 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ IGRAPH_VECTOR_INT_INIT_FINALLY(&eorder, no_edges); IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, no_edges); for (i = 0; i < no_edges; i++) { - igraph_integer_t idx1 = 2 * i, idx2 = idx1 + 1; - igraph_integer_t from = VECTOR(*edges)[idx1]; - igraph_integer_t to = VECTOR(*edges)[idx2]; + igraph_int_t idx1 = 2 * i, idx2 = idx1 + 1; + igraph_int_t from = VECTOR(*edges)[idx1]; + igraph_int_t to = VECTOR(*edges)[idx2]; VECTOR(tmp)[i] = from; ADD_STUB(from, idx1); ADD_STUB(to, idx2); @@ -95,13 +96,13 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ /* Rewire the stubs, part I */ - to_rewire = (igraph_integer_t) RNG_GEOM(prob); + to_rewire = (igraph_int_t) RNG_GEOM(prob); while (to_rewire < no_edges) { - igraph_integer_t stub = 2 * VECTOR(eorder)[to_rewire] + 1; - igraph_integer_t v = VECTOR(*edges)[stub]; - igraph_integer_t ostub = stub - 1; - igraph_integer_t other = VECTOR(*edges)[ostub]; - igraph_integer_t pot; + igraph_int_t stub = 2 * VECTOR(eorder)[to_rewire] + 1; + igraph_int_t v = VECTOR(*edges)[stub]; + igraph_int_t ostub = stub - 1; + igraph_int_t other = VECTOR(*edges)[ostub]; + igraph_int_t pot; if (last_other != other) { MARK_NEIGHBORS(other); } @@ -142,13 +143,13 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ igraph_vector_int_null(&marked); last_other = -1; - to_rewire = (igraph_integer_t) RNG_GEOM(prob); + to_rewire = (igraph_int_t) RNG_GEOM(prob); while (to_rewire < no_edges) { - igraph_integer_t stub = (2 * VECTOR(eorder)[to_rewire]); - igraph_integer_t v = VECTOR(*edges)[stub]; - igraph_integer_t ostub = stub + 1; - igraph_integer_t other = VECTOR(*edges)[ostub]; - igraph_integer_t pot; + igraph_int_t stub = (2 * VECTOR(eorder)[to_rewire]); + igraph_int_t v = VECTOR(*edges)[stub]; + igraph_int_t ostub = stub + 1; + igraph_int_t other = VECTOR(*edges)[ostub]; + igraph_int_t pot; if (last_other != other) { MARK_NEIGHBORS(other); } @@ -203,10 +204,8 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ * directed or undirected. * \param prob The rewiring probability a constant between zero and * one (inclusive). - * \param loops Boolean, whether loop edges are allowed in the new - * graph, or not. - * \param multiple Boolean, whether multiple edges are allowed in the - * new graph. + * \param allowed_edge_types Controls whether multi-edges and self-loops + * are allowed in the new graph. See \ref igraph_edge_type_sw_t. * \return Error code. * * \sa \ref igraph_watts_strogatz_game() uses this function for the @@ -215,14 +214,17 @@ static igraph_error_t igraph_i_rewire_edges_no_multiple(igraph_t *graph, igraph_ * Time complexity: O(|V|+|E|). */ igraph_error_t igraph_rewire_edges(igraph_t *graph, igraph_real_t prob, - igraph_bool_t loops, igraph_bool_t multiple) { + igraph_edge_type_sw_t allowed_edge_types) { igraph_t newgraph; - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t endpoints = no_of_edges * 2; - igraph_integer_t to_rewire; + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t endpoints = no_of_edges * 2; + igraph_int_t to_rewire; igraph_vector_int_t edges; + igraph_bool_t loops, multiple; + + IGRAPH_CHECK(igraph_i_edge_type_to_loops_multiple(allowed_edge_types, &loops, &multiple)); if (prob < 0 || prob > 1) { IGRAPH_ERROR("Rewiring probability should be between zero and one", @@ -248,9 +250,9 @@ igraph_error_t igraph_rewire_edges(igraph_t *graph, igraph_real_t prob, if (loops) { VECTOR(edges)[to_rewire] = RNG_INTEGER(0, no_of_nodes - 1); } else { - igraph_integer_t opos = to_rewire % 2 ? to_rewire - 1 : to_rewire + 1; - igraph_integer_t nei = VECTOR(edges)[opos]; - igraph_integer_t r = RNG_INTEGER(0, no_of_nodes - 2); + igraph_int_t opos = to_rewire % 2 ? to_rewire - 1 : to_rewire + 1; + igraph_int_t nei = VECTOR(edges)[opos]; + igraph_int_t r = RNG_INTEGER(0, no_of_nodes - 2); VECTOR(edges)[ to_rewire ] = (r != nei ? r : no_of_nodes - 1); } to_rewire += RNG_GEOM(prob) + 1; @@ -331,10 +333,10 @@ igraph_error_t igraph_rewire_directed_edges(igraph_t *graph, igraph_real_t prob, if (igraph_is_directed(graph) && mode != IGRAPH_ALL) { igraph_t newgraph; - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t to_rewire; - igraph_integer_t offset = 0; + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t to_rewire; + igraph_int_t offset = 0; igraph_vector_int_t edges; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 2 * no_of_edges); @@ -357,8 +359,8 @@ igraph_error_t igraph_rewire_directed_edges(igraph_t *graph, igraph_real_t prob, if (loops) { VECTOR(edges)[2 * to_rewire + offset] = RNG_INTEGER(0, no_of_nodes - 1); } else { - igraph_integer_t nei = VECTOR(edges)[2 * to_rewire + (1 - offset)]; - igraph_integer_t r = RNG_INTEGER(0, no_of_nodes - 2); + igraph_int_t nei = VECTOR(edges)[2 * to_rewire + (1 - offset)]; + igraph_int_t r = RNG_INTEGER(0, no_of_nodes - 2); VECTOR(edges)[2 * to_rewire + offset] = (r != nei ? r : no_of_nodes - 1); } to_rewire += RNG_GEOM(prob) + 1; @@ -376,7 +378,7 @@ igraph_error_t igraph_rewire_directed_edges(igraph_t *graph, igraph_real_t prob, *graph = newgraph; } else { - IGRAPH_CHECK(igraph_rewire_edges(graph, prob, loops, /* multiple = */ 1)); + IGRAPH_CHECK(igraph_rewire_edges(graph, prob, IGRAPH_MULTI_SW | (loops ? IGRAPH_LOOPS_SW : IGRAPH_SIMPLE_SW))); } return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/operators/rewire_internal.h b/src/vendor/cigraph/src/operators/rewire_internal.h index 5308b121daf..145a79bdc26 100644 --- a/src/vendor/cigraph/src/operators/rewire_internal.h +++ b/src/vendor/cigraph/src/operators/rewire_internal.h @@ -9,8 +9,8 @@ IGRAPH_BEGIN_C_DECLS IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_i_rewire( - igraph_t *graph, igraph_integer_t n, igraph_bool_t loops, - igraph_bool_t use_adjlist); + igraph_t *graph, igraph_int_t n, igraph_bool_t loops, + igraph_bool_t use_adjlist, igraph_rewiring_stats_t *stats); IGRAPH_END_C_DECLS diff --git a/src/vendor/cigraph/src/operators/simplify.c b/src/vendor/cigraph/src/operators/simplify.c index 1851a11b4dd..06257c862d2 100644 --- a/src/vendor/cigraph/src/operators/simplify.c +++ b/src/vendor/cigraph/src/operators/simplify.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -56,16 +56,16 @@ igraph_error_t igraph_simplify(igraph_t *graph, const igraph_attribute_combination_t *edge_comb) { igraph_vector_int_t edges; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t edge; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t edge; igraph_bool_t attr = edge_comb && igraph_has_attribute_table(); - igraph_integer_t from, to, pfrom = -1, pto = -2; + igraph_int_t from, to, pfrom = -1, pto = -2; igraph_t res; igraph_es_t es; igraph_eit_t eit; igraph_vector_int_t mergeinto; - igraph_integer_t actedge; + igraph_int_t actedge; /* if we already know there are no multi-edges, they don't need to be removed */ if (igraph_i_property_cache_has(graph, IGRAPH_PROP_HAS_MULTI) && diff --git a/src/vendor/cigraph/src/operators/subgraph.c b/src/vendor/cigraph/src/operators/subgraph.c index 8f6a4450c37..d164755ac7c 100644 --- a/src/vendor/cigraph/src/operators/subgraph.c +++ b/src/vendor/cigraph/src/operators/subgraph.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,8 +35,8 @@ static igraph_error_t igraph_i_induced_subgraph_copy_and_delete( const igraph_t *graph, igraph_t *res, const igraph_vs_t vids, igraph_vector_int_t *map, igraph_vector_int_t *invmap) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_new_nodes_estimate; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_new_nodes_estimate; igraph_vector_int_t delete; igraph_bitset_t remain; igraph_vit_t vit; @@ -60,7 +60,7 @@ static igraph_error_t igraph_i_induced_subgraph_copy_and_delete( IGRAPH_BIT_SET(remain, IGRAPH_VIT_GET(vit)); } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_ALLOW_INTERRUPTION(); if (! IGRAPH_BIT_TEST(remain, i)) { @@ -99,11 +99,11 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( igraph_bool_t map_is_prepared) { const igraph_bool_t directed = igraph_is_directed(graph); - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_new_nodes = 0; - igraph_integer_t n; - igraph_integer_t to; - igraph_integer_t eid; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_new_nodes = 0; + igraph_int_t n; + igraph_int_t to; + igraph_int_t eid; igraph_vector_int_t vids_old2new, vids_new2old; igraph_vector_int_t eids_new2old; igraph_vector_int_t vids_vec; @@ -153,8 +153,8 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( igraph_vector_int_sort(&vids_vec); n = igraph_vector_int_size(&vids_vec); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t vid = VECTOR(vids_vec)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t vid = VECTOR(vids_vec)[i]; /* Cater for duplicate vertex IDs in the input vertex selector; we use * the first occurrence of each vertex ID and ignore the rest */ @@ -168,9 +168,9 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( IGRAPH_FINALLY_CLEAN(1); /* Create the new edge list */ - for (igraph_integer_t i = 0; i < no_of_new_nodes; i++) { - igraph_integer_t old_vid = VECTOR(*my_vids_new2old)[i]; - igraph_integer_t new_vid = i; + for (igraph_int_t i = 0; i < no_of_new_nodes; i++) { + igraph_int_t old_vid = VECTOR(*my_vids_new2old)[i]; + igraph_int_t new_vid = i; igraph_bool_t skip_loop_edge; IGRAPH_CHECK(igraph_incident(graph, &nei_edges, old_vid, IGRAPH_OUT, IGRAPH_LOOPS)); @@ -178,7 +178,7 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( if (directed) { /* directed graph; this is easier */ - for (igraph_integer_t j = 0; j < n; j++) { + for (igraph_int_t j = 0; j < n; j++) { eid = VECTOR(nei_edges)[j]; to = VECTOR(*my_vids_old2new)[ IGRAPH_TO(graph, eid) ]; @@ -195,7 +195,7 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( * loop edge will appear twice. We use a boolean flag to skip every * second loop edge */ skip_loop_edge = false; - for (igraph_integer_t j = 0; j < n; j++) { + for (igraph_int_t j = 0; j < n; j++) { eid = VECTOR(nei_edges)[j]; if (IGRAPH_FROM(graph, eid) != old_vid) { @@ -326,7 +326,7 @@ static igraph_error_t igraph_i_induced_subgraph_suggest_implementation( const igraph_t *graph, const igraph_vs_t vids, igraph_subgraph_implementation_t *result) { double ratio; - igraph_integer_t num_vs; + igraph_int_t num_vs; if (igraph_vs_is_all(&vids)) { ratio = 1.0; @@ -476,13 +476,13 @@ igraph_error_t igraph_induced_subgraph_edges(const igraph_t *graph, igraph_vs_t IGRAPH_VECTOR_INT_INIT_FINALLY(&incedges, 0); for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { - igraph_integer_t v = IGRAPH_VIT_GET(vit); + igraph_int_t v = IGRAPH_VIT_GET(vit); IGRAPH_CHECK(igraph_incident(graph, &incedges, v, IGRAPH_ALL, IGRAPH_LOOPS_ONCE)); - igraph_integer_t d = igraph_vector_int_size(&incedges); - for (igraph_integer_t i=0; i < d; i++) { - igraph_integer_t e = VECTOR(incedges)[i]; - igraph_integer_t u = IGRAPH_OTHER(graph, e, v); + igraph_int_t d = igraph_vector_int_size(&incedges); + for (igraph_int_t i=0; i < d; i++) { + igraph_int_t e = VECTOR(incedges)[i]; + igraph_int_t u = IGRAPH_OTHER(graph, e, v); /* The v <= u check avoids adding non-loop edges twice. * Loop edges only appear once due to the use of * IGRAPH_LOOPS_ONCE in igraph_incident() */ @@ -538,9 +538,9 @@ igraph_error_t igraph_subgraph_from_edges( igraph_bool_t delete_vertices ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_edges_to_delete_estimate; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges_to_delete_estimate; igraph_vector_int_t delete = IGRAPH_VECTOR_NULL; igraph_bitset_t vremain, eremain; igraph_eit_t eit; @@ -563,8 +563,8 @@ igraph_error_t igraph_subgraph_from_edges( /* Collect the vertex and edge IDs that will remain */ for (IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t eid = IGRAPH_EIT_GET(eit); - igraph_integer_t from = IGRAPH_FROM(graph, eid), to = IGRAPH_TO(graph, eid); + igraph_int_t eid = IGRAPH_EIT_GET(eit); + igraph_int_t from = IGRAPH_FROM(graph, eid), to = IGRAPH_TO(graph, eid); IGRAPH_BIT_SET(eremain, eid); IGRAPH_BIT_SET(vremain, from); IGRAPH_BIT_SET(vremain, to); @@ -574,7 +574,7 @@ igraph_error_t igraph_subgraph_from_edges( IGRAPH_FINALLY_CLEAN(1); /* Collect the edge IDs to be deleted */ - for (igraph_integer_t i = 0; i < no_of_edges; i++) { + for (igraph_int_t i = 0; i < no_of_edges; i++) { IGRAPH_ALLOW_INTERRUPTION(); if (! IGRAPH_BIT_TEST(eremain, i)) { IGRAPH_CHECK(igraph_vector_int_push_back(&delete, i)); @@ -592,7 +592,7 @@ igraph_error_t igraph_subgraph_from_edges( if (delete_vertices) { /* Collect the vertex IDs to be deleted */ igraph_vector_int_clear(&delete); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { IGRAPH_ALLOW_INTERRUPTION(); if (! IGRAPH_BIT_TEST(vremain, i)) { IGRAPH_CHECK(igraph_vector_int_push_back(&delete, i)); diff --git a/src/vendor/cigraph/src/operators/subgraph.h b/src/vendor/cigraph/src/operators/subgraph.h index ec954d0a671..bc17c96fe6d 100644 --- a/src/vendor/cigraph/src/operators/subgraph.h +++ b/src/vendor/cigraph/src/operators/subgraph.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2003-2021 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/operators/union.c b/src/vendor/cigraph/src/operators/union.c index d106200f036..29392a2230e 100644 --- a/src/vendor/cigraph/src/operators/union.c +++ b/src/vendor/cigraph/src/operators/union.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -118,14 +118,14 @@ igraph_error_t igraph_union_many( igraph_vector_int_list_t *edgemaps ) { - igraph_integer_t no_of_graphs = igraph_vector_ptr_size(graphs); - igraph_integer_t no_of_nodes = 0; + igraph_int_t no_of_graphs = igraph_vector_ptr_size(graphs); + igraph_int_t no_of_nodes = 0; igraph_bool_t directed = true; igraph_vector_int_t edges; igraph_vector_int_list_t edge_vects, order_vects; igraph_vector_int_t no_edges; - igraph_integer_t i, j, tailfrom = no_of_graphs > 0 ? 0 : -1, tailto = -1; - igraph_integer_t idx = 0; + igraph_int_t i, j, tailfrom = no_of_graphs > 0 ? 0 : -1, tailto = -1; + igraph_int_t idx = 0; /* Check directedness */ if (no_of_graphs != 0) { @@ -145,7 +145,7 @@ igraph_error_t igraph_union_many( /* Calculate number of nodes, query number of edges */ for (i = 0; i < no_of_graphs; i++) { - igraph_integer_t n = igraph_vcount(VECTOR(*graphs)[i]); + igraph_int_t n = igraph_vcount(VECTOR(*graphs)[i]); if (n > no_of_nodes) { no_of_nodes = n; } @@ -166,14 +166,14 @@ igraph_error_t igraph_union_many( /* Query and sort the edge lists */ for (i = 0; i < no_of_graphs; i++) { - igraph_integer_t k, j, n = VECTOR(no_edges)[i]; + igraph_int_t k, j, n = VECTOR(no_edges)[i]; igraph_vector_int_t *ev = igraph_vector_int_list_get_ptr(&edge_vects, i); igraph_vector_int_t *order = igraph_vector_int_list_get_ptr(&order_vects, i); IGRAPH_CHECK(igraph_get_edgelist(VECTOR(*graphs)[i], ev, /*bycol=*/ false)); if (!directed) { for (k = 0, j = 0; k < n; k++, j += 2) { if (VECTOR(*ev)[j] > VECTOR(*ev)[j + 1]) { - igraph_integer_t tmp = VECTOR(*ev)[j]; + igraph_int_t tmp = VECTOR(*ev)[j]; VECTOR(*ev)[j] = VECTOR(*ev)[j + 1]; VECTOR(*ev)[j + 1] = tmp; } @@ -195,9 +195,9 @@ igraph_error_t igraph_union_many( igraph_vector_int_t *order = igraph_vector_int_list_get_ptr(&order_vects, j); if (!igraph_vector_int_empty(order)) { igraph_vector_int_t *ev = igraph_vector_int_list_get_ptr(&edge_vects, j); - igraph_integer_t edge = igraph_vector_int_tail(order); - igraph_integer_t from = VECTOR(*ev)[2 * edge]; - igraph_integer_t to = VECTOR(*ev)[2 * edge + 1]; + igraph_int_t edge = igraph_vector_int_tail(order); + igraph_int_t from = VECTOR(*ev)[2 * edge]; + igraph_int_t to = VECTOR(*ev)[2 * edge + 1]; if (from > tailfrom || (from == tailfrom && to > tailto)) { tailfrom = from; tailto = to; } @@ -216,9 +216,9 @@ igraph_error_t igraph_union_many( igraph_vector_int_t *order = igraph_vector_int_list_get_ptr(&order_vects, j); if (!igraph_vector_int_empty(order)) { igraph_vector_int_t *ev = igraph_vector_int_list_get_ptr(&edge_vects, j); - igraph_integer_t edge = igraph_vector_int_tail(order); - igraph_integer_t from = VECTOR(*ev)[2 * edge]; - igraph_integer_t to = VECTOR(*ev)[2 * edge + 1]; + igraph_int_t edge = igraph_vector_int_tail(order); + igraph_int_t from = VECTOR(*ev)[2 * edge]; + igraph_int_t to = VECTOR(*ev)[2 * edge + 1]; if (from == tailfrom && to == tailto) { igraph_vector_int_pop_back(order); if (edgemaps) { diff --git a/src/vendor/cigraph/src/paths/all_shortest_paths.c b/src/vendor/cigraph/src/paths/all_shortest_paths.c index ee0df71bf7f..1b53bdb7bf2 100644 --- a/src/vendor/cigraph/src/paths/all_shortest_paths.c +++ b/src/vendor/cigraph/src/paths/all_shortest_paths.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2005-2021 The igraph development team + igraph library. + Copyright (C) 2005-2025 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 @@ -13,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #include "igraph_paths.h" @@ -26,15 +23,10 @@ #include "igraph_memory.h" #include "core/interruption.h" +#include "paths/paths_internal.h" #include /* memset */ -static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( - const igraph_t *graph, igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, igraph_vector_int_t *nrgeo, - igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode -); - /** * \function igraph_get_all_shortest_paths * \brief All shortest paths (geodesics) from a vertex. @@ -98,13 +90,15 @@ static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( * Time complexity: O(|V|+|E|) for most graphs, O(|V|^2) in the worst * case. */ - igraph_error_t igraph_get_all_shortest_paths( - const igraph_t *graph, const igraph_vector_t *weights, - igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_vector_int_t *nrgeo, - igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode -) { + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_vector_int_t *nrgeo, + igraph_int_t from, const igraph_vs_t to, + igraph_neimode_t mode) { + if (weights == NULL) { /* Unweighted version */ return igraph_i_get_all_shortest_paths_unweighted( @@ -118,13 +112,16 @@ igraph_error_t igraph_get_all_shortest_paths( } } -static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( - const igraph_t *graph, igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, igraph_vector_int_t *nrgeo, - igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode -) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t *geodist; +igraph_error_t igraph_i_get_all_shortest_paths_unweighted( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_vector_int_t *nrgeo, + igraph_int_t from, const igraph_vs_t to, + igraph_neimode_t mode) { + + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t *geodist; igraph_vector_int_list_t paths; igraph_vector_int_list_t path_edge; igraph_dqueue_int_t q; @@ -133,8 +130,8 @@ static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( igraph_vector_int_t neis; igraph_vector_int_t ptrlist; igraph_vector_int_t ptrhead; - igraph_integer_t n; - igraph_integer_t to_reach, reached = 0, maxdist = 0; + igraph_int_t n; + igraph_int_t to_reach, reached = 0, maxdist = 0; igraph_vit_t vit; @@ -170,7 +167,7 @@ static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( * is in the target vertex sequence. Otherwise it is * one larger than the length of the shortest path from the * source */ - geodist = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + geodist = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(geodist, "Insufficient memory for calculating shortest paths."); IGRAPH_FINALLY(igraph_free, geodist); /* dequeue to store the BFS queue -- odd elements are the vertex indices, @@ -212,8 +209,8 @@ static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( IGRAPH_CHECK(igraph_dqueue_int_push(&q, from)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); IGRAPH_ALLOW_INTERRUPTION(); @@ -240,9 +237,9 @@ static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( } n = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t neighbor; - igraph_integer_t parentptr; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t neighbor; + igraph_int_t parentptr; if (edges) { /* user needs the edge-paths, so 'neis' contains edge IDs, we need to resolve @@ -318,8 +315,8 @@ static igraph_error_t igraph_i_get_all_shortest_paths_unweighted( igraph_vector_int_list_clear(edges); } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t parentptr = VECTOR(ptrhead)[i]; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t parentptr = VECTOR(ptrhead)[i]; IGRAPH_ALLOW_INTERRUPTION(); diff --git a/src/vendor/cigraph/src/paths/astar.c b/src/vendor/cigraph/src/paths/astar.c index 4fcdfb0acf6..2913b7634cc 100644 --- a/src/vendor/cigraph/src/paths/astar.c +++ b/src/vendor/cigraph/src/paths/astar.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ #include "core/interruption.h" static igraph_error_t null_heuristic( - igraph_real_t *result, igraph_integer_t from, igraph_integer_t to, + igraph_real_t *result, igraph_int_t from, igraph_int_t to, void *extra ) { IGRAPH_UNUSED(from); @@ -93,8 +93,8 @@ static igraph_error_t null_heuristic( igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode, igraph_astar_heuristic_func_t *heuristic, @@ -102,12 +102,12 @@ igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph, { igraph_real_t heur_res; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_2wheap_t Q; igraph_lazy_inclist_t inclist; igraph_vector_t dists; - igraph_integer_t *parent_eids; + igraph_int_t *parent_eids; if (from < 0 || from >= no_of_nodes) { IGRAPH_ERROR("Starting vertex out of range.", IGRAPH_EINVVID); @@ -148,7 +148,7 @@ igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph, /* parent_eids[v] is the 1 + the ID of v's inbound edge in the shortest path tree. * A value of 0 indicates unreachable vertices. */ - parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(parent_eids, "Insufficient memory for shortest paths with A* algorithm."); IGRAPH_FINALLY(igraph_free, parent_eids); @@ -170,7 +170,7 @@ igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph, * in order to obtain smallest values first. The value taken off * the heap is ignored, we just want the index of 'u'. */ - igraph_integer_t u; + igraph_int_t u; igraph_2wheap_delete_max_index(&Q, &u); /* Reached the target vertex, the search can be stopped. */ @@ -185,10 +185,10 @@ igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph, igraph_vector_int_t *neis = igraph_lazy_inclist_get(&inclist, u); IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); - igraph_integer_t nlen = igraph_vector_int_size(neis); - for (igraph_integer_t i = 0; i < nlen; i++) { - igraph_integer_t edge = VECTOR(*neis)[i]; - igraph_integer_t v = IGRAPH_OTHER(graph, edge, u); + igraph_int_t nlen = igraph_vector_int_size(neis); + for (igraph_int_t i = 0; i < nlen; i++) { + igraph_int_t edge = VECTOR(*neis)[i]; + igraph_int_t v = IGRAPH_OTHER(graph, edge, u); igraph_real_t altdist; /* candidate from -> v distance */ if (weights) { igraph_real_t weight = VECTOR(*weights)[edge]; @@ -223,7 +223,7 @@ igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph, /* Reconstruct the shortest paths based on vertex and/or edge IDs */ if (vertices || edges) { - igraph_integer_t size, act, edge; + igraph_int_t size, act, edge; if (vertices) { igraph_vector_int_clear(vertices); diff --git a/src/vendor/cigraph/src/paths/bellman_ford.c b/src/vendor/cigraph/src/paths/bellman_ford.c index b0ff4a7d905..3ff84e40049 100644 --- a/src/vendor/cigraph/src/paths/bellman_ford.c +++ b/src/vendor/cigraph/src/paths/bellman_ford.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2005-2021 The igraph development team + igraph library. + Copyright (C) 2005-2025 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 @@ -25,6 +25,7 @@ #include "igraph_memory.h" #include "core/interruption.h" +#include "paths/paths_internal.h" /** * \function igraph_distances_bellman_ford @@ -43,10 +44,10 @@ * vertices the matrix contains \c IGRAPH_INFINITY. * \param from The source vertices. * \param to The target vertices. - * \param weights The edge weights. There must not be any closed loop in + * \param weights The edge weights. There must not be any cycle in * the graph that has a negative total weight (since this would allow * us to decrease the weight of any path containing at least a single - * vertex of this loop infinitely). Additionally, no edge weight may + * vertex of this cycle infinitely). Additionally, no edge weight may * be NaN. If either case does not hold, an error is returned. If this * is a null pointer, then the unweighted version, * \ref igraph_distances() is called. @@ -59,50 +60,56 @@ * Time complexity: O(s*|E|*|V|), where |V| is the number of * vertices, |E| the number of edges and s the number of sources. * - * \sa \ref igraph_distances() for a faster unweighted version - * or \ref igraph_distances_dijkstra() if you do not have negative + * \sa \ref igraph_distances() for a non-algorithm-specific interface; + * \ref igraph_distances_dijkstra() if you do not have negative * edge weights. * * \example examples/simple/bellman_ford.c */ -igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - 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); +igraph_error_t igraph_distances_bellman_ford( + const igraph_t *graph, + igraph_matrix_t *res, + const igraph_vs_t from, + const igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode) { + + igraph_bool_t negative_weights; + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + return igraph_i_distances_bellman_ford(graph, res, from, to, weights, mode); +} + +igraph_error_t igraph_i_distances_bellman_ford( + const igraph_t *graph, + igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode) { + + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_lazy_inclist_t inclist; - igraph_integer_t i; - igraph_integer_t no_of_from, no_of_to; + igraph_int_t i; + igraph_int_t no_of_from, no_of_to; igraph_dqueue_int_t Q; igraph_bitset_t clean_vertices; igraph_vector_int_t num_queued; igraph_vit_t fromvit, tovit; igraph_bool_t all_to; igraph_vector_t dist; - int counter = 0; + int iter = 0; /* - speedup: a vertex is marked clean if its distance from the source did not change during the last phase. Neighbors of a clean vertex are not relaxed again, since it would mean no change in the - shortest path values. Dirty vertices are queued. Negative loops can + shortest path values. Dirty vertices are queued. Negative cycles can be detected by checking whether a vertex has been queued at least n times. */ - if (!weights) { - return igraph_distances(graph, NULL, res, from, to, mode); - } - if (igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", - IGRAPH_EINVAL, - igraph_vector_size(weights), no_of_edges); - } - if (igraph_vector_is_any_nan(weights)) { - IGRAPH_ERROR("Weight vector must not contain NaN values.", IGRAPH_EINVAL); + if (!weights || no_of_edges == 0) { + return igraph_i_distances_unweighted_cutoff(graph, res, from, to, mode, -1); } IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit)); @@ -135,7 +142,7 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, for (IGRAPH_VIT_RESET(fromvit), i = 0; !IGRAPH_VIT_END(fromvit); IGRAPH_VIT_NEXT(fromvit), i++) { - igraph_integer_t source = IGRAPH_VIT_GET(fromvit); + igraph_int_t source = IGRAPH_VIT_GET(fromvit); igraph_vector_fill(&dist, IGRAPH_INFINITY); VECTOR(dist)[source] = 0; @@ -143,22 +150,19 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, igraph_vector_int_null(&num_queued); /* Fill the queue with vertices to be checked */ - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { IGRAPH_CHECK(igraph_dqueue_int_push(&Q, j)); } while (!igraph_dqueue_int_empty(&Q)) { - if (++counter >= 10000) { - counter = 0; - IGRAPH_ALLOW_INTERRUPTION(); - } + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 13); - igraph_integer_t j = igraph_dqueue_int_pop(&Q); + igraph_int_t j = igraph_dqueue_int_pop(&Q); IGRAPH_BIT_SET(clean_vertices, j); VECTOR(num_queued)[j] += 1; if (VECTOR(num_queued)[j] > no_of_nodes) { - IGRAPH_ERROR("Negative loop in graph while calculating distances with Bellman-Ford algorithm.", - IGRAPH_ENEGLOOP); + IGRAPH_ERROR("Negative cycle in graph while calculating distances with Bellman-Ford algorithm.", + IGRAPH_ENEGCYCLE); } /* If we cannot get to j in finite time yet, there is no need to relax @@ -170,10 +174,10 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, igraph_vector_int_t *neis = igraph_lazy_inclist_get(&inclist, j); IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); - igraph_integer_t nlen = igraph_vector_int_size(neis); - for (igraph_integer_t k = 0; k < nlen; k++) { - igraph_integer_t nei = VECTOR(*neis)[k]; - igraph_integer_t target = IGRAPH_OTHER(graph, nei, j); + igraph_int_t nlen = igraph_vector_int_size(neis); + for (igraph_int_t k = 0; k < nlen; k++) { + igraph_int_t nei = VECTOR(*neis)[k]; + igraph_int_t target = IGRAPH_OTHER(graph, nei, j); igraph_real_t altdist = VECTOR(dist)[j] + VECTOR(*weights)[nei]; if (VECTOR(dist)[target] > altdist) { /* relax the edge */ @@ -188,12 +192,12 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, /* Copy it to the result */ if (all_to) { - igraph_matrix_set_row(res, &dist, i); + IGRAPH_CHECK(igraph_matrix_set_row(res, &dist, i)); } else { - igraph_integer_t j; + igraph_int_t j; for (IGRAPH_VIT_RESET(tovit), j = 0; !IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit), j++) { - igraph_integer_t v = IGRAPH_VIT_GET(tovit); + igraph_int_t v = IGRAPH_VIT_GET(tovit); MATRIX(*res, i, j) = VECTOR(dist)[v]; } } @@ -243,10 +247,10 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, * \param to Vertex sequence with the IDs of the vertices to/from which the * shortest paths will be calculated. A vertex might be given multiple * times. - * \param weights The edge weights. There must not be any closed loop in + * \param weights The edge weights. There must not be any cycle in * the graph that has a negative total weight (since this would allow * us to decrease the weight of any path containing at least a single - * vertex of this loop infinitely). If this is a null pointer, then the + * vertex of this cycle infinitely). If this is a null pointer, then the * unweighted version, \ref igraph_get_shortest_paths() is called. * Edges with positive infinite weights are ignored. * \param mode For directed graphs; whether to follow paths along edge @@ -278,8 +282,8 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, * The weight vector doesn't math the number of edges. * \cli IGRAPH_EINVVID * \p from is invalid vertex ID - * \cli IGRAPH_ENEGLOOP - * Bellman-ford algorithm encounted a negative loop. + * \cli IGRAPH_ENEGCYCLE + * Bellman-ford algorithm encounted a negative cycle. * \endclist * * Time complexity: O(|E|*|V|), where |V| is the number of @@ -287,44 +291,54 @@ igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph, * * \sa \ref igraph_distances_bellman_ford() to compute only shortest path * lengths, but not the paths themselves; \ref igraph_get_shortest_paths() for - * a faster unweighted version or \ref igraph_get_shortest_paths_dijkstra() - * if you do not have negative edge weights. + * a non-algorithm-specific interface. */ +igraph_error_t igraph_get_shortest_paths_bellman_ford( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, + igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges) { + + igraph_bool_t negative_weights; + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + return igraph_i_get_shortest_paths_bellman_ford(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); +} -igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, - igraph_integer_t from, - igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode, - igraph_vector_int_t *parents, - igraph_vector_int_t *inbound_edges) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t *parent_eids; +igraph_error_t igraph_i_get_shortest_paths_bellman_ford( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, + igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges) { + + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t *parent_eids; igraph_lazy_inclist_t inclist; - igraph_integer_t i, j, k; + igraph_int_t i, j, k; igraph_dqueue_int_t Q; igraph_bitset_t clean_vertices; igraph_vector_int_t num_queued; igraph_vit_t tovit; igraph_vector_t dist; - int counter = 0; + int iter = 0; if (!weights) { - return igraph_get_shortest_paths(graph, NULL, vertices, edges, from, to, mode, - parents, inbound_edges); + return igraph_i_get_shortest_paths_unweighted(graph, vertices, edges, from, to, mode, parents, inbound_edges); } if (from < 0 || from >= no_of_nodes) { IGRAPH_ERROR("Index of source vertex is out of range.", IGRAPH_EINVVID); } - if (igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERROR("Weight vector length must match number of edges.", IGRAPH_EINVAL); - } - IGRAPH_DQUEUE_INT_INIT_FINALLY(&Q, no_of_nodes); IGRAPH_BITSET_INIT_FINALLY(&clean_vertices, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&num_queued, no_of_nodes); @@ -341,7 +355,7 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_list_resize(edges, IGRAPH_VIT_SIZE(tovit))); } - parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(parent_eids, "Insufficient memory for shortest paths with Bellman-Ford."); IGRAPH_FINALLY(igraph_free, parent_eids); @@ -356,17 +370,14 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, } while (!igraph_dqueue_int_empty(&Q)) { - if (++counter >= 10000) { - counter = 0; - IGRAPH_ALLOW_INTERRUPTION(); - } + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 13); j = igraph_dqueue_int_pop(&Q); IGRAPH_BIT_SET(clean_vertices, j); VECTOR(num_queued)[j] += 1; if (VECTOR(num_queued)[j] > no_of_nodes) { - IGRAPH_ERROR("Negative loop in graph while calculating distances with Bellman-Ford algorithm.", - IGRAPH_ENEGLOOP); + IGRAPH_ERROR("Negative cycle in graph while calculating distances with Bellman-Ford algorithm.", + IGRAPH_ENEGCYCLE); } /* If we cannot get to j in finite time yet, there is no need to relax its edges */ @@ -377,17 +388,13 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, igraph_vector_int_t *neis = igraph_lazy_inclist_get(&inclist, j); IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); - igraph_integer_t nlen = igraph_vector_int_size(neis); + igraph_int_t nlen = igraph_vector_int_size(neis); for (k = 0; k < nlen; k++) { - igraph_integer_t nei = VECTOR(*neis)[k]; - igraph_integer_t target = IGRAPH_OTHER(graph, nei, j); + igraph_int_t nei = VECTOR(*neis)[k]; + igraph_int_t target = IGRAPH_OTHER(graph, nei, j); igraph_real_t weight = VECTOR(*weights)[nei]; igraph_real_t altdist = VECTOR(dist)[j] + weight; - if (isnan(weight)) { - IGRAPH_ERROR("Weight vector must not contain NaN values.", IGRAPH_EINVAL); - } - /* infinite weights are handled correctly here; if an edge has * infinite weight, altdist will also be infinite so the condition * will never be true as if the edge was ignored */ @@ -440,8 +447,8 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, /* Reconstruct the shortest paths based on vertex and/or edge IDs */ if (vertices || edges) { for (IGRAPH_VIT_RESET(tovit), i = 0; !IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit), i++) { - igraph_integer_t node = IGRAPH_VIT_GET(tovit); - igraph_integer_t size, act, edge; + igraph_int_t node = IGRAPH_VIT_GET(tovit); + igraph_int_t size, act, edge; igraph_vector_int_t *vvec = 0, *evec = 0; if (vertices) { vvec = igraph_vector_int_list_get_ptr(vertices, i); @@ -520,10 +527,10 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, * path are stored here. * \param from The ID of the source vertex. * \param to The ID of the target vertex. - * \param weights The edge weights. There must not be any closed loop in + * \param weights The edge weights. There must not be any cycle in * the graph that has a negative total weight (since this would allow * us to decrease the weight of any path containing at least a single - * vertex of this loop infinitely). If this is a null pointer, then the + * vertex of this cycle infinitely). If this is a null pointer, then the * unweighted version is called. * \param mode A constant specifying how edge directions are * considered in directed graphs. \c IGRAPH_OUT follows edge @@ -542,8 +549,8 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph, igraph_error_t igraph_get_shortest_path_bellman_ford(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode) { diff --git a/src/vendor/cigraph/src/paths/dijkstra.c b/src/vendor/cigraph/src/paths/dijkstra.c index c3f56de66f9..a6960481021 100644 --- a/src/vendor/cigraph/src/paths/dijkstra.c +++ b/src/vendor/cigraph/src/paths/dijkstra.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2005-2021 The igraph development team + igraph library. + Copyright (C) 2005-2025 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 @@ -13,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #include "igraph_paths.h" @@ -30,9 +27,40 @@ #include "core/indheap.h" #include "core/interruption.h" +#include "paths/paths_internal.h" #include /* memset */ +igraph_error_t igraph_i_validate_distance_weights( + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_bool_t *negative_weights) { + + const igraph_int_t ecount = igraph_ecount(graph); + + *negative_weights = false; + + if (weights) { + if (igraph_vector_size(weights) != ecount) { + IGRAPH_ERRORF("Edge weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", + IGRAPH_EINVAL, + igraph_vector_size(weights), ecount); + } + + if (ecount > 0) { + igraph_real_t min = igraph_vector_min(weights); + if (min < 0) { + *negative_weights = true; + } + if (isnan(min)) { + IGRAPH_ERROR("Edge weights must not contain NaN values.", IGRAPH_EINVAL); + } + } + } + + return IGRAPH_SUCCESS; +} + /** * \function igraph_distances_dijkstra_cutoff * \brief Weighted shortest path lengths between vertices, with cutoff. @@ -62,8 +90,8 @@ * for undirected graphs. * \param cutoff The maximal length of paths that will be considered. * When the distance of two vertices is greater than this value, - * it will be returned as \c IGRAPH_INFINITY. Negative cutoffs are - * treated as infinity. + * it will be returned as \c IGRAPH_INFINITY. Negative cutoffs and + * \ref IGRAPH_UNLIMITED are treated as infinity. * \return Error code. * * Time complexity: at most O(s |E| log|V| + |V|), where |V| is the number of @@ -76,7 +104,27 @@ * * \example examples/simple/distances.c */ -igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, +igraph_error_t igraph_distances_dijkstra_cutoff( + const igraph_t *graph, + igraph_matrix_t *res, + const igraph_vs_t from, + const igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_real_t cutoff) { + + igraph_bool_t negative_weights; + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + if (negative_weights) { + IGRAPH_ERRORF("Edge weights must not be negative when using Dijkstra's algorithm, got %g.", + IGRAPH_EINVAL, + igraph_vector_min(weights)); + } + return igraph_i_distances_dijkstra_cutoff(graph, res, from, to, weights, mode, cutoff); +} + + +igraph_error_t igraph_i_distances_dijkstra_cutoff(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t from, const igraph_vs_t to, @@ -96,33 +144,17 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, maximum heap and we need a minimum heap. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_2wheap_t Q; igraph_vit_t fromvit, tovit; - igraph_integer_t no_of_from, no_of_to; + igraph_int_t no_of_from, no_of_to; igraph_lazy_inclist_t inclist; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_bool_t all_to; igraph_vector_int_t indexv; if (!weights) { - return igraph_distances_cutoff(graph, NULL, res, from, to, mode, cutoff); - } - - if (igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", - IGRAPH_EINVAL, - igraph_vector_size(weights), no_of_edges); - } - - if (no_of_edges > 0) { - igraph_real_t min = igraph_vector_min(weights); - if (min < 0) { - IGRAPH_ERRORF("Weights must not be negative, got %g.", IGRAPH_EINVAL, min); - } else if (isnan(min)) { - IGRAPH_ERROR("Weights must not contain NaN values.", IGRAPH_EINVAL); - } + return igraph_i_distances_unweighted_cutoff(graph, res, from, to, mode, cutoff); } IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit)); @@ -150,7 +182,7 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, * map a target vertex to its column in the distance matrix. The mapping * is constructed by the loop below */ for (i = 0; !IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit)) { - igraph_integer_t v = IGRAPH_VIT_GET(tovit); + igraph_int_t v = IGRAPH_VIT_GET(tovit); if (VECTOR(indexv)[v]) { IGRAPH_ERROR("Target vertex list must not have any duplicates.", IGRAPH_EINVAL); @@ -166,8 +198,8 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, !IGRAPH_VIT_END(fromvit); IGRAPH_VIT_NEXT(fromvit), i++) { - igraph_integer_t reached = 0; - igraph_integer_t source = IGRAPH_VIT_GET(fromvit); + igraph_int_t reached = 0; + igraph_int_t source = IGRAPH_VIT_GET(fromvit); igraph_2wheap_clear(&Q); @@ -178,10 +210,10 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, igraph_2wheap_push_with_index(&Q, source, -0.0); while (!igraph_2wheap_empty(&Q)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&Q); + igraph_int_t minnei = igraph_2wheap_max_index(&Q); igraph_real_t mindist = -igraph_2wheap_deactivate_max(&Q); igraph_vector_int_t *neis; - igraph_integer_t nlen; + igraph_int_t nlen; if (cutoff >= 0 && mindist > cutoff) { continue; @@ -205,7 +237,7 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; + igraph_int_t edge = VECTOR(*neis)[j]; igraph_real_t weight = VECTOR(*weights)[edge]; /* Optimization: do not follow infinite-weight edges. */ @@ -213,7 +245,7 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, continue; } - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei); + igraph_int_t tto = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + weight; if (! igraph_2wheap_has_elem(&Q, tto)) { @@ -280,19 +312,21 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph, * Time complexity: O(s*|E|log|V|+|V|), where |V| is the number of * vertices, |E| the number of edges and s the number of sources. * - * \sa \ref igraph_distances() for a (slightly) faster unweighted - * version or \ref igraph_distances_bellman_ford() for a weighted + * \sa \ref igraph_distances() for a non-algorithm-specific interface + * or \ref igraph_distances_bellman_ford() for a weighted * variant that works in the presence of negative edge weights (but no * negative loops) * * \example examples/simple/distances.c */ -igraph_error_t igraph_distances_dijkstra(const igraph_t *graph, - igraph_matrix_t *res, - const igraph_vs_t from, - const igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode) { +igraph_error_t igraph_distances_dijkstra( + const igraph_t *graph, + igraph_matrix_t *res, + const igraph_vs_t from, + const igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode) { + return igraph_distances_dijkstra_cutoff(graph, res, from, to, weights, mode, -1); } @@ -369,23 +403,43 @@ igraph_error_t igraph_distances_dijkstra(const igraph_t *graph, * vertices and |E| is the number of edges * * \sa \ref igraph_distances_dijkstra() if you only need the path lengths but - * not the paths themselves; \ref igraph_get_shortest_paths() if all edge - * weights are equal; \ref igraph_get_all_shortest_paths() to find all - * shortest paths between (source, target) pairs; - * \ref igraph_get_shortest_paths_bellman_ford() if some edge weights are - * negative. + * not the paths themselves; \ref igraph_get_all_shortest_paths_dijkstra() to + * find all shortest paths between (source, target) pairs; + * \ref igraph_get_shortest_paths() for a non-algorithm-specific interface. * * \example examples/simple/igraph_get_shortest_paths_dijkstra.c */ -igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, - igraph_vector_int_list_t *vertices, - igraph_vector_int_list_t *edges, - igraph_integer_t from, - igraph_vs_t to, - const igraph_vector_t *weights, - igraph_neimode_t mode, - igraph_vector_int_t *parents, - igraph_vector_int_t *inbound_edges) { +igraph_error_t igraph_get_shortest_paths_dijkstra( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, + igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges) { + + igraph_bool_t negative_weights; + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + if (negative_weights) { + IGRAPH_ERRORF("Edge weights must not be negative when using Dijkstra's algorithm, got %g.", + IGRAPH_EINVAL, + igraph_vector_min(weights)); + } + return igraph_i_get_shortest_paths_dijkstra(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); +} + + +igraph_error_t igraph_i_get_shortest_paths_dijkstra(const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, + igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges) { /* Implementation details. This is the basic Dijkstra algorithm, with a binary heap. The heap is indexed, i.e. it stores not only the distances, but also which vertex they belong to. The other @@ -405,38 +459,23 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, edge ID + 1 is stored, zero means unreachable vertices. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vit_t vit; igraph_2wheap_t Q; igraph_lazy_inclist_t inclist; igraph_vector_t dists; - igraph_integer_t *parent_eids; + igraph_int_t *parent_eids; igraph_bool_t *is_target; - igraph_integer_t i, to_reach; + igraph_int_t i, to_reach; if (!weights) { - return igraph_get_shortest_paths(graph, NULL, vertices, edges, from, to, mode, - parents, inbound_edges); + return igraph_i_get_shortest_paths_unweighted(graph, vertices, edges, from, to, mode, parents, inbound_edges); } if (from < 0 || from >= no_of_nodes) { IGRAPH_ERROR("Index of source vertex is out of range.", IGRAPH_EINVVID); } - if (igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERROR("Weight vector length does not match number of edges.", IGRAPH_EINVAL); - } - if (no_of_edges > 0) { - igraph_real_t min = igraph_vector_min(weights); - if (min < 0) { - IGRAPH_ERRORF("Weights must not be negative, got %g.", IGRAPH_EINVAL, min); - } - else if (isnan(min)) { - IGRAPH_ERROR("Weights must not contain NaN values.", IGRAPH_EINVAL); - } - } - IGRAPH_CHECK(igraph_vit_create(graph, to, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); @@ -455,7 +494,7 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&dists, no_of_nodes); igraph_vector_fill(&dists, -1.0); - parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(parent_eids, "Insufficient memory for shortest paths with Dijkstra's algorithm."); IGRAPH_FINALLY(igraph_free, parent_eids); @@ -478,7 +517,7 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, igraph_2wheap_push_with_index(&Q, from, 0); while (!igraph_2wheap_empty(&Q) && to_reach > 0) { - igraph_integer_t nlen, minnei = igraph_2wheap_max_index(&Q); + igraph_int_t nlen, minnei = igraph_2wheap_max_index(&Q); igraph_real_t mindist = -igraph_2wheap_delete_max(&Q); igraph_vector_int_t *neis; @@ -494,8 +533,8 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); for (i = 0; i < nlen; i++) { - igraph_integer_t edge = VECTOR(*neis)[i]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei); + igraph_int_t edge = VECTOR(*neis)[i]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_real_t curdist = VECTOR(dists)[tto]; if (curdist < 0) { @@ -552,8 +591,8 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, /* Reconstruct the shortest paths based on vertex and/or edge IDs */ if (vertices || edges) { for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); - igraph_integer_t size, act, edge; + igraph_int_t node = IGRAPH_VIT_GET(vit); + igraph_int_t size, act, edge; igraph_vector_int_t *vvec = 0, *evec = 0; if (vertices) { vvec = igraph_vector_int_list_get_ptr(vertices, i); @@ -650,8 +689,8 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph, igraph_error_t igraph_get_shortest_path_dijkstra(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode) { @@ -759,15 +798,14 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, igraph_vector_int_t *nrgeo, - igraph_integer_t from, igraph_vs_t to, + igraph_int_t from, igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode) { - /* Implementation details: see igraph_get_shortest_paths_dijkstra, - it's basically the same. - */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + /* Implementation details: see igraph_get_shortest_paths_dijkstra(), + * it's basically the same. */ + + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vit_t vit; igraph_2wheap_t Q; igraph_lazy_inclist_t inclist; @@ -775,36 +813,32 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, igraph_vector_int_t index; igraph_vector_int_t order; igraph_vector_ptr_t parents, parents_edge; + igraph_bool_t negative_weights; unsigned char *is_target; /* uses more than two discrete values, can't be 'bool' */ - igraph_integer_t i, n, to_reach; + igraph_int_t i, n, to_reach; igraph_bool_t free_vertices = false; int cmp_result; const double eps = IGRAPH_SHORTEST_PATH_EPSILON; if (!weights) { - return igraph_get_all_shortest_paths(graph, NULL, vertices, edges, nrgeo, from, to, mode); + return igraph_i_get_all_shortest_paths_unweighted(graph, vertices, edges, nrgeo, from, to, mode); } if (from < 0 || from >= no_of_nodes) { IGRAPH_ERROR("Index of source vertex is out of range.", IGRAPH_EINVVID); } + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + if (negative_weights) { + IGRAPH_ERRORF("Edge weights must not be negative when using Dijkstra's algorithm, got %g.", + IGRAPH_EINVAL, + igraph_vector_min(weights)); + } + if (vertices == NULL && nrgeo == NULL && edges == NULL) { return IGRAPH_SUCCESS; } - if (igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERROR("Weight vector length does not match number of edges.", IGRAPH_EINVAL); - } - if (no_of_edges > 0) { - igraph_real_t min = igraph_vector_min(weights); - if (min < 0) { - IGRAPH_ERRORF("Edge weights must not be negative, got %g.", IGRAPH_EINVAL, min); - } - else if (isnan(min)) { - IGRAPH_ERROR("Weights must not contain NaN values.", IGRAPH_EINVAL); - } - } /* parents stores a vector for each vertex, listing the parent vertices * of each vertex in the traversal. Right now we do not use an @@ -878,7 +912,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, igraph_2wheap_push_with_index(&Q, from, 0.0); while (!igraph_2wheap_empty(&Q) && to_reach > 0) { - igraph_integer_t nlen, minnei = igraph_2wheap_max_index(&Q); + igraph_int_t nlen, minnei = igraph_2wheap_max_index(&Q); igraph_real_t mindist = -igraph_2wheap_delete_max(&Q); igraph_vector_int_t *neis; @@ -897,8 +931,8 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); for (i = 0; i < nlen; i++) { - igraph_integer_t edge = VECTOR(*neis)[i]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei); + igraph_int_t edge = VECTOR(*neis)[i]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_real_t curdist = VECTOR(dists)[tto]; igraph_vector_int_t *parent_vec, *parent_edge_vec; @@ -975,7 +1009,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, VECTOR(*nrgeo)[from] = 1; n = igraph_vector_int_size(&order); for (i = 1; i < n; i++) { - igraph_integer_t node, j, k; + igraph_int_t node, j, k; igraph_vector_int_t *parent_vec; node = VECTOR(order)[i]; @@ -992,7 +1026,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, igraph_vector_int_t *path, *parent_vec, *parent_edge_vec; igraph_vector_t *paths_index; igraph_stack_int_t stack; - igraph_integer_t j, node; + igraph_int_t j, node; /* a shortest path from the starting vertex to vertex i can be * obtained by calculating the shortest paths from the "parents" @@ -1028,7 +1062,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, while (!igraph_stack_int_empty(&stack)) { /* For each parent of node i, get its parents */ - igraph_integer_t el = igraph_stack_int_pop(&stack); + igraph_int_t el = igraph_stack_int_pop(&stack); parent_vec = (igraph_vector_int_t*) VECTOR(parents)[el]; i = igraph_vector_int_size(parent_vec); @@ -1085,7 +1119,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, VECTOR(*paths_index)[from] = 1; for (i = 1; i < n; i++) { - igraph_integer_t m, path_count; + igraph_int_t m, path_count; igraph_vector_int_t *parent_path, *parent_path_edge; node = VECTOR(order)[i]; @@ -1118,9 +1152,9 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, for (j = 0; j < m; j++) { /* for each parent, copy the shortest paths leading to that parent * and add the current vertex in the end */ - igraph_integer_t parent_node = VECTOR(*parent_vec)[j]; - igraph_integer_t parent_edge = VECTOR(*parent_edge_vec)[j]; - igraph_integer_t parent_path_idx = VECTOR(*paths_index)[parent_node] - 1; + igraph_int_t parent_node = VECTOR(*parent_vec)[j]; + igraph_int_t parent_edge = VECTOR(*parent_edge_vec)[j]; + igraph_int_t parent_path_idx = VECTOR(*paths_index)[parent_node] - 1; /* printf(" Considering parent: %ld\n", parent_node); printf(" Paths to parent start at index %ld in vertices\n", parent_path_idx); @@ -1156,7 +1190,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph, n = igraph_vector_int_list_size(vertices); i = 0; while (i < n) { - igraph_integer_t tmp; + igraph_int_t tmp; path = igraph_vector_int_list_get_ptr(vertices, i); tmp = igraph_vector_int_tail(path); if (is_target[tmp] == 1) { diff --git a/src/vendor/cigraph/src/paths/distances.c b/src/vendor/cigraph/src/paths/distances.c index b6fd98b7f5a..106d7f94316 100644 --- a/src/vendor/cigraph/src/paths/distances.c +++ b/src/vendor/cigraph/src/paths/distances.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -36,16 +36,16 @@ * the single given vertex, -1 is returned in vid_ecc. */ static igraph_error_t igraph_i_eccentricity_unweighted( const igraph_t *graph, igraph_vector_t *res, igraph_vs_t vids, - igraph_lazy_adjlist_t *adjlist, igraph_integer_t *vid_ecc, + igraph_lazy_adjlist_t *adjlist, igraph_int_t *vid_ecc, igraph_bool_t unconn ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; igraph_vit_t vit; igraph_vector_int_t counted; - igraph_integer_t i, mark = 1; - igraph_integer_t min_degree = 0; + igraph_int_t i, mark = 1; + igraph_int_t min_degree = 0; IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100); @@ -61,8 +61,8 @@ static igraph_error_t igraph_i_eccentricity_unweighted( !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), mark++, i++) { - igraph_integer_t source; - igraph_integer_t nodes_reached = 1; + igraph_int_t source; + igraph_int_t nodes_reached = 1; source = IGRAPH_VIT_GET(vit); IGRAPH_CHECK(igraph_dqueue_int_push(&q, source)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); @@ -71,16 +71,16 @@ static igraph_error_t igraph_i_eccentricity_unweighted( IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t act = igraph_dqueue_int_pop(&q); - igraph_integer_t dist = igraph_dqueue_int_pop(&q); + igraph_int_t act = igraph_dqueue_int_pop(&q); + igraph_int_t dist = igraph_dqueue_int_pop(&q); igraph_vector_int_t *neis = igraph_lazy_adjlist_get(adjlist, act); - igraph_integer_t j, n; + igraph_int_t j, n; IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); n = igraph_vector_int_size(neis); for (j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(*neis)[j]; + igraph_int_t nei = VECTOR(*neis)[j]; if (VECTOR(counted)[nei] != mark) { VECTOR(counted)[nei] = mark; nodes_reached++; @@ -128,16 +128,16 @@ static igraph_error_t igraph_i_eccentricity_unweighted( */ static igraph_error_t igraph_i_eccentricity_dijkstra( const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *ecc, - igraph_integer_t vid_start, igraph_integer_t *vid_ecc, igraph_bool_t unconn, + igraph_int_t vid_start, igraph_int_t *vid_ecc, igraph_bool_t unconn, igraph_lazy_inclist_t *inclist ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_2wheap_t Q; igraph_vector_t vec_dist; - igraph_integer_t i; + igraph_int_t i; igraph_real_t degree_ecc, dist; - igraph_integer_t degree_i; + igraph_int_t degree_i; igraph_vector_int_t *neis; IGRAPH_VECTOR_INIT_FINALLY(&vec_dist, no_of_nodes); @@ -149,9 +149,9 @@ static igraph_error_t igraph_i_eccentricity_dijkstra( igraph_2wheap_push_with_index(&Q, vid_start, -1.0); while (!igraph_2wheap_empty(&Q)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&Q); + igraph_int_t minnei = igraph_2wheap_max_index(&Q); igraph_real_t mindist = -igraph_2wheap_deactivate_max(&Q); - igraph_integer_t nlen; + igraph_int_t nlen; VECTOR(vec_dist)[minnei] = mindist - 1.0; @@ -160,8 +160,8 @@ static igraph_error_t igraph_i_eccentricity_dijkstra( IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); for (i = 0; i < nlen; i++) { - igraph_integer_t edge = VECTOR(*neis)[i]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei); + igraph_int_t edge = VECTOR(*neis)[i]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_bool_t active = igraph_2wheap_has_active(&Q, tto); igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto); @@ -260,9 +260,9 @@ igraph_error_t igraph_eccentricity( ) { igraph_lazy_inclist_t inclist; igraph_vit_t vit; - igraph_integer_t dump; + igraph_int_t dump; igraph_real_t ecc; - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); if (weights == NULL) { igraph_lazy_adjlist_t adjlist; @@ -316,8 +316,6 @@ igraph_error_t igraph_eccentricity( * \function igraph_radius * \brief Radius of a graph, using weighted edges. * - * \experimental - * * The radius of a graph is the defined as the minimum eccentricity of * its vertices, see \ref igraph_eccentricity(). * @@ -348,7 +346,7 @@ igraph_error_t igraph_radius( const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *radius, igraph_neimode_t mode ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (no_of_nodes == 0) { *radius = IGRAPH_NAN; @@ -365,16 +363,16 @@ igraph_error_t igraph_radius( } static igraph_error_t igraph_i_pseudo_diameter_unweighted( - const igraph_t *graph, igraph_real_t *diameter, igraph_integer_t vid_start, - igraph_integer_t *from, igraph_integer_t *to, + const igraph_t *graph, igraph_real_t *diameter, igraph_int_t vid_start, + igraph_int_t *from, igraph_int_t *to, igraph_bool_t directed, igraph_bool_t unconn ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_real_t ecc_v; igraph_real_t ecc_u; - igraph_integer_t vid_ecc; - igraph_integer_t ito, ifrom; + igraph_int_t vid_ecc; + igraph_int_t ito, ifrom; igraph_bool_t inf = false; if (vid_start >= no_of_nodes) { @@ -442,9 +440,9 @@ static igraph_error_t igraph_i_pseudo_diameter_unweighted( } else { igraph_vector_t ecc_out; igraph_vector_t ecc_in; - igraph_integer_t vid_ecc_in; - igraph_integer_t vid_ecc_out; - igraph_integer_t vid_end; + igraph_int_t vid_ecc_in; + igraph_int_t vid_ecc_out; + igraph_int_t vid_end; igraph_bool_t direction; igraph_lazy_adjlist_t adjlist_in; igraph_lazy_adjlist_t adjlist_out; @@ -560,17 +558,17 @@ static igraph_error_t igraph_i_pseudo_diameter_unweighted( static igraph_error_t igraph_i_pseudo_diameter_dijkstra( const igraph_t *graph, const igraph_vector_t *weights, - igraph_real_t *diameter, igraph_integer_t vid_start, - igraph_integer_t *from, igraph_integer_t *to, + igraph_real_t *diameter, igraph_int_t vid_start, + igraph_int_t *from, igraph_int_t *to, igraph_bool_t directed, igraph_bool_t unconn ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_real_t ecc_v; igraph_real_t ecc_u; - igraph_integer_t vid_ecc; - igraph_integer_t ito, ifrom; + igraph_int_t vid_ecc; + igraph_int_t ito, ifrom; igraph_bool_t inf = false; if (vid_start >= no_of_nodes) { @@ -643,9 +641,9 @@ static igraph_error_t igraph_i_pseudo_diameter_dijkstra( } else { igraph_real_t ecc_out; igraph_real_t ecc_in; - igraph_integer_t vid_ecc_in; - igraph_integer_t vid_ecc_out; - igraph_integer_t vid_end; + igraph_int_t vid_ecc_in; + igraph_int_t vid_ecc_out; + igraph_int_t vid_end; igraph_bool_t direction; igraph_lazy_inclist_t inclist_out; igraph_lazy_inclist_t inclist_in; @@ -786,8 +784,8 @@ static igraph_error_t igraph_i_pseudo_diameter_dijkstra( */ igraph_error_t igraph_pseudo_diameter( const igraph_t *graph, const igraph_vector_t *weights, - igraph_real_t *diameter, igraph_integer_t vid_start, - igraph_integer_t *from, igraph_integer_t *to, + igraph_real_t *diameter, igraph_int_t vid_start, + igraph_int_t *from, igraph_int_t *to, igraph_bool_t directed, igraph_bool_t unconn ) { if (weights) { @@ -852,8 +850,8 @@ igraph_error_t igraph_graph_center( /* igraph_eccentricity() does not return infinity or NaN, and the null graph * case was handled above, therefore calling vector_min() is safe. */ igraph_real_t min_eccentricity = igraph_vector_min(&ecc); - igraph_integer_t n = igraph_vector_size(&ecc); - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t n = igraph_vector_size(&ecc); + for (igraph_int_t i = 0; i < n; i++) { if (igraph_cmp_epsilon(VECTOR(ecc)[i], min_eccentricity, eps) == 0) { IGRAPH_CHECK(igraph_vector_int_push_back(res, i)); } diff --git a/src/vendor/cigraph/src/paths/eulerian.c b/src/vendor/cigraph/src/paths/eulerian.c index 982c839a57f..77acd2be61c 100644 --- a/src/vendor/cigraph/src/paths/eulerian.c +++ b/src/vendor/cigraph/src/paths/eulerian.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -40,18 +40,18 @@ has_path is set to 1 if a path exists, 0 otherwise has_cycle is set to 1 if a cycle exists, 0 otherwise */ static igraph_error_t igraph_i_is_eulerian_undirected( - const igraph_t *graph, igraph_bool_t *has_path, igraph_bool_t *has_cycle, igraph_integer_t *start_of_path) { - igraph_integer_t odd; + const igraph_t *graph, igraph_bool_t *has_path, igraph_bool_t *has_cycle, igraph_int_t *start_of_path) { + igraph_int_t odd; igraph_vector_int_t degree; igraph_vector_int_t csize; /* boolean vector to mark singletons: */ igraph_vector_int_t nonsingleton; - igraph_integer_t i, n, vsize; - igraph_integer_t cluster_count; + igraph_int_t i, n, vsize; + igraph_int_t cluster_count; /* number of self-looping singletons: */ - igraph_integer_t es; + igraph_int_t es; /* will be set to 1 if there are non-isolated vertices, otherwise 0: */ - igraph_integer_t ens; + igraph_int_t ens; n = igraph_vcount(graph); @@ -103,7 +103,7 @@ static igraph_error_t igraph_i_is_eulerian_undirected( es = 0; ens = 0; for (i = 0; i < n; i++) { - igraph_integer_t deg = VECTOR(degree)[i]; + igraph_int_t deg = VECTOR(degree)[i]; /* Eulerian is about edges, so skip free vertices */ if (deg == 0) continue; @@ -163,18 +163,18 @@ static igraph_error_t igraph_i_is_eulerian_undirected( static igraph_error_t igraph_i_is_eulerian_directed( - const igraph_t *graph, igraph_bool_t *has_path, igraph_bool_t *has_cycle, igraph_integer_t *start_of_path) { - igraph_integer_t incoming_excess, outgoing_excess, n; - igraph_integer_t i, vsize; - igraph_integer_t cluster_count; + const igraph_t *graph, igraph_bool_t *has_path, igraph_bool_t *has_cycle, igraph_int_t *start_of_path) { + igraph_int_t incoming_excess, outgoing_excess, n; + igraph_int_t i, vsize; + igraph_int_t cluster_count; igraph_vector_int_t out_degree, in_degree; igraph_vector_int_t csize; /* boolean vector to mark singletons: */ igraph_vector_int_t nonsingleton; /* number of self-looping singletons: */ - igraph_integer_t es; + igraph_int_t es; /* will be set to 1 if there are non-isolated vertices, otherwise 0: */ - igraph_integer_t ens; + igraph_int_t ens; n = igraph_vcount(graph); @@ -231,8 +231,8 @@ static igraph_error_t igraph_i_is_eulerian_directed( ens = 0; *start_of_path = -1; for (i = 0; i < n; i++) { - igraph_integer_t degin = VECTOR(in_degree)[i]; - igraph_integer_t degout = VECTOR(out_degree)[i]; + igraph_int_t degin = VECTOR(in_degree)[i]; + igraph_int_t degout = VECTOR(out_degree)[i]; /* Eulerian is about edges, so skip free vertices */ if (degin + degout == 0) continue; @@ -331,7 +331,7 @@ static igraph_error_t igraph_i_is_eulerian_directed( */ igraph_error_t igraph_is_eulerian(const igraph_t *graph, igraph_bool_t *has_path, igraph_bool_t *has_cycle) { - igraph_integer_t start_of_path = 0; + igraph_int_t start_of_path = 0; if (igraph_is_directed(graph)) { IGRAPH_CHECK(igraph_i_is_eulerian_directed(graph, has_path, has_cycle, &start_of_path)); @@ -344,10 +344,10 @@ igraph_error_t igraph_is_eulerian(const igraph_t *graph, igraph_bool_t *has_path static igraph_error_t igraph_i_eulerian_path_undirected( const igraph_t *graph, igraph_vector_int_t *edge_res, igraph_vector_int_t *vertex_res, - igraph_integer_t start_of_path) { + igraph_int_t start_of_path) { - igraph_integer_t curr; - igraph_integer_t n, m; + igraph_int_t curr; + igraph_int_t n, m; igraph_inclist_t il; igraph_stack_int_t path, tracker, edge_tracker, edge_path; igraph_bitset_t visited_list; @@ -388,8 +388,8 @@ static igraph_error_t igraph_i_eulerian_path_undirected( if (VECTOR(degree)[curr] != 0) { igraph_vector_int_t *incedges; - igraph_integer_t nc, edge = -1; - igraph_integer_t j, next; + igraph_int_t nc, edge = -1; + igraph_int_t j, next; IGRAPH_CHECK(igraph_stack_int_push(&tracker, curr)); incedges = igraph_inclist_get(&il, curr); @@ -414,7 +414,7 @@ static igraph_error_t igraph_i_eulerian_path_undirected( curr = next; } else { /* back track to find remaining circuit */ - igraph_integer_t curr_e; + igraph_int_t curr_e; IGRAPH_CHECK(igraph_stack_int_push(&path, curr)); curr = igraph_stack_int_pop(&tracker); if (!igraph_stack_int_empty(&edge_tracker)) { @@ -452,10 +452,10 @@ static igraph_error_t igraph_i_eulerian_path_undirected( /* solution adapted from https://www.geeksforgeeks.org/hierholzers-algorithm-directed-graph/ */ static igraph_error_t igraph_i_eulerian_path_directed( const igraph_t *graph, igraph_vector_int_t *edge_res, igraph_vector_int_t *vertex_res, - igraph_integer_t start_of_path) { + igraph_int_t start_of_path) { - igraph_integer_t curr; - igraph_integer_t n, m; + igraph_int_t curr; + igraph_int_t n, m; igraph_inclist_t il; igraph_stack_int_t path, tracker, edge_tracker, edge_path; igraph_bitset_t visited_list; @@ -496,8 +496,8 @@ static igraph_error_t igraph_i_eulerian_path_directed( if (VECTOR(remaining_out_edges)[curr] != 0) { igraph_vector_int_t *incedges; - igraph_integer_t nc, edge = -1; - igraph_integer_t j, next; + igraph_int_t nc, edge = -1; + igraph_int_t j, next; IGRAPH_CHECK(igraph_stack_int_push(&tracker, curr)); incedges = igraph_inclist_get(&il, curr); @@ -521,7 +521,7 @@ static igraph_error_t igraph_i_eulerian_path_directed( curr = next; } else { /* back track to find remaining circuit */ - igraph_integer_t curr_e; + igraph_int_t curr_e; IGRAPH_CHECK(igraph_stack_int_push(&path, curr)); curr = igraph_stack_int_pop(&tracker); if (!igraph_stack_int_empty(&edge_tracker)) { @@ -596,7 +596,7 @@ igraph_error_t igraph_eulerian_cycle( igraph_bool_t has_cycle; igraph_bool_t has_path; - igraph_integer_t start_of_path = 0; + igraph_int_t start_of_path = 0; if (igraph_is_directed(graph)) { IGRAPH_CHECK(igraph_i_is_eulerian_directed(graph, &has_path, &has_cycle, &start_of_path)); @@ -658,7 +658,7 @@ igraph_error_t igraph_eulerian_path( igraph_bool_t has_cycle; igraph_bool_t has_path; - igraph_integer_t start_of_path = 0; + igraph_int_t start_of_path = 0; if (igraph_is_directed(graph)) { IGRAPH_CHECK(igraph_i_is_eulerian_directed(graph, &has_path, &has_cycle, &start_of_path)); diff --git a/src/vendor/cigraph/src/paths/floyd_warshall.c b/src/vendor/cigraph/src/paths/floyd_warshall.c index 0ab833869c8..5cb7b7341d6 100644 --- a/src/vendor/cigraph/src/paths/floyd_warshall.c +++ b/src/vendor/cigraph/src/paths/floyd_warshall.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2022-2023 The igraph development team + igraph library. + Copyright (C) 2022-2025 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 @@ -22,23 +22,24 @@ #include "core/interruption.h" #include "internal/utils.h" +#include "paths/paths_internal.h" static igraph_error_t distances_floyd_warshall_original(igraph_matrix_t *res) { - igraph_integer_t no_of_nodes = igraph_matrix_nrow(res); + igraph_int_t no_of_nodes = igraph_matrix_nrow(res); - for (igraph_integer_t k = 0; k < no_of_nodes; k++) { + for (igraph_int_t k = 0; k < no_of_nodes; k++) { IGRAPH_ALLOW_INTERRUPTION(); /* Iteration order matters for performance! * First j, then i, because matrices are stored as column-major. */ - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { igraph_real_t dkj = MATRIX(*res, k, j); if (dkj == IGRAPH_INFINITY) { continue; } - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_real_t di = MATRIX(*res, i, k) + dkj; igraph_real_t dd = MATRIX(*res, i, j); if (di < dd) { @@ -46,7 +47,7 @@ static igraph_error_t distances_floyd_warshall_original(igraph_matrix_t *res) { } if (i == j && MATRIX(*res, i, i) < 0) { IGRAPH_ERROR("Negative cycle found while calculating distances with Floyd-Warshall.", - IGRAPH_ENEGLOOP); + IGRAPH_ENEGCYCLE); } } } @@ -64,7 +65,7 @@ static igraph_error_t distances_floyd_warshall_tree(igraph_matrix_t *res) { * This makes it easier to iterate through matrices in column-major order, * i.e. storage order, thus increasing performance. */ - igraph_integer_t no_of_nodes = igraph_matrix_nrow(res); + igraph_int_t no_of_nodes = igraph_matrix_nrow(res); /* successors[v][u] is the second vertex on the shortest path from v to u, i.e. the parent of v in the IN_u tree. */ @@ -99,28 +100,28 @@ static igraph_error_t distances_floyd_warshall_tree(igraph_matrix_t *res) { igraph_stack_int_t stack; IGRAPH_STACK_INT_INIT_FINALLY(&stack, no_of_nodes); - for (igraph_integer_t u = 0; u < no_of_nodes; u++) { - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { + for (igraph_int_t u = 0; u < no_of_nodes; u++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { MATRIX(successors, v, u) = u; } } - for (igraph_integer_t k = 0; k < no_of_nodes; k++) { + for (igraph_int_t k = 0; k < no_of_nodes; k++) { IGRAPH_ALLOW_INTERRUPTION(); /* Count the children of each node in the shortest path tree, assuming that at this point all elements of no_of_children[] are zeros. */ - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { if (v == k) continue; - igraph_integer_t parent = MATRIX(successors, v, k); + igraph_int_t parent = MATRIX(successors, v, k); VECTOR(no_of_children)[parent]++; } /* Note: we do not use igraph_vector_int_cumsum() here as that function produces an output vector of the same length as the input vector. Here we need an output one longer, with a 0 being prepended to what vector_cumsum() would produce. */ - igraph_integer_t cumsum = 0; - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { + igraph_int_t cumsum = 0; + for (igraph_int_t v = 0; v < no_of_nodes; v++) { VECTOR(children_start)[v] = cumsum; cumsum += VECTOR(no_of_children)[v]; } @@ -131,25 +132,25 @@ static igraph_error_t distances_floyd_warshall_tree(igraph_matrix_t *res) { vector as re-used as an index of where to insert child node indices. At the end of the calculation, all elements of no_of_children[] will be zeros, making this vector ready for the next iteration of the outer loop. */ - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { if (v == k) continue; - igraph_integer_t parent = MATRIX(successors, v, k); + igraph_int_t parent = MATRIX(successors, v, k); VECTOR(no_of_children)[parent]--; VECTOR(children)[ VECTOR(children_start)[parent] + VECTOR(no_of_children)[parent] ] = v; } /* constructing dfs-traversal and dfs-skip arrays for the IN_k tree */ IGRAPH_CHECK(igraph_stack_int_push(&stack, k)); - igraph_integer_t counter = 0; + igraph_int_t counter = 0; while (!igraph_stack_int_empty(&stack)) { - igraph_integer_t parent = igraph_stack_int_pop(&stack); + igraph_int_t parent = igraph_stack_int_pop(&stack); if (parent >= 0) { VECTOR(dfs_traversal)[counter] = parent; counter++; /* a negative marker -parent - 1 that is popped right after all the descendants of the parent were processed */ IGRAPH_CHECK(igraph_stack_int_push(&stack, -parent - 1)); - for (igraph_integer_t l = VECTOR(children_start)[parent]; l < VECTOR(children_start)[parent + 1]; l++) { + for (igraph_int_t l = VECTOR(children_start)[parent]; l < VECTOR(children_start)[parent + 1]; l++) { IGRAPH_CHECK(igraph_stack_int_push(&stack, VECTOR(children)[l])); } } else { @@ -158,14 +159,14 @@ static igraph_error_t distances_floyd_warshall_tree(igraph_matrix_t *res) { } /* main inner loop */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { igraph_real_t dki = MATRIX(*res, k, i); if (dki == IGRAPH_INFINITY || i == k) { continue; } - igraph_integer_t counter = 1; + igraph_int_t counter = 1; while (counter < no_of_nodes) { - igraph_integer_t j = VECTOR(dfs_traversal)[counter]; + igraph_int_t j = VECTOR(dfs_traversal)[counter]; igraph_real_t di = MATRIX(*res, j, k) + dki; igraph_real_t dd = MATRIX(*res, j, i); if (di < dd) { @@ -177,7 +178,7 @@ static igraph_error_t distances_floyd_warshall_tree(igraph_matrix_t *res) { } if (i == j && MATRIX(*res, i, i) < 0) { IGRAPH_ERROR("Negative cycle found while calculating distances with Floyd-Warshall.", - IGRAPH_ENEGLOOP); + IGRAPH_ENEGCYCLE); } } } @@ -254,7 +255,7 @@ static igraph_error_t distances_floyd_warshall_tree(igraph_matrix_t *res) { * the "Tree" speedup of Brodnik et al., faster than the original algorithm * in most cases. * \endclist - * \return Error code. \c IGRAPH_ENEGLOOP is returned if a negative-weight + * \return Error code. \c IGRAPH_ENEGCYCLE is returned if a negative-weight * cycle is found. * * \sa \ref igraph_distances(), \ref igraph_distances_dijkstra(), @@ -272,13 +273,20 @@ igraph_error_t igraph_distances_floyd_warshall( const igraph_vector_t *weights, igraph_neimode_t mode, const igraph_floyd_warshall_algorithm_t method) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_bool_t in = false, out = false; + igraph_bool_t negative_weights; + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + return igraph_i_distances_floyd_warshall(graph, res, from, to, weights, mode, method); +} - if (weights && igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERROR("Invalid weight vector length.", IGRAPH_EINVAL); - } +igraph_error_t igraph_i_distances_floyd_warshall( + const igraph_t *graph, igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, igraph_neimode_t mode, + const igraph_floyd_warshall_algorithm_t method) { + + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_bool_t in = false, out = false; if (! igraph_is_directed(graph)) { mode = IGRAPH_ALL; @@ -298,31 +306,27 @@ igraph_error_t igraph_distances_floyd_warshall( IGRAPH_ERROR("Invalid mode for Floyd-Warshall shortest path calculation.", IGRAPH_EINVMODE); } - if (weights && igraph_vector_is_any_nan(weights)) { - IGRAPH_ERROR("Weight vector must not contain NaN values.", IGRAPH_EINVAL); - } - IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, no_of_nodes)); igraph_matrix_fill(res, IGRAPH_INFINITY); - for (igraph_integer_t v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { MATRIX(*res, v, v) = 0; } - for (igraph_integer_t e = 0; e < no_of_edges; e++) { - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); + for (igraph_int_t e = 0; e < no_of_edges; e++) { + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); igraph_real_t w = weights ? VECTOR(*weights)[e] : 1; if (w < 0) { if (mode == IGRAPH_ALL) { IGRAPH_ERRORF("Negative edge weight (%g) found in undirected graph " "while calculating distances with Floyd-Warshall.", - IGRAPH_ENEGLOOP, w); + IGRAPH_ENEGCYCLE, w); } else if (to == from) { IGRAPH_ERRORF("Self-loop with negative weight (%g) found " "while calculating distances with Floyd-Warshall.", - IGRAPH_ENEGLOOP, w); + IGRAPH_ENEGCYCLE, w); } } else if (w == IGRAPH_INFINITY) { /* Ignore edges with infinite weight */ diff --git a/src/vendor/cigraph/src/paths/histogram.c b/src/vendor/cigraph/src/paths/histogram.c index d9bd65b5d50..02bd706c4f9 100644 --- a/src/vendor/cigraph/src/paths/histogram.c +++ b/src/vendor/cigraph/src/paths/histogram.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -54,14 +54,14 @@ igraph_error_t igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *res, igraph_real_t *unconnected, igraph_bool_t directed) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t already_added; - igraph_integer_t nodes_reached; + igraph_int_t nodes_reached; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; igraph_vector_int_t *neis; igraph_adjlist_t allneis; igraph_real_t unconn = 0; - igraph_integer_t ressize; + igraph_int_t ressize; if (! igraph_is_directed(graph)) { directed = false; @@ -78,7 +78,7 @@ igraph_error_t igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *r igraph_vector_clear(res); ressize = 0; - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { nodes_reached = 1; /* itself */ IGRAPH_CHECK(igraph_dqueue_int_push(&q, i)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); @@ -89,13 +89,13 @@ igraph_error_t igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *r IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); neis = igraph_adjlist_get(&allneis, actnode); - const igraph_integer_t n = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + const igraph_int_t n = igraph_vector_int_size(neis); + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t neighbor = VECTOR(*neis)[j]; if (VECTOR(already_added)[neighbor] == i + 1) { continue; } @@ -122,7 +122,7 @@ igraph_error_t igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *r /* count every pair only once for an undirected graph */ if (!directed) { - for (igraph_integer_t i = 0; i < ressize; i++) { + for (igraph_int_t i = 0; i < ressize; i++) { VECTOR(*res)[i] /= 2; } unconn /= 2; diff --git a/src/vendor/cigraph/src/paths/johnson.c b/src/vendor/cigraph/src/paths/johnson.c index 5d8a92cfab9..75e614f3fe2 100644 --- a/src/vendor/cigraph/src/paths/johnson.c +++ b/src/vendor/cigraph/src/paths/johnson.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2005-2021 The igraph development team + igraph library. + Copyright (C) 2005-2025 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 @@ -13,10 +13,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - + along with this program. If not, see . */ #include "igraph_paths.h" @@ -25,6 +22,9 @@ #include "igraph_interface.h" #include "math/safe_intop.h" +#include "paths/paths_internal.h" + + /** * \function igraph_distances_johnson * \brief Weighted shortest path lengths between vertices, using Johnson's algorithm. @@ -80,54 +80,50 @@ * edge weights, \ref igraph_distances_bellman_ford() if you only * need to calculate shortest paths from a couple of sources. */ -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, - igraph_neimode_t mode) { - - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); +igraph_error_t igraph_distances_johnson( + const igraph_t *graph, + igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode) { + + igraph_bool_t negative_weights; + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + if (!negative_weights) { + /* If no negative weights, then we can run Dijkstra's algorithm directly, without + * needing to go through Johnson's procedure to eliminate negative weights. */ + return igraph_i_distances_dijkstra_cutoff(graph, res, from, to, weights, mode, -1); + } else { + return igraph_i_distances_johnson(graph, res, from, to, weights, mode); + } +} + +igraph_error_t igraph_i_distances_johnson( + const igraph_t *graph, + igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode) { + + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_t newgraph; igraph_vector_int_t edges; igraph_vector_t newweights; igraph_matrix_t bfres; - igraph_integer_t i, ptr; - igraph_integer_t nr, nc; + igraph_int_t i, ptr; + igraph_int_t nr, nc; igraph_vit_t fromvit; - igraph_integer_t no_edges_reserved; + igraph_int_t no_edges_reserved; - /* If no weights, then we can just run the unweighted version */ - if (!weights) { - return igraph_distances(graph, NULL, res, from, to, mode); - } - - if (igraph_vector_size(weights) != no_of_edges) { - IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", - IGRAPH_EINVAL, - igraph_vector_size(weights), no_of_edges); - } - - /* If no edges, then we can just run the unweighted version */ - if (no_of_edges == 0) { - return igraph_distances(graph, NULL, res, from, to, mode); - } - - /* If no negative weights, then we can run Dijkstra's algorithm */ - { - igraph_real_t min_weight = igraph_vector_min(weights); - if (isnan(min_weight)) { - IGRAPH_ERROR("Weight vector must not contain NaN values.", IGRAPH_EINVAL); - } - if (min_weight >= 0) { - return igraph_distances_dijkstra(graph, res, from, to, weights, mode); - } + /* If no weights or no edges, then we can just run the unweighted version */ + if (!weights || no_of_edges == 0) { + return igraph_i_distances_unweighted_cutoff(graph, res, from, to, mode, -1); } if (!igraph_is_directed(graph) || mode == IGRAPH_ALL) { IGRAPH_ERROR("Undirected graph with negative weight.", - IGRAPH_ENEGLOOP); + IGRAPH_ENEGCYCLE); } /* ------------------------------------------------------------ */ @@ -171,9 +167,10 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, /* Run Bellman-Ford algorithm on the new graph, starting from the new vertex. */ - IGRAPH_CHECK(igraph_distances_bellman_ford(&newgraph, &bfres, - igraph_vss_1(no_of_nodes), - igraph_vss_all(), &newweights, mode)); + IGRAPH_CHECK(igraph_i_distances_bellman_ford( + &newgraph, &bfres, + igraph_vss_1(no_of_nodes), igraph_vss_all(), + &newweights, mode)); igraph_destroy(&newgraph); IGRAPH_FINALLY_CLEAN(1); @@ -184,8 +181,8 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, igraph_vector_resize(&newweights, no_of_edges); /* reserved */ for (i = 0; i < no_of_edges; i++) { - igraph_integer_t ffrom = IGRAPH_FROM(graph, i); - igraph_integer_t tto = IGRAPH_TO(graph, i); + igraph_int_t ffrom = IGRAPH_FROM(graph, i); + igraph_int_t tto = IGRAPH_TO(graph, i); if (mode == IGRAPH_OUT) { VECTOR(newweights)[i] += MATRIX(bfres, 0, ffrom) - MATRIX(bfres, 0, tto); } else { @@ -198,9 +195,11 @@ 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, - mode)); + IGRAPH_CHECK(igraph_i_distances_dijkstra_cutoff( + graph, res, + from, to, + &newweights, + mode, -1)); igraph_vector_destroy(&newweights); IGRAPH_FINALLY_CLEAN(1); @@ -213,9 +212,9 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, IGRAPH_FINALLY(igraph_vit_destroy, &fromvit); for (i = 0; i < nr; i++, IGRAPH_VIT_NEXT(fromvit)) { - igraph_integer_t v1 = IGRAPH_VIT_GET(fromvit); + igraph_int_t v1 = IGRAPH_VIT_GET(fromvit); if (igraph_vs_is_all(&to)) { - igraph_integer_t v2; + igraph_int_t v2; for (v2 = 0; v2 < nc; v2++) { igraph_real_t sub; if (mode == IGRAPH_OUT) { @@ -227,13 +226,13 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, } } } else { - igraph_integer_t j; + igraph_int_t j; igraph_vit_t tovit; 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_int_t v2 = IGRAPH_VIT_GET(tovit); if (mode == IGRAPH_OUT) { sub = MATRIX(bfres, 0, v1) - MATRIX(bfres, 0, v2); MATRIX(*res, i, j) -= sub; diff --git a/src/vendor/cigraph/src/paths/paths_internal.h b/src/vendor/cigraph/src/paths/paths_internal.h new file mode 100644 index 00000000000..477ef03bf7e --- /dev/null +++ b/src/vendor/cigraph/src/paths/paths_internal.h @@ -0,0 +1,119 @@ +/* + igraph library. + Copyright (C) 2025 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 . +*/ + +#ifndef IGRAPH_PATHS_INTERNAL_H +#define IGRAPH_PATHS_INTERNAL_H + +#include "igraph_decls.h" +#include "igraph_paths.h" + +IGRAPH_BEGIN_C_DECLS + +/* Helper functions for validating input to shortest path functions. */ + +igraph_error_t igraph_i_validate_distance_weights( + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_bool_t *negative_weights); + + +/* The following shortest path functions skip most input validation, + * and are meant for internal use in context where the validation + * has already been done. */ + +/* Distances */ + +igraph_error_t igraph_i_distances_unweighted_cutoff( + const igraph_t *graph, + igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + igraph_neimode_t mode, + igraph_real_t cutoff); + +igraph_error_t igraph_i_distances_dijkstra_cutoff( + const igraph_t *graph, + igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_real_t cutoff); + +igraph_error_t igraph_i_distances_bellman_ford( + const igraph_t *graph, + igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode); + +igraph_error_t igraph_i_distances_johnson( + const igraph_t *graph, + igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode); + +igraph_error_t igraph_i_distances_floyd_warshall( + const igraph_t *graph, + igraph_matrix_t *res, + igraph_vs_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_floyd_warshall_algorithm_t method); + +/* Get shortest paths */ + +igraph_error_t igraph_i_get_shortest_paths_unweighted( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, igraph_vs_t to, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges); + +igraph_error_t igraph_i_get_shortest_paths_dijkstra( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges); + +igraph_error_t igraph_i_get_shortest_paths_bellman_ford( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, igraph_vs_t to, + const igraph_vector_t *weights, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges); + +igraph_error_t igraph_i_get_all_shortest_paths_unweighted( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_vector_int_t *nrgeo, + igraph_int_t from, igraph_vs_t to, + igraph_neimode_t mode); + +IGRAPH_END_C_DECLS + +#endif /* IGRAPH_PATHS_INTERNAL_H */ diff --git a/src/vendor/cigraph/src/paths/random_walk.c b/src/vendor/cigraph/src/paths/random_walk.c index ebdd615ca00..fde30bfc515 100644 --- a/src/vendor/cigraph/src/paths/random_walk.c +++ b/src/vendor/cigraph/src/paths/random_walk.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2014 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -41,11 +41,11 @@ */ static igraph_error_t igraph_i_random_walk_adjlist(const igraph_t *graph, igraph_vector_int_t *vertices, - igraph_integer_t start, + igraph_int_t start, igraph_neimode_t mode, - igraph_integer_t steps, + igraph_int_t steps, igraph_random_walk_stuck_t stuck) { - igraph_integer_t i; + igraph_int_t i; igraph_lazy_adjlist_t adj; if (vertices == NULL) { @@ -61,7 +61,7 @@ static igraph_error_t igraph_i_random_walk_adjlist(const igraph_t *graph, VECTOR(*vertices)[0] = start; for (i = 1; i <= steps; i++) { igraph_vector_int_t *neis; - igraph_integer_t nn; + igraph_int_t nn; neis = igraph_lazy_adjlist_get(&adj, start); IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); @@ -117,13 +117,13 @@ static igraph_error_t igraph_i_random_walk_inclist( const igraph_vector_t *weights, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t start, + igraph_int_t start, igraph_neimode_t mode, - igraph_integer_t steps, + igraph_int_t steps, igraph_random_walk_stuck_t stuck) { - igraph_integer_t vc = igraph_vcount(graph); - igraph_integer_t i, next; + igraph_int_t vc = igraph_vcount(graph); + igraph_int_t i, next; igraph_vector_t weight_temp; igraph_lazy_inclist_t il; igraph_vector_ptr_t cdfs; /* cumulative distribution vectors for each node, used for weighted choice */ @@ -154,7 +154,7 @@ static igraph_error_t igraph_i_random_walk_inclist( VECTOR(*vertices)[0] = start; } for (i = 0; i < steps; ++i) { - igraph_integer_t degree, edge, idx; + igraph_int_t degree, edge, idx; igraph_vector_int_t *inc_edges = igraph_lazy_inclist_get(&il, start); IGRAPH_CHECK_OOM(inc_edges, "Failed to query incident edges."); @@ -182,7 +182,7 @@ static igraph_error_t igraph_i_random_walk_inclist( /* compute out-edge cdf for this node if not already done */ if (IGRAPH_UNLIKELY(! *cd)) { - igraph_integer_t j; + igraph_int_t j; *cd = IGRAPH_CALLOC(1, igraph_vector_t); IGRAPH_CHECK_OOM(*cd, "Insufficient memory for random walk."); @@ -289,13 +289,13 @@ igraph_error_t igraph_random_walk(const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t start, + igraph_int_t start, igraph_neimode_t mode, - igraph_integer_t steps, + igraph_int_t steps, igraph_random_walk_stuck_t stuck) { - igraph_integer_t vc = igraph_vcount(graph); - igraph_integer_t ec = igraph_ecount(graph); + igraph_int_t vc = igraph_vcount(graph); + igraph_int_t ec = igraph_ecount(graph); if (!(mode == IGRAPH_ALL || mode == IGRAPH_IN || mode == IGRAPH_OUT)) { IGRAPH_ERROR("Invalid mode parameter.", IGRAPH_EINVMODE); diff --git a/src/vendor/cigraph/src/paths/shortest_paths.c b/src/vendor/cigraph/src/paths/shortest_paths.c index 64dea6c8d82..a443c0097a8 100644 --- a/src/vendor/cigraph/src/paths/shortest_paths.c +++ b/src/vendor/cigraph/src/paths/shortest_paths.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2020 The igraph development team This program is free software; you can redistribute it and/or modify @@ -43,15 +43,15 @@ static igraph_error_t igraph_i_average_path_length_unweighted( const igraph_bool_t invert, /* average inverse distances instead of distances */ const igraph_bool_t unconn /* average over connected pairs instead of all pairs */) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); /* The number of ordered vertex pairs. * While the conditional below is not mathematically necessary, it prevents * returning -0.0 where 0.0 would be expected. */ const igraph_real_t no_of_pairs = no_of_nodes > 0 ? no_of_nodes * (no_of_nodes - 1.0) : 0.0; - igraph_integer_t n; - igraph_integer_t *already_added; + igraph_int_t n; + igraph_int_t *already_added; igraph_real_t no_of_conn_pairs = 0.0; /* no. of ordered pairs between which there is a path */ @@ -60,7 +60,7 @@ static igraph_error_t igraph_i_average_path_length_unweighted( igraph_adjlist_t allneis; *res = 0; - already_added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + already_added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(already_added, "Insufficient memory for average path length."); IGRAPH_FINALLY(igraph_free, already_added); @@ -73,7 +73,7 @@ static igraph_error_t igraph_i_average_path_length_unweighted( )); IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis); - for (igraph_integer_t source = 0; source < no_of_nodes; source++) { + for (igraph_int_t source = 0; source < no_of_nodes; source++) { IGRAPH_CHECK(igraph_dqueue_int_push(&q, source)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); already_added[source] = source + 1; @@ -81,13 +81,13 @@ static igraph_error_t igraph_i_average_path_length_unweighted( IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); neis = igraph_adjlist_get(&allneis, actnode); n = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t neighbor = VECTOR(*neis)[j]; if (already_added[neighbor] == source + 1) { continue; } @@ -169,8 +169,8 @@ static igraph_error_t igraph_i_average_path_length_dijkstra( and we want to spare that. -1 will denote infinity instead. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_2wheap_t Q; igraph_lazy_inclist_t inclist; igraph_real_t no_of_pairs; @@ -208,7 +208,7 @@ static igraph_error_t igraph_i_average_path_length_dijkstra( *res = 0.0; - for (igraph_integer_t source = 0; source < no_of_nodes; ++source) { + for (igraph_int_t source = 0; source < no_of_nodes; ++source) { IGRAPH_ALLOW_INTERRUPTION(); @@ -216,10 +216,10 @@ static igraph_error_t igraph_i_average_path_length_dijkstra( igraph_2wheap_push_with_index(&Q, source, -1.0); while (!igraph_2wheap_empty(&Q)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&Q); + igraph_int_t minnei = igraph_2wheap_max_index(&Q); igraph_real_t mindist = -igraph_2wheap_deactivate_max(&Q); igraph_vector_int_t *neis; - igraph_integer_t nlen; + igraph_int_t nlen; if (minnei != source) { if (invert) { @@ -234,9 +234,9 @@ static igraph_error_t igraph_i_average_path_length_dijkstra( neis = igraph_lazy_inclist_get(&inclist, minnei); IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei); + for (igraph_int_t j = 0; j < nlen; j++) { + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_bool_t active = igraph_2wheap_has_active(&Q, tto); igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto); @@ -413,17 +413,17 @@ static igraph_error_t igraph_i_local_efficiency_unweighted( const igraph_t *graph, const igraph_adjlist_t *adjlist, igraph_dqueue_int_t *q, - igraph_integer_t *already_counted, + igraph_int_t *already_counted, igraph_vector_int_t *vertex_neis, igraph_vector_char_t *nei_mask, igraph_real_t *res, - igraph_integer_t vertex, + igraph_int_t vertex, igraph_neimode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t vertex_neis_size; - igraph_integer_t neighbor_count; /* unlike 'vertex_neis_size', 'neighbor_count' does not count self-loops and multi-edges */ + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t vertex_neis_size; + igraph_int_t neighbor_count; /* unlike 'vertex_neis_size', 'neighbor_count' does not count self-loops and multi-edges */ igraph_dqueue_int_clear(q); @@ -437,8 +437,8 @@ static igraph_error_t igraph_i_local_efficiency_unweighted( igraph_vector_char_null(nei_mask); neighbor_count = 0; - for (igraph_integer_t i=0; i < vertex_neis_size; ++i) { - igraph_integer_t v = VECTOR(*vertex_neis)[i]; + for (igraph_int_t i=0; i < vertex_neis_size; ++i) { + igraph_int_t v = VECTOR(*vertex_neis)[i]; if (v != vertex && ! VECTOR(*nei_mask)[v]) { VECTOR(*nei_mask)[v] = 1; /* mark as unprocessed neighbour */ neighbor_count++; @@ -452,9 +452,9 @@ static igraph_error_t igraph_i_local_efficiency_unweighted( return IGRAPH_SUCCESS; } - for (igraph_integer_t i=0; i < vertex_neis_size; ++i) { - igraph_integer_t source = VECTOR(*vertex_neis)[i]; - igraph_integer_t reached = 0; + for (igraph_int_t i=0; i < vertex_neis_size; ++i) { + igraph_int_t source = VECTOR(*vertex_neis)[i]; + igraph_int_t reached = 0; IGRAPH_ALLOW_INTERRUPTION(); @@ -472,9 +472,9 @@ static igraph_error_t igraph_i_local_efficiency_unweighted( while (!igraph_dqueue_int_empty(q)) { igraph_vector_int_t *act_neis; - igraph_integer_t act_neis_size; - igraph_integer_t act = igraph_dqueue_int_pop(q); - igraph_integer_t actdist = igraph_dqueue_int_pop(q); + igraph_int_t act_neis_size; + igraph_int_t act = igraph_dqueue_int_pop(q); + igraph_int_t actdist = igraph_dqueue_int_pop(q); if (act != source && VECTOR(*nei_mask)[act]) { *res += 1.0 / actdist; @@ -487,8 +487,8 @@ static igraph_error_t igraph_i_local_efficiency_unweighted( act_neis = igraph_adjlist_get(adjlist, act); act_neis_size = igraph_vector_int_size(act_neis); - for (igraph_integer_t j = 0; j < act_neis_size; j++) { - igraph_integer_t neighbor = VECTOR(*act_neis)[j]; + for (igraph_int_t j = 0; j < act_neis_size; j++) { + igraph_int_t neighbor = VECTOR(*act_neis)[j]; if (neighbor == vertex || already_counted[neighbor] == i + 1) continue; @@ -512,7 +512,7 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( igraph_vector_int_t *vertex_neis, igraph_vector_char_t *nei_mask, /* true if the corresponding node is a neighbour of 'vertex' */ igraph_real_t *res, - igraph_integer_t vertex, + igraph_int_t vertex, igraph_neimode_t mode, const igraph_vector_t *weights) { @@ -532,16 +532,16 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( and we want to spare that. -1 will denote infinity instead. */ - igraph_integer_t vertex_neis_size; - igraph_integer_t neighbor_count; /* unlike 'inc_edges_size', 'neighbor_count' does not count self-loops or multi-edges */ + igraph_int_t vertex_neis_size; + igraph_int_t neighbor_count; /* unlike 'inc_edges_size', 'neighbor_count' does not count self-loops or multi-edges */ IGRAPH_CHECK(igraph_neighbors(graph, vertex_neis, vertex, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); vertex_neis_size = igraph_vector_int_size(vertex_neis); igraph_vector_char_null(nei_mask); neighbor_count = 0; - for (igraph_integer_t i=0; i < vertex_neis_size; ++i) { - igraph_integer_t v = VECTOR(*vertex_neis)[i]; + for (igraph_int_t i=0; i < vertex_neis_size; ++i) { + igraph_int_t v = VECTOR(*vertex_neis)[i]; if (v != vertex && ! VECTOR(*nei_mask)[v]) { VECTOR(*nei_mask)[v] = 1; /* mark as unprocessed neighbour */ neighbor_count++; @@ -555,9 +555,9 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( return IGRAPH_SUCCESS; } - for (igraph_integer_t i=0; i < vertex_neis_size; ++i) { - igraph_integer_t source = VECTOR(*vertex_neis)[i]; - igraph_integer_t reached = 0; + for (igraph_int_t i=0; i < vertex_neis_size; ++i) { + igraph_int_t source = VECTOR(*vertex_neis)[i]; + igraph_int_t reached = 0; IGRAPH_ALLOW_INTERRUPTION(); @@ -573,10 +573,10 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( igraph_2wheap_push_with_index(Q, source, -1.0); while (!igraph_2wheap_empty(Q)) { - igraph_integer_t minnei = igraph_2wheap_max_index(Q); + igraph_int_t minnei = igraph_2wheap_max_index(Q); igraph_real_t mindist = -igraph_2wheap_deactivate_max(Q); igraph_vector_int_t *neis; - igraph_integer_t nlen; + igraph_int_t nlen; if (minnei != source && VECTOR(*nei_mask)[minnei]) { *res += 1.0/(mindist - 1.0); @@ -591,11 +591,11 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra( neis = igraph_lazy_inclist_get(inclist, minnei); IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nlen; j++) { + for (igraph_int_t j = 0; j < nlen; j++) { igraph_real_t altdist, curdist; igraph_bool_t active, has; - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei); + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, minnei); if (tto == vertex) { continue; @@ -689,13 +689,13 @@ igraph_error_t igraph_local_efficiency( const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, const igraph_vs_t vids, igraph_bool_t directed, igraph_neimode_t mode ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t nodes_to_calc; /* no. of vertices includes in computation */ + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t nodes_to_calc; /* no. of vertices includes in computation */ igraph_vit_t vit; igraph_vector_int_t vertex_neis; igraph_vector_char_t nei_mask; - igraph_integer_t i; + igraph_int_t i; /* 'nei_mask' is a vector indexed by vertices. The meaning of its values is as follows: * 0: not a neighbour of 'vertex' @@ -718,11 +718,11 @@ igraph_error_t igraph_local_efficiency( if (! weights) /* unweighted case */ { - igraph_integer_t *already_counted; + igraph_int_t *already_counted; igraph_adjlist_t adjlist; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; - already_counted = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + already_counted = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(already_counted, "Insufficient memory for local efficiency calculation."); IGRAPH_FINALLY(igraph_free, already_counted); @@ -843,7 +843,7 @@ igraph_error_t igraph_average_local_efficiency( const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, igraph_bool_t directed, igraph_neimode_t mode ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_t local_eff; /* If there are fewer than 3 vertices, no vertex has more than one neighbour, thus all @@ -916,18 +916,18 @@ igraph_error_t igraph_average_local_efficiency( */ static igraph_error_t igraph_i_diameter_unweighted( - const igraph_t *graph, igraph_real_t *res, igraph_integer_t *from, - igraph_integer_t *to, igraph_vector_int_t *vertex_path, + const igraph_t *graph, igraph_real_t *res, igraph_int_t *from, + igraph_int_t *to, igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path, igraph_bool_t directed, igraph_bool_t unconn ) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t n; - igraph_integer_t *already_added; - igraph_integer_t nodes_reached; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t n; + igraph_int_t *already_added; + igraph_int_t nodes_reached; /* from/to are initialized to 0 because in a singleton graph, or in an edgeless graph * with unconn = true, the diameter path will be considered to consist of vertex 0 only. */ - igraph_integer_t ifrom = 0, ito = 0; + igraph_int_t ifrom = 0, ito = 0; igraph_real_t ires = 0; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; @@ -961,7 +961,7 @@ static igraph_error_t igraph_i_diameter_unweighted( } else { dirmode = IGRAPH_ALL; } - already_added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + already_added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(already_added, "Insufficient memory for diameter calculation."); IGRAPH_FINALLY(igraph_free, already_added); @@ -970,7 +970,7 @@ static igraph_error_t igraph_i_diameter_unweighted( IGRAPH_CHECK(igraph_adjlist_init(graph, &allneis, dirmode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { nodes_reached = 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, i)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); @@ -981,8 +981,8 @@ static igraph_error_t igraph_i_diameter_unweighted( IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); if (actdist > ires) { ires = actdist; ifrom = i; @@ -991,8 +991,8 @@ static igraph_error_t igraph_i_diameter_unweighted( neis = igraph_adjlist_get(&allneis, actnode); n = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t neighbor = VECTOR(*neis)[j]; if (already_added[neighbor] == i + 1) { continue; } @@ -1049,7 +1049,7 @@ static igraph_error_t igraph_i_diameter_unweighted( static igraph_error_t igraph_i_diameter_dijkstra( const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, - igraph_integer_t *from, igraph_integer_t *to, igraph_vector_int_t *vertex_path, + igraph_int_t *from, igraph_int_t *to, igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path, igraph_bool_t directed, igraph_bool_t unconn ) { /* Implementation details. This is the basic Dijkstra algorithm, @@ -1067,8 +1067,8 @@ static igraph_error_t igraph_i_diameter_dijkstra( infinity instead. */ - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); igraph_2wheap_t Q; igraph_inclist_t inclist; @@ -1076,9 +1076,9 @@ static igraph_error_t igraph_i_diameter_dijkstra( /* from/to are initialized to 0 because in a singleton graph, or in an edgeless graph * with unconn = true, the diameter path will be considered to consist of vertex 0 only. */ - igraph_integer_t ifrom = 0, ito = 0; + igraph_int_t ifrom = 0, ito = 0; igraph_real_t ires = 0; - igraph_integer_t nodes_reached = 0; + igraph_int_t nodes_reached = 0; /* See https://github.com/igraph/igraph/issues/1538#issuecomment-724071857 * for why we return NaN for the null graph. */ @@ -1123,7 +1123,7 @@ static igraph_error_t igraph_i_diameter_dijkstra( IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, dirmode, IGRAPH_LOOPS)); IGRAPH_FINALLY(igraph_inclist_destroy, &inclist); - for (igraph_integer_t source = 0; source < no_of_nodes; source++) { + for (igraph_int_t source = 0; source < no_of_nodes; source++) { IGRAPH_PROGRESS("Weighted diameter: ", source * 100.0 / no_of_nodes, NULL); IGRAPH_ALLOW_INTERRUPTION(); @@ -1134,10 +1134,10 @@ static igraph_error_t igraph_i_diameter_dijkstra( nodes_reached = 0.0; while (!igraph_2wheap_empty(&Q)) { - igraph_integer_t minnei = igraph_2wheap_max_index(&Q); + igraph_int_t minnei = igraph_2wheap_max_index(&Q); igraph_real_t mindist = -igraph_2wheap_deactivate_max(&Q); igraph_vector_int_t *neis; - igraph_integer_t nlen; + igraph_int_t nlen; if (mindist > ires) { ires = mindist; ifrom = source; ito = minnei; @@ -1147,9 +1147,9 @@ static igraph_error_t igraph_i_diameter_dijkstra( /* Now check all neighbors of 'minnei' for a shorter path */ neis = igraph_inclist_get(&inclist, minnei); nlen = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei); + for (igraph_int_t j = 0; j < nlen; j++) { + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, minnei); igraph_real_t altdist = mindist + VECTOR(*weights)[edge]; igraph_bool_t active = igraph_2wheap_has_active(&Q, tto); igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto); @@ -1258,7 +1258,7 @@ static igraph_error_t igraph_i_diameter_dijkstra( */ igraph_error_t igraph_diameter( const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *res, - igraph_integer_t *from, igraph_integer_t *to, igraph_vector_int_t *vertex_path, + igraph_int_t *from, igraph_int_t *to, igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path, igraph_bool_t directed, igraph_bool_t unconn ) { if (weights) { @@ -1288,14 +1288,14 @@ igraph_error_t igraph_diameter( */ static igraph_error_t igraph_i_semidelete_vertex( const igraph_t *graph, igraph_vector_t *weights, - igraph_integer_t vid, igraph_vector_int_t *edges_removed, + igraph_int_t vid, igraph_vector_int_t *edges_removed, igraph_vector_int_t *eids ) { IGRAPH_CHECK(igraph_incident(graph, eids, vid, IGRAPH_ALL, IGRAPH_LOOPS)); - const igraph_integer_t n = igraph_vector_int_size(eids); - for (igraph_integer_t j = 0; j < n; j++) { - const igraph_integer_t eid = VECTOR(*eids)[j]; + const igraph_int_t n = igraph_vector_int_size(eids); + for (igraph_int_t j = 0; j < n; j++) { + const igraph_int_t eid = VECTOR(*eids)[j]; IGRAPH_CHECK(igraph_vector_int_push_back(edges_removed, eid)); VECTOR(*weights)[eid] = IGRAPH_INFINITY; } @@ -1306,9 +1306,9 @@ static igraph_error_t igraph_i_semidelete_vertex( static igraph_bool_t igraph_i_has_edge_with_infinite_weight( const igraph_vector_int_t* path, const igraph_vector_t* weights ) { - const igraph_integer_t n = weights ? igraph_vector_int_size(path) : 0; - for (igraph_integer_t i = 0; i < n; i++) { - const igraph_integer_t edge = VECTOR(*path)[i]; + const igraph_int_t n = weights ? igraph_vector_int_size(path) : 0; + for (igraph_int_t i = 0; i < n; i++) { + const igraph_int_t edge = VECTOR(*path)[i]; if (!isfinite(VECTOR(*weights)[edge])) { return true; } @@ -1320,13 +1320,13 @@ static igraph_bool_t igraph_i_has_edge_with_infinite_weight( static igraph_real_t igraph_i_get_total_weight_of_path( igraph_vector_int_t* path, const igraph_vector_t* weights ) { - const igraph_integer_t n = igraph_vector_int_size(path); + const igraph_int_t n = igraph_vector_int_size(path); igraph_real_t result; if (weights) { result = 0; - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t edge = VECTOR(*path)[i]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t edge = VECTOR(*path)[i]; result += VECTOR(*weights)[edge]; } } else { @@ -1403,22 +1403,22 @@ igraph_error_t igraph_get_k_shortest_paths( const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_list_t *vertex_paths, igraph_vector_int_list_t *edge_paths, - igraph_integer_t k, igraph_integer_t from, igraph_integer_t to, + igraph_int_t k, igraph_int_t from, igraph_int_t to, igraph_neimode_t mode ) { igraph_vector_int_list_t paths_pot; /* potential shortest paths */ - igraph_integer_t vertex_spur; + igraph_int_t vertex_spur; igraph_vector_int_t path_spur, path_root, path_total, path_shortest; - igraph_integer_t nr_edges_root, i_path_current, i_path, edge_path_root, vertex_root_del; - igraph_integer_t n; + igraph_int_t nr_edges_root, i_path_current, i_path, edge_path_root, vertex_root_del; + igraph_int_t n; igraph_vector_t current_weights; igraph_vector_int_t edges_removed; - const igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t infinite_path, already_in_potential_paths; igraph_vector_int_t *path_0; igraph_vector_int_t eids; igraph_real_t path_weight, shortest_path_weight; - igraph_integer_t edge_paths_owned = 0; + igraph_int_t edge_paths_owned = 0; if (!igraph_is_directed(graph) && (mode == IGRAPH_IN || mode == IGRAPH_OUT)) { mode = IGRAPH_ALL; @@ -1485,7 +1485,7 @@ igraph_error_t igraph_get_k_shortest_paths( for (i_path_current = 1; i_path_current < k; i_path_current++) { igraph_vector_int_t *path_previous = igraph_vector_int_list_tail_ptr(edge_paths); - igraph_integer_t path_previous_length = igraph_vector_int_size(path_previous); + igraph_int_t path_previous_length = igraph_vector_int_size(path_previous); for (nr_edges_root = 0; nr_edges_root < path_previous_length; nr_edges_root++) { /* Determine spur node. */ if (mode == IGRAPH_OUT) { @@ -1493,13 +1493,13 @@ igraph_error_t igraph_get_k_shortest_paths( } else if (mode == IGRAPH_IN) { vertex_spur = IGRAPH_TO(graph, VECTOR(*path_previous)[nr_edges_root]); } else { - igraph_integer_t eid = VECTOR(*path_previous)[nr_edges_root]; - igraph_integer_t vertex_spur_1 = IGRAPH_FROM(graph, eid); - igraph_integer_t vertex_spur_2 = IGRAPH_TO(graph, eid); - igraph_integer_t vertex_spur_3; - igraph_integer_t vertex_spur_4; + igraph_int_t eid = VECTOR(*path_previous)[nr_edges_root]; + igraph_int_t vertex_spur_1 = IGRAPH_FROM(graph, eid); + igraph_int_t vertex_spur_2 = IGRAPH_TO(graph, eid); + igraph_int_t vertex_spur_3; + igraph_int_t vertex_spur_4; if (nr_edges_root < path_previous_length-1) { - igraph_integer_t eid_next = VECTOR(*path_previous)[nr_edges_root + 1]; + igraph_int_t eid_next = VECTOR(*path_previous)[nr_edges_root + 1]; vertex_spur_3 = IGRAPH_FROM(graph, eid_next); vertex_spur_4 = IGRAPH_TO(graph, eid_next); } else { @@ -1514,7 +1514,7 @@ igraph_error_t igraph_get_k_shortest_paths( /* Determine root path. */ IGRAPH_CHECK(igraph_vector_int_resize(&path_root, nr_edges_root)); - for (igraph_integer_t i = 0; i < nr_edges_root; i++) { + for (igraph_int_t i = 0; i < nr_edges_root; i++) { VECTOR(path_root)[i] = VECTOR(*path_previous)[i]; } @@ -1522,7 +1522,7 @@ igraph_error_t igraph_get_k_shortest_paths( for (i_path = 0; i_path < i_path_current; i_path++) { igraph_vector_int_t *path_check = igraph_vector_int_list_get_ptr(edge_paths, i_path); igraph_bool_t equal = true; - for (igraph_integer_t i = 0; i < nr_edges_root; i++) { + for (igraph_int_t i = 0; i < nr_edges_root; i++) { if (VECTOR(path_root)[i] != VECTOR(*path_check)[i]) { equal = false; break; @@ -1543,12 +1543,12 @@ igraph_error_t igraph_get_k_shortest_paths( } else if (mode == IGRAPH_IN) { vertex_root_del = IGRAPH_TO(graph, VECTOR(path_root)[edge_path_root]); } else { - igraph_integer_t eid = VECTOR(*path_previous)[edge_path_root]; - igraph_integer_t eid_next = VECTOR(*path_previous)[edge_path_root + 1]; - igraph_integer_t vertex_root_del_1 = IGRAPH_FROM(graph, eid); - igraph_integer_t vertex_root_del_2 = IGRAPH_TO(graph, eid); - igraph_integer_t vertex_root_del_3 = IGRAPH_FROM(graph, eid_next); - igraph_integer_t vertex_root_del_4 = IGRAPH_TO(graph, eid_next); + igraph_int_t eid = VECTOR(*path_previous)[edge_path_root]; + igraph_int_t eid_next = VECTOR(*path_previous)[edge_path_root + 1]; + igraph_int_t vertex_root_del_1 = IGRAPH_FROM(graph, eid); + igraph_int_t vertex_root_del_2 = IGRAPH_TO(graph, eid); + igraph_int_t vertex_root_del_3 = IGRAPH_FROM(graph, eid_next); + igraph_int_t vertex_root_del_4 = IGRAPH_TO(graph, eid_next); if (vertex_root_del_1 == vertex_root_del_3 || vertex_root_del_1 == vertex_root_del_4) { vertex_root_del = vertex_root_del_2; } else { @@ -1579,7 +1579,7 @@ igraph_error_t igraph_get_k_shortest_paths( already_in_potential_paths = false; n = igraph_vector_int_list_size(&paths_pot); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { if (igraph_vector_int_all_e(&path_total, igraph_vector_int_list_get_ptr(&paths_pot, i))) { already_in_potential_paths = true; break; @@ -1593,7 +1593,7 @@ igraph_error_t igraph_get_k_shortest_paths( /* Cleanup */ n = igraph_vector_int_size(&edges_removed); - for (igraph_integer_t i = 0; i < n; i++) { + for (igraph_int_t i = 0; i < n; i++) { VECTOR(current_weights)[VECTOR(edges_removed)[i]] = weights ? VECTOR(*weights)[VECTOR(edges_removed)[i]] : 1; } @@ -1610,7 +1610,7 @@ igraph_error_t igraph_get_k_shortest_paths( igraph_vector_int_list_get_ptr(&paths_pot, 0), weights ); i_path = 0; - for (igraph_integer_t i = 1; i < n; i++) { + for (igraph_int_t i = 1; i < n; i++) { path_weight = igraph_i_get_total_weight_of_path( igraph_vector_int_list_get_ptr(&paths_pot, i), weights ); @@ -1634,10 +1634,10 @@ igraph_error_t igraph_get_k_shortest_paths( IGRAPH_FINALLY_CLEAN(7); if (vertex_paths) { - const igraph_integer_t no_of_edge_paths = igraph_vector_int_list_size(edge_paths); + const igraph_int_t no_of_edge_paths = igraph_vector_int_list_size(edge_paths); IGRAPH_CHECK(igraph_vector_int_list_resize(vertex_paths, no_of_edge_paths)); - for (igraph_integer_t i = 0; i < no_of_edge_paths; i++) { + for (igraph_int_t i = 0; i < no_of_edge_paths; i++) { igraph_vector_int_t* edge_path = igraph_vector_int_list_get_ptr(edge_paths, i); igraph_vector_int_t* vertex_path = igraph_vector_int_list_get_ptr(vertex_paths, i); IGRAPH_CHECK(igraph_vertex_path_from_edge_path(graph, from, edge_path, vertex_path, mode)); diff --git a/src/vendor/cigraph/src/paths/simple_paths.c b/src/vendor/cigraph/src/paths/simple_paths.c index 8c56fd2414d..630689a0227 100644 --- a/src/vendor/cigraph/src/paths/simple_paths.c +++ b/src/vendor/cigraph/src/paths/simple_paths.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2014-2024 The igraph development team This program is free software; you can redistribute it and/or modify @@ -47,10 +47,6 @@ * they are found. * \param from The start vertex. * \param to The target vertices. - * \param minlen Minimum length of paths that is considered. If negative, - * no lower bound is used on the path lengths. - * \param maxlen Maximum length of paths that is considered. If negative, - * no upper bound is used on the path lengths. * \param mode The type of paths to be used for the calculation in directed * graphs. Possible values: * \clist @@ -62,6 +58,12 @@ * the directed graph is considered as an undirected one for * the computation. * \endclist + * \param minlen Minimum length of paths that is considered. If negative + * or \ref IGRAPH_UNLIMITED, no lower bound is used on the path lengths. + * \param maxlen Maximum length of paths that is considered. If negative + * or \ref IGRAPH_UNLIMITED, no upper bound is used on the path lengths. + * \param max_results At most this many paths will be recorded. If + * negative, or \ref IGRAPH_UNLIMITED, no limit is applied. * \return Error code. * * \sa \ref igraph_get_k_shortest_paths() @@ -73,13 +75,12 @@ igraph_error_t igraph_get_all_simple_paths( const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_integer_t from, - const igraph_vs_t to, - igraph_integer_t minlen, - igraph_integer_t maxlen, - igraph_neimode_t mode) { + igraph_int_t from, const igraph_vs_t to, + igraph_neimode_t mode, + igraph_int_t minlen, igraph_int_t maxlen, + igraph_int_t max_results) { - const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_int_t vcount = igraph_vcount(graph); const igraph_bool_t toall = igraph_vs_is_all(&to); igraph_vit_t vit; igraph_lazy_adjlist_t adjlist; @@ -93,6 +94,12 @@ igraph_error_t igraph_get_all_simple_paths( IGRAPH_ERROR("Index of source vertex is out of range.", IGRAPH_EINVVID); } + igraph_vector_int_list_clear(res); + + if (max_results == 0) { + return IGRAPH_SUCCESS; + } + if (!toall) { IGRAPH_BITSET_INIT_FINALLY(&markto, vcount); IGRAPH_CHECK(igraph_vit_create(graph, to, &vit)); @@ -113,25 +120,23 @@ igraph_error_t igraph_get_all_simple_paths( IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); IGRAPH_VECTOR_INT_INIT_FINALLY(&nptr, vcount); - igraph_vector_int_list_clear(res); - igraph_vector_int_clear(&stack); igraph_vector_int_clear(&dist); - igraph_vector_int_push_back(&stack, from); - igraph_vector_int_push_back(&dist, 0); + igraph_vector_int_push_back(&stack, from); /* reserved enough for initial push */ + igraph_vector_int_push_back(&dist, 0); /* reserved enough for initial push */ IGRAPH_BIT_SET(added, from); while (!igraph_vector_int_empty(&stack)) { - const igraph_integer_t act = igraph_vector_int_tail(&stack); - const igraph_integer_t curdist = igraph_vector_int_tail(&dist); + const igraph_int_t act = igraph_vector_int_tail(&stack); + const igraph_int_t curdist = igraph_vector_int_tail(&dist); const igraph_vector_int_t *neis = igraph_lazy_adjlist_get(&adjlist, act); IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); - const igraph_integer_t n = igraph_vector_int_size(neis); - igraph_integer_t *ptr = igraph_vector_int_get_ptr(&nptr, act); + const igraph_int_t n = igraph_vector_int_size(neis); + igraph_int_t *ptr = igraph_vector_int_get_ptr(&nptr, act); igraph_bool_t any; igraph_bool_t within_dist; - igraph_integer_t nei; + igraph_int_t nei; within_dist = (curdist < maxlen || maxlen < 0); if (within_dist) { @@ -152,11 +157,14 @@ igraph_error_t igraph_get_all_simple_paths( if (toall || IGRAPH_BIT_TEST(markto, nei)) { if (curdist + 1 >= minlen) { IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(res, &stack)); + if (max_results >= 0 && igraph_vector_int_list_size(res) == max_results) { + break; + } } } } else { /* There is no such neighbor, finished with the subtree */ - igraph_integer_t up = igraph_vector_int_pop_back(&stack); + igraph_int_t up = igraph_vector_int_pop_back(&stack); igraph_vector_int_pop_back(&dist); IGRAPH_BIT_CLEAR(added, up); VECTOR(nptr)[up] = 0; diff --git a/src/vendor/cigraph/src/paths/sparsifier.c b/src/vendor/cigraph/src/paths/sparsifier.c index c27e487fe4b..1d9a1405c31 100644 --- a/src/vendor/cigraph/src/paths/sparsifier.c +++ b/src/vendor/cigraph/src/paths/sparsifier.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -49,31 +49,31 @@ * one is O(|V|), while igraph_i_clean_lightest_edge_vector() is O(d) where d * is the degree of the vertex. */ -static igraph_error_t igraph_i_collect_lightest_edges_to_clusters( +static igraph_error_t collect_lightest_edges_to_clusters( const igraph_adjlist_t *adjlist, const igraph_inclist_t *inclist, const igraph_vector_t *weights, const igraph_vector_int_t *clustering, const igraph_bitset_t *is_cluster_sampled, - igraph_integer_t v, + igraph_int_t v, igraph_vector_int_t *lightest_eid, igraph_vector_t *lightest_weight, igraph_vector_int_t *dirty_vids, - igraph_integer_t *nearest_neighboring_sampled_cluster + igraph_int_t *nearest_neighboring_sampled_cluster ) { // This internal function gets the residual graph, the clustering, the sampled clustering and - // the vector and return the lightest edge to each neighboring cluster and the index of the lightest + // the vector and returns the lightest edge to each neighboring cluster and the index of the lightest // sampled cluster (if any) igraph_real_t lightest_weight_to_sampled = IGRAPH_INFINITY; - igraph_vector_int_t* adjacent_nodes = igraph_adjlist_get(adjlist, v); - igraph_vector_int_t* incident_edges = igraph_inclist_get(inclist, v); - igraph_integer_t i, nlen = igraph_vector_int_size(incident_edges); - - for (i = 0; i < nlen; i++) { - igraph_integer_t neighbor_node = VECTOR(*adjacent_nodes)[i]; - igraph_integer_t edge = VECTOR(*incident_edges)[i]; - igraph_integer_t neighbor_cluster = VECTOR(*clustering)[neighbor_node]; + const igraph_vector_int_t *adjacent_nodes = igraph_adjlist_get(adjlist, v); + const igraph_vector_int_t *incident_edges = igraph_inclist_get(inclist, v); + const igraph_int_t nlen = igraph_vector_int_size(incident_edges); + + for (igraph_int_t i = 0; i < nlen; i++) { + igraph_int_t neighbor_node = VECTOR(*adjacent_nodes)[i]; + igraph_int_t edge = VECTOR(*incident_edges)[i]; + igraph_int_t neighbor_cluster = VECTOR(*clustering)[neighbor_node]; igraph_real_t weight = weights ? VECTOR(*weights)[edge] : 1; // If the weight of the edge being considered is smaller than the weight @@ -100,14 +100,14 @@ static igraph_error_t igraph_i_collect_lightest_edges_to_clusters( return IGRAPH_SUCCESS; } -static void igraph_i_clear_lightest_edges_to_clusters( +static void clear_lightest_edges_to_clusters( igraph_vector_int_t *dirty_vids, igraph_vector_int_t *lightest_eid, igraph_vector_t *lightest_weight ) { - igraph_integer_t i, n = igraph_vector_int_size(dirty_vids); - for (i = 0; i < n; i++) { - igraph_integer_t vid = VECTOR(*dirty_vids)[i]; + const igraph_int_t n = igraph_vector_int_size(dirty_vids); + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t vid = VECTOR(*dirty_vids)[i]; VECTOR(*lightest_weight)[vid] = IGRAPH_INFINITY; VECTOR(*lightest_eid)[vid] = -1; } @@ -143,12 +143,7 @@ static void igraph_i_clear_lightest_edges_to_clusters( * graph object. * \param stretch The stretch factor \c t of the spanner. * \param weights The edge weights or \c NULL. - * - * \return Error code: - * \clist - * \cli IGRAPH_ENOMEM - * not enough memory for temporary data. - * \endclist + * \return Error code. * * Time complexity: The algorithm is a randomized Las Vegas algorithm. The expected * running time is O(km) where k is the value mentioned above and m is the number @@ -157,9 +152,9 @@ static void igraph_i_clear_lightest_edges_to_clusters( igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanner, igraph_real_t stretch, const igraph_vector_t *weights) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); - const igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t i, j, v, nlen, neighbor, cluster; + const igraph_int_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t nlen, neighbor, cluster; igraph_real_t sample_prob, k = (stretch + 1) / 2, weight, lightest_sampled_weight; igraph_vector_int_t clustering, lightest_eid; igraph_vector_t lightest_weight; @@ -171,8 +166,8 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne igraph_vector_int_t *incident_edges; igraph_adjlist_t adjlist; igraph_inclist_t inclist; - igraph_integer_t edge; - igraph_integer_t index; + igraph_int_t edge; + igraph_int_t index; if (spanner == NULL) { return IGRAPH_SUCCESS; @@ -220,14 +215,14 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne // A mapping vector which indicates the neighboring edge with the smallest // weight for each cluster central, for a single vertex of interest. - // Preconditions needed by igraph_i_collect_lightest_edges_to_clusters() + // Preconditions needed by collect_lightest_edges_to_clusters() // are enforced here. IGRAPH_VECTOR_INT_INIT_FINALLY(&lightest_eid, no_of_nodes); igraph_vector_int_fill(&lightest_eid, -1); // A mapping vector which indicated the minimum weight to each neighboring // cluster, for a single vertex of interest. - // Preconditions needed by igraph_i_collect_lightest_edges_to_clusters() + // Preconditions needed by collect_lightest_edges_to_clusters() // are enforced here. IGRAPH_VECTOR_INIT_FINALLY(&lightest_weight, no_of_nodes); igraph_vector_fill(&lightest_weight, IGRAPH_INFINITY); @@ -239,35 +234,35 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne IGRAPH_BITSET_INIT_FINALLY(&is_cluster_sampled, no_of_nodes); IGRAPH_BITSET_INIT_FINALLY(&is_edge_in_spanner, no_of_edges); - // Temporary vector used by igraph_i_collect_lightest_edges_to_clusters() + // Temporary vector used by collect_lightest_edges_to_clusters() // to keep track of the nodes that it has written to IGRAPH_VECTOR_INT_INIT_FINALLY(&dirty_vids, 0); - sample_prob = pow(no_of_nodes, -1 / k); + sample_prob = pow((igraph_real_t) no_of_nodes, -1 / k); #define ADD_EDGE_TO_SPANNER \ - if (!IGRAPH_BIT_TEST(is_edge_in_spanner, edge)) { \ + do { if (!IGRAPH_BIT_TEST(is_edge_in_spanner, edge)) { \ IGRAPH_BIT_SET(is_edge_in_spanner, edge); \ IGRAPH_CHECK(igraph_vector_int_push_back(spanner, edge)); \ - } + } } while (0) igraph_vector_fill(&lightest_weight, IGRAPH_INFINITY); - for (i = 0; i < k - 1; i++) { + for (igraph_int_t i = 0; i < k - 1; i++) { IGRAPH_ALLOW_INTERRUPTION(); igraph_vector_int_fill(&new_clustering, -1); igraph_bitset_null(&is_cluster_sampled); // Step 1: sample cluster centers - for (j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { if (VECTOR(clustering)[j] == j && RNG_UNIF01() < sample_prob) { IGRAPH_BIT_SET(is_cluster_sampled, j); } } // Step 2 and 3 - for (v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { // If v is inside a cluster and the cluster of v is sampled, then continue cluster = VECTOR(clustering)[v]; if (cluster != -1 && IGRAPH_BIT_TEST(is_cluster_sampled, cluster)) { @@ -277,18 +272,18 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne // Step 2: find the lightest edge that connects vertex v to its // neighboring sampled clusters - igraph_integer_t nearest_neighboring_sampled_cluster = -1; - IGRAPH_CHECK(igraph_i_collect_lightest_edges_to_clusters( - &adjlist, - &inclist, - weights, - &clustering, - &is_cluster_sampled, - v, - &lightest_eid, - &lightest_weight, - &dirty_vids, - &nearest_neighboring_sampled_cluster + igraph_int_t nearest_neighboring_sampled_cluster = -1; + IGRAPH_CHECK(collect_lightest_edges_to_clusters( + &adjlist, + &inclist, + weights, + &clustering, + &is_cluster_sampled, + v, + &lightest_eid, + &lightest_weight, + &dirty_vids, + &nearest_neighboring_sampled_cluster )); // Step 3: add edges to spanner @@ -298,7 +293,7 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne // Add lightest edge which connects vertex v to each neighboring // cluster (none of which are sampled) - for (j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { edge = VECTOR(lightest_eid)[j]; if (edge != -1) { ADD_EDGE_TO_SPANNER; @@ -311,7 +306,7 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne adjacent_vertices = igraph_adjlist_get(&adjlist, v); incident_edges = igraph_inclist_get(&inclist, v); nlen = igraph_vector_int_size(incident_edges); - for (j = 0; j < nlen; j++) { + for (igraph_int_t j = 0; j < nlen; j++) { neighbor = VECTOR(*adjacent_vertices)[j]; if (neighbor == v) { /* should not happen as we did not ask for loop edges in @@ -346,7 +341,7 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne VECTOR(new_clustering)[v] = nearest_neighboring_sampled_cluster; // Add to the spanner light edges with weight less than 'lightest_sampled_weight' - for (j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { if (VECTOR(lightest_weight)[j] < lightest_sampled_weight) { edge = VECTOR(lightest_eid)[j]; ADD_EDGE_TO_SPANNER; @@ -357,7 +352,7 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne adjacent_vertices = igraph_adjlist_get(&adjlist, v); incident_edges = igraph_inclist_get(&inclist, v); nlen = igraph_vector_int_size(incident_edges); - for (j = 0; j < nlen; j++) { + for (igraph_int_t j = 0; j < nlen; j++) { neighbor = VECTOR(*adjacent_vertices)[j]; if (neighbor == v) { /* should not happen as we did not ask for loop edges in @@ -386,10 +381,10 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne } } - // We don't need lightest_eids and lightest_weights any more so + // We don't need lightest_eids and lightest_weights anymore so // clear them in O(d) time - igraph_i_clear_lightest_edges_to_clusters( - &dirty_vids, &lightest_eid, &lightest_weight + clear_lightest_edges_to_clusters( + &dirty_vids, &lightest_eid, &lightest_weight ); } @@ -397,11 +392,11 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne igraph_vector_int_update(&clustering, &new_clustering); /* reserved */ // Remove intra-cluster edges - for (v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { adjacent_vertices = igraph_adjlist_get(&adjlist, v); incident_edges = igraph_inclist_get(&inclist, v); nlen = igraph_vector_int_size(incident_edges); - for (j = 0; j < nlen; j++) { + for (igraph_int_t j = 0; j < nlen; j++) { neighbor = VECTOR(*adjacent_vertices)[j]; edge = VECTOR(*incident_edges)[j]; @@ -420,27 +415,27 @@ igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanne } // Phase 2: vertex_clustering joining - for (v = 0; v < no_of_nodes; v++) { + for (igraph_int_t v = 0; v < no_of_nodes; v++) { if (VECTOR(clustering)[v] != -1) { - IGRAPH_CHECK(igraph_i_collect_lightest_edges_to_clusters( - &adjlist, - &inclist, - weights, - &clustering, - /* is_cluster_sampled = */ NULL, - v, - &lightest_eid, - &lightest_weight, - &dirty_vids, - NULL + IGRAPH_CHECK(collect_lightest_edges_to_clusters( + &adjlist, + &inclist, + weights, + &clustering, + /* is_cluster_sampled = */ NULL, + v, + &lightest_eid, + &lightest_weight, + &dirty_vids, + NULL )); - for (j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < no_of_nodes; j++) { edge = VECTOR(lightest_eid)[j]; if (edge != -1) { ADD_EDGE_TO_SPANNER; } } - igraph_i_clear_lightest_edges_to_clusters(&dirty_vids, &lightest_eid, &lightest_weight); + clear_lightest_edges_to_clusters(&dirty_vids, &lightest_eid, &lightest_weight); } } diff --git a/src/vendor/cigraph/src/paths/unweighted.c b/src/vendor/cigraph/src/paths/unweighted.c index c8a34b5c068..ad691c0022b 100644 --- a/src/vendor/cigraph/src/paths/unweighted.c +++ b/src/vendor/cigraph/src/paths/unweighted.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2005-2021 The igraph development team + igraph library. + Copyright (C) 2005-2025 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 @@ -24,17 +24,7 @@ #include "igraph_memory.h" #include "core/interruption.h" - -static igraph_error_t igraph_i_distances_cutoff_unweighted( - const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode, igraph_real_t cutoff -); -static igraph_error_t igraph_i_get_shortest_paths_unweighted( - const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode, - igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges -); +#include "paths/paths_internal.h" /** * \ingroup structural @@ -71,8 +61,8 @@ static igraph_error_t igraph_i_get_shortest_paths_unweighted( * \endclist * \param cutoff The maximal length of paths that will be considered. * When the distance of two vertices is greater than this value, - * it will be returned as \c IGRAPH_INFINITY. Negative cutoffs are - * treated as infinity. + * it will be returned as \c IGRAPH_INFINITY. Negative cutoffs and + * \ref IGRAPH_UNLIMITED are treated as infinity. * \return Error code: * \clist * \cli IGRAPH_ENOMEM @@ -93,33 +83,38 @@ static igraph_error_t igraph_i_get_shortest_paths_unweighted( * \example examples/simple/distances.c */ igraph_error_t igraph_distances_cutoff( - const igraph_t *graph, const igraph_vector_t* weights, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode, igraph_real_t cutoff -) { + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, + igraph_neimode_t mode, + igraph_real_t cutoff) { + if (weights == NULL) { /* Unweighted distances */ - return igraph_i_distances_cutoff_unweighted(graph, res, from, to, mode, cutoff); + return igraph_i_distances_unweighted_cutoff(graph, res, from, to, mode, cutoff); } else { /* Dijkstra's algorithm; will return an error if there are negative weights */ return igraph_distances_dijkstra_cutoff(graph, res, from, to, weights, mode, cutoff); } } -static igraph_error_t igraph_i_distances_cutoff_unweighted( - const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, - igraph_neimode_t mode, igraph_real_t cutoff -) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_from, no_of_to; - igraph_integer_t *already_counted; +igraph_error_t igraph_i_distances_unweighted_cutoff( + const igraph_t *graph, + igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, + igraph_neimode_t mode, + igraph_real_t cutoff) { + + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_from, no_of_to; + igraph_int_t *already_counted; igraph_adjlist_t adjlist; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; igraph_vector_int_t *neis; igraph_bool_t all_to; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_vit_t fromvit, tovit; igraph_vector_int_t indexv; @@ -135,7 +130,7 @@ static igraph_error_t igraph_i_distances_cutoff_unweighted( IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); - already_counted = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + already_counted = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(already_counted, "Insufficient memory for graph distance calculation."); IGRAPH_FINALLY(igraph_free, already_counted); @@ -150,7 +145,7 @@ static igraph_error_t igraph_i_distances_cutoff_unweighted( IGRAPH_FINALLY(igraph_vit_destroy, &tovit); no_of_to = IGRAPH_VIT_SIZE(tovit); for (i = 0; !IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit)) { - igraph_integer_t v = IGRAPH_VIT_GET(tovit); + igraph_int_t v = IGRAPH_VIT_GET(tovit); if (VECTOR(indexv)[v]) { IGRAPH_ERROR("Target vertex list must not have any duplicates.", IGRAPH_EINVAL); @@ -165,7 +160,7 @@ static igraph_error_t igraph_i_distances_cutoff_unweighted( for (IGRAPH_VIT_RESET(fromvit), i = 0; !IGRAPH_VIT_END(fromvit); IGRAPH_VIT_NEXT(fromvit), i++) { - igraph_integer_t reached = 0; + igraph_int_t reached = 0; IGRAPH_CHECK(igraph_dqueue_int_push(&q, IGRAPH_VIT_GET(fromvit))); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); already_counted[ IGRAPH_VIT_GET(fromvit) ] = i + 1; @@ -173,8 +168,8 @@ static igraph_error_t igraph_i_distances_cutoff_unweighted( IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t act = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t act = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); if (cutoff >= 0 && actdist > cutoff) { continue; @@ -194,9 +189,9 @@ static igraph_error_t igraph_i_distances_cutoff_unweighted( } neis = igraph_adjlist_get(&adjlist, act); - igraph_integer_t nei_count = igraph_vector_int_size(neis); + igraph_int_t nei_count = igraph_vector_int_size(neis); for (j = 0; j < nei_count; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + igraph_int_t neighbor = VECTOR(*neis)[j]; if (already_counted[neighbor] == i + 1) { continue; } @@ -276,23 +271,56 @@ static igraph_error_t igraph_i_distances_cutoff_unweighted( * \example examples/simple/distances.c */ igraph_error_t igraph_distances( - const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *res, - const igraph_vs_t from, const igraph_vs_t to, igraph_neimode_t mode -) { - igraph_integer_t from_size; - - if (weights == NULL || igraph_vector_size(weights) == 0 || igraph_vector_min(weights) >= 0) { - /* These are handled by igraph_distances_cutoff() */ - return igraph_distances_cutoff(graph, weights, res, from, to, mode, -1); + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_matrix_t *res, + const igraph_vs_t from, const igraph_vs_t to, + igraph_neimode_t mode) { + + igraph_real_t vcount_real = igraph_vcount(graph); + igraph_real_t ecount_real = igraph_ecount(graph); + igraph_real_t ecount_threshold; + igraph_int_t from_size; + igraph_bool_t negative_weights = false; + + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + + if (!igraph_is_directed(graph)) { + mode = IGRAPH_ALL; + } + + /* Edge count threshold for using Floyd-Warshall for all-to-all case. + * Based on experiments, this is faster than Dijkstra for densities + * above 0.1, provided that the graph has more than about 50 vertices. + * See also https://github.com/igraph/igraph/issues/2822 */ + ecount_threshold = vcount_real * vcount_real * 0.1; + if (ecount_threshold < 250) ecount_threshold = 250; + + if (!weights) { + /* Unweighted case */ + return igraph_i_distances_unweighted_cutoff(graph, res, from, to, mode, -1); + } else if (igraph_vs_is_all(&from) && ecount_real > ecount_threshold) { + /* All-to-all distances with dense graph */ + return igraph_distances_floyd_warshall(graph, res, from, to, weights, mode, IGRAPH_FLOYD_WARSHALL_AUTOMATIC); + } else if (!negative_weights) { + /* Non-negative weights: use Dijkstra's algorithm. */ + return igraph_i_distances_dijkstra_cutoff(graph, res, from, to, weights, mode, -1); } else { - /* Negative weights; will use Bellman-Ford or Johnson algorithm */ - if (mode != IGRAPH_OUT) { + /* Negative weights: use Bellman-Ford or Johnson's algorithm. + * + * In the undirected case we always use Bellman-Ford. Normally, a negative weight + * undirected edge triggers an error as it is effectively a negative cycle. + * However, with Bellman-Ford the negative edge might be avoided if it is + * not reachable from the 'from' vertices. In cotrast, Johnson will always raise + * an error. + */ + if (mode != IGRAPH_ALL) { IGRAPH_CHECK(igraph_vs_size(graph, &from, &from_size)); - if (from_size <= 100) { - return igraph_distances_bellman_ford(graph, res, from, to, weights, mode); + if (from_size > 100) { + return igraph_i_distances_johnson(graph, res, from, to, weights, mode); } } - return igraph_distances_johnson(graph, res, from, to, weights, mode); + return igraph_i_distances_bellman_ford(graph, res, from, to, weights, mode); } } @@ -374,41 +402,52 @@ igraph_error_t igraph_distances( * \example examples/simple/igraph_get_shortest_paths.c */ igraph_error_t igraph_get_shortest_paths( - const igraph_t *graph, const igraph_vector_t *weights, - igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode, - igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges -) { + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, const igraph_vs_t to, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges) { + + igraph_bool_t negative_weights; + IGRAPH_CHECK(igraph_i_validate_distance_weights(graph, weights, &negative_weights)); + if (weights == NULL) { return igraph_i_get_shortest_paths_unweighted(graph, vertices, edges, from, to, mode, parents, inbound_edges); - } else if (igraph_vector_size(weights) == 0 || igraph_vector_min(weights) >= 0) { + } else if (!negative_weights) { /* Dijkstra's algorithm */ - return igraph_get_shortest_paths_dijkstra(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); + return igraph_i_get_shortest_paths_dijkstra(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); } else { /* Negative weights; will use Bellman-Ford algorithm */ - return igraph_get_shortest_paths_bellman_ford(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); + return igraph_i_get_shortest_paths_bellman_ford(graph, vertices, edges, from, to, weights, mode, parents, inbound_edges); } } -static igraph_error_t igraph_i_get_shortest_paths_unweighted( - const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, const igraph_vs_t to, igraph_neimode_t mode, - igraph_vector_int_t *parents, igraph_vector_int_t *inbound_edges -) { +igraph_error_t igraph_i_get_shortest_paths_unweighted( + const igraph_t *graph, + igraph_vector_int_list_t *vertices, + igraph_vector_int_list_t *edges, + igraph_int_t from, igraph_vs_t to, + igraph_neimode_t mode, + igraph_vector_int_t *parents, + igraph_vector_int_t *inbound_edges) { + /* TODO: use inclist_t if to is long (longer than 1?) */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t *parent_eids; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t *parent_eids; igraph_dqueue_int_t q = IGRAPH_DQUEUE_NULL; - igraph_integer_t i, j, vsize; + igraph_int_t i, j, vsize; igraph_vector_int_t tmp = IGRAPH_VECTOR_NULL; igraph_vit_t vit; - igraph_integer_t to_reach; - igraph_integer_t reached = 0; + igraph_int_t to_reach; + igraph_int_t reached = 0; if (from < 0 || from >= no_of_nodes) { IGRAPH_ERROR("Index of source vertex is out of range.", IGRAPH_EINVVID); @@ -428,7 +467,7 @@ static igraph_error_t igraph_i_get_shortest_paths_unweighted( IGRAPH_CHECK(igraph_vector_int_list_resize(edges, IGRAPH_VIT_SIZE(vit))); } - parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(parent_eids, "Insufficient memory for shortest path calculation."); IGRAPH_FINALLY(igraph_free, parent_eids); @@ -466,13 +505,13 @@ static igraph_error_t igraph_i_get_shortest_paths_unweighted( parent_eids[ from ] = 1; while (!igraph_dqueue_int_empty(&q) && reached < to_reach) { - igraph_integer_t act = igraph_dqueue_int_pop(&q) - 1; + igraph_int_t act = igraph_dqueue_int_pop(&q) - 1; IGRAPH_CHECK(igraph_incident(graph, &tmp, act, mode, IGRAPH_LOOPS)); vsize = igraph_vector_int_size(&tmp); for (j = 0; j < vsize; j++) { - igraph_integer_t edge = VECTOR(tmp)[j]; - igraph_integer_t neighbor = IGRAPH_OTHER(graph, edge, act); + igraph_int_t edge = VECTOR(tmp)[j]; + igraph_int_t neighbor = IGRAPH_OTHER(graph, edge, act); if (parent_eids[neighbor] > 0) { continue; } else if (parent_eids[neighbor] < 0) { @@ -525,7 +564,7 @@ static igraph_error_t igraph_i_get_shortest_paths_unweighted( for (IGRAPH_VIT_RESET(vit), j = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), j++) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); + igraph_int_t node = IGRAPH_VIT_GET(vit); igraph_vector_int_t *vvec = 0, *evec = 0; if (vertices) { vvec = igraph_vector_int_list_get_ptr(vertices, j); @@ -539,9 +578,9 @@ static igraph_error_t igraph_i_get_shortest_paths_unweighted( IGRAPH_ALLOW_INTERRUPTION(); if (parent_eids[node] > 0) { - igraph_integer_t act = node; - igraph_integer_t size = 0; - igraph_integer_t edge; + igraph_int_t act = node; + igraph_int_t size = 0; + igraph_int_t edge; while (parent_eids[act] > 1) { size++; edge = parent_eids[act] - 2; @@ -620,13 +659,13 @@ static igraph_error_t igraph_i_get_shortest_paths_unweighted( * \sa \ref igraph_get_shortest_paths() for the version with more target * vertices. */ - igraph_error_t igraph_get_shortest_path( - const igraph_t *graph, const igraph_vector_t *weights, - igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, igraph_integer_t to, - igraph_neimode_t mode -) { + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_vector_int_t *vertices, + igraph_vector_int_t *edges, + igraph_int_t from, igraph_int_t to, + igraph_neimode_t mode) { igraph_vector_int_list_t vertices2, *vp = &vertices2; igraph_vector_int_list_t edges2, *ep = &edges2; diff --git a/src/vendor/cigraph/src/paths/voronoi.c b/src/vendor/cigraph/src/paths/voronoi.c index 01eedea1b70..4646b281def 100644 --- a/src/vendor/cigraph/src/paths/voronoi.c +++ b/src/vendor/cigraph/src/paths/voronoi.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -35,8 +35,8 @@ static igraph_error_t igraph_i_voronoi( igraph_neimode_t mode, igraph_voronoi_tiebreaker_t tiebreaker) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_generators = igraph_vector_int_size(generators); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_generators = igraph_vector_int_size(generators); igraph_adjlist_t al; igraph_dqueue_int_t q; @@ -69,8 +69,8 @@ static igraph_error_t igraph_i_voronoi( * is shorter than what was recorded so far in 'mindist', we update 'mindist' and * assign that vertex to the current generator. */ - for (igraph_integer_t i=0; i < no_of_generators; i++) { - igraph_integer_t g = VECTOR(*generators)[i]; + for (igraph_int_t i=0; i < no_of_generators; i++) { + igraph_int_t g = VECTOR(*generators)[i]; IGRAPH_ALLOW_INTERRUPTION(); @@ -83,10 +83,10 @@ static igraph_error_t igraph_i_voronoi( IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t vid = igraph_dqueue_int_pop(&q); - igraph_integer_t dist = igraph_dqueue_int_pop(&q); + igraph_int_t vid = igraph_dqueue_int_pop(&q); + igraph_int_t dist = igraph_dqueue_int_pop(&q); - /* Attention! This must be igraph_real_t, not igraph_integer_t + /* Attention! This must be igraph_real_t, not igraph_int_t * because later it will be compared with another igraph_real_t * whose value may be infinite. */ igraph_real_t md = VECTOR(*mindist)[vid]; @@ -128,9 +128,9 @@ static igraph_error_t igraph_i_voronoi( } igraph_vector_int_t *neis = igraph_adjlist_get(&al, vid); - igraph_integer_t nei_count = igraph_vector_int_size(neis); - for (igraph_integer_t j = 0; j < nei_count; j++) { - igraph_integer_t neighbor = VECTOR(*neis)[j]; + igraph_int_t nei_count = igraph_vector_int_size(neis); + for (igraph_int_t j = 0; j < nei_count; j++) { + igraph_int_t neighbor = VECTOR(*neis)[j]; if (VECTOR(already_counted)[neighbor] == i + 1) { continue; } @@ -164,9 +164,9 @@ static igraph_error_t igraph_i_voronoi_dijkstra( igraph_neimode_t mode, igraph_voronoi_tiebreaker_t tiebreaker) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_generators = igraph_vector_int_size(generators); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_generators = igraph_vector_int_size(generators); igraph_inclist_t il; igraph_2wheap_t q; @@ -211,8 +211,8 @@ static igraph_error_t igraph_i_voronoi_dijkstra( * is shorter than what was recorded so far in 'mindist', we update 'mindist' and * assign that vertex to the current generator. */ - for (igraph_integer_t i=0; i < no_of_generators; i++) { - igraph_integer_t g = VECTOR(*generators)[i]; + for (igraph_int_t i=0; i < no_of_generators; i++) { + igraph_int_t g = VECTOR(*generators)[i]; /* Weighted shortest path implementation using Dijkstra's algorithm */ @@ -226,7 +226,7 @@ static igraph_error_t igraph_i_voronoi_dijkstra( IGRAPH_CHECK(igraph_2wheap_push_with_index(&q, g, -0.0)); while (!igraph_2wheap_empty(&q)) { - igraph_integer_t vid = igraph_2wheap_max_index(&q); + igraph_int_t vid = igraph_2wheap_max_index(&q); igraph_real_t dist = -igraph_2wheap_deactivate_max(&q); igraph_real_t md = VECTOR(*mindist)[vid]; @@ -269,9 +269,9 @@ static igraph_error_t igraph_i_voronoi_dijkstra( } igraph_vector_int_t *inc_edges = igraph_inclist_get(&il, vid); - igraph_integer_t inc_count = igraph_vector_int_size(inc_edges); - for (igraph_integer_t j=0; j < inc_count; j++) { - igraph_integer_t edge = VECTOR(*inc_edges)[j]; + igraph_int_t inc_count = igraph_vector_int_size(inc_edges); + for (igraph_int_t j=0; j < inc_count; j++) { + igraph_int_t edge = VECTOR(*inc_edges)[j]; igraph_real_t weight = VECTOR(*weights)[edge]; /* Optimization: do not follow infinite-weight edges. */ @@ -279,7 +279,7 @@ static igraph_error_t igraph_i_voronoi_dijkstra( continue; } - igraph_integer_t to = IGRAPH_OTHER(graph, edge, vid); + igraph_int_t to = IGRAPH_OTHER(graph, edge, vid); igraph_real_t altdist = dist + weight; if (! igraph_2wheap_has_elem(&q, to)) { @@ -313,8 +313,6 @@ static igraph_error_t igraph_i_voronoi_dijkstra( * \function igraph_voronoi * \brief Voronoi partitioning of a graph. * - * \experimental - * * To obtain a Voronoi partitioning of a graph, we start with a set of generator * vertices, which will define the partitions. Each vertex is assigned to the generator * vertex from (or to) which it is closest. @@ -367,7 +365,7 @@ igraph_error_t igraph_voronoi( igraph_neimode_t mode, igraph_voronoi_tiebreaker_t tiebreaker) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t *pmembership; igraph_vector_int_t imembership; igraph_vector_t *pdistances; diff --git a/src/vendor/cigraph/src/paths/widest_paths.c b/src/vendor/cigraph/src/paths/widest_paths.c index 2691861f218..02dab7ed53c 100644 --- a/src/vendor/cigraph/src/paths/widest_paths.c +++ b/src/vendor/cigraph/src/paths/widest_paths.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -34,26 +34,29 @@ * \function igraph_get_widest_paths * \brief Widest paths from a single vertex. * - * Calculates the widest paths from a single node to all other specified nodes, - * using a modified Dijkstra's algorithm. If there is more than one path with - * the largest width between two vertices, this function gives only one of them. + * Calculates the widest paths from a single vertex to all other specified + * vertices, using a modified Dijkstra's algorithm. The width of a path is + * defined as the width of the narrowest edge in the path.If there is more than + * one path with the largest width between two vertices, this function gives + * only one of them. + * * \param graph The graph object. - * \param vertices The result, the IDs of the vertices along the paths. - * This is a list of integer vectors where each element is an - * \ref igraph_vector_int_t object. The list will be resized as needed. - * Supply a null pointer here if you don't need these vectors. - * \param edges The result, the IDs of the edges along the paths. - * This is a list of integer vectors where each element is an - * \ref igraph_vector_int_t object. The list will be resized as needed. - * Supply a null pointer here if you don't need these vectors. - * \param from The id of the vertex from/to which the widest paths are - * calculated. + * \param vertices The result, the IDs of the vertices along the paths. This + * is a list of integer vectors where each element is an + * \ref igraph_vector_int_t object. The list will be resized as needed. + * Supply a null pointer here if you don't need these vectors. + * \param edges The result, the IDs of the edges along the paths. This is a + * list of integer vectors where each element is an + * \ref igraph_vector_int_t object. The vector list will be resized as + * needed. Supply a null pointer here if you don't need these vectors. + * \param from The ID of the vertex from/to which the widest paths are + * calculated. * \param to Vertex sequence with the IDs of the vertices to/from which the - * widest paths will be calculated. A vertex might be given multiple - * times. - * \param weights The edge weights. Edge weights can be negative. If this - * is a null pointer or if any edge weight is NaN, then an error - * is returned. Edges with positive infinite weight are ignored. + * widest paths will be calculated. A vertex may be given multiple times. + * \param weights The edge weights, interpreted as widths. Edge weights can be + * negative, but must not be NaN. Edges with negative infinite weight are + * ignored. The weight vector is required: if \c NULL is passed, an error is + * raised. * \param mode The type of widest paths to be used for the * calculation in directed graphs. Possible values: * \clist @@ -65,23 +68,20 @@ * the directed graph is considered as an * undirected one for the computation. * \endclist - * \param parents A pointer to an initialized igraph vector or null. - * If not null, a vector containing the parent of each vertex in - * the single source widest path tree is returned here. The - * parent of vertex i in the tree is the vertex from which vertex i - * was reached. The parent of the start vertex (in the \c from - * argument) is -1. If the parent is -2, it means - * that the given vertex was not reached from the source during the - * search. Note that the search terminates if all the vertices in - * \c to are reached. - * \param inbound_edges A pointer to an initialized igraph vector or null. - * If not null, a vector containing the inbound edge of each vertex in - * the single source widest path tree is returned here. The - * inbound edge of vertex i in the tree is the edge via which vertex i - * was reached. The start vertex and vertices that were not reached - * during the search will have -1 in the corresponding entry of the - * vector. Note that the search terminates if all the vertices in - * \c to are reached. + * \param parents A pointer to an initialized igraph vector or null. If not + * null, a vector containing the parent of each vertex in the single source + * widest path tree is returned here. The parent of vertex \c i in the tree + * is the vertex from which vertex \c i was reached. The parent of the start + * vertex (in the \p from argument) is -1. If the parent is -2, it means + * that the given vertex was not reached from the source during the search. + * The search terminates when all the vertices in \p to have been reached. + * \param inbound_edges A pointer to an initialized igraph vector or \c NULL. + * If not \c NULL, a vector containing the inbound edge of each vertex in + * the single source widest path tree is returned here. The inbound edge of + * vertex \c i in the tree is the edge via which vertex \c i was reached. + * The start vertex and vertices that were not reached during the search + * will have -1 in the corresponding entry of the vector. The search + * terminates when all the vertices in \p to have been reached. * \return Error code: * \clist * \cli IGRAPH_ENOMEM @@ -102,7 +102,7 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges, - igraph_integer_t from, + igraph_int_t from, igraph_vs_t to, const igraph_vector_t *weights, igraph_neimode_t mode, @@ -111,37 +111,37 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, /* Implementation details: This is a Dijkstra algorithm with a binary heap, modified to support widest paths. The heap is indexed, - so it stores both the widest path to a node, as well as it's index. We + so it stores both the widest path to a vertex, as well as it's index. We use a 2 way heap so that we can query indexes directly in the heap. To adapt a Dijkstra to handle widest path, instead of prioritising candidate - nodes with the minimum distance, we prioritise those with the maximum - width instead. When adding a node into our set of 'completed' nodes, we - update all neighbouring nodes with a width that is equal to the min of the - width to the current node and the width of the edge. + vertices with the minimum distance, we prioritise those with the maximum + width instead. When adding a vertex into our set of 'completed' vertices, we + update all neighbouring vertices with a width that is equal to the min of the + width to the current vertex and the width of the edge. - We denote the widest path from a node to itself as infinity, and the widest - path from a node to a node it cannot reach as negative infinity. + We denote the widest path from a vertex to itself as infinity, and the widest + path from a vertex to a vertex it cannot reach as negative infinity. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_vit_t vit; igraph_2wheap_t Q; igraph_lazy_inclist_t inclist; igraph_vector_t widths; - igraph_integer_t *parent_eids; + igraph_int_t *parent_eids; bool *is_target; - igraph_integer_t i, to_reach; + igraph_int_t i, to_reach; if (!weights) { IGRAPH_ERROR("Weight vector is required.", IGRAPH_EINVAL); } - if (igraph_vector_size(weights) != no_of_edges) { + if (igraph_vector_size(weights) != ecount) { IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", IGRAPH_EINVAL, - igraph_vector_size(weights), no_of_edges); + igraph_vector_size(weights), ecount); } if (igraph_vector_is_any_nan(weights)) { @@ -158,19 +158,19 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_int_list_resize(edges, IGRAPH_VIT_SIZE(vit))); } - IGRAPH_CHECK(igraph_2wheap_init(&Q, no_of_nodes)); + IGRAPH_CHECK(igraph_2wheap_init(&Q, vcount)); IGRAPH_FINALLY(igraph_2wheap_destroy, &Q); IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, mode, IGRAPH_LOOPS)); IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist); - IGRAPH_VECTOR_INIT_FINALLY(&widths, no_of_nodes); + IGRAPH_VECTOR_INIT_FINALLY(&widths, vcount); igraph_vector_fill(&widths, -IGRAPH_INFINITY); - parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + parent_eids = IGRAPH_CALLOC(vcount, igraph_int_t); IGRAPH_CHECK_OOM(parent_eids, "Insufficient memory for widest paths."); IGRAPH_FINALLY(igraph_free, parent_eids); - is_target = IGRAPH_CALLOC(no_of_nodes, bool); + is_target = IGRAPH_CALLOC(vcount, bool); IGRAPH_CHECK_OOM(is_target, "Insufficient memory for widest paths."); IGRAPH_FINALLY(igraph_free, is_target); @@ -180,7 +180,7 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, if (!is_target[ IGRAPH_VIT_GET(vit) ]) { is_target[ IGRAPH_VIT_GET(vit) ] = true; } else { - to_reach--; /* this node was given multiple times */ + to_reach--; /* this vertex was given multiple times */ } } @@ -189,7 +189,7 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, igraph_2wheap_push_with_index(&Q, from, IGRAPH_INFINITY); while (!igraph_2wheap_empty(&Q) && to_reach > 0) { - igraph_integer_t nlen, maxnei = igraph_2wheap_max_index(&Q); + igraph_int_t nlen, maxnei = igraph_2wheap_max_index(&Q); igraph_real_t maxwidth = igraph_2wheap_delete_max(&Q); igraph_vector_int_t *neis; @@ -205,13 +205,13 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); for (i = 0; i < nlen; i++) { - igraph_integer_t edge = VECTOR(*neis)[i]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, maxnei); + igraph_int_t edge = VECTOR(*neis)[i]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, maxnei); igraph_real_t edgewidth = VECTOR(*weights)[edge]; igraph_real_t altwidth = maxwidth < edgewidth ? maxwidth : edgewidth; igraph_real_t curwidth = VECTOR(widths)[tto]; - if (edgewidth == IGRAPH_INFINITY) { - /* Ignore edges with infinite weight */ + if (edgewidth == -IGRAPH_INFINITY) { + /* Ignore edges with negative infinite weight */ } else if (curwidth < 0) { /* This is the first assigning a width to this vertex */ VECTOR(widths)[tto] = altwidth; @@ -233,9 +233,9 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, /* Create `parents' if needed */ if (parents) { - IGRAPH_CHECK(igraph_vector_int_resize(parents, no_of_nodes)); + IGRAPH_CHECK(igraph_vector_int_resize(parents, vcount)); - for (i = 0; i < no_of_nodes; i++) { + for (i = 0; i < vcount; i++) { if (i == from) { /* i is the start vertex */ VECTOR(*parents)[i] = -1; @@ -251,9 +251,9 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, /* Create `inbound_edges' if needed */ if (inbound_edges) { - IGRAPH_CHECK(igraph_vector_int_resize(inbound_edges, no_of_nodes)); + IGRAPH_CHECK(igraph_vector_int_resize(inbound_edges, vcount)); - for (i = 0; i < no_of_nodes; i++) { + for (i = 0; i < vcount; i++) { if (parent_eids[i] <= 0) { /* i was not reached */ VECTOR(*inbound_edges)[i] = -1; @@ -266,8 +266,8 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, /* Reconstruct the widest paths based on vertex and/or edge IDs */ if (vertices || edges) { for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); - igraph_integer_t size, act, edge; + igraph_int_t v = IGRAPH_VIT_GET(vit); + igraph_int_t size, act, edge; igraph_vector_int_t *vvec = 0, *evec = 0; if (vertices) { @@ -282,20 +282,20 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, IGRAPH_ALLOW_INTERRUPTION(); size = 0; - act = node; + act = v; while (parent_eids[act]) { size++; edge = parent_eids[act] - 1; act = IGRAPH_OTHER(graph, edge, act); } - if (vvec && (size > 0 || node == from)) { + if (vvec && (size > 0 || v == from)) { IGRAPH_CHECK(igraph_vector_int_resize(vvec, size + 1)); - VECTOR(*vvec)[size] = node; + VECTOR(*vvec)[size] = v; } if (evec) { IGRAPH_CHECK(igraph_vector_int_resize(evec, size)); } - act = node; + act = v; while (parent_eids[act]) { edge = parent_eids[act] - 1; act = IGRAPH_OTHER(graph, edge, act); @@ -332,23 +332,28 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, * \ref igraph_get_widest_paths(). * * \param graph The input graph, it can be directed or undirected. - * \param vertices Pointer to an initialized vector or a null - * pointer. If not a null pointer, then the vertex IDs along - * the path are stored here, including the source and target - * vertices. - * \param edges Pointer to an initialized vector or a null - * pointer. If not a null pointer, then the edge IDs along the - * path are stored here. - * \param from The id of the source vertex. - * \param to The id of the target vertex. - * \param weights The edge weights. Edge weights can be negative. If this - * is a null pointer or if any edge weight is NaN, then an error - * is returned. Edges with positive infinite weight are ignored. - * \param mode A constant specifying how edge directions are - * considered in directed graphs. \c IGRAPH_OUT follows edge - * directions, \c IGRAPH_IN follows the opposite directions, - * and \c IGRAPH_ALL ignores edge directions. This argument is - * ignored for undirected graphs. + * \param vertices Pointer to an initialized vector or \c NULL. If not \c NULL, + * then the vertex IDs along the path are stored here, including the source + * and target vertices. + * \param edges Pointer to an initialized vector or \c NULL. If not \c NULL, + * then the edge IDs along the path are stored here. + * \param from The ID of the source vertex. + * \param to The ID of the target vertex. + * \param weights The edge weights, interpreted as widths. Edge weights can be + * negative, but must not be NaN. Edges with negative infinite weight are + * ignored. The weight vector is required: if \c NULL is passed, an error is + * raised. + * \param mode The type of widest paths to be used for the + * calculation in directed graphs. Possible values: + * \clist + * \cli IGRAPH_OUT + * the outgoing paths are calculated. + * \cli IGRAPH_IN + * the incoming paths are calculated. + * \cli IGRAPH_ALL + * the directed graph is considered as an + * undirected one for the computation. + * \endclist * \return Error code. * * Time complexity: O(|E|log|E|+|V|), |V| is the number of vertices, @@ -360,8 +365,8 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph, igraph_error_t igraph_get_widest_path(const igraph_t *graph, igraph_vector_int_t *vertices, igraph_vector_int_t *edges, - igraph_integer_t from, - igraph_integer_t to, + igraph_int_t from, + igraph_int_t to, const igraph_vector_t *weights, igraph_neimode_t mode) { @@ -403,12 +408,16 @@ igraph_error_t igraph_get_widest_path(const igraph_t *graph, * \function igraph_widest_path_widths_floyd_warshall * \brief Widths of widest paths between vertices. * - * This function implements a modified Floyd-Warshall algorithm, - * to find the widest path widths between a set of source and target - * vertices. It is primarily useful for all-pairs path widths in very dense - * graphs, as its running time is manily determined by the vertex count, - * and is not sensitive to the graph density. In sparse graphs, other methods - * such as the Dijkstra algorithm, will perform better. + * This function implements a modified Floyd-Warshall algorithm, to find the + * widest path widths between a set of source and target vertices. The width + * of a path is defined as the width of the narrowest edge in the path. + * + * + * This algorithm is primarily useful for all-pairs path widths in very dense + * graphs, as its running time is manily determined by the vertex count, and + * is not sensitive to the graph density. In sparse graphs, other methods such + * as Dijkstra's algorithm, implemented in + * \ref igraph_widest_path_widths_dijkstra() will perform better. * * * Note that internally this function always computes the path width matrix @@ -417,17 +426,17 @@ igraph_error_t igraph_get_widest_path(const igraph_t *graph, * calculation. * * \param graph The input graph, can be directed. - * \param res The result, a matrix. A pointer to an initialized matrix - * should be passed here. The matrix will be resized as needed. - * Each row contains the widths from a single source, to the - * vertices given in the \c to argument. + * \param res An initialized matrix, the result will be written here. The + * matrix will be resized as needed. Each row will contain the widths + * from a single source to the vertices given in the \p to argument. * Unreachable vertices have width \c -IGRAPH_INFINITY, and vertices * have a width of \c IGRAPH_INFINITY to themselves. * \param from The source vertices. * \param to The target vertices. - * \param weights The edge weights. Edge weights can be negative. If this - * is a null pointer or if any edge weight is NaN, then an error - * is returned. Edges with positive infinite weight are ignored. + * \param weights The edge weights, interpreted as widths. Edge weights can be + * negative, but must not be NaN. Edges with negative infinite weight are + * ignored. The weight vector is required: if \c NULL is passed, an error is + * raised. * \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 @@ -447,28 +456,28 @@ igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph, igraph_neimode_t mode) { /* Implementation Details: This is a modified Floyd Warshall algorithm - which computes the widest path between every pair of nodes. The key + which computes the widest path between every pair of vertices. The key difference between this and the regular Floyd Warshall is that instead - of updating the distance between two nodes to be the minimum of itself - and the distance through an intermediate node, we instead set the width - to be the maximum of itself and the width through the intermediate node. + of updating the distance between two vertices to be the minimum of itself + and the distance through an intermediate vertex, we instead set the width + to be the maximum of itself and the width through the intermediate vertex. - We denote the widest path from a node to itself as infinity, and the widest - path from a node to a node it cannot reach as negative infinity. + We denote the widest path from a vertex to itself as infinity, and the widest + path from a vertex to a vertex it cannot reach as negative infinity. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_bool_t in = false, out = false; if (! weights) { IGRAPH_ERROR("Weight vector is required.", IGRAPH_EINVAL); } - if (igraph_vector_size(weights) != no_of_edges) { + if (igraph_vector_size(weights) != ecount) { IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", IGRAPH_EINVAL, - igraph_vector_size(weights), no_of_edges); + igraph_vector_size(weights), ecount); } if (igraph_vector_is_any_nan(weights)) { @@ -494,18 +503,18 @@ igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph, } /* Fill out adjacency matrix */ - IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, no_of_nodes)); + IGRAPH_CHECK(igraph_matrix_resize(res, vcount, vcount)); igraph_matrix_fill(res, -IGRAPH_INFINITY); - for (igraph_integer_t i=0; i < no_of_nodes; i++) { + for (igraph_int_t i=0; i < vcount; i++) { MATRIX(*res, i, i) = IGRAPH_INFINITY; } - for (igraph_integer_t edge=0; edge < no_of_edges; edge++) { - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); + for (igraph_int_t edge=0; edge < ecount; edge++) { + igraph_int_t from = IGRAPH_FROM(graph, edge); + igraph_int_t to = IGRAPH_TO(graph, edge); igraph_real_t w = VECTOR(*weights)[edge]; - if (w == IGRAPH_INFINITY) { + if (w == -IGRAPH_INFINITY) { /* Ignore edges with infinite weight */ continue; } @@ -515,15 +524,15 @@ igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph, } /* Run modified Floyd Warshall */ - for (igraph_integer_t k = 0; k < no_of_nodes; k++) { + for (igraph_int_t k = 0; k < vcount; k++) { /* Iterate in column-major order for better performance */ - for (igraph_integer_t j = 0; j < no_of_nodes; j++) { + for (igraph_int_t j = 0; j < vcount; j++) { igraph_real_t width_kj = MATRIX(*res, k, j); if (j == k || width_kj == -IGRAPH_INFINITY) continue; IGRAPH_ALLOW_INTERRUPTION(); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { if (i == j || i == k) continue; /* alternative_width := min(A(i,k), A(k,j)) @@ -549,26 +558,29 @@ igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph, * \function igraph_widest_path_widths_dijkstra * \brief Widths of widest paths between vertices. * - * This function implements a modified Dijkstra's algorithm, which - * can find the widest path widths from a source vertex to all - * other vertices. This function allows specifying a set of source - * and target vertices. The algorithm is run independently for each - * source and the results are retained only for the specified targets. - * This implementation uses a binary heap for efficiency. + * This function implements a modified Dijkstra's algorithm, which can find + * the widest path widths from a source vertex to all other vertices. The width + * of a path is defined as the width of the narrowest edge in the path. + * + * + * This function allows specifying a set of source and target vertices. The + * algorithm is run independently for each source and the results are retained + * only for the specified targets. This implementation uses a binary heap for + * efficiency. * * \param graph The input graph, can be directed. - * \param res The result, a matrix. A pointer to an initialized matrix - * should be passed here. The matrix will be resized as needed. - * Each row contains the widths from a single source, to the - * vertices given in the \c to argument. + * \param res An initialized matrix, the result will be written here. The + * matrix will be resized as needed. Each row will contain the widths + * from a single source to the vertices given in the \p to argument. * Unreachable vertices have width \c -IGRAPH_INFINITY, and vertices * have a width of \c IGRAPH_INFINITY to themselves. * \param from The source vertices. - * \param to The target vertices. It is not allowed to include a - * vertex twice or more. - * \param weights The edge weights. Edge weights can be negative. If this - * is a null pointer or if any edge weight is NaN, then an error - * is returned. Edges with positive infinite weight are ignored. + * \param to The target vertices. It is not allowed to include a vertex twice + * or more. + * \param weights The edge weights, interpreted as widths. Edge weights can be + * negative, but must not be NaN. Edges with negative infinite weight are + * ignored. The weight vector is required: if \c NULL is passed, an error is + * raised. * \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 @@ -578,8 +590,8 @@ igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph, * Time complexity: O(s*(|E|log|E|+|V|)), where |V| is the number of * vertices in the graph, |E| the number of edges and s the number of sources. * - * \sa \ref igraph_widest_path_widths_floyd_warshall() for a variant that runs faster - * on dense graphs. + * \sa \ref igraph_widest_path_widths_floyd_warshall() for a variant that runs + * faster on dense graphs. */ igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph, igraph_matrix_t *res, @@ -590,26 +602,26 @@ igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph, /* Implementation details: This is a Dijkstra algorithm with a binary heap, modified to support widest paths. The heap is indexed, - so it stores both the widest path to a node, as well as it's index. We + so it stores both the widest path to a vertex, as well as it's index. We use a 2 way heap so that we can query indexes directly in the heap. To adapt a Dijkstra to handle widest path, instead of prioritising candidate - nodes with the minimum distance, we prioritise those with the maximum - width instead. When adding a node into our set of 'completed' nodes, we - update all neighbouring nodes with a width that is equal to the min of the - width to the current node and the width of the edge. + vertices with the minimum distance, we prioritise those with the maximum + width instead. When adding a vertex into our set of 'completed' vertices, we + update all neighbouring vertices with a width that is equal to the min of the + width to the current vertex and the width of the edge. - We denote the widest path from a node to itself as infinity, and the widest - path from a node to a node it cannot reach as negative infinity. + We denote the widest path from a vertex to itself as infinity, and the widest + path from a vertex to a vertex it cannot reach as negative infinity. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_2wheap_t Q; igraph_vit_t fromvit, tovit; - igraph_integer_t no_of_from, no_of_to; + igraph_int_t no_of_from, no_of_to; igraph_lazy_inclist_t inclist; - igraph_integer_t i, j; + igraph_int_t i, j; igraph_bool_t all_to; igraph_vector_int_t indexv; @@ -617,10 +629,10 @@ igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph, IGRAPH_ERROR("Weight vector is required.", IGRAPH_EINVAL); } - if (igraph_vector_size(weights) != no_of_edges) { + if (igraph_vector_size(weights) != ecount) { IGRAPH_ERRORF("Weight vector length (%" IGRAPH_PRId ") does not match number of edges (%" IGRAPH_PRId ").", IGRAPH_EINVAL, - igraph_vector_size(weights), no_of_edges); + igraph_vector_size(weights), ecount); } if (igraph_vector_is_any_nan(weights)) { @@ -631,23 +643,23 @@ igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph, IGRAPH_FINALLY(igraph_vit_destroy, &fromvit); no_of_from = IGRAPH_VIT_SIZE(fromvit); - IGRAPH_CHECK(igraph_2wheap_init(&Q, no_of_nodes)); + IGRAPH_CHECK(igraph_2wheap_init(&Q, vcount)); IGRAPH_FINALLY(igraph_2wheap_destroy, &Q); IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, mode, IGRAPH_LOOPS)); IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist); all_to = igraph_vs_is_all(&to); if (all_to) { - no_of_to = no_of_nodes; + no_of_to = vcount; } else { - IGRAPH_VECTOR_INT_INIT_FINALLY(&indexv, no_of_nodes); + IGRAPH_VECTOR_INT_INIT_FINALLY(&indexv, vcount); IGRAPH_CHECK(igraph_vit_create(graph, to, &tovit)); IGRAPH_FINALLY(igraph_vit_destroy, &tovit); no_of_to = IGRAPH_VIT_SIZE(tovit); for (i = 0; !IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit)) { - igraph_integer_t v = IGRAPH_VIT_GET(tovit); + igraph_int_t v = IGRAPH_VIT_GET(tovit); if (VECTOR(indexv)[v]) { - IGRAPH_ERROR("Duplicate vertices in `to', this is not allowed.", + IGRAPH_ERROR("Duplicate vertices in target vertex set, this is not allowed.", IGRAPH_EINVAL); } VECTOR(indexv)[v] = ++i; @@ -661,16 +673,16 @@ igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph, !IGRAPH_VIT_END(fromvit); IGRAPH_VIT_NEXT(fromvit), i++) { - igraph_integer_t reached = 0; - igraph_integer_t source = IGRAPH_VIT_GET(fromvit); + igraph_int_t reached = 0; + igraph_int_t source = IGRAPH_VIT_GET(fromvit); igraph_2wheap_clear(&Q); igraph_2wheap_push_with_index(&Q, source, IGRAPH_INFINITY); while (!igraph_2wheap_empty(&Q)) { - igraph_integer_t maxnei = igraph_2wheap_max_index(&Q); + igraph_int_t maxnei = igraph_2wheap_max_index(&Q); igraph_real_t maxwidth = igraph_2wheap_deactivate_max(&Q); igraph_vector_int_t *neis; - igraph_integer_t nlen; + igraph_int_t nlen; IGRAPH_ALLOW_INTERRUPTION(); @@ -692,15 +704,15 @@ igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph, IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); nlen = igraph_vector_int_size(neis); for (j = 0; j < nlen; j++) { - igraph_integer_t edge = VECTOR(*neis)[j]; - igraph_integer_t tto = IGRAPH_OTHER(graph, edge, maxnei); + igraph_int_t edge = VECTOR(*neis)[j]; + igraph_int_t tto = IGRAPH_OTHER(graph, edge, maxnei); igraph_real_t edgewidth = VECTOR(*weights)[edge]; igraph_real_t altwidth = maxwidth < edgewidth ? maxwidth : edgewidth; igraph_bool_t active = igraph_2wheap_has_active(&Q, tto); igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto); igraph_real_t curwidth = active ? igraph_2wheap_get(&Q, tto) : IGRAPH_INFINITY; - if (edgewidth == IGRAPH_INFINITY) { - /* Ignore edges with infinite weight */ + if (edgewidth == -IGRAPH_INFINITY) { + /* Ignore edges with negative infinite weight */ } else if (!has) { /* This is the first time assigning a width to this vertex */ IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, altwidth)); diff --git a/src/vendor/cigraph/src/properties/basic_properties.c b/src/vendor/cigraph/src/properties/basic_properties.c index db6a1d32dd4..d6e457b94f9 100644 --- a/src/vendor/cigraph/src/properties/basic_properties.c +++ b/src/vendor/cigraph/src/properties/basic_properties.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -42,48 +42,70 @@ * \p loops parameter. * * - * Note that density is ill-defined for graphs which have multiple edges - * between some pairs of vertices. Consider calling \ref igraph_simplify() - * on such graphs. This function does not check whether the graph has - * parallel edges. The result it returns for such graphs is not meaningful. + * The classic definition of the density is formulated for unweighted + * graphs without multi-edges. This function allows multigraphs and + * weighted graphs as well. In this case, it computes the ratio of the + * total edge weight to the largest possible number of adjacent vertex + * pairs the graph could have. This value may be larger than 1. + * + * + * If you need the density concept for simple graphs, make sure to + * eliminate any multi-edges appropriately. This can be done using + * \ref igraph_simplify(). * * \param graph The input graph object. It must not have parallel edges. * \param res Pointer to a real number, the result will be stored here. + * \param weights Vector of edge weights. Pass \c NULL to to perform + * an unweighted density calculation. * \param loops Boolean constant, whether to include self-loops in the * calculation. If this constant is \c true then * loop edges are thought to be possible in the graph (this does not * necessarily mean that the graph really contains any loops). If * this is \c false then the result is only correct if the graph does not - * contain loops. + * contain loops. This function does not check if loops are actually + * present. * \return Error code. * * Time complexity: O(1). */ -igraph_error_t igraph_density(const igraph_t *graph, igraph_real_t *res, - igraph_bool_t loops) { - - igraph_real_t no_of_nodes = (igraph_real_t) igraph_vcount(graph); - igraph_real_t no_of_edges = (igraph_real_t) igraph_ecount(graph); - igraph_bool_t directed = igraph_is_directed(graph); - - if (no_of_nodes == 0) { +igraph_error_t igraph_density( + const igraph_t *graph, + const igraph_vector_t *weights, + igraph_real_t *res, + igraph_bool_t loops) { + + const igraph_bool_t directed = igraph_is_directed(graph); + const igraph_int_t ecount = igraph_ecount(graph); + const igraph_real_t vcount = (igraph_real_t) igraph_vcount(graph); /* note real type */ + igraph_real_t total_weight; + + if (vcount == 0) { *res = IGRAPH_NAN; return IGRAPH_SUCCESS; } + if (weights) { + if (igraph_vector_size(weights) != ecount) { + IGRAPH_ERROR("Weight vector length does not match edge count.", IGRAPH_EINVAL); + } + total_weight = igraph_vector_sum(weights); + } else { + total_weight = ecount; + } + if (!loops) { - if (no_of_nodes == 1) { + if (vcount == 1) { *res = IGRAPH_NAN; } else if (directed) { - *res = no_of_edges / no_of_nodes / (no_of_nodes - 1); + *res = total_weight / vcount / (vcount - 1); } else { - *res = no_of_edges / no_of_nodes * 2.0 / (no_of_nodes - 1); + *res = total_weight / vcount * 2.0 / (vcount - 1); } } else { if (directed) { - *res = no_of_edges / no_of_nodes / no_of_nodes; + *res = total_weight / vcount / vcount; } else { - *res = no_of_edges / no_of_nodes * 2.0 / (no_of_nodes + 1); + *res = total_weight / vcount * 2.0 / (vcount + 1); } } @@ -110,8 +132,8 @@ igraph_error_t igraph_density(const igraph_t *graph, igraph_real_t *res, igraph_error_t igraph_mean_degree(const igraph_t *graph, igraph_real_t *res, igraph_bool_t loops) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); if (no_of_nodes == 0) { @@ -120,7 +142,7 @@ igraph_error_t igraph_mean_degree(const igraph_t *graph, igraph_real_t *res, } if (! loops) { - igraph_integer_t loop_count; + igraph_int_t loop_count; IGRAPH_CHECK(igraph_count_loops(graph, &loop_count)); no_of_edges -= loop_count; } @@ -171,8 +193,8 @@ igraph_error_t igraph_mean_degree(const igraph_t *graph, igraph_real_t *res, igraph_error_t igraph_diversity(const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_t *res, const igraph_vs_t vids) { - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t k, i; + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t k, i; igraph_vector_int_t incident; igraph_bool_t has_multiple; igraph_vit_t vit; @@ -213,7 +235,7 @@ igraph_error_t igraph_diversity(const igraph_t *graph, const igraph_vector_t *we for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { igraph_real_t d; - igraph_integer_t v = IGRAPH_VIT_GET(vit); + igraph_int_t v = IGRAPH_VIT_GET(vit); IGRAPH_CHECK(igraph_incident(graph, &incident, v, IGRAPH_ALL, IGRAPH_LOOPS)); k = igraph_vector_int_size(&incident); /* degree */ @@ -304,9 +326,9 @@ igraph_error_t igraph_reciprocity(const igraph_t *graph, igraph_real_t *res, igraph_bool_t ignore_loops, igraph_reciprocity_t mode) { - igraph_integer_t nonrec = 0, rec = 0, loops = 0; + igraph_int_t nonrec = 0, rec = 0, loops = 0; igraph_vector_int_t inneis, outneis; - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); if (mode != IGRAPH_RECIPROCITY_DEFAULT && mode != IGRAPH_RECIPROCITY_RATIO) { @@ -322,8 +344,8 @@ igraph_error_t igraph_reciprocity(const igraph_t *graph, igraph_real_t *res, IGRAPH_VECTOR_INT_INIT_FINALLY(&inneis, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&outneis, 0); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { - igraph_integer_t ip, op, indeg, outdeg; + for (igraph_int_t i = 0; i < no_of_nodes; i++) { + igraph_int_t ip, op, indeg, outdeg; IGRAPH_CHECK(igraph_neighbors( graph, &inneis, i, IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE )); diff --git a/src/vendor/cigraph/src/properties/complete.c b/src/vendor/cigraph/src/properties/complete.c index 4951b86858a..088a2103982 100644 --- a/src/vendor/cigraph/src/properties/complete.c +++ b/src/vendor/cigraph/src/properties/complete.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2024 The igraph development team This program is free software; you can redistribute it and/or modify it under @@ -26,8 +26,6 @@ * \function igraph_is_complete * \brief Decides whether the graph is complete. * - * \experimental - * * A graph is considered complete if all pairs of different vertices are * adjacent. * @@ -44,9 +42,9 @@ igraph_error_t igraph_is_complete(const igraph_t *graph, igraph_bool_t *res) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); - igraph_integer_t complete_ecount; + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); + igraph_int_t complete_ecount; igraph_bool_t simple, directed = igraph_is_directed(graph); igraph_vector_int_t neighbours; int iter = 0; @@ -129,7 +127,7 @@ igraph_error_t igraph_is_complete(const igraph_t *graph, igraph_bool_t *res) { /* Allocate memory for vector of size v */ IGRAPH_VECTOR_INT_INIT_FINALLY(&neighbours, vcount); - for (igraph_integer_t i = 0; i < vcount; ++i) { + for (igraph_int_t i = 0; i < vcount; ++i) { IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 8); IGRAPH_CHECK(igraph_neighbors( @@ -162,7 +160,7 @@ static igraph_error_t is_clique(const igraph_t *graph, igraph_vs_t candidate, igraph_bool_t directed, igraph_bool_t *res, igraph_bool_t independent_set) { igraph_vector_int_t vids; - igraph_integer_t n; /* clique size */ + igraph_int_t n; /* clique size */ igraph_bool_t result = true; /* be optimistic */ int iter = 0; @@ -174,14 +172,14 @@ static igraph_error_t is_clique(const igraph_t *graph, igraph_vs_t candidate, n = igraph_vector_int_size(&vids); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t u = VECTOR(vids)[i]; - for (igraph_integer_t j = directed ? 0 : i+1; j < n; j++) { - igraph_integer_t v = VECTOR(vids)[j]; + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t u = VECTOR(vids)[i]; + for (igraph_int_t j = directed ? 0 : i+1; j < n; j++) { + igraph_int_t v = VECTOR(vids)[j]; /* Compare u and v for equality instead of i and j in case * the vertex list contained duplicates. */ if (u != v) { - igraph_integer_t eid; + igraph_int_t eid; IGRAPH_CHECK(igraph_get_eid(graph, &eid, u, v, directed, false)); if (independent_set) { if (eid != -1) { @@ -271,7 +269,7 @@ igraph_error_t igraph_is_independent_vertex_set(const igraph_t *graph, igraph_vs /* Note: igraph_count_loops() already makes use of the cache. */ if (igraph_vs_is_all(&candidate)) { - igraph_integer_t loop_count; + igraph_int_t loop_count; igraph_count_loops(graph, &loop_count); *res = (igraph_ecount(graph) - loop_count) == 0; return IGRAPH_SUCCESS; diff --git a/src/vendor/cigraph/src/properties/constraint.c b/src/vendor/cigraph/src/properties/constraint.c index b71573c9a78..357aedadf1d 100644 --- a/src/vendor/cigraph/src/properties/constraint.c +++ b/src/vendor/cigraph/src/properties/constraint.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -76,12 +76,12 @@ igraph_error_t igraph_constraint(const igraph_t *graph, igraph_vector_t *res, igraph_vs_t vids, const igraph_vector_t *weights) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_vit_t vit; - igraph_integer_t nodes_to_calc; - igraph_integer_t a, b, c, i, j, q, vsize, vsize2; - igraph_integer_t edge, edge2; + igraph_int_t nodes_to_calc; + igraph_int_t a, b, c, i, j, q, vsize, vsize2; + igraph_int_t edge, edge2; igraph_vector_t contrib; igraph_vector_t degree; diff --git a/src/vendor/cigraph/src/properties/convergence_degree.c b/src/vendor/cigraph/src/properties/convergence_degree.c index 0c707fdaf57..6bedb9d776b 100644 --- a/src/vendor/cigraph/src/properties/convergence_degree.c +++ b/src/vendor/cigraph/src/properties/convergence_degree.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -70,10 +70,10 @@ */ igraph_error_t igraph_convergence_degree(const igraph_t *graph, igraph_vector_t *result, igraph_vector_t *ins, igraph_vector_t *outs) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t i, j, k, n; - igraph_integer_t *geodist; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t i, j, k, n; + igraph_int_t *geodist; igraph_vector_int_t *eids; igraph_vector_t *ins_p, *outs_p, ins_v, outs_v; igraph_dqueue_int_t q; @@ -104,7 +104,7 @@ igraph_error_t igraph_convergence_degree(const igraph_t *graph, igraph_vector_t igraph_vector_null(outs_p); } - geodist = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + geodist = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); if (geodist == 0) { IGRAPH_ERROR("Cannot calculate convergence degrees", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -125,13 +125,13 @@ igraph_error_t igraph_convergence_degree(const igraph_t *graph, igraph_vector_t IGRAPH_CHECK(igraph_dqueue_int_push(&q, i)); IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0)); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); IGRAPH_ALLOW_INTERRUPTION(); eids = igraph_inclist_get(&inclist, actnode); n = igraph_vector_int_size(eids); for (j = 0; j < n; j++) { - igraph_integer_t neighbor = IGRAPH_OTHER(graph, VECTOR(*eids)[j], actnode); + igraph_int_t neighbor = IGRAPH_OTHER(graph, VECTOR(*eids)[j], actnode); if (geodist[neighbor] != 0) { /* we've already seen this node, another shortest path? */ if (geodist[neighbor] - 1 == actdist + 1) { diff --git a/src/vendor/cigraph/src/properties/dag.c b/src/vendor/cigraph/src/properties/dag.c index 420d7059164..0550cbd4162 100644 --- a/src/vendor/cigraph/src/properties/dag.c +++ b/src/vendor/cigraph/src/properties/dag.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2024 The igraph development team This program is free software; you can redistribute it and/or modify it under @@ -57,12 +57,12 @@ igraph_error_t igraph_topological_sorting( /* Note: This function ignores self-loops, there it cannot * use the IGRAPH_PROP_IS_DAG property cache entry. */ - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degrees; igraph_vector_int_t neis; igraph_dqueue_int_t sources; igraph_neimode_t deg_mode; - igraph_integer_t node, i, j; + igraph_int_t node, i, j; if (mode == IGRAPH_ALL || !igraph_is_directed(graph)) { IGRAPH_ERROR("Topological sorting does not make sense for undirected graphs.", @@ -130,7 +130,7 @@ igraph_error_t igraph_topological_sorting( * A directed acyclic graph (DAG) is a directed graph with no cycles. * * - * This function returns false for undirected graphs. + * This function returns \c false for undirected graphs. * * * The return value of this function is cached in the graph itself; calling @@ -149,7 +149,7 @@ igraph_error_t igraph_topological_sorting( * sorting of a DAG. */ igraph_error_t igraph_is_dag(const igraph_t* graph, igraph_bool_t *res) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degrees; igraph_vector_int_t neis; igraph_dqueue_int_t sources; @@ -167,10 +167,10 @@ igraph_error_t igraph_is_dag(const igraph_t* graph, igraph_bool_t *res) { IGRAPH_CHECK(igraph_degree(graph, °rees, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS)); - igraph_integer_t vertices_left = no_of_nodes; + igraph_int_t vertices_left = no_of_nodes; /* Do we have nodes with no incoming edges? */ - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { if (VECTOR(degrees)[i] == 0) { IGRAPH_CHECK(igraph_dqueue_int_push(&sources, i)); } @@ -178,15 +178,15 @@ igraph_error_t igraph_is_dag(const igraph_t* graph, igraph_bool_t *res) { /* Take all nodes with no incoming edges and remove them */ while (!igraph_dqueue_int_empty(&sources)) { - igraph_integer_t node = igraph_dqueue_int_pop(&sources); + igraph_int_t node = igraph_dqueue_int_pop(&sources); /* Exclude the node from further source searches */ VECTOR(degrees)[node] = -1; vertices_left--; /* Get the neighbors and decrease their degrees by one */ IGRAPH_CHECK(igraph_neighbors(graph, &neis, node, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE)); - igraph_integer_t n = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < n; i++) { - igraph_integer_t nei = VECTOR(neis)[i]; + igraph_int_t n = igraph_vector_int_size(&neis); + for (igraph_int_t i = 0; i < n; i++) { + igraph_int_t nei = VECTOR(neis)[i]; if (nei == node) { /* Found a self-loop, graph is not a DAG */ *res = false; diff --git a/src/vendor/cigraph/src/properties/degrees.c b/src/vendor/cigraph/src/properties/degrees.c index 79c90c1185c..1e3f702512b 100644 --- a/src/vendor/cigraph/src/properties/degrees.c +++ b/src/vendor/cigraph/src/properties/degrees.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2023 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ * 0 is returned, as this is the smallest possible value for degrees. * * \param graph The input graph. - * \param res Pointer to an integer (\c igraph_integer_t), the result + * \param res Pointer to an integer (\c igraph_int_t), the result * will be stored here. * \param vids Vector giving the vertex IDs for which the maximum degree will * be calculated. @@ -54,7 +54,7 @@ * \sa \ref igraph_degree() to retrieve the degrees for several vertices. */ igraph_error_t igraph_maxdegree( - const igraph_t *graph, igraph_integer_t *res, igraph_vs_t vids, + const igraph_t *graph, igraph_int_t *res, igraph_vs_t vids, igraph_neimode_t mode, igraph_loops_t loops ) { @@ -83,14 +83,14 @@ static igraph_error_t avg_nearest_neighbor_degree_weighted(const igraph_t *graph igraph_vector_t *knnk, const igraph_vector_t *weights) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t neis, edge_neis; - igraph_integer_t no_vids; + igraph_int_t no_vids; igraph_vit_t vit; igraph_vector_t my_knn_v, *my_knn = knn; igraph_vector_t strength; igraph_vector_int_t deg; - igraph_integer_t maxdeg; + igraph_int_t maxdeg; igraph_vector_t deghist; if (igraph_vector_size(weights) != igraph_ecount(graph)) { @@ -132,18 +132,18 @@ static igraph_error_t avg_nearest_neighbor_degree_weighted(const igraph_t *graph IGRAPH_VECTOR_INIT_FINALLY(°hist, maxdeg); } - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + for (igraph_int_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { igraph_real_t sum = 0.0; - igraph_integer_t v = IGRAPH_VIT_GET(vit); - igraph_integer_t nv; + igraph_int_t v = IGRAPH_VIT_GET(vit); + igraph_int_t nv; igraph_real_t str = VECTOR(strength)[v]; /* Get neighbours and incident edges */ IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); IGRAPH_CHECK(igraph_incident(graph, &edge_neis, v, mode, IGRAPH_LOOPS)); nv = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < nv; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; - igraph_integer_t e = VECTOR(edge_neis)[j]; + for (igraph_int_t j = 0; j < nv; j++) { + igraph_int_t nei = VECTOR(neis)[j]; + igraph_int_t e = VECTOR(edge_neis)[j]; igraph_real_t w = VECTOR(*weights)[e]; sum += w * VECTOR(deg)[nei]; } @@ -163,7 +163,7 @@ static igraph_error_t avg_nearest_neighbor_degree_weighted(const igraph_t *graph IGRAPH_FINALLY_CLEAN(2); if (knnk) { - for (igraph_integer_t i = 0; i < maxdeg; i++) { + for (igraph_int_t i = 0; i < maxdeg; i++) { igraph_real_t dh = VECTOR(deghist)[i]; if (dh != 0) { VECTOR(*knnk)[i] /= dh; @@ -268,13 +268,13 @@ igraph_error_t igraph_avg_nearest_neighbor_degree(const igraph_t *graph, igraph_vector_t *knnk, const igraph_vector_t *weights) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t neis; - igraph_integer_t no_vids; + igraph_int_t no_vids; igraph_vit_t vit; igraph_vector_t my_knn_v, *my_knn = knn; igraph_vector_int_t deg; - igraph_integer_t maxdeg; + igraph_int_t maxdeg; igraph_vector_int_t deghist; if (weights) { @@ -306,14 +306,14 @@ igraph_error_t igraph_avg_nearest_neighbor_degree(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(°hist, maxdeg); } - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + for (igraph_int_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { igraph_real_t sum = 0.0; - igraph_integer_t v = IGRAPH_VIT_GET(vit); - igraph_integer_t nv; + igraph_int_t v = IGRAPH_VIT_GET(vit); + igraph_int_t nv; IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); nv = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < nv; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < nv; j++) { + igraph_int_t nei = VECTOR(neis)[j]; sum += VECTOR(deg)[nei]; } if (nv != 0) { @@ -328,8 +328,8 @@ igraph_error_t igraph_avg_nearest_neighbor_degree(const igraph_t *graph, } if (knnk) { - for (igraph_integer_t i = 0; i < maxdeg; i++) { - igraph_integer_t dh = VECTOR(deghist)[i]; + for (igraph_int_t i = 0; i < maxdeg; i++) { + igraph_int_t dh = VECTOR(deghist)[i]; if (dh != 0) { VECTOR(*knnk)[i] /= dh; } else { @@ -357,8 +357,6 @@ igraph_error_t igraph_avg_nearest_neighbor_degree(const igraph_t *graph, * \function igraph_degree_correlation_vector * \brief Degree correlation function. * - * \experimental - * * Computes the degree correlation function k_nn(k), defined as the * mean degree of the targets of directed edges whose source has degree \c k. * The averaging is done over all directed edges. The \p from_mode and \p to_mode @@ -435,9 +433,9 @@ igraph_error_t igraph_degree_correlation_vector( igraph_neimode_t from_mode, igraph_neimode_t to_mode, igraph_bool_t directed_neighbors) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t maxdeg; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t maxdeg; igraph_vector_t weight_sums; igraph_vector_int_t *deg_from, *deg_to, deg_out, deg_in, deg_all; @@ -494,11 +492,11 @@ igraph_error_t igraph_degree_correlation_vector( IGRAPH_CHECK(igraph_vector_resize(knnk, maxdeg+1)); igraph_vector_null(knnk); - for (igraph_integer_t eid=0; eid < no_of_edges; eid++) { - igraph_integer_t from = IGRAPH_FROM(graph, eid); - igraph_integer_t to = IGRAPH_TO(graph, eid); - igraph_integer_t fromdeg = VECTOR(*deg_from)[from]; - igraph_integer_t todeg = VECTOR(*deg_to)[to]; + for (igraph_int_t eid=0; eid < no_of_edges; eid++) { + igraph_int_t from = IGRAPH_FROM(graph, eid); + igraph_int_t to = IGRAPH_TO(graph, eid); + igraph_int_t fromdeg = VECTOR(*deg_from)[from]; + igraph_int_t todeg = VECTOR(*deg_to)[to]; igraph_real_t w = weights ? VECTOR(*weights)[eid] : 1; VECTOR(weight_sums)[fromdeg] += w; @@ -542,8 +540,8 @@ static igraph_error_t strength_all( const igraph_vector_t *weights) { // When calculating strength for all vertices, iterating over edges is faster - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); IGRAPH_CHECK(igraph_vector_resize(res, no_of_nodes)); igraph_vector_null(res); @@ -554,27 +552,27 @@ static igraph_error_t strength_all( if (loops) { if (mode & IGRAPH_OUT) { - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { VECTOR(*res)[IGRAPH_FROM(graph, edge)] += VECTOR(*weights)[edge]; } } if (mode & IGRAPH_IN) { - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { VECTOR(*res)[IGRAPH_TO(graph, edge)] += VECTOR(*weights)[edge]; } } } else { if (mode & IGRAPH_OUT) { - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { - igraph_integer_t from = IGRAPH_FROM(graph, edge); + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { + igraph_int_t from = IGRAPH_FROM(graph, edge); if (from != IGRAPH_TO(graph, edge)) { VECTOR(*res)[from] += VECTOR(*weights)[edge]; } } } if (mode & IGRAPH_IN) { - for (igraph_integer_t edge = 0; edge < no_of_edges; ++edge) { - igraph_integer_t to = IGRAPH_TO(graph, edge); + for (igraph_int_t edge = 0; edge < no_of_edges; ++edge) { + igraph_int_t to = IGRAPH_TO(graph, edge); if (IGRAPH_FROM(graph, edge) != to) { VECTOR(*res)[to] += VECTOR(*weights)[edge]; } @@ -600,10 +598,11 @@ static igraph_error_t strength_all( * \param mode Gives whether to count only outgoing (\c IGRAPH_OUT), * incoming (\c IGRAPH_IN) edges or both (\c IGRAPH_ALL). * This parameter is ignored for undirected graphs. - * \param loops Specifies how to treat loop edges when calculating the - * strength. \c IGRAPH_NO_LOOPS ignores loop edges; \c IGRAPH_LOOPS_ONCE - * counts each loop edge only once; \c IGRAPH_LOOPS_TWICE counts each - * loop edge twice in undirected graphs and once in directed graphs. + * \param loops Constant of type \ref igraph_loops_t. Specifies how to treat + * loop edges when calculating the strength. \c IGRAPH_NO_LOOPS ignores loop + * edges; \c IGRAPH_LOOPS_ONCE counts each loop edge only once; + * \c IGRAPH_LOOPS_TWICE counts each loop edge twice in undirected graphs and + * once in directed graphs. * \param weights A vector giving the edge weights. If this is a \c NULL * pointer, then \ref igraph_degree() is called to perform the * calculation. @@ -619,9 +618,9 @@ igraph_error_t igraph_strength( igraph_neimode_t mode, igraph_loops_t loops, const igraph_vector_t *weights ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vit_t vit; - igraph_integer_t no_vids; + igraph_int_t no_vids; igraph_vector_int_t degrees; igraph_vector_int_t neis; @@ -629,7 +628,7 @@ igraph_error_t igraph_strength( IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, no_of_nodes); IGRAPH_CHECK(igraph_vector_resize(res, no_of_nodes)); IGRAPH_CHECK(igraph_degree(graph, °rees, vids, mode, loops)); - for (igraph_integer_t i = 0; i < no_of_nodes; i++) { + for (igraph_int_t i = 0; i < no_of_nodes; i++) { VECTOR(*res)[i] = VECTOR(degrees)[i]; } igraph_vector_int_destroy(°rees); @@ -658,11 +657,11 @@ igraph_error_t igraph_strength( IGRAPH_CHECK(igraph_vector_resize(res, no_vids)); igraph_vector_null(res); - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + for (igraph_int_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { IGRAPH_CHECK(igraph_incident(graph, &neis, IGRAPH_VIT_GET(vit), mode, loops)); - const igraph_integer_t n = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t edge = VECTOR(neis)[j]; + const igraph_int_t n = igraph_vector_int_size(&neis); + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t edge = VECTOR(neis)[j]; VECTOR(*res)[i] += VECTOR(*weights)[edge]; } } @@ -715,7 +714,7 @@ igraph_error_t igraph_sort_vertex_ids_by_degree( igraph_vs_t vids, igraph_neimode_t mode, igraph_loops_t loops, igraph_order_t order, igraph_bool_t only_indices ) { - igraph_integer_t i, n; + igraph_int_t i, n; igraph_vector_int_t degrees; igraph_vector_int_t vs_vec; IGRAPH_VECTOR_INT_INIT_FINALLY(°rees, 0); diff --git a/src/vendor/cigraph/src/properties/ecc.c b/src/vendor/cigraph/src/properties/ecc.c index 5701596f0c8..4a5dd7bfd19 100644 --- a/src/vendor/cigraph/src/properties/ecc.c +++ b/src/vendor/cigraph/src/properties/ecc.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify @@ -34,7 +34,7 @@ static igraph_error_t igraph_i_ecc3_1( const igraph_t *graph, igraph_vector_t *res, const igraph_es_t eids, igraph_bool_t offset, igraph_bool_t normalize) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degree; igraph_adjlist_t al; igraph_eit_t eit; @@ -51,12 +51,12 @@ static igraph_error_t igraph_i_ecc3_1( IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_EIT_SIZE(eit))); - for (igraph_integer_t i=0; + for (igraph_int_t i=0; ! IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit), i++) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); - igraph_integer_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); + igraph_int_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); igraph_real_t z; /* number of triangles the edge participates in */ igraph_real_t s; /* max number of triangles the edge could be part of */ @@ -69,7 +69,7 @@ static igraph_error_t igraph_i_ecc3_1( s = 0.0; } else { const igraph_vector_int_t *a1 = igraph_adjlist_get(&al, v1), *a2 = igraph_adjlist_get(&al, v2); - igraph_integer_t d1 = VECTOR(degree)[v1], d2 = VECTOR(degree)[v2]; + igraph_int_t d1 = VECTOR(degree)[v1], d2 = VECTOR(degree)[v2]; z = igraph_vector_int_intersection_size_sorted(a1, a2); s = (d1 < d2 ? d1 : d2) - 1.0; @@ -105,12 +105,12 @@ static igraph_error_t igraph_i_ecc3_2( IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_EIT_SIZE(eit))); - for (igraph_integer_t i=0; + for (igraph_int_t i=0; ! IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit), i++) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); - igraph_integer_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); + igraph_int_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); igraph_real_t z; /* number of triangles the edge participates in */ igraph_real_t s; /* max number of triangles the edge could be part of */ @@ -125,7 +125,7 @@ static igraph_error_t igraph_i_ecc3_2( igraph_vector_int_t *a1 = igraph_lazy_adjlist_get(&al, v1); igraph_vector_int_t *a2 = igraph_lazy_adjlist_get(&al, v2); - igraph_integer_t d1, d2; + igraph_int_t d1, d2; IGRAPH_CHECK(igraph_degree_1(graph, &d1, v1, IGRAPH_ALL, IGRAPH_LOOPS)); IGRAPH_CHECK(igraph_degree_1(graph, &d2, v2, IGRAPH_ALL, IGRAPH_LOOPS)); @@ -150,7 +150,7 @@ static igraph_error_t igraph_i_ecc4_1( const igraph_t *graph, igraph_vector_t *res, const igraph_es_t eids, igraph_bool_t offset, igraph_bool_t normalize) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t degree; igraph_adjlist_t al; igraph_eit_t eit; @@ -167,12 +167,12 @@ static igraph_error_t igraph_i_ecc4_1( IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_EIT_SIZE(eit))); - for (igraph_integer_t i=0; + for (igraph_int_t i=0; ! IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit), i++) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); - igraph_integer_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); + igraph_int_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); igraph_real_t z; /* number of 4-cycles the edge participates in */ igraph_real_t s; /* max number of 4-cycles the edge could be part of */ @@ -185,16 +185,16 @@ static igraph_error_t igraph_i_ecc4_1( } else { /* ensure that v1 is the vertex with the smaller degree */ if (VECTOR(degree)[v1] > VECTOR(degree)[v2]) { - igraph_integer_t tmp = v1; + igraph_int_t tmp = v1; v1 = v2; v2 = tmp; } z = 0.0; const igraph_vector_int_t *a1 = igraph_adjlist_get(&al, v1); - const igraph_integer_t n = igraph_vector_int_size(a1); - for (igraph_integer_t j=0; j < n; j++) { - igraph_integer_t v3 = VECTOR(*a1)[j]; + const igraph_int_t n = igraph_vector_int_size(a1); + for (igraph_int_t j=0; j < n; j++) { + igraph_int_t v3 = VECTOR(*a1)[j]; /* It is not possible that v3 == v1 because self-loops have been removed from the adjlist. */ @@ -205,7 +205,7 @@ static igraph_error_t igraph_i_ecc4_1( z += igraph_vector_int_intersection_size_sorted(a2, a3) - 1.0; } - igraph_integer_t d1 = VECTOR(degree)[v1], d2 = VECTOR(degree)[v2]; + igraph_int_t d1 = VECTOR(degree)[v1], d2 = VECTOR(degree)[v2]; s = (d1 - 1.0) * (d2 - 1.0); } @@ -239,19 +239,19 @@ static igraph_error_t igraph_i_ecc4_2( IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_EIT_SIZE(eit))); - for (igraph_integer_t i=0; + for (igraph_int_t i=0; ! IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit), i++) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); - igraph_integer_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); + igraph_int_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t v1 = IGRAPH_FROM(graph, edge), v2 = IGRAPH_TO(graph, edge); igraph_real_t z; /* number of 4-cycles the edge participates in */ igraph_real_t s; /* max number of 4-cycles the edge could be part of */ IGRAPH_ALLOW_INTERRUPTION(); - igraph_integer_t d1, d2; + igraph_int_t d1, d2; IGRAPH_CHECK(igraph_degree_1(graph, &d1, v1, IGRAPH_ALL, IGRAPH_LOOPS)); IGRAPH_CHECK(igraph_degree_1(graph, &d2, v2, IGRAPH_ALL, IGRAPH_LOOPS)); @@ -261,7 +261,7 @@ static igraph_error_t igraph_i_ecc4_2( } else { /* ensure that v1 is the vertex with the smaller degree */ if (d1 > d2) { - igraph_integer_t tmp = v1; + igraph_int_t tmp = v1; v1 = v2; v2 = tmp; @@ -274,9 +274,9 @@ static igraph_error_t igraph_i_ecc4_2( igraph_vector_int_t *a1 = igraph_lazy_adjlist_get(&al, v1); - const igraph_integer_t n = igraph_vector_int_size(a1); - for (igraph_integer_t j=0; j < n; j++) { - igraph_integer_t v3 = VECTOR(*a1)[j]; + const igraph_int_t n = igraph_vector_int_size(a1); + for (igraph_int_t j=0; j < n; j++) { + igraph_int_t v3 = VECTOR(*a1)[j]; /* It is not possible that v3 == v1 because self-loops have been removed from the adjlist. */ @@ -307,8 +307,6 @@ static igraph_error_t igraph_i_ecc4_2( * \function igraph_ecc * \brief Edge clustering coefficient of some edges. * - * \experimental - * * The edge clustering coefficient C^(k)_ij of an edge (i, j) * is defined based on the number of k-cycles the edge participates in, * z^(k)_ij, and the largest number of such cycles it could @@ -359,7 +357,7 @@ static igraph_error_t igraph_i_ecc4_2( * When \p k is 4, O(|V| d log d + |E| d^2). d denotes the degree of vertices. */ igraph_error_t igraph_ecc(const igraph_t *graph, igraph_vector_t *res, - const igraph_es_t eids, igraph_integer_t k, + const igraph_es_t eids, igraph_int_t k, igraph_bool_t offset, igraph_bool_t normalize) { if (k < 3) { diff --git a/src/vendor/cigraph/src/properties/girth.c b/src/vendor/cigraph/src/properties/girth.c index df52e696ec4..c5195f55a33 100644 --- a/src/vendor/cigraph/src/properties/girth.c +++ b/src/vendor/cigraph/src/properties/girth.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -58,9 +58,9 @@ * \param graph The input graph. Edge directions will be ignored. * \param girth Pointer to an \c igraph_real_t, if not \c NULL then the result * will be stored here. - * \param circle Pointer to an initialized vector, the vertex IDs in - * the shortest circle will be stored here. If \c NULL then it is - * ignored. + * \param cycle Pointer to an initialized vector, the vertex IDs in + * the shortest cycle of length at least 3 will be stored here. + * If \c NULL then it is ignored. * \return Error code. * * Time complexity: O((|V|+|E|)^2), |V| is the number of vertices, |E| @@ -70,20 +70,21 @@ * * \example examples/simple/igraph_girth.c */ -igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth, - igraph_vector_int_t *circle) { +igraph_error_t igraph_girth(const igraph_t *graph, + igraph_real_t *girth, + igraph_vector_int_t *cycle) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; igraph_lazy_adjlist_t adjlist; - igraph_integer_t mincirc = IGRAPH_INTEGER_MAX, minvertex = 0; - igraph_integer_t node; + igraph_int_t mincirc = IGRAPH_INTEGER_MAX, minvertex = 0; + igraph_int_t node; igraph_bool_t triangle = false; igraph_vector_int_t *neis; igraph_vector_int_t level; - igraph_integer_t stoplevel = no_of_nodes + 1; + igraph_int_t stoplevel = no_of_nodes + 1; igraph_bool_t anycircle = false; - igraph_integer_t t1 = 0, t2 = 0; + igraph_int_t t1 = 0, t2 = 0; IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); @@ -111,9 +112,9 @@ igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth, IGRAPH_ALLOW_INTERRUPTION(); while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actlevel = VECTOR(level)[actnode]; - igraph_integer_t i, n; + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actlevel = VECTOR(level)[actnode]; + igraph_int_t i, n; if (actlevel >= stoplevel) { break; @@ -124,8 +125,8 @@ igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth, n = igraph_vector_int_size(neis); for (i = 0; i < n; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; - igraph_integer_t neilevel = VECTOR(level)[nei]; + igraph_int_t nei = VECTOR(*neis)[i]; + igraph_int_t neilevel = VECTOR(level)[nei]; if (neilevel != 0) { if (neilevel == actlevel - 1) { continue; @@ -148,7 +149,7 @@ igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth, } } } else { - igraph_dqueue_int_push(&q, nei); + IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); VECTOR(level)[nei] = actlevel + 1; } } @@ -169,42 +170,42 @@ igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth, } /* Store the actual circle, if needed */ - if (circle) { - IGRAPH_CHECK(igraph_vector_int_resize(circle, mincirc)); + if (cycle) { + IGRAPH_CHECK(igraph_vector_int_resize(cycle, mincirc)); if (mincirc != 0) { - igraph_integer_t i, n, idx = 0; + igraph_int_t i, n, idx = 0; igraph_dqueue_int_clear(&q); - igraph_vector_int_null(&level); /* used for father pointers */ -#define FATHER(x) (VECTOR(level)[(x)]) + igraph_vector_int_null(&level); /* used for parent pointers */ +#define PARENT(x) (VECTOR(level)[(x)]) IGRAPH_CHECK(igraph_dqueue_int_push(&q, minvertex)); - FATHER(minvertex) = minvertex; - while (FATHER(t1) == 0 || FATHER(t2) == 0) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); + PARENT(minvertex) = minvertex; + while (PARENT(t1) == 0 || PARENT(t2) == 0) { + igraph_int_t actnode = igraph_dqueue_int_pop(&q); neis = igraph_lazy_adjlist_get(&adjlist, actnode); IGRAPH_CHECK_OOM(neis, "Failed to query neighbors."); n = igraph_vector_int_size(neis); for (i = 0; i < n; i++) { - igraph_integer_t nei = VECTOR(*neis)[i]; - if (FATHER(nei) == 0) { - FATHER(nei) = actnode + 1; - igraph_dqueue_int_push(&q, nei); + igraph_int_t nei = VECTOR(*neis)[i]; + if (PARENT(nei) == 0) { + PARENT(nei) = actnode + 1; + IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); } } } /* while q !empty */ - /* Ok, now use FATHER to create the path */ + /* Ok, now use PARENT to create the path */ while (t1 != minvertex) { - VECTOR(*circle)[idx++] = t1; - t1 = FATHER(t1) - 1; + VECTOR(*cycle)[idx++] = t1; + t1 = PARENT(t1) - 1; } - VECTOR(*circle)[idx] = minvertex; + VECTOR(*cycle)[idx] = minvertex; idx = mincirc - 1; while (t2 != minvertex) { - VECTOR(*circle)[idx--] = t2; - t2 = FATHER(t2) - 1; + VECTOR(*cycle)[idx--] = t2; + t2 = PARENT(t2) - 1; } } /* anycircle */ } /* circle */ -#undef FATHER +#undef PARENT igraph_vector_int_destroy(&level); igraph_dqueue_int_destroy(&q); diff --git a/src/vendor/cigraph/src/properties/loops.c b/src/vendor/cigraph/src/properties/loops.c index ed220512268..e77a7de8d2d 100644 --- a/src/vendor/cigraph/src/properties/loops.c +++ b/src/vendor/cigraph/src/properties/loops.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -46,7 +46,7 @@ * \example examples/simple/igraph_is_loop.c */ igraph_error_t igraph_has_loop(const igraph_t *graph, igraph_bool_t *res) { - igraph_integer_t i, m = igraph_ecount(graph); + igraph_int_t i, m = igraph_ecount(graph); IGRAPH_RETURN_IF_CACHED_BOOL(graph, IGRAPH_PROP_HAS_LOOP, res); @@ -98,8 +98,8 @@ igraph_error_t igraph_is_loop(const igraph_t *graph, igraph_vector_bool_t *res, goto done; } - for (igraph_integer_t i = 0; !IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); + for (igraph_int_t i = 0; !IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) { + igraph_int_t e = IGRAPH_EIT_GET(eit); igraph_bool_t is_loop = (IGRAPH_FROM(graph, e) == IGRAPH_TO(graph, e)); VECTOR(*res)[i] = is_loop; if (is_loop) { @@ -134,9 +134,9 @@ igraph_error_t igraph_is_loop(const igraph_t *graph, igraph_vector_bool_t *res, * * \example examples/simple/igraph_is_loop.c */ -igraph_error_t igraph_count_loops(const igraph_t *graph, igraph_integer_t *loop_count) { - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t count; +igraph_error_t igraph_count_loops(const igraph_t *graph, igraph_int_t *loop_count) { + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t count; /* Nothing to do if we know that there are no loops. */ if (igraph_i_property_cache_has(graph, IGRAPH_PROP_HAS_LOOP) && @@ -146,7 +146,7 @@ igraph_error_t igraph_count_loops(const igraph_t *graph, igraph_integer_t *loop_ } count = 0; - for (igraph_integer_t e=0; e < no_of_edges; e++) { + for (igraph_int_t e=0; e < no_of_edges; e++) { if (IGRAPH_FROM(graph, e) == IGRAPH_TO(graph, e)) { count++; } diff --git a/src/vendor/cigraph/src/properties/multiplicity.c b/src/vendor/cigraph/src/properties/multiplicity.c index 87cbd6ff150..51b48248c18 100644 --- a/src/vendor/cigraph/src/properties/multiplicity.c +++ b/src/vendor/cigraph/src/properties/multiplicity.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -50,8 +50,8 @@ * Time complexity: O(|V|+|E|). */ igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res, igraph_bool_t directed) { - igraph_integer_t vc = igraph_vcount(graph); - igraph_integer_t ec = igraph_ecount(graph); + igraph_int_t vc = igraph_vcount(graph); + igraph_int_t ec = igraph_ecount(graph); /* Is it already known whether the graph has loops or multi-edges? */ igraph_bool_t known_loop, known_multi; @@ -98,12 +98,12 @@ igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res, igrap } else { igraph_vector_int_t neis; IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); - for (igraph_integer_t i = 0; i < vc; i++) { + for (igraph_int_t i = 0; i < vc; i++) { IGRAPH_CHECK(igraph_neighbors( graph, &neis, i, IGRAPH_OUT, IGRAPH_LOOPS, IGRAPH_MULTIPLE )); - const igraph_integer_t n = igraph_vector_int_size(&neis); - for (igraph_integer_t j = 0; j < n; j++) { + const igraph_int_t n = igraph_vector_int_size(&neis); + for (igraph_int_t j = 0; j < n; j++) { if (VECTOR(neis)[j] == i) { known_loop = true; has_loop = true; break; } @@ -174,8 +174,8 @@ igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res, igrap * \example examples/simple/igraph_has_multiple.c */ igraph_error_t igraph_has_multiple(const igraph_t *graph, igraph_bool_t *res) { - igraph_integer_t vc = igraph_vcount(graph); - igraph_integer_t ec = igraph_ecount(graph); + igraph_int_t vc = igraph_vcount(graph); + igraph_int_t ec = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); IGRAPH_RETURN_IF_CACHED_BOOL(graph, IGRAPH_PROP_HAS_MULTI, res); @@ -184,7 +184,7 @@ igraph_error_t igraph_has_multiple(const igraph_t *graph, igraph_bool_t *res) { *res = false; } else { igraph_vector_int_t neis; - igraph_integer_t i, j, n; + igraph_int_t i, j, n; igraph_bool_t found = false; IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); for (i = 0; i < vc && !found; i++) { @@ -249,7 +249,7 @@ igraph_error_t igraph_has_multiple(const igraph_t *graph, igraph_bool_t *res) { igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *res, igraph_es_t es) { igraph_eit_t eit; - igraph_integer_t i, j, n; + igraph_int_t i, j, n; igraph_lazy_inclist_t inclist; IGRAPH_CHECK(igraph_eit_create(graph, es, &eit)); @@ -261,9 +261,9 @@ igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *r IGRAPH_CHECK(igraph_vector_bool_resize(res, IGRAPH_EIT_SIZE(eit))); for (i = 0; !IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); + igraph_int_t e = IGRAPH_EIT_GET(eit); + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); igraph_vector_int_t *neis = igraph_lazy_inclist_get(&inclist, from); IGRAPH_CHECK_OOM(neis, "Failed to query incident edges."); @@ -272,8 +272,8 @@ igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *r n = igraph_vector_int_size(neis); for (j = 0; j < n; j++) { - igraph_integer_t e2 = VECTOR(*neis)[j]; - igraph_integer_t to2 = IGRAPH_OTHER(graph, e2, from); + igraph_int_t e2 = VECTOR(*neis)[j]; + igraph_int_t to2 = IGRAPH_OTHER(graph, e2, from); if (to2 == to && e2 < e) { VECTOR(*res)[i] = true; } @@ -313,7 +313,7 @@ igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *r igraph_error_t igraph_count_multiple(const igraph_t *graph, igraph_vector_int_t *res, igraph_es_t es) { igraph_eit_t eit; - igraph_integer_t i, j, n; + igraph_int_t i, j, n; igraph_lazy_adjlist_t adjlist; IGRAPH_CHECK(igraph_eit_create(graph, es, &eit)); @@ -324,9 +324,9 @@ igraph_error_t igraph_count_multiple(const igraph_t *graph, igraph_vector_int_t IGRAPH_CHECK(igraph_vector_int_resize(res, IGRAPH_EIT_SIZE(eit))); for (i = 0; !IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t e = IGRAPH_EIT_GET(eit); - igraph_integer_t from = IGRAPH_FROM(graph, e); - igraph_integer_t to = IGRAPH_TO(graph, e); + igraph_int_t e = IGRAPH_EIT_GET(eit); + igraph_int_t from = IGRAPH_FROM(graph, e); + igraph_int_t to = IGRAPH_TO(graph, e); igraph_vector_int_t *neis = igraph_lazy_adjlist_get(&adjlist, from); IGRAPH_CHECK_OOM(neis, "Failed to query adjacent vertices."); @@ -364,12 +364,12 @@ igraph_error_t igraph_count_multiple(const igraph_t *graph, igraph_vector_int_t * * Time complexity: O(d), where d is the out-degree of the tail of the edge. */ -igraph_error_t igraph_count_multiple_1(const igraph_t *graph, igraph_integer_t *res, - igraph_integer_t eid) +igraph_error_t igraph_count_multiple_1(const igraph_t *graph, igraph_int_t *res, + igraph_int_t eid) { - igraph_integer_t i, n, count; - igraph_integer_t from = IGRAPH_FROM(graph, eid); - igraph_integer_t to = IGRAPH_TO(graph, eid); + igraph_int_t i, n, count; + igraph_int_t from = IGRAPH_FROM(graph, eid); + igraph_int_t to = IGRAPH_TO(graph, eid); igraph_vector_int_t vids; IGRAPH_VECTOR_INT_INIT_FINALLY(&vids, 0); @@ -428,7 +428,7 @@ igraph_error_t igraph_is_mutual(const igraph_t *graph, igraph_vector_bool_t *res igraph_eit_t eit; igraph_lazy_adjlist_t adjlist; - igraph_integer_t i; + igraph_int_t i; /* How many edges do we have? */ IGRAPH_CHECK(igraph_eit_create(graph, es, &eit)); @@ -448,9 +448,9 @@ igraph_error_t igraph_is_mutual(const igraph_t *graph, igraph_vector_bool_t *res IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); for (i = 0; ! IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) { - igraph_integer_t edge = IGRAPH_EIT_GET(eit); - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); + igraph_int_t edge = IGRAPH_EIT_GET(eit); + igraph_int_t from = IGRAPH_FROM(graph, edge); + igraph_int_t to = IGRAPH_TO(graph, edge); if (from == to) { VECTOR(*res)[i] = loops; @@ -499,7 +499,7 @@ igraph_error_t igraph_is_mutual(const igraph_t *graph, igraph_vector_bool_t *res */ igraph_error_t igraph_has_mutual(const igraph_t *graph, igraph_bool_t *res, igraph_bool_t loops) { - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_lazy_adjlist_t adjlist; if (! igraph_is_directed(graph)) { @@ -529,9 +529,9 @@ igraph_error_t igraph_has_mutual(const igraph_t *graph, igraph_bool_t *res, IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); *res = false; /* assume no mutual edges */ - for (igraph_integer_t edge=0; edge < no_of_edges; edge++) { - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); + for (igraph_int_t edge=0; edge < no_of_edges; edge++) { + igraph_int_t from = IGRAPH_FROM(graph, edge); + igraph_int_t to = IGRAPH_TO(graph, edge); if (from == to) { if (loops) { diff --git a/src/vendor/cigraph/src/properties/neighborhood.c b/src/vendor/cigraph/src/properties/neighborhood.c index 2db0b8c7a84..58e44a88416 100644 --- a/src/vendor/cigraph/src/properties/neighborhood.c +++ b/src/vendor/cigraph/src/properties/neighborhood.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -68,14 +68,14 @@ * the calculation is performed, d is the average degree, o is the order. */ igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int_t *res, - igraph_vs_t vids, igraph_integer_t order, + igraph_vs_t vids, igraph_int_t order, igraph_neimode_t mode, - igraph_integer_t mindist) { + igraph_int_t mindist) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; igraph_vit_t vit; - igraph_integer_t *added; + igraph_int_t *added; igraph_vector_int_t neis; igraph_bool_t inf_order = false; @@ -89,14 +89,14 @@ igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int } if (mindist < 0) { - IGRAPH_ERRORF("Minium distance must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, mindist); + IGRAPH_ERRORF("Minimum distance must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, mindist); } if (!inf_order && mindist > order) { IGRAPH_ERRORF("Minimum distance must not exceed the neighborhood order (%" IGRAPH_PRId "), got %" IGRAPH_PRId ".", IGRAPH_EINVAL, order, mindist); } - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Insufficient memory to calculate neighborhood sizes."); IGRAPH_FINALLY(igraph_free, added); @@ -106,9 +106,9 @@ igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); IGRAPH_CHECK(igraph_vector_int_resize(res, IGRAPH_VIT_SIZE(vit))); - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - const igraph_integer_t node = IGRAPH_VIT_GET(vit); - igraph_integer_t size = mindist == 0 ? 1 : 0; + for (igraph_int_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + const igraph_int_t node = IGRAPH_VIT_GET(vit); + igraph_int_t size = mindist == 0 ? 1 : 0; added[node] = i + 1; igraph_dqueue_int_clear(&q); if (order > 0) { @@ -117,16 +117,16 @@ igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int } while (!igraph_dqueue_int_empty(&q)) { - const igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - const igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + const igraph_int_t actnode = igraph_dqueue_int_pop(&q); + const igraph_int_t actdist = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); - const igraph_integer_t n = igraph_vector_int_size(&neis); + const igraph_int_t n = igraph_vector_int_size(&neis); if (actdist < order - 1) { /* we add them to the q */ - for (igraph_integer_t j = 0; j < n; j++) { - igraph_integer_t nei = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); @@ -138,8 +138,8 @@ igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int } } else { /* we just count them, but don't add them */ - for (igraph_integer_t j = 0; j < n; j++) { - const igraph_integer_t nei = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + const igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; if (actdist + 1 >= mindist) { @@ -206,13 +206,13 @@ igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int * order. */ igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list_t *res, - igraph_vs_t vids, igraph_integer_t order, - igraph_neimode_t mode, igraph_integer_t mindist) { + igraph_vs_t vids, igraph_int_t order, + igraph_neimode_t mode, igraph_int_t mindist) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; igraph_vit_t vit; - igraph_integer_t *added; + igraph_int_t *added; igraph_vector_int_t neis; igraph_vector_int_t tmp; igraph_bool_t inf_order = false; @@ -223,14 +223,14 @@ igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list } if (mindist < 0) { - IGRAPH_ERRORF("Minium distance must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, mindist); + IGRAPH_ERRORF("Minimum distance must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, mindist); } if (!inf_order && mindist > order) { IGRAPH_ERRORF("Minimum distance must not exceed the neighborhood order (%" IGRAPH_PRId "), got %" IGRAPH_PRId ".", IGRAPH_EINVAL, order, mindist); } - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Insufficient memory to calculate neighborhood sizes."); IGRAPH_FINALLY(igraph_free, added); @@ -242,8 +242,8 @@ igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list IGRAPH_CHECK(igraph_vector_int_list_reserve(res, IGRAPH_VIT_SIZE(vit))); igraph_vector_int_list_clear(res); - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - const igraph_integer_t node = IGRAPH_VIT_GET(vit); + for (igraph_int_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + const igraph_int_t node = IGRAPH_VIT_GET(vit); added[node] = i + 1; igraph_vector_int_clear(&tmp); if (mindist == 0) { @@ -255,16 +255,16 @@ igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list } while (!igraph_dqueue_int_empty(&q)) { - const igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - const igraph_integer_t actdist = igraph_dqueue_int_pop(&q); + const igraph_int_t actnode = igraph_dqueue_int_pop(&q); + const igraph_int_t actdist = igraph_dqueue_int_pop(&q); IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); - const igraph_integer_t n = igraph_vector_int_size(&neis); + const igraph_int_t n = igraph_vector_int_size(&neis); if (actdist < order - 1) { /* we add them to the q */ - for (igraph_integer_t j = 0; j < n; j++) { - const igraph_integer_t nei = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + const igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); @@ -276,8 +276,8 @@ igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list } } else { /* we just count them but don't add them to q */ - for (igraph_integer_t j = 0; j < n; j++) { - const igraph_integer_t nei = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + const igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; if (actdist + 1 >= mindist) { @@ -350,13 +350,13 @@ igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list * vertices and edges in the original input graph. */ igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_list_t *res, - igraph_vs_t vids, igraph_integer_t order, + igraph_vs_t vids, igraph_int_t order, igraph_neimode_t mode, - igraph_integer_t mindist) { - const igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t mindist) { + const igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_dqueue_int_t q; igraph_vit_t vit; - igraph_integer_t *added; + igraph_int_t *added; igraph_vector_int_t neis; igraph_vector_int_t tmp; igraph_t newg; @@ -368,14 +368,14 @@ igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_li } if (mindist < 0) { - IGRAPH_ERRORF("Minium distance must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, mindist); + IGRAPH_ERRORF("Minimum distance must not be negative, got %" IGRAPH_PRId ".", IGRAPH_EINVAL, mindist); } if (!inf_order && mindist > order) { IGRAPH_ERRORF("Minimum distance must not exceed the neighborhood order (%" IGRAPH_PRId "), got %" IGRAPH_PRId ".", IGRAPH_EINVAL, order, mindist); } - added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(added, "Insufficient memory to calculate neighborhood graphs."); IGRAPH_FINALLY(igraph_free, added); @@ -387,8 +387,8 @@ igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_li igraph_graph_list_clear(res); - for (igraph_integer_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - const igraph_integer_t node = IGRAPH_VIT_GET(vit); + for (igraph_int_t i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + const igraph_int_t node = IGRAPH_VIT_GET(vit); added[node] = i + 1; igraph_vector_int_clear(&tmp); if (mindist == 0) { @@ -400,16 +400,16 @@ igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_li } while (!igraph_dqueue_int_empty(&q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&q); - igraph_integer_t actdist = igraph_dqueue_int_pop(&q); - igraph_integer_t n; + igraph_int_t actnode = igraph_dqueue_int_pop(&q); + igraph_int_t actdist = igraph_dqueue_int_pop(&q); + igraph_int_t n; IGRAPH_CHECK(igraph_neighbors(graph, &neis, actnode, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); n = igraph_vector_int_size(&neis); if (actdist < order - 1) { /* we add them to the q */ - for (igraph_integer_t j = 0; j < n; j++) { - const igraph_integer_t nei = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + const igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei)); @@ -421,8 +421,8 @@ igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_li } } else { /* we just count them but don't add them to q */ - for (igraph_integer_t j = 0; j < n; j++) { - const igraph_integer_t nei = VECTOR(neis)[j]; + for (igraph_int_t j = 0; j < n; j++) { + const igraph_int_t nei = VECTOR(neis)[j]; if (added[nei] != i + 1) { added[nei] = i + 1; if (actdist + 1 >= mindist) { diff --git a/src/vendor/cigraph/src/properties/perfect.c b/src/vendor/cigraph/src/properties/perfect.c index 8f0988bbc38..f931427a467 100644 --- a/src/vendor/cigraph/src/properties/perfect.c +++ b/src/vendor/cigraph/src/properties/perfect.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -56,10 +56,10 @@ igraph_error_t igraph_is_perfect(const igraph_t *graph, igraph_bool_t *perfect) igraph_bool_t is_bipartite, is_chordal, iso, is_simple; igraph_real_t girth, comp_girth; - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t start; - igraph_integer_t cycle_len; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t start; + igraph_int_t cycle_len; igraph_t comp_graph, cycle; // If the graph is directed return error. @@ -129,13 +129,13 @@ igraph_error_t igraph_is_perfect(const igraph_t *graph, igraph_bool_t *perfect) // If the girth (or the smallest circle in the graph) is bigger than 3 and have odd number of vertices then // the graph isn't perfect. IGRAPH_CHECK(igraph_girth(graph, &girth, NULL)); - if ((girth > 3) && (((igraph_integer_t)girth) % 2 == 1)) { + if ((girth > 3) && (((igraph_int_t)girth) % 2 == 1)) { *perfect = false; goto clean1; } IGRAPH_CHECK(igraph_girth(&comp_graph, &comp_girth, NULL)); - if ((comp_girth > 3) && (((igraph_integer_t)comp_girth) % 2 == 1)) { + if ((comp_girth > 3) && (((igraph_int_t)comp_girth) % 2 == 1)) { *perfect = false; goto clean1; } @@ -145,7 +145,7 @@ igraph_error_t igraph_is_perfect(const igraph_t *graph, igraph_bool_t *perfect) // Strong perfect graph theorem: // A graph is perfect iff neither it or its complement contains an induced odd cycle of length >= 5 // (i.e. an odd hole). TODO: Find a more efficient way to check for odd holes. - start = (igraph_integer_t) (girth < comp_girth ? girth : comp_girth); + start = (igraph_int_t) (girth < comp_girth ? girth : comp_girth); start = start % 2 == 0 ? start + 1 : start + 2; for (cycle_len = start; cycle_len <= no_of_nodes ; cycle_len += 2) { diff --git a/src/vendor/cigraph/src/properties/properties_internal.h b/src/vendor/cigraph/src/properties/properties_internal.h index 70d6a8a3b4e..e16b6e5f92b 100644 --- a/src/vendor/cigraph/src/properties/properties_internal.h +++ b/src/vendor/cigraph/src/properties/properties_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-2021 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/properties/rich_club.c b/src/vendor/cigraph/src/properties/rich_club.c index cf0de3dc18b..30076270b53 100644 --- a/src/vendor/cigraph/src/properties/rich_club.c +++ b/src/vendor/cigraph/src/properties/rich_club.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ * Loops, undirected: n * (n+1) / 2 * Loops, directed: n^2 */ -static igraph_real_t total_possible_edges(igraph_integer_t vcount, +static igraph_real_t total_possible_edges(igraph_int_t vcount, igraph_bool_t directed, igraph_bool_t loops) { igraph_real_t nv = (igraph_real_t) vcount; @@ -95,8 +95,8 @@ igraph_error_t igraph_rich_club_sequence( igraph_bool_t normalized, igraph_bool_t loops, igraph_bool_t directed) { - const igraph_integer_t vcount = igraph_vcount(graph); - const igraph_integer_t ecount = igraph_ecount(graph); + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); igraph_vector_int_t order_of; // Error handling: invalid vertex_order and weights sizes @@ -126,32 +126,32 @@ igraph_error_t igraph_rich_club_sequence( igraph_bool_t warning_issued = false; // remaining_total_weight vector: number of edges (or total edge weight) removed by index - for (igraph_integer_t eid = 0; eid < ecount; eid++) { - igraph_integer_t v1 = IGRAPH_FROM(graph, eid); - igraph_integer_t v2 = IGRAPH_TO(graph, eid); + for (igraph_int_t eid = 0; eid < ecount; eid++) { + igraph_int_t v1 = IGRAPH_FROM(graph, eid); + igraph_int_t v2 = IGRAPH_TO(graph, eid); if (!loops && normalized && !warning_issued && v1 == v2) { IGRAPH_WARNING("Self-loops were requested to be assumed absent, " "but encountered a self-loop. Density calculations will proceed " "with the assumption of no loops."); warning_issued = true; } - igraph_integer_t order_v1 = VECTOR(order_of)[v1]; // order of endpoints - igraph_integer_t order_v2 = VECTOR(order_of)[v2]; + igraph_int_t order_v1 = VECTOR(order_of)[v1]; // order of endpoints + igraph_int_t order_v2 = VECTOR(order_of)[v2]; - igraph_integer_t edge_removal_index = (order_v1 < order_v2 ? order_v1 : order_v2); + igraph_int_t edge_removal_index = (order_v1 < order_v2 ? order_v1 : order_v2); VECTOR(*res)[edge_removal_index] += (weights ? VECTOR(*weights)[eid] : 1); } // remaining_total_weight vector: edges (or total edge weight) remaining after i removals igraph_real_t total = 0; - for (igraph_integer_t i = vcount - 1; i >= 0; i--) { + for (igraph_int_t i = vcount - 1; i >= 0; i--) { total += VECTOR(*res)[i]; VECTOR(*res)[i] = total; } // Normalize edge counts to densities if (normalized) { - for (igraph_integer_t i = 0; i < vcount; i++) { + for (igraph_int_t i = 0; i < vcount; i++) { // (vcount - i) = the number of vertices left in this loop VECTOR(*res)[i] = VECTOR(*res)[i] / diff --git a/src/vendor/cigraph/src/properties/spectral.c b/src/vendor/cigraph/src/properties/spectral.c index 380c46f001d..fa6df094a29 100644 --- a/src/vendor/cigraph/src/properties/spectral.c +++ b/src/vendor/cigraph/src/properties/spectral.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2006-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -30,7 +30,7 @@ static igraph_error_t igraph_i_laplacian_validate_weights( const igraph_t* graph, const igraph_vector_t* weights ) { - igraph_integer_t no_of_edges; + igraph_int_t no_of_edges; if (weights == NULL) { return IGRAPH_SUCCESS; @@ -102,11 +102,11 @@ igraph_error_t igraph_get_laplacian( igraph_laplacian_normalization_t normalization, const igraph_vector_t *weights ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); igraph_vector_t degree; - igraph_integer_t i; + igraph_int_t i; IGRAPH_ASSERT(res != NULL); @@ -152,8 +152,8 @@ igraph_error_t igraph_get_laplacian( } for (i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); igraph_real_t weight = weights ? VECTOR(*weights)[i] : 1.0; igraph_real_t norm; @@ -254,12 +254,12 @@ igraph_error_t igraph_get_laplacian_sparse( igraph_laplacian_normalization_t normalization, const igraph_vector_t *weights ) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t directed = igraph_is_directed(graph); igraph_vector_t degree; - igraph_integer_t i; - igraph_integer_t nz; + igraph_int_t i; + igraph_int_t nz; if (directed) { IGRAPH_SAFE_ADD(no_of_edges, no_of_nodes, &nz); @@ -303,8 +303,8 @@ igraph_error_t igraph_get_laplacian_sparse( } for (i = 0; i < no_of_edges; i++) { - igraph_integer_t from = IGRAPH_FROM(graph, i); - igraph_integer_t to = IGRAPH_TO(graph, i); + igraph_int_t from = IGRAPH_FROM(graph, i); + igraph_int_t to = IGRAPH_TO(graph, i); igraph_real_t weight = weights ? VECTOR(*weights)[i] : 1.0; igraph_real_t norm; diff --git a/src/vendor/cigraph/src/properties/trees.c b/src/vendor/cigraph/src/properties/trees.c index d30d35a4c2f..2ab6620f22c 100644 --- a/src/vendor/cigraph/src/properties/trees.c +++ b/src/vendor/cigraph/src/properties/trees.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2021 The igraph development team This program is free software; you can redistribute it and/or modify @@ -58,10 +58,10 @@ igraph_error_t igraph_unfold_tree(const igraph_t *graph, igraph_t *tree, igraph_neimode_t mode, const igraph_vector_int_t *roots, igraph_vector_int_t *vertex_index) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); - igraph_integer_t no_of_roots = igraph_vector_int_size(roots); - igraph_integer_t tree_vertex_count = no_of_nodes; + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_roots = igraph_vector_int_size(roots); + igraph_int_t tree_vertex_count = no_of_nodes; igraph_vector_int_t edges; igraph_bitset_t seen_vertices; @@ -70,7 +70,7 @@ igraph_error_t igraph_unfold_tree(const igraph_t *graph, igraph_t *tree, igraph_dqueue_int_t Q; igraph_vector_int_t neis; - igraph_integer_t v_ptr = no_of_nodes; + igraph_int_t v_ptr = no_of_nodes; if (! igraph_vector_int_isininterval(roots, 0, no_of_nodes-1)) { IGRAPH_ERROR("All roots should be vertices of the graph.", IGRAPH_EINVVID); @@ -87,24 +87,24 @@ igraph_error_t igraph_unfold_tree(const igraph_t *graph, igraph_t *tree, IGRAPH_CHECK(igraph_vector_int_range(vertex_index, 0, no_of_nodes)); } - for (igraph_integer_t r = 0; r < no_of_roots; r++) { + for (igraph_int_t r = 0; r < no_of_roots; r++) { - igraph_integer_t root = VECTOR(*roots)[r]; + igraph_int_t root = VECTOR(*roots)[r]; IGRAPH_BIT_SET(seen_vertices, root); IGRAPH_CHECK(igraph_dqueue_int_push(&Q, root)); while (!igraph_dqueue_int_empty(&Q)) { - igraph_integer_t actnode = igraph_dqueue_int_pop(&Q); + igraph_int_t actnode = igraph_dqueue_int_pop(&Q); IGRAPH_CHECK(igraph_incident(graph, &neis, actnode, mode, IGRAPH_LOOPS)); - igraph_integer_t n = igraph_vector_int_size(&neis); - for (igraph_integer_t i = 0; i < n; i++) { + igraph_int_t n = igraph_vector_int_size(&neis); + for (igraph_int_t i = 0; i < n; i++) { - igraph_integer_t edge = VECTOR(neis)[i]; - igraph_integer_t from = IGRAPH_FROM(graph, edge); - igraph_integer_t to = IGRAPH_TO(graph, edge); - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, actnode); + igraph_int_t edge = VECTOR(neis)[i]; + igraph_int_t from = IGRAPH_FROM(graph, edge); + igraph_int_t to = IGRAPH_TO(graph, edge); + igraph_int_t nei = IGRAPH_OTHER(graph, edge, actnode); if (! IGRAPH_BIT_TEST(seen_edges, edge)) { @@ -157,11 +157,11 @@ igraph_error_t igraph_unfold_tree(const igraph_t *graph, igraph_t *tree, /* igraph_is_tree -- check if a graph is a tree */ /* count the number of vertices reachable from the root */ -static igraph_error_t igraph_i_is_tree_visitor(const igraph_t *graph, igraph_integer_t root, igraph_neimode_t mode, igraph_integer_t *visited_count) { +static igraph_error_t igraph_i_is_tree_visitor(const igraph_t *graph, igraph_int_t root, igraph_neimode_t mode, igraph_int_t *visited_count) { igraph_stack_int_t stack; igraph_bitset_t visited; igraph_vector_int_t neighbors; - igraph_integer_t i; + igraph_int_t i; IGRAPH_VECTOR_INT_INIT_FINALLY(&neighbors, 0); @@ -176,8 +176,8 @@ static igraph_error_t igraph_i_is_tree_visitor(const igraph_t *graph, igraph_int IGRAPH_CHECK(igraph_stack_int_push(&stack, root)); while (! igraph_stack_int_empty(&stack)) { - igraph_integer_t u; - igraph_integer_t ncount; + igraph_int_t u; + igraph_int_t ncount; /* take a vertex from the stack, mark it as visited */ u = igraph_stack_int_pop(&stack); @@ -190,7 +190,7 @@ static igraph_error_t igraph_i_is_tree_visitor(const igraph_t *graph, igraph_int IGRAPH_CHECK(igraph_neighbors(graph, &neighbors, u, mode, IGRAPH_LOOPS, IGRAPH_MULTIPLE)); ncount = igraph_vector_int_size(&neighbors); for (i = 0; i < ncount; ++i) { - igraph_integer_t v = VECTOR(neighbors)[i]; + igraph_int_t v = VECTOR(neighbors)[i]; if (! IGRAPH_BIT_TEST(visited, v)) { IGRAPH_CHECK(igraph_stack_int_push(&stack, v)); } @@ -248,12 +248,12 @@ static igraph_error_t igraph_i_is_tree_visitor(const igraph_t *graph, igraph_int * * \example examples/simple/igraph_kary_tree.c */ -igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_integer_t *root, igraph_neimode_t mode) { +igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_int_t *root, igraph_neimode_t mode) { igraph_bool_t is_tree = false; igraph_bool_t treat_as_undirected = !igraph_is_directed(graph) || mode == IGRAPH_ALL; - igraph_integer_t iroot = 0; - igraph_integer_t visited_count; - igraph_integer_t vcount, ecount; + igraph_int_t iroot = 0; + igraph_int_t visited_count; + igraph_int_t vcount, ecount; vcount = igraph_vcount(graph); ecount = igraph_ecount(graph); @@ -325,7 +325,7 @@ igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_ case IGRAPH_IN: case IGRAPH_OUT: { igraph_vector_int_t degree; - igraph_integer_t i; + igraph_int_t i; IGRAPH_CHECK(igraph_vector_int_init(°ree, 0)); IGRAPH_FINALLY(igraph_vector_int_destroy, °ree); @@ -400,11 +400,11 @@ igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_ * including 'root' itself. */ static igraph_error_t igraph_i_is_forest_visitor( - const igraph_t *graph, igraph_integer_t root, igraph_neimode_t mode, + const igraph_t *graph, igraph_int_t root, igraph_neimode_t mode, igraph_bitset_t *visited, igraph_stack_int_t *stack, igraph_vector_int_t *neis, - igraph_integer_t *visited_count, igraph_bool_t *res) + igraph_int_t *visited_count, igraph_bool_t *res) { - igraph_integer_t i; + igraph_int_t i; igraph_stack_int_clear(stack); @@ -412,8 +412,8 @@ static igraph_error_t igraph_i_is_forest_visitor( IGRAPH_CHECK(igraph_stack_int_push(stack, root)); while (! igraph_stack_int_empty(stack)) { - igraph_integer_t u; - igraph_integer_t ncount; + igraph_int_t u; + igraph_int_t ncount; /* Take a vertex from stack and check if it is already visited. * If yes, then we found a cycle: the graph is not a forest. @@ -434,7 +434,7 @@ static igraph_error_t igraph_i_is_forest_visitor( ncount = igraph_vector_int_size(neis); for (i = 0; i < ncount; ++i) { - igraph_integer_t v = VECTOR(*neis)[i]; + igraph_int_t v = VECTOR(*neis)[i]; if (mode == IGRAPH_ALL) { /* In the undirected case, we avoid returning to the predecessor @@ -514,7 +514,8 @@ static igraph_error_t igraph_i_is_forest( * number of vertices plus the number of edges in the graph. * * \sa \ref igraph_is_tree() to check if a graph is a tree, i.e. a forest with - * a single component. + * a single component; \ref igraph_is_acyclic() to check if a graph lacks + * (undirected or directed) cycles. */ igraph_error_t igraph_is_forest(const igraph_t *graph, igraph_bool_t *res, igraph_vector_int_t *roots, igraph_neimode_t mode) { @@ -585,9 +586,9 @@ static igraph_error_t igraph_i_is_forest( igraph_bitset_t visited; igraph_vector_int_t neis; igraph_stack_int_t stack; - igraph_integer_t visited_count = 0; - igraph_integer_t vcount, ecount; - igraph_integer_t v; + igraph_int_t visited_count = 0; + igraph_int_t vcount, ecount; + igraph_int_t v; igraph_bool_t result; vcount = igraph_vcount(graph); @@ -731,6 +732,11 @@ static igraph_error_t igraph_i_is_forest( * This function checks whether a graph has any cycles. Edge directions are * considered, i.e. in directed graphs, only directed cycles are searched for. * + * + * The result of this function is cached in the graph itself; calling + * the function multiple times with no modifications to the graph in between + * will return a cached value in O(1) time. + * * \param graph The input graph. * \param res Pointer to a boolean constant, the result is stored here. @@ -738,7 +744,8 @@ static igraph_error_t igraph_i_is_forest( * * \sa \ref igraph_find_cycle() to find a cycle that demonstrates * that the graph is not acyclic; \ref igraph_is_forest() to look - * for undirected cycles even in directed graphs. + * for undirected cycles even in directed graphs; \ref igraph_is_dag() + * to test specifically for directed acyclic graphs. * * Time complexity: O(|V|+|E|), where |V| and |E| are the number of * vertices and edges in the original input graph. diff --git a/src/vendor/cigraph/src/properties/triangles.c b/src/vendor/cigraph/src/properties/triangles.c index a37d1ff9ae7..eaed274feb2 100644 --- a/src/vendor/cigraph/src/properties/triangles.c +++ b/src/vendor/cigraph/src/properties/triangles.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -79,7 +79,7 @@ igraph_error_t igraph_transitivity_avglocal_undirected(const igraph_t *graph, igraph_real_t *res, igraph_transitivity_mode_t mode) { - igraph_integer_t i, no_of_nodes = igraph_vcount(graph), nans = 0; + igraph_int_t i, no_of_nodes = igraph_vcount(graph), nans = 0; igraph_real_t sum = 0.0; igraph_vector_t vec; @@ -128,16 +128,16 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, const igraph_vs_t vids, igraph_transitivity_mode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vit_t vit; - igraph_integer_t nodes_to_calc, affected_nodes; - igraph_integer_t maxdegree = 0; - igraph_integer_t i, j, k, nn; + igraph_int_t nodes_to_calc, affected_nodes; + igraph_int_t maxdegree = 0; + igraph_int_t i, j, k, nn; igraph_lazy_adjlist_t adjlist; igraph_vector_int_t degree; igraph_vector_t indexv, avids, rank, triangles; igraph_vector_int_t order; - igraph_integer_t *neis; + igraph_int_t *neis; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); @@ -151,9 +151,9 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_reserve(&avids, nodes_to_calc)); k = 0; for (i = 0; i < nodes_to_calc; IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t v = IGRAPH_VIT_GET(vit); + igraph_int_t v = IGRAPH_VIT_GET(vit); igraph_vector_int_t *neis2; - igraph_integer_t neilen; + igraph_int_t neilen; if (VECTOR(indexv)[v] == 0) { VECTOR(indexv)[v] = k + 1; k++; IGRAPH_CHECK(igraph_vector_push_back(&avids, v)); @@ -164,7 +164,7 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, neilen = igraph_vector_int_size(neis2); for (j = 0; j < neilen; j++) { - igraph_integer_t nei = VECTOR(*neis2)[j]; + igraph_int_t nei = VECTOR(*neis2)[j]; if (VECTOR(indexv)[nei] == 0) { VECTOR(indexv)[nei] = k + 1; k++; IGRAPH_CHECK(igraph_vector_push_back(&avids, nei)); @@ -177,9 +177,9 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&order, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(°ree, affected_nodes); for (i = 0; i < affected_nodes; i++) { - igraph_integer_t v = VECTOR(avids)[i]; + igraph_int_t v = VECTOR(avids)[i]; igraph_vector_int_t *neis2; - igraph_integer_t deg; + igraph_int_t deg; neis2 = igraph_lazy_adjlist_get(&adjlist, v); IGRAPH_CHECK_OOM(neis2, "Failed to query neighbors."); VECTOR(degree)[i] = deg = igraph_vector_int_size(neis2); @@ -195,7 +195,7 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, VECTOR(rank)[ VECTOR(order)[i] ] = affected_nodes - i - 1; } - neis = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); + neis = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); if (neis == 0) { IGRAPH_ERROR("Insufficient memory for local transitivity calculation.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -203,11 +203,11 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, IGRAPH_VECTOR_INIT_FINALLY(&triangles, affected_nodes); for (nn = affected_nodes - 1; nn >= 0; nn--) { - igraph_integer_t node = VECTOR(avids) [ VECTOR(order)[nn] ]; + igraph_int_t node = VECTOR(avids) [ VECTOR(order)[nn] ]; igraph_vector_int_t *neis1, *neis2; - igraph_integer_t neilen1, neilen2; - igraph_integer_t nodeindex = VECTOR(indexv)[node]; - igraph_integer_t noderank = VECTOR(rank) [nodeindex - 1]; + igraph_int_t neilen1, neilen2; + igraph_int_t nodeindex = VECTOR(indexv)[node]; + igraph_int_t noderank = VECTOR(rank) [nodeindex - 1]; IGRAPH_ALLOW_INTERRUPTION(); @@ -216,13 +216,13 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, neilen1 = igraph_vector_int_size(neis1); for (i = 0; i < neilen1; i++) { - igraph_integer_t nei = VECTOR(*neis1)[i]; + igraph_int_t nei = VECTOR(*neis1)[i]; neis[nei] = node + 1; } for (i = 0; i < neilen1; i++) { - igraph_integer_t nei = VECTOR(*neis1)[i]; - igraph_integer_t neiindex = VECTOR(indexv)[nei]; - igraph_integer_t neirank = VECTOR(rank)[neiindex - 1]; + igraph_int_t nei = VECTOR(*neis1)[i]; + igraph_int_t neiindex = VECTOR(indexv)[nei]; + igraph_int_t neirank = VECTOR(rank)[neiindex - 1]; /* fprintf(stderr, " nei %li (indexv %li, rank %li)\n", nei, */ /* neiindex, neirank); */ @@ -231,9 +231,9 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, IGRAPH_CHECK_OOM(neis2, "Failed to query neighbors."); neilen2 = igraph_vector_int_size(neis2); for (j = 0; j < neilen2; j++) { - igraph_integer_t nei2 = VECTOR(*neis2)[j]; - igraph_integer_t nei2index = VECTOR(indexv)[nei2]; - igraph_integer_t nei2rank = VECTOR(rank)[nei2index - 1]; + igraph_int_t nei2 = VECTOR(*neis2)[j]; + igraph_int_t nei2index = VECTOR(indexv)[nei2]; + igraph_int_t nei2rank = VECTOR(rank)[nei2index - 1]; /* fprintf(stderr, " triple %li %li %li\n", node, nei, nei2); */ if (nei2rank < neirank) { continue; @@ -254,10 +254,10 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, IGRAPH_CHECK(igraph_vector_resize(res, nodes_to_calc)); IGRAPH_VIT_RESET(vit); for (i = 0; i < nodes_to_calc; i++, IGRAPH_VIT_NEXT(vit)) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); - igraph_integer_t idx = VECTOR(indexv)[node] - 1; + igraph_int_t node = IGRAPH_VIT_GET(vit); + igraph_int_t idx = VECTOR(indexv)[node] - 1; igraph_vector_int_t *neis2 = igraph_lazy_adjlist_get(&adjlist, node); - igraph_integer_t deg; + igraph_int_t deg; IGRAPH_CHECK_OOM(neis2, "Failed to query neighbors."); @@ -288,8 +288,8 @@ static igraph_error_t transitivity_local_undirected2(const igraph_t *graph, /* Note: Also used in scan.c */ igraph_error_t igraph_i_trans4_al_simplify(igraph_adjlist_t *al, const igraph_vector_int_t *rank) { - igraph_integer_t i; - igraph_integer_t n = al->length; + igraph_int_t i; + igraph_int_t n = al->length; igraph_vector_int_t mark; IGRAPH_CHECK(igraph_vector_int_init(&mark, n)); @@ -297,11 +297,11 @@ igraph_error_t igraph_i_trans4_al_simplify(igraph_adjlist_t *al, for (i = 0; i < n; i++) { igraph_vector_int_t *v = &al->adjs[i]; - igraph_integer_t j, l = igraph_vector_int_size(v); - igraph_integer_t irank = VECTOR(*rank)[i]; + igraph_int_t j, l = igraph_vector_int_size(v); + igraph_int_t irank = VECTOR(*rank)[i]; VECTOR(mark)[i] = i + 1; for (j = 0; j < l; /* nothing */) { - igraph_integer_t e = VECTOR(*v)[j]; + igraph_int_t e = VECTOR(*v)[j]; if (VECTOR(*rank)[e] > irank && VECTOR(mark)[e] != i + 1) { VECTOR(mark)[e] = i + 1; j++; @@ -379,7 +379,7 @@ igraph_error_t igraph_transitivity_local_undirected(const igraph_t *graph, return transitivity_local_undirected4(graph, res, mode); } else { igraph_vit_t vit; - igraph_integer_t size; + igraph_int_t size; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); size = IGRAPH_VIT_SIZE(vit); @@ -409,7 +409,7 @@ static igraph_error_t adjacent_triangles4(const igraph_t *graph, static igraph_error_t count_triangles_and_triples( const igraph_t *graph, igraph_real_t *triangles, igraph_real_t *connected_triples) { - const igraph_integer_t vcount = igraph_vcount(graph); + const igraph_int_t vcount = igraph_vcount(graph); igraph_vector_int_t mark; igraph_adjlist_t al; @@ -439,28 +439,28 @@ static igraph_error_t count_triangles_and_triples( * * Some other functions achieve the same via igraph_i_trans4_al_simplify(). */ - for (igraph_integer_t v1 = 0; v1 < vcount; v1++) { + for (igraph_int_t v1 = 0; v1 < vcount; v1++) { const igraph_vector_int_t *nei1 = igraph_adjlist_get(&al, v1); - const igraph_integer_t d1 = igraph_vector_int_size(nei1); + const igraph_int_t d1 = igraph_vector_int_size(nei1); if (d1 > 1) { if (connected_triples) { *connected_triples += (igraph_real_t) d1 * (d1 - 1.0) / 2.0; } - for (igraph_integer_t i=0; i < d1; i++) { - const igraph_integer_t v2 = VECTOR(*nei1)[i]; + for (igraph_int_t i=0; i < d1; i++) { + const igraph_int_t v2 = VECTOR(*nei1)[i]; if (v2 >= v1) break; VECTOR(mark)[v2] = v1+1; } - for (igraph_integer_t i=0; i < d1; i++) { - const igraph_integer_t v2 = VECTOR(*nei1)[i]; + for (igraph_int_t i=0; i < d1; i++) { + const igraph_int_t v2 = VECTOR(*nei1)[i]; if (v2 >= v1) break; const igraph_vector_int_t *nei2 = igraph_adjlist_get(&al, v2); - const igraph_integer_t d2 = igraph_vector_int_size(nei2); - for (igraph_integer_t j=0; j < d2; j++) { - const igraph_integer_t v3 = VECTOR(*nei2)[j]; + const igraph_int_t d2 = igraph_vector_int_size(nei2); + for (igraph_int_t j=0; j < d2; j++) { + const igraph_int_t v3 = VECTOR(*nei2)[j]; if (v3 >= v2) break; if (VECTOR(mark)[v3] == v1+1) { @@ -639,14 +639,14 @@ static igraph_error_t transitivity_barrat1( const igraph_vector_t *weights, igraph_transitivity_mode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vit_t vit; - igraph_integer_t nodes_to_calc; + igraph_int_t nodes_to_calc; igraph_vector_int_t *adj1, *adj2; igraph_vector_int_t neis; igraph_vector_t actw; igraph_lazy_inclist_t incident; - igraph_integer_t i; + igraph_int_t i; igraph_vector_t strength; /* Precondition: weight vector is not null, its length equals the number of @@ -673,8 +673,8 @@ static igraph_error_t transitivity_barrat1( IGRAPH_CHECK(igraph_vector_resize(res, nodes_to_calc)); for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); - igraph_integer_t adjlen1, adjlen2, j, k; + igraph_int_t node = IGRAPH_VIT_GET(vit); + igraph_int_t adjlen1, adjlen2, j, k; igraph_real_t triples, triangles; IGRAPH_ALLOW_INTERRUPTION(); @@ -684,8 +684,8 @@ static igraph_error_t transitivity_barrat1( adjlen1 = igraph_vector_int_size(adj1); /* Mark the neighbors of the node */ for (j = 0; j < adjlen1; j++) { - igraph_integer_t edge = VECTOR(*adj1)[j]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, node); + igraph_int_t edge = VECTOR(*adj1)[j]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, node); VECTOR(neis)[nei] = i + 1; VECTOR(actw)[nei] = VECTOR(*weights)[edge]; } @@ -693,15 +693,15 @@ static igraph_error_t transitivity_barrat1( triangles = 0.0; for (j = 0; j < adjlen1; j++) { - igraph_integer_t edge1 = VECTOR(*adj1)[j]; + igraph_int_t edge1 = VECTOR(*adj1)[j]; igraph_real_t weight1 = VECTOR(*weights)[edge1]; - igraph_integer_t v = IGRAPH_OTHER(graph, edge1, node); + igraph_int_t v = IGRAPH_OTHER(graph, edge1, node); adj2 = igraph_lazy_inclist_get(&incident, v); IGRAPH_CHECK_OOM(adj2, "Failed to query incident edges."); adjlen2 = igraph_vector_int_size(adj2); for (k = 0; k < adjlen2; k++) { - igraph_integer_t edge2 = VECTOR(*adj2)[k]; - igraph_integer_t v2 = IGRAPH_OTHER(graph, edge2, v); + igraph_int_t edge2 = VECTOR(*adj2)[k]; + igraph_int_t v2 = IGRAPH_OTHER(graph, edge2, v); if (VECTOR(neis)[v2] == i + 1) { triangles += (VECTOR(actw)[v2] + weight1) / 2.0; } @@ -730,17 +730,17 @@ static igraph_error_t transitivity_barrat4( const igraph_vector_t *weights, igraph_transitivity_mode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vector_int_t order; igraph_vector_int_t degree; igraph_vector_t strength; igraph_vector_t rank; - igraph_integer_t maxdegree; + igraph_int_t maxdegree; igraph_inclist_t incident; igraph_vector_int_t neis; igraph_vector_int_t *adj1, *adj2; igraph_vector_t actw; - igraph_integer_t i, nn; + igraph_int_t i, nn; /* Precondition: weight vector is not null, its length equals the number of * edges, and the graph has at least one vertex. The graph must not have @@ -776,9 +776,9 @@ static igraph_error_t transitivity_barrat4( igraph_vector_null(res); for (nn = no_of_nodes - 1; nn >= 0; nn--) { - igraph_integer_t adjlen1, adjlen2; + igraph_int_t adjlen1, adjlen2; igraph_real_t triples; - igraph_integer_t node = VECTOR(order)[nn]; + igraph_int_t node = VECTOR(order)[nn]; IGRAPH_ALLOW_INTERRUPTION(); @@ -787,24 +787,24 @@ static igraph_error_t transitivity_barrat4( triples = VECTOR(strength)[node] * (adjlen1 - 1) / 2.0; /* Mark the neighbors of the node */ for (i = 0; i < adjlen1; i++) { - igraph_integer_t edge = VECTOR(*adj1)[i]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge, node); + igraph_int_t edge = VECTOR(*adj1)[i]; + igraph_int_t nei = IGRAPH_OTHER(graph, edge, node); VECTOR(neis)[nei] = node + 1; VECTOR(actw)[nei] = VECTOR(*weights)[edge]; } for (i = 0; i < adjlen1; i++) { - igraph_integer_t edge1 = VECTOR(*adj1)[i]; + igraph_int_t edge1 = VECTOR(*adj1)[i]; igraph_real_t weight1 = VECTOR(*weights)[edge1]; - igraph_integer_t nei = IGRAPH_OTHER(graph, edge1, node); - igraph_integer_t j; + igraph_int_t nei = IGRAPH_OTHER(graph, edge1, node); + igraph_int_t j; if (VECTOR(rank)[nei] > VECTOR(rank)[node]) { adj2 = igraph_inclist_get(&incident, nei); adjlen2 = igraph_vector_int_size(adj2); for (j = 0; j < adjlen2; j++) { - igraph_integer_t edge2 = VECTOR(*adj2)[j]; + igraph_int_t edge2 = VECTOR(*adj2)[j]; igraph_real_t weight2 = VECTOR(*weights)[edge2]; - igraph_integer_t nei2 = IGRAPH_OTHER(graph, edge2, nei); + igraph_int_t nei2 = IGRAPH_OTHER(graph, edge2, nei); if (VECTOR(rank)[nei2] < VECTOR(rank)[nei]) { continue; } @@ -879,8 +879,8 @@ igraph_error_t igraph_transitivity_barrat(const igraph_t *graph, const igraph_vs_t vids, const igraph_vector_t *weights, igraph_transitivity_mode_t mode) { - igraph_integer_t no_of_nodes = igraph_vcount(graph); - igraph_integer_t no_of_edges = igraph_ecount(graph); + igraph_int_t no_of_nodes = igraph_vcount(graph); + igraph_int_t no_of_edges = igraph_ecount(graph); igraph_bool_t has_multiple; /* Handle fallback to unweighted version and common cases */ diff --git a/src/vendor/cigraph/src/properties/triangles_template.h b/src/vendor/cigraph/src/properties/triangles_template.h index fbc50e93c8f..c18bf97d08d 100644 --- a/src/vendor/cigraph/src/properties/triangles_template.h +++ b/src/vendor/cigraph/src/properties/triangles_template.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -24,16 +24,16 @@ #define TRANSIT_TRIEDGES #endif -igraph_integer_t no_of_nodes = igraph_vcount(graph); -igraph_integer_t node, i, j, nn; +igraph_int_t no_of_nodes = igraph_vcount(graph); +igraph_int_t node, i, j, nn; igraph_adjlist_t allneis; igraph_vector_int_t *neis1, *neis2; -igraph_integer_t neilen1, neilen2; -igraph_integer_t *neis; -igraph_integer_t maxdegree; +igraph_int_t neilen1, neilen2; +igraph_int_t *neis; +igraph_int_t maxdegree; #ifdef TRANSIT_TRIEDGES -igraph_integer_t deg1; +igraph_int_t deg1; #endif igraph_vector_int_t order; @@ -68,7 +68,7 @@ for (i = 0; i < no_of_nodes; i++) { IGRAPH_CHECK(igraph_i_trans4_al_simplify(&allneis, &rank)); -neis = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); +neis = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(neis, "Insufficient memory to count triangles."); IGRAPH_FINALLY(igraph_free, neis); @@ -97,11 +97,11 @@ for (nn = no_of_nodes - 1; nn >= 0; nn--) { } for (i = 0; i < neilen1; i++) { - igraph_integer_t nei = VECTOR(*neis1)[i]; + igraph_int_t nei = VECTOR(*neis1)[i]; neis2 = igraph_adjlist_get(&allneis, nei); neilen2 = igraph_vector_int_size(neis2); for (j = 0; j < neilen2; j++) { - igraph_integer_t nei2 = VECTOR(*neis2)[j]; + igraph_int_t nei2 = VECTOR(*neis2)[j]; if (neis[nei2] == node + 1) { #ifndef TRIANGLES VECTOR(*res)[nei2] += 1; diff --git a/src/vendor/cigraph/src/properties/triangles_template1.h b/src/vendor/cigraph/src/properties/triangles_template1.h index 187f5029334..8e33a5328ac 100644 --- a/src/vendor/cigraph/src/properties/triangles_template1.h +++ b/src/vendor/cigraph/src/properties/triangles_template1.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -20,14 +20,14 @@ */ -igraph_integer_t no_of_nodes = igraph_vcount(graph); +igraph_int_t no_of_nodes = igraph_vcount(graph); igraph_vit_t vit; -igraph_integer_t nodes_to_calc; +igraph_int_t nodes_to_calc; igraph_vector_int_t *neis1, *neis2; igraph_real_t triangles; -igraph_integer_t i, j, k; -igraph_integer_t neilen1, neilen2; -igraph_integer_t *neis; +igraph_int_t i, j, k; +igraph_int_t neilen1, neilen2; +igraph_int_t *neis; igraph_lazy_adjlist_t adjlist; IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); @@ -41,7 +41,7 @@ if (nodes_to_calc == 0) { return IGRAPH_SUCCESS; } -neis = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t); +neis = IGRAPH_CALLOC(no_of_nodes, igraph_int_t); IGRAPH_CHECK_OOM(neis, "Insufficient memory to count triangles."); IGRAPH_FINALLY(igraph_free, neis); @@ -51,7 +51,7 @@ IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, IGRAPH_ALL, IGRAPH_NO_LOO IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { - igraph_integer_t node = IGRAPH_VIT_GET(vit); + igraph_int_t node = IGRAPH_VIT_GET(vit); IGRAPH_ALLOW_INTERRUPTION(); @@ -64,12 +64,12 @@ for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { triangles = 0; for (j = 0; j < neilen1; j++) { - igraph_integer_t v = VECTOR(*neis1)[j]; + igraph_int_t v = VECTOR(*neis1)[j]; neis2 = igraph_lazy_adjlist_get(&adjlist, v); IGRAPH_CHECK_OOM(neis2, "Failed to query neighbors."); neilen2 = igraph_vector_int_size(neis2); for (k = 0; k < neilen2; k++) { - igraph_integer_t v2 = VECTOR(*neis2)[k]; + igraph_int_t v2 = VECTOR(*neis2)[k]; if (neis[v2] == i + 1) { triangles += 1.0; } diff --git a/src/vendor/cigraph/src/random/random.c b/src/vendor/cigraph/src/random/random.c index 15c98f76f53..708fba0192c 100644 --- a/src/vendor/cigraph/src/random/random.c +++ b/src/vendor/cigraph/src/random/random.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2005-2012 Gabor Csardi 334 Harvard street, Cambridge, MA 02139 USA @@ -207,7 +207,7 @@ static uint64_t igraph_i_rng_get_uint64_bounded(igraph_rng_t *rng, uint64_t rang static double igraph_i_norm_rand(igraph_rng_t *rng); static double igraph_i_exp_rand(igraph_rng_t *rng); -static double igraph_i_rbinom(igraph_rng_t *rng, igraph_integer_t n, double pp); +static double igraph_i_rbinom(igraph_rng_t *rng, igraph_int_t n, double pp); static double igraph_i_rexp(igraph_rng_t *rng, double rate); static double igraph_i_rgamma(igraph_rng_t *rng, double shape, double scale); static double igraph_i_rpois(igraph_rng_t *rng, double rate); @@ -274,7 +274,7 @@ igraph_error_t igraph_rng_seed(igraph_rng_t *rng, igraph_uint_t seed) { * * Time complexity: O(1). */ -igraph_integer_t igraph_rng_bits(const igraph_rng_t* rng) { +igraph_int_t igraph_rng_bits(const igraph_rng_t* rng) { return rng->type->bits; } @@ -335,7 +335,7 @@ const char *igraph_rng_name(const igraph_rng_t *rng) { */ static igraph_uint_t igraph_i_rng_get_random_bits(igraph_rng_t *rng, uint8_t bits) { const igraph_rng_type_t *type = rng->type; - igraph_integer_t rng_bitwidth = igraph_rng_bits(rng); + igraph_int_t rng_bitwidth = igraph_rng_bits(rng); igraph_uint_t result; if (rng_bitwidth >= bits) { @@ -374,7 +374,7 @@ static igraph_uint_t igraph_i_rng_get_random_bits(igraph_rng_t *rng, uint8_t bit */ static uint64_t igraph_i_rng_get_random_bits_uint64(igraph_rng_t *rng, uint8_t bits) { const igraph_rng_type_t *type = rng->type; - igraph_integer_t rng_bitwidth = igraph_rng_bits(rng); + igraph_int_t rng_bitwidth = igraph_rng_bits(rng); uint64_t result; if (rng_bitwidth >= bits) { @@ -561,7 +561,7 @@ static igraph_uint_t igraph_i_rng_get_uint_bounded(igraph_rng_t *rng, igraph_uin igraph_bool_t igraph_rng_get_bool(igraph_rng_t *rng) { const igraph_rng_type_t *type = rng->type; - const igraph_integer_t rng_bitwidth = igraph_rng_bits(rng); + const igraph_int_t rng_bitwidth = igraph_rng_bits(rng); /* Keep the highest bit as RNGs sometimes tend to have lower entropy in * low bits than in high bits. * @@ -588,8 +588,8 @@ igraph_bool_t igraph_rng_get_bool(igraph_rng_t *rng) { * \ref igraph_rng_bits(rng). */ -igraph_integer_t igraph_rng_get_integer( - igraph_rng_t *rng, igraph_integer_t l, igraph_integer_t h +igraph_int_t igraph_rng_get_integer( + igraph_rng_t *rng, igraph_int_t l, igraph_int_t h ) { const igraph_rng_type_t *type = rng->type; igraph_uint_t range; @@ -607,9 +607,9 @@ igraph_integer_t igraph_rng_get_integer( if (IGRAPH_UNLIKELY(l == IGRAPH_INTEGER_MIN && h == IGRAPH_INTEGER_MAX)) { /* Full uint range is needed, we can just grab a random number from * the uint range and cast it to a signed integer */ - return (igraph_integer_t) igraph_i_rng_get_uint(rng); + return (igraph_int_t) igraph_i_rng_get_uint(rng); } else if (l >= 0 || h < 0) { - /* this is okay, (h - l) will not overflow an igraph_integer_t */ + /* this is okay, (h - l) will not overflow an igraph_int_t */ range = (igraph_uint_t)(h - l) + 1; } else { /* (h - l) could potentially overflow so we need to play it safe. If we @@ -767,7 +767,7 @@ igraph_real_t igraph_rng_get_geom(igraph_rng_t *rng, igraph_real_t p) { * Time complexity: depends on the RNG. */ -igraph_real_t igraph_rng_get_binom(igraph_rng_t *rng, igraph_integer_t n, igraph_real_t p) { +igraph_real_t igraph_rng_get_binom(igraph_rng_t *rng, igraph_int_t n, igraph_real_t p) { const igraph_rng_type_t *type = rng->type; if (type->get_binom) { return type->get_binom(rng->state, n, p); @@ -872,16 +872,16 @@ igraph_real_t igraph_rng_get_pois(igraph_rng_t *rng, igraph_real_t rate) { */ static void igraph_i_random_sample_alga(igraph_vector_int_t *res, - igraph_integer_t l, igraph_integer_t h, - igraph_integer_t length) { + igraph_int_t l, igraph_int_t h, + igraph_int_t length) { /* Vitter: Variables V, quot, Nreal, and top are of type real */ - igraph_integer_t N = h - l + 1; - igraph_integer_t n = length; + igraph_int_t N = h - l + 1; + igraph_int_t n = length; igraph_real_t top = N - n; igraph_real_t Nreal = N; - igraph_integer_t S = 0; + igraph_int_t S = 0; igraph_real_t V, quot; l = l - 1; @@ -946,23 +946,23 @@ static void igraph_i_random_sample_alga(igraph_vector_int_t *res, * \example examples/simple/igraph_random_sample.c */ -igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_integer_t l, igraph_integer_t h, - igraph_integer_t length) { - igraph_integer_t N; /* := h - l + 1 */ +igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_int_t l, igraph_int_t h, + igraph_int_t length) { + igraph_int_t N; /* := h - l + 1 */ IGRAPH_SAFE_ADD(h, -l, &N); IGRAPH_SAFE_ADD(N, 1, &N); - igraph_integer_t n = length; + igraph_int_t n = length; igraph_real_t nreal = length; igraph_real_t ninv = (nreal != 0) ? 1.0 / nreal : 0.0; igraph_real_t Nreal = N; igraph_real_t Vprime; - igraph_integer_t qu1 = -n + 1 + N; + igraph_int_t qu1 = -n + 1 + N; igraph_real_t qu1real = -nreal + 1.0 + Nreal; igraph_real_t negalphainv = -13; igraph_real_t threshold = -negalphainv * n; - igraph_integer_t S; + igraph_int_t S; /* getting back some sense of sanity */ if (l > h) { @@ -985,7 +985,7 @@ igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_integer_t l } if (length == N) { IGRAPH_CHECK(igraph_vector_int_resize(res, length)); - for (igraph_integer_t i = 0; i < length; i++) { + for (igraph_int_t i = 0; i < length; i++) { VECTOR(*res)[i] = l++; } return IGRAPH_SUCCESS; @@ -1102,7 +1102,7 @@ static void igraph_i_random_sample_alga_real(igraph_vector_t *res, * This function is the 'real' version of \ref igraph_random_sample(), and was added * so \ref igraph_erdos_renyi_game_gnm() and related functions can use a random sample * of doubles instead of integers to prevent overflows on systems with 32-bit - * \type igraph_integer_t. + * \type igraph_int_t. * * \param res Pointer to an initialized vector. This will hold the * result. It will be resized to the proper size. @@ -1122,10 +1122,10 @@ static void igraph_i_random_sample_alga_real(igraph_vector_t *res, */ igraph_error_t igraph_i_random_sample_real(igraph_vector_t *res, igraph_real_t l, - igraph_real_t h, igraph_integer_t length) { + igraph_real_t h, igraph_int_t length) { /* This function is the 'real' version of igraph_random_sample, and was added * so erdos_renyi_game_gnm can use a random sample of doubles instead of integers - * to prevent overflows on systems with 32-bits igraph_integer_t. + * to prevent overflows on systems with 32-bits igraph_int_t. */ igraph_real_t N = h - l + 1; igraph_real_t n = length; @@ -1167,7 +1167,7 @@ igraph_error_t igraph_i_random_sample_real(igraph_vector_t *res, igraph_real_t l } if (length == N) { IGRAPH_CHECK(igraph_vector_resize(res, length)); - for (igraph_integer_t i = 0; i < length; i++) { + for (igraph_int_t i = 0; i < length; i++) { VECTOR(*res)[i] = l++; } return IGRAPH_SUCCESS; @@ -1515,11 +1515,11 @@ static double igraph_i_qnorm5(double p, double mu, double sigma, igraph_bool_t l return mu + sigma * val; } -static igraph_integer_t imax2(igraph_integer_t x, igraph_integer_t y) { +static igraph_int_t imax2(igraph_int_t x, igraph_int_t y) { return (x < y) ? y : x; } -static igraph_integer_t imin2(igraph_integer_t x, igraph_integer_t y) { +static igraph_int_t imin2(igraph_int_t x, igraph_int_t y) { return (x < y) ? x : y; } @@ -1616,7 +1616,7 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { /* These are static --- persistent between calls for same mu : */ static IGRAPH_THREAD_LOCAL int l; - static IGRAPH_THREAD_LOCAL igraph_integer_t m; + static IGRAPH_THREAD_LOCAL igraph_int_t m; static IGRAPH_THREAD_LOCAL double b1, b2, c, c0, c1, c2, c3; static IGRAPH_THREAD_LOCAL double pp[36], p0, p, q, s, d, omega; @@ -1663,7 +1663,7 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { /*muprev = 0.;-* such that next time, mu != muprev ..*/ if (mu != muprev) { muprev = mu; - m = imax2(1, (igraph_integer_t) mu); + m = imax2(1, (igraph_int_t) mu); l = 0; /* pp[] is already ok up to pp[l] */ q = p0 = p = exp(-mu); } @@ -1821,18 +1821,18 @@ static double igraph_i_rpois(igraph_rng_t *rng, double mu) { #define repeat for(;;) -static double igraph_i_rbinom(igraph_rng_t *rng, igraph_integer_t n, double pp) { +static double igraph_i_rbinom(igraph_rng_t *rng, igraph_int_t n, double pp) { static IGRAPH_THREAD_LOCAL double c, fm, npq, p1, p2, p3, p4, qn; static IGRAPH_THREAD_LOCAL double xl, xll, xlr, xm, xr; static IGRAPH_THREAD_LOCAL double psave = -1.0; - static IGRAPH_THREAD_LOCAL igraph_integer_t nsave = -1; - static IGRAPH_THREAD_LOCAL igraph_integer_t m; + static IGRAPH_THREAD_LOCAL igraph_int_t nsave = -1; + static IGRAPH_THREAD_LOCAL igraph_int_t m; double f, f1, f2, u, v, w, w2, x, x1, x2, z, z2; double p, q, np, g, r, al, alv, amaxp, ffm, ynorm; - igraph_integer_t i, ix, k; + igraph_int_t i, ix, k; if (!isfinite(pp) || /* n=0, p=0, p=1 are not errors */ diff --git a/src/vendor/cigraph/src/random/random_device.cpp b/src/vendor/cigraph/src/random/random_device.cpp index b2a8abab16e..2a79a6b1cf5 100644 --- a/src/vendor/cigraph/src/random/random_device.cpp +++ b/src/vendor/cigraph/src/random/random_device.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify it under diff --git a/src/vendor/cigraph/src/random/random_internal.h b/src/vendor/cigraph/src/random/random_internal.h index f935fd7c020..3a3c3afd550 100644 --- a/src/vendor/cigraph/src/random/random_internal.h +++ b/src/vendor/cigraph/src/random/random_internal.h @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2021-2025 The igraph development team This program is free software; you can redistribute it and/or modify it under @@ -26,7 +26,7 @@ IGRAPH_BEGIN_C_DECLS igraph_error_t igraph_i_random_sample_real( igraph_vector_t *res, igraph_real_t l, igraph_real_t h, - igraph_integer_t length); + igraph_int_t length); igraph_uint_t igraph_i_get_random_seed(void); diff --git a/src/vendor/cigraph/src/random/rng_glibc2.c b/src/vendor/cigraph/src/random/rng_glibc2.c index 968f5d46e81..fd9cf41431a 100644 --- a/src/vendor/cigraph/src/random/rng_glibc2.c +++ b/src/vendor/cigraph/src/random/rng_glibc2.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/random/rng_mt19937.c b/src/vendor/cigraph/src/random/rng_mt19937.c index adff540a312..c30988a0e82 100644 --- a/src/vendor/cigraph/src/random/rng_mt19937.c +++ b/src/vendor/cigraph/src/random/rng_mt19937.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/random/rng_pcg32.c b/src/vendor/cigraph/src/random/rng_pcg32.c index 0bc23c78d8d..d8990a11175 100644 --- a/src/vendor/cigraph/src/random/rng_pcg32.c +++ b/src/vendor/cigraph/src/random/rng_pcg32.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/random/rng_pcg64.c b/src/vendor/cigraph/src/random/rng_pcg64.c index c460b4ae4d0..c5040944f10 100644 --- a/src/vendor/cigraph/src/random/rng_pcg64.c +++ b/src/vendor/cigraph/src/random/rng_pcg64.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2022 The igraph development team This program is free software; you can redistribute it and/or modify diff --git a/src/vendor/cigraph/src/random/sampling.c b/src/vendor/cigraph/src/random/sampling.c index 588c74780ab..3d51ab64538 100644 --- a/src/vendor/cigraph/src/random/sampling.c +++ b/src/vendor/cigraph/src/random/sampling.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -45,10 +45,10 @@ * igraph_rng_sample_dirichlet() for other similar samplers. */ igraph_error_t igraph_rng_sample_sphere_surface( - igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_rng_t* rng, igraph_int_t dim, igraph_int_t n, igraph_real_t radius, igraph_bool_t positive, igraph_matrix_t *res ) { - igraph_integer_t i, j; + igraph_int_t i, j; if (dim < 2) { IGRAPH_ERROR("Sphere must be at least two dimensional to sample from " @@ -108,11 +108,11 @@ igraph_error_t igraph_rng_sample_sphere_surface( * igraph_rng_sample_dirichlet() for other similar samplers. */ igraph_error_t igraph_rng_sample_sphere_volume( - igraph_rng_t* rng, igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, + igraph_rng_t* rng, igraph_int_t dim, igraph_int_t n, igraph_real_t radius, igraph_bool_t positive, igraph_matrix_t *res ) { - igraph_integer_t i, j; + igraph_int_t i, j; /* Arguments are checked by the following call */ @@ -151,12 +151,12 @@ igraph_error_t igraph_rng_sample_sphere_volume( * latent vectors. */ igraph_error_t igraph_rng_sample_dirichlet( - igraph_rng_t* rng, igraph_integer_t n, const igraph_vector_t *alpha, + igraph_rng_t* rng, igraph_int_t n, const igraph_vector_t *alpha, igraph_matrix_t *res ) { - igraph_integer_t len = igraph_vector_size(alpha); - igraph_integer_t i, j; + igraph_int_t len = igraph_vector_size(alpha); + igraph_int_t i, j; igraph_real_t sum, num; if (n < 0) { diff --git a/src/vendor/cigraph/src/spatial/beta_skeleton.cpp b/src/vendor/cigraph/src/spatial/beta_skeleton.cpp new file mode 100644 index 00000000000..20baaa87927 --- /dev/null +++ b/src/vendor/cigraph/src/spatial/beta_skeleton.cpp @@ -0,0 +1,816 @@ +/* + igraph library. + Copyright (C) 2025 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 . +*/ + +#include "igraph_spatial.h" + +#include "igraph_constructors.h" +#include "igraph_error.h" +#include "igraph_matrix.h" +#include "igraph_types.h" +#include "igraph_vector.h" + +#include "core/exceptions.h" +#include "spatial/nanoflann_internal.hpp" +#include "spatial/spatial_internal.h" +#include + +#define TOLERANCE (128 * DBL_EPSILON) + +// Some methods to get distances between two vectors, including when one or both are embedded in a matrix. +static inline igraph_real_t ind_ind_sqr_distance(igraph_int_t a, igraph_int_t b, + const igraph_matrix_t *points) { + igraph_real_t distance = 0; + igraph_int_t dims = igraph_matrix_ncol(points); + for (igraph_int_t i = 0; i < dims; i++) { + igraph_real_t temp = MATRIX(*points, a, i) - MATRIX(*points, b, i); + distance += temp * temp; + } + return distance; +} + +static inline igraph_real_t vec_vec_sqr_dist(const igraph_vector_t *a, const igraph_vector_t *b) { + igraph_real_t distance = 0; + igraph_int_t dims = igraph_vector_size(a); + for (igraph_int_t i = 0; i < dims; i++) { + igraph_real_t temp = VECTOR(*a)[i] - VECTOR(*b)[i]; + distance += temp * temp; + } + return distance; +} + +static inline igraph_real_t vec_vec_sqr_dist(const std::vector &a, const std::vector &b) { + igraph_real_t distance = 0; + igraph_int_t dims = a.size(); + for (igraph_int_t i = 0; i < dims; i++) { + igraph_real_t temp = a[i] - b[i]; + distance += temp * temp; + } + return distance; +} + +static inline igraph_real_t vec_ind_sqr_dist(const igraph_vector_t *a, const igraph_int_t b, const igraph_matrix_t *points) { + igraph_real_t distance = 0; + igraph_int_t dims = igraph_matrix_ncol(points); + for (igraph_int_t i = 0; i < dims; i++) { + igraph_real_t temp = VECTOR(*a)[i] - MATRIX(*points, b, i); + distance += temp * temp; + } + return distance; +} +static inline igraph_real_t vec_ind_sqr_dist(const std::vector &a, const igraph_int_t b, const igraph_matrix_t *points) { + igraph_real_t distance = 0; + igraph_int_t dims = igraph_matrix_ncol(points); + for (igraph_int_t i = 0; i < dims; i++) { + igraph_real_t temp = a[i] - MATRIX(*points, b, i); + distance += temp * temp; + } + return distance; +} + +// Adapted from code by Szabolcs at https://github.com/szhorvat/IGraphM +// Used in is_union_empty +class NeighborCounts { + const igraph_real_t radius; // L2 search radius + const igraph_int_t a, b; // edge endpoints; excluded from the count + igraph_bool_t short_circuit; + igraph_int_t found; + +public: + // Boilerplate for nanoflann + using DistanceType = igraph_real_t; + NeighborCounts(igraph_real_t radius, igraph_int_t a, igraph_int_t b, igraph_bool_t short_circuit) + : radius(radius), a(a), b(b), short_circuit(short_circuit) { + init(); + } + + void init() { + clear(); + } + + void clear() { + found = 0; + } + + size_t size() const { + return found; + } + + bool full() const { + return true; + } + + void sort() const {} + + igraph_real_t worstDist() const { + return radius; + } + + // Business logic + // Add the point if it's close enough + bool addPoint(igraph_real_t dist, igraph_int_t index) { + if (dist < radius && index != a && index != b) { + found += 1; + if (short_circuit) { + // Don't continue searching if it only matters if there's one or more. + return false; + } + } + return true; + } +}; + +// Helper result class for listing the points in the intersection of two spheres +// and counting how many are within the lune. +// Used in is_intersection_empty. +// Adapted from code by Szabolcs at https://github.com/szhorvat/IGraphM. +class IntersectionCounts { + const igraph_real_t radius; // Half height of intersection lune + const igraph_real_t beta_radius; // Radius of circles + const igraph_bool_t short_circuit; // Whether to stop after one point has been found + const igraph_int_t a, b; // Edge endpoints; excluded from the count. + const std::vector &a_center, &b_center; // Circle centers. + const igraph_matrix_t *points; // List of points, used to test if points are in range + size_t count; // how many are found. +public: + // Boilerplate for nanoflann + using DistanceType = igraph_real_t; + IntersectionCounts( + igraph_real_t radius_, igraph_real_t beta_radius_, + bool short_circuit_, + igraph_int_t a, igraph_int_t b, const std::vector &a_center, const std::vector &b_center, const igraph_matrix_t *points) + : radius(radius_), beta_radius(beta_radius_), + short_circuit(short_circuit_), + a(a), b(b), + a_center(a_center), b_center(b_center), points(points) { + init(); + } + + void init() { + clear(); + } + + void clear() { + count = 0; + } + + size_t size() const { + return count; + } + + bool full() const { + return true; + } + + void sort() const {} + + igraph_real_t worstDist() const { + return radius; + } + + // Business logic is all contained here. + // Count the point if it is within the radius from both centers, and if it's not one of the endpoints. + bool addPoint(igraph_real_t dist, igraph_int_t index) { + if (dist < radius && index != a && index != b) { + igraph_real_t pd1 = vec_ind_sqr_dist(a_center, index, points); + igraph_real_t pd2 = vec_ind_sqr_dist(b_center, index, points); + if (pd1 < beta_radius && pd2 < beta_radius) { + count++; + // Stop searching if it only matters to have at least one point. + if (short_circuit) { + return false; + } + } + } + return true; + } +}; + +// Shrinks type signatures significantly. +template +using KDTree = nanoflann::KDTreeSingleIndexAdaptor < + nanoflann::L2_Adaptor, + ig_point_adaptor, Dimension, igraph_int_t >; + +// give a known good superset of edges for a given value of beta. +// In the case of beta < 1, that is a complete graph, for +// beta >= 1 it is the delaunay triangulation of the points. +static igraph_error_t beta_skeleton_edge_superset(igraph_vector_int_t *edges, + const igraph_matrix_t *points, + igraph_real_t beta) { + + igraph_int_t num_points = igraph_matrix_nrow(points); + igraph_int_t num_dims = igraph_matrix_ncol(points); + + if (beta >= 1 && num_points > num_dims) { + // Large beta and enough points, subset of delaunay. + IGRAPH_CHECK(igraph_i_delaunay_edges(edges, points)); + } else { + // Small beta, not subset of Delaunay, give complete graph. + // Or Delaunay not calculable due to point count + // TODO: update when/if Delaunay supports small numbers. + igraph_int_t numpoints = igraph_matrix_nrow(points); + for (igraph_int_t a = 0; a < numpoints - 1; a++) { + for (igraph_int_t b = a + 1; b < numpoints; b++) { + IGRAPH_CHECK(igraph_vector_int_push_back(edges, a)); + IGRAPH_CHECK(igraph_vector_int_push_back(edges, b)); + } + } + } + return IGRAPH_SUCCESS; +} + +static inline igraph_real_t calculate_r(igraph_real_t beta) { + if (beta < 1) { + return 0.5 / beta; + } + return 0.5 * beta; +} + + +/* -!- center construction interface -!- + * igraph_vector_t *a_center, b_center : Expects an initialized vector of the + * correct size, will be written to. + * + * igraph_int_t a, b: the indices of the points, + * + * igraph_real_t r: the circles will be constructed with radius r * (distance a-> b) + * + * const igraph_matrix_t *points: point set containing the points a and b + */ + +typedef void CenterConstructor( + std::vector &a_centre, + std::vector &b_centre, + igraph_int_t a, + igraph_int_t b, + igraph_real_t beta, + const igraph_matrix_t *points); + +// construct the centers of the points for lune based beta skeletons with beta +// >= 1. The points lie on the line from a to b, such that the points lie on one +// of the circles. +// formula is a_center = a + (r-1) * (a - b), similar for b_center +static void construct_lune_centers(std::vector &a_centre, + std::vector &b_centre, + igraph_int_t a, + igraph_int_t b, + igraph_real_t r, + const igraph_matrix_t *points) { + igraph_int_t dims = igraph_matrix_ncol(points); + a_centre.resize(dims); + b_centre.resize(dims); + for (igraph_int_t i = 0; i < dims; i++) { + a_centre[i] = MATRIX(*points, a, i) + (r - 1) * (MATRIX(*points, a, i) - MATRIX(*points, b, i)); + b_centre[i] = MATRIX(*points, b, i) + (r - 1) * (MATRIX(*points, b, i) - MATRIX(*points, a, i)); + } +} + +// construct the centers of the circles for beta < 1, or circle based beta +// skeletons. +// Since it relies on a 90-degree rotation around the axis perpendicular +// to the line AB, it is only well-defined in 2d. +static void construct_perp_centers(std::vector &a_centre, + std::vector &b_centre, + igraph_int_t a, + igraph_int_t b, + igraph_real_t r, + const igraph_matrix_t *points) { + igraph_real_t mid[2], perp[2]; + + for (igraph_int_t i = 0; i < 2; i++) { + mid[i] = (MATRIX(*points, a, i) + MATRIX(*points, b, i)) * 0.5; + perp[i] = (MATRIX(*points, a, i) - MATRIX(*points, b, i)) * sqrt(r * r - 0.25); + } + + // Since this is only well-defined for 2d, a manual 90-degree rotation works and is simpler. + // The rotation being x = -y, y = x, 90 degrees counter-clockwise. + igraph_real_t temp = perp[0]; + perp[0] = - perp[1]; + perp[1] = temp; + + a_centre.resize(2); + b_centre.resize(2); + for (igraph_int_t i = 0; i < 2; i++) { + a_centre[i] = mid[i] + perp[i]; + b_centre[i] = mid[i] - perp[i]; + } +} + +/* -!- Filter interface -!- + * igraph_bool_t *result : will be overwritten with the result + * kdTree <-1> &tree : used for nanoflann check, should be + * initialized and filed with points. igraph_int_t a, b : the + * endpoints of the edge being evaluated. igraph_real_t beta : + * parameter for beta-skeletons. const igraph_matrix_t *points: matrix + * containing all the points. + */ +typedef bool FilterFunc( + const KDTree<-1> &tree, + igraph_int_t a, + igraph_int_t b, + const igraph_matrix_t *points, + igraph_real_t beta +); + + +// Test whether the intersection of the two circles as generated +// by center_positions is empty of points except for a and b. +template +static bool is_intersection_empty( + const KDTree<-1> &tree, + igraph_int_t a, + igraph_int_t b, + const igraph_matrix_t *points, + igraph_real_t beta) { + + igraph_real_t r = calculate_r(beta); + igraph_real_t sqr_dist = ind_ind_sqr_distance(a, b, points); + + std::vector midpoint; + igraph_int_t dims = igraph_matrix_ncol(points); + + std::vector a_centre, b_centre; + center_positions(a_centre, b_centre, a, b, r, points); + + midpoint.resize(dims); + for (igraph_int_t i = 0; i < dims; i++) { + midpoint[i] = 0.5 * (a_centre[i] + b_centre[i]); + } + // squared half-height of lune + igraph_real_t lune_height = sqr_dist - vec_vec_sqr_dist(midpoint, a_centre); + igraph_real_t tol = is_closed ? 1 + TOLERANCE : 1 - TOLERANCE; + IntersectionCounts intersections(lune_height * tol * tol, sqr_dist * r * r * tol * tol, true, a, b, a_centre, b_centre, points); + + tree.findNeighbors(intersections, midpoint.data()); + return intersections.size() == 0; +} + +// Test whether the union of the circles given by center_positions +// is empty of other points except for a and b. +template +static bool is_union_empty( + const KDTree<-1> &tree, + igraph_int_t a, + igraph_int_t b, + const igraph_matrix_t *points, + igraph_real_t beta) { + + igraph_real_t sqr_dist = ind_ind_sqr_distance(a, b, points); + igraph_real_t r = calculate_r(beta); + std::vector a_centre, b_centre; + + center_positions(a_centre, b_centre, a, b, r, points); + + NeighborCounts neighbor_search(sqr_dist * r * r * (1 + TOLERANCE), a, b, true); + + tree.findNeighbors(neighbor_search, a_centre.data()); + + if (neighbor_search.size() > 0) { + return false; + } else { + neighbor_search.clear(); + tree.findNeighbors(neighbor_search, b_centre.data()); + return neighbor_search.size() == 0; + } +} + +// Iterate through the edges given, applying the provided filter. +// Currently used with is_intersection_empty and is_union_empty. +// TODO: specialize for multiple dimensions? +template +static igraph_error_t filter_edges(igraph_vector_int_t *edges, const igraph_matrix_t *points, igraph_real_t beta) { + igraph_int_t available_edges = igraph_vector_int_size(edges); + igraph_int_t added_edges = 0; + ig_point_adaptor adaptor(points); + igraph_int_t dim = igraph_matrix_ncol(points); + KDTree<-1> tree(dim, adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10)); + tree.buildIndex(); + for (igraph_int_t i = 0; i * 2 < available_edges; i++) { + if (filter(tree, VECTOR(*edges)[2 * i], VECTOR(*edges)[2 * i + 1], points, beta)) { + VECTOR(*edges)[added_edges * 2] = VECTOR(*edges)[i * 2]; + VECTOR(*edges)[added_edges * 2 + 1] = VECTOR(*edges)[i * 2 + 1]; + added_edges += 1; + } + } + IGRAPH_CHECK(igraph_vector_int_resize(edges, added_edges * 2)); + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_lune_beta_skeleton + * \brief The lune based β-skeleton of a spatial point set. + * + * \experimental + * + * This function constructs the lune-based β-skeleton of an n-dimensional + * spatial point set. + * + * + * A larger β results in a larger region, and a sparser graph. + * Values of β < 1 are only supported in 2D, and are considerably slower. + * + * + * The Gabriel graph is a special case of beta skeleton where β = 1. + * + * + * The Relative Neighborhood graph is a special case of beta skeleton where + * β approaches + * + * \param graph A pointer to the graph that will be created. + * \param points A matrix containing the points that will be used to create the + * graph. Each row is a point, dimensionality is inferred from the column count. + * + * \return Error code. + * + * Time Complexity: Around O(n^floor(d/2) log n), where n is the number of points + * and d is the dimensionality of the point set. + * + */ +igraph_error_t igraph_lune_beta_skeleton(igraph_t *graph, const igraph_matrix_t *points, igraph_real_t beta) { + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; + + igraph_vector_int_t potential_edges; + IGRAPH_VECTOR_INT_INIT_FINALLY(&potential_edges, 0); + + IGRAPH_CHECK(beta_skeleton_edge_superset(&potential_edges, points, beta)); + // determine filter required based on beta. + if (beta >= 1) { + IGRAPH_CHECK((filter_edges>(&potential_edges, points, beta))); + } else { + if (igraph_matrix_ncol(points) != 2) { + IGRAPH_ERROR("Beta skeletons with beta < 1 are only supported in 2 dimensions.", IGRAPH_UNIMPLEMENTED); + } + + IGRAPH_CHECK((filter_edges>(&potential_edges, points, beta))); + } + + IGRAPH_CHECK(igraph_create(graph, &potential_edges, igraph_matrix_nrow(points), false)); + + igraph_vector_int_destroy(&potential_edges); + IGRAPH_FINALLY_CLEAN(1); + + IGRAPH_HANDLE_EXCEPTIONS_END; + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_circle_beta_skeleton + * \brief The circle based β-skeleton of a 2D spatial point set. + * + * \experimental + * + * This function constructs the circle based β-skeleton of a 2D spatial point set. + * + * + * A larger \p beta value results in a larger region, and a sparser graph. + * Values of beta < 1 are considerably slower + * + * \param graph A pointer to the graph that will be created. + * \param points An n-by-2 matrix containing the points that will be used to + * create the graph. Each row is a point. + * \param beta A positive real value used to parameterize the graph. + * \return Error code. + * + * Time Complexity: Around O(n^floor(d/2) log n), where n is the number of points + * and d is the dimensionality of the point set. + * + */ +igraph_error_t igraph_circle_beta_skeleton(igraph_t *graph, const igraph_matrix_t *points, igraph_real_t beta) { + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; + + igraph_vector_int_t potential_edges; + IGRAPH_VECTOR_INT_INIT_FINALLY(&potential_edges, 0); + + if (igraph_matrix_ncol(points) != 2) { + IGRAPH_ERROR("Circle based beta skeletons are only supported in 2 dimensions.", IGRAPH_UNIMPLEMENTED); + } + + IGRAPH_CHECK(beta_skeleton_edge_superset(&potential_edges, points, beta)); + if (beta >= 1) { + IGRAPH_CHECK(filter_edges>(&potential_edges, points, beta)); + } else { + IGRAPH_CHECK((filter_edges>(&potential_edges, points, beta))); + } + + IGRAPH_CHECK(igraph_create(graph, &potential_edges, igraph_matrix_nrow(points), false)); + + igraph_vector_int_destroy(&potential_edges); + IGRAPH_FINALLY_CLEAN(1); + + IGRAPH_HANDLE_EXCEPTIONS_END; + + return IGRAPH_SUCCESS; +} + +// Derived from code by Szabolcs at github.com/szhorvat/IGraphM + +class BetaFinder { + const igraph_real_t max_beta; + const igraph_real_t tol; + const igraph_int_t ai, bi; + const igraph_matrix_t *ps; + const igraph_real_t ab2; + + igraph_real_t smallest_beta; + igraph_real_t max_radius; + +public: + using DistanceType = igraph_real_t; + using IndexType = igraph_int_t; + BetaFinder(igraph_real_t max_beta, igraph_real_t tol, igraph_int_t v1, igraph_int_t v2, const igraph_matrix_t *ps) : + max_beta(max_beta), tol(tol), ai(v1), bi(v2), ps(ps), + ab2(ind_ind_sqr_distance(ai, bi, ps)) { + init(); + } + + void init() { + clear(); + } + + void clear() { + smallest_beta = IGRAPH_INFINITY; + max_radius = luneHalfHeight2(max_beta); + } + + bool full() const { + return true; + } + + size_t size() const { + return 1; + } + + igraph_real_t luneHalfHeight2(igraph_real_t beta) const { + if (beta == 0) { + return 0; + } + return (ab2 / 4) * (2 * beta - 1); + } + + // Calculate the beta at which point index would make the edge a-b disappear. + // If calculated beta is under 1, it would not appear in the gabriel graph, so a 0 is returned + // which is to be interpreted as the edge being missing. + igraph_real_t pointBeta(igraph_int_t index) const { + if (index == ai || index == bi) { + return IGRAPH_INFINITY; + } + + igraph_real_t ap2 = ind_ind_sqr_distance(ai, index, ps); + igraph_real_t bp2 = ind_ind_sqr_distance(bi, index, ps); + + if (ap2 > bp2) { + std::swap(ap2, bp2); + } + + igraph_real_t denom = ab2 + ap2 - bp2; + + if (denom <= 0) { + return IGRAPH_INFINITY; + } + + igraph_real_t beta = 2 * ap2 / denom; + return beta < 1 + tol ? 0 : beta; + } + + bool addPoint(igraph_real_t dist, igraph_int_t index) { + if (dist < max_radius) { + igraph_real_t beta = pointBeta(index); + if (beta < smallest_beta && beta < max_beta) { + smallest_beta = beta; + max_radius = luneHalfHeight2(beta); + } + } + + return true; + } + + igraph_real_t worstDist() const { + return max_radius; + } + + void sort() {} + + igraph_real_t thresholdBeta() const { + return smallest_beta; + } +}; + +/** + * \function igraph_beta_weighted_gabriel_graph + * \brief A Gabriel graph, with edges weighted by the β value at which it disappears. + * + * \experimental + * + * This function generates a Gabriel graph, and for each edge of this graph it + * computes the threshold β value at which the edge ceases to be part of the + * lune-based β-skeleton. For edges that continue to be part of β-skeletons + * for arbitrarily large β, \c IGRAPH_INFINITΥ is returned. + * + * + * The \p max_beta cutoff parameter controls the largest β value to consider + * For edges that persist above this β value, \c IGRAPH_INFINITΥ is returned. + * This parameter serves to improve performance: the smaller this cutoff, + * the faster the computation. Pass \c IGRAPH_INFINITY to use no cutoff. + * + * \param graph A pointer to the graph that will be created. + * \param weights Will contain the edge weights corresponding to the edge + * indices from the graph. + * \param points A matrix containing the points that will be used. + * Each row is a point, dimensionality is inferred from the column count. + * There must be no duplicate points. + * \param max_beta Maximum value of beta to search to, higher values will be + * represented as \c IGRAPH_INFINITY. + * \return Error code. + * + * \sa \ref igraph_lune_beta_skeleton() or \ref igraph_circle_beta_skeleton() + * to generate a graph with a given value of beta; \ref igraph_gabriel_graph() + * to only generate a Gabriel graph, without edge weights. + * + * + * Time Complexity: Around O(n^floor(d/2) log n), where n is the number of points + * and d is the dimensionality of the point set. Though large values of max_beta + * can cause long run times if there are edges that disappear only at large betas. + * + */ +igraph_error_t igraph_beta_weighted_gabriel_graph( + igraph_t *graph, + igraph_vector_t *weights, + const igraph_matrix_t *points, + igraph_real_t max_beta) { + + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; + + igraph_vector_int_t edges; + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + + igraph_int_t dim = igraph_matrix_ncol(points); + igraph_int_t point_count = igraph_matrix_nrow(points); + ig_point_adaptor adaptor(points); + + IGRAPH_CHECK(igraph_i_delaunay_edges(&edges, points)); + igraph_int_t edge_count = igraph_vector_int_size(&edges) / 2; + + IGRAPH_CHECK(igraph_vector_resize(weights, edge_count)); + + KDTree<-1> tree(dim, adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10)); + tree.buildIndex(); + + igraph_vector_t midpoint; + IGRAPH_VECTOR_INIT_FINALLY(&midpoint, dim); + + for (igraph_int_t i = 0; i < edge_count; i++) { + BetaFinder finder(max_beta, TOLERANCE, VECTOR(edges)[2 * i], VECTOR(edges)[2 * i + 1], points); + + for (igraph_int_t axis = 0; axis < dim; axis++) { + VECTOR(midpoint)[axis] = 0.5 * ( + MATRIX(*points, VECTOR(edges)[2 * i], axis) + + MATRIX(*points, VECTOR(edges)[2 * i + 1], axis) + ); + } + + tree.findNeighbors(finder, VECTOR(midpoint)); + VECTOR(*weights)[i] = finder.thresholdBeta(); + } + + // Filter out edges with beta == 0. + igraph_int_t added_edges = 0; + for (igraph_int_t i = 0; i < edge_count; i++) { + if (VECTOR(*weights)[i] != 0) { + VECTOR(*weights)[added_edges] = VECTOR(*weights)[i]; + VECTOR(edges)[added_edges * 2] = VECTOR(edges)[i * 2]; + VECTOR(edges)[added_edges * 2 + 1] = VECTOR(edges)[i * 2 + 1]; + added_edges += 1; + } + } + + IGRAPH_CHECK(igraph_vector_int_resize(&edges, added_edges * 2)); + IGRAPH_CHECK(igraph_vector_resize(weights, added_edges)); + + IGRAPH_CHECK(igraph_create(graph, &edges, point_count, false)); + + igraph_vector_int_destroy(&edges); + igraph_vector_destroy(&midpoint); + IGRAPH_FINALLY_CLEAN(2); + + IGRAPH_HANDLE_EXCEPTIONS_END; + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_gabriel_graph + * \brief The Gabriel graph of a point set. + * + * \experimental + * + * In the Gabriel graph of a point set, two points A and B are connected if + * there is no other point C within the closed ball of which AB is a diameter. + * The Gabriel graph is connected, and in 2D it is planar. igraph supports + * computing the Gabriel graph of arbitrary dimensional point sets. + * + * + * The Gabriel graph is a special case of lune-based and circle-based β-skeletons + * with β=1. + * + * \param graph A pointer to the graph to be created. + * \param points The point set that will be used. Each row is a point, + * dimensionality is inferred from column count. + * + * \return Error Code. + * \sa The Gabriel graph is a special case of + * \ref igraph_lune_beta_skeleton() and \ref igraph_circle_beta_skeleton() + * where β = 1. + * + * Time Complexity: Around O(n^floor(d/2) log n), where n is the number of points + * and d is the dimensionality of the point set. + * + */ +igraph_error_t igraph_gabriel_graph(igraph_t *graph, const igraph_matrix_t *points) { + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; + + igraph_vector_int_t potential_edges; + IGRAPH_VECTOR_INT_INIT_FINALLY(&potential_edges, 0); + + IGRAPH_CHECK(beta_skeleton_edge_superset(&potential_edges, points, 1)); + + IGRAPH_CHECK((filter_edges>(&potential_edges, points, 1))); + + IGRAPH_CHECK(igraph_create(graph, &potential_edges, igraph_matrix_nrow(points), false)); + + igraph_vector_int_destroy(&potential_edges); + IGRAPH_FINALLY_CLEAN(1); + + IGRAPH_HANDLE_EXCEPTIONS_END; + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_relative_neighborhood_graph + * \brief The relative neighborhood graph of a point set. + * + * \experimental + * + * The relative neighborhood graph is constructed from a set of points in space. + * Two points A and B are connected if and only if there is no other point C so + * that AC < AB and BC < AB, with the inequalities being strict. + * + * + * Most authors define the relative neighborhood graph to coincide with a + * lune-based β-skeleton for β = 2. In igraph, there is a subtle + * difference: the β = 2 skeleton connects points A and B when there + * is no point C so that AC <= AB and BC <= AB. Therefore, three points + * forming an equilateral triangle are connected in the relative neighborhood graph, + * but disconnected in the β = 2 skeleton. + * + * + * With these definitions, the relative neighborhood graph is always connected, + * while the β = 2 skeleton is always triangle-free. + * + * \param graph A pointer to the graph that will be created. + * \param points The point set that will be used, each row is a point. + * Dimensionality is inferred from the column number. + * \return Error code. + * + * \sa \ref igraph_lune_beta_skeleton() to compute the lune based β-skeleton + * for β = 2 or other β values. + * + * Time Complexity: Around O(n^floor(d/2) log n), where n is the number of points + * and d is the dimensionality of the point set. + * + */ +igraph_error_t igraph_relative_neighborhood_graph(igraph_t *graph, const igraph_matrix_t *points) { + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; + + igraph_vector_int_t potential_edges; + IGRAPH_VECTOR_INT_INIT_FINALLY(&potential_edges, 0); + + IGRAPH_CHECK(beta_skeleton_edge_superset(&potential_edges, points, 1)); + + IGRAPH_CHECK((filter_edges>(&potential_edges, points, 2))); + + IGRAPH_CHECK(igraph_create(graph, &potential_edges, igraph_matrix_nrow(points), false)); + + igraph_vector_int_destroy(&potential_edges); + IGRAPH_FINALLY_CLEAN(1); + + IGRAPH_HANDLE_EXCEPTIONS_END; + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/spatial/convex_hull.c b/src/vendor/cigraph/src/spatial/convex_hull.c new file mode 100644 index 00000000000..f815c3d7b67 --- /dev/null +++ b/src/vendor/cigraph/src/spatial/convex_hull.c @@ -0,0 +1,188 @@ +/* + igraph library. + Copyright (C) 2025 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 . +*/ + +#include "igraph_spatial.h" + +/** + * \function igraph_convex_hull_2d + * \brief Determines the convex hull of a given set of points in the 2D plane. + * + * + * The convex hull is determined by the Graham scan algorithm. + * See the following reference for details: + * + * + * Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford + * Stein. Introduction to Algorithms, Second Edition. MIT Press and + * McGraw-Hill, 2001. ISBN 0262032937. Pages 949-955 of section 33.3: + * Finding the convex hull. + * + * \param data vector containing the coordinates. The length of the + * vector must be even, since it contains X-Y coordinate pairs. + * \param resverts the vector containing the result, e.g. the vector of + * vertex indices used as the corners of the convex hull. Supply + * \c NULL here if you are only interested in the coordinates of + * the convex hull corners. + * \param rescoords the matrix containing the coordinates of the selected + * corner vertices. Supply \c NULL here if you are only interested in + * the vertex indices. + * \return Error code: + * \c IGRAPH_ENOMEM: not enough memory + * + * Time complexity: O(n log(n)) where n is the number of vertices. + */ +igraph_error_t igraph_convex_hull_2d( + const igraph_matrix_t *data, + igraph_vector_int_t *resverts, + igraph_matrix_t *rescoords) +{ + igraph_int_t no_of_nodes; + igraph_int_t i, pivot_idx = 0, last_idx, before_last_idx, next_idx, j; + igraph_vector_t angles; + igraph_vector_int_t order, stack; + igraph_real_t px, py, cp; + + no_of_nodes = igraph_matrix_nrow(data); + if (igraph_matrix_ncol(data) != 2) { + IGRAPH_ERROR("Only two-dimensional point sets are supports, matrix must have two columns.", IGRAPH_EINVAL); + } + if (no_of_nodes == 0) { + if (resverts) { + igraph_vector_int_clear(resverts); + } + if (rescoords) { + IGRAPH_CHECK(igraph_matrix_resize(rescoords, 0, 2)); + } + /**************************** this is an exit here *********/ + return IGRAPH_SUCCESS; + } + + IGRAPH_VECTOR_INIT_FINALLY(&angles, no_of_nodes); + IGRAPH_VECTOR_INT_INIT_FINALLY(&stack, 0); + + /* Search for the pivot vertex */ + for (i = 1; i < no_of_nodes; i++) { + if (MATRIX(*data, i, 1) < MATRIX(*data, pivot_idx, 1)) { + pivot_idx = i; + } else if (MATRIX(*data, i, 1) == MATRIX(*data, pivot_idx, 1) && + MATRIX(*data, i, 0) < MATRIX(*data, pivot_idx, 0)) { + pivot_idx = i; + } + } + px = MATRIX(*data, pivot_idx, 0); + py = MATRIX(*data, pivot_idx, 1); + + /* Create angle array */ + for (i = 0; i < no_of_nodes; i++) { + if (i == pivot_idx) { + /* We can't calculate the angle of the pivot point with itself, + * so we use 10 here. This way, after sorting the angle vector, + * the pivot point will always be the first one, since the range + * of atan2 is -3.14..3.14 */ + VECTOR(angles)[i] = 10; + } else { + VECTOR(angles)[i] = atan2(MATRIX(*data, i, 1) - py, MATRIX(*data, i, 0) - px); + } + } + + /* Sort points by angles */ + IGRAPH_VECTOR_INT_INIT_FINALLY(&order, no_of_nodes); + IGRAPH_CHECK(igraph_vector_sort_ind(&angles, &order, IGRAPH_ASCENDING)); + + /* Check if two points have the same angle. If so, keep only the point that + * is farthest from the pivot */ + j = 0; + last_idx = VECTOR(order)[0]; + pivot_idx = VECTOR(order)[no_of_nodes - 1]; + for (i = 1; i < no_of_nodes; i++) { + next_idx = VECTOR(order)[i]; + if (VECTOR(angles)[last_idx] == VECTOR(angles)[next_idx]) { + /* Keep the vertex that is farther from the pivot, drop the one that is + * closer */ + px = pow(MATRIX(*data, last_idx, 0) - MATRIX(*data, pivot_idx, 0), 2) + + pow(MATRIX(*data, last_idx, 1) - MATRIX(*data, pivot_idx, 1), 2); + py = pow(MATRIX(*data, next_idx, 0) - MATRIX(*data, pivot_idx, 0), 2) + + pow(MATRIX(*data, next_idx, 1) - MATRIX(*data, pivot_idx, 1), 2); + if (px > py) { + VECTOR(order)[i] = -1; + } else { + VECTOR(order)[j] = -1; + last_idx = next_idx; + j = i; + } + } else { + last_idx = next_idx; + j = i; + } + } + + j = 0; + last_idx = -1; + before_last_idx = -1; + while (!igraph_vector_int_empty(&order)) { + next_idx = igraph_vector_int_tail(&order); + if (next_idx < 0) { + /* This vertex should be skipped; was excluded in an earlier step */ + igraph_vector_int_pop_back(&order); + continue; + } + /* Determine whether we are at a left or right turn */ + if (j < 2) { + /* Pretend that we are turning into the right direction if we have less + * than two items in the stack */ + cp = -1; + } else { + cp = (MATRIX(*data, last_idx, 0) - MATRIX(*data, before_last_idx, 0)) * + (MATRIX(*data, next_idx, 1) - MATRIX(*data, before_last_idx, 1)) - + (MATRIX(*data, next_idx, 0) - MATRIX(*data, before_last_idx, 0)) * + (MATRIX(*data, last_idx, 1) - MATRIX(*data, before_last_idx, 1)); + } + + if (cp < 0) { + /* We are turning into the right direction */ + igraph_vector_int_pop_back(&order); + IGRAPH_CHECK(igraph_vector_int_push_back(&stack, next_idx)); + before_last_idx = last_idx; + last_idx = next_idx; + j++; + } else { + /* No, skip back and try again in the next iteration */ + igraph_vector_int_pop_back(&stack); + j--; + last_idx = before_last_idx; + before_last_idx = (j >= 2) ? VECTOR(stack)[j - 2] : -1; + } + } + + /* Create result vector */ + if (resverts != 0) { + igraph_vector_int_clear(resverts); + IGRAPH_CHECK(igraph_vector_int_append(resverts, &stack)); + } + if (rescoords != 0) { + igraph_matrix_select_rows(data, rescoords, &stack); + } + + /* Free everything */ + igraph_vector_int_destroy(&order); + igraph_vector_int_destroy(&stack); + igraph_vector_destroy(&angles); + IGRAPH_FINALLY_CLEAN(3); + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/spatial/delaunay.c b/src/vendor/cigraph/src/spatial/delaunay.c new file mode 100644 index 00000000000..0668aa3dd41 --- /dev/null +++ b/src/vendor/cigraph/src/spatial/delaunay.c @@ -0,0 +1,280 @@ +/* + igraph library. + Copyright (C) 2025 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 . +*/ + +#include "igraph_spatial.h" + +#include "igraph_bitset.h" +#include "igraph_constructors.h" +#include "igraph_error.h" +#include "igraph_matrix.h" +#include "igraph_memory.h" +#include "igraph_types.h" +#include "igraph_vector.h" + +#include "internal/utils.h" +#include "spatial/spatial_internal.h" + +#include "qhull/libqhull_r/libqhull_r.h" + +/** + * Raises an error if a spatial point set is invalid. + * The coordinate matrix must have at least one column and must not + * contain NaN or infinities. + * + * \param points Matrix, each row is a spatial point. + * \return Error code. + */ +igraph_error_t igraph_i_check_spatial_points(const igraph_matrix_t *points) { + const igraph_int_t dim = igraph_matrix_ncol(points); + const igraph_int_t n = igraph_matrix_nrow(points); + + /* Special case: we allow zero columns when there are zero rows, i.e. no points. + * Some languages cannot represent size-zero matrices and length-zero point + * lists may translate as a 0-by-0 matrix to igraph. */ + if (dim == 0 && n > 0) { + IGRAPH_ERROR("Point sets must not be zero-dimensional.", IGRAPH_EINVAL); + } + + if (!igraph_vector_is_all_finite(&points->data)) { + IGRAPH_ERROR("Coordinates must not be NaN or infinite.", IGRAPH_EINVAL); + } + + return IGRAPH_SUCCESS; +} + +// Append an undirected clique of the indices in destination to source. +// Assumes that source is an initialized vector. +static igraph_error_t add_clique(igraph_vector_int_t *destination, const igraph_vector_int_t *source) { + igraph_int_t num_points = igraph_vector_int_size(source); + for (igraph_int_t a = 0; a < num_points - 1; a++) { + for (igraph_int_t b = a + 1; b < num_points; b++) { + IGRAPH_CHECK(igraph_vector_int_push_back(destination, VECTOR(*source)[a])); + IGRAPH_CHECK(igraph_vector_int_push_back(destination, VECTOR(*source)[b])); + } + } + return IGRAPH_SUCCESS; +} + + +// Helper that can go on the finally stack to free qhT Qhull data structure in case of an error. +static void destroy_qhull(qhT *qh) { + int curlong, totlong; + qh->NOerrexit = True; /* no more setjmp */ + qh_freeqhull(qh, !qh_ALL); + qh_memfreeshort(qh, &curlong, &totlong); +} + + +/* In the 1D case we simply connect points in sorted order. + * This function assumes that there is at least one point. */ +static igraph_error_t delaunay_edges_1d(igraph_vector_int_t *edges, const igraph_matrix_t *points) { + const igraph_int_t numpoints = igraph_matrix_nrow(points); + const igraph_vector_t coords = igraph_vector_view(&MATRIX(*points, 0, 0), numpoints); + igraph_vector_int_t order; + + IGRAPH_ASSERT(igraph_matrix_ncol(points) == 1); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&order, numpoints); + + IGRAPH_CHECK(igraph_vector_sort_ind(&coords, &order, IGRAPH_ASCENDING)); + + IGRAPH_CHECK(igraph_vector_int_resize(edges, 2*(numpoints-1))); + + for (igraph_int_t i=0; i < numpoints-1; i++) { + igraph_int_t from = VECTOR(order)[i]; + igraph_int_t to = VECTOR(order)[i+1]; + VECTOR(*edges)[2*i] = from; + VECTOR(*edges)[2*i + 1] = to; + if (VECTOR(coords)[from] == VECTOR(coords)[to]) { + IGRAPH_ERROR("Duplicate points for Delaunay triangulation.", IGRAPH_EINVAL); + } + } + + igraph_vector_int_destroy(&order); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + +igraph_error_t igraph_i_delaunay_edges(igraph_vector_int_t *edges, const igraph_matrix_t *points) { + const igraph_int_t numpoints = igraph_matrix_nrow(points) ; + const igraph_int_t dim = igraph_matrix_ncol(points); + int exitcode; + qhT qh_qh; /* Qhull's data structure. First argument of most Qhull calls. */ + qhT *qh = &qh_qh; /* Convenience pointer. */ + + /* Error checks */ + + /* Validate point set. */ + IGRAPH_CHECK(igraph_i_check_spatial_points(points)); + + /* No edges for one or zero points. */ + if (numpoints <= 1) { + igraph_vector_int_clear(edges); + return IGRAPH_SUCCESS; + } + + /* Qhull does not support the 1D case. */ + if (dim == 1) { + return delaunay_edges_1d(edges, points); + } + + if (dim >= numpoints) { + IGRAPH_ERRORF("Not enough points to create simplex, need at least %" IGRAPH_PRId ".", IGRAPH_EINVAL, dim); + } + + /* Prevent overflow in igraph_int_t -> int conversions below. + * Note that Qhull will likely already fail for a much smaller point count. */ + if (numpoints > INT_MAX) { + IGRAPH_ERROR("Too many points for Qhull.", IGRAPH_EOVERFLOW); + } + + /* Prepare point set in row-major format for Qhull */ + + coordT *qhull_points = IGRAPH_CALLOC(dim*numpoints, igraph_real_t); + IGRAPH_CHECK_OOM(qhull_points, "Insufficient memory for constructing Delaunay graph."); + IGRAPH_FINALLY(igraph_free, qhull_points); + igraph_matrix_copy_to(points, qhull_points, IGRAPH_ROW_MAJOR); + + /* Call Qhull. + * + * This is mainly based on qdelaunay/qdelaun_r.c and qh_new_qhull() in user_r.c. + * + * Note that output routines in userprintf_r.c are patched to not print + * when passing NULL as a file pointer, which is what we do here. */ + + /* Check for compatible library. Not technically necessary, as igraph + * vendors Qhull due to the need to override output routines. Would + * become necessary if linking to an external Qhull. */ + QHULL_LIB_CHECK + + /* Initializes qh, sets qh->qhull_command. */ + qh_init_A(qh, NULL, NULL, NULL, 0, NULL); + IGRAPH_FINALLY(destroy_qhull, qh); + + exitcode = setjmp(qh->errexit); + if (!exitcode) { + qh->NOerrexit = False; + + /* qh_option() does not change the operation of Qhull. It simply records options to be + * output with error messages. Here we manually keep it in sync with the settings below. */ + qh_option(qh, "delaunay Qz-infinity-point Q3-no-merge-vertices", NULL, NULL); + + qh->PROJECTdelaunay = True; // project points to parabola to calculate delaunay triangulation + qh->DELAUNAY = True; // 'd' + qh->ATinfinity = True; // 'Qz', required for cocircular points + qh->MERGEvertices = False; // 'Q3', do not merge identical vertices + + qh_initflags(qh, qh->qhull_command); + qh_init_B(qh, qhull_points, numpoints, dim, /*ismalloc=*/ False); // read points and project them to parabola. + qh_qhull(qh); // do the triangulation + qh_triangulate(qh); // this guarantees that everything is simplicial + + igraph_vector_int_t simplex; + IGRAPH_VECTOR_INT_INIT_FINALLY(&simplex, dim + 1); // a simplex in n dimensions has n+1 incident vertices. + + facetT *facet; // required for FORALLfacets + vertexT *vertex, **vertexp; // required for FOREACHvertex_ + + FORALLfacets { + if (!facet->upperdelaunay) { + igraph_int_t curr_vert = 0; + FOREACHvertex_(facet->vertices) { + VECTOR(simplex)[curr_vert++] = qh_pointid(qh, vertex->point); + } + IGRAPH_CHECK(add_clique(edges, &simplex)); + } + } + igraph_i_simplify_edge_list(edges, true, true, false); + + /* Check if there are any points/vertices that do not appear in the edge list. + * This happens when there are duplicate points, as Qhull ignores one of them. + * We raise an error when there are duplicates. */ + igraph_int_t edges_size = igraph_vector_int_size(edges); + igraph_bitset_t in_edge_list; + + IGRAPH_BITSET_INIT_FINALLY(&in_edge_list, numpoints); + for (igraph_int_t i = 0; i < edges_size; i++) { + IGRAPH_BIT_SET(in_edge_list, VECTOR(*edges)[i]); + } + if (igraph_bitset_is_any_zero(&in_edge_list)) { + IGRAPH_ERROR("Duplicate points for Delaunay triangulation.", IGRAPH_EINVAL); + } + + igraph_bitset_destroy(&in_edge_list); + igraph_vector_int_destroy(&simplex); + destroy_qhull(qh); + igraph_free(qhull_points); + IGRAPH_FINALLY_CLEAN(4); + } else { + switch (qh->last_errcode) { + /* TODO: More specific error descriptions for common Qhull errors. */ + default: + /* TODO: Report Qhull error text? */ + IGRAPH_ERRORF("Error while computing Delaunay triangulation, Qhull error code %d.", IGRAPH_EINVAL, qh->last_errcode); + } + } + + return IGRAPH_SUCCESS; +} + + +/** + * \function igraph_delaunay_graph + * \brief Computes the Delaunay graph of a spatial point set. + * + * \experimental + * + * This function constructs the graph corresponding to the Delaunay triangulation + * of an n-dimensional spatial point set. + * + * + * The current implementation uses Qhull. + * + * + * Reference: + * + * + * Barber, C. Bradford, David P. Dobkin, and Hannu Huhdanpaa. + * The Quickhull Algorithm for Convex Hulls. + * ACM Transactions on Mathematical Software 22, no. 4 (1996): 469–83. + * https://doi.org/10.1145/235815.235821. + * + * \param graph A pointer to the graph that will be created. + * \param points A matrix containing the points that will be used to create the graph. + * Each row is a point, dimensionality is inferred from the column count. + * There must not be duplicate points. + * \return Error code. + * + * Time complexity: According to Theorem 3.2 in the Qhull paper, + * O(n log n) for d <= 3 and O(n^floor(d/2) / floor(d/2)!) where + * n is the number of points and d is the dimensionality of the point set. + */ +igraph_error_t igraph_delaunay_graph(igraph_t *graph, const igraph_matrix_t *points) { + igraph_vector_int_t edges; + const igraph_int_t numpoints = igraph_matrix_nrow(points); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_i_delaunay_edges(&edges, points)); + IGRAPH_CHECK(igraph_create(graph, &edges, numpoints, IGRAPH_UNDIRECTED)); + + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/spatial/edge_lengths.c b/src/vendor/cigraph/src/spatial/edge_lengths.c new file mode 100644 index 00000000000..7b5f19ef8db --- /dev/null +++ b/src/vendor/cigraph/src/spatial/edge_lengths.c @@ -0,0 +1,119 @@ +/* + igraph library. + Copyright (C) 2025 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 . +*/ + +#include "igraph_spatial.h" + +#include "igraph_datatype.h" +#include "igraph_error.h" +#include "igraph_interface.h" +#include "igraph_matrix.h" +#include "igraph_vector.h" + +#include /* sqrt, fabs */ + +/** + * \function igraph_spatial_edge_lengths + * \brief Edge lengths based on spatial vertex coordinates. + * + * \experimental + * + * The length of each edge is computed based on spatial coordinates. The length + * can be employed by several igraph functions, such as \ref igraph_voronoi(), + * \ref igraph_betweenness(), \ref igraph_closeness() and others. + * + * \param graph The graph whose edge lengths are to be computed. + * \param lengths An initialized vector. Length will be stored here, in the + * order of edge IDs. It will be resized as needed. + * \param points A matrix of vertex coordinates. Each row contains the + * coordinates of the corresponding vertex, in the order of vertex IDs. + * Arbitrary dimensional point sets are supported. + * \param metric The distance metric to use. See \ref igraph_metric_t for + * valid values. + * \return Error code. + * + * \sa \ref igraph_nearest_neighbor_graph() computes a k nearest neighbor graph + * and \ref igraph_delaunay_graph() computes a Delaunay graph based on a set of + * spatial points. + * + * Time complexity: O(|E| d) where |E| is the number of edges and d is the + * dimensionality of the point set. + */ +igraph_error_t igraph_spatial_edge_lengths( + const igraph_t *graph, + igraph_vector_t *lengths, + const igraph_matrix_t *points, + igraph_metric_t metric) { + + const igraph_int_t vcount = igraph_vcount(graph); + const igraph_int_t ecount = igraph_ecount(graph); + const igraph_int_t dim = igraph_matrix_ncol(points); + + /* Validate input. + * + * We opt not to check for Inf/NaN, as these can safely propagate to the result. */ + + if (igraph_matrix_nrow(points) != vcount) { + IGRAPH_ERROR("Number of vertex coordinates must match the vertex count.", IGRAPH_EINVAL); + } + + /* Special case: we allow zero columns when there are zero rows, i.e. no points. + * Some languages cannot represent size-zero matrices and length-zero point + * lists may translate as a 0-by-0 matrix to igraph. */ + if (dim == 0 && vcount > 0) { + IGRAPH_ERROR("Vertex coordinates must not be zero-dimensional.", IGRAPH_EINVAL); + } + + IGRAPH_CHECK(igraph_vector_resize(lengths, ecount)); + + /* Validate distance metric. The switch statement is helpful because + * compilers tend to show warnings when some enum values are missing. */ + switch (metric) { + case IGRAPH_METRIC_EUCLIDEAN: + case IGRAPH_METRIC_MANHATTAN: + break; + default: + IGRAPH_ERROR("Invalid distance metric.", IGRAPH_EINVAL); + } + + /* Compute edge lengths. */ + + for (igraph_int_t eid=0; eid < ecount; eid++) { + const igraph_int_t from = IGRAPH_FROM(graph, eid); + const igraph_int_t to = IGRAPH_TO(graph, eid); + igraph_real_t length = 0.0; + + for (igraph_int_t i=0; i < dim; i++) { + igraph_real_t diff = MATRIX(*points, from, i) - MATRIX(*points, to, i); + + switch (metric) { + case IGRAPH_METRIC_EUCLIDEAN: + length += diff*diff; break; + case IGRAPH_METRIC_MANHATTAN: + length += fabs(diff); break; + } + } + + if (metric == IGRAPH_METRIC_EUCLIDEAN) { + length = sqrt(length); + } + + VECTOR(*lengths)[eid] = length; + } + + return IGRAPH_SUCCESS; +} diff --git a/src/vendor/cigraph/src/spatial/nanoflann_internal.hpp b/src/vendor/cigraph/src/spatial/nanoflann_internal.hpp new file mode 100644 index 00000000000..93f62e0a977 --- /dev/null +++ b/src/vendor/cigraph/src/spatial/nanoflann_internal.hpp @@ -0,0 +1,121 @@ +#ifndef SPATIAL_NANOFLANN_INTERNAL_H +#define SPATIAL_NANOFLANN_INTERNAL_H + +#include "igraph_decls.h" +#include "igraph_types.h" + +#include "igraph_matrix.h" + +#include "nanoflann/nanoflann.hpp" + +#include + + +class ig_point_adaptor { + const igraph_matrix_t *points; + const igraph_int_t point_count; + +public: + explicit ig_point_adaptor(const igraph_matrix_t *points) : + points(points), point_count(igraph_matrix_nrow(points)) { } + + size_t kdtree_get_point_count() const { + return point_count; + } + + igraph_real_t kdtree_get_pt(const size_t idx, const size_t dim) const { + return MATRIX(*points, idx, dim); + } + template + bool kdtree_get_bbox(BoundingBox &bb) const { + IGRAPH_UNUSED(bb); + return false; // indicates that it should use default + } +}; + + +class GraphBuildingResultSet { + igraph_int_t added_count = 0; + const igraph_real_t max_distance; + const igraph_int_t max_neighbors; + +public: + igraph_int_t current_vertex = 0; + std::vector neighbors; + std::vector distances; + + using DistanceType = igraph_real_t; + using IndexType = igraph_int_t; + + GraphBuildingResultSet(const igraph_int_t max_neighbors, const igraph_real_t max_distance) : + max_distance(max_distance), + max_neighbors(max_neighbors), + neighbors(0), + distances(0) { } + + bool addPoint(const igraph_real_t distance, const igraph_int_t index) { + igraph_int_t i; + + if (index == current_vertex) { + return true; + } + + for (i = added_count; i > 0; i--) { + // TODO: Stabilize result in case of multiple points at exactly the same distance? + // See NANOFLANN_FIRST_MATCH in RKNNResultSet in nanoflann.hpp for reference. + if (distances[i - 1] > distance) { + registerPoint(i, neighbors[i - 1], distances[i - 1]); + } else { + break; + } + } + if (i < max_neighbors) { + registerPoint(i, index, distance); + } + if (added_count != max_neighbors) { + added_count++; + } + return true; + } + + void registerPoint(igraph_int_t where, igraph_int_t index, igraph_real_t distance) { + if (neighbors.size() == where) { + neighbors.push_back(index); + distances.push_back(distance); + } else { + neighbors[where] = index; + distances[where] = distance; + } + + } + + void reset(igraph_int_t current_vertex_) { + added_count = 0; + current_vertex = current_vertex_; + } + + // Never called. Necessary to conform to the interface. + void sort() { } + + igraph_int_t size() const { + return added_count; + } + + bool full() const { + return added_count == max_neighbors; + } + + bool empty() const { + return added_count == 0; + } + + igraph_real_t worstDist() const { + if (added_count < max_neighbors || added_count == 0) { + return max_distance; + } + return distances[added_count - 1]; + } +}; + + +#endif // SPATIAL_NANOFLANN_INTERNAL_H diff --git a/src/vendor/cigraph/src/spatial/nearest_neighbor.cpp b/src/vendor/cigraph/src/spatial/nearest_neighbor.cpp index 6fb5f12fc19..4650cd05f3c 100644 --- a/src/vendor/cigraph/src/spatial/nearest_neighbor.cpp +++ b/src/vendor/cigraph/src/spatial/nearest_neighbor.cpp @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2025 The igraph development team This program is free software; you can redistribute it and/or modify @@ -26,127 +26,30 @@ #include "igraph_types.h" #include "igraph_vector.h" +#include "spatial/nanoflann_internal.hpp" + #include "core/exceptions.h" #include "core/interruption.h" +#include "spatial/spatial_internal.h" #include "nanoflann/nanoflann.hpp" #include -class ig_point_adaptor { - const igraph_matrix_t *points; - const igraph_integer_t point_count; - -public: - explicit ig_point_adaptor(const igraph_matrix_t *points) : - points(points), point_count(igraph_matrix_nrow(points)) { } - - size_t kdtree_get_point_count() const { - return point_count; - } - - igraph_real_t kdtree_get_pt(const size_t idx, const size_t dim) const { - return MATRIX(*points, idx, dim); - } - - template - bool kdtree_get_bbox(BoundingBox &bb) const { - IGRAPH_UNUSED(bb); - return false; // indicates that it should use default - } -}; - - -class GraphBuildingResultSet { - igraph_integer_t current_vertex = 0; - igraph_integer_t added_count = 0; - const igraph_real_t max_distance; - const igraph_integer_t max_neighbors; - -public: - std::vector neighbors; - std::vector distances; - - using DistanceType = igraph_real_t; - using IndexType = igraph_integer_t; - - GraphBuildingResultSet(const igraph_integer_t max_neighbors, const igraph_real_t max_distance) : - max_distance(max_distance), - max_neighbors(max_neighbors), - neighbors(max_neighbors), - distances(max_neighbors) { } - - bool addPoint(const igraph_real_t distance, const igraph_integer_t index) { - igraph_integer_t i; - - if (index == current_vertex) { - return true; - } - - for (i = added_count; i > 0; i--) { - // TODO: Stabilize result in case of multiple points at exactly the same distance? - // See NANOFLANN_FIRST_MATCH in RKNNResultSet in nanoflann.hpp for reference. - if (distances[i-1] > distance) { - if (i < max_neighbors) { - distances[i] = distances[i-1]; - neighbors[i] = neighbors[i-1]; - } - } else { - break; - } - } - if (i < max_neighbors) { - neighbors[i] = index; - distances[i] = distance; - } - if (added_count != max_neighbors) { - added_count++; - } - return true; - } - - void reset(igraph_integer_t current_vertex_) { - added_count = 0; - current_vertex = current_vertex_; - } - - // Never called. Necessary to conform to the interface. - void sort() { } - - igraph_integer_t size() const { - return added_count; - } - - bool full() const { - return added_count == max_neighbors; - } - - bool empty() const { - return added_count == 0; - } - - igraph_real_t worstDist() const { - if (added_count < max_neighbors || added_count == 0) { - return max_distance; - } - return distances[added_count-1]; - } -}; - -template +template static igraph_error_t neighbor_helper( igraph_t *graph, const igraph_matrix_t *points, - igraph_integer_t k, + igraph_int_t k, igraph_real_t cutoff, - igraph_integer_t dimension, + igraph_int_t dimension, igraph_bool_t directed) { - const igraph_integer_t point_count = igraph_matrix_nrow(points); + const igraph_int_t point_count = igraph_matrix_nrow(points); ig_point_adaptor adaptor(points); int iter = 0; - using kdTree = nanoflann::KDTreeSingleIndexAdaptor; + using kdTree = nanoflann::KDTreeSingleIndexAdaptor; kdTree tree(dimension, adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10)); tree.buildIndex(); @@ -154,16 +57,16 @@ static igraph_error_t neighbor_helper( igraph_vector_t current_point; IGRAPH_VECTOR_INIT_FINALLY(¤t_point, dimension); - igraph_integer_t neighbor_count = k >= 0 ? k : point_count; + igraph_int_t neighbor_count = k >= 0 ? k : point_count; GraphBuildingResultSet results(neighbor_count, cutoff); - std::vector edges; - for (igraph_integer_t i = 0; i < point_count; i++) { + std::vector edges; + for (igraph_int_t i = 0; i < point_count; i++) { results.reset(i); IGRAPH_CHECK(igraph_matrix_get_row(points, ¤t_point, i)); tree.findNeighbors(results, VECTOR(current_point), nanoflann::SearchParameters(0, false)); - for (igraph_integer_t j = 0; j < results.size(); j++) { + for (igraph_int_t j = 0; j < results.size(); j++) { edges.push_back(i); edges.push_back(results.neighbors[j]); } @@ -179,8 +82,7 @@ static igraph_error_t neighbor_helper( IGRAPH_ERROR("Too many edges.", IGRAPH_EOVERFLOW); } - igraph_vector_int_t edge_view; - igraph_vector_int_view(&edge_view, edges.data(), edges.size()); + const igraph_vector_int_t edge_view = igraph_vector_int_view(edges.data(), edges.size()); IGRAPH_CHECK(igraph_create(graph, &edge_view, point_count, true)); if (! directed) { @@ -195,9 +97,9 @@ template static igraph_error_t dimension_dispatcher( igraph_t *graph, const igraph_matrix_t *points, - igraph_integer_t k, + igraph_int_t k, igraph_real_t cutoff, - igraph_integer_t dimension, + igraph_int_t dimension, igraph_bool_t directed) { switch (dimension) { @@ -219,6 +121,8 @@ static igraph_error_t dimension_dispatcher( * \function igraph_nearest_neighbor_graph * \brief Computes the nearest neighbor graph for a spatial point set. * + * \experimental + * * This function constructs the \p k nearest neighbor graph of a given point * set. Each point is connected to at most \p k spatial neighbors within a * radius of \p cutoff. @@ -240,11 +144,11 @@ static igraph_error_t dimension_dispatcher( igraph_error_t igraph_nearest_neighbor_graph(igraph_t *graph, const igraph_matrix_t *points, igraph_metric_t metric, - igraph_integer_t k, + igraph_int_t k, igraph_real_t cutoff, igraph_bool_t directed) { - const igraph_integer_t dimension = igraph_matrix_ncol(points); + const igraph_int_t dimension = igraph_matrix_ncol(points); // Negative cutoff values signify that no cutoff should be used. cutoff = cutoff >= 0 ? cutoff : IGRAPH_INFINITY; @@ -256,6 +160,8 @@ igraph_error_t igraph_nearest_neighbor_graph(igraph_t *graph, return igraph_empty(graph, 0, directed); } + IGRAPH_CHECK(igraph_i_check_spatial_points(points)); + IGRAPH_HANDLE_EXCEPTIONS_BEGIN; switch (metric) { diff --git a/src/vendor/cigraph/src/spatial/spatial_internal.h b/src/vendor/cigraph/src/spatial/spatial_internal.h new file mode 100644 index 00000000000..eb42367b98c --- /dev/null +++ b/src/vendor/cigraph/src/spatial/spatial_internal.h @@ -0,0 +1,34 @@ +/* + igraph library. + Copyright (C) 2025 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 . +*/ + +#ifndef IGRAPH_SPATIAL_INTERNAL_H +#define IGRAPH_SPATIAL_INTERNAL_H + +#include "igraph_decls.h" +#include "igraph_error.h" +#include "igraph_vector.h" +#include "igraph_matrix.h" + +IGRAPH_BEGIN_C_DECLS + +igraph_error_t igraph_i_delaunay_edges(igraph_vector_int_t *edges, const igraph_matrix_t *points); +igraph_error_t igraph_i_check_spatial_points(const igraph_matrix_t *points); + +IGRAPH_END_C_DECLS + +#endif /* IGRAPH_SPATIAL_INTERNAL_H */ diff --git a/src/vendor/cigraph/src/version.c b/src/vendor/cigraph/src/version.c index f0bf43917df..7df72226392 100644 --- a/src/vendor/cigraph/src/version.c +++ b/src/vendor/cigraph/src/version.c @@ -1,6 +1,6 @@ /* - IGraph library. - Copyright (C) 2008-2022 The igraph development team + igraph library. + Copyright (C) 2008-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 @@ -26,15 +26,17 @@ static const char *igraph_version_string = IGRAPH_VERSION; * \function igraph_version * \brief The version of the igraph C library. * - * \param version_string Pointer to a string pointer. If not null, it - * is set to the igraph version string, e.g. "0.9.11" or "0.10.0". This - * string must not be modified or deallocated. - * \param major If not a null pointer, then it is set to the major - * igraph version. E.g. for version "0.9.11" this is 0. - * \param minor If not a null pointer, then it is set to the minor - * igraph version. E.g. for version "0.9.11" this is 11. - * \param subminor If not a null pointer, then it is set to the - * subminor igraph version. E.g. for version "0.9.11" this is 11. + * \param version_string Pointer to a string pointer. If not \c NULL, it + * is set to the igraph version string, e.g. "0.10.13", "1.2.0", or + * "0.10.13-14-g997f59ad7". It consists of three dot-separated numerical + * parts and potentially of a dash-separated suffix, used in prerelease + * versions. This string must not be modified or deallocated. + * \param major If not a \c NULL pointer, then it is set to the major + * igraph version. E.g. for version "0.10.13" this is 0. + * \param minor If not a \c NULL pointer, then it is set to the minor + * igraph version. E.g. for version "0.10.13" this is 10. + * \param patch If not a \c NULL pointer, then it is set to the + * subminor igraph version. E.g. for version "0.10.13" this is 13. * * \example examples/simple/igraph_version.c */ @@ -42,11 +44,11 @@ static const char *igraph_version_string = IGRAPH_VERSION; void igraph_version(const char **version_string, int *major, int *minor, - int *subminor) { + int *patch) { int i1, i2, i3; int *p1 = major ? major : &i1; int *p2 = minor ? minor : &i2; - int *p3 = subminor ? subminor : &i3; + int *p3 = patch ? patch : &i3; if (version_string) { *version_string = igraph_version_string; diff --git a/src/vendor/cigraph/vendor/CMakeLists.txt b/src/vendor/cigraph/vendor/CMakeLists.txt index f22769136c1..3aa40eaffc8 100644 --- a/src/vendor/cigraph/vendor/CMakeLists.txt +++ b/src/vendor/cigraph/vendor/CMakeLists.txt @@ -6,3 +6,4 @@ add_subdirectory(lapack) add_subdirectory(mini-gmp) add_subdirectory(pcg) add_subdirectory(plfit) +add_subdirectory(qhull) diff --git a/src/vendor/cigraph/vendor/cs/cs.h b/src/vendor/cigraph/vendor/cs/cs.h index a505ca55aa6..f6ce945b8f8 100644 --- a/src/vendor/cigraph/vendor/cs/cs.h +++ b/src/vendor/cigraph/vendor/cs/cs.h @@ -3,7 +3,7 @@ * here: * * - Dependency on SuiteSparse_long was removed - * - CXSparse is configured to use igraph_integer_t as cs_long_t + * - CXSparse is configured to use igraph_int_t as cs_long_t * - CXSparse function prefix is set to cs_igraph instead of cs_igraph * - Unneeded CXSparse function variants are removed * @@ -61,7 +61,7 @@ extern "C" { #define CS_COPYRIGHT "Copyright (c) Timothy A. Davis, 2006-2016" #define CXSPARSE -#define cs_long_t igraph_integer_t +#define cs_long_t igraph_int_t #define cs_long_t_id "%" IGRAPH_PRId #define cs_long_t_max IGRAPH_INTEGER_MAX diff --git a/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp index 2ce1f3d102c..8ae9ad61b2a 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp +++ b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.cpp @@ -225,6 +225,7 @@ void BiasedMapEquation::consolidateModules(std::vector& modules) currentNumModules = numModules; } +#if 0 // =================================================== // Debug // =================================================== @@ -234,5 +235,6 @@ void BiasedMapEquation::printDebug() const std::cout << "BiasedMapEquation\n"; Base::printDebug(); } +#endif } // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h index 5663ba53109..6f043e8125c 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h +++ b/src/vendor/cigraph/vendor/infomap/src/core/BiasedMapEquation.h @@ -92,11 +92,13 @@ class BiasedMapEquation : private MapEquation<> { void consolidateModules(std::vector& modules) override; +#if 0 // =================================================== // Debug // =================================================== void printDebug() const override; +#endif private: // =================================================== diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h b/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h index 01b87e06bec..4c8a13293e7 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapBase.h @@ -469,11 +469,14 @@ class InfomapBase : public InfomapConfig { std::string writeClu(const std::string& filename = "", bool states = false, int moduleIndexLevel = 1) { return infomap::writeClu(*this, m_network, filename, states, moduleIndexLevel); } private: + +#if 0 // =================================================== // Debug: * // =================================================== void printDebug() const { return m_optimizer->printDebug(); } +#endif // =================================================== // Members diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h index e534992556e..29c683fc200 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizer.h @@ -89,11 +89,13 @@ class InfomapOptimizer : public InfomapOptimizerBase { bool restoreConsolidatedOptimizationPointIfNoImprovement(bool forceRestore = false) override; +#if 0 // =================================================== // Debug: * // =================================================== void printDebug() override { m_objective.printDebug(); } +#endif // =================================================== // Protected members diff --git a/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h index 7d89262bdb9..75ba8ff8b42 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h +++ b/src/vendor/cigraph/vendor/infomap/src/core/InfomapOptimizerBase.h @@ -94,11 +94,13 @@ class InfomapOptimizerBase { virtual bool restoreConsolidatedOptimizationPointIfNoImprovement(bool forceRestore = false) = 0; +#if 0 // =================================================== // Debug: * // =================================================== virtual void printDebug() = 0; +#endif private: diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h index 64860f6244e..b9913f87394 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h +++ b/src/vendor/cigraph/vendor/infomap/src/core/MapEquation.h @@ -136,12 +136,14 @@ class MapEquation { // Debug // =================================================== +#if 0 virtual void printDebug() const { std::cout << "(enterFlow_log_enterFlow: " << enterFlow_log_enterFlow << ", " << "enter_log_enter: " << enter_log_enter << ", " << "exitNetworkFlow_log_exitNetworkFlow: " << exitNetworkFlow_log_exitNetworkFlow << ") "; } +#endif protected: // =================================================== diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp index cc19e770af5..1c25d4b99c3 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp +++ b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.cpp @@ -436,6 +436,7 @@ void MemMapEquation::consolidateModules(std::vector& modules) } } +#if 0 // =================================================== // Debug // =================================================== @@ -445,5 +446,6 @@ void MemMapEquation::printDebug() const std::cout << "MemMapEquation::m_numPhysicalNodes: " << m_numPhysicalNodes << "\n"; Base::printDebug(); } +#endif } // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h index b7a8d969407..e4d7410d242 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h +++ b/src/vendor/cigraph/vendor/infomap/src/core/MemMapEquation.h @@ -89,11 +89,13 @@ class MemMapEquation : private MapEquation { void consolidateModules(std::vector& modules) override; +#if 0 // =================================================== // Debug // =================================================== void printDebug() const override; +#endif private: // =================================================== diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp index e19d931dcef..48685fb601f 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp +++ b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.cpp @@ -256,6 +256,7 @@ void MetaMapEquation::consolidateModules(std::vector& modules) } } +#if 0 // =================================================== // Debug // =================================================== @@ -265,5 +266,6 @@ void MetaMapEquation::printDebug() const std::cout << "MetaMapEquation\n"; Base::printDebug(); } +#endif } // namespace infomap diff --git a/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h index 79b3bd4b104..29b780c6114 100644 --- a/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h +++ b/src/vendor/cigraph/vendor/infomap/src/core/MetaMapEquation.h @@ -94,11 +94,13 @@ class MetaMapEquation : private MapEquation<> { void consolidateModules(std::vector& modules) override; +#if 0 // =================================================== // Debug // =================================================== void printDebug() const override; +#endif private: // =================================================== diff --git a/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp index 5ddfd764423..54d06248afc 100644 --- a/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp +++ b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.cpp @@ -10,6 +10,8 @@ #include "ProgramInterface.h" #include "../utils/Log.h" +#include "igraph_error.h" + #include #include #include @@ -45,6 +47,9 @@ ProgramInterface::ProgramInterface(std::string name, std::string shortDescriptio addOptionArgument(m_printJsonParameters, "print-json-parameters", "Print Infomap parameters in JSON.", "About").setHidden(true); } +/* Modification for igraph: Disable functions that call forbidden + * functions such as exit(). */ +#if 0 void ProgramInterface::exitWithUsage(bool showAdvanced) const { Log() << "Name:\n"; @@ -125,9 +130,16 @@ void ProgramInterface::exitWithVersionInformation() const Log() << "See www.mapequation.org for terms of use.\n"; std::exit(0); } +#endif void ProgramInterface::exitWithError(const std::string& message) const { + /* Modification for igraph: This function must never be called + * when using Infomap through igraph. The function is disabled + * to eliminate forbidden references to exit() and std::cerr. */ + IGRAPH_FATALF("Infomap called exitWithError() with message '%s'.", + message.c_str()); +#if 0 Log() << m_programName << " version " << m_programVersion; #ifdef _OPENMP Log() << " compiled with OpenMP"; @@ -142,6 +154,7 @@ void ProgramInterface::exitWithError(const std::string& message) const Log() << " [options]"; Log() << ". Run with option '-h' for more information.\n"; std::exit(1); +#endif } std::string toJson(const std::string& key, const std::string& value) @@ -178,6 +191,9 @@ std::string toJson(const Option& opt) << " }"; } +/* Modification for igraph: Disable functions that call forbidden + * functions such as exit(). */ +#if 0 void ProgramInterface::exitWithJsonParameters() const { Log() << "{\n \"parameters\": [\n"; @@ -197,6 +213,7 @@ void ProgramInterface::exitWithJsonParameters() const std::exit(0); } +#endif void ProgramInterface::parseArgs(const std::string& args) { @@ -298,12 +315,16 @@ void ProgramInterface::parseArgs(const std::string& args) } } } + /* Modification for igraph: Disable calls to functions that + * needed to be removed because they referenced exit(). */ +#if 0 if (m_displayHelp > 0) exitWithUsage(m_displayHelp > 1); if (m_displayVersion) exitWithVersionInformation(); if (m_printJsonParameters) exitWithJsonParameters(); +#endif } } catch (std::exception& e) { exitWithError(e.what()); diff --git a/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h index d0e352d8ca3..21841cbd9e3 100644 --- a/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h +++ b/src/vendor/cigraph/vendor/infomap/src/io/ProgramInterface.h @@ -392,10 +392,16 @@ class ProgramInterface { unsigned int numRequiredArguments() const { return m_nonOptionArguments.size() - m_numOptionalNonOptionArguments; } private: +/* Modification for igraph: Disable functions that call forbidden + * functions such as exit(). */ +#if 0 void exitWithUsage(bool showAdvanced) const; void exitWithVersionInformation() const; +#endif void exitWithError(const std::string& message) const; +#if 0 void exitWithJsonParameters() const; +#endif std::deque> m_optionArguments; std::deque> m_nonOptionArguments; diff --git a/src/vendor/cigraph/vendor/infomap/src/utils/Log.h b/src/vendor/cigraph/vendor/infomap/src/utils/Log.h index 6a236544635..412dcd516e1 100644 --- a/src/vendor/cigraph/vendor/infomap/src/utils/Log.h +++ b/src/vendor/cigraph/vendor/infomap/src/utils/Log.h @@ -39,15 +39,19 @@ class Log { template Log& operator<<(const T& data) { +#if 0 if (m_visible) m_ostream << data; +#endif return *this; } Log& operator<<(ostreamFuncPtr f) { +#if 0 if (m_visible) m_ostream << f; +#endif return *this; } @@ -69,18 +73,21 @@ class Log { static bool isSilent() { return s_silent; } - static std::streamsize precision() { return std::cout.precision(); } + /* precision() is patched in igraph to avoid references to std::cout */ + static std::streamsize precision() { return 6; } - static std::streamsize precision(std::streamsize precision) + static std::streamsize precision(std::streamsize) { - return std::cout.precision(precision); + return precision(); } private: unsigned int m_level; unsigned int m_maxLevel; bool m_visible; +#if 0 std::ostream& m_ostream = std::cout; +#endif static unsigned int s_verboseLevel; static bool s_silent; diff --git a/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c b/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c index 418b823481a..e0b126f0a61 100644 --- a/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c +++ b/src/vendor/cigraph/vendor/lapack/fortran_intrinsics.c @@ -1,5 +1,5 @@ /* - IGraph library. + igraph library. Copyright (C) 2011-12 Gabor Csardi 334 Harvard street, Cambridge MA, 02139 USA diff --git a/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.c b/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.c index df99e070ba8..4540fd93c03 100644 --- a/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.c +++ b/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.c @@ -2710,6 +2710,66 @@ mpn_gcd_11 (mp_limb_t u, mp_limb_t v) return u << shift; } +mp_size_t +mpn_gcd (mp_ptr rp, mp_ptr up, mp_size_t un, mp_ptr vp, mp_size_t vn) +{ + assert (un >= vn); + assert (vn > 0); + assert (!GMP_MPN_OVERLAP_P (up, un, vp, vn)); + assert (vp[vn-1] > 0); + assert ((up[0] | vp[0]) & 1); + + if (un > vn) + mpn_div_qr (NULL, up, un, vp, vn); + + un = mpn_normalized_size (up, vn); + if (un == 0) + { + mpn_copyi (rp, vp, vn); + return vn; + } + + if (!(vp[0] & 1)) + MPN_PTR_SWAP (up, un, vp, vn); + + while (un > 1 || vn > 1) + { + int shift; + assert (vp[0] & 1); + + while (up[0] == 0) + { + up++; + un--; + } + gmp_ctz (shift, up[0]); + if (shift > 0) + { + gmp_assert_nocarry (mpn_rshift(up, up, un, shift)); + un -= (up[un-1] == 0); + } + + if (un < vn) + MPN_PTR_SWAP (up, un, vp, vn); + else if (un == vn) + { + int c = mpn_cmp (up, vp, un); + if (c == 0) + { + mpn_copyi (rp, up, un); + return un; + } + else if (c < 0) + MP_PTR_SWAP (up, vp); + } + + gmp_assert_nocarry (mpn_sub (up, up, un, vp, vn)); + un = mpn_normalized_size (up, un); + } + rp[0] = mpn_gcd_11 (up[0], vp[0]); + return 1; +} + unsigned long mpz_gcd_ui (mpz_t g, const mpz_t u, unsigned long v) { @@ -2769,42 +2829,11 @@ mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v) if (tu->_mp_size < tv->_mp_size) mpz_swap (tu, tv); - mpz_tdiv_r (tu, tu, tv); - if (tu->_mp_size == 0) - { - mpz_swap (g, tv); - } - else - for (;;) - { - int c; - - mpz_make_odd (tu); - c = mpz_cmp (tu, tv); - if (c == 0) - { - mpz_swap (g, tu); - break; - } - if (c < 0) - mpz_swap (tu, tv); + tu->_mp_size = mpn_gcd (tu->_mp_d, tu->_mp_d, tu->_mp_size, tv->_mp_d, tv->_mp_size); + mpz_mul_2exp (g, tu, gz); - if (tv->_mp_size == 1) - { - mp_limb_t *gp; - - mpz_tdiv_r (tu, tu, tv); - gp = MPZ_REALLOC (g, 1); /* gp = mpz_limbs_modify (g, 1); */ - *gp = mpn_gcd_11 (tu->_mp_d[0], tv->_mp_d[0]); - - g->_mp_size = *gp != 0; /* mpz_limbs_finish (g, 1); */ - break; - } - mpz_sub (tu, tu, tv); - } mpz_clear (tu); mpz_clear (tv); - mpz_mul_2exp (g, g, gz); } void @@ -2813,6 +2842,7 @@ mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v) mpz_t tu, tv, s0, s1, t0, t1; mp_bitcnt_t uz, vz, gz; mp_bitcnt_t power; + int cmp; if (u->_mp_size == 0) { @@ -2964,12 +2994,21 @@ mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v) mpz_tdiv_q_2exp (t0, t0, 1); } - /* Arrange so that |s| < |u| / 2g */ + /* Choose small cofactors (they should generally satify + + |s| < |u| / 2g and |t| < |v| / 2g, + + with some documented exceptions). Always choose the smallest s, + if there are two choices for s with same absolute value, choose + the one with smallest corresponding t (this asymmetric condition + is needed to prefer s = 0, |t| = 1 when g = |a| = |b|). */ mpz_add (s1, s0, s1); - if (mpz_cmpabs (s0, s1) > 0) + mpz_sub (t1, t0, t1); + cmp = mpz_cmpabs (s0, s1); + if (cmp > 0 || (cmp == 0 && mpz_cmpabs (t0, t1) > 0)) { mpz_swap (s0, s1); - mpz_sub (t0, t0, t1); + mpz_swap (t0, t1); } if (u->_mp_size < 0) mpz_neg (s0, s0); @@ -4480,6 +4519,11 @@ mpz_import (mpz_t r, size_t count, int order, size_t size, int endian, assert (order == 1 || order == -1); assert (endian >= -1 && endian <= 1); + if (count == 0) + { + r->_mp_size = 0; + return; + } if (endian == 0) endian = gmp_detect_endian (); diff --git a/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.h b/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.h index 59c24cf5111..f28cb360ce1 100644 --- a/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.h +++ b/src/vendor/cigraph/vendor/mini-gmp/mini-gmp.h @@ -105,6 +105,7 @@ void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); int mpn_perfect_square_p (mp_srcptr, mp_size_t); mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); +mp_size_t mpn_gcd (mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t); mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); diff --git a/src/vendor/cigraph/vendor/qhull/CHANGES.md b/src/vendor/cigraph/vendor/qhull/CHANGES.md new file mode 100644 index 00000000000..917243989d0 --- /dev/null +++ b/src/vendor/cigraph/vendor/qhull/CHANGES.md @@ -0,0 +1,12 @@ +Modifying from https://github.com/qhull/qhull on commit d1c2fc0caa5f644f3a0f220290d4a868c68ed4f6 + +Changed `userprintf_r.c` to not print when passed a null pointer as file handle. + +Changed `usermem_r.c` to not reference `exit()`. Even though this `exit()` is never called, it is necessary to keep igraph free of any references to it to satisfy CRAN requirements and comply with Debian guidelines. + +Changed the following settings in `user_r.h`: + + - `#define qh_KEEPstatistics 0`, do not incude statistics gathering code + - `#define qh_NOtrace`, do not include tracing code + +Patched with https://github.com/qhull/qhull/pull/165. diff --git a/src/vendor/cigraph/vendor/qhull/CMakeLists.txt b/src/vendor/cigraph/vendor/qhull/CMakeLists.txt new file mode 100644 index 00000000000..2e7cf5eb718 --- /dev/null +++ b/src/vendor/cigraph/vendor/qhull/CMakeLists.txt @@ -0,0 +1,48 @@ +# Declare the files needed to compile our vendored plfit copy +add_library( + qhull_vendored + OBJECT + EXCLUDE_FROM_ALL + libqhull_r/accessors_r.c + libqhull_r/geom_r.c + libqhull_r/geom2_r.c + libqhull_r/global_r.c + libqhull_r/io_r.c + libqhull_r/libqhull_r.c + libqhull_r/mem_r.c + libqhull_r/merge_r.c + libqhull_r/poly_r.c + libqhull_r/poly2_r.c + libqhull_r/qset_r.c + libqhull_r/random_r.c + libqhull_r/rboxlib_r.c + libqhull_r/stat_r.c + libqhull_r/user_r.c + libqhull_r/usermem_r.c + libqhull_r/userprintf_r.c + libqhull_r/userprintf_rbox_r.c +) + +target_include_directories( + qhull_vendored + PRIVATE + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include + #PUBLIC + #${CMAKE_CURRENT_SOURCE_DIR} +) + +if (BUILD_SHARED_LIBS) + set_property(TARGET qhull_vendored PROPERTY POSITION_INDEPENDENT_CODE ON) +endif() + +# Since these are included as object files, they should call the +# function as is (without visibility specification) +target_compile_definitions(qhull_vendored PRIVATE IGRAPH_STATIC) + +use_all_warnings(qhull_vendored) + +target_compile_options( + qhull_vendored PRIVATE + $<$:-Wno-unused-variable> +) \ No newline at end of file diff --git a/src/vendor/cigraph/vendor/qhull/COPYING.txt b/src/vendor/cigraph/vendor/qhull/COPYING.txt new file mode 100644 index 00000000000..122a00a4fa9 --- /dev/null +++ b/src/vendor/cigraph/vendor/qhull/COPYING.txt @@ -0,0 +1,39 @@ + Qhull, Copyright (c) 1993-2020 + + C.B. Barber + Arlington, MA + + and + + The National Science and Technology Research Center for + Computation and Visualization of Geometric Structures + (The Geometry Center) + University of Minnesota + + email: qhull@qhull.org + +This software includes Qhull from C.B. Barber and The Geometry Center. +Files derived from Qhull 1.0 are copyrighted by the Geometry Center. The +remaining files are copyrighted by C.B. Barber. Qhull is free software +and may be obtained via http from www.qhull.org. It may be freely copied, +modified, and redistributed under the following conditions: + +1. All copyright notices must remain intact in all files. + +2. A copy of this text file must be distributed along with any copies + of Qhull that you redistribute; this includes copies that you have + modified, or copies of programs or other software products that + include Qhull. + +3. If you modify Qhull, you must include a notice giving the + name of the person performing the modification, the date of + modification, and the reason for such modification. + +4. When distributing modified versions of Qhull, or other software + products that include Qhull, you must provide notice that the original + source code may be obtained as noted above. + +5. There is no warranty or other guarantee of fitness for Qhull, it is + provided solely "as is". Bug reports or fixes may be sent to + qhull_bug@qhull.org; the authors may or may not act on them as + they desire. diff --git a/src/vendor/cigraph/vendor/qhull/README.txt b/src/vendor/cigraph/vendor/qhull/README.txt new file mode 100644 index 00000000000..baf1b80aa90 --- /dev/null +++ b/src/vendor/cigraph/vendor/qhull/README.txt @@ -0,0 +1,720 @@ +Name + + qhull, rbox 2020.2 2020/08/31 (8.0.2) + +Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection + + Documentation: + html/index.htm + + + Available from: + + + (git@github.com:qhull/qhull.git) + + News and a paper: + + + + Version 1 (simplicial only): + + +Purpose + + Qhull is a general dimension convex hull program that reads a set + of points from stdin, and outputs the smallest convex set that contains + the points to stdout. It also generates Delaunay triangulations, Voronoi + diagrams, furthest-site Voronoi diagrams, and halfspace intersections + about a point. + + Rbox is a useful tool in generating input for Qhull; it generates + hypercubes, diamonds, cones, circles, simplices, spirals, + lattices, and random points. + + Qhull produces graphical output for Geomview. This helps with + understanding the output. + +Environment requirements + + Qhull and rbox should run on all 32-bit and 64-bit computers. Use + an ANSI C or C++ compiler to compile the program. The software is + self-contained. It comes with examples and test scripts. + + Qhull's C++ interface uses the STL. The C++ test program uses QTestLib + from the Qt Framework. + + Qhull is copyrighted software. Please read COPYING.txt and REGISTER.txt + before using or distributing Qhull. + +To cite Qhull, please use + + Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull + algorithm for convex hulls," ACM Trans. on Mathematical Software, + 22(4):469-483, Dec 1996, http://www.qhull.org. + +To modify Qhull, particularly the C++ interface + + Qhull is on GitHub + (http://github.com/qhull/qhull/wiki, git@github.com:qhull/qhull.git) + + For internal documentation, see html/qh-code.htm + +To install Qhull + + Qhull is precompiled for Windows 32-bit, otherwise it needs compilation. + + Qhull includes Makefiles for gcc and other targets, CMakeLists.txt for CMake, + .sln/.vcproj/.vcxproj files for Microsoft Visual Studio, and .pro files + for Qt Creator. It compiles under Windows with mingw. + () + + Install and build instructions follow. + + See the end of this document for a list of distributed files. + +------------------ +Index + +Installing Qhull on Windows 10, 8, 7 (32- or 64-bit), Windows XP, and Windows NT +Installing Qhull on Unix with gcc +Installing Qhull with CMake 2.6 or later +Installing Qhull with Qt +Working with Qhull's C++ interface +Calling Qhull from C programs +Compiling Qhull with Microsoft Visual C++ +Compiling Qhull with Qt Creator +Compiling Qhull with mingw/gcc on Windows +Compiling Qhull with cygwin on Windows +Compiling from Makfile without gcc +Compiling on other machines and compilers +Distributed files +Authors + +------------------ +Installing Qhull on Windows 10, 8, 7 (32- or 64-bit), Windows XP, and Windows NT + + The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe, + qhalf.exe, qvoronoi.exe, testqset.exe, user_eg*.exe, documentation files, + and source files. Qhull.exe and user-eg3.exe are compiled with the reentrant + library while the other executables use the non-reentrant library. + + To install Qhull: + - Unzip the files into a directory (e.g., named 'qhull') + - Click on QHULL-GO or open a command window into Qhull's bin directory. + - Test with 'rbox D4 | qhull' + + To uninstall Qhull + - Delete the qhull directory + + To learn about Qhull: + - Execute 'qconvex' for a synopsis and examples. + Or 'qconvex --help' or 'qconvex -?' + - Execute 'rbox 10 | qconvex' to compute the convex hull of 10 random points. + - Execute 'rbox 10 | qconvex i TO file' to write results to 'file'. + - Browse the documentation: qhull\html\index.htm + - If an error occurs, Windows sends the error to stdout instead of stderr. + Use 'TO xxx' to send normal output to xxx + + To improve the command window + - Double-click the window bar to increase the size of the window + - Right-click the window bar + - Select Properties + - Check QuickEdit Mode + Select text with right-click or Enter + Paste text with right-click + - Change Font to Lucinda Console + - Change Layout to Screen Buffer Height 999, Window Size Height 55 + - Change Colors to Screen Background White, Screen Text Black + - Click OK + - Select 'Modify shortcut that started this window', then OK + + If you regularly use qhull on a Windows host, install a bash shell such as + https://gitforwindows.org/ # based on MSYS2 + https://github.com/git-for-windows/git/wiki + http://www.msys2.org/ + https://github.com/msys2/msys2/wiki + [mar'19] Git for Windows v2.21 requires 'qhull --help' + Install in C:\Git\... # Not 'Program Files\...' otherwise './configure && make' fails + www.cygwin.com + www.mingw.org/wiki/msys # for Windows XP + Road Bash (www.qhull.org/bash) # based on MSYS + +------------------ +Installing Qhull on Unix with gcc + + To build Qhull, static libraries, shared library, and C++ interface + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - make + - export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH + - make test + + 'make install' installs Qhull at '/usr/local/'. It installs pkg-config files + at '/usr/local/lib/pkgconfig'. Change the install directory with DESTDIR and PREFIX. + + To build 32-bit Qhull on a 64-bit host (uses 33% less memory in 4-d) + - make new M32=-m32 + + To build 32-bit Qhull without -fpic (may be faster, but shared library may fail) + - make new M32=-m32 FPIC= + + The Makefiles may be edited for other compilers. + If 'testqset' exits with an error, qhull is broken + + A simple Makefile for Qhull is in src/libqhull and src/libqhull_r. + To build the Qhull executables and libqhullstatic + - Extract Qhull from qhull...tgz or qhull...zip + - cd src/libqhull_r # cd src/libqhull + - make + + +------------------ +Installing Qhull with CMake 2.6 or later + + See CMakeLists.txt for examples and further build instructions + + To build Qhull, static libraries, shared library, and C++ interface + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - cd build + - cmake --help # List build generators + - cmake -G "" .. # e.g., for MINGW-w64 -- cmake -G "MSYS Makefiles" .. + - cmake .. + - make + - ctest + - make install # If MSYS or UNIX, default CMAKE_INSTALL_PREFIX is '/usr/local' + # otherwise if WINDOWS, installs to ../bin, ../include, and ../lib + - make uninstall # Delete the files in install_manifest.txt + + The ".." is important. It refers to the parent directory (i.e., qhull/) + + CMake installs lib/pkgconfig/qhull*.pc for use with pkg-config + + If CMAKE_INSTALL_PREFIX is C:/Program Files/qhull, you may need to give 'Users' "full control" + to qhull's sub-directories: bin, doc, include, lib, and man (folder > Properties > Security > Edit > Users). + + On Windows, CMake's 64-bit generators have a "Win64" tag. Qhull's data structures + are substantial larger as 64-bit code than as 32-bit code. This may slow down Qhull. + + If cmake fails with "No CMAKE_C_COMPILER could be found" + - cmake was not able to find the build environment specified by -G "..." + + If cmake's gcc smoketest fails after a Windows update + - Reinstall MINGW-w64 and delete build/CMakeCache.txt. A Windows update can break gcc process creation for cc1. + +------------------ +Installing Qhull with Qt + + To build Qhull, including its C++ test program (qhulltest) + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - Load src/qhull-all.pro into QtCreator + - Configure the project to use a Shadow build at the same level as 'src', 'bin', and 'lib' + If, instead, the shadow build is a subdirectory of 'build', Qt Creator will install Qhull in 'build/bin' and 'build/lib' + - Build + + - Build qhulltest with a C++11 or later compiler + - qhulltest depends on shared libraries QtCore.a and QtTest.a. They may need to be copied + into the bin directory. On Windows, copy Qt5Core.dll and Qt5Test.dll, e.g., /qt/5.11.2/msvc2017_64/bin + - If qhulltest fails with exit status 127 and no error message, + check for missing Q5Core.dll and Qt5Test.dll + +------------------ +Working with Qhull's C++ interface + + See html/qh-code.htm#cpp for calling Qhull from C++ programs + + Class and method documentation is limited + + See html/qh-code.htm#reentrant for converting from Qhull-2012 + + Examples of using the C++ interface + user_eg3_r.cpp + qhulltest/*_test.cpp + + Qhull's C++ interface is likely to change. Stay current with GitHub. + + To clone Qhull's next branch from http://github.com/qhull/qhull/wiki + git init + git clone git@github.com:qhull/qhull.git + cd qhull + git checkout next + ... + git pull origin next + + Compile qhullcpp and libqhullstatic_r with the same compiler. Both libraries + use the C routines setjmp() and longjmp() for error handling. They must + be compiled with the same compiler. + + Qhull provides pkg-config support with build/qhull.pc.in and lib/pkgconfig/qhull*.pc + With back-ticks, you can compile your C++ program with the Qhull libraries: + g++ `pkg-config --cflags --libs qhullcpp qhullstatic_r` -o my_app my_app.cpp + or + g++ `pkg-config --cflags --libs qhullcpp qhull_r` -o my_app my_app.cpp + + qhullcpp must be linked before qhull_r, otherwise the linker reports + an error -- "QhullUser ... multiple definition of `qh_fprintf'" + +------------------ +Calling Qhull from C programs + + See html/qh-code.htm#library for calling Qhull from C programs + + Qhull provides pkg-config support with build/qhull.pc.in and lib/pkgconfig/qhull*.pc + With back-ticks, you can compile your C program with the Qhull library + gcc `pkg-config --cflags --libs qhull_r` -o my_app my_app.c + + See html/qh-code.htm#reentrant for converting from Qhull-2012 + + Warning: You will need to understand Qhull's data structures and read the + code. Most users will find it easier to call Qhull as an external command. + + The reentrant 'C' code (src/libqhull_r), passes a pointer to qhT + to most Qhull routines. This allows multiple instances of Qhull to run + at the same time. It simplifies the C++ interface. + + The non-reentrant 'C' code (src/libqhull) looks unusual. It refers to + Qhull's global data structure, qhT, through a 'qh' macro (e.g., 'qh ferr'). + This allows the same code to use static memory or heap memory. + If qh_QHpointer is defined, qh_qh is a pointer to an allocated qhT; + otherwise qh_qh is a global static data structure of type qhT. + +------------------ +Compiling Qhull with Microsoft Visual C++ + + To compile 32-bit Qhull with Microsoft Visual C++ 2010 and later + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - Load solution build/qhull-32.sln + - Right-click 'Retarget solution' from toolset v110 to your Platform Toolset + File > Save All + - Build target 'Win32' + - Project qhulltest requires Qt for DevStudio (http://www.qt.io) + Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/5.2.0/5.2.0/msvc2012) + If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified' + - Copy Qt shared libraries, QtCore.dll and QtTest.dll, into the bin directory + + To compile 64-bit Qhull with Microsoft Visual C++ 2010 and later + - 64-bit Qhull has larger data structures due to 64-bit pointers. This may slow down Qhull. + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - Load solution build/qhull-64.sln + - Right-click 'Retarget solution' from toolset v110 to your Platform Toolset + File > Save All + - Build target 'x64' + - If build as 32-bit fails, use solution build/qhull-32.sln + - Project qhulltest requires Qt for DevStudio (http://www.qt.io) + Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/5.2.0/5.2.0/msvc2012_64) + If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified' + + If error -- MSB8020: The build tools for Visual Studio 2012 (Platform Toolset = 'v110') cannot be found. + - 'Project > Retarget solution' for both qhull-32.sln and qhull-64.sln + - 'File > Open' your preferred solution (qhull-32.sln or qhull-64.sln) + - 'Save All' both projects + - DevStudio may need a restart + + To compile Qhull with Microsoft Visual C++ 2005 (vcproj files) + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - Load solution build/qhull.sln + - Build target 'win32' (not 'x64') + - Project qhulltest requires Qt for DevStudio (http://www.qt.io) + Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/4.7.4) + If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified' + +------------------ +Compiling Qhull with Qt Creator + + Qt (http://www.qt.io) is a C++ framework for Windows, Linux, and Macintosh + + Qhull uses QTestLib to test qhull's C++ interface (see src/qhulltest/) + + To compile Qhull with Qt Creator + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - Download the Qt SDK + - Start Qt Creator + - Load src/qhull-all.pro + - Configure the project to use a Shadow build at the same level as 'src', 'bin', and 'lib' + If, instead, the shadow build is a subdirectory of 'build', Qt Creator will install Qhull in 'build/bin' and 'build/lib' + - Build + + - Build qhulltest with a C++11 or later compiler + - qhulltest depends on shared libraries QtCore.a and QtTest.a. They may need to be copied + into the bin directory. On Windows, copy Qt5Core.dll and Qt5Test.dll, e.g., /qt/5.11.2/msvc2017_64/bin + - If qhulltest fails with exit status 127 and no error message, + check for missing Q5Core.dll and Qt5Test.dll + +------------------ +Compiling Qhull with mingw/gcc on Windows + + To compile Qhull with MINGW + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - Install GitForWindows (https://gitforwindows.org/) + or MSYS2 (http://www.msys2.org/) + Install in C:\Git\... # Not 'Program Files\...' otherwise './configure && make' will not work + - Install MINGW-w64 with gcc (https://mingw-w64.org/) + 1) Goto sourceforge -- https://sourceforge.net/projects/mingw-w64/files/ + 2) in folder -- mingw-w64 + 3) download installer -- MinGW-W64-install.exe + Run the installer + 1) Select i686/posix/dwarf + 2) Install in 'C:\mingw-w64' # Not 'Program Files\...' + Rename /c/mingw-w64/mingw32/bin/mingw32-make.exe to make.exe + Add the 'C:\mingw-w64\mingw32\bin' directory to your $PATH environment variable + Execute 'which make' to check that 'make' is mingw-w64's make + - Compile Qhull from the home directory + make help + make + + Notes + - Mingw is included with Qt SDK in qt/Tools/mingw53_32 + - If you use Windows XP + Install Road Bash (http://www.qhull.org/bash) or MSYS (http://www.mingw.org/wiki/msys) + Install MINGW (http://mingw.org/) + +------------------ +Compiling Qhull with cygwin on Windows + + To compile Qhull with cygwin + - Download and extract Qhull (either GitHub, .tgz file, or .zip file) + - Install cygwin (http://www.cygwin.com) + - Include packages for gcc, make, ar, and ln + - make + +------------------ +Compiling from Makfile without gcc + + The file, qhull-src.tgz, contains documentation and source files for + qhull and rbox. + + To unpack the tgz file + - tar zxf qhull-src.tgz + - cd qhull + - Use qhull/Makefile + Simpler Makefiles are qhull/src/libqhull/Makefile and qhull/src/libqhull_r/Makefile + + Compiling qhull and rbox with Makefile + - in Makefile, check the CC, CCOPTS1, PRINTMAN, and PRINTC defines + - the defaults are gcc and enscript + - CCOPTS1 should include the ANSI flag. It defines __STDC__ + - in user.h, check the definitions of qh_SECticks and qh_CPUclock. + - use '#define qh_CLOCKtype 2' for timing runs longer than 1 hour + - type: make + - this builds: qhull qconvex qdelaunay qhalf qvoronoi rbox libqhull.a libqhull_r.a + - type: make doc + - this prints the man page + - See also qhull/html/index.htm + - if your compiler reports many errors, it is probably not a ANSI C compiler + - you will need to set the -ansi switch or find another compiler + - if your compiler warns about missing prototypes for fprintf() etc. + - this is ok, your compiler should have these in stdio.h + - if your compiler warns about missing prototypes for memset() etc. + - include memory.h in qhull_a.h + - if your compiler reports "global.c: storage size of 'qh_qh' isn't known" + - delete the initializer "={0}" in global.c, stat.c and mem.c + - if your compiler warns about "stat.c: improper initializer" + - this is ok, the initializer is not used + - if you have trouble building libqhull.a with 'ar' + - try 'make -f Makefile.txt qhullx' + - if the code compiles, the qhull test case will automatically execute + - if an error occurs, there's an incompatibility between machines + - If you can, try a different compiler + - You can turn off the Qhull memory manager with qh_NOmem in mem.h + - You can turn off compiler optimization (-O2 in Makefile) + - If you find the source of the problem, please let us know + - to install the programs and their man pages: + - define MANDIR and BINDIR + - type 'make install' + + - if you have Geomview (www.geomview.org) + - try 'rbox 100 | qconvex G >a' and load 'a' into Geomview + - run 'q_eg' for Geomview examples of Qhull output (see qh-eg.htm) + +------------------ +Compiling on other machines and compilers + + Qhull may compile with Borland C++ 5.0 bcc32. A Makefile is included. + Execute 'cd src/libqhull; make -f Mborland'. If you use the Borland IDE, set + the ANSI option in Options:Project:Compiler:Source:Language-compliance. + + Qhull may compile with Borland C++ 4.02 for Win32 and DOS Power Pack. + Use 'cd src/libqhull; make -f Mborland -D_DPMI'. Qhull 1.0 compiles with + Borland C++ 4.02. For rbox 1.0, use "bcc32 -WX -w- -O2-e -erbox -lc rbox.c". + Use the same options for Qhull 1.0. [D. Zwick] + + If you have troubles with the memory manager, you can turn it off by + defining qh_NOmem in mem.h. + +------------------ +Distributed files + + README.txt // Instructions for installing Qhull + REGISTER.txt // Qhull registration + COPYING.txt // Copyright notice + QHULL-GO.lnk // Windows icon for eg/qhull-go.bat + Announce.txt // Announcement + CMakeLists.txt // CMake build file (2.6 or later) + File_id.diz // Package descriptor + index.htm // Home page + Makefile // Makefile for gcc and other compilers + qhull*.md5sum // md5sum for all files + + bin/* // Qhull executables and dll (.zip only) + build/CMakeModules/CheckLFS.cmake // enables Large File Support in CMake + build/config.cmake.in // extract target variables + build/qhull.pc.in // pkg-config template for creating lib/pkgconfig/qhull*.pc + build/qhull-32.sln // 32-bit DevStudio solution and project files (2010 and later) + build/*-32.vcxproj + build/qhull-64.sln // 64-bit DevStudio solution and project files (2010 and later) + build/*-64.vcxproj + build/qhull.sln // DevStudio solution and project files (2005 and 2009) + build/*.vcproj + build/qhulltest/ // DevStudio project files for qhulltest (C++ and Qt) + build/README-build.txt // Contents of build/ + eg/* // Test scripts and geomview files from q_eg + html/index.htm // Manual + html/qh-faq.htm // Frequently asked questions + html/qh-get.htm // Download page + html/qhull-cpp.xml // C++ style notes as a Road FAQ (www.qhull.org/road) + src/Changes.txt // Change history for Qhull and rbox + src/qhull-all.pro // Qt project + +eg/ + q_benchmark // shell script for precision and performance benchmark + q_benchmark-ok.txt // reviewed output from q_benchmark + q_eg // shell script for Geomview examples (eg.01.cube) + q_egtest // shell script for Geomview test examples + q_test // shell script to test qhull + q_test.bat // Windows batch test for QHULL-GO.bat + // cd bin; ..\eg\q_test.bat >q_test.x 2>&1 + q_test-ok.txt // reviewed output from q_test + qhulltest-ok.txt // reviewed output from qhulltest (Qt only) + make-qhull_qh.sh // shell script to create non-reentrant qhull_qh from reentrant Qhull + make-vcproj.sh // shell script to create vcproj and vcxprog files + qhull-zip.sh // shell script to create distribution files + qtest.sh // shell script for testing and logging qhull + +rbox consists of (bin, html): + rbox.exe // Win32 executable (.zip only) + rbox.htm // html manual + rbox.man // Unix man page + rbox.txt + +qhull consists of (bin, html): + qconvex.exe // Win32 executables and dlls (.zip download only) + qhull.exe // Built with the reentrant library (about 2% slower) + qdelaunay.exe + qhalf.exe + qvoronoi.exe + qhull_r.dll + qhull-go.bat // command window + qconvex.htm // html manual + qdelaun.htm + qdelau_f.htm + qhalf.htm + qvoronoi.htm + qvoron_f.htm + qh-eg.htm + qh-code.htm + qh-impre.htm + index.htm + qh-opt*.htm + qh-quick.htm + qh--*.gif // images for manual + normal_voronoi_knauss_oesterle.jpg + qh_findbestfacet-drielsma.pdf + qhull.man // Unix man page + qhull.txt + +bin/ + msvcr80.dll // Visual C++ redistributable file (.zip download only) + +src/ + qhull/unix.c // Qhull and rbox applications using non-reentrant libqhullstatic.a + rbox/rbox.c + qconvex/qconvex.c + qhalf/qhalf.c + qdelaunay/qdelaunay.c + qvoronoi/qvoronoi.c + + qhull/unix_r.c // Qhull and rbox applications using reentrant libqhullstatic_r.a + rbox/rbox_r.c + qconvex/qconvex_r.c // Qhull applications built with reentrant libqhull_r/Makefile + qhalf/qhalf_r.c + qdelaunay/qdelaun_r.c + qvoronoi/qvoronoi_r.c + + user_eg/user_eg_r.c // example of using qhull_r.dll from a user program + user_eg2/user_eg2_r.c // example of using libqhullstatic_r.a from a user program + user_eg3/user_eg3_r.cpp // example of Qhull's C++ interface libqhullcpp with libqhullstatic_r.a + qhulltest/qhulltest.cpp // Test of Qhull's C++ interface using Qt's QTestLib + qhull-*.pri // Include files for Qt projects + testqset_r/testqset_r.c // Test of reentrant qset_r.c and mem_r.c + testqset/testqset.c // Test of non-rentrant qset.c and mem.c + +src/libqhull + libqhull.pro // Qt project for non-rentrant, shared library (qhull.dll) + index.htm // design documentation for libqhull + qh-*.htm + qhull-exports.def // Export Definition files for Visual C++ + qhull-nomerge-exports.def + qhull_p-exports.def + qhull_p-nomerge-exports.def + Makefile // Simple gcc Makefile for qhull and libqhullstatic.a + Mborland // Makefile for Borland C++ 5.0 + + libqhull.h // header file for qhull + user.h // header file of user definable constants + libqhull.c // Quickhull algorithm with partitioning + user.c // user re-definable functions + usermem.c + userprintf.c + userprintf_rbox.c + + qhull_a.h // include files for libqhull/*.c + geom.c // geometric routines + geom2.c + geom.h + global.c // global variables + io.c // input-output routines + io.h + mem.c // memory routines, this is stand-alone code + mem.h + merge.c // merging of non-convex facets + merge.h + poly.c // polyhedron routines + poly2.c + poly.h + qset.c // set routines, this only depends on mem.c + qset.h + random.c // utilities w/ Park & Miller's random number generator + random.h + rboxlib.c // point set generator for rbox + stat.c // statistics + stat.h + +src/libqhull_r + libqhull_r.pro // Qt project for rentrant, shared library (qhull_r.dll) + index.htm // design documentation for libqhull_r + qh-*_r.htm + qhull_r-exports.def // Export Definition files for Visual C++ + qhull_r-nomerge-exports.def + Makefile // Simple gcc Makefile for qhull and libqhullstatic.a + + libqhull_r.h // header file for qhull + user_r.h // header file of user definable constants + libqhull_r.c // Quickhull algorithm wi_r.hpartitioning + user_r.c // user re-definable functions + usermem.c + userprintf.c + userprintf_rbox.c + qhull_ra.h // include files for libqhull/*_r.c + geom_r.c // geometric routines + geom2.c + geom_r.h + global_r.c // global variables + io_r.c // input-output routines + io_r.h + mem_r.c // memory routines, this is stand-alone code + mem.h + merge_r.c // merging of non-convex facets + merge.h + poly_r.c // polyhedron routines + poly2.c + poly_r.h + qset_r.c // set routines, this only depends on mem_r.c + qset.h + random_r.c // utilities w/ Park & Miller's random number generator + random.h + rboxlib_r.c // point set generator for rbox + stat_r.c // statistics + stat.h + +src/libqhullcpp/ + libqhullcpp.pro // Qt project for renentrant, static C++ library + Qhull.cpp // Calls libqhull_r.c from C++ + Qhull.h + qt-qhull.cpp // Supporting methods for Qt + + Coordinates.cpp // input classes + Coordinates.h + + PointCoordinates.cpp + PointCoordinates.h + RboxPoints.cpp // call rboxlib.c from C++ + RboxPoints.h + + QhullFacet.cpp // data structure classes + QhullFacet.h + QhullHyperplane.cpp + QhullHyperplane.h + QhullPoint.cpp + QhullPoint.h + QhullQh.cpp + QhullRidge.cpp + QhullRidge.h + QhullVertex.cpp + QhullVertex.h + + QhullFacetList.cpp // collection classes + QhullFacetList.h + QhullFacetSet.cpp + QhullFacetSet.h + QhullIterator.h + QhullLinkedList.h + QhullPoints.cpp + QhullPoints.h + QhullPointSet.cpp + QhullPointSet.h + QhullSet.cpp + QhullSet.h + QhullSets.h + QhullVertexSet.cpp + QhullVertexSet.h + + functionObjects.h // supporting classes + QhullError.cpp + QhullError.h + QhullQh.cpp + QhullQh.h + QhullStat.cpp + QhullStat.h + QhullUser.cpp + QhullUser.h + RoadError.cpp // Supporting base classes + RoadError.h + RoadLogEvent.cpp + RoadLogEvent.h + usermem_r-cpp.cpp // Optional override for qh_exit() to throw an error + +src/libqhullstatic/ + libqhullstatic.pro // Qt project for non-reentrant, static library + +src/libqhullstatic_r/ + libqhullstatic_r.pro // Qt project for reentrant, static library + +src/qhulltest/ + qhulltest.pro // Qt project for test of C++ interface + Coordinates_test.cpp // Test of each class + PointCoordinates_test.cpp + Qhull_test.cpp + QhullFacet_test.cpp + QhullFacetList_test.cpp + QhullFacetSet_test.cpp + QhullHyperplane_test.cpp + QhullLinkedList_test.cpp + QhullPoint_test.cpp + QhullPoints_test.cpp + QhullPointSet_test.cpp + QhullRidge_test.cpp + QhullSet_test.cpp + QhullVertex_test.cpp + QhullVertexSet_test.cpp + RboxPoints_test.cpp + RoadTest.cpp // Run multiple test files with QTestLib + RoadTest.h + +------------------ +Authors + + C. Bradford Barber Hannu Huhdanpaa (Version 1.0) + bradb@shore.net hannu@qhull.org + + Qhull 1.0 and 2.0 were developed under NSF grants NSF/DMS-8920161 + and NSF-CCR-91-15793 750-7504 at the Geometry Center and Harvard + University. If you find Qhull useful, please let us know. diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/accessors_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/accessors_r.c new file mode 100644 index 00000000000..5052e0890c3 --- /dev/null +++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/accessors_r.c @@ -0,0 +1,69 @@ +#include +#include "libqhull_r.h" + +qhT *qh_alloc_qh(FILE *errfile) { + qhT *qh = (qhT*) qh_malloc(sizeof(qhT)); + QHULL_LIB_CHECK + if (qh) qh_zero(qh, errfile); + return qh; +} + +/* Free the qhT pointer. + + Note: qh_freeqhull and qh_memfreeshort should be called before calling qh_free_qh. */ +void qh_free_qh(qhT *qh) { + qh_free(qh); +} + +#define GETTER(TYPE, FIELD) TYPE qh_get_##FIELD(const qhT *qh) { return qh->FIELD; } +#define SETTER(TYPE, FIELD) void qh_set_##FIELD(qhT *qh, TYPE _val_) { qh->FIELD = _val_; } + +/* required to emulate the various FOR* macros */ +GETTER(facetT*, facet_list) +GETTER(pointT*, first_point) +GETTER(int, hull_dim) +GETTER(int, num_facets) +GETTER(int, num_points) +GETTER(int, num_vertices) +GETTER(vertexT*, vertex_list) + +/* suggested by @blegat based on Qhull.jl wrappers */ +GETTER(realT, totarea) +GETTER(realT, totvol) +GETTER(boolT, hasAreaVolume) +SETTER(boolT, hasAreaVolume) +GETTER(boolT, hasTriangulation) +SETTER(boolT, hasTriangulation) + +/* suggested by @JuhaHeiskala based on his DirectQHull.jl wrapper */ +GETTER(int, num_good) +GETTER(setT*, del_vertices) +GETTER(int, input_dim) + +/* other accessors, mimicking those provided by the scipy API: */ +GETTER(boolT, DELAUNAY) +GETTER(boolT, SCALElast) +GETTER(boolT, KEEPcoplanar) +GETTER(boolT, MERGEexact) +GETTER(boolT, NOerrexit) +GETTER(boolT, PROJECTdelaunay) +GETTER(boolT, ATinfinity) +GETTER(boolT, UPPERdelaunay) +GETTER(int, normal_size) +GETTER(int, num_visible) +GETTER(int, center_size) +GETTER(const char *, qhull_command) +GETTER(facetT*, facet_tail) +GETTER(vertexT*, vertex_tail) +GETTER(unsigned int, facet_id) +GETTER(unsigned int, visit_id) +GETTER(unsigned int, vertex_visit) +GETTER(pointT*, input_points) +GETTER(coordT*, feasible_point) +GETTER(realT, last_low) +GETTER(realT, last_high) +GETTER(realT, last_newhigh) +GETTER(realT, max_outside) +GETTER(realT, MINoutside) +GETTER(realT, DISTround) +GETTER(setT*, other_points) diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/geom2_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/geom2_r.c new file mode 100644 index 00000000000..7d171e4bd60 --- /dev/null +++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/geom2_r.c @@ -0,0 +1,2302 @@ +/*
  ---------------------------------
+
+
+   geom2_r.c
+   infrequently used geometric routines of qhull
+
+   see qh-geom_r.htm and geom_r.h
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/geom2_r.c#18 $$Change: 3396 $
+   $DateTime: 2023/01/02 16:59:48 $$Author: bbarber $
+
+   frequently used code goes into geom_r.c
+*/
+
+#include "qhull_ra.h"
+
+/*================== functions in alphabetic order ============*/
+
+/*---------------------------------
+
+  qh_copypoints(qh, points, numpoints, dimension )
+    return qh_malloc'd copy of points
+
+  notes:
+    qh_free the returned points to avoid a memory leak
+*/
+coordT *qh_copypoints(qhT *qh, coordT *points, int numpoints, int dimension)
+{
+  int size;
+  coordT *newpoints;
+
+  size= numpoints * dimension * (int)sizeof(coordT);
+  if (!(newpoints= (coordT *)qh_malloc((size_t)size))) {
+    qh_fprintf(qh, qh->ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
+        numpoints);
+    qh_errexit(qh, qh_ERRmem, NULL, NULL);
+  }
+  memcpy((char *)newpoints, (char *)points, (size_t)size); /* newpoints!=0 by QH6004 */
+  return newpoints;
+} /* copypoints */
+
+/*---------------------------------
+
+  qh_crossproduct( dim, vecA, vecB, vecC )
+    crossproduct of 2 dim vectors
+    C= A x B
+
+  notes:
+    from Glasner, Graphics Gems I, p. 639
+    only defined for dim==3
+*/
+void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
+
+  if (dim == 3) {
+    vecC[0]=   det2_(vecA[1], vecA[2],
+                     vecB[1], vecB[2]);
+    vecC[1]= - det2_(vecA[0], vecA[2],
+                     vecB[0], vecB[2]);
+    vecC[2]=   det2_(vecA[0], vecA[1],
+                     vecB[0], vecB[1]);
+  }
+} /* vcross */
+
+/*---------------------------------
+
+  qh_determinant(qh, rows, dim, nearzero )
+    compute signed determinant of a square matrix
+    uses qh.NEARzero to test for degenerate matrices
+
+  returns:
+    determinant
+    overwrites rows and the matrix
+    if dim == 2 or 3
+      nearzero iff determinant < qh->NEARzero[dim-1]
+      (!quite correct, not critical)
+    if dim >= 4
+      nearzero iff diagonal[k] < qh->NEARzero[k]
+*/
+realT qh_determinant(qhT *qh, realT **rows, int dim, boolT *nearzero) {
+  realT det=0;
+  int i;
+  boolT sign= False;
+
+  *nearzero= False;
+  if (dim < 2) {
+    qh_fprintf(qh, qh->ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }else if (dim == 2) {
+    det= det2_(rows[0][0], rows[0][1],
+                 rows[1][0], rows[1][1]);
+    if (fabs_(det) < 10*qh->NEARzero[1])  /* QH11031 FIX: not really correct, what should this be? */
+      *nearzero= True;
+  }else if (dim == 3) {
+    det= det3_(rows[0][0], rows[0][1], rows[0][2],
+                 rows[1][0], rows[1][1], rows[1][2],
+                 rows[2][0], rows[2][1], rows[2][2]);
+    if (fabs_(det) < 10*qh->NEARzero[2])  /* QH11031 FIX: what should this be?  det 5.5e-12 was flat for qh_maxsimplex of qdelaunay 0,0 27,27 -36,36 -9,63 */
+      *nearzero= True;
+  }else {
+    qh_gausselim(qh, rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok */
+    det= 1.0;
+    for (i=dim; i--; )
+      det *= (rows[i])[i];
+    if (sign)
+      det= -det;
+  }
+  return det;
+} /* determinant */
+
+/*---------------------------------
+
+  qh_detjoggle(qh, points, numpoints, dimension )
+    determine default max joggle for point array
+      as qh_distround * qh_JOGGLEdefault
+
+  returns:
+    initial value for JOGGLEmax from points and REALepsilon
+
+  notes:
+    computes DISTround since qh_maxmin not called yet
+    if qh->SCALElast, last dimension will be scaled later to MAXwidth
+
+    loop duplicated from qh_maxmin
+*/
+realT qh_detjoggle(qhT *qh, pointT *points, int numpoints, int dimension) {
+  realT abscoord, distround, joggle, maxcoord, mincoord;
+  pointT *point, *pointtemp;
+  realT maxabs= -REALmax;
+  realT sumabs= 0;
+  realT maxwidth= 0;
+  int k;
+
+  if (qh->SETroundoff)
+    distround= qh->DISTround; /* 'En' */
+  else{
+    for (k=0; k < dimension; k++) {
+      if (qh->SCALElast && k == dimension-1)
+        abscoord= maxwidth;
+      else if (qh->DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
+        abscoord= 2 * maxabs * maxabs;  /* may be low by qh->hull_dim/2 */
+      else {
+        maxcoord= -REALmax;
+        mincoord= REALmax;
+        FORALLpoint_(qh, points, numpoints) {
+          maximize_(maxcoord, point[k]);
+          minimize_(mincoord, point[k]);
+        }
+        maximize_(maxwidth, maxcoord-mincoord);
+        abscoord= fmax_(maxcoord, -mincoord);
+      }
+      sumabs += abscoord;
+      maximize_(maxabs, abscoord);
+    } /* for k */
+    distround= qh_distround(qh, qh->hull_dim, maxabs, sumabs);
+  }
+  joggle= distround * qh_JOGGLEdefault;
+  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
+  trace2((qh, qh->ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
+  return joggle;
+} /* detjoggle */
+
+/*---------------------------------
+
+  qh_detmaxoutside(qh);
+    determine qh.MAXoutside target for qh_RATIO... tests of distance
+    updates option '_max-outside'
+
+  notes:
+    called from qh_addpoint and qh_detroundoff
+    accounts for qh.ONEmerge, qh.DISTround, qh.MINoutside ('Wn'), qh.max_outside
+    see qh_maxout for qh.max_outside with qh.DISTround
+*/
+
+void qh_detmaxoutside(qhT *qh) {
+  realT maxoutside;
+
+  maxoutside= fmax_(qh->max_outside, qh->ONEmerge + qh->DISTround);
+  maximize_(maxoutside, qh->MINoutside);
+  qh->MAXoutside= maxoutside;
+  trace3((qh, qh->ferr, 3056, "qh_detmaxoutside: MAXoutside %2.2g from qh.max_outside %2.2g, ONEmerge %2.2g, MINoutside %2.2g, DISTround %2.2g\n",
+      qh->MAXoutside, qh->max_outside, qh->ONEmerge, qh->MINoutside, qh->DISTround));
+} /* detmaxoutside */
+
+/*---------------------------------
+
+  qh_detroundoff(qh)
+    determine maximum roundoff errors from
+      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
+      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
+
+    accounts for qh.SETroundoff, qh.RANDOMdist, qh->MERGEexact
+      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
+      qh.postmerge_centrum, qh.MINoutside,
+      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
+
+  returns:
+    sets qh.DISTround, etc. (see below)
+    appends precision constants to qh.qhull_options
+
+  see:
+    qh_maxmin() for qh.NEARzero
+
+  design:
+    determine qh.DISTround for distance computations
+    determine minimum denominators for qh_divzero
+    determine qh.ANGLEround for angle computations
+    adjust qh.premerge_cos,... for roundoff error
+    determine qh.ONEmerge for maximum error due to a single merge
+    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
+      qh.MINoutside, qh.WIDEfacet
+    initialize qh.max_vertex and qh.minvertex
+*/
+void qh_detroundoff(qhT *qh) {
+
+  qh_option(qh, "_max-width", NULL, &qh->MAXwidth);
+  if (!qh->SETroundoff) {
+    qh->DISTround= qh_distround(qh, qh->hull_dim, qh->MAXabs_coord, qh->MAXsumcoord);
+    qh_option(qh, "Error-roundoff", NULL, &qh->DISTround);
+  }
+  qh->MINdenom= qh->MINdenom_1 * qh->MAXabs_coord;
+  qh->MINdenom_1_2= sqrt(qh->MINdenom_1 * qh->hull_dim) ;  /* if will be normalized */
+  qh->MINdenom_2= qh->MINdenom_1_2 * qh->MAXabs_coord;
+                                              /* for inner product */
+  qh->ANGLEround= 1.01 * qh->hull_dim * REALepsilon;
+  if (qh->RANDOMdist) {
+    qh->ANGLEround += qh->RANDOMfactor;
+    trace4((qh, qh->ferr, 4096, "qh_detroundoff: increase qh.ANGLEround by option 'R%2.2g'\n", qh->RANDOMfactor));
+  }
+  if (qh->premerge_cos < REALmax/2) {
+    qh->premerge_cos -= qh->ANGLEround;
+    if (qh->RANDOMdist)
+      qh_option(qh, "Angle-premerge-with-random", NULL, &qh->premerge_cos);
+  }
+  if (qh->postmerge_cos < REALmax/2) {
+    qh->postmerge_cos -= qh->ANGLEround;
+    if (qh->RANDOMdist)
+      qh_option(qh, "Angle-postmerge-with-random", NULL, &qh->postmerge_cos);
+  }
+  qh->premerge_centrum += 2 * qh->DISTround;    /*2 for centrum and distplane()*/
+  qh->postmerge_centrum += 2 * qh->DISTround;
+  if (qh->RANDOMdist && (qh->MERGEexact || qh->PREmerge))
+    qh_option(qh, "Centrum-premerge-with-random", NULL, &qh->premerge_centrum);
+  if (qh->RANDOMdist && qh->POSTmerge)
+    qh_option(qh, "Centrum-postmerge-with-random", NULL, &qh->postmerge_centrum);
+  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
+    realT maxangle= 1.0, maxrho;
+
+    minimize_(maxangle, qh->premerge_cos);
+    minimize_(maxangle, qh->postmerge_cos);
+    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
+    qh->ONEmerge= sqrt((realT)qh->hull_dim) * qh->MAXwidth *
+      sqrt(1.0 - maxangle * maxangle) + qh->DISTround;
+    maxrho= qh->hull_dim * qh->premerge_centrum + qh->DISTround;
+    maximize_(qh->ONEmerge, maxrho);
+    maxrho= qh->hull_dim * qh->postmerge_centrum + qh->DISTround;
+    maximize_(qh->ONEmerge, maxrho);
+    if (qh->MERGING)
+      qh_option(qh, "_one-merge", NULL, &qh->ONEmerge);
+  }
+  qh->NEARinside= qh->ONEmerge * qh_RATIOnearinside; /* only used if qh->KEEPnearinside */
+  if (qh->JOGGLEmax < REALmax/2 && (qh->KEEPcoplanar || qh->KEEPinside)) {
+    realT maxdist;             /* adjust qh.NEARinside for joggle */
+    qh->KEEPnearinside= True;
+    maxdist= sqrt((realT)qh->hull_dim) * qh->JOGGLEmax + qh->DISTround;
+    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
+    maximize_(qh->NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
+  }
+  if (qh->KEEPnearinside)
+    qh_option(qh, "_near-inside", NULL, &qh->NEARinside);
+  if (qh->JOGGLEmax < qh->DISTround) {
+    qh_fprintf(qh, qh->ferr, 6006, "qhull option error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
+         qh->JOGGLEmax, qh->DISTround);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (qh->MINvisible > REALmax/2) {
+    if (!qh->MERGING)
+      qh->MINvisible= qh->DISTround;
+    else if (qh->hull_dim <= 3)
+      qh->MINvisible= qh->premerge_centrum;
+    else
+      qh->MINvisible= qh_COPLANARratio * qh->premerge_centrum;
+    if (qh->APPROXhull && qh->MINvisible > qh->MINoutside)
+      qh->MINvisible= qh->MINoutside;
+    qh_option(qh, "Visible-distance", NULL, &qh->MINvisible);
+  }
+  if (qh->MAXcoplanar > REALmax/2) {
+    qh->MAXcoplanar= qh->MINvisible;
+    qh_option(qh, "U-max-coplanar", NULL, &qh->MAXcoplanar);
+  }
+  if (!qh->APPROXhull) {             /* user may specify qh->MINoutside */
+    qh->MINoutside= 2 * qh->MINvisible;
+    if (qh->premerge_cos < REALmax/2)
+      maximize_(qh->MINoutside, (1- qh->premerge_cos) * qh->MAXabs_coord);
+    qh_option(qh, "Width-outside", NULL, &qh->MINoutside);
+  }
+  qh->WIDEfacet= qh->MINoutside;
+  maximize_(qh->WIDEfacet, qh_WIDEcoplanar * qh->MAXcoplanar);
+  maximize_(qh->WIDEfacet, qh_WIDEcoplanar * qh->MINvisible);
+  qh_option(qh, "_wide-facet", NULL, &qh->WIDEfacet);
+  if (qh->MINvisible > qh->MINoutside + 3 * REALepsilon
+  && !qh->BESToutside && !qh->FORCEoutput)
+    qh_fprintf(qh, qh->ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
+             qh->MINvisible, qh->MINoutside);
+  qh->max_vertex= qh->DISTround;
+  qh->min_vertex= -qh->DISTround;
+  /* numeric constants reported in printsummary */
+  qh_detmaxoutside(qh);
+} /* detroundoff */
+
+/*---------------------------------
+
+  qh_detsimplex(qh, apex, points, dim, nearzero )
+    compute determinant of a simplex with point apex and base points
+
+  returns:
+     signed determinant and nearzero from qh_determinant
+
+  notes:
+     called by qh_maxsimplex and qh_initialvertices
+     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
+
+  design:
+    construct qm_matrix by subtracting apex from points
+    compute determinate
+*/
+realT qh_detsimplex(qhT *qh, pointT *apex, setT *points, int dim, boolT *nearzero) {
+  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
+  coordT **rows;
+  int k,  i=0;
+  realT det;
+
+  zinc_(Zdetsimplex);
+  gmcoord= qh->gm_matrix;
+  rows= qh->gm_row;
+  FOREACHpoint_(points) {
+    if (i == dim)
+      break;
+    rows[i++]= gmcoord;
+    coordp= point;
+    coorda= apex;
+    for (k=dim; k--; )
+      *(gmcoord++)= *coordp++ - *coorda++;
+  }
+  if (i < dim) {
+    qh_fprintf(qh, qh->ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
+               i, dim);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  det= qh_determinant(qh, rows, dim, nearzero);
+  trace2((qh, qh->ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
+          det, qh_pointid(qh, apex), dim, *nearzero));
+  return det;
+} /* detsimplex */
+
+/*---------------------------------
+
+  qh_distnorm( dim, point, normal, offset )
+    return distance from point to hyperplane at normal/offset
+
+  returns:
+    dist
+
+  notes:
+    dist > 0 if point is outside of hyperplane
+
+  see:
+    qh_distplane in geom_r.c
+*/
+realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
+  coordT *normalp= normal, *coordp= point;
+  realT dist;
+  int k;
+
+  dist= *offsetp;
+  for (k=dim; k--; )
+    dist += *(coordp++) * *(normalp++);
+  return dist;
+} /* distnorm */
+
+/*---------------------------------
+
+  qh_distround(qh, dimension, maxabs, maxsumabs )
+    compute maximum round-off error for a distance computation
+      to a normalized hyperplane
+    maxabs is the maximum absolute value of a coordinate
+    maxsumabs is the maximum possible sum of absolute coordinate values
+    if qh.RANDOMdist ('Qr'), adjusts qh_distround
+
+  returns:
+    max dist round for qh.REALepsilon and qh.RANDOMdist
+
+  notes:
+    calculate roundoff error according to Golub & van Loan, 1983, Lemma 3.2-1, "Rounding Errors"
+    use sqrt(dim) since one vector is normalized
+      or use maxsumabs since one vector is < 1
+*/
+realT qh_distround(qhT *qh, int dimension, realT maxabs, realT maxsumabs) {
+  realT maxdistsum, maxround, delta;
+
+  maxdistsum= sqrt((realT)dimension) * maxabs;
+  minimize_( maxdistsum, maxsumabs);
+  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
+              /* adds maxabs for offset */
+  if (qh->RANDOMdist) {
+    delta= qh->RANDOMfactor * maxabs;
+    maxround += delta;
+    trace4((qh, qh->ferr, 4092, "qh_distround: increase roundoff by random delta %2.2g for option 'R%2.2g'\n", delta, qh->RANDOMfactor));
+  }
+  trace4((qh, qh->ferr, 4008, "qh_distround: %2.2g, maxabs %2.2g, maxsumabs %2.2g, maxdistsum %2.2g\n",
+            maxround, maxabs, maxsumabs, maxdistsum));
+  return maxround;
+} /* distround */
+
+/*---------------------------------
+
+  qh_divzero( numer, denom, mindenom1, zerodiv )
+    divide by a number that's nearly zero
+    mindenom1= minimum denominator for dividing into 1.0
+
+  returns:
+    quotient
+    sets zerodiv and returns 0.0 if it would overflow
+
+  design:
+    if numer is nearly zero and abs(numer) < abs(denom)
+      return numer/denom
+    else if numer is nearly zero
+      return 0 and zerodiv
+    else if denom/numer non-zero
+      return numer/denom
+    else
+      return 0 and zerodiv
+*/
+realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
+  realT temp, numerx, denomx;
+
+
+  if (numer < mindenom1 && numer > -mindenom1) {
+    numerx= fabs_(numer);
+    denomx= fabs_(denom);
+    if (numerx < denomx) {
+      *zerodiv= False;
+      return numer/denom;
+    }else {
+      *zerodiv= True;
+      return 0.0;
+    }
+  }
+  temp= denom/numer;
+  if (temp > mindenom1 || temp < -mindenom1) {
+    *zerodiv= False;
+    return numer/denom;
+  }else {
+    *zerodiv= True;
+    return 0.0;
+  }
+} /* divzero */
+
+
+/*---------------------------------
+
+  qh_facetarea(qh, facet )
+    return area for a facet
+
+  notes:
+    if non-simplicial,
+      uses centrum to triangulate facet and sums the projected areas.
+    if (qh->DELAUNAY),
+      computes projected area instead for last coordinate
+    assumes facet->normal exists
+    projecting tricoplanar facets to the hyperplane does not appear to make a difference
+
+  design:
+    if simplicial
+      compute area
+    else
+      for each ridge
+        compute area from centrum to ridge
+    negate area if upper Delaunay facet
+*/
+realT qh_facetarea(qhT *qh, facetT *facet) {
+  vertexT *apex;
+  pointT *centrum;
+  realT area= 0.0;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->simplicial) {
+    apex= SETfirstt_(facet->vertices, vertexT);
+    area= qh_facetarea_simplex(qh, qh->hull_dim, apex->point, facet->vertices,
+                    apex, facet->toporient, facet->normal, &facet->offset);
+  }else {
+    if (qh->CENTERtype == qh_AScentrum)
+      centrum= facet->center;
+    else
+      centrum= qh_getcentrum(qh, facet);
+    FOREACHridge_(facet->ridges)
+      area += qh_facetarea_simplex(qh, qh->hull_dim, centrum, ridge->vertices,
+                 NULL, (boolT)(ridge->top == facet),  facet->normal, &facet->offset);
+    if (qh->CENTERtype != qh_AScentrum)
+      qh_memfree(qh, centrum, qh->normal_size);
+  }
+  if (facet->upperdelaunay && qh->DELAUNAY)
+    area= -area;  /* the normal should be [0,...,1] */
+  trace4((qh, qh->ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
+  return area;
+} /* facetarea */
+
+/*---------------------------------
+
+  qh_facetarea_simplex(qh, dim, apex, vertices, notvertex, toporient, normal, offset )
+    return area for a simplex defined by
+      an apex, a base of vertices, an orientation, and a unit normal
+    if simplicial or tricoplanar facet,
+      notvertex is defined and it is skipped in vertices
+
+  returns:
+    computes area of simplex projected to plane [normal,offset]
+    returns 0 if vertex too far below plane (qh->WIDEfacet)
+      vertex can't be apex of tricoplanar facet
+
+  notes:
+    if (qh->DELAUNAY),
+      computes projected area instead for last coordinate
+    uses qh->gm_matrix/gm_row and qh->hull_dim
+    helper function for qh_facetarea
+
+  design:
+    if Notvertex
+      translate simplex to apex
+    else
+      project simplex to normal/offset
+      translate simplex to apex
+    if Delaunay
+      set last row/column to 0 with -1 on diagonal
+    else
+      set last row to Normal
+    compute determinate
+    scale and flip sign for area
+*/
+realT qh_facetarea_simplex(qhT *qh, int dim, coordT *apex, setT *vertices,
+        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
+  pointT *coorda, *coordp, *gmcoord;
+  coordT **rows, *normalp;
+  int k,  i=0;
+  realT area, dist;
+  vertexT *vertex, **vertexp;
+  boolT nearzero;
+
+  gmcoord= qh->gm_matrix;
+  rows= qh->gm_row;
+  FOREACHvertex_(vertices) {
+    if (vertex == notvertex)
+      continue;
+    rows[i++]= gmcoord;
+    coorda= apex;
+    coordp= vertex->point;
+    normalp= normal;
+    if (notvertex) {
+      for (k=dim; k--; )
+        *(gmcoord++)= *coordp++ - *coorda++;
+    }else {
+      dist= *offset;
+      for (k=dim; k--; )
+        dist += *coordp++ * *normalp++;
+      if (dist < -qh->WIDEfacet) {
+        zinc_(Znoarea);
+        return 0.0;
+      }
+      coordp= vertex->point;
+      normalp= normal;
+      for (k=dim; k--; )
+        *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
+    }
+  }
+  if (i != dim-1) {
+    qh_fprintf(qh, qh->ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
+               i, dim);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  rows[i]= gmcoord;
+  if (qh->DELAUNAY) {
+    for (i=0; i < dim-1; i++)
+      rows[i][dim-1]= 0.0;
+    for (k=dim; k--; )
+      *(gmcoord++)= 0.0;
+    rows[dim-1][dim-1]= -1.0;
+  }else {
+    normalp= normal;
+    for (k=dim; k--; )
+      *(gmcoord++)= *normalp++;
+  }
+  zinc_(Zdetfacetarea);
+  area= qh_determinant(qh, rows, dim, &nearzero);
+  if (toporient)
+    area= -area;
+  area *= qh->AREAfactor;
+  trace4((qh, qh->ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
+          area, qh_pointid(qh, apex), toporient, nearzero));
+  return area;
+} /* facetarea_simplex */
+
+/*---------------------------------
+
+  qh_facetcenter(qh, vertices )
+    return Voronoi center (Voronoi vertex) for a facet's vertices
+
+  returns:
+    return temporary point equal to the center
+
+  see:
+    qh_voronoi_center()
+*/
+pointT *qh_facetcenter(qhT *qh, setT *vertices) {
+  setT *points= qh_settemp(qh, qh_setsize(qh, vertices));
+  vertexT *vertex, **vertexp;
+  pointT *center;
+
+  FOREACHvertex_(vertices)
+    qh_setappend(qh, &points, vertex->point);
+  center= qh_voronoi_center(qh, qh->hull_dim-1, points);
+  qh_settempfree(qh, &points);
+  return center;
+} /* facetcenter */
+
+/*---------------------------------
+
+  qh_findgooddist(qh, point, facetA, dist, facetlist )
+    find best good facet visible for point from facetA
+    assumes facetA is visible from point
+
+  returns:
+    best facet, i.e., good facet that is furthest from point
+      distance to best facet
+      NULL if none
+
+    moves good, visible facets (and some other visible facets)
+      to end of qh->facet_list
+
+  notes:
+    uses qh->visit_id
+
+  design:
+    initialize bestfacet if facetA is good
+    move facetA to end of facetlist
+    for each facet on facetlist
+      for each unvisited neighbor of facet
+        move visible neighbors to end of facetlist
+        update best good neighbor
+        if no good neighbors, update best facet
+*/
+facetT *qh_findgooddist(qhT *qh, pointT *point, facetT *facetA, realT *distp,
+               facetT **facetlist) {
+  realT bestdist= -REALmax, dist;
+  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
+  boolT goodseen= False;
+
+  if (facetA->good) {
+    zzinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
+    qh_distplane(qh, point, facetA, &bestdist);
+    bestfacet= facetA;
+    goodseen= True;
+  }
+  qh_removefacet(qh, facetA);
+  qh_appendfacet(qh, facetA);
+  *facetlist= facetA;
+  facetA->visitid= ++qh->visit_id;
+  FORALLfacet_(*facetlist) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh->visit_id)
+        continue;
+      neighbor->visitid= qh->visit_id;
+      if (goodseen && !neighbor->good)
+        continue;
+      zzinc_(Zcheckpart);
+      qh_distplane(qh, point, neighbor, &dist);
+      if (dist > 0) {
+        qh_removefacet(qh, neighbor);
+        qh_appendfacet(qh, neighbor);
+        if (neighbor->good) {
+          goodseen= True;
+          if (dist > bestdist) {
+            bestdist= dist;
+            bestfacet= neighbor;
+          }
+        }
+      }
+    }
+  }
+  if (bestfacet) {
+    *distp= bestdist;
+    trace2((qh, qh->ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
+      qh_pointid(qh, point), bestdist, bestfacet->id));
+    return bestfacet;
+  }
+  trace4((qh, qh->ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
+      qh_pointid(qh, point), facetA->id));
+  return NULL;
+}  /* findgooddist */
+
+/*---------------------------------
+
+  qh_furthestnewvertex(qh, unvisited, facet, &maxdist )
+    return furthest unvisited, new vertex to a facet
+
+  return:
+    NULL if no vertex is above facet
+    maxdist to facet
+    updates v.visitid
+
+  notes:
+    Ignores vertices in facetB
+    Does not change qh.vertex_visit.  Use in conjunction with qh_furthestvertex
+*/
+vertexT *qh_furthestnewvertex(qhT *qh, unsigned int unvisited, facetT *facet, realT *maxdistp /* qh.newvertex_list */) {
+  vertexT *maxvertex= NULL, *vertex;
+  coordT dist, maxdist= 0.0;
+
+  FORALLvertex_(qh->newvertex_list) {
+    if (vertex->newfacet && vertex->visitid <= unvisited) {
+      vertex->visitid= qh->vertex_visit;
+      qh_distplane(qh, vertex->point, facet, &dist);
+      if (dist > maxdist) {
+        maxdist= dist;
+        maxvertex= vertex;
+      }
+    }
+  }
+  trace4((qh, qh->ferr, 4085, "qh_furthestnewvertex: v%d dist %2.2g is furthest new vertex for f%d\n",
+    getid_(maxvertex), maxdist, facet->id));
+  *maxdistp= maxdist;
+  return maxvertex;
+} /* furthestnewvertex */
+
+/*---------------------------------
+
+  qh_furthestvertex(qh, facetA, facetB, &maxdist, &mindist )
+    return furthest vertex in facetA from facetB, or NULL if none
+
+  return:
+    maxdist and mindist to facetB or 0.0 if none
+    updates qh.vertex_visit
+
+  notes:
+    Ignores vertices in facetB
+*/
+vertexT *qh_furthestvertex(qhT *qh, facetT *facetA, facetT *facetB, realT *maxdistp, realT *mindistp) {
+  vertexT *maxvertex= NULL, *vertex, **vertexp;
+  coordT dist, maxdist= -REALmax, mindist= REALmax;
+
+  qh->vertex_visit++;
+  FOREACHvertex_(facetB->vertices)
+    vertex->visitid= qh->vertex_visit;
+  FOREACHvertex_(facetA->vertices) {
+    if (vertex->visitid != qh->vertex_visit) {
+      vertex->visitid= qh->vertex_visit;
+      zzinc_(Zvertextests);
+      qh_distplane(qh, vertex->point, facetB, &dist);
+      if (!maxvertex) {
+        maxdist= dist;
+        mindist= dist;
+        maxvertex= vertex;
+      }else if (dist > maxdist) {
+        maxdist= dist;
+        maxvertex= vertex;
+      }else if (dist < mindist)
+        mindist= dist;
+    }
+  }
+  if (!maxvertex) {
+    trace3((qh, qh->ferr, 3067, "qh_furthestvertex: all vertices of f%d are in f%d.  Returning 0.0 for max and mindist\n",
+      facetA->id, facetB->id));
+    maxdist= mindist= 0.0;
+  }else {
+    trace4((qh, qh->ferr, 4084, "qh_furthestvertex: v%d dist %2.2g is furthest (mindist %2.2g) of f%d above f%d\n",
+      maxvertex->id, maxdist, mindist, facetA->id, facetB->id));
+  }
+  *maxdistp= maxdist;
+  *mindistp= mindist;
+  return maxvertex;
+} /* furthestvertex */
+
+/*---------------------------------
+
+  qh_getarea(qh, facetlist )
+    set area of all facets in facetlist
+    collect statistics
+    nop if hasAreaVolume
+
+  returns:
+    sets qh->totarea/totvol to total area and volume of convex hull
+    for Delaunay triangulation, computes projected area of the lower or upper hull
+      ignores upper hull if qh->ATinfinity
+
+  notes:
+    could compute outer volume by expanding facet area by rays from interior
+    the following attempt at perpendicular projection underestimated badly:
+      qh.totoutvol += (-dist + facet->maxoutside + qh->DISTround)
+                            * area/ qh->hull_dim;
+  design:
+    for each facet on facetlist
+      compute facet->area
+      update qh.totarea and qh.totvol
+*/
+void qh_getarea(qhT *qh, facetT *facetlist) {
+  realT area;
+  realT dist;
+  facetT *facet;
+
+  if (qh->hasAreaVolume)
+    return;
+  if (qh->REPORTfreq)
+    qh_fprintf(qh, qh->ferr, 8020, "computing area of each facet and volume of the convex hull\n");
+  else
+    trace1((qh, qh->ferr, 1001, "qh_getarea: computing area for each facet and its volume to qh.interior_point (dist*area/dim)\n"));
+  qh->totarea= qh->totvol= 0.0;
+  FORALLfacet_(facetlist) {
+    if (!facet->normal)
+      continue;
+    if (facet->upperdelaunay && qh->ATinfinity)
+      continue;
+    if (!facet->isarea) {
+      facet->f.area= qh_facetarea(qh, facet);
+      facet->isarea= True;
+    }
+    area= facet->f.area;
+    if (qh->DELAUNAY) {
+      if (facet->upperdelaunay == qh->UPPERdelaunay)
+        qh->totarea += area;
+    }else {
+      qh->totarea += area;
+      qh_distplane(qh, qh->interior_point, facet, &dist);
+      qh->totvol += -dist * area/ qh->hull_dim;
+    }
+    if (qh->PRINTstatistics) {
+      wadd_(Wareatot, area);
+      wmax_(Wareamax, area);
+      wmin_(Wareamin, area);
+    }
+  }
+  qh->hasAreaVolume= True;
+} /* getarea */
+
+/*---------------------------------
+
+  qh_gram_schmidt(qh, dim, row )
+    implements Gram-Schmidt orthogonalization by rows
+
+  returns:
+    false if zero norm
+    overwrites rows[dim][dim]
+
+  notes:
+    see Golub & van Loan, 1983, Algorithm 6.2-2, "Modified Gram-Schmidt"
+    overflow due to small divisors not handled
+
+  design:
+    for each row
+      compute norm for row
+      if non-zero, normalize row
+      for each remaining rowA
+        compute inner product of row and rowA
+        reduce rowA by row * inner product
+*/
+boolT qh_gram_schmidt(qhT *qh, int dim, realT **row) {
+  realT *rowi, *rowj, norm;
+  int i, j, k;
+
+  for (i=0; i < dim; i++) {
+    rowi= row[i];
+    for (norm=0.0, k=dim; k--; rowi++)
+      norm += *rowi * *rowi;
+    norm= sqrt(norm);
+    wmin_(Wmindenom, norm);
+    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
+      return False;
+    for (k=dim; k--; )
+      *(--rowi) /= norm;
+    for (j=i+1; j < dim; j++) {
+      rowj= row[j];
+      for (norm=0.0, k=dim; k--; )
+        norm += *rowi++ * *rowj++;
+      for (k=dim; k--; )
+        *(--rowj) -= *(--rowi) * norm;
+    }
+  }
+  return True;
+} /* gram_schmidt */
+
+
+/*---------------------------------
+
+  qh_inthresholds(qh, normal, angle )
+    return True if normal within qh.lower_/upper_threshold
+
+  returns:
+    estimate of angle by summing of threshold diffs
+      angle may be NULL
+      smaller "angle" is better
+
+  notes:
+    invalid if qh.SPLITthresholds
+
+  see:
+    qh.lower_threshold in qh_initbuild()
+    qh_initthresholds()
+
+  design:
+    for each dimension
+      test threshold
+*/
+boolT qh_inthresholds(qhT *qh, coordT *normal, realT *angle) {
+  boolT within= True;
+  int k;
+  realT threshold;
+
+  if (angle)
+    *angle= 0.0;
+  for (k=0; k < qh->hull_dim; k++) {
+    threshold= qh->lower_threshold[k];
+    if (threshold > -REALmax/2) {
+      if (normal[k] < threshold)
+        within= False;
+      if (angle) {
+        threshold -= normal[k];
+        *angle += fabs_(threshold);
+      }
+    }
+    if (qh->upper_threshold[k] < REALmax/2) {
+      threshold= qh->upper_threshold[k];
+      if (normal[k] > threshold)
+        within= False;
+      if (angle) {
+        threshold -= normal[k];
+        *angle += fabs_(threshold);
+      }
+    }
+  }
+  return within;
+} /* inthresholds */
+
+
+/*---------------------------------
+
+  qh_joggleinput(qh)
+    randomly joggle input to Qhull by qh.JOGGLEmax
+    initial input is qh.first_point/qh.num_points of qh.hull_dim
+      repeated calls use qh.input_points/qh.num_points
+
+  returns:
+    joggles points at qh.first_point/qh.num_points
+    copies data to qh.input_points/qh.input_malloc if first time
+    determines qh.JOGGLEmax if it was zero
+    if qh.DELAUNAY
+      computes the Delaunay projection of the joggled points
+
+  notes:
+    if qh.DELAUNAY, unnecessarily joggles the last coordinate
+    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
+
+  design:
+    if qh.DELAUNAY
+      set qh.SCALElast for reduced precision errors
+    if first call
+      initialize qh.input_points to the original input points
+      if qh.JOGGLEmax == 0
+        determine default qh.JOGGLEmax
+    else
+      increase qh.JOGGLEmax according to qh.build_cnt
+    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
+    if qh.DELAUNAY
+      sets the Delaunay projection
+*/
+void qh_joggleinput(qhT *qh) {
+  int i, seed, size;
+  coordT *coordp, *inputp;
+  realT randr, randa, randb;
+
+  if (!qh->input_points) { /* first call */
+    qh->input_points= qh->first_point;
+    qh->input_malloc= qh->POINTSmalloc;
+    size= qh->num_points * qh->hull_dim * (int)sizeof(coordT);
+    if (!(qh->first_point= (coordT *)qh_malloc((size_t)size))) {
+      qh_fprintf(qh, qh->ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
+          qh->num_points);
+      qh_errexit(qh, qh_ERRmem, NULL, NULL);
+    }
+    qh->POINTSmalloc= True;
+    if (qh->JOGGLEmax == 0.0) {
+      qh->JOGGLEmax= qh_detjoggle(qh, qh->input_points, qh->num_points, qh->hull_dim);
+      qh_option(qh, "QJoggle", NULL, &qh->JOGGLEmax);
+    }
+  }else {                 /* repeated call */
+    if (!qh->RERUN && qh->build_cnt > qh_JOGGLEretry) {
+      if (((qh->build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
+        realT maxjoggle= qh->MAXwidth * qh_JOGGLEmaxincrease;
+        if (qh->JOGGLEmax < maxjoggle) {
+          qh->JOGGLEmax *= qh_JOGGLEincrease;
+          minimize_(qh->JOGGLEmax, maxjoggle);
+        }
+      }
+    }
+    qh_option(qh, "QJoggle", NULL, &qh->JOGGLEmax);
+  }
+  if (qh->build_cnt > 1 && qh->JOGGLEmax > fmax_(qh->MAXwidth/4, 0.1)) {
+      qh_fprintf(qh, qh->ferr, 6010, "qhull input error (qh_joggleinput): the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
+                qh->JOGGLEmax);
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  /* for some reason, using qh->ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
+  seed= qh_RANDOMint;
+  qh_option(qh, "_joggle-seed", &seed, NULL);
+  trace0((qh, qh->ferr, 6, "qh_joggleinput: joggle input by %4.4g with seed %d\n",
+    qh->JOGGLEmax, seed));
+  inputp= qh->input_points;
+  coordp= qh->first_point;
+  randa= 2.0 * qh->JOGGLEmax/qh_RANDOMmax;
+  randb= -qh->JOGGLEmax;
+  size= qh->num_points * qh->hull_dim;
+  for (i=size; i--; ) {
+    randr= qh_RANDOMint;
+    *(coordp++)= *(inputp++) + (randr * randa + randb);
+  }
+  if (qh->DELAUNAY) {
+    qh->last_low= qh->last_high= qh->last_newhigh= REALmax;
+    qh_setdelaunay(qh, qh->hull_dim, qh->num_points, qh->first_point);
+  }
+} /* joggleinput */
+
+/*---------------------------------
+
+  qh_maxabsval( normal, dim )
+    return pointer to maximum absolute value of a dim vector
+    returns NULL if dim=0
+*/
+realT *qh_maxabsval(realT *normal, int dim) {
+  realT maxval= -REALmax;
+  realT *maxp= NULL, *colp, absval;
+  int k;
+
+  for (k=dim, colp= normal; k--; colp++) {
+    absval= fabs_(*colp);
+    if (absval > maxval) {
+      maxval= absval;
+      maxp= colp;
+    }
+  }
+  return maxp;
+} /* maxabsval */
+
+
+/*---------------------------------
+
+  qh_maxmin(qh, points, numpoints, dimension )
+    return max/min points for each dimension
+    determine max and min coordinates
+
+  returns:
+    returns a temporary set of max and min points
+      may include duplicate points. Does not include qh.GOODpoint
+    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
+         qh.MAXlastcoord, qh.MINlastcoord
+    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
+
+  notes:
+    loop duplicated in qh_detjoggle()
+
+  design:
+    initialize global precision variables
+    checks definition of REAL...
+    for each dimension
+      for each point
+        collect maximum and minimum point
+      collect maximum of maximums and minimum of minimums
+      determine qh.NEARzero for Gaussian Elimination
+*/
+setT *qh_maxmin(qhT *qh, pointT *points, int numpoints, int dimension) {
+  int k;
+  realT maxcoord, temp;
+  pointT *minimum, *maximum, *point, *pointtemp;
+  setT *set;
+
+  qh->max_outside= 0.0;
+  qh->MAXabs_coord= 0.0;
+  qh->MAXwidth= -REALmax;
+  qh->MAXsumcoord= 0.0;
+  qh->min_vertex= 0.0;
+  qh->WAScoplanar= False;
+  if (qh->ZEROcentrum)
+    qh->ZEROall_ok= True;
+  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
+  && REALmax > 0.0 && -REALmax < 0.0)
+    ; /* all ok */
+  else {
+    qh_fprintf(qh, qh->ferr, 6011, "qhull error: one or more floating point constants in user_r.h are inconsistent. REALmin %g, -REALmax %g, 0.0, REALepsilon %g, REALmax %g\n",
+          REALmin, -REALmax, REALepsilon, REALmax);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  set= qh_settemp(qh, 2*dimension);
+  trace1((qh, qh->ferr, 8082, "qh_maxmin: dim             min             max           width    nearzero  min-point  max-point\n"));
+  for (k=0; k < dimension; k++) {
+    if (points == qh->GOODpointp)
+      minimum= maximum= points + dimension;
+    else
+      minimum= maximum= points;
+    FORALLpoint_(qh, points, numpoints) {
+      if (point == qh->GOODpointp)
+        continue;
+      if (maximum[k] < point[k])
+        maximum= point;
+      else if (minimum[k] > point[k])
+        minimum= point;
+    }
+    if (k == dimension-1) {
+      qh->MINlastcoord= minimum[k];
+      qh->MAXlastcoord= maximum[k];
+    }
+    if (qh->SCALElast && k == dimension-1)
+      maxcoord= qh->MAXabs_coord;
+    else {
+      maxcoord= fmax_(maximum[k], -minimum[k]);
+      if (qh->GOODpointp) {
+        temp= fmax_(qh->GOODpointp[k], -qh->GOODpointp[k]);
+        maximize_(maxcoord, temp);
+      }
+      temp= maximum[k] - minimum[k];
+      maximize_(qh->MAXwidth, temp);
+    }
+    maximize_(qh->MAXabs_coord, maxcoord);
+    qh->MAXsumcoord += maxcoord;
+    qh_setappend(qh, &set, minimum);
+    qh_setappend(qh, &set, maximum);
+    /* calculation of qh NEARzero is based on Golub & van Loan, 1983,
+       Eq. 4.4-13 for "Gaussian elimination with complete pivoting".
+       Golub & van Loan say that n^3 can be ignored and 10 be used in
+       place of rho */
+    qh->NEARzero[k]= 80 * qh->MAXsumcoord * REALepsilon;
+    trace1((qh, qh->ferr, 8106, "           %3d % 14.8e % 14.8e % 14.8e  %4.4e  p%-9d p%-d\n",
+            k, minimum[k], maximum[k], maximum[k]-minimum[k], qh->NEARzero[k], qh_pointid(qh, minimum), qh_pointid(qh, maximum)));
+    if (qh->SCALElast && k == dimension-1)
+      trace1((qh, qh->ferr, 8107, "           last coordinate scaled to (%4.4g, %4.4g), width %4.4e for option 'Qbb'\n",
+            qh->MAXabs_coord - qh->MAXwidth, qh->MAXabs_coord, qh->MAXwidth));
+  }
+  if (qh->IStracing >= 1)
+    qh_printpoints(qh, qh->ferr, "qh_maxmin: found the max and min points (by dim):", set);
+  return(set);
+} /* maxmin */
+
+/*---------------------------------
+
+  qh_maxouter(qh)
+    return maximum distance from facet to outer plane
+    normally this is qh.max_outside+qh.DISTround
+    does not include qh.JOGGLEmax
+
+  see:
+    qh_outerinner()
+
+  notes:
+    need to add another qh.DISTround if testing actual point with computation
+    see qh_detmaxoutside for a qh_RATIO... target
+
+  for joggle:
+    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
+    need to use Wnewvertexmax since could have a coplanar point for a high
+      facet that is replaced by a low facet
+    need to add qh.JOGGLEmax if testing input points
+*/
+realT qh_maxouter(qhT *qh) {
+  realT dist;
+
+  dist= fmax_(qh->max_outside, qh->DISTround);
+  dist += qh->DISTround;
+  trace4((qh, qh->ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %4.4g, qh.max_outside is %4.4g\n", dist, qh->max_outside));
+  return dist;
+} /* maxouter */
+
+/*---------------------------------
+
+  qh_maxsimplex(qh, dim, maxpoints, points, numpoints, simplex )
+    determines maximum simplex for a set of points
+    maxpoints is the subset of points with a min or max coordinate
+    may start with points already in simplex
+    skips qh.GOODpointp (assumes that it isn't in maxpoints)
+
+  returns:
+    simplex with dim+1 points
+
+  notes:
+    called by qh_initialvertices, qh_detvnorm, and qh_voronoi_center
+    requires qh.MAXwidth to estimate determinate for each vertex
+    assumes at least needed points in points
+    maximizes determinate for x,y,z,w, etc.
+    uses maxpoints as long as determinate is clearly non-zero
+
+  design:
+    initialize simplex with at least two points
+      (find points with max or min x coordinate)
+    create a simplex of dim+1 vertices as follows
+      add point from maxpoints that maximizes the determinate of the point and the simplex vertices  
+      if last point and maxdet/prevdet < qh_RATIOmaxsimplex (3.0e-2)
+        flag maybe_falsenarrow
+      if no maxpoint or maxnearzero or maybe_falsenarrow
+        search all points for maximum determinate
+        early exit if maybe_falsenarrow and !maxnearzero and maxdet > prevdet
+*/
+void qh_maxsimplex(qhT *qh, int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
+  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
+  boolT nearzero, maxnearzero= False, maybe_falsenarrow;
+  int i, sizinit;
+  realT maxdet= -1.0, prevdet= -1.0, det, mincoord= REALmax, maxcoord= -REALmax, mindet, ratio, targetdet;
+
+  if (qh->MAXwidth <= 0.0) {
+    qh_fprintf(qh, qh->ferr, 6421, "qhull internal error (qh_maxsimplex): qh.MAXwidth required for qh_maxsimplex.  Used to estimate determinate\n");
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  sizinit= qh_setsize(qh, *simplex);
+  if (sizinit >= 2) {
+    maxdet= pow(qh->MAXwidth, sizinit - 1);
+  }else {
+    if (qh_setsize(qh, maxpoints) >= 2) {
+      FOREACHpoint_(maxpoints) {
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+        if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }else {
+      FORALLpoint_(qh, points, numpoints) {
+        if (point == qh->GOODpointp)
+          continue;
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+        if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }
+    maxdet= maxcoord - mincoord;
+    qh_setunique(qh, simplex, minx);
+    if (qh_setsize(qh, *simplex) < 2)
+      qh_setunique(qh, simplex, maxx);
+    sizinit= qh_setsize(qh, *simplex);
+    if (sizinit < 2) {
+      qh_joggle_restart(qh, "input has same x coordinate");
+      if (zzval_(Zsetplane) > qh->hull_dim+1) {
+        qh_fprintf(qh, qh->ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center): %d points with the same x coordinate %4.4g\n",
+                 qh_setsize(qh, maxpoints)+numpoints, mincoord);
+        qh_errexit(qh, qh_ERRprec, NULL, NULL);
+      }else {
+        qh_fprintf(qh, qh->ferr, 6013, "qhull input error: input is less than %d-dimensional since all points have the same x coordinate %4.4g\n",
+                 qh->hull_dim, mincoord);
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }
+    }
+  }
+  for (i=sizinit; i < dim+1; i++) {
+    prevdet= maxdet;
+    maxpoint= NULL;
+    maxdet= -1.0;
+    FOREACHpoint_(maxpoints) {
+      if (!qh_setin(*simplex, point) && point != maxpoint) {
+        det= qh_detsimplex(qh, point, *simplex, i, &nearzero); /* retests maxpoints if duplicate or multiple iterations */
+        if ((det= fabs_(det)) > maxdet) {
+          maxdet= det;
+          maxpoint= point;
+          maxnearzero= nearzero;
+        }
+      }
+    }
+    maybe_falsenarrow= False;
+    ratio= 1.0;
+    targetdet= prevdet * qh->MAXwidth;
+    mindet= 10 * qh_RATIOmaxsimplex * targetdet;
+    if (maxdet > 0.0) {
+      ratio= maxdet / targetdet;
+      if (ratio < qh_RATIOmaxsimplex)
+        maybe_falsenarrow= True;
+    }
+    if (!maxpoint || maxnearzero || maybe_falsenarrow) {
+      zinc_(Zsearchpoints);
+      if (!maxpoint) {
+        trace0((qh, qh->ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex, better than mindet %4.4g, targetdet %4.4g\n",
+                i+1, mindet, targetdet));
+      }else if (qh->ALLpoints) {
+        trace0((qh, qh->ferr, 30, "qh_maxsimplex: searching all points ('Qs') for %d-th initial vertex, better than p%d det %4.4g, targetdet %4.4g, ratio %4.4g\n",
+                i+1, qh_pointid(qh, maxpoint), maxdet, targetdet, ratio));
+      }else if (maybe_falsenarrow) {
+        trace0((qh, qh->ferr, 17, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %4.4g and mindet %4.4g, ratio %4.4g\n",
+                i+1, qh_pointid(qh, maxpoint), maxdet, mindet, ratio));
+      }else {
+        trace0((qh, qh->ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g and mindet %4.4g, targetdet %4.4g\n",
+                i+1, qh_pointid(qh, maxpoint), maxdet, mindet, targetdet));
+      }
+      FORALLpoint_(qh, points, numpoints) {
+        if (point == qh->GOODpointp)
+          continue;
+        if (!qh_setin(maxpoints, point) && !qh_setin(*simplex, point)) {
+          det= qh_detsimplex(qh, point, *simplex, i, &nearzero);
+          if ((det= fabs_(det)) > maxdet) {
+            maxdet= det;
+            maxpoint= point;
+            maxnearzero= nearzero;
+            if (!maxnearzero && !qh->ALLpoints && maxdet > mindet)
+              break;
+          }
+        }
+      }
+    } /* !maxpoint */
+    if (!maxpoint) {
+      qh_fprintf(qh, qh->ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+    qh_setappend(qh, simplex, maxpoint);
+    trace1((qh, qh->ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%4.4g, targetdet=%4.4g, mindet=%4.4g\n",
+            qh_pointid(qh, maxpoint), i+1, maxdet, prevdet * qh->MAXwidth, mindet));
+  } /* i */
+} /* maxsimplex */
+
+/*---------------------------------
+
+  qh_minabsval( normal, dim )
+    return minimum absolute value of a dim vector
+*/
+realT qh_minabsval(realT *normal, int dim) {
+  realT minval= 0;
+  realT maxval= 0;
+  realT *colp;
+  int k;
+
+  for (k=dim, colp=normal; k--; colp++) {
+    maximize_(maxval, *colp);
+    minimize_(minval, *colp);
+  }
+  return fmax_(maxval, -minval);
+} /* minabsval */
+
+
+/*---------------------------------
+
+  qh_mindif(qh, vecA, vecB, dim )
+    return index of min abs. difference of two vectors
+*/
+int qh_mindiff(realT *vecA, realT *vecB, int dim) {
+  realT mindiff= REALmax, diff;
+  realT *vecAp= vecA, *vecBp= vecB;
+  int k, mink= 0;
+
+  for (k=0; k < dim; k++) {
+    diff= *vecAp++ - *vecBp++;
+    diff= fabs_(diff);
+    if (diff < mindiff) {
+      mindiff= diff;
+      mink= k;
+    }
+  }
+  return mink;
+} /* mindiff */
+
+
+
+/*---------------------------------
+
+  qh_orientoutside(qh, facet  )
+    make facet outside oriented via qh.interior_point
+
+  returns:
+    True if facet reversed orientation.
+*/
+boolT qh_orientoutside(qhT *qh, facetT *facet) {
+  int k;
+  realT dist;
+
+  qh_distplane(qh, qh->interior_point, facet, &dist);
+  if (dist > 0) {
+    for (k=qh->hull_dim; k--; )
+      facet->normal[k]= -facet->normal[k];
+    facet->offset= -facet->offset;
+    return True;
+  }
+  return False;
+} /* orientoutside */
+
+/*---------------------------------
+
+  qh_outerinner(qh, facet, outerplane, innerplane  )
+    if facet and qh.maxoutdone (i.e., qh_check_maxout)
+      returns outer and inner plane for facet
+    else
+      returns maximum outer and inner plane
+    accounts for qh.JOGGLEmax
+
+  see:
+    qh_maxouter(qh), qh_check_bestdist(), qh_check_points()
+
+  notes:
+    outerplaner or innerplane may be NULL
+    facet is const
+    Does not error (QhullFacet)
+
+    includes qh.DISTround for actual points
+    adds another qh.DISTround if testing with floating point arithmetic
+*/
+void qh_outerinner(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane) {
+  realT dist, mindist;
+  vertexT *vertex, **vertexp;
+
+  if (outerplane) {
+    if (!qh_MAXoutside || !facet || !qh->maxoutdone) {
+      *outerplane= qh_maxouter(qh);       /* includes qh.DISTround */
+    }else { /* qh_MAXoutside ... */
+#if qh_MAXoutside
+      *outerplane= facet->maxoutside + qh->DISTround;
+#endif
+
+    }
+    if (qh->JOGGLEmax < REALmax/2)
+      *outerplane += qh->JOGGLEmax * sqrt((realT)qh->hull_dim);
+  }
+  if (innerplane) {
+    if (facet) {
+      mindist= REALmax;
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdistio);
+        qh_distplane(qh, vertex->point, facet, &dist);
+        minimize_(mindist, dist);
+      }
+      *innerplane= mindist - qh->DISTround;
+    }else
+      *innerplane= qh->min_vertex - qh->DISTround;
+    if (qh->JOGGLEmax < REALmax/2)
+      *innerplane -= qh->JOGGLEmax * sqrt((realT)qh->hull_dim);
+  }
+} /* outerinner */
+
+/*---------------------------------
+
+  qh_pointdist( point1, point2, dim )
+    return distance between two points
+
+  notes:
+    returns distance squared if 'dim' is negative
+*/
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
+  coordT dist, diff;
+  int k;
+
+  dist= 0.0;
+  for (k= (dim > 0 ? dim : -dim); k--; ) {
+    diff= *point1++ - *point2++;
+    dist += diff * diff;
+  }
+  if (dim > 0)
+    return(sqrt(dist));
+  return dist;
+} /* pointdist */
+
+
+/*---------------------------------
+
+  qh_printmatrix(qh, fp, string, rows, numrow, numcol )
+    print matrix to fp given by row vectors
+    print string as header
+    qh may be NULL if fp is defined
+
+  notes:
+    print a vector by qh_printmatrix(qh, fp, "", &vect, 1, len)
+*/
+void qh_printmatrix(qhT *qh, FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
+  realT *rowp;
+  realT r; /*bug fix*/
+  int i,k;
+
+  qh_fprintf(qh, fp, 9001, "%s\n", string);
+  for (i=0; i < numrow; i++) {
+    rowp= rows[i];
+    for (k=0; k < numcol; k++) {
+      r= *rowp++;
+      qh_fprintf(qh, fp, 9002, "%6.3g ", r);
+    }
+    qh_fprintf(qh, fp, 9003, "\n");
+  }
+} /* printmatrix */
+
+
+/*---------------------------------
+
+  qh_printpoints(qh, fp, string, points )
+    print pointids to fp for a set of points
+    if string, prints string and 'p' point ids
+*/
+void qh_printpoints(qhT *qh, FILE *fp, const char *string, setT *points) {
+  pointT *point, **pointp;
+
+  if (string) {
+    qh_fprintf(qh, fp, 9004, "%s", string);
+    FOREACHpoint_(points)
+      qh_fprintf(qh, fp, 9005, " p%d", qh_pointid(qh, point));
+    qh_fprintf(qh, fp, 9006, "\n");
+  }else {
+    FOREACHpoint_(points)
+      qh_fprintf(qh, fp, 9007, " %d", qh_pointid(qh, point));
+    qh_fprintf(qh, fp, 9008, "\n");
+  }
+} /* printpoints */
+
+
+/*---------------------------------
+
+  qh_projectinput(qh)
+    project input points using qh.lower_bound/upper_bound and qh->DELAUNAY
+    if qh.lower_bound[k]=qh.upper_bound[k]= 0,
+      removes dimension k
+    if halfspace intersection
+      removes dimension k from qh.feasible_point
+    input points in qh->first_point, num_points, input_dim
+
+  returns:
+    new point array in qh->first_point of qh->hull_dim coordinates
+    sets qh->POINTSmalloc
+    if qh->DELAUNAY
+      projects points to paraboloid
+      lowbound/highbound is also projected
+    if qh->ATinfinity
+      adds point "at-infinity"
+    if qh->POINTSmalloc
+      frees old point array
+
+  notes:
+    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
+
+
+  design:
+    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
+    determines newdim and newnum for qh->hull_dim and qh->num_points
+    projects points to newpoints
+    projects qh.lower_bound to itself
+    projects qh.upper_bound to itself
+    if qh->DELAUNAY
+      if qh->ATINFINITY
+        projects points to paraboloid
+        computes "infinity" point as vertex average and 10% above all points
+      else
+        uses qh_setdelaunay to project points to paraboloid
+*/
+void qh_projectinput(qhT *qh) {
+  int k,i;
+  int newdim= qh->input_dim, newnum= qh->num_points;
+  signed char *project;
+  int projectsize= (qh->input_dim + 1) * (int)sizeof(*project);
+  pointT *newpoints, *coord, *infinity;
+  realT paraboloid, maxboloid= 0;
+
+  project= (signed char *)qh_memalloc(qh, projectsize);
+  memset((char *)project, 0, (size_t)projectsize);
+  for (k=0; k < qh->input_dim; k++) {   /* skip Delaunay bound */
+    if (qh->lower_bound[k] == 0.0 && qh->upper_bound[k] == 0.0) {
+      project[k]= -1;
+      newdim--;
+    }
+  }
+  if (qh->DELAUNAY) {
+    project[k]= 1;
+    newdim++;
+    if (qh->ATinfinity)
+      newnum++;
+  }
+  if (newdim != qh->hull_dim) {
+    qh_memfree(qh, project, projectsize);
+    qh_fprintf(qh, qh->ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh->hull_dim);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (!(newpoints= qh->temp_malloc= (coordT *)qh_malloc((size_t)(newnum * newdim) * sizeof(coordT)))) {
+    qh_memfree(qh, project, projectsize);
+    qh_fprintf(qh, qh->ferr, 6016, "qhull error: insufficient memory to project %d points\n",
+           qh->num_points);
+    qh_errexit(qh, qh_ERRmem, NULL, NULL);
+  }
+  /* qh_projectpoints throws error if mismatched dimensions */
+  qh_projectpoints(qh, project, qh->input_dim+1, qh->first_point,
+                    qh->num_points, qh->input_dim, newpoints, newdim);
+  trace1((qh, qh->ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
+  qh_projectpoints(qh, project, qh->input_dim+1, qh->lower_bound,
+                    1, qh->input_dim+1, qh->lower_bound, newdim+1);
+  qh_projectpoints(qh, project, qh->input_dim+1, qh->upper_bound,
+                    1, qh->input_dim+1, qh->upper_bound, newdim+1);
+  if (qh->HALFspace) {
+    if (!qh->feasible_point) {
+      qh_memfree(qh, project, projectsize);
+      qh_fprintf(qh, qh->ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+    qh_projectpoints(qh, project, qh->input_dim, qh->feasible_point,
+                      1, qh->input_dim, qh->feasible_point, newdim);
+  }
+  qh_memfree(qh, project, projectsize);
+  if (qh->POINTSmalloc)
+    qh_free(qh->first_point);
+  qh->first_point= newpoints;
+  qh->POINTSmalloc= True;
+  qh->temp_malloc= NULL;
+  if (qh->DELAUNAY && qh->ATinfinity) {
+    coord= qh->first_point;
+    infinity= qh->first_point + qh->hull_dim * qh->num_points;
+    for (k=qh->hull_dim-1; k--; )
+      infinity[k]= 0.0;
+    for (i=qh->num_points; i--; ) {
+      paraboloid= 0.0;
+      for (k=0; k < qh->hull_dim-1; k++) {
+        paraboloid += *coord * *coord;
+        infinity[k] += *coord;
+        coord++;
+      }
+      *(coord++)= paraboloid;
+      maximize_(maxboloid, paraboloid);
+    }
+    /* coord == infinity */
+    for (k=qh->hull_dim-1; k--; )
+      *(coord++) /= qh->num_points;
+    *(coord++)= maxboloid * 1.1;
+    qh->num_points++;
+    trace0((qh, qh->ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
+  }else if (qh->DELAUNAY)  /* !qh->ATinfinity */
+    qh_setdelaunay(qh, qh->hull_dim, qh->num_points, qh->first_point);
+} /* projectinput */
+
+
+/*---------------------------------
+
+  qh_projectpoints(qh, project, n, points, numpoints, dim, newpoints, newdim )
+    project points/numpoints/dim to newpoints/newdim
+    if project[k] == -1
+      delete dimension k
+    if project[k] == 1
+      add dimension k by duplicating previous column
+    n is size of project
+
+  notes:
+    newpoints may be points if only adding dimension at end
+
+  design:
+    check that 'project' and 'newdim' agree
+    for each dimension
+      if project == -1
+        skip dimension
+      else
+        determine start of column in newpoints
+        determine start of column in points
+          if project == +1, duplicate previous column
+        copy dimension (column) from points to newpoints
+*/
+void qh_projectpoints(qhT *qh, signed char *project, int n, realT *points,
+        int numpoints, int dim, realT *newpoints, int newdim) {
+  int testdim= dim, oldk=0, newk=0, i,j=0,k;
+  realT *newp, *oldp;
+
+  for (k=0; k < n; k++)
+    testdim += project[k];
+  if (testdim != newdim) {
+    qh_fprintf(qh, qh->ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
+      newdim, testdim);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  for (j=0; j= dim)
+          continue;
+        oldp= points+oldk;
+      }else
+        oldp= points+oldk++;
+      for (i=numpoints; i--; ) {
+        *newp= *oldp;
+        newp += newdim;
+        oldp += dim;
+      }
+    }
+    if (oldk >= dim)
+      break;
+  }
+  trace1((qh, qh->ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
+    numpoints, dim, newdim));
+} /* projectpoints */
+
+
+/*---------------------------------
+
+  qh_rotateinput(qh, rows )
+    rotate input using row matrix
+    input points given by qh->first_point, num_points, hull_dim
+    assumes rows[dim] is a scratch buffer
+    if qh->POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    rotated input
+    sets qh->POINTSmalloc
+
+  design:
+    see qh_rotatepoints
+*/
+void qh_rotateinput(qhT *qh, realT **rows) {
+
+  if (!qh->POINTSmalloc) {
+    qh->first_point= qh_copypoints(qh, qh->first_point, qh->num_points, qh->hull_dim);
+    qh->POINTSmalloc= True;
+  }
+  qh_rotatepoints(qh, qh->first_point, qh->num_points, qh->hull_dim, rows);
+}  /* rotateinput */
+
+/*---------------------------------
+
+  qh_rotatepoints(qh, points, numpoints, dim, row )
+    rotate numpoints points by a d-dim row matrix
+    assumes rows[dim] is a scratch buffer
+
+  returns:
+    rotated points in place
+
+  design:
+    for each point
+      for each coordinate
+        use row[dim] to compute partial inner product
+      for each coordinate
+        rotate by partial inner product
+*/
+void qh_rotatepoints(qhT *qh, realT *points, int numpoints, int dim, realT **row) {
+  realT *point, *rowi, *coord= NULL, sum, *newval;
+  int i,j,k;
+
+  if (qh->IStracing >= 1)
+    qh_printmatrix(qh, qh->ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
+  for (point=points, j=numpoints; j--; point += dim) {
+    newval= row[dim];
+    for (i=0; i < dim; i++) {
+      rowi= row[i];
+      coord= point;
+      for (sum=0.0, k=dim; k--; )
+        sum += *rowi++ * *coord++;
+      *(newval++)= sum;
+    }
+    for (k=dim; k--; )
+      *(--coord)= *(--newval);
+  }
+} /* rotatepoints */
+
+
+/*---------------------------------
+
+  qh_scaleinput(qh)
+    scale input points using qh->low_bound/high_bound
+    input points given by qh->first_point, num_points, hull_dim
+    if qh->POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    scales coordinates of points to low_bound[k], high_bound[k]
+    sets qh->POINTSmalloc
+
+  design:
+    see qh_scalepoints
+*/
+void qh_scaleinput(qhT *qh) {
+
+  if (!qh->POINTSmalloc) {
+    qh->first_point= qh_copypoints(qh, qh->first_point, qh->num_points, qh->hull_dim);
+    qh->POINTSmalloc= True;
+  }
+  qh_scalepoints(qh, qh->first_point, qh->num_points, qh->hull_dim,
+       qh->lower_bound, qh->upper_bound);
+}  /* scaleinput */
+
+/*---------------------------------
+
+  qh_scalelast(qh, points, numpoints, dim, low, high, newhigh )
+    scale last coordinate to [0.0, newhigh], for Delaunay triangulation
+    input points given by points, numpoints, dim
+
+  returns:
+    changes scale of last coordinate from [low, high] to [0.0, newhigh]
+    overwrites last coordinate of each point
+    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
+
+  notes:
+    to reduce precision issues, qh_scalelast makes the last coordinate similar to other coordinates
+      the last coordinate for Delaunay triangulation is the sum of squares of input coordinates
+      note that the range [0.0, newwidth] is wrong for narrow distributions with large positive coordinates (e.g., [995933.64, 995963.48])
+
+    when called by qh_setdelaunay, low/high may not match the data passed to qh_setdelaunay
+
+  design:
+    compute scale and shift factors
+    apply to last coordinate of each point
+*/
+void qh_scalelast(qhT *qh, coordT *points, int numpoints, int dim, coordT low,
+                   coordT high, coordT newhigh) {
+  realT scale, shift;
+  coordT *coord, newlow;
+  int i;
+  boolT nearzero= False;
+
+  newlow= 0.0;
+  trace4((qh, qh->ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [%2.2g, %2.2g]\n",
+    low, high, newlow, newhigh));
+  qh->last_low= low;
+  qh->last_high= high;
+  qh->last_newhigh= newhigh;
+  scale= qh_divzero(newhigh - newlow, high - low,
+                  qh->MINdenom_1, &nearzero);
+  if (nearzero) {
+    if (qh->DELAUNAY)
+      qh_fprintf(qh, qh->ferr, 6019, "qhull input error (qh_scalelast): can not scale last coordinate to [%4.4g, %4.4g].  Input is cocircular or cospherical.   Use option 'Qz' to add a point at infinity.\n",
+             newlow, newhigh);
+    else
+      qh_fprintf(qh, qh->ferr, 6020, "qhull input error (qh_scalelast): can not scale last coordinate to [%4.4g, %4.4g].  New bounds are too wide for compared to existing bounds [%4.4g, %4.4g] (width %4.4g)\n",
+             newlow, newhigh, low, high, high-low);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  shift= newlow - low * scale;
+  coord= points + dim - 1;
+  for (i=numpoints; i--; coord += dim)
+    *coord= *coord * scale + shift;
+} /* scalelast */
+
+/*---------------------------------
+
+  qh_scalepoints(qh, points, numpoints, dim, newlows, newhighs )
+    scale points to new lowbound and highbound
+    retains old bound when newlow= -REALmax or newhigh= +REALmax
+
+  returns:
+    scaled points
+    overwrites old points
+
+  design:
+    for each coordinate
+      compute current low and high bound
+      compute scale and shift factors
+      scale all points
+      enforce new low and high bound for all points
+*/
+void qh_scalepoints(qhT *qh, pointT *points, int numpoints, int dim,
+        realT *newlows, realT *newhighs) {
+  int i,k;
+  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
+  boolT nearzero= False;
+
+  for (k=0; k < dim; k++) {
+    newhigh= newhighs[k];
+    newlow= newlows[k];
+    if (newhigh > REALmax/2 && newlow < -REALmax/2)
+      continue;
+    low= REALmax;
+    high= -REALmax;
+    for (i=numpoints, coord=points+k; i--; coord += dim) {
+      minimize_(low, *coord);
+      maximize_(high, *coord);
+    }
+    if (newhigh > REALmax/2)
+      newhigh= high;
+    if (newlow < -REALmax/2)
+      newlow= low;
+    if (qh->DELAUNAY && k == dim-1 && newhigh < newlow) {
+      qh_fprintf(qh, qh->ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
+               k, k, newhigh, newlow);
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    scale= qh_divzero(newhigh - newlow, high - low,
+                  qh->MINdenom_1, &nearzero);
+    if (nearzero) {
+      qh_fprintf(qh, qh->ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
+              k, newlow, newhigh, low, high);
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    shift= (newlow * high - low * newhigh)/(high-low);
+    coord= points+k;
+    for (i=numpoints; i--; coord += dim)
+      *coord= *coord * scale + shift;
+    coord= points+k;
+    if (newlow < newhigh) {
+      mincoord= newlow;
+      maxcoord= newhigh;
+    }else {
+      mincoord= newhigh;
+      maxcoord= newlow;
+    }
+    for (i=numpoints; i--; coord += dim) {
+      minimize_(*coord, maxcoord);  /* because of roundoff error */
+      maximize_(*coord, mincoord);
+    }
+    trace0((qh, qh->ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
+      k, low, high, newlow, newhigh, numpoints, scale, shift));
+  }
+} /* scalepoints */
+
+
+/*---------------------------------
+
+  qh_setdelaunay(qh, dim, count, points )
+    project count points to dim-d paraboloid for Delaunay triangulation
+
+    dim is one more than the dimension of the input set
+    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
+
+    points is a dim*count realT array.  The first dim-1 coordinates
+    are the coordinates of the first input point.  array[dim] is
+    the first coordinate of the second input point.  array[2*dim] is
+    the first coordinate of the third input point.
+
+    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
+      calls qh_scalelast to scale the last coordinate the same as the other points
+
+  returns:
+    for each point
+      sets point[dim-1] to sum of squares of coordinates
+    scale points to 'Qbb' if needed
+
+  notes:
+    to project one point, use
+      qh_setdelaunay(qh, qh->hull_dim, 1, point)
+
+    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
+    the coordinates after the original projection.
+
+*/
+void qh_setdelaunay(qhT *qh, int dim, int count, pointT *points) {
+  int i, k;
+  coordT *coordp, coord;
+  realT paraboloid;
+
+  trace0((qh, qh->ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
+  coordp= points;
+  for (i=0; i < count; i++) {
+    coord= *coordp++;
+    paraboloid= coord*coord;
+    for (k=dim-2; k--; ) {
+      coord= *coordp++;
+      paraboloid += coord*coord;
+    }
+    *coordp++= paraboloid;
+  }
+  if (qh->last_low < REALmax/2)
+    qh_scalelast(qh, points, count, dim, qh->last_low, qh->last_high, qh->last_newhigh);
+} /* setdelaunay */
+
+
+/*---------------------------------
+
+  qh_sethalfspace(qh, dim, coords, nextp, normal, offset, feasible )
+    set point to dual of halfspace relative to feasible point
+    halfspace is normal coefficients and offset.
+
+  returns:
+    false and prints error if feasible point is outside of hull
+    overwrites coordinates for point at dim coords
+    nextp= next point (coords)
+    does not call qh_errexit
+
+  design:
+    compute distance from feasible point to halfspace
+    divide each normal coefficient by -dist
+*/
+boolT qh_sethalfspace(qhT *qh, int dim, coordT *coords, coordT **nextp,
+         coordT *normal, coordT *offset, coordT *feasible) {
+  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
+  realT dist;
+  realT r; /*bug fix*/
+  int k;
+  boolT zerodiv;
+
+  dist= *offset;
+  for (k=dim; k--; )
+    dist += *(normp++) * *(feasiblep++);
+  if (dist > 0)
+    goto LABELerroroutside;
+  normp= normal;
+  if (dist < -qh->MINdenom) {
+    for (k=dim; k--; )
+      *(coordp++)= *(normp++) / -dist;
+  }else {
+    for (k=dim; k--; ) {
+      *(coordp++)= qh_divzero(*(normp++), -dist, qh->MINdenom_1, &zerodiv);
+      if (zerodiv)
+        goto LABELerroroutside;
+    }
+  }
+  *nextp= coordp;
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 4) {
+    qh_fprintf(qh, qh->ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
+    for (k=dim, coordp=coords; k--; ) {
+      r= *coordp++;
+      qh_fprintf(qh, qh->ferr, 8022, " %6.2g", r);
+    }
+    qh_fprintf(qh, qh->ferr, 8023, "\n");
+  }
+#endif
+  return True;
+LABELerroroutside:
+  feasiblep= feasible;
+  normp= normal;
+  qh_fprintf(qh, qh->ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
+  for (k=dim; k--; )
+    qh_fprintf(qh, qh->ferr, 8024, qh_REAL_1, r=*(feasiblep++));
+  qh_fprintf(qh, qh->ferr, 8025, "\n     halfspace: ");
+  for (k=dim; k--; )
+    qh_fprintf(qh, qh->ferr, 8026, qh_REAL_1, r=*(normp++));
+  qh_fprintf(qh, qh->ferr, 8027, "\n     at offset: ");
+  qh_fprintf(qh, qh->ferr, 8028, qh_REAL_1, *offset);
+  qh_fprintf(qh, qh->ferr, 8029, " and distance: ");
+  qh_fprintf(qh, qh->ferr, 8030, qh_REAL_1, dist);
+  qh_fprintf(qh, qh->ferr, 8031, "\n");
+  return False;
+} /* sethalfspace */
+
+/*---------------------------------
+
+  qh_sethalfspace_all(qh, dim, count, halfspaces, feasible )
+    generate dual for halfspace intersection with feasible point
+    array of count halfspaces
+      each halfspace is normal coefficients followed by offset
+      the origin is inside the halfspace if the offset is negative
+    feasible is a point inside all halfspaces (http://www.qhull.org/html/qhalf.htm#notes)
+
+  returns:
+    malloc'd array of count X dim-1 points
+
+  notes:
+    call before qh_init_B or qh_initqhull_globals
+    free memory when done
+    unused/untested code: please email bradb@shore.net if this works ok for you
+    if using option 'Fp', qh.feasible_point must be set (e.g., to 'feasible')
+    qh->feasible_point is a malloc'd array that is freed by qh_freebuffers.
+
+  design:
+    see qh_sethalfspace
+*/
+coordT *qh_sethalfspace_all(qhT *qh, int dim, int count, coordT *halfspaces, pointT *feasible) {
+  int i, newdim;
+  pointT *newpoints;
+  coordT *coordp, *normalp, *offsetp;
+
+  trace0((qh, qh->ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
+  newdim= dim - 1;
+  if (!(newpoints= (coordT *)qh_malloc((size_t)(count * newdim) * sizeof(coordT)))){
+    qh_fprintf(qh, qh->ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
+          count);
+    qh_errexit(qh, qh_ERRmem, NULL, NULL);
+  }
+  coordp= newpoints;
+  normalp= halfspaces;
+  for (i=0; i < count; i++) {
+    offsetp= normalp + newdim;
+    if (!qh_sethalfspace(qh, newdim, coordp, &coordp, normalp, offsetp, feasible)) {
+      qh_free(newpoints);  /* feasible is not inside halfspace as reported by qh_sethalfspace */
+      qh_fprintf(qh, qh->ferr, 8032, "The halfspace was at index %d\n", i);
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    normalp= offsetp + 1;
+  }
+  return newpoints;
+} /* sethalfspace_all */
+
+
+/*---------------------------------
+
+  qh_sharpnewfacets(qh)
+
+  returns:
+    true if could be an acute angle (facets in different quadrants)
+
+  notes:
+    for qh_findbest
+
+  design:
+    for all facets on qh.newfacet_list
+      if two facets are in different quadrants
+        set issharp
+*/
+boolT qh_sharpnewfacets(qhT *qh) {
+  facetT *facet;
+  boolT issharp= False;
+  int *quadrant, k;
+
+  quadrant= (int *)qh_memalloc(qh, qh->hull_dim * (int)sizeof(int));
+  FORALLfacet_(qh->newfacet_list) {
+    if (facet == qh->newfacet_list) {
+      for (k=qh->hull_dim; k--; )
+        quadrant[ k]= (facet->normal[ k] > 0);
+    }else {
+      for (k=qh->hull_dim; k--; ) {
+        if (quadrant[ k] != (facet->normal[ k] > 0)) {
+          issharp= True;
+          break;
+        }
+      }
+    }
+    if (issharp)
+      break;
+  }
+  qh_memfree(qh, quadrant, qh->hull_dim * (int)sizeof(int));
+  trace3((qh, qh->ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
+  return issharp;
+} /* sharpnewfacets */
+
+/*---------------------------------
+
+  qh_vertex_bestdist(qh, vertices )
+  qh_vertex_bestdist2(qh, vertices, vertexp, vertexp2 )
+    return nearest distance between vertices
+    optionally returns vertex and vertex2
+
+  notes:
+    called by qh_partitioncoplanar, qh_mergefacet, qh_check_maxout, qh_checkpoint
+*/
+coordT qh_vertex_bestdist(qhT *qh, setT *vertices) {
+  vertexT *vertex, *vertex2;
+
+  return qh_vertex_bestdist2(qh, vertices, &vertex, &vertex2);
+} /* vertex_bestdist */
+
+coordT qh_vertex_bestdist2(qhT *qh, setT *vertices, vertexT **vertexp/*= NULL*/, vertexT **vertexp2/*= NULL*/) {
+  vertexT *vertex, *vertexA, *bestvertex= NULL, *bestvertex2= NULL;
+  coordT dist, bestdist= REALmax;
+  int k, vertex_i, vertex_n;
+
+  FOREACHvertex_i_(qh, vertices) {
+    for (k= vertex_i+1; k < vertex_n; k++) {
+      vertexA= SETelemt_(vertices, k, vertexT);
+      dist= qh_pointdist(vertex->point, vertexA->point, -qh->hull_dim);
+      if (dist < bestdist) {
+        bestdist= dist;
+        bestvertex= vertex;
+        bestvertex2= vertexA;
+      }
+    }
+  }
+  *vertexp= bestvertex;
+  *vertexp2= bestvertex2;
+  return sqrt(bestdist);
+} /* vertex_bestdist */
+
+/*---------------------------------
+
+  qh_voronoi_center(qh, dim, points )
+    return Voronoi center for a set of points
+    dim is the original dimension of the points
+    gh.gm_matrix/qh.gm_row are scratch buffers
+
+  returns:
+    center as a temporary point (qh_memalloc)
+    if non-simplicial,
+      returns center for max simplex of points
+
+  notes:
+    only called by qh_facetcenter
+    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
+
+  design:
+    if non-simplicial
+      determine max simplex for points
+    translate point0 of simplex to origin
+    compute sum of squares of diagonal
+    compute determinate
+    compute Voronoi center (see Bowyer & Woodwark)
+*/
+pointT *qh_voronoi_center(qhT *qh, int dim, setT *points) {
+  pointT *point, **pointp, *point0;
+  pointT *center= (pointT *)qh_memalloc(qh, qh->center_size);
+  setT *simplex;
+  int i, j, k, size= qh_setsize(qh, points);
+  coordT *gmcoord;
+  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
+  boolT nearzero, infinite;
+
+  if (size == dim+1)
+    simplex= points;
+  else if (size < dim+1) {
+    qh_memfree(qh, center, qh->center_size);
+    qh_fprintf(qh, qh->ferr, 6025, "qhull internal error (qh_voronoi_center):  need at least %d points to construct a Voronoi center\n",
+             dim+1);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    simplex= points;  /* never executed -- avoids warning */
+  }else {
+    simplex= qh_settemp(qh, dim+1);
+    qh_maxsimplex(qh, dim, points, NULL, 0, &simplex);
+  }
+  point0= SETfirstt_(simplex, pointT);
+  gmcoord= qh->gm_matrix;
+  for (k=0; k < dim; k++) {
+    qh->gm_row[k]= gmcoord;
+    FOREACHpoint_(simplex) {
+      if (point != point0)
+        *(gmcoord++)= point[k] - point0[k];
+    }
+  }
+  sum2row= gmcoord;
+  for (i=0; i < dim; i++) {
+    sum2= 0.0;
+    for (k=0; k < dim; k++) {
+      diffp= qh->gm_row[k] + i;
+      sum2 += *diffp * *diffp;
+    }
+    *(gmcoord++)= sum2;
+  }
+  det= qh_determinant(qh, qh->gm_row, dim, &nearzero);
+  factor= qh_divzero(0.5, det, qh->MINdenom, &infinite);
+  if (infinite) {
+    for (k=dim; k--; )
+      center[k]= qh_INFINITE;
+    if (qh->IStracing)
+      qh_printpoints(qh, qh->ferr, "qh_voronoi_center: at infinity for ", simplex);
+  }else {
+    for (i=0; i < dim; i++) {
+      gmcoord= qh->gm_matrix;
+      sum2p= sum2row;
+      for (k=0; k < dim; k++) {
+        qh->gm_row[k]= gmcoord;
+        if (k == i) {
+          for (j=dim; j--; )
+            *(gmcoord++)= *sum2p++;
+        }else {
+          FOREACHpoint_(simplex) {
+            if (point != point0)
+              *(gmcoord++)= point[k] - point0[k];
+          }
+        }
+      }
+      center[i]= qh_determinant(qh, qh->gm_row, dim, &nearzero)*factor + point0[i];
+    }
+#ifndef qh_NOtrace
+    if (qh->IStracing >= 3) {
+      qh_fprintf(qh, qh->ferr, 3061, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
+      qh_printmatrix(qh, qh->ferr, "center:", ¢er, 1, dim);
+      if (qh->IStracing >= 5) {
+        qh_printpoints(qh, qh->ferr, "points", simplex);
+        FOREACHpoint_(simplex)
+          qh_fprintf(qh, qh->ferr, 8034, "p%d dist %.2g, ", qh_pointid(qh, point),
+                   qh_pointdist(point, center, dim));
+        qh_fprintf(qh, qh->ferr, 8035, "\n");
+      }
+    }
+#endif
+  }
+  if (simplex != points)
+    qh_settempfree(qh, &simplex);
+  return center;
+} /* voronoi_center */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.c
new file mode 100644
index 00000000000..22faead499f
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.c
@@ -0,0 +1,1284 @@
+/*
  ---------------------------------
+
+   geom_r.c
+   geometric routines of qhull
+
+   see qh-geom_r.htm and geom_r.h
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/geom_r.c#5 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+
+   infrequent code goes into geom2_r.c
+*/
+
+#include "qhull_ra.h"
+
+/*---------------------------------
+
+  qh_distplane(qh, point, facet, dist )
+    return distance from point to facet
+
+  returns:
+    dist
+    if qh.RANDOMdist, joggles result
+
+  notes:
+    dist > 0 if point is above facet (i.e., outside)
+    does not error (for qh_sortfacets, qh_outerinner)
+    for nearly coplanar points, the returned values may be duplicates
+      for example pairs of nearly incident points, rbox 175 C1,2e-13 t1538759579 | qhull d T4
+      622 qh_distplane: e-014  # count of two or more duplicate values for unique calls
+      258 qh_distplane: e-015
+      38 qh_distplane: e-016
+      40 qh_distplane: e-017
+      6 qh_distplane: e-018
+      5 qh_distplane: -e-018
+      33 qh_distplane: -e-017
+         3153 qh_distplane: -2.775557561562891e-017  # duplicated value for 3153 unique calls
+      42 qh_distplane: -e-016
+      307 qh_distplane: -e-015
+      1271 qh_distplane: -e-014
+      13 qh_distplane: -e-013
+
+  see:
+    qh_distnorm in geom2_r.c
+    qh_distplane [geom_r.c], QhullFacet::distance, and QhullHyperplane::distance are copies
+*/
+void qh_distplane(qhT *qh, pointT *point, facetT *facet, realT *dist) {
+  coordT *normal= facet->normal, *coordp, randr;
+  int k;
+
+  switch (qh->hull_dim){
+  case 2:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
+    break;
+  case 3:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
+    break;
+  case 4:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
+    break;
+  case 5:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
+    break;
+  case 6:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
+    break;
+  case 7:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
+    break;
+  case 8:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
+    break;
+  default:
+    *dist= facet->offset;
+    coordp= point;
+    for (k=qh->hull_dim; k--; )
+      *dist += *coordp++ * *normal++;
+    break;
+  }
+  zzinc_(Zdistplane);
+  if (!qh->RANDOMdist && qh->IStracing < 4)
+    return;
+  if (qh->RANDOMdist) {
+    randr= qh_RANDOMint;
+    *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh->RANDOMfactor * qh->MAXabs_coord;
+  }
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 4) {
+    qh_fprintf(qh, qh->ferr, 8001, "qh_distplane: ");
+    qh_fprintf(qh, qh->ferr, 8002, qh_REAL_1, *dist);
+    qh_fprintf(qh, qh->ferr, 8003, "from p%d to f%d\n", qh_pointid(qh, point), facet->id);
+  }
+#endif
+  return;
+} /* distplane */
+
+
+/*---------------------------------
+
+  qh_findbest(qh, point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
+    find facet that is furthest below a point
+    for upperDelaunay facets
+      returns facet only if !qh_NOupper and clearly above
+
+  input:
+    starts search at 'startfacet' (can not be flipped)
+    if !bestoutside(qh_ALL), stops at qh.MINoutside
+
+  returns:
+    best facet (reports error if NULL)
+    early out if isoutside defined and bestdist > qh.MINoutside
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart counts the number of distance tests
+
+  see also:
+    qh_findbestnew()
+
+  notes:
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
+      avoid calls to distplane, function calls, and real number operations.
+    caller traces result
+    Optimized for outside points.   Tried recording a search set for qh_findhorizon.
+    Made code more complicated.
+
+  when called by qh_partitionvisible():
+    indicated by qh_ISnewfacets
+    qh.newfacet_list is list of simplicial, new facets
+    qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
+    qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
+
+  when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(),
+                 qh_check_bestdist(), qh_addpoint()
+    indicated by !qh_ISnewfacets
+    returns best facet in neighborhood of given facet
+      this is best facet overall if dist >= -qh.MAXcoplanar
+        or hull has at least a "spherical" curvature
+
+  design:
+    initialize and test for early exit
+    repeat while there are better facets
+      for each neighbor of facet
+        exit if outside facet found
+        test for better facet
+    if point is inside and partitioning
+      test for new facets with a "sharp" intersection
+      if so, future calls go to qh_findbestnew()
+    test horizon facets
+*/
+facetT *qh_findbest(qhT *qh, pointT *point, facetT *startfacet,
+                     boolT bestoutside, boolT isnewfacets, boolT noupper,
+                     realT *dist, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  facetT *facet, *neighbor, **neighborp;
+  facetT *bestfacet= NULL, *lastfacet= NULL;
+  int oldtrace= qh->IStracing;
+  unsigned int visitid= ++qh->visit_id;
+  int numpartnew=0;
+  boolT testhorizon= True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  zinc_(Zfindbest);
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 4 || (qh->TRACElevel && qh->TRACEpoint >= 0 && qh->TRACEpoint == qh_pointid(qh, point))) {
+    if (qh->TRACElevel > qh->IStracing)
+      qh->IStracing= qh->TRACElevel;
+    qh_fprintf(qh, qh->ferr, 8004, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g,",
+             qh_pointid(qh, point), startfacet->id, isnewfacets, bestoutside, qh->MINoutside);
+    qh_fprintf(qh, qh->ferr, 8005, " testhorizon? %d, noupper? %d,", testhorizon, noupper);
+    qh_fprintf(qh, qh->ferr, 8006, " Last qh_addpoint p%d,", qh->furthest_id);
+    qh_fprintf(qh, qh->ferr, 8007, " Last merge #%d, max_outside %2.2g\n", zzval_(Ztotmerge), qh->max_outside);
+  }
+#endif
+  if (isoutside)
+    *isoutside= True;
+  if (!startfacet->flipped) {  /* test startfacet before testing its neighbors */
+    *numpart= 1;
+    qh_distplane(qh, point, startfacet, dist);  /* this code is duplicated below */
+    if (!bestoutside && *dist >= qh->MINoutside
+    && (!startfacet->upperdelaunay || !noupper)) {
+      bestfacet= startfacet;
+      goto LABELreturn_best;
+    }
+    bestdist= *dist;
+    if (!startfacet->upperdelaunay) {
+      bestfacet= startfacet;
+    }
+  }else
+    *numpart= 0;
+  startfacet->visitid= visitid;
+  facet= startfacet;
+  while (facet) {
+    trace4((qh, qh->ferr, 4001, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n",
+                facet->id, bestdist, getid_(bestfacet)));
+    lastfacet= facet;
+    FOREACHneighbor_(facet) {
+      if (!neighbor->newfacet && isnewfacets)
+        continue;
+      if (neighbor->visitid == visitid)
+        continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) {  /* code duplicated above */
+        (*numpart)++;
+        qh_distplane(qh, point, neighbor, dist);
+        if (*dist > bestdist) {
+          if (!bestoutside && *dist >= qh->MINoutside
+          && (!neighbor->upperdelaunay || !noupper)) {
+            bestfacet= neighbor;
+            goto LABELreturn_best;
+          }
+          if (!neighbor->upperdelaunay) {
+            bestfacet= neighbor;
+            bestdist= *dist;
+            break; /* switch to neighbor */
+          }else if (!bestfacet) {
+            bestdist= *dist;
+            break; /* switch to neighbor */
+          }
+        } /* end of *dist>bestdist */
+      } /* end of !flipped */
+    } /* end of FOREACHneighbor */
+    facet= neighbor;  /* non-NULL only if *dist>bestdist */
+  } /* end of while facet (directed search) */
+  if (isnewfacets) {
+    if (!bestfacet) { /* startfacet is upperdelaunay (or flipped) w/o !flipped newfacet neighbors */
+      bestdist= -REALmax/2;
+      bestfacet= qh_findbestnew(qh, point, qh->newfacet_list, &bestdist, bestoutside, isoutside, &numpartnew);
+      testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+    }else if (!qh->findbest_notsharp && bestdist < -qh->DISTround) {
+      if (qh_sharpnewfacets(qh)) {
+        /* seldom used, qh_findbestnew will retest all facets */
+        zinc_(Zfindnewsharp);
+        bestfacet= qh_findbestnew(qh, point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
+        testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+        qh->findbestnew= True;
+      }else
+        qh->findbest_notsharp= True;
+    }
+  }
+  if (!bestfacet)
+    bestfacet= qh_findbestlower(qh, lastfacet, point, &bestdist, numpart); /* lastfacet is non-NULL because startfacet is non-NULL */
+  if (testhorizon) /* qh_findbestnew not called */
+    bestfacet= qh_findbesthorizon(qh, !qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
+  *dist= bestdist;
+  if (isoutside && bestdist < qh->MINoutside)
+    *isoutside= False;
+LABELreturn_best:
+  zadd_(Zfindbesttot, *numpart);
+  zmax_(Zfindbestmax, *numpart);
+  (*numpart) += numpartnew;
+  qh->IStracing= oldtrace;
+  return bestfacet;
+}  /* findbest */
+
+
+/*---------------------------------
+
+  qh_findbesthorizon(qh, qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
+    search coplanar and better horizon facets from startfacet/bestdist
+    ischeckmax turns off statistics and minsearch update
+    all arguments must be initialized, including *bestdist and *numpart
+    qh.coplanarfacetset used to maintain current search set, reset whenever best facet is substantially better
+  returns(ischeckmax):
+    best facet
+    updates f.maxoutside for neighbors of searched facets (if qh_MAXoutside)
+  returns(!ischeckmax):
+    best facet that is not upperdelaunay or newfacet (qh.first_newfacet)
+    allows upperdelaunay that is clearly outside
+  returns:
+    bestdist is distance to bestfacet
+    numpart -- updates number of distance tests
+
+  notes:
+    called by qh_findbest if point is not outside a facet (directed search)
+    called by qh_findbestnew if point is not outside a new facet
+    called by qh_check_maxout for each point in hull
+    called by qh_check_bestdist for each point in hull (rarely used)
+
+    no early out -- use qh_findbest() or qh_findbestnew()
+    Searches coplanar or better horizon facets
+
+  when called by qh_check_maxout() (qh_IScheckmax)
+    startfacet must be closest to the point
+      Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
+      even though other facets are below the point.
+    updates facet->maxoutside for good, visited facets
+    may return NULL
+
+    searchdist is qh.max_outside + 2 * DISTround
+      + max( MINvisible('Vn'), MAXcoplanar('Un'));
+    This setting is a guess.  It must be at least max_outside + 2*DISTround
+    because a facet may have a geometric neighbor across a vertex
+
+  design:
+    for each horizon facet of coplanar best facets
+      continue if clearly inside
+      unless upperdelaunay or clearly outside
+         update best facet
+*/
+facetT *qh_findbesthorizon(qhT *qh, boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
+  facetT *bestfacet= startfacet;
+  realT dist;
+  facetT *neighbor, **neighborp, *facet;
+  facetT *nextfacet= NULL; /* optimize last facet of coplanarfacetset */
+  int numpartinit= *numpart, coplanarfacetset_size, numcoplanar= 0, numfacet= 0;
+  unsigned int visitid= ++qh->visit_id;
+  boolT newbest= False; /* for tracing */
+  realT minsearch, searchdist;  /* skip facets that are too far from point */
+  boolT is_5x_minsearch;
+
+  if (!ischeckmax) {
+    zinc_(Zfindhorizon);
+  }else {
+#if qh_MAXoutside
+    if ((!qh->ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
+      startfacet->maxoutside= *bestdist;
+#endif
+  }
+  searchdist= qh_SEARCHdist; /* an expression, a multiple of qh.max_outside and precision constants */
+  minsearch= *bestdist - searchdist;
+  if (ischeckmax) {
+    /* Always check coplanar facets.  Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
+    minimize_(minsearch, -searchdist);
+  }
+  coplanarfacetset_size= 0;
+  startfacet->visitid= visitid;
+  facet= startfacet;
+  while (True) {
+    numfacet++;
+    is_5x_minsearch= (ischeckmax && facet->nummerge > 10 && qh_setsize(qh, facet->neighbors) > 100);  /* QH11033 FIX: qh_findbesthorizon: many tests for facets with many merges and neighbors.  Can hide coplanar facets, e.g., 'rbox 1000 s Z1 G1e-13' with 4400+ neighbors */
+    trace4((qh, qh->ferr, 4002, "qh_findbesthorizon: test neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g is_5x? %d searchdist %2.2g\n",
+                facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
+                minsearch, is_5x_minsearch, searchdist));
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == visitid)
+        continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) {  /* neighbors of flipped facets always searched via nextfacet */
+        qh_distplane(qh, point, neighbor, &dist); /* duplicate qh_distpane for new facets, they may be coplanar */
+        (*numpart)++;
+        if (dist > *bestdist) {
+          if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh->MINoutside)) {
+            if (!ischeckmax) {
+              minsearch= dist - searchdist;
+              if (dist > *bestdist + searchdist) {
+                zinc_(Zfindjump);  /* everything in qh.coplanarfacetset at least searchdist below */
+                coplanarfacetset_size= 0;
+              }
+            }
+            bestfacet= neighbor;
+            *bestdist= dist;
+            newbest= True;
+          }
+        }else if (is_5x_minsearch) {
+          if (dist < 5 * minsearch)
+            continue; /* skip this neighbor, do not set nextfacet.  dist is negative */
+        }else if (dist < minsearch)
+          continue;  /* skip this neighbor, do not set nextfacet.  If ischeckmax, dist can't be positive */
+#if qh_MAXoutside
+        if (ischeckmax && dist > neighbor->maxoutside)
+          neighbor->maxoutside= dist;
+#endif
+      } /* end of !flipped, need to search neighbor */
+      if (nextfacet) {
+        numcoplanar++;
+        if (!coplanarfacetset_size++) {
+          SETfirst_(qh->coplanarfacetset)= nextfacet;
+          SETtruncate_(qh->coplanarfacetset, 1);
+        }else
+          qh_setappend(qh, &qh->coplanarfacetset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
+                                                 and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv  */
+      }
+      nextfacet= neighbor;
+    } /* end of EACHneighbor */
+    facet= nextfacet;
+    if (facet)
+      nextfacet= NULL;
+    else if (!coplanarfacetset_size)
+      break;
+    else if (!--coplanarfacetset_size) {
+      facet= SETfirstt_(qh->coplanarfacetset, facetT);
+      SETtruncate_(qh->coplanarfacetset, 0);
+    }else
+      facet= (facetT *)qh_setdellast(qh->coplanarfacetset);
+  } /* while True, i.e., "for each facet in qh.coplanarfacetset" */
+  if (!ischeckmax) {
+    zadd_(Zfindhorizontot, *numpart - numpartinit);
+    zmax_(Zfindhorizonmax, *numpart - numpartinit);
+    if (newbest)
+      zinc_(Znewbesthorizon);
+  }
+  trace4((qh, qh->ferr, 4003, "qh_findbesthorizon: p%d, newbest? %d, bestfacet f%d, bestdist %2.2g, numfacet %d, coplanarfacets %d, numdist %d\n",
+    qh_pointid(qh, point), newbest, getid_(bestfacet), *bestdist, numfacet, numcoplanar, *numpart - numpartinit));
+  return bestfacet;
+}  /* findbesthorizon */
+
+/*---------------------------------
+
+  qh_findbestnew(qh, point, startfacet, dist, isoutside, numpart )
+    find best newfacet for point
+    searches all of qh.newfacet_list starting at startfacet
+    searches horizon facets of coplanar best newfacets
+    searches all facets if startfacet == qh.facet_list
+  returns:
+    best new or horizon facet that is not upperdelaunay
+    early out if isoutside and not 'Qf'
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart is number of distance tests
+
+  notes:
+    Always used for merged new facets (see qh_USEfindbestnew)
+    Avoids upperdelaunay facet unless (isoutside and outside)
+
+    Uses qh.visit_id, qh.coplanarfacetset.
+    If share visit_id with qh_findbest, coplanarfacetset is incorrect.
+
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    a point maybe coplanar to the bestfacet, below its horizon facet,
+    and above a horizon facet of a coplanar newfacet.  For example,
+      rbox 1000 s Z1 G1e-13 | qhull
+      rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
+
+    qh_findbestnew() used if
+       qh_sharpnewfacets -- newfacets contains a sharp angle
+       if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
+
+  see also:
+    qh_partitionall() and qh_findbest()
+
+  design:
+    for each new facet starting from startfacet
+      test distance from point to facet
+      return facet if clearly outside
+      unless upperdelaunay and a lowerdelaunay exists
+         update best facet
+    test horizon facets
+*/
+facetT *qh_findbestnew(qhT *qh, pointT *point, facetT *startfacet,
+           realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2;
+  facetT *bestfacet= NULL, *facet;
+  int oldtrace= qh->IStracing, i;
+  unsigned int visitid= ++qh->visit_id;
+  realT distoutside= 0.0;
+  boolT isdistoutside; /* True if distoutside is defined */
+  boolT testhorizon= True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  if (!startfacet || !startfacet->next) {
+    if (qh->MERGING) {
+      qh_fprintf(qh, qh->ferr, 6001, "qhull topology error (qh_findbestnew): merging has formed and deleted a cone of new facets.  Can not continue.\n");
+      qh_errexit(qh, qh_ERRtopology, NULL, NULL);
+    }else {
+      qh_fprintf(qh, qh->ferr, 6002, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
+              qh->furthest_id);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+  }
+  zinc_(Zfindnew);
+  if (qh->BESToutside || bestoutside)
+    isdistoutside= False;
+  else {
+    isdistoutside= True;
+    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user_r.h */
+  }
+  if (isoutside)
+    *isoutside= True;
+  *numpart= 0;
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 4 || (qh->TRACElevel && qh->TRACEpoint >= 0 && qh->TRACEpoint == qh_pointid(qh, point))) {
+    if (qh->TRACElevel > qh->IStracing)
+      qh->IStracing= qh->TRACElevel;
+    qh_fprintf(qh, qh->ferr, 8008, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g,",
+             qh_pointid(qh, point), startfacet->id, isdistoutside, distoutside);
+    qh_fprintf(qh, qh->ferr, 8009, " Last qh_addpoint p%d, qh.visit_id %d, vertex_visit %d,",  qh->furthest_id, visitid, qh->vertex_visit);
+    qh_fprintf(qh, qh->ferr, 8010, " Last merge #%d\n", zzval_(Ztotmerge));
+  }
+#endif
+  /* visit all new facets starting with startfacet, maybe qh->facet_list */
+  for (i=0, facet=startfacet; i < 2; i++, facet= qh->newfacet_list) {
+    FORALLfacet_(facet) {
+      if (facet == startfacet && i)
+        break;
+      facet->visitid= visitid;
+      if (!facet->flipped) {
+        qh_distplane(qh, point, facet, dist);
+        (*numpart)++;
+        if (*dist > bestdist) {
+          if (!facet->upperdelaunay || *dist >= qh->MINoutside) {
+            bestfacet= facet;
+            if (isdistoutside && *dist >= distoutside)
+              goto LABELreturn_bestnew;
+            bestdist= *dist;
+          }
+        }
+      } /* end of !flipped */
+    } /* FORALLfacet from startfacet or qh->newfacet_list */
+  }
+  if (testhorizon || !bestfacet) /* testhorizon is always True.  Keep the same code as qh_findbest */
+    bestfacet= qh_findbesthorizon(qh, !qh_IScheckmax, point, bestfacet ? bestfacet : startfacet,
+                                        !qh_NOupper, &bestdist, numpart);
+  *dist= bestdist;
+  if (isoutside && *dist < qh->MINoutside)
+    *isoutside= False;
+LABELreturn_bestnew:
+  zadd_(Zfindnewtot, *numpart);
+  zmax_(Zfindnewmax, *numpart);
+  trace4((qh, qh->ferr, 4004, "qh_findbestnew: bestfacet f%d bestdist %2.2g for p%d f%d bestoutside? %d \n",
+    getid_(bestfacet), *dist, qh_pointid(qh, point), startfacet->id, bestoutside));
+  qh->IStracing= oldtrace;
+  return bestfacet;
+}  /* findbestnew */
+
+/* ============ hyperplane functions -- keep code together [?] ============ */
+
+/*---------------------------------
+
+  qh_backnormal(qh, rows, numrow, numcol, sign, normal, nearzero )
+    given an upper-triangular rows array and a sign,
+    solve for normal equation x using back substitution over rows U
+
+  returns:
+     normal= x
+
+     if will not be able to divzero() when normalized(qh.MINdenom_2 and qh.MINdenom_1_2),
+       if fails on last row
+         this means that the hyperplane intersects [0,..,1]
+         sets last coordinate of normal to sign
+       otherwise
+         sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
+         sets nearzero
+
+  notes:
+     assumes numrow == numcol-1
+
+     see Golub & van Loan, 1983, Eq. 4.4-9 for "Gaussian elimination with complete pivoting"
+
+     solves Ux=b where Ax=b and PA=LU
+     b= [0,...,0,sign or 0]  (sign is either -1 or +1)
+     last row of A= [0,...,0,1]
+
+     1) Ly=Pb == y=b since P only permutes the 0's of   b
+
+  design:
+    for each row from end
+      perform back substitution
+      if near zero
+        use qh_divzero for division
+        if zero divide and not last row
+          set tail of normal to 0
+*/
+void qh_backnormal(qhT *qh, realT **rows, int numrow, int numcol, boolT sign,
+        coordT *normal, boolT *nearzero) {
+  int i, j;
+  coordT *normalp, *normal_tail, *ai, *ak;
+  realT diagonal;
+  boolT waszero;
+  int zerocol= -1;
+
+  normalp= normal + numcol - 1;
+  *normalp--= (sign ? -1.0 : 1.0);
+  for (i=numrow; i--; ) {
+    *normalp= 0.0;
+    ai= rows[i] + i + 1;
+    ak= normalp+1;
+    for (j=i+1; j < numcol; j++)
+      *normalp -= *ai++ * *ak++;
+    diagonal= (rows[i])[i];
+    if (fabs_(diagonal) > qh->MINdenom_2)
+      *(normalp--) /= diagonal;
+    else {
+      waszero= False;
+      *normalp= qh_divzero(*normalp, diagonal, qh->MINdenom_1_2, &waszero);
+      if (waszero) {
+        zerocol= i;
+        *(normalp--)= (sign ? -1.0 : 1.0);
+        for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
+          *normal_tail= 0.0;
+      }else
+        normalp--;
+    }
+  }
+  if (zerocol != -1) {
+    *nearzero= True;
+    trace4((qh, qh->ferr, 4005, "qh_backnormal: zero diagonal at column %d.\n", i));
+    zzinc_(Zback0);
+    qh_joggle_restart(qh, "zero diagonal on back substitution");
+  }
+} /* backnormal */
+
+/*---------------------------------
+
+  qh_gausselim(qh, rows, numrow, numcol, sign )
+    Gaussian elimination with partial pivoting
+
+  returns:
+    rows is upper triangular (includes row exchanges)
+    flips sign for each row exchange
+    sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
+
+  notes:
+    if nearzero, the determinant's sign may be incorrect.
+    assumes numrow <= numcol
+
+  design:
+    for each row
+      determine pivot and exchange rows if necessary
+      test for near zero
+      perform gaussian elimination step
+*/
+void qh_gausselim(qhT *qh, realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
+  realT *ai, *ak, *rowp, *pivotrow;
+  realT n, pivot, pivot_abs= 0.0, temp;
+  int i, j, k, pivoti, flip=0;
+
+  *nearzero= False;
+  for (k=0; k < numrow; k++) {
+    pivot_abs= fabs_((rows[k])[k]);
+    pivoti= k;
+    for (i=k+1; i < numrow; i++) {
+      if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
+        pivot_abs= temp;
+        pivoti= i;
+      }
+    }
+    if (pivoti != k) {
+      rowp= rows[pivoti];
+      rows[pivoti]= rows[k];
+      rows[k]= rowp;
+      *sign ^= 1;
+      flip ^= 1;
+    }
+    if (pivot_abs <= qh->NEARzero[k]) {
+      *nearzero= True;
+      if (pivot_abs == 0.0) {   /* remainder of column == 0 */
+#ifndef qh_NOtrace
+        if (qh->IStracing >= 4) {
+          qh_fprintf(qh, qh->ferr, 8011, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh->DISTround);
+          qh_printmatrix(qh, qh->ferr, "Matrix:", rows, numrow, numcol);
+        }
+#endif
+        zzinc_(Zgauss0);
+        qh_joggle_restart(qh, "zero pivot for Gaussian elimination");
+        goto LABELnextcol;
+      }
+    }
+    pivotrow= rows[k] + k;
+    pivot= *pivotrow++;  /* signed value of pivot, and remainder of row */
+    for (i=k+1; i < numrow; i++) {
+      ai= rows[i] + k;
+      ak= pivotrow;
+      n= (*ai++)/pivot;   /* divzero() not needed since |pivot| >= |*ai| */
+      for (j= numcol - (k+1); j--; )
+        *ai++ -= n * *ak++;
+    }
+  LABELnextcol:
+    ;
+  }
+  wmin_(Wmindenom, pivot_abs);  /* last pivot element */
+  if (qh->IStracing >= 5)
+    qh_printmatrix(qh, qh->ferr, "qh_gausselem: result", rows, numrow, numcol);
+} /* gausselim */
+
+
+/*---------------------------------
+
+  qh_getangle(qh, vect1, vect2 )
+    returns the dot product of two vectors
+    if qh.RANDOMdist, joggles result
+
+  notes:
+    the angle may be > 1.0 or < -1.0 because of roundoff errors
+
+*/
+realT qh_getangle(qhT *qh, pointT *vect1, pointT *vect2) {
+  realT angle= 0, randr;
+  int k;
+
+  for (k=qh->hull_dim; k--; )
+    angle += *vect1++ * *vect2++;
+  if (qh->RANDOMdist) {
+    randr= qh_RANDOMint;
+    angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh->RANDOMfactor;
+  }
+  trace4((qh, qh->ferr, 4006, "qh_getangle: %4.4g\n", angle));
+  return(angle);
+} /* getangle */
+
+
+/*---------------------------------
+
+  qh_getcenter(qh, vertices )
+    returns arithmetic center of a set of vertices as a new point
+
+  notes:
+    allocates point array for center
+*/
+pointT *qh_getcenter(qhT *qh, setT *vertices) {
+  int k;
+  pointT *center, *coord;
+  vertexT *vertex, **vertexp;
+  int count= qh_setsize(qh, vertices);
+
+  if (count < 2) {
+    qh_fprintf(qh, qh->ferr, 6003, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  center= (pointT *)qh_memalloc(qh, qh->normal_size);
+  for (k=0; k < qh->hull_dim; k++) {
+    coord= center+k;
+    *coord= 0.0;
+    FOREACHvertex_(vertices)
+      *coord += vertex->point[k];
+    *coord /= count;  /* count>=2 by QH6003 */
+  }
+  return(center);
+} /* getcenter */
+
+
+/*---------------------------------
+
+  qh_getcentrum(qh, facet )
+    returns the centrum for a facet as a new point
+
+  notes:
+    allocates the centrum
+*/
+pointT *qh_getcentrum(qhT *qh, facetT *facet) {
+  realT dist;
+  pointT *centrum, *point;
+
+  point= qh_getcenter(qh, facet->vertices);
+  zzinc_(Zcentrumtests);
+  qh_distplane(qh, point, facet, &dist);
+  centrum= qh_projectpoint(qh, point, facet, dist);
+  qh_memfree(qh, point, qh->normal_size);
+  trace4((qh, qh->ferr, 4007, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
+          facet->id, qh_setsize(qh, facet->vertices), dist));
+  return centrum;
+} /* getcentrum */
+
+
+/*---------------------------------
+
+  qh_getdistance(qh, facet, neighbor, mindist, maxdist )
+    returns the min and max distance to neighbor of non-neighbor vertices in facet
+
+  returns:
+    the max absolute value
+
+  design:
+    for each vertex of facet that is not in neighbor
+      test the distance from vertex to neighbor
+*/
+coordT qh_getdistance(qhT *qh, facetT *facet, facetT *neighbor, coordT *mindist, coordT *maxdist) {
+  vertexT *vertex, **vertexp;
+  coordT dist, maxd, mind;
+
+  FOREACHvertex_(facet->vertices)
+    vertex->seen= False;
+  FOREACHvertex_(neighbor->vertices)
+    vertex->seen= True;
+  mind= 0.0;
+  maxd= 0.0;
+  FOREACHvertex_(facet->vertices) {
+    if (!vertex->seen) {
+      zzinc_(Zbestdist);
+      qh_distplane(qh, vertex->point, neighbor, &dist);
+      if (dist < mind)
+        mind= dist;
+      else if (dist > maxd)
+        maxd= dist;
+    }
+  }
+  *mindist= mind;
+  *maxdist= maxd;
+  mind= -mind;
+  if (maxd > mind)
+    return maxd;
+  else
+    return mind;
+} /* getdistance */
+
+
+/*---------------------------------
+
+  qh_normalize(qh, normal, dim, toporient )
+    normalize a vector and report if too small
+    does not use min norm
+
+  see:
+    qh_normalize2
+*/
+void qh_normalize(qhT *qh, coordT *normal, int dim, boolT toporient) {
+  qh_normalize2(qh, normal, dim, toporient, NULL, NULL);
+} /* normalize */
+
+/*---------------------------------
+
+  qh_normalize2(qh, normal, dim, toporient, minnorm, ismin )
+    normalize a vector and report if too small
+    qh.MINdenom/MINdenom1 are the upper limits for divide overflow
+
+  returns:
+    normalized vector
+    flips sign if !toporient
+    if minnorm non-NULL,
+      sets ismin if normal < minnorm
+
+  notes:
+    if zero norm
+       sets all elements to sqrt(1.0/dim)
+    if divide by zero (divzero())
+       sets largest element to   +/-1
+       bumps Znearlysingular
+
+  design:
+    computes norm
+    test for minnorm
+    if not near zero
+      normalizes normal
+    else if zero norm
+      sets normal to standard value
+    else
+      uses qh_divzero to normalize
+      if nearzero
+        sets norm to direction of maximum value
+*/
+void qh_normalize2(qhT *qh, coordT *normal, int dim, boolT toporient,
+            realT *minnorm, boolT *ismin) {
+  int k;
+  realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
+  boolT zerodiv;
+
+  norm1= normal+1;
+  norm2= normal+2;
+  norm3= normal+3;
+  if (dim == 2)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
+  else if (dim == 3)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
+  else if (dim == 4) {
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
+               + (*norm3)*(*norm3));
+  }else if (dim > 4) {
+    norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
+               + (*norm3)*(*norm3);
+    for (k=dim-4, colp=normal+4; k--; colp++)
+      norm += (*colp) * (*colp);
+    norm= sqrt(norm);
+  }
+  if (minnorm) {
+    if (norm < *minnorm)
+      *ismin= True;
+    else
+      *ismin= False;
+  }
+  wmin_(Wmindenom, norm);
+  if (norm > qh->MINdenom) {
+    if (!toporient)
+      norm= -norm;
+    *normal /= norm;
+    *norm1 /= norm;
+    if (dim == 2)
+      ; /* all done */
+    else if (dim == 3)
+      *norm2 /= norm;
+    else if (dim == 4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+    }else if (dim >4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+      for (k=dim-4, colp=normal+4; k--; )
+        *colp++ /= norm;
+    }
+  }else if (norm == 0.0) {
+    temp= sqrt(1.0/dim);
+    for (k=dim, colp=normal; k--; )
+      *colp++= temp;
+  }else {
+    if (!toporient)
+      norm= -norm;
+    for (k=dim, colp=normal; k--; colp++) { /* k used below */
+      temp= qh_divzero(*colp, norm, qh->MINdenom_1, &zerodiv);
+      if (!zerodiv)
+        *colp= temp;
+      else {
+        maxp= qh_maxabsval(normal, dim);
+        temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
+        for (k=dim, colp=normal; k--; colp++)
+          *colp= 0.0;
+        *maxp= temp;
+        zzinc_(Znearlysingular);
+        /* qh_joggle_restart ignored for Znearlysingular, normal part of qh_sethyperplane_gauss */
+        trace0((qh, qh->ferr, 1, "qh_normalize: norm=%2.2g too small during p%d\n",
+               norm, qh->furthest_id));
+        return;
+      }
+    }
+  }
+} /* normalize */
+
+
+/*---------------------------------
+
+  qh_projectpoint(qh, point, facet, dist )
+    project point onto a facet by dist
+
+  returns:
+    returns a new point
+
+  notes:
+    if dist= distplane(point,facet)
+      this projects point to hyperplane
+    assumes qh_memfree_() is valid for normal_size
+*/
+pointT *qh_projectpoint(qhT *qh, pointT *point, facetT *facet, realT dist) {
+  pointT *newpoint, *np, *normal;
+  int normsize= qh->normal_size;
+  int k;
+  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
+
+  qh_memalloc_(qh, normsize, freelistp, newpoint, pointT);
+  np= newpoint;
+  normal= facet->normal;
+  for (k=qh->hull_dim; k--; )
+    *(np++)= *point++ - dist * *normal++;
+  return(newpoint);
+} /* projectpoint */
+
+
+/*---------------------------------
+
+  qh_setfacetplane(qh, facet )
+    sets the hyperplane for a facet
+    if qh.RANDOMdist, joggles hyperplane
+
+  notes:
+    uses global buffers qh.gm_matrix and qh.gm_row
+    overwrites facet->normal if already defined
+    updates Wnewvertex if PRINTstatistics
+    sets facet->upperdelaunay if upper envelope of Delaunay triangulation
+
+  design:
+    copy vertex coordinates to qh.gm_matrix/gm_row
+    compute determinate
+    if nearzero
+      recompute determinate with gaussian elimination
+      if nearzero
+        force outside orientation by testing interior point
+*/
+void qh_setfacetplane(qhT *qh, facetT *facet) {
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int normsize= qh->normal_size;
+  int k,i, oldtrace= 0;
+  realT dist;
+  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
+  coordT *coord, *gmcoord;
+  pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
+  boolT nearzero= False;
+
+  zzinc_(Zsetplane);
+  if (!facet->normal)
+    qh_memalloc_(qh, normsize, freelistp, facet->normal, coordT);
+#ifndef qh_NOtrace
+  if (facet == qh->tracefacet) {
+    oldtrace= qh->IStracing;
+    qh->IStracing= 5;
+    qh_fprintf(qh, qh->ferr, 8012, "qh_setfacetplane: facet f%d created.\n", facet->id);
+    qh_fprintf(qh, qh->ferr, 8013, "  Last point added to hull was p%d.", qh->furthest_id);
+    if (zzval_(Ztotmerge))
+      qh_fprintf(qh, qh->ferr, 8014, "  Last merge was #%d.", zzval_(Ztotmerge));
+    qh_fprintf(qh, qh->ferr, 8015, "\n\nCurrent summary is:\n");
+      qh_printsummary(qh, qh->ferr);
+  }
+#endif
+  if (qh->hull_dim <= 4) {
+    i= 0;
+    if (qh->RANDOMdist) {
+      gmcoord= qh->gm_matrix;
+      FOREACHvertex_(facet->vertices) {
+        qh->gm_row[i++]= gmcoord;
+        coord= vertex->point;
+        for (k=qh->hull_dim; k--; )
+          *(gmcoord++)= *coord++ * qh_randomfactor(qh, qh->RANDOMa, qh->RANDOMb);
+      }
+    }else {
+      FOREACHvertex_(facet->vertices)
+       qh->gm_row[i++]= vertex->point;
+    }
+    qh_sethyperplane_det(qh, qh->hull_dim, qh->gm_row, point0, facet->toporient,
+                facet->normal, &facet->offset, &nearzero);
+  }
+  if (qh->hull_dim > 4 || nearzero) {
+    i= 0;
+    gmcoord= qh->gm_matrix;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+        qh->gm_row[i++]= gmcoord;
+        coord= vertex->point;
+        point= point0;
+        for (k=qh->hull_dim; k--; )
+          *(gmcoord++)= *coord++ - *point++;
+      }
+    }
+    qh->gm_row[i]= gmcoord;  /* for areasimplex */
+    if (qh->RANDOMdist) {
+      gmcoord= qh->gm_matrix;
+      for (i=qh->hull_dim-1; i--; ) {
+        for (k=qh->hull_dim; k--; )
+          *(gmcoord++) *= qh_randomfactor(qh, qh->RANDOMa, qh->RANDOMb);
+      }
+    }
+    qh_sethyperplane_gauss(qh, qh->hull_dim, qh->gm_row, point0, facet->toporient,
+                facet->normal, &facet->offset, &nearzero);
+    if (nearzero) {
+      if (qh_orientoutside(qh, facet)) {
+        trace0((qh, qh->ferr, 2, "qh_setfacetplane: flipped orientation due to nearzero gauss and interior_point test.  During p%d\n", qh->furthest_id));
+      /* this is part of using Gaussian Elimination.  For example in 5-d
+           1 1 1 1 0
+           1 1 1 1 1
+           0 0 0 1 0
+           0 1 0 0 0
+           1 0 0 0 0
+           norm= 0.38 0.38 -0.76 0.38 0
+         has a determinate of 1, but g.e. after subtracting pt. 0 has
+         0's in the diagonal, even with full pivoting.  It does work
+         if you subtract pt. 4 instead. */
+      }
+    }
+  }
+  facet->upperdelaunay= False;
+  if (qh->DELAUNAY) {
+    if (qh->UPPERdelaunay) {     /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
+      if (facet->normal[qh->hull_dim -1] >= qh->ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }else {
+      if (facet->normal[qh->hull_dim -1] > -qh->ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }
+  }
+  if (qh->PRINTstatistics || qh->IStracing || qh->TRACElevel || qh->JOGGLEmax < REALmax) {
+    qh->old_randomdist= qh->RANDOMdist;
+    qh->RANDOMdist= False;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+        boolT istrace= False;
+        zinc_(Zdiststat);
+        qh_distplane(qh, vertex->point, facet, &dist);
+        dist= fabs_(dist);
+        zinc_(Znewvertex);
+        wadd_(Wnewvertex, dist);
+        if (dist > wwval_(Wnewvertexmax)) {
+          wwval_(Wnewvertexmax)= dist;
+          if (dist > qh->max_outside) {
+            qh->max_outside= dist;  /* used by qh_maxouter(qh) */
+            if (dist > qh->TRACEdist)
+              istrace= True;
+          }
+        }else if (-dist > qh->TRACEdist)
+          istrace= True;
+        if (istrace) {
+          qh_fprintf(qh, qh->ferr, 3060, "qh_setfacetplane: ====== vertex p%d(v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
+                qh_pointid(qh, vertex->point), vertex->id, dist, facet->id, qh->furthest_id);
+          qh_errprint(qh, "DISTANT", facet, NULL, NULL, NULL);
+        }
+      }
+    }
+    qh->RANDOMdist= qh->old_randomdist;
+  }
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 4) {
+    qh_fprintf(qh, qh->ferr, 8017, "qh_setfacetplane: f%d offset %2.2g normal: ",
+             facet->id, facet->offset);
+    for (k=0; k < qh->hull_dim; k++)
+      qh_fprintf(qh, qh->ferr, 8018, "%2.2g ", facet->normal[k]);
+    qh_fprintf(qh, qh->ferr, 8019, "\n");
+  }
+#endif
+  qh_checkflipped(qh, facet, NULL, qh_ALL);
+  if (facet == qh->tracefacet) {
+    qh->IStracing= oldtrace;
+    qh_printfacet(qh, qh->ferr, facet);
+  }
+} /* setfacetplane */
+
+
+/*---------------------------------
+
+  qh_sethyperplane_det(qh, dim, rows, point0, toporient, normal, offset, nearzero )
+    given dim X dim array indexed by rows[], one row per point,
+        toporient(flips all signs),
+        and point0 (any row)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+    sets nearzero if hyperplane not through points
+
+  notes:
+    only defined for dim == 2..4
+    rows[] is not modified
+    solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
+    see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
+
+  derivation of 3-d minnorm
+    Goal: all vertices V_i within qh.one_merge of hyperplane
+    Plan: exactly translate the facet so that V_0 is the origin
+          exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
+          exactly rotate the effective perturbation to only effect n_0
+             this introduces a factor of sqrt(3)
+    n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
+    Let M_d be the max coordinate difference
+    Let M_a be the greater of M_d and the max abs. coordinate
+    Let u be machine roundoff and distround be max error for distance computation
+    The max error for n_0 is sqrt(3) u M_a M_d / norm.  n_1 is approx. 1 and n_2 is approx. 0
+    The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm.  Offset=0 at origin
+    Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
+
+  derivation of 4-d minnorm
+    same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
+     [if two vertices fixed on x-axis, can rotate the other two in yzw.]
+    n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
+     [all other terms contain at least two factors nearly zero.]
+    The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
+    Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
+*/
+void qh_sethyperplane_det(qhT *qh, int dim, coordT **rows, coordT *point0,
+          boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
+  realT maxround, dist;
+  int i;
+  pointT *point;
+
+
+  if (dim == 2) {
+    normal[0]= dY(1,0);
+    normal[1]= dX(0,1);
+    qh_normalize2(qh, normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
+    *nearzero= False;  /* since nearzero norm => incident points */
+  }else if (dim == 3) {
+    normal[0]= det2_(dY(2,0), dZ(2,0),
+                     dY(1,0), dZ(1,0));
+    normal[1]= det2_(dX(1,0), dZ(1,0),
+                     dX(2,0), dZ(2,0));
+    normal[2]= det2_(dX(2,0), dY(2,0),
+                     dX(1,0), dY(1,0));
+    qh_normalize2(qh, normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+               + point0[2]*normal[2]);
+    maxround= qh->DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+               + point[2]*normal[2]);
+        if (dist > maxround || dist < -maxround) {
+          *nearzero= True;
+          break;
+        }
+      }
+    }
+  }else if (dim == 4) {
+    normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
+                        dY(1,0), dZ(1,0), dW(1,0),
+                        dY(3,0), dZ(3,0), dW(3,0));
+    normal[1]=   det3_(dX(2,0), dZ(2,0), dW(2,0),
+                        dX(1,0), dZ(1,0), dW(1,0),
+                        dX(3,0), dZ(3,0), dW(3,0));
+    normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
+                        dX(1,0), dY(1,0), dW(1,0),
+                        dX(3,0), dY(3,0), dW(3,0));
+    normal[3]=   det3_(dX(2,0), dY(2,0), dZ(2,0),
+                        dX(1,0), dY(1,0), dZ(1,0),
+                        dX(3,0), dY(3,0), dZ(3,0));
+    qh_normalize2(qh, normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+               + point0[2]*normal[2] + point0[3]*normal[3]);
+    maxround= qh->DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+               + point[2]*normal[2] + point[3]*normal[3]);
+        if (dist > maxround || dist < -maxround) {
+          *nearzero= True;
+          break;
+        }
+      }
+    }
+  }
+  if (*nearzero) {
+    zzinc_(Zminnorm);
+    /* qh_joggle_restart not needed, will call qh_sethyperplane_gauss instead */
+    trace0((qh, qh->ferr, 3, "qh_sethyperplane_det: degenerate norm during p%d, use qh_sethyperplane_gauss instead.\n", qh->furthest_id));
+  }
+} /* sethyperplane_det */
+
+
+/*---------------------------------
+
+  qh_sethyperplane_gauss(qh, dim, rows, point0, toporient, normal, offset, nearzero )
+    given(dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+
+  notes:
+    if nearzero
+      orientation may be incorrect because of incorrect sign flips in gausselim
+    solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1]
+        or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0]
+    i.e., N is normal to the hyperplane, and the unnormalized
+        distance to [0 .. 1] is either 1 or   0
+
+  design:
+    perform gaussian elimination
+    flip sign for negative values
+    perform back substitution
+    normalize result
+    compute offset
+*/
+void qh_sethyperplane_gauss(qhT *qh, int dim, coordT **rows, pointT *point0,
+                boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
+  coordT *pointcoord, *normalcoef;
+  int k;
+  boolT sign= toporient, nearzero2= False;
+
+  qh_gausselim(qh, rows, dim-1, dim, &sign, nearzero);
+  for (k=dim-1; k--; ) {
+    if ((rows[k])[k] < 0)
+      sign ^= 1;
+  }
+  if (*nearzero) {
+    zzinc_(Znearlysingular);
+    /* qh_joggle_restart ignored for Znearlysingular, normal part of qh_sethyperplane_gauss */
+    trace0((qh, qh->ferr, 4, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh->furthest_id));
+    qh_backnormal(qh, rows, dim-1, dim, sign, normal, &nearzero2);
+  }else {
+    qh_backnormal(qh, rows, dim-1, dim, sign, normal, &nearzero2);
+    if (nearzero2) {
+      zzinc_(Znearlysingular);
+      trace0((qh, qh->ferr, 5, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh->furthest_id));
+    }
+  }
+  if (nearzero2)
+    *nearzero= True;
+  qh_normalize2(qh, normal, dim, True, NULL, NULL);
+  pointcoord= point0;
+  normalcoef= normal;
+  *offset= -(*pointcoord++ * *normalcoef++);
+  for (k=dim-1; k--; )
+    *offset -= *pointcoord++ * *normalcoef++;
+} /* sethyperplane_gauss */
+
+
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.h
new file mode 100644
index 00000000000..f3f8ee81400
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/geom_r.h
@@ -0,0 +1,189 @@
+/*
  ---------------------------------
+
+  geom_r.h
+    header file for geometric routines
+
+   see qh-geom_r.htm and geom_r.c
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/geom_r.h#2 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#ifndef qhDEFgeom
+#define qhDEFgeom 1
+
+#include "libqhull_r.h"
+
+/* ============ -macros- ======================== */
+
+/*----------------------------------
+
+  fabs_(a)
+    returns the absolute value of a
+*/
+#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
+
+/*----------------------------------
+
+  fmax_(a,b)
+    returns the maximum value of a and b
+*/
+#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
+
+/*----------------------------------
+
+  fmin_(a,b)
+    returns the minimum value of a and b
+*/
+#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
+
+/*----------------------------------
+
+  maximize_(maxval, val)
+    set maxval to val if val is greater than maxval
+*/
+#define maximize_( maxval, val ) { if (( maxval ) < ( val )) ( maxval )= ( val ); }
+
+/*----------------------------------
+
+  minimize_(minval, val)
+    set minval to val if val is less than minval
+*/
+#define minimize_( minval, val ) { if (( minval ) > ( val )) ( minval )= ( val ); }
+
+/*----------------------------------
+
+  det2_(a1, a2,
+        b1, b2)
+
+    compute a 2-d determinate
+*/
+#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
+
+/*----------------------------------
+
+  det3_(a1, a2, a3,
+       b1, b2, b3,
+       c1, c2, c3)
+
+    compute a 3-d determinate
+*/
+#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
+                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
+
+/*----------------------------------
+
+  dX( p1, p2 )
+  dY( p1, p2 )
+  dZ( p1, p2 )
+
+    given two indices into rows[],
+
+    compute the difference between X, Y, or Z coordinates
+*/
+#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
+#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
+#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
+#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
+
+/*============= prototypes in alphabetical order, infrequent at end ======= */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    qh_backnormal(qhT *qh, realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
+void    qh_distplane(qhT *qh, pointT *point, facetT *facet, realT *dist);
+facetT *qh_findbest(qhT *qh, pointT *point, facetT *startfacet,
+                     boolT bestoutside, boolT isnewfacets, boolT noupper,
+                     realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbesthorizon(qhT *qh, boolT ischeckmax, pointT *point,
+                     facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
+facetT *qh_findbestnew(qhT *qh, pointT *point, facetT *startfacet, realT *dist,
+                     boolT bestoutside, boolT *isoutside, int *numpart);
+void    qh_gausselim(qhT *qh, realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
+realT   qh_getangle(qhT *qh, pointT *vect1, pointT *vect2);
+pointT *qh_getcenter(qhT *qh, setT *vertices);
+pointT *qh_getcentrum(qhT *qh, facetT *facet);
+coordT  qh_getdistance(qhT *qh, facetT *facet, facetT *neighbor, coordT *mindist, coordT *maxdist);
+void    qh_normalize(qhT *qh, coordT *normal, int dim, boolT toporient);
+void    qh_normalize2(qhT *qh, coordT *normal, int dim, boolT toporient,
+            realT *minnorm, boolT *ismin);
+pointT *qh_projectpoint(qhT *qh, pointT *point, facetT *facet, realT dist);
+
+void    qh_setfacetplane(qhT *qh, facetT *newfacets);
+void    qh_sethyperplane_det(qhT *qh, int dim, coordT **rows, coordT *point0,
+              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
+void    qh_sethyperplane_gauss(qhT *qh, int dim, coordT **rows, pointT *point0,
+             boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
+boolT   qh_sharpnewfacets(qhT *qh);
+
+/*========= infrequently used code in geom2_r.c =============*/
+
+coordT *qh_copypoints(qhT *qh, coordT *points, int numpoints, int dimension);
+void    qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
+realT   qh_determinant(qhT *qh, realT **rows, int dim, boolT *nearzero);
+realT   qh_detjoggle(qhT *qh, pointT *points, int numpoints, int dimension);
+void    qh_detmaxoutside(qhT *qh);
+void    qh_detroundoff(qhT *qh);
+realT   qh_detsimplex(qhT *qh, pointT *apex, setT *points, int dim, boolT *nearzero);
+realT   qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp);
+realT   qh_distround(qhT *qh, int dimension, realT maxabs, realT maxsumabs);
+realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
+realT   qh_facetarea(qhT *qh, facetT *facet);
+realT   qh_facetarea_simplex(qhT *qh, int dim, coordT *apex, setT *vertices,
+          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
+pointT *qh_facetcenter(qhT *qh, setT *vertices);
+facetT *qh_findgooddist(qhT *qh, pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
+vertexT *qh_furthestnewvertex(qhT *qh, unsigned int unvisited, facetT *facet, realT *maxdistp /* qh.newvertex_list */);
+vertexT *qh_furthestvertex(qhT *qh, facetT *facetA, facetT *facetB, realT *maxdistp, realT *mindistp);
+void    qh_getarea(qhT *qh, facetT *facetlist);
+boolT   qh_gram_schmidt(qhT *qh, int dim, realT **rows);
+boolT   qh_inthresholds(qhT *qh, coordT *normal, realT *angle);
+void    qh_joggleinput(qhT *qh);
+realT  *qh_maxabsval(realT *normal, int dim);
+setT   *qh_maxmin(qhT *qh, pointT *points, int numpoints, int dimension);
+realT   qh_maxouter(qhT *qh);
+void    qh_maxsimplex(qhT *qh, int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
+realT   qh_minabsval(realT *normal, int dim);
+int     qh_mindiff(realT *vecA, realT *vecB, int dim);
+boolT   qh_orientoutside(qhT *qh, facetT *facet);
+void    qh_outerinner(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane);
+coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
+void    qh_printmatrix(qhT *qh, FILE *fp, const char *string, realT **rows, int numrow, int numcol);
+void    qh_printpoints(qhT *qh, FILE *fp, const char *string, setT *points);
+void    qh_projectinput(qhT *qh);
+void    qh_projectpoints(qhT *qh, signed char *project, int n, realT *points,
+             int numpoints, int dim, realT *newpoints, int newdim);
+void    qh_rotateinput(qhT *qh, realT **rows);
+void    qh_rotatepoints(qhT *qh, realT *points, int numpoints, int dim, realT **rows);
+void    qh_scaleinput(qhT *qh);
+void    qh_scalelast(qhT *qh, coordT *points, int numpoints, int dim, coordT low,
+                   coordT high, coordT newhigh);
+void    qh_scalepoints(qhT *qh, pointT *points, int numpoints, int dim,
+                realT *newlows, realT *newhighs);
+boolT   qh_sethalfspace(qhT *qh, int dim, coordT *coords, coordT **nextp,
+              coordT *normal, coordT *offset, coordT *feasible);
+coordT *qh_sethalfspace_all(qhT *qh, int dim, int count, coordT *halfspaces, pointT *feasible);
+coordT  qh_vertex_bestdist(qhT *qh, setT *vertices);
+coordT  qh_vertex_bestdist2(qhT *qh, setT *vertices, vertexT **vertexp, vertexT **vertexp2);
+pointT *qh_voronoi_center(qhT *qh, int dim, setT *points);
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* qhDEFgeom */
+
+
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/global_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/global_r.c
new file mode 100644
index 00000000000..d8f0f0b0165
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/global_r.c
@@ -0,0 +1,2268 @@
+
+/*
  ---------------------------------
+
+   global_r.c
+   initializes all the globals of the qhull application
+
+   see README
+
+   see libqhull_r.h for qh.globals and function prototypes
+
+   see qhull_ra.h for internal functions
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/global_r.c#21 $$Change: 3664 $
+   $DateTime: 2024/07/22 23:55:01 $$Author: bbarber $
+ */
+
+#include "qhull_ra.h"
+
+/*========= qh->definition -- globals defined in libqhull_r.h =======================*/
+
+/*----------------------------------
+
+  qh_version
+    version string by year and date
+    qh_version2 for Unix users and -V
+
+    the revision increases on code changes only
+
+  notes:
+    change date:    Changes.txt, Announce.txt, index.htm, README.txt,
+                    qhull-news.html, Eudora signatures, CMakeLists.txt
+    change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt, CMakeLists.txt
+    check that CMakeLists.txt @version is the same as qh_version2
+    change year:    Copying.txt
+    check download size
+    recompile user_eg_r.c, rbox_r.c, libqhull_r.c, qconvex_r.c, qdelaun_r.c qvoronoi_r.c, qhalf_r.c, testqset_r.c
+*/
+
+const char qh_version[]= "2020.2.r 2023/01/02";
+const char qh_version2[]= "qhull_r 8.1-alpha3 (2020.2.r 2023/01/02)";
+
+/*---------------------------------
+
+  qh_appendprint(qh, printFormat )
+    append printFormat to qh.PRINTout unless already defined
+*/
+void qh_appendprint(qhT *qh, qh_PRINT format) {
+  int i;
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    if (qh->PRINTout[i] == format && format != qh_PRINTqhull)
+      break;
+    if (!qh->PRINTout[i]) {
+      qh->PRINTout[i]= format;
+      break;
+    }
+  }
+} /* appendprint */
+
+/*---------------------------------
+
+  qh_checkflags(qh, commandStr, hiddenFlags )
+    errors if commandStr contains hiddenFlags
+    hiddenFlags starts and ends with a space and is space delimited (checked)
+
+  notes:
+    ignores first word (e.g., "qconvex i")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initflags() initializes Qhull according to commandStr
+*/
+void qh_checkflags(qhT *qh, char *command, char *hiddenflags) {
+  char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
+  char key, opt, prevopt;
+  char chkkey[]=  "   ";    /* check one character options ('s') */
+  char chkopt[]=  "    ";   /* check two character options ('Ta') */
+  char chkopt2[]= "     ";  /* check three character options ('Q12') */
+  boolT waserr= False;
+
+  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
+    qh_fprintf(qh, qh->ferr, 6026, "qhull internal error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"\n", hiddenflags);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (strpbrk(hiddenflags, ",\n\r\t")) {
+    qh_fprintf(qh, qh->ferr, 6027, "qhull internal error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"\n", hiddenflags);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    key= *s++;
+    chkerr= NULL;
+    if (key == 'T' && (*s == 'I' || *s == 'O')) {  /* TI or TO 'file name' */
+      s= qh_skipfilename(qh, ++s);
+      continue;
+    }
+    chkkey[1]= key;
+    if (strstr(hiddenflags, chkkey)) {
+      chkerr= chkkey;
+    }else if (isupper(key)) {
+      opt= ' ';
+      prevopt= ' ';
+      chkopt[1]= key;
+      chkopt2[1]= key;
+      while (!chkerr && *s && !isspace(*s)) {
+        opt= *s++;
+        if (isalpha(opt)) {
+          chkopt[2]= opt;
+          if (strstr(hiddenflags, chkopt))
+            chkerr= chkopt;
+          if (prevopt != ' ') {
+            chkopt2[2]= prevopt;
+            chkopt2[3]= opt;
+            if (strstr(hiddenflags, chkopt2))
+              chkerr= chkopt2;
+          }
+        }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
+              && (prevopt == ' ' || islower(prevopt))) {
+            if (isdigit(*s)) {  /* Q12 */
+              chkopt2[2]= opt;
+              chkopt2[3]= *s++;
+              if (strstr(hiddenflags, chkopt2))
+                chkerr= chkopt2;
+            }else {
+              chkopt[2]= opt;
+              if (strstr(hiddenflags, chkopt))
+                chkerr= chkopt;
+            }
+        }else {
+          qh_strtod(s-1, &t);
+          if (s < t)
+            s= t;
+        }
+        prevopt= opt;
+      }
+    }
+    if (chkerr) {
+      *chkerr= '\'';
+      chkerr[strlen(chkerr)-1]=  '\'';
+      qh_fprintf(qh, qh->ferr, 6029, "qhull option error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
+      waserr= True;
+    }
+  }
+  if (waserr)
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+} /* checkflags */
+
+/*---------------------------------
+
+  qh_clear_outputflags(qh)
+    Clear output flags for QhullPoints
+*/
+void qh_clear_outputflags(qhT *qh) {
+  int i,k;
+
+  qh->ANNOTATEoutput= False;
+  qh->DOintersections= False;
+  qh->DROPdim= -1;
+  qh->FORCEoutput= False;
+  qh->GETarea= False;
+  qh->GOODpoint= 0;
+  qh->GOODpointp= NULL;
+  qh->GOODthreshold= False;
+  qh->GOODvertex= 0;
+  qh->GOODvertexp= NULL;
+  qh->IStracing= 0;
+  qh->KEEParea= False;
+  qh->KEEPmerge= False;
+  qh->KEEPminArea= REALmax;
+  qh->PRINTcentrums= False;
+  qh->PRINTcoplanar= False;
+  qh->PRINTdots= False;
+  qh->PRINTgood= False;
+  qh->PRINTinner= False;
+  qh->PRINTneighbors= False;
+  qh->PRINTnoplanes= False;
+  qh->PRINToptions1st= False;
+  qh->PRINTouter= False;
+  qh->PRINTprecision= True;
+  qh->PRINTridges= False;
+  qh->PRINTspheres= False;
+  qh->PRINTstatistics= False;
+  qh->PRINTsummary= False;
+  qh->PRINTtransparent= False;
+  qh->SPLITthresholds= False;
+  qh->TRACElevel= 0;
+  qh->TRInormals= False;
+  qh->USEstdout= False;
+  qh->VERIFYoutput= False;
+  for (k=qh->input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
+    qh->lower_threshold[k]= -REALmax;
+    qh->upper_threshold[k]= REALmax;
+    qh->lower_bound[k]= -REALmax;
+    qh->upper_bound[k]= REALmax;
+  }
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    qh->PRINTout[i]= qh_PRINTnone;
+  }
+
+  if (!qh->qhull_commandsiz2)
+      qh->qhull_commandsiz2= (int)strlen(qh->qhull_command); /* WARN64 */
+  else {
+      qh->qhull_command[qh->qhull_commandsiz2]= '\0';
+  }
+  if (!qh->qhull_optionsiz2)
+    qh->qhull_optionsiz2= (int)strlen(qh->qhull_options);  /* WARN64 */
+  else {
+    qh->qhull_options[qh->qhull_optionsiz2]= '\0';
+    qh->qhull_optionlen= qh_OPTIONline;  /* start a new line */
+  }
+} /* clear_outputflags */
+
+/*---------------------------------
+
+  qh_clock()
+    return user CPU time in 100ths (qh_SECtick)
+    only defined for qh_CLOCKtype == 2
+
+  notes:
+    use first value to determine time 0
+    from Stevens '92 8.15
+*/
+unsigned long qh_clock(qhT *qh) {
+
+#if (qh_CLOCKtype == 2)
+  struct tms time;
+  static long clktck;  /* initialized first call and never updated */
+  double ratio, cpu;
+  unsigned long ticks;
+
+  if (!clktck) {
+    if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
+      qh_fprintf(qh, qh->ferr, 6030, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user_r.h\n");
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+  }
+  if (times(&time) == -1) {
+    qh_fprintf(qh, qh->ferr, 6031, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user_r.h\n");
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  ratio= qh_SECticks / (double)clktck;
+  ticks= time.tms_utime * ratio;
+  return ticks;
+#else
+  qh_fprintf(qh, qh->ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user_r.h\n");
+  qh_errexit(qh, qh_ERRqhull, NULL, NULL); /* never returns */
+  return 0;
+#endif
+} /* clock */
+
+/*---------------------------------
+
+  qh_freebuffers()
+    free up global memory buffers
+
+  notes:
+    must match qh_initbuffers()
+*/
+void qh_freebuffers(qhT *qh) {
+
+  trace5((qh, qh->ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
+  /* allocated by qh_initqhull_buffers */
+  qh_setfree(qh, &qh->other_points);
+  qh_setfree(qh, &qh->del_vertices);
+  qh_setfree(qh, &qh->coplanarfacetset);
+  qh_memfree(qh, qh->NEARzero, qh->hull_dim * (int)sizeof(realT));
+  qh_memfree(qh, qh->lower_threshold, (qh->input_dim+1) * (int)sizeof(realT));
+  qh_memfree(qh, qh->upper_threshold, (qh->input_dim+1) * (int)sizeof(realT));
+  qh_memfree(qh, qh->lower_bound, (qh->input_dim+1) * (int)sizeof(realT));
+  qh_memfree(qh, qh->upper_bound, (qh->input_dim+1) * (int)sizeof(realT));
+  qh_memfree(qh, qh->gm_matrix, (qh->hull_dim+1) * qh->hull_dim * (int)sizeof(coordT));
+  qh_memfree(qh, qh->gm_row, (qh->hull_dim+1) * (int)sizeof(coordT *));
+  qh->NEARzero= qh->lower_threshold= qh->upper_threshold= NULL;
+  qh->lower_bound= qh->upper_bound= NULL;
+  qh->gm_matrix= NULL;
+  qh->gm_row= NULL;
+
+  if (qh->line)                /* allocated by qh_readinput, freed if no error */
+    qh_free(qh->line);
+  if (qh->half_space)
+    qh_free(qh->half_space);
+  if (qh->temp_malloc)
+    qh_free(qh->temp_malloc);
+  if (qh->feasible_point)      /* allocated by qh_readfeasible */
+    qh_free(qh->feasible_point);
+  if (qh->feasible_string)     /* allocated by qh_initflags */
+    qh_free(qh->feasible_string);
+  qh->line= qh->feasible_string= NULL;
+  qh->half_space= qh->feasible_point= qh->temp_malloc= NULL;
+  /* usually allocated by qh_readinput */
+  if (qh->first_point && qh->POINTSmalloc) {
+    qh_free(qh->first_point);
+    qh->first_point= NULL;
+  }
+  if (qh->input_points && qh->input_malloc) { /* set by qh_joggleinput */
+    qh_free(qh->input_points);
+    qh->input_points= NULL;
+  }
+  trace5((qh, qh->ferr, 5002, "qh_freebuffers: finished\n"));
+} /* freebuffers */
+
+
+/*---------------------------------
+
+  qh_freebuild(qh, allmem )
+    free global memory used by qh_initbuild and qh_buildhull
+    if !allmem,
+      does not free short memory (e.g., facetT, freed by qh_memfreeshort)
+
+  design:
+    free centrums
+    free each vertex
+    for each facet
+      free ridges
+      free outside set, coplanar set, neighbor set, ridge set, vertex set
+      free facet
+    free hash table
+    free interior point
+    free merge sets
+    free temporary sets
+*/
+void qh_freebuild(qhT *qh, boolT allmem) {
+  facetT *facet, *previousfacet= NULL;
+  vertexT *vertex, *previousvertex= NULL;
+  ridgeT *ridge, **ridgep, *previousridge= NULL;
+  mergeT *merge, **mergep;
+  int newsize;
+  boolT freeall;
+
+  /* free qhT global sets first, includes references from qh_buildhull */
+  trace5((qh, qh->ferr, 5004, "qh_freebuild: free global sets\n"));
+  FOREACHmerge_(qh->facet_mergeset)  /* usually empty */
+    qh_memfree(qh, merge, (int)sizeof(mergeT));
+  FOREACHmerge_(qh->degen_mergeset)  /* usually empty */
+    qh_memfree(qh, merge, (int)sizeof(mergeT));
+  FOREACHmerge_(qh->vertex_mergeset)  /* usually empty */
+    qh_memfree(qh, merge, (int)sizeof(mergeT));
+  qh->facet_mergeset= NULL;  /* temp set freed by qh_settempfree_all */
+  qh->degen_mergeset= NULL;  /* temp set freed by qh_settempfree_all */
+  qh->vertex_mergeset= NULL;  /* temp set freed by qh_settempfree_all */
+  qh_setfree(qh, &(qh->hash_table));
+  trace5((qh, qh->ferr, 5003, "qh_freebuild: free temporary sets (qh_settempfree_all)\n"));
+  qh_settempfree_all(qh);
+  trace1((qh, qh->ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
+  if (qh->del_vertices)
+    qh_settruncate(qh, qh->del_vertices, 0);
+  if (allmem) {
+    while ((vertex= qh->vertex_list)) {
+      if (vertex->next)
+        qh_delvertex(qh, vertex);
+      else {
+        qh_memfree(qh, vertex, (int)sizeof(vertexT)); /* sentinel */
+        qh->newvertex_list= qh->vertex_list= NULL;
+        break;
+      }
+      previousvertex= vertex; /* in case of memory fault */
+      QHULL_UNUSED(previousvertex)
+    }
+  }else if (qh->VERTEXneighbors) {
+    FORALLvertices
+      qh_setfreelong(qh, &(vertex->neighbors));
+  }
+  qh->VERTEXneighbors= False;
+  qh->GOODclosest= NULL;
+  if (allmem) {
+    FORALLfacets {
+      FOREACHridge_(facet->ridges)
+        ridge->seen= False;
+    }
+    while ((facet= qh->facet_list)) {
+      if (!facet->newfacet || !qh->NEWtentative || qh_setsize(qh, facet->ridges) > 1) { /* skip tentative horizon ridges */
+        trace4((qh, qh->ferr, 4095, "qh_freebuild: delete the previously-seen ridges of f%d\n", facet->id));
+        FOREACHridge_(facet->ridges) {
+          if (ridge->seen)
+            qh_delridge(qh, ridge);
+          else
+            ridge->seen= True;
+          previousridge= ridge; /* in case of memory fault */
+          QHULL_UNUSED(previousridge)
+        }
+      }
+      qh_setfree(qh, &(facet->outsideset));
+      qh_setfree(qh, &(facet->coplanarset));
+      qh_setfree(qh, &(facet->neighbors));
+      qh_setfree(qh, &(facet->ridges));
+      qh_setfree(qh, &(facet->vertices));
+      if (facet->next)
+        qh_delfacet(qh, facet);
+      else {
+        qh_memfree(qh, facet, (int)sizeof(facetT));
+        qh->visible_list= qh->newfacet_list= qh->facet_list= NULL;
+      }
+      previousfacet= facet; /* in case of memory fault */
+      QHULL_UNUSED(previousfacet)
+    }
+  }else {
+    freeall= True;
+    if (qh_setlarger_quick(qh, qh->hull_dim + 1, &newsize))
+      freeall= False;
+    FORALLfacets {
+      qh_setfreelong(qh, &(facet->outsideset));
+      qh_setfreelong(qh, &(facet->coplanarset));
+      if (!facet->simplicial || freeall) {
+        qh_setfreelong(qh, &(facet->neighbors));
+        qh_setfreelong(qh, &(facet->ridges));
+        qh_setfreelong(qh, &(facet->vertices));
+      }
+    }
+  }
+  /* qh internal constants */
+  qh_memfree(qh, qh->interior_point, qh->normal_size);
+  qh->interior_point= NULL;
+} /* freebuild */
+
+/*---------------------------------
+
+  qh_freeqhull(qh, allmem )
+
+  free global memory and set qhT to 0
+  if !allmem,
+    does not free short memory (freed by qh_memfreeshort unless qh_NOmem)
+
+notes:
+  sets qh.NOerrexit in case caller forgets to
+  Does not throw errors
+
+see:
+  see qh_initqhull_start2()
+  For libqhull_r, qhstatT is part of qhT
+
+design:
+  free global and temporary memory from qh_initbuild and qh_buildhull
+  free buffers
+*/
+void qh_freeqhull(qhT *qh, boolT allmem) {
+
+  qh->NOerrexit= True;  /* no more setjmp since called at exit and ~QhullQh */
+  trace1((qh, qh->ferr, 1006, "qh_freeqhull: free global memory\n"));
+  qh_freebuild(qh, allmem);
+  qh_freebuffers(qh);
+  trace1((qh, qh->ferr, 1061, "qh_freeqhull: clear qhT except for qh.qhmem and qh.qhstat\n"));
+  /* memset is the same in qh_freeqhull() and qh_initqhull_start2() */
+  memset((char *)qh, 0, sizeof(qhT)-sizeof(qhmemT)-sizeof(qhstatT));
+  qh->NOerrexit= True;
+} /* freeqhull */
+
+/*---------------------------------
+
+  qh_init_A(qh, infile, outfile, errfile, argc, argv )
+    initialize memory and stdio files
+    convert input options to option string (qh.qhull_command)
+
+  notes:
+    infile may be NULL if qh_readpoints() is not called
+
+    errfile should always be defined.  It is used for reporting
+    errors.  outfile is used for output and format options.
+
+    argc/argv may be 0/NULL
+
+    called before error handling initialized
+    qh_errexit() may not be used
+*/
+void qh_init_A(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
+  qh_meminit(qh, errfile);
+  qh_initqhull_start(qh, infile, outfile, errfile);
+  qh_init_qhull_command(qh, argc, argv);
+} /* init_A */
+
+/*---------------------------------
+
+  qh_init_B(qh, points, numpoints, dim, ismalloc )
+    initialize globals for points array
+
+    points has numpoints dim-dimensional points
+      points[0] is the first coordinate of the first point
+      points[1] is the second coordinate of the first point
+      points[dim] is the first coordinate of the second point
+
+    ismalloc=True
+      Qhull will call qh_free(points) on exit or input transformation
+    ismalloc=False
+      Qhull will allocate a new point array if needed for input transformation
+
+    qh.qhull_command
+      is the option string.
+      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
+
+  returns:
+    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
+      projects the input to a new point array
+
+        if qh.DELAUNAY,
+          qh.hull_dim is increased by one
+        if qh.ATinfinity,
+          qh_projectinput adds point-at-infinity for Delaunay tri.
+
+    if qh.SCALEinput
+      changes the upper and lower bounds of the input, see qh_scaleinput
+
+    if qh.ROTATEinput
+      rotates the input by a random rotation, see qh_rotateinput
+      if qh.DELAUNAY
+        rotates about the last coordinate
+
+  notes:
+    called after points are defined
+    qh_errexit() may be used
+*/
+void qh_init_B(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc) {
+  qh_initqhull_globals(qh, points, numpoints, dim, ismalloc);
+  if (qh->qhmem.LASTsize == 0)
+    qh_initqhull_mem(qh);
+  /* mem_r.c and qset_r.c are initialized */
+  qh_initqhull_buffers(qh);
+  qh_initthresholds(qh, qh->qhull_command);
+  if (qh->PROJECTinput || (qh->DELAUNAY && qh->PROJECTdelaunay))
+    qh_projectinput(qh);
+  if (qh->SCALEinput)
+    qh_scaleinput(qh);
+  if (qh->ROTATErandom >= 0) {
+    qh_randommatrix(qh, qh->gm_matrix, qh->hull_dim, qh->gm_row);
+    if (qh->DELAUNAY) {
+      int k, lastk= qh->hull_dim-1;
+      for (k=0; k < lastk; k++) {
+        qh->gm_row[k][lastk]= 0.0;
+        qh->gm_row[lastk][k]= 0.0;
+      }
+      qh->gm_row[lastk][lastk]= 1.0;
+    }
+    qh_gram_schmidt(qh, qh->hull_dim, qh->gm_row);
+    qh_rotateinput(qh, qh->gm_row);
+  }
+} /* init_B */
+
+/*---------------------------------
+
+  qh_init_qhull_command(qh, argc, argv )
+    build qh.qhull_command from argc/argv
+    Calls qh_exit if qhull_command is too short
+
+  returns:
+    a space-delimited string of options (just as typed)
+
+  notes:
+    makes option string easy to input and output
+
+    argc/argv may be 0/NULL
+*/
+void qh_init_qhull_command(qhT *qh, int argc, char *argv[]) {
+
+  if (!qh_argv_to_command(argc, argv, qh->qhull_command, (int)sizeof(qh->qhull_command))){
+    /* Assumes qh.ferr is defined. */
+    qh_fprintf(qh, qh->ferr, 6033, "qhull input error: more than %d characters in command line.\n",
+          (int)sizeof(qh->qhull_command));
+    qh_exit(qh_ERRinput);  /* error reported, can not use qh_errexit */
+  }
+} /* init_qhull_command */
+
+/*---------------------------------
+
+  qh_initflags(qh, commandStr )
+    set flags and initialized constants from commandStr
+    calls qh_exit() if qh.NOerrexit
+
+  returns:
+    sets qh.qhull_command to command if needed
+
+  notes:
+    ignores first word (e.g., 'qhull' in "qhull d")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
+    'prompt' in unix_r.c for documentation
+
+  design:
+    for each space-delimited option group
+      if top-level option
+        check syntax
+        append appropriate option to option string
+        set appropriate global variable or append printFormat to print options
+      else
+        for each sub-option
+          check syntax
+          append appropriate option to option string
+          set appropriate global variable or append printFormat to print options
+*/
+void qh_initflags(qhT *qh, char *command) {
+  int k, i, lastproject;
+  char *s= command, *t, *prev_s, *start, key, *lastwarning= NULL;
+  boolT isgeom= False, wasproject;
+  realT r;
+
+  if(qh->NOerrexit){
+    qh_fprintf(qh, qh->ferr, 6245, "qhull internal error (qh_initflags): qh.NOerrexit was not cleared before calling qh_initflags().  It should be cleared after setjmp().  Exit qhull.\n");
+    qh_exit(qh_ERRqhull);
+  }
+#ifdef qh_RANDOMdist
+  qh->RANDOMfactor= qh_RANDOMdist;
+  qh_option(qh, "Random-qh_RANDOMdist", NULL, &qh->RANDOMfactor);
+  qh->RANDOMdist= True;
+#endif
+  if (command <= &qh->qhull_command[0] || command > &qh->qhull_command[0] + sizeof(qh->qhull_command)) {
+    if (command != &qh->qhull_command[0]) {
+      *qh->qhull_command= '\0';
+      strncat(qh->qhull_command, command, sizeof(qh->qhull_command)-strlen(qh->qhull_command)-1);
+    }
+    while (*s && !isspace(*s))  /* skip program name */
+      s++;
+  }
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    prev_s= s;
+    switch (*s++) {
+    case 'd':
+      qh_option(qh, "delaunay", NULL, NULL);
+      qh->DELAUNAY= True;
+      break;
+    case 'f':
+      qh_option(qh, "facets", NULL, NULL);
+      qh_appendprint(qh, qh_PRINTfacets);
+      break;
+    case 'i':
+      qh_option(qh, "incidence", NULL, NULL);
+      qh_appendprint(qh, qh_PRINTincidences);
+      break;
+    case 'm':
+      qh_option(qh, "mathematica", NULL, NULL);
+      qh_appendprint(qh, qh_PRINTmathematica);
+      break;
+    case 'n':
+      qh_option(qh, "normals", NULL, NULL);
+      qh_appendprint(qh, qh_PRINTnormals);
+      break;
+    case 'o':
+      qh_option(qh, "offFile", NULL, NULL);
+      qh_appendprint(qh, qh_PRINToff);
+      break;
+    case 'p':
+      qh_option(qh, "points", NULL, NULL);
+      qh_appendprint(qh, qh_PRINTpoints);
+      break;
+    case 's':
+      qh_option(qh, "summary", NULL, NULL);
+      qh->PRINTsummary= True;
+      break;
+    case 'v':
+      qh_option(qh, "voronoi", NULL, NULL);
+      qh->VORONOI= True;
+      qh->DELAUNAY= True;
+      break;
+    case 'A':
+      if (!isdigit(*s) && *s != '.' && *s != '-') {
+        qh_fprintf(qh, qh->ferr, 7002, "qhull input warning: no maximum cosine angle given for option 'An'.  A1.0 is coplanar\n");
+        lastwarning= s-1;
+      }else {
+        if (*s == '-') {
+          qh->premerge_cos= -qh_strtod(s, &s);
+          qh_option(qh, "Angle-premerge-", NULL, &qh->premerge_cos);
+          qh->PREmerge= True;
+        }else {
+          qh->postmerge_cos= qh_strtod(s, &s);
+          qh_option(qh, "Angle-postmerge", NULL, &qh->postmerge_cos);
+          qh->POSTmerge= True;
+        }
+        qh->MERGING= True;
+      }
+      break;
+    case 'C':
+      if (!isdigit(*s) && *s != '.' && *s != '-') {
+        qh_fprintf(qh, qh->ferr, 7003, "qhull input warning: no centrum radius given for option 'Cn'\n");
+        lastwarning= s-1;
+      }else {
+        if (*s == '-') {
+          qh->premerge_centrum= -qh_strtod(s, &s);
+          qh_option(qh, "Centrum-premerge-", NULL, &qh->premerge_centrum);
+          qh->PREmerge= True;
+        }else {
+          qh->postmerge_centrum= qh_strtod(s, &s);
+          qh_option(qh, "Centrum-postmerge", NULL, &qh->postmerge_centrum);
+          qh->POSTmerge= True;
+        }
+        qh->MERGING= True;
+      }
+      break;
+    case 'E':
+      if (*s == '-') {
+        qh_fprintf(qh, qh->ferr, 6363, "qhull option error: expecting a positive number for maximum roundoff 'En'.  Got '%s'\n", s-1);
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }else if (!isdigit(*s)) {
+        qh_fprintf(qh, qh->ferr, 7005, "qhull option warning: no maximum roundoff given for option 'En'\n");
+        lastwarning= s-1;
+      }else {
+        qh->DISTround= qh_strtod(s, &s);
+        qh_option(qh, "Distance-roundoff", NULL, &qh->DISTround);
+        qh->SETroundoff= True;
+      }
+      break;
+    case 'H':
+      start= s;
+      qh->HALFspace= True;
+      qh_strtod(s, &t);
+      while (t > s)  {
+        if (*t && !isspace(*t)) {
+          if (*t == ',')
+            t++;
+          else {
+            qh_fprintf(qh, qh->ferr, 6364, "qhull option error: expecting 'Hn,n,n,...' for feasible point of halfspace intersection. Got '%s'\n", start-1);
+            qh_errexit(qh, qh_ERRinput, NULL, NULL);
+          }
+        }
+        s= t;
+        qh_strtod(s, &t);
+      }
+      if (start < t) {
+        if (!(qh->feasible_string= (char *)calloc((size_t)(t-start+1), (size_t)1))) {
+          qh_fprintf(qh, qh->ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
+          qh_errexit(qh, qh_ERRmem, NULL, NULL);
+        }
+        strncpy(qh->feasible_string, start, (size_t)(t-start));
+        qh_option(qh, "Halfspace-about", NULL, NULL);
+        qh_option(qh, qh->feasible_string, NULL, NULL);
+      }else
+        qh_option(qh, "Halfspace", NULL, NULL);
+      break;
+    case 'R':
+      if (!isdigit(*s)) {
+        qh_fprintf(qh, qh->ferr, 7007, "qhull option warning: missing random perturbation for option 'Rn'\n");
+        lastwarning= s-1;
+      }else {
+        qh->RANDOMfactor= qh_strtod(s, &s);
+        qh_option(qh, "Random-perturb", NULL, &qh->RANDOMfactor);
+        qh->RANDOMdist= True;
+      }
+      break;
+    case 'V':
+      if (!isdigit(*s) && *s != '-') {
+        qh_fprintf(qh, qh->ferr, 7008, "qhull option warning: missing visible distance for option 'Vn'\n");
+        lastwarning= s-1;
+      }else {
+        qh->MINvisible= qh_strtod(s, &s);
+        qh_option(qh, "Visible", NULL, &qh->MINvisible);
+      }
+      break;
+    case 'U':
+      if (!isdigit(*s) && *s != '-') {
+        qh_fprintf(qh, qh->ferr, 7009, "qhull option warning: missing coplanar distance for option 'Un'\n");
+        lastwarning= s-1;
+      }else {
+        qh->MAXcoplanar= qh_strtod(s, &s);
+        qh_option(qh, "U-coplanar", NULL, &qh->MAXcoplanar);
+      }
+      break;
+    case 'W':
+      if (*s == '-') {
+        qh_fprintf(qh, qh->ferr, 6365, "qhull option error: expecting a positive number for outside width 'Wn'.  Got '%s'\n", s-1);
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }else if (!isdigit(*s)) {
+        qh_fprintf(qh, qh->ferr, 7011, "qhull option warning: missing outside width for option 'Wn'\n");
+        lastwarning= s-1;
+      }else {
+        qh->MINoutside= qh_strtod(s, &s);
+        qh_option(qh, "W-outside", NULL, &qh->MINoutside);
+        qh->APPROXhull= True;
+      }
+      break;
+    /************  sub menus ***************/
+    case 'F':
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'a':
+          qh_option(qh, "Farea", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTarea);
+          qh->GETarea= True;
+          break;
+        case 'A':
+          qh_option(qh, "FArea-total", NULL, NULL);
+          qh->GETarea= True;
+          break;
+        case 'c':
+          qh_option(qh, "Fcoplanars", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTcoplanars);
+          break;
+        case 'C':
+          qh_option(qh, "FCentrums", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTcentrums);
+          break;
+        case 'd':
+          qh_option(qh, "Fd-cdd-in", NULL, NULL);
+          qh->CDDinput= True;
+          break;
+        case 'D':
+          qh_option(qh, "FD-cdd-out", NULL, NULL);
+          qh->CDDoutput= True;
+          break;
+        case 'F':
+          qh_option(qh, "FFacets-xridge", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTfacets_xridge);
+          break;
+        case 'i':
+          qh_option(qh, "Finner", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTinner);
+          break;
+        case 'I':
+          qh_option(qh, "FIDs", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTids);
+          break;
+        case 'm':
+          qh_option(qh, "Fmerges", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTmerges);
+          break;
+        case 'M':
+          qh_option(qh, "FMaple", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTmaple);
+          break;
+        case 'n':
+          qh_option(qh, "Fneighbors", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTneighbors);
+          break;
+        case 'N':
+          qh_option(qh, "FNeighbors-vertex", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTvneighbors);
+          break;
+        case 'o':
+          qh_option(qh, "Fouter", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTouter);
+          break;
+        case 'O':
+          if (qh->PRINToptions1st) {
+            qh_option(qh, "FOptions", NULL, NULL);
+            qh_appendprint(qh, qh_PRINToptions);
+          }else
+            qh->PRINToptions1st= True;
+          break;
+        case 'p':
+          qh_option(qh, "Fpoint-intersect", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTpointintersect);
+          break;
+        case 'P':
+          qh_option(qh, "FPoint-nearest", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTpointnearest);
+          break;
+        case 'Q':
+          qh_option(qh, "FQhull", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTqhull);
+          break;
+        case 's':
+          qh_option(qh, "Fsummary", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTsummary);
+          break;
+        case 'S':
+          qh_option(qh, "FSize", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTsize);
+          qh->GETarea= True;
+          break;
+        case 't':
+          qh_option(qh, "Ftriangles", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTtriangles);
+          break;
+        case 'v':
+          /* option set in qh_initqhull_globals */
+          qh_appendprint(qh, qh_PRINTvertices);
+          break;
+        case 'V':
+          qh_option(qh, "FVertex-average", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTaverage);
+          break;
+        case 'x':
+          qh_option(qh, "Fxtremes", NULL, NULL);
+          qh_appendprint(qh, qh_PRINTextremes);
+          break;
+        default:
+          s--;
+          qh_fprintf(qh, qh->ferr, 7012, "qhull option warning: unknown 'F' output option 'F%c', skip to next space\n", (int)s[0]);
+          lastwarning= s-1;
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'G':
+      isgeom= True;
+      qh_appendprint(qh, qh_PRINTgeom);
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'a':
+          qh_option(qh, "Gall-points", NULL, NULL);
+          qh->PRINTdots= True;
+          break;
+        case 'c':
+          qh_option(qh, "Gcentrums", NULL, NULL);
+          qh->PRINTcentrums= True;
+          break;
+        case 'h':
+          qh_option(qh, "Gintersections", NULL, NULL);
+          qh->DOintersections= True;
+          break;
+        case 'i':
+          qh_option(qh, "Ginner", NULL, NULL);
+          qh->PRINTinner= True;
+          break;
+        case 'n':
+          qh_option(qh, "Gno-planes", NULL, NULL);
+          qh->PRINTnoplanes= True;
+          break;
+        case 'o':
+          qh_option(qh, "Gouter", NULL, NULL);
+          qh->PRINTouter= True;
+          break;
+        case 'p':
+          qh_option(qh, "Gpoints", NULL, NULL);
+          qh->PRINTcoplanar= True;
+          break;
+        case 'r':
+          qh_option(qh, "Gridges", NULL, NULL);
+          qh->PRINTridges= True;
+          break;
+        case 't':
+          qh_option(qh, "Gtransparent", NULL, NULL);
+          qh->PRINTtransparent= True;
+          break;
+        case 'v':
+          qh_option(qh, "Gvertices", NULL, NULL);
+          qh->PRINTspheres= True;
+          break;
+        case 'D':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7004, "qhull option warning: missing dimension for option 'GDn'\n");
+            lastwarning= s-2;
+          }else {
+            if (qh->DROPdim >= 0) {
+              qh_fprintf(qh, qh->ferr, 7013, "qhull option warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
+                   qh->DROPdim);
+              lastwarning= s-2;
+            }
+            qh->DROPdim= qh_strtol(s, &s);
+            qh_option(qh, "GDrop-dim", &qh->DROPdim, NULL);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh, qh->ferr, 7014, "qhull option warning: unknown 'G' geomview option 'G%c', skip to next space\n", (int)s[0]);
+          lastwarning= s-1;
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'P':
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'd': case 'D':  /* see qh_initthresholds() */
+          key= s[-1];
+          i= qh_strtol(s, &s);
+          r= 0;
+          if (*s == ':') {
+            s++;
+            r= qh_strtod(s, &s);
+          }
+          if (key == 'd')
+            qh_option(qh, "Pdrop-facets-dim-less", &i, &r);
+          else
+            qh_option(qh, "PDrop-facets-dim-more", &i, &r);
+          break;
+        case 'g':
+          qh_option(qh, "Pgood-facets", NULL, NULL);
+          qh->PRINTgood= True;
+          break;
+        case 'G':
+          qh_option(qh, "PGood-facet-neighbors", NULL, NULL);
+          qh->PRINTneighbors= True;
+          break;
+        case 'o':
+          qh_option(qh, "Poutput-forced", NULL, NULL);
+          qh->FORCEoutput= True;
+          break;
+        case 'p':
+          qh_option(qh, "Pprecision-ignore", NULL, NULL);
+          qh->PRINTprecision= False;
+          break;
+        case 'A':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7006, "qhull option warning: missing facet count for keep area option 'PAn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->KEEParea= qh_strtol(s, &s);
+            qh_option(qh, "PArea-keep", &qh->KEEParea, NULL);
+            qh->GETarea= True;
+          }
+          break;
+        case 'F':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7010, "qhull option warning: missing facet area for option 'PFn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->KEEPminArea= qh_strtod(s, &s);
+            qh_option(qh, "PFacet-area-keep", NULL, &qh->KEEPminArea);
+            qh->GETarea= True;
+          }
+          break;
+        case 'M':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7090, "qhull option warning: missing merge count for option 'PMn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->KEEPmerge= qh_strtol(s, &s);
+            qh_option(qh, "PMerge-keep", &qh->KEEPmerge, NULL);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh, qh->ferr, 7015, "qhull option warning: unknown 'P' print option 'P%c', skip to next space\n", (int)s[0]);
+          lastwarning= s-1;
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'Q':
+      lastproject= -1;
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'a':
+          qh_option(qh, "Qallow-short", NULL, NULL);
+          qh->ALLOWshort= True;
+          break;
+        case 'b': case 'B':  /* handled by qh_initthresholds */
+          key= s[-1];
+          if (key == 'b' && *s == 'B') {
+            s++;
+            r= qh_DEFAULTbox;
+            qh->SCALEinput= True;
+            qh_option(qh, "QbBound-unit-box", NULL, &r);
+            break;
+          }
+          if (key == 'b' && *s == 'b') {
+            s++;
+            qh->SCALElast= True;
+            qh_option(qh, "Qbbound-last", NULL, NULL);
+            break;
+          }
+          k= qh_strtol(s, &s);
+          r= 0.0;
+          wasproject= False;
+          if (*s == ':') {
+            s++;
+            if ((r= qh_strtod(s, &s)) == 0.0) {
+              t= s;            /* need true dimension for memory allocation */
+              while (*t && !isspace(*t)) {
+                if (toupper(*t++) == 'B'
+                 && k == qh_strtol(t, &t)
+                 && *t++ == ':'
+                 && qh_strtod(t, &t) == 0.0) {
+                  qh->PROJECTinput++;
+                  trace2((qh, qh->ferr, 2004, "qh_initflags: project dimension %d\n", k));
+                  qh_option(qh, "Qb-project-dim", &k, NULL);
+                  wasproject= True;
+                  lastproject= k;
+                  break;
+                }
+              }
+            }
+          }
+          if (!wasproject) {
+            if (lastproject == k && r == 0.0)
+              lastproject= -1;  /* doesn't catch all possible sequences */
+            else if (key == 'b') {
+              qh->SCALEinput= True;
+              if (r == 0.0)
+                r= -qh_DEFAULTbox;
+              qh_option(qh, "Qbound-dim-low", &k, &r);
+            }else {
+              qh->SCALEinput= True;
+              if (r == 0.0)
+                r= qh_DEFAULTbox;
+              qh_option(qh, "QBound-dim-high", &k, &r);
+            }
+          }
+          break;
+        case 'c':
+          qh_option(qh, "Qcoplanar-keep", NULL, NULL);
+          qh->KEEPcoplanar= True;
+          break;
+        case 'f':
+          qh_option(qh, "Qfurthest-outside", NULL, NULL);
+          qh->BESToutside= True;
+          break;
+        case 'g':
+          qh_option(qh, "Qgood-facets-only", NULL, NULL);
+          qh->ONLYgood= True;
+          break;
+        case 'i':
+          qh_option(qh, "Qinterior-keep", NULL, NULL);
+          qh->KEEPinside= True;
+          break;
+        case 'm':
+          qh_option(qh, "Qmax-outside-only", NULL, NULL);
+          qh->ONLYmax= True;
+          break;
+        case 'r':
+          qh_option(qh, "Qrandom-outside", NULL, NULL);
+          qh->RANDOMoutside= True;
+          break;
+        case 's':
+          qh_option(qh, "Qsearch-initial-simplex", NULL, NULL);
+          qh->ALLpoints= True;
+          break;
+        case 't':
+          qh_option(qh, "Qtriangulate", NULL, NULL);
+          qh->TRIangulate= True;
+          break;
+        case 'T':
+          qh_option(qh, "QTestPoints", NULL, NULL);
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7091, "qhull option warning: missing number of test points for option 'QTn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->TESTpoints= qh_strtol(s, &s);
+            qh_option(qh, "QTestPoints", &qh->TESTpoints, NULL);
+          }
+          break;
+        case 'u':
+          qh_option(qh, "QupperDelaunay", NULL, NULL);
+          qh->UPPERdelaunay= True;
+          break;
+        case 'v':
+          qh_option(qh, "Qvertex-neighbors-convex", NULL, NULL);
+          qh->TESTvneighbors= True;
+          break;
+        case 'x':
+          qh_option(qh, "Qxact-merge", NULL, NULL);
+          qh->MERGEexact= True;
+          break;
+        case 'z':
+          qh_option(qh, "Qz-infinity-point", NULL, NULL);
+          qh->ATinfinity= True;
+          break;
+        case '0':
+          qh_option(qh, "Q0-no-premerge", NULL, NULL);
+          qh->NOpremerge= True;
+          break;
+        case '1':
+          if (!isdigit(*s)) {
+            qh_option(qh, "Q1-angle-merge", NULL, NULL);
+            qh->ANGLEmerge= True;
+            break;
+          }
+          switch (*s++) {
+          case '0':
+            qh_option(qh, "Q10-no-narrow", NULL, NULL);
+            qh->NOnarrow= True;
+            break;
+          case '1':
+            qh_option(qh, "Q11-trinormals Qtriangulate", NULL, NULL);
+            qh->TRInormals= True;
+            qh->TRIangulate= True;
+            break;
+          case '2':
+            qh_option(qh, "Q12-allow-wide", NULL, NULL);
+            qh->ALLOWwide= True;
+            break;
+          case '4':
+#ifndef qh_NOmerge
+            qh_option(qh, "Q14-merge-pinched-vertices", NULL, NULL);
+            qh->MERGEpinched= True;
+#else
+            /* ignore 'Q14' for q_benchmark testing of difficult cases for Qhull */
+            qh_fprintf(qh, qh->ferr, 7099, "qhull option warning: option 'Q14-merge-pinched' disabled due to qh_NOmerge\n");
+#endif
+            break;
+          case '7':
+            qh_option(qh, "Q17-check-duplicates", NULL, NULL);
+            qh->CHECKduplicates= True;
+            break;
+          default:
+            s--;
+            qh_fprintf(qh, qh->ferr, 7016, "qhull option warning: unknown 'Q' qhull option 'Q1%c', skip to next space\n", (int)s[0]);
+            lastwarning= s-1;
+            while (*++s && !isspace(*s));
+            break;
+          }
+          break;
+        case '2':
+          qh_option(qh, "Q2-no-merge-independent", NULL, NULL);
+          qh->MERGEindependent= False;
+          goto LABELcheckdigit;
+          break; /* no gcc warnings */
+        case '3':
+          qh_option(qh, "Q3-no-merge-vertices", NULL, NULL);
+          qh->MERGEvertices= False;
+        LABELcheckdigit:
+          if (isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7017, "qhull option warning: can not follow '1', '2', or '3' with a digit.  'Q%c%c' skipped\n", *(s-1), *s);
+            lastwarning= s-2;
+            s++;
+          }
+          break;
+        case '4':
+          qh_option(qh, "Q4-avoid-old-into-new", NULL, NULL);
+          qh->AVOIDold= True;
+          break;
+        case '5':
+          qh_option(qh, "Q5-no-check-outer", NULL, NULL);
+          qh->SKIPcheckmax= True;
+          break;
+        case '6':
+          qh_option(qh, "Q6-no-concave-merge", NULL, NULL);
+          qh->SKIPconvex= True;
+          break;
+        case '7':
+          qh_option(qh, "Q7-no-breadth-first", NULL, NULL);
+          qh->VIRTUALmemory= True;
+          break;
+        case '8':
+          qh_option(qh, "Q8-no-near-inside", NULL, NULL);
+          qh->NOnearinside= True;
+          break;
+        case '9':
+          qh_option(qh, "Q9-pick-furthest", NULL, NULL);
+          qh->PICKfurthest= True;
+          break;
+        case 'G':
+          i= qh_strtol(s, &t);
+          if (qh->GOODpoint) {
+            qh_fprintf(qh, qh->ferr, 7018, "qhull option warning: good point already defined for option 'QGn'.  Ignored\n");
+            lastwarning= s-2;
+          }else if (s == t) {
+            qh_fprintf(qh, qh->ferr, 7019, "qhull option warning: missing good point id for option 'QGn'.  Ignored\n");
+            lastwarning= s-2;
+          }else if (i < 0 || *s == '-') {
+            qh->GOODpoint= i-1;
+            qh_option(qh, "QGood-if-dont-see-point", &i, NULL);
+          }else {
+            qh->GOODpoint= i+1;
+            qh_option(qh, "QGood-if-see-point", &i, NULL);
+          }
+          s= t;
+          break;
+        case 'J':
+          if (!isdigit(*s) && *s != '-')
+            qh->JOGGLEmax= 0.0;
+          else {
+            qh->JOGGLEmax= (realT) qh_strtod(s, &s);
+            qh_option(qh, "QJoggle", NULL, &qh->JOGGLEmax);
+          }
+          break;
+        case 'R':
+          if (!isdigit(*s) && *s != '-') {
+            qh_fprintf(qh, qh->ferr, 7020, "qhull option warning: missing random seed for option 'QRn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->ROTATErandom= i= qh_strtol(s, &s);
+            if (i > 0)
+              qh_option(qh, "QRotate-id", &i, NULL );
+            else if (i < -1)
+              qh_option(qh, "QRandom-seed", &i, NULL );
+          }
+          break;
+        case 'V':
+          i= qh_strtol(s, &t);
+          if (qh->GOODvertex) {
+            qh_fprintf(qh, qh->ferr, 7021, "qhull option warning: good vertex already defined for option 'QVn'.  Ignored\n");
+            lastwarning= s-2;
+          }else if (s == t) {
+            qh_fprintf(qh, qh->ferr, 7022, "qhull option warning: no good point id given for option 'QVn'.  Ignored\n");
+            lastwarning= s-2;
+          }else if (i < 0) {
+            qh->GOODvertex= i - 1;
+            qh_option(qh, "QV-good-facets-not-point", &i, NULL);
+          }else {
+            qh_option(qh, "QV-good-facets-point", &i, NULL);
+            qh->GOODvertex= i + 1;
+          }
+          s= t;
+          break;
+        case 'w':
+          qh_option(qh, "Qwarn-allow", NULL, NULL);
+          qh->ALLOWwarning= True;
+          break;
+        default:
+          s--;
+          qh_fprintf(qh, qh->ferr, 7023, "qhull option warning: unknown 'Q' qhull option 'Q%c', skip to next space\n", (int)s[0]);
+          lastwarning= s-1;
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'T':
+      while (*s && !isspace(*s)) {
+        if (isdigit(*s) || *s == '-')
+          qh->IStracing= qh_strtol(s, &s);
+        else switch (*s++) {
+        case 'a':
+          qh_option(qh, "Tannotate-output", NULL, NULL);
+          qh->ANNOTATEoutput= True;
+          break;
+        case 'c':
+          qh_option(qh, "Tcheck-frequently", NULL, NULL);
+          qh->CHECKfrequently= True;
+          break;
+        case 'f':
+          qh_option(qh, "Tflush", NULL, NULL);
+          qh->FLUSHprint= True;
+          break;
+        case 's':
+          qh_option(qh, "Tstatistics", NULL, NULL);
+          qh->PRINTstatistics= True;
+          break;
+        case 'v':
+          qh_option(qh, "Tverify", NULL, NULL);
+          qh->VERIFYoutput= True;
+          break;
+        case 'z':
+          if (qh->ferr == qh_FILEstderr) {
+            /* The C++ interface captures the output in qh_fprint_qhull() */
+            qh_option(qh, "Tz-stdout", NULL, NULL);
+            qh->USEstdout= True;
+          }else if (!qh->fout) {
+            qh_fprintf(qh, qh->ferr, 7024, "qhull option warning: output file undefined(stdout).  Option 'Tz' ignored.\n");
+            lastwarning= s-2;
+          }else {
+            qh_option(qh, "Tz-stdout", NULL, NULL);
+            qh->USEstdout= True;
+            qh->ferr= qh->fout;
+            qh->qhmem.ferr= qh->fout;
+          }
+          break;
+        case 'C':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7025, "qhull option warning: missing point id for cone for trace option 'TCn'\n");
+            lastwarning= s-2;
+          }else {
+            i= qh_strtol(s, &s);
+            qh_option(qh, "TCone-stop", &i, NULL);
+            qh->STOPcone= i + 1;
+          }
+          break;
+        case 'F':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7026, "qhull option warning: missing frequency count for trace option 'TFn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->REPORTfreq= qh_strtol(s, &s);
+            qh_option(qh, "TFacet-log", &qh->REPORTfreq, NULL);
+            qh->REPORTfreq2= qh->REPORTfreq/2;  /* for tracemerging() */
+          }
+          break;
+        case 'I':
+          while (isspace(*s))
+            s++;
+          t= qh_skipfilename(qh, s);
+          {
+            char filename[qh_FILENAMElen];
+
+            qh_copyfilename(qh, filename, (int)sizeof(filename), s, (int)(t-s));   /* WARN64 */
+            s= t;
+            if (!freopen(filename, "r", stdin)) {
+              qh_fprintf(qh, qh->ferr, 6041, "qhull option error: cannot open 'TI' file \"%s\"\n", filename);
+              qh_errexit(qh, qh_ERRinput, NULL, NULL);
+            }else {
+              qh_option(qh, "TInput-file", NULL, NULL);
+              qh_option(qh, filename, NULL, NULL);
+            }
+          }
+          break;
+        case 'O':
+          while (isspace(*s))
+            s++;
+          t= qh_skipfilename(qh, s);
+          {
+            char filename[qh_FILENAMElen];
+
+            qh_copyfilename(qh, filename, (int)sizeof(filename), s, (int)(t-s));  /* WARN64 */
+            if (!qh->fout) {
+              qh_fprintf(qh, qh->ferr, 7092, "qhull option warning: qh.fout was not set by caller of qh_initflags.  Cannot use option 'TO' to redirect output.  Ignoring option 'TO'\n");
+              lastwarning= s-2;
+            }else if (!freopen(filename, "w", qh->fout)) {
+              qh_fprintf(qh, qh->ferr, 6044, "qhull option error: cannot open file \"%s\" for writing as option 'TO'.  It is already in use or read-only\n", filename);
+              qh_errexit(qh, qh_ERRinput, NULL, NULL);
+            }else {
+              qh_option(qh, "TOutput-file", NULL, NULL);
+              qh_option(qh, filename, NULL, NULL);
+            }
+            s= t;
+          }
+          break;
+        case 'A':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7093, "qhull option warning: missing count of added points for trace option 'TAn'\n");
+            lastwarning= s-2;
+          }else {
+            i= qh_strtol(s, &t);
+            qh->STOPadd= i + 1;
+            qh_option(qh, "TA-stop-add", &i, NULL);
+          }
+          s= t;
+          break;
+        case 'P':
+          if (*s == '-') {
+            if (s[1] == '1' && !isdigit(s[2])) {
+              s += 2;
+              qh->TRACEpoint= qh_IDunknown; /* qh_buildhull done */
+              qh_option(qh, "Trace-point", &qh->TRACEpoint, NULL);
+            }else {
+              qh_fprintf(qh, qh->ferr, 7100, "qhull option warning: negative point id for trace option 'TPn'.  Expecting 'TP-1' for tracing after qh_buildhull and qh_postmerge\n");
+              lastwarning= s-2;
+              while (isdigit(*(++s)))
+                ; /* skip digits */
+            }
+          }else if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7029, "qhull option warning: missing point id or -1 for trace option 'TPn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->TRACEpoint= qh_strtol(s, &s);
+            qh_option(qh, "Trace-point", &qh->TRACEpoint, NULL);
+          }
+          break;
+        case 'M':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7030, "qhull option warning: missing merge id for trace option 'TMn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->TRACEmerge= qh_strtol(s, &s);
+            qh_option(qh, "Trace-merge", &qh->TRACEmerge, NULL);
+          }
+          break;
+        case 'R':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7031, "qhull option warning: missing rerun count for trace option 'TRn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->RERUN= qh_strtol(s, &s);
+            qh_option(qh, "TRerun", &qh->RERUN, NULL);
+          }
+          break;
+        case 'V':
+          i= qh_strtol(s, &t);
+          if (s == t) {
+            qh_fprintf(qh, qh->ferr, 7032, "qhull option warning: missing furthest point id for trace option 'TVn'\n");
+            lastwarning= s-2;
+          }else if (i < 0) {
+            qh->STOPpoint= i - 1;
+            qh_option(qh, "TV-stop-before-point", &i, NULL);
+          }else {
+            qh->STOPpoint= i + 1;
+            qh_option(qh, "TV-stop-after-point", &i, NULL);
+          }
+          s= t;
+          break;
+        case 'W':
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7033, "qhull option warning: missing max width for trace option 'TWn'\n");
+            lastwarning= s-2;
+          }else {
+            qh->TRACEdist= (realT) qh_strtod(s, &s);
+            qh_option(qh, "TWide-trace", NULL, &qh->TRACEdist);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh, qh->ferr, 7034, "qhull option warning: unknown 'T' trace option 'T%c', skip to next space\n", (int)s[0]);
+          lastwarning= s-2;
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    default:
+      qh_fprintf(qh, qh->ferr, 7094, "qhull option warning: unknown option '%c'(%x)\n",
+        (int)s[-1], (int)s[-1]);
+      lastwarning= s-2;
+      break;
+    }
+    if (s-1 == prev_s && *s && !isspace(*s)) {
+      qh_fprintf(qh, qh->ferr, 7036, "qhull option warning: missing space after option '%c'(%x), reserved for sub-options, ignoring '%c' options to next space\n",
+               (int)*prev_s, (int)*prev_s, (int)*prev_s);
+      lastwarning= s-1;
+      while (*s && !isspace(*s))
+        s++;
+    }
+  }
+  if (qh->STOPcone && qh->JOGGLEmax < REALmax/2) {
+    qh_fprintf(qh, qh->ferr, 7078, "qhull option warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
+    lastwarning= command;
+  }
+  if (isgeom && !qh->FORCEoutput && qh->PRINTout[1]) {
+    qh_fprintf(qh, qh->ferr, 7037, "qhull option warning: additional output formats ('Fc',etc.) are not compatible with Geomview ('G').  Use option 'Po' to override\n");
+    lastwarning= command;
+  }
+  if (lastwarning && !qh->ALLOWwarning) {
+    qh_fprintf(qh, qh->ferr, 6035, "qhull option error: see previous warnings, use 'Qw' to override: '%s' (last offset %d)\n",
+          command, (int)(lastwarning-command));
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  trace4((qh, qh->ferr, 4093, "qh_initflags: option flags initialized\n"));
+  /* set derived values in qh_initqhull_globals */
+} /* initflags */
+
+
+/*---------------------------------
+
+  qh_initqhull_buffers(qh)
+    initialize global memory buffers
+
+  notes:
+    must match qh_freebuffers()
+*/
+void qh_initqhull_buffers(qhT *qh) {
+  int k;
+
+  qh->TEMPsize= (qh->qhmem.LASTsize - SETbasesize)/SETelemsize;
+  if (qh->TEMPsize <= 0 || qh->TEMPsize > qh->qhmem.LASTsize)
+    qh->TEMPsize= 8;  /* e.g., if qh_NOmem */
+  qh->other_points= qh_setnew(qh, qh->TEMPsize);
+  qh->del_vertices= qh_setnew(qh, qh->TEMPsize);
+  qh->coplanarfacetset= qh_setnew(qh, qh->TEMPsize);
+  qh->NEARzero= (realT *)qh_memalloc(qh, qh->hull_dim * (int)sizeof(realT));
+  qh->lower_threshold= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
+  qh->upper_threshold= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
+  qh->lower_bound= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
+  qh->upper_bound= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
+  for (k=qh->input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
+    qh->lower_threshold[k]= -REALmax;
+    qh->upper_threshold[k]= REALmax;
+    qh->lower_bound[k]= -REALmax;
+    qh->upper_bound[k]= REALmax;
+  }
+  qh->gm_matrix= (coordT *)qh_memalloc(qh, (qh->hull_dim+1) * qh->hull_dim * (int)sizeof(coordT));
+  qh->gm_row= (coordT **)qh_memalloc(qh, (qh->hull_dim+1) * (int)sizeof(coordT *));
+} /* initqhull_buffers */
+
+/*---------------------------------
+
+  qh_initqhull_globals(qh, points, numpoints, dim, ismalloc )
+    initialize globals
+    if ismalloc
+      points were malloc'd and qhull should free at end
+
+  returns:
+    sets qh.first_point, num_points, input_dim, hull_dim and others
+    seeds random number generator (seed=1 if tracing)
+    modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
+    adjust user flags as needed
+    also checks DIM3 dependencies and constants
+
+  notes:
+    do not use qh_point() since an input transformation may move them elsewhere
+    qh_initqhull_start() sets default values for non-zero globals
+    consider duplicate error checks in qh_readpoints.  It is called before qh_initqhull_globals
+
+  design:
+    initialize points array from input arguments
+    test for qh.ZEROcentrum
+      (i.e., use opposite vertex instead of cetrum for convexity testing)
+    initialize qh.CENTERtype, qh.normal_size,
+      qh.center_size, qh.TRACEpoint/level,
+    initialize and test random numbers
+    qh_initqhull_outputflags() -- adjust and test output flags
+*/
+void qh_initqhull_globals(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc) {
+  int seed, pointsneeded, extra= 0, i, randi, k;
+  realT randr;
+  realT factorial;
+
+  time_t timedata;
+
+  trace0((qh, qh->ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh->rbox_command,
+      qh->qhull_command));
+  if (numpoints < 1 || numpoints > qh_POINTSmax) {
+    qh_fprintf(qh, qh->ferr, 6412, "qhull input error (qh_initqhull_globals): expecting between 1 and %d points.  Got %d %d-d points\n",
+      qh_POINTSmax, numpoints, dim);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    /* same error message in qh_readpoints */
+  }
+  qh->POINTSmalloc= ismalloc;
+  qh->first_point= points;
+  qh->num_points= numpoints;
+  qh->hull_dim= qh->input_dim= dim;
+  if (!qh->NOpremerge && !qh->MERGEexact && !qh->PREmerge && qh->JOGGLEmax > REALmax/2) {
+    qh->MERGING= True;
+    if (qh->hull_dim <= 4) {
+      qh->PREmerge= True;
+      qh_option(qh, "_pre-merge", NULL, NULL);
+    }else {
+      qh->MERGEexact= True;
+      qh_option(qh, "Qxact-merge", NULL, NULL);
+    }
+  }else if (qh->MERGEexact)
+    qh->MERGING= True;
+  if (qh->NOpremerge && (qh->MERGEexact || qh->PREmerge))
+    qh_fprintf(qh, qh->ferr, 7095, "qhull option warning: 'Q0-no-premerge' ignored due to exact merge ('Qx') or pre-merge ('C-n' or 'A-n')\n");
+  if (!qh->NOpremerge && qh->JOGGLEmax > REALmax/2) {
+#ifdef qh_NOmerge
+    qh->JOGGLEmax= 0.0;
+#endif
+  }
+  if (qh->TRIangulate && qh->JOGGLEmax < REALmax/2 && !qh->PREmerge && !qh->POSTmerge && qh->PRINTprecision)
+    qh_fprintf(qh, qh->ferr, 7038, "qhull option warning: joggle ('QJ') produces simplicial output (i.e., triangles in 2-D).  Unless merging is requested, option 'Qt' has no effect\n");
+  if (qh->JOGGLEmax < REALmax/2 && qh->DELAUNAY && !qh->SCALEinput && !qh->SCALElast) {
+    qh->SCALElast= True;
+    qh_option(qh, "Qbbound-last-qj", NULL, NULL);
+  }
+  if (qh->MERGING && !qh->POSTmerge && qh->premerge_cos > REALmax/2
+  && qh->premerge_centrum == 0.0) {
+    qh->ZEROcentrum= True;
+    qh->ZEROall_ok= True;
+    qh_option(qh, "_zero-centrum", NULL, NULL);
+  }
+  if (qh->JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh->PRINTprecision)
+    qh_fprintf(qh, qh->ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user_r.h).\n",
+          REALepsilon);
+#ifdef qh_NOmerge
+  if (qh->MERGING) {
+    qh_fprintf(qh, qh->ferr, 6045, "qhull option error: merging not installed (qh_NOmerge) for 'Qx', 'Cn' or 'An')\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+#endif
+  if (qh->DELAUNAY && qh->KEEPcoplanar && !qh->KEEPinside) {
+    qh->KEEPinside= True;
+    qh_option(qh, "Qinterior-keep", NULL, NULL);
+  }
+  if (qh->VORONOI && !qh->DELAUNAY) {
+    qh_fprintf(qh, qh->ferr, 6038, "qhull internal error (qh_initqhull_globals): if qh.VORONOI is set, qh.DELAUNAY must be set.  Qhull constructs the Delaunay triangulation in order to compute the Voronoi diagram\n");
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (qh->DELAUNAY && qh->HALFspace) {
+    qh_fprintf(qh, qh->ferr, 6046, "qhull option error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    /* same error message in qh_readpoints */
+  }
+  if (!qh->DELAUNAY && (qh->UPPERdelaunay || qh->ATinfinity)) {
+    qh_fprintf(qh, qh->ferr, 6047, "qhull option error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (qh->UPPERdelaunay && qh->ATinfinity) {
+    qh_fprintf(qh, qh->ferr, 6048, "qhull option error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (qh->MERGEpinched && qh->ONLYgood) {
+    qh_fprintf(qh, qh->ferr, 6362, "qhull option error: can not use merge-pinched-vertices ('Q14') with good-facets-only ('Qg')\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (qh->MERGEpinched && qh->hull_dim == 2) {
+    trace2((qh, qh->ferr, 2108, "qh_initqhull_globals: disable qh.MERGEpinched for 2-d.  It has no effect"))
+    qh->MERGEpinched= False;
+  }
+  if (qh->SCALElast && !qh->DELAUNAY && qh->PRINTprecision)
+    qh_fprintf(qh, qh->ferr, 7040, "qhull option warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
+  qh->DOcheckmax= (!qh->SKIPcheckmax && (qh->MERGING || qh->APPROXhull));
+  qh->KEEPnearinside= (qh->DOcheckmax && !(qh->KEEPinside && qh->KEEPcoplanar)
+                          && !qh->NOnearinside);
+  if (qh->MERGING)
+    qh->CENTERtype= qh_AScentrum;
+  else if (qh->VORONOI)
+    qh->CENTERtype= qh_ASvoronoi;
+  if (qh->TESTvneighbors && !qh->MERGING) {
+    qh_fprintf(qh, qh->ferr, 6049, "qhull option error: test vertex neighbors('Qv') needs a merge option\n");
+    qh_errexit(qh, qh_ERRinput, NULL ,NULL);
+  }
+  if (qh->PROJECTinput || (qh->DELAUNAY && qh->PROJECTdelaunay)) {
+    qh->hull_dim -= qh->PROJECTinput;
+    if (qh->DELAUNAY) {
+      qh->hull_dim++;
+      if (qh->ATinfinity)
+        extra= 1;
+    }
+  }
+  if (qh->hull_dim <= 1) {
+    qh_fprintf(qh, qh->ferr, 6050, "qhull error: dimension %d must be > 1\n", qh->hull_dim);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  for (k=2, factorial=1.0; k < qh->hull_dim; k++)
+    factorial *= k;
+  qh->AREAfactor= 1.0 / factorial;
+  trace2((qh, qh->ferr, 2005, "qh_initqhull_globals: initialize globals.  input_dim %d, numpoints %d, malloc? %d, projected %d to hull_dim %d\n",
+        qh->input_dim, numpoints, ismalloc, qh->PROJECTinput, qh->hull_dim));
+  qh->normal_size= qh->hull_dim * (int)sizeof(coordT);
+  qh->center_size= qh->normal_size - (int)sizeof(coordT);
+  pointsneeded= qh->hull_dim+1;
+  if (qh->hull_dim > qh_DIMmergeVertex) {
+    qh->MERGEvertices= False;
+    qh_option(qh, "Q3-no-merge-vertices-dim-high", NULL, NULL);
+  }
+  if (qh->GOODpoint)
+    pointsneeded++;
+#ifdef qh_NOtrace
+  if (qh->IStracing || qh->TRACEmerge || qh->TRACEpoint != qh_IDnone || qh->TRACEdist < REALmax/2) {
+      qh_fprintf(qh, qh->ferr, 6051, "qhull option error: tracing is not installed (qh_NOtrace in user_r.h).  Trace options 'Tn', 'TMn', 'TPn' and 'TWn' mostly removed.  Continue with 'Qw' (allow warning)\n");
+      if (!qh->ALLOWwarning)
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+#endif
+  if (qh->RERUN > 1) {
+    qh->TRACElastrun= qh->IStracing; /* qh_build_withrestart duplicates next conditional */
+    if (qh->IStracing && qh->IStracing != -1) {
+      qh_fprintf(qh, qh->ferr, 8162, "qh_initqhull_globals: trace last of TR%d runs at level %d\n", qh->RERUN, qh->IStracing);
+      qh->IStracing= 0;
+    }
+  }else if (qh->TRACEpoint != qh_IDnone || qh->TRACEdist < REALmax/2 || qh->TRACEmerge) {
+    qh->TRACElevel= (qh->IStracing ? qh->IStracing : 3);
+    qh->IStracing= 0;
+  }
+  if (qh->ROTATErandom == 0 || qh->ROTATErandom == -1) {
+    seed= (int)time(&timedata);
+    if (qh->ROTATErandom  == -1) {
+      seed= -seed;
+      qh_option(qh, "QRandom-seed", &seed, NULL );
+    }else
+      qh_option(qh, "QRotate-random", &seed, NULL);
+    qh->ROTATErandom= seed;
+  }
+  seed= qh->ROTATErandom;
+  if (seed == INT_MIN)    /* default value */
+    seed= 1;
+  else if (seed < 0)
+    seed= -seed;
+  qh_RANDOMseed_(qh, seed);
+  randr= 0.0;
+  for (i=1000; i--; ) {
+    randi= qh_RANDOMint;
+    randr += randi;
+    if (randi > qh_RANDOMmax) {
+      qh_fprintf(qh, qh->ferr, 8036, "\
+qhull configuration error (qh_RANDOMmax in user_r.h): random integer %d > qh_RANDOMmax (%.8g)\n",
+               randi, qh_RANDOMmax);
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+  }
+  qh_RANDOMseed_(qh, seed);
+  randr= randr/1000;
+  if (randr < qh_RANDOMmax * 0.1
+  || randr > qh_RANDOMmax * 0.9)
+    qh_fprintf(qh, qh->ferr, 8037, "\
+qhull configuration warning (qh_RANDOMmax in user_r.h): average of 1000 random integers (%.2g) is much different than expected (%.2g).  Is qh_RANDOMmax (%.2g) wrong?\n",
+             randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
+  qh->RANDOMa= 2.0 * qh->RANDOMfactor/qh_RANDOMmax;
+  qh->RANDOMb= 1.0 - qh->RANDOMfactor;
+  if (qh_HASHfactor < 1.1) {
+    qh_fprintf(qh, qh->ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1.  Qhull uses linear hash probing\n",
+      qh_HASHfactor);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (numpoints+extra < pointsneeded) {
+    qh_fprintf(qh, qh->ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
+            numpoints, pointsneeded);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  qh_initqhull_outputflags(qh);
+} /* initqhull_globals */
+
+/*---------------------------------
+
+  qh_initqhull_mem(qh )
+    initialize mem_r.c for qhull
+    qh.hull_dim and qh.normal_size determine some of the allocation sizes
+    if qh.MERGING,
+      includes ridgeT
+    calls qh_user_memsizes (user_r.c) to add up to 10 additional sizes for quick allocation
+      (see numsizes below)
+
+  returns:
+    mem_r.c already for qh_memalloc/qh_memfree (errors if called beforehand)
+
+  notes:
+    qh_produceoutput() prints memsizes
+
+*/
+void qh_initqhull_mem(qhT *qh) {
+  int numsizes;
+  int i;
+
+  numsizes= 8+10;
+  qh_meminitbuffers(qh, qh->IStracing, qh_MEMalign, numsizes,
+                     qh_MEMbufsize, qh_MEMinitbuf);
+  qh_memsize(qh, (int)sizeof(vertexT));
+  if (qh->MERGING) {
+    qh_memsize(qh, (int)sizeof(ridgeT));
+    qh_memsize(qh, (int)sizeof(mergeT));
+  }
+  qh_memsize(qh, (int)sizeof(facetT));
+  i= SETbasesize + (qh->hull_dim - 1) * SETelemsize;  /* ridge.vertices */
+  qh_memsize(qh, i);
+  qh_memsize(qh, qh->normal_size);        /* normal */
+  i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
+  qh_memsize(qh, i);
+  qh_user_memsizes(qh);
+  qh_memsetup(qh);
+} /* initqhull_mem */
+
+/*---------------------------------
+
+  qh_initqhull_outputflags
+    initialize flags concerned with output
+
+  returns:
+    adjust user flags as needed
+
+  see:
+    qh_clear_outputflags() resets the flags
+
+  design:
+    test for qh.PRINTgood (i.e., only print 'good' facets)
+    check for conflicting print output options
+*/
+void qh_initqhull_outputflags(qhT *qh) {
+  boolT printgeom= False, printmath= False, printcoplanar= False;
+  int i;
+
+  trace3((qh, qh->ferr, 3024, "qh_initqhull_outputflags: %s\n", qh->qhull_command));
+  if (!(qh->PRINTgood || qh->PRINTneighbors)) {
+    if (qh->DELAUNAY || qh->KEEParea || qh->KEEPminArea < REALmax/2 || qh->KEEPmerge
+        || (!qh->ONLYgood && (qh->GOODvertex || qh->GOODpoint))) {
+      qh->PRINTgood= True;
+      qh_option(qh, "Pgood", NULL, NULL);
+    }
+  }
+  if (qh->PRINTtransparent) {
+    if (qh->hull_dim != 4 || !qh->DELAUNAY || qh->VORONOI || qh->DROPdim >= 0) {
+      qh_fprintf(qh, qh->ferr, 6215, "qhull option error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    qh->DROPdim= 3;
+    qh->PRINTridges= True;
+  }
+  for (i=qh_PRINTEND; i--; ) {
+    if (qh->PRINTout[i] == qh_PRINTgeom)
+      printgeom= True;
+    else if (qh->PRINTout[i] == qh_PRINTmathematica || qh->PRINTout[i] == qh_PRINTmaple)
+      printmath= True;
+    else if (qh->PRINTout[i] == qh_PRINTcoplanars)
+      printcoplanar= True;
+    else if (qh->PRINTout[i] == qh_PRINTpointnearest)
+      printcoplanar= True;
+    else if (qh->PRINTout[i] == qh_PRINTpointintersect && !qh->HALFspace) {
+      qh_fprintf(qh, qh->ferr, 6053, "qhull option error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }else if (qh->PRINTout[i] == qh_PRINTtriangles && (qh->HALFspace || qh->VORONOI)) {
+      qh_fprintf(qh, qh->ferr, 6054, "qhull option error: option 'Ft' is not available for Voronoi vertices ('v') or halfspace intersection ('H')\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }else if (qh->PRINTout[i] == qh_PRINTcentrums && qh->VORONOI) {
+      qh_fprintf(qh, qh->ferr, 6055, "qhull option error: option 'FC' is not available for Voronoi vertices('v')\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }else if (qh->PRINTout[i] == qh_PRINTvertices) {
+      if (qh->VORONOI)
+        qh_option(qh, "Fvoronoi", NULL, NULL);
+      else
+        qh_option(qh, "Fvertices", NULL, NULL);
+    }
+  }
+  if (printcoplanar && qh->DELAUNAY && qh->JOGGLEmax < REALmax/2) {
+    if (qh->PRINTprecision)
+      qh_fprintf(qh, qh->ferr, 7041, "qhull option warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
+  }
+  if (printmath && (qh->hull_dim > 3 || qh->VORONOI)) {
+    qh_fprintf(qh, qh->ferr, 6056, "qhull option error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (printgeom) {
+    if (qh->hull_dim > 4) {
+      qh_fprintf(qh, qh->ferr, 6057, "qhull option error: Geomview output is only available for 2-d, 3-d and 4-d\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    if (qh->PRINTnoplanes && !(qh->PRINTcoplanar + qh->PRINTcentrums
+     + qh->PRINTdots + qh->PRINTspheres + qh->DOintersections + qh->PRINTridges)) {
+      qh_fprintf(qh, qh->ferr, 6058, "qhull option error: no output specified for Geomview\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    if (qh->VORONOI && (qh->hull_dim > 3 || qh->DROPdim >= 0)) {
+      qh_fprintf(qh, qh->ferr, 6059, "qhull option error: Geomview output for Voronoi diagrams only for 2-d\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    /* can not warn about furthest-site Geomview output: no lower_threshold */
+    if (qh->hull_dim == 4 && qh->DROPdim == -1 &&
+        (qh->PRINTcoplanar || qh->PRINTspheres || qh->PRINTcentrums)) {
+      qh_fprintf(qh, qh->ferr, 7042, "qhull option warning: coplanars, vertices, and centrums output not available for 4-d output(ignored).  Could use 'GDn' instead.\n");
+      qh->PRINTcoplanar= qh->PRINTspheres= qh->PRINTcentrums= False;
+    }
+  }
+  if (!qh->KEEPcoplanar && !qh->KEEPinside && !qh->ONLYgood) {
+    if ((qh->PRINTcoplanar && qh->PRINTspheres) || printcoplanar) {
+      if (qh->QHULLfinished) {
+        qh_fprintf(qh, qh->ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
+      }else {
+        qh->KEEPcoplanar= True;
+        qh_option(qh, "Qcoplanar", NULL, NULL);
+      }
+    }
+  }
+  qh->PRINTdim= qh->hull_dim;
+  if (qh->DROPdim >=0) {    /* after Geomview checks */
+    if (qh->DROPdim < qh->hull_dim) {
+      qh->PRINTdim--;
+      if (!printgeom || qh->hull_dim < 3)
+        qh_fprintf(qh, qh->ferr, 7043, "qhull option warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh->DROPdim);
+    }else
+      qh->DROPdim= -1;
+  }else if (qh->VORONOI) {
+    qh->DROPdim= qh->hull_dim-1;
+    qh->PRINTdim= qh->hull_dim-1;
+  }
+} /* qh_initqhull_outputflags */
+
+/*---------------------------------
+
+  qh_initqhull_start(qh, infile, outfile, errfile )
+    allocate memory if needed and call qh_initqhull_start2()
+*/
+void qh_initqhull_start(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile) {
+
+  qh_initstatistics(qh);
+  qh_initqhull_start2(qh, infile, outfile, errfile);
+} /* initqhull_start */
+
+/*---------------------------------
+
+  qh_initqhull_start2(qh, infile, outfile, errfile )
+    start initialization of qhull
+    initialize statistics, stdio, default values for global variables
+    assumes qh is allocated
+  notes:
+    report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
+  see:
+    qh_maxmin() determines the precision constants
+    qh_freeqhull()
+*/
+void qh_initqhull_start2(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile) {
+  time_t timedata;
+  int seed;
+
+  qh_CPUclock; /* start the clock(for qh_clock).  One-shot. */
+  /* memset is the same in qh_freeqhull() and qh_initqhull_start2() */
+  memset((char *)qh, 0, sizeof(qhT)-sizeof(qhmemT)-sizeof(qhstatT));   /* every field is 0, FALSE, NULL */
+  qh->NOerrexit= True;
+  qh->DROPdim= -1;
+  qh->ferr= errfile;
+  qh->fin= infile;
+  qh->fout= outfile;
+  qh->furthest_id= qh_IDunknown;
+#ifndef qh_NOmerge
+  qh->JOGGLEmax= REALmax;
+#else
+  qh->JOGGLEmax= 0.0;  /* Joggle ('QJ') if qh_NOmerge */
+#endif
+  qh->KEEPminArea= REALmax;
+  qh->last_low= REALmax;
+  qh->last_high= REALmax;
+  qh->last_newhigh= REALmax;
+  qh->last_random= 1; /* reentrant only */
+  qh->lastcpu= 0.0;
+  qh->max_outside= 0.0;
+  qh->max_vertex= 0.0;
+  qh->MAXabs_coord= 0.0;
+  qh->MAXsumcoord= 0.0;
+  qh->MAXwidth= -REALmax;
+  qh->MERGEindependent= True;
+  qh->MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
+  qh->MINoutside= 0.0;
+  qh->MINvisible= REALmax;
+  qh->MAXcoplanar= REALmax;
+  qh->outside_err= REALmax;
+  qh->premerge_centrum= 0.0;
+  qh->premerge_cos= REALmax;
+  qh->PRINTprecision= True;
+  qh->PRINTradius= 0.0;
+  qh->postmerge_cos= REALmax;
+  qh->postmerge_centrum= 0.0;
+  qh->ROTATErandom= INT_MIN;
+  qh->MERGEvertices= True;
+  qh->totarea= 0.0;
+  qh->totvol= 0.0;
+  qh->TRACEdist= REALmax;
+  qh->TRACEpoint= qh_IDnone;    /* recompile to trace a point, or use 'TPn' */
+  qh->tracefacet_id= UINT_MAX;  /* recompile to trace a facet, set to UINT_MAX when done, see userprintf_r.c/qh_fprintf */
+  qh->traceridge_id= UINT_MAX;  /* recompile to trace a ridge, set to UINT_MAX when done, see userprintf_r.c/qh_fprintf */
+  qh->tracevertex_id= UINT_MAX; /* recompile to trace a vertex, set to UINT_MAX when done, see userprintf_r.c/qh_fprintf */
+  seed= (int)time(&timedata);
+  qh_RANDOMseed_(qh, seed);
+  qh->run_id= qh_RANDOMint;
+  if(!qh->run_id)
+      qh->run_id++;  /* guarantee non-zero */
+  qh_option(qh, "run-id", &qh->run_id, NULL);
+  strcat(qh->qhull, "qhull");
+} /* initqhull_start2 */
+
+/*---------------------------------
+
+  qh_initthresholds(qh, commandString )
+    set thresholds for printing and scaling from commandString
+
+  returns:
+    sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
+
+  see:
+    qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
+    qh_inthresholds()
+
+  design:
+    for each 'Pdn' or 'PDn' option
+      check syntax
+      set qh.lower_threshold or qh.upper_threshold
+    set qh.GOODthreshold if an unbounded threshold is used
+    set qh.SPLITthreshold if a bounded threshold is used
+*/
+void qh_initthresholds(qhT *qh, char *command) {
+  realT value;
+  int idx, maxdim, k;
+  char *s= command; /* non-const due to strtol */
+  char *lastoption, *lastwarning= NULL;
+  char key;
+
+  maxdim= qh->input_dim;
+  if (qh->DELAUNAY && (qh->PROJECTdelaunay || qh->PROJECTinput))
+    maxdim++;
+  while (*s) {
+    if (*s == '-')
+      s++;
+    if (*s == 'P') {
+      lastoption= s++;
+      while (*s && !isspace(key= *s++)) {
+        if (key == 'd' || key == 'D') {
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7044, "qhull option warning: no dimension given for Print option 'P%c' at: %s.  Ignored\n",
+                    key, s-1);
+            lastwarning= lastoption;
+            continue;
+          }
+          idx= qh_strtol(s, &s);
+          if (idx >= qh->hull_dim) {
+            qh_fprintf(qh, qh->ferr, 7045, "qhull option warning: dimension %d for Print option 'P%c' is >= %d.  Ignored\n",
+                idx, key, qh->hull_dim);
+            lastwarning= lastoption;
+            continue;
+          }
+          if (*s == ':') {
+            s++;
+            value= qh_strtod(s, &s);
+            if (fabs((double)value) > 1.0) {
+              qh_fprintf(qh, qh->ferr, 7046, "qhull option warning: value %2.4g for Print option 'P%c' is > +1 or < -1.  Ignored\n",
+                      value, key);
+              lastwarning= lastoption;
+              continue;
+            }
+          }else
+            value= 0.0;
+          if (key == 'd')
+            qh->lower_threshold[idx]= value;
+          else
+            qh->upper_threshold[idx]= value;
+        }
+      }
+    }else if (*s == 'Q') {
+      lastoption= s++;
+      while (*s && !isspace(key= *s++)) {
+        if (key == 'b' && *s == 'B') {
+          s++;
+          for (k=maxdim; k--; ) {
+            qh->lower_bound[k]= -qh_DEFAULTbox;
+            qh->upper_bound[k]= qh_DEFAULTbox;
+          }
+        }else if (key == 'b' && *s == 'b')
+          s++;
+        else if (key == 'b' || key == 'B') {
+          if (!isdigit(*s)) {
+            qh_fprintf(qh, qh->ferr, 7047, "qhull option warning: no dimension given for Qhull option 'Q%c'\n",
+                    key);
+            lastwarning= lastoption;
+            continue;
+          }
+          idx= qh_strtol(s, &s);
+          if (idx >= maxdim) {
+            qh_fprintf(qh, qh->ferr, 7048, "qhull option warning: dimension %d for Qhull option 'Q%c' is >= %d.  Ignored\n",
+                idx, key, maxdim);
+            lastwarning= lastoption;
+            continue;
+          }
+          if (*s == ':') {
+            s++;
+            value= qh_strtod(s, &s);
+          }else if (key == 'b')
+            value= -qh_DEFAULTbox;
+          else
+            value= qh_DEFAULTbox;
+          if (key == 'b')
+            qh->lower_bound[idx]= value;
+          else
+            qh->upper_bound[idx]= value;
+        }
+      }
+    }else {
+      while (*s && !isspace(*s))
+        s++;
+    }
+    while (isspace(*s))
+      s++;
+  }
+  for (k=qh->hull_dim; k--; ) {
+    if (qh->lower_threshold[k] > -REALmax/2) {
+      qh->GOODthreshold= True;
+      if (qh->upper_threshold[k] < REALmax/2) {
+        qh->SPLITthresholds= True;
+        qh->GOODthreshold= False;
+        break;
+      }
+    }else if (qh->upper_threshold[k] < REALmax/2)
+      qh->GOODthreshold= True;
+  }
+  if (lastwarning && !qh->ALLOWwarning) {
+    qh_fprintf(qh, qh->ferr, 6036, "qhull option error: see previous warnings, use 'Qw' to override: '%s' (last offset %d)\n",
+      command, (int)(lastwarning-command));
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+} /* initthresholds */
+
+/*---------------------------------
+
+  qh_lib_check( qhullLibraryType, qhTsize, vertexTsize, ridgeTsize, facetTsize, setTsize, qhmemTsize )
+    Report error if library does not agree with caller
+
+  notes:
+    NOerrors -- qh_lib_check can not call qh_errexit()
+*/
+void qh_lib_check(int qhullLibraryType, int qhTsize, int vertexTsize, int ridgeTsize, int facetTsize, int setTsize, int qhmemTsize) {
+    int last_errcode= qh_ERRnone;
+
+#if defined(_MSC_VER) && defined(_DEBUG) && defined(QHULL_CRTDBG)  /* user_r.h */
+    /*_CrtSetBreakAlloc(744);*/  /* Break at memalloc {744}, or 'watch' _crtBreakAlloc */
+    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) );
+    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
+    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );
+    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
+    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
+    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
+    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
+#endif
+
+    if (qhullLibraryType==QHULL_NON_REENTRANT) { /* 0 */
+      qh_fprintf_stderr(6257, "qh_lib_check: Incorrect qhull library called.  Caller uses non-reentrant Qhull with a static qhT.  Qhull library is reentrant.\n");
+      last_errcode= 6257;
+    }else if (qhullLibraryType==QHULL_QH_POINTER) { /* 1 */
+      qh_fprintf_stderr(6258, "qh_lib_check: Incorrect qhull library called.  Caller uses non-reentrant Qhull with a dynamic qhT via qh_QHpointer.  Qhull library is reentrant.\n");
+      last_errcode= 6258;
+    }else if (qhullLibraryType != QHULL_REENTRANT) { /* 2 */
+      qh_fprintf_stderr(6262, "qh_lib_check: Expecting qhullLibraryType QHULL_NON_REENTRANT(0), QHULL_QH_POINTER(1), or QHULL_REENTRANT(2).  Got %d\n", qhullLibraryType);
+      last_errcode= 6262;
+    }
+    if (qhTsize != (int)sizeof(qhT)) {
+      qh_fprintf_stderr(6249, "qh_lib_check: Incorrect qhull library called.  Size of qhT for caller is %d, but for qhull library is %d.\n", qhTsize, (int)sizeof(qhT));
+      last_errcode= 6249;
+    }
+    if (vertexTsize != (int)sizeof(vertexT)) {
+      qh_fprintf_stderr(6250, "qh_lib_check: Incorrect qhull library called.  Size of vertexT for caller is %d, but for qhull library is %d.\n", vertexTsize, (int)sizeof(vertexT));
+      last_errcode= 6250;
+    }
+    if (ridgeTsize != (int)sizeof(ridgeT)) {
+      qh_fprintf_stderr(6251, "qh_lib_check: Incorrect qhull library called.  Size of ridgeT for caller is %d, but for qhull library is %d.\n", ridgeTsize, (int)sizeof(ridgeT));
+      last_errcode= 6251;
+    }
+    if (facetTsize != (int)sizeof(facetT)) {
+      qh_fprintf_stderr(6252, "qh_lib_check: Incorrect qhull library called.  Size of facetT for caller is %d, but for qhull library is %d.\n", facetTsize, (int)sizeof(facetT));
+      last_errcode= 6252;
+    }
+    if (setTsize && setTsize != SETbasesize) {
+      qh_fprintf_stderr(6253, "qh_lib_check: Incorrect qhull library called.  Size of setT for caller is %d, but for qhull library is %d.\n", setTsize, SETbasesize);
+      last_errcode= 6253;
+    }
+    if (qhmemTsize && qhmemTsize != sizeof(qhmemT)) {
+      qh_fprintf_stderr(6254, "qh_lib_check: Incorrect qhull library called.  Size of qhmemT for caller is %d, but for qhull library is %d.\n", qhmemTsize, (int)sizeof(qhmemT));
+      last_errcode= 6254;
+    }
+    if (last_errcode) {
+      qh_fprintf_stderr(6259, "qhull internal error (qh_lib_check): Cannot continue due to QH%d.  '%s' is not reentrant (e.g., qhull.so) or out-of-date.  Exit with %d\n",
+            last_errcode, qh_version2, last_errcode - 6200);
+      qh_exit(last_errcode - 6200);  /* can not use qh_errexit(), must be less than 255 */
+    }
+} /* lib_check */
+
+/*---------------------------------
+
+  qh_option(qh, option, intVal, realVal )
+    add an option description to qh.qhull_options
+
+  notes:
+    NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
+    will be printed with statistics ('Ts') and errors
+    strlen(option) < 40
+*/
+void qh_option(qhT *qh, const char *option, int *i, realT *r) {
+  char buf[200];
+  int buflen, remainder;
+
+  if (strlen(option) > sizeof(buf)-30-30) {
+    qh_fprintf(qh, qh->ferr, 6408, "qhull internal error (qh_option): option (%d chars) has more than %d chars.  May overflow temporary buffer.  Option '%s'\n",
+        (int)strlen(option), (int)sizeof(buf)-30-30, option);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  buflen = 0;
+  buflen += snprintf(buf, sizeof(buf) / sizeof(buf[0]), "  %s", option);
+  if (i)
+    buflen += snprintf(buf+buflen, sizeof(buf) / sizeof(buf[0]) - buflen, " %d", *i);
+  if (r)
+    buflen += snprintf(buf+buflen, sizeof(buf) / sizeof(buf[0]) - buflen, " %2.2g", *r);
+  qh->qhull_optionlen += buflen;
+  remainder= (int)(sizeof(qh->qhull_options) - strlen(qh->qhull_options)) - 1;    /* WARN64 */
+  maximize_(remainder, 0);
+  if (qh->qhull_optionlen >= qh_OPTIONline && remainder > 0) {
+    strncat(qh->qhull_options, "\n", (unsigned int)remainder);
+    --remainder;
+    qh->qhull_optionlen= buflen;
+  }
+  if (buflen > remainder) {
+    trace1((qh, qh->ferr, 1058, "qh_option: option would overflow qh.qhull_options. Truncated '%s'\n", buf));
+  }
+  strncat(qh->qhull_options, buf, (unsigned int)remainder);
+} /* option */
+
+/*---------------------------------
+
+  qh_zero( qh, errfile )
+    Initialize and zero Qhull's memory for qh_new_qhull()
+
+  notes:
+    Not needed in global_r.c because static variables are initialized to zero
+*/
+void qh_zero(qhT *qh, FILE *errfile) {
+    memset((char *)qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
+    qh->NOerrexit= True;
+    qh_meminit(qh, errfile);
+} /* zero */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.c
new file mode 100644
index 00000000000..148d31254b8
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.c
@@ -0,0 +1,4128 @@
+/*
  ---------------------------------
+
+   io_r.c
+   Input/Output routines of qhull application
+
+   see qh-io_r.htm and io_r.h
+
+   see user_r.c for qh_errprint and qh_printfacetlist
+
+   unix_r.c calls qh_readpoints and qh_produce_output
+
+   unix_r.c and user_r.c are the only callers of io_r.c functions
+   This allows the user to avoid loading io_r.o from qhull.a
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/io_r.c#12 $$Change: 2965 $
+   $DateTime: 2020/06/04 15:37:41 $$Author: bbarber $
+*/
+
+#include "qhull_ra.h"
+
+/*========= -functions in alphabetical order after qh_produce_output(qh)  =====*/
+
+/*---------------------------------
+
+  qh_produce_output(qh )
+  qh_produce_output2(qh )
+    prints out the result of qhull in desired format
+    qh_produce_output2 does not call qh_prepare_output
+      qh_checkpolygon is valid for qh_prepare_output
+    if qh.GETarea
+      computes and prints area and volume
+    qh.PRINTout[] is an array of output formats
+
+  notes:
+    prints output in qh.PRINTout order
+*/
+void qh_produce_output(qhT *qh) {
+    int tempsize= qh_setsize(qh, qh->qhmem.tempstack);
+
+    qh_prepare_output(qh);
+    qh_produce_output2(qh);
+    if (qh_setsize(qh, qh->qhmem.tempstack) != tempsize) {
+        qh_fprintf(qh, qh->ferr, 6206, "qhull internal error (qh_produce_output): temporary sets not empty(%d)\n",
+            qh_setsize(qh, qh->qhmem.tempstack));
+        qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+} /* produce_output */
+
+
+void qh_produce_output2(qhT *qh) {
+  int i, tempsize= qh_setsize(qh, qh->qhmem.tempstack), d_1;
+
+  fflush(NULL);
+  if (qh->PRINTsummary)
+    qh_printsummary(qh, qh->ferr);
+  else if (qh->PRINTout[0] == qh_PRINTnone)
+    qh_printsummary(qh, qh->fout);
+  for (i=0; i < qh_PRINTEND; i++)
+    qh_printfacets(qh, qh->fout, qh->PRINTout[i], qh->facet_list, NULL, !qh_ALL);
+  fflush(NULL);
+
+  qh_allstatistics(qh);
+  if (qh->PRINTprecision && !qh->MERGING && (qh->JOGGLEmax > REALmax/2 || qh->RERUN))
+    qh_printstats(qh, qh->ferr, qh->qhstat.precision, NULL);
+  if (qh->VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
+    qh_printstats(qh, qh->ferr, qh->qhstat.vridges, NULL);
+  if (qh->PRINTstatistics) {
+    qh_printstatistics(qh, qh->ferr, "");
+    qh_memstatistics(qh, qh->ferr);
+    d_1= SETbasesize + (qh->hull_dim - 1) * SETelemsize;
+    qh_fprintf(qh, qh->ferr, 8040, "\
+    size in bytes: merge %d ridge %d vertex %d facet %d\n\
+         normal %d ridge vertices %d facet vertices or neighbors %d\n",
+            (int)sizeof(mergeT), (int)sizeof(ridgeT),
+            (int)sizeof(vertexT), (int)sizeof(facetT),
+            qh->normal_size, d_1, d_1 + SETelemsize);
+  }
+  if (qh_setsize(qh, qh->qhmem.tempstack) != tempsize) {
+    qh_fprintf(qh, qh->ferr, 6065, "qhull internal error (qh_produce_output2): temporary sets not empty(%d)\n",
+             qh_setsize(qh, qh->qhmem.tempstack));
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+} /* produce_output2 */
+
+/*---------------------------------
+
+  qh_dfacet(qh, id )
+    print facet by id, for debugging
+
+*/
+void qh_dfacet(qhT *qh, unsigned int id) {
+  facetT *facet;
+
+  FORALLfacets {
+    if (facet->id == id) {
+      qh_printfacet(qh, qh->fout, facet);
+      break;
+    }
+  }
+} /* dfacet */
+
+
+/*---------------------------------
+
+  qh_dvertex(qh, id )
+    print vertex by id, for debugging
+*/
+void qh_dvertex(qhT *qh, unsigned int id) {
+  vertexT *vertex;
+
+  FORALLvertices {
+    if (vertex->id == id) {
+      qh_printvertex(qh, qh->fout, vertex);
+      break;
+    }
+  }
+} /* dvertex */
+
+
+/*---------------------------------
+
+  qh_compare_facetarea( p1, p2 )
+    used by qsort() to order facets by area
+*/
+int qh_compare_facetarea(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+
+  if (!a->isarea)
+    return -1;
+  if (!b->isarea)
+    return 1;
+  if (a->f.area > b->f.area)
+    return 1;
+  else if (a->f.area == b->f.area)
+    return 0;
+  return -1;
+} /* compare_facetarea */
+
+/*---------------------------------
+
+  qh_compare_facetvisit( p1, p2 )
+    used by qsort() to order facets by visit id or id
+*/
+int qh_compare_facetvisit(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+  int i,j;
+
+  if (!(i= (int)a->visitid))
+    i= (int)(0 - a->id); /* sign distinguishes id from visitid */
+  if (!(j= (int)b->visitid))
+    j= (int)(0 - b->id);
+  return(i - j);
+} /* compare_facetvisit */
+
+/*---------------------------------
+
+  qh_compare_nummerge( p1, p2 )
+    used by qsort() to order facets by number of merges
+
+notes:
+    called by qh_markkeep ('PMerge-keep')
+*/
+int qh_compare_nummerge(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+
+  return(a->nummerge - b->nummerge);
+} /* compare_nummerge */
+
+/*---------------------------------
+
+  qh_copyfilename(qh, dest, size, source, length )
+    copy filename identified by qh_skipfilename()
+
+  notes:
+    see qh_skipfilename() for syntax
+*/
+void qh_copyfilename(qhT *qh, char *filename, int size, const char* source, int length) {
+  char c= *source;
+
+  if (length > size + 1) {
+      qh_fprintf(qh, qh->ferr, 6040, "qhull error: filename is more than %d characters, %s\n",  size-1, source);
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  strncpy(filename, source, (size_t)length);
+  filename[length]= '\0';
+  if (c == '\'' || c == '"') {
+    char *s= filename + 1;
+    char *t= filename;
+    while (*s) {
+      if (*s == c) {
+          if (s[-1] == '\\')
+              t[-1]= c;
+      }else
+          *t++= *s;
+      s++;
+    }
+    *t= '\0';
+  }
+} /* copyfilename */
+
+/*---------------------------------
+
+  qh_countfacets(qh, facetlist, facets, printall,
+          numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
+    count good facets for printing and set visitid
+    if allfacets, ignores qh_skipfacet()
+
+  notes:
+    qh_printsummary and qh_countfacets must match counts
+
+  returns:
+    numfacets, numsimplicial, total neighbors, numridges, coplanars
+    each facet with ->visitid indicating 1-relative position
+      ->visitid==0 indicates not good
+
+  notes
+    numfacets >= numsimplicial
+    if qh.NEWfacets,
+      does not count visible facets (matches qh_printafacet)
+
+  design:
+    for all facets on facetlist and in facets set
+      unless facet is skipped or visible (i.e., will be deleted)
+        mark facet->visitid
+        update counts
+*/
+void qh_countfacets(qhT *qh, facetT *facetlist, setT *facets, boolT printall,
+    int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
+  facetT *facet, **facetp;
+  int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
+
+  FORALLfacet_(facetlist) {
+    if ((facet->visible && qh->NEWfacets)
+    || (!printall && qh_skipfacet(qh, facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= (unsigned int)(++numfacets);
+      totneighbors += qh_setsize(qh, facet->neighbors);
+      if (facet->simplicial) {
+        numsimplicial++;
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else
+        numridges += qh_setsize(qh, facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize(qh, facet->coplanarset);
+    }
+  }
+
+  FOREACHfacet_(facets) {
+    if ((facet->visible && qh->NEWfacets)
+    || (!printall && qh_skipfacet(qh, facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= (unsigned int)(++numfacets);
+      totneighbors += qh_setsize(qh, facet->neighbors);
+      if (facet->simplicial){
+        numsimplicial++;
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else
+        numridges += qh_setsize(qh, facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize(qh, facet->coplanarset);
+    }
+  }
+  qh->visit_id += (unsigned int)numfacets + 1;
+  *numfacetsp= numfacets;
+  *numsimplicialp= numsimplicial;
+  *totneighborsp= totneighbors;
+  *numridgesp= numridges;
+  *numcoplanarsp= numcoplanars;
+  *numtricoplanarsp= numtricoplanars;
+} /* countfacets */
+
+/*---------------------------------
+
+  qh_detvnorm(qh, vertex, vertexA, centers, offset )
+    compute separating plane of the Voronoi diagram for a pair of input sites
+    centers= set of facets (i.e., Voronoi vertices)
+      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
+
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+
+  returns:
+    norm
+      a pointer into qh.gm_matrix to qh.hull_dim-1 reals
+      copy the data before reusing qh.gm_matrix
+    offset
+      if 'QVn'
+        sign adjusted so that qh.GOODvertexp is inside
+      else
+        sign adjusted so that vertex is inside
+
+    qh.gm_matrix= simplex of points from centers relative to first center
+
+  notes:
+    in io_r.c so that code for 'v Tv' can be removed by removing io_r.c
+    returns pointer into qh.gm_matrix to avoid tracking of temporary memory
+
+  design:
+    determine midpoint of input sites
+    build points as the set of Voronoi vertices
+    select a simplex from points (if necessary)
+      include midpoint if the Voronoi region is unbounded
+    relocate the first vertex of the simplex to the origin
+    compute the normalized hyperplane through the simplex
+    orient the hyperplane toward 'QVn' or 'vertex'
+    if 'Tv' or 'Ts'
+      if bounded
+        test that hyperplane is the perpendicular bisector of the input sites
+      test that Voronoi vertices not in the simplex are still on the hyperplane
+    free up temporary memory
+*/
+pointT *qh_detvnorm(qhT *qh, vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
+  facetT *facet, **facetp;
+  int  i, k, pointid, pointidA, point_i, point_n;
+  setT *simplex= NULL;
+  pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
+  coordT *coord, *gmcoord, *normalp;
+  setT *points= qh_settemp(qh, qh->TEMPsize);
+  boolT nearzero= False;
+  boolT unbounded= False;
+  int numcenters= 0;
+  int dim= qh->hull_dim - 1;
+  realT dist, offset, angle, zero= 0.0;
+
+  midpoint= qh->gm_matrix + qh->hull_dim * qh->hull_dim;  /* last row */
+  for (k=0; k < dim; k++)
+    midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
+  FOREACHfacet_(centers) {
+    numcenters++;
+    if (!facet->visitid)
+      unbounded= True;
+    else {
+      if (!facet->center)
+        facet->center= qh_facetcenter(qh, facet->vertices);
+      qh_setappend(qh, &points, facet->center);
+    }
+  }
+  if (numcenters > dim) {
+    simplex= qh_settemp(qh, qh->TEMPsize);
+    qh_setappend(qh, &simplex, vertex->point);
+    if (unbounded)
+      qh_setappend(qh, &simplex, midpoint);
+    qh_maxsimplex(qh, dim, points, NULL, 0, &simplex);
+    qh_setdelnth(qh, simplex, 0);
+  }else if (numcenters == dim) {
+    if (unbounded)
+      qh_setappend(qh, &points, midpoint);
+    simplex= points;
+  }else {
+    qh_fprintf(qh, qh->ferr, 6216, "qhull internal error (qh_detvnorm): too few points(%d) to compute separating plane\n", numcenters);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  i= 0;
+  gmcoord= qh->gm_matrix;
+  point0= SETfirstt_(simplex, pointT);
+  FOREACHpoint_(simplex) {
+    if (qh->IStracing >= 4)
+      qh_printmatrix(qh, qh->ferr, "qh_detvnorm: Voronoi vertex or midpoint",
+                              &point, 1, dim);
+    if (point != point0) {
+      qh->gm_row[i++]= gmcoord;
+      coord= point0;
+      for (k=dim; k--; )
+        *(gmcoord++)= *point++ - *coord++;
+    }
+  }
+  qh->gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
+  normal= gmcoord;
+  qh_sethyperplane_gauss(qh, dim, qh->gm_row, point0, True,
+                normal, &offset, &nearzero);
+  /* nearzero is true for axis-parallel hyperplanes (e.g., a bounding box).  Should detect degenerate hyperplanes.  See 'Tv' check following */
+  if (qh->GOODvertexp == vertexA->point)
+    inpoint= vertexA->point;
+  else
+    inpoint= vertex->point;
+  zinc_(Zdistio);
+  dist= qh_distnorm(dim, inpoint, normal, &offset);
+  if (dist > 0) {
+    offset= -offset;
+    normalp= normal;
+    for (k=dim; k--; ) {
+      *normalp= -(*normalp);
+      normalp++;
+    }
+  }
+  if (qh->VERIFYoutput || qh->PRINTstatistics) {
+    pointid= qh_pointid(qh, vertex->point);
+    pointidA= qh_pointid(qh, vertexA->point);
+    if (!unbounded) {
+      zinc_(Zdiststat);
+      dist= qh_distnorm(dim, midpoint, normal, &offset);
+      if (dist < 0)
+        dist= -dist;
+      zzinc_(Zridgemid);
+      wwmax_(Wridgemidmax, dist);
+      wwadd_(Wridgemid, dist);
+      trace4((qh, qh->ferr, 4014, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
+                 pointid, pointidA, dist));
+      for (k=0; k < dim; k++)
+        midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
+      qh_normalize(qh, midpoint, dim, False);
+      angle= qh_distnorm(dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
+      if (angle < 0.0)
+        angle= angle + 1.0;
+      else
+        angle= angle - 1.0;
+      if (angle < 0.0)
+        angle= -angle;
+      trace4((qh, qh->ferr, 4015, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
+                 pointid, pointidA, angle, nearzero));
+      if (nearzero) {
+        zzinc_(Zridge0);
+        wwmax_(Wridge0max, angle);
+        wwadd_(Wridge0, angle);
+      }else {
+        zzinc_(Zridgeok)
+        wwmax_(Wridgeokmax, angle);
+        wwadd_(Wridgeok, angle);
+      }
+    }
+    if (simplex != points) {
+      FOREACHpoint_i_(qh, points) {
+        if (!qh_setin(simplex, point)) {
+          facet= SETelemt_(centers, point_i, facetT);
+          zinc_(Zdiststat);
+          dist= qh_distnorm(dim, point, normal, &offset);
+          if (dist < 0)
+            dist= -dist;
+          zzinc_(Zridge);
+          wwmax_(Wridgemax, dist);
+          wwadd_(Wridge, dist);
+          trace4((qh, qh->ferr, 4016, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
+                             pointid, pointidA, facet->visitid, dist));
+        }
+      }
+    }
+  }
+  *offsetp= offset;
+  if (simplex != points)
+    qh_settempfree(qh, &simplex);
+  qh_settempfree(qh, &points);
+  return normal;
+} /* detvnorm */
+
+/*---------------------------------
+
+  qh_detvridge(qh, vertexA )
+    determine Voronoi ridge from 'seen' neighbors of vertexA
+    include one vertex-at-infinite if an !neighbor->visitid
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    sorted by center id
+*/
+setT *qh_detvridge(qhT *qh, vertexT *vertex) {
+  setT *centers= qh_settemp(qh, qh->TEMPsize);
+  setT *tricenters= qh_settemp(qh, qh->TEMPsize);
+  facetT *neighbor, **neighborp;
+  boolT firstinf= True;
+
+  FOREACHneighbor_(vertex) {
+    if (neighbor->seen) {
+      if (neighbor->visitid) {
+        if (!neighbor->tricoplanar || qh_setunique(qh, &tricenters, neighbor->center))
+          qh_setappend(qh, ¢ers, neighbor);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend(qh, ¢ers, neighbor);
+      }
+    }
+  }
+  qsort(SETaddr_(centers, facetT), (size_t)qh_setsize(qh, centers),
+             sizeof(facetT *), qh_compare_facetvisit);
+  qh_settempfree(qh, &tricenters);
+  return centers;
+} /* detvridge */
+
+/*---------------------------------
+
+  qh_detvridge3(qh, atvertex, vertex )
+    determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
+    include one vertex-at-infinite for !neighbor->visitid
+    assumes all facet->seen2= True
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    listed in adjacency order (!oriented)
+    all facet->seen2= True
+
+  design:
+    mark all neighbors of atvertex
+    for each adjacent neighbor of both atvertex and vertex
+      if neighbor selected
+        add neighbor to set of Voronoi vertices
+*/
+setT *qh_detvridge3(qhT *qh, vertexT *atvertex, vertexT *vertex) {
+  setT *centers= qh_settemp(qh, qh->TEMPsize);
+  setT *tricenters= qh_settemp(qh, qh->TEMPsize);
+  facetT *neighbor, **neighborp, *facet= NULL;
+  boolT firstinf= True;
+
+  FOREACHneighbor_(atvertex)
+    neighbor->seen2= False;
+  FOREACHneighbor_(vertex) {
+    if (!neighbor->seen2) {
+      facet= neighbor;
+      break;
+    }
+  }
+  while (facet) {
+    facet->seen2= True;
+    if (neighbor->seen) {
+      if (facet->visitid) {
+        if (!facet->tricoplanar || qh_setunique(qh, &tricenters, facet->center))
+          qh_setappend(qh, ¢ers, facet);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend(qh, ¢ers, facet);
+      }
+    }
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen2) {
+        if (qh_setin(vertex->neighbors, neighbor))
+          break;
+        else
+          neighbor->seen2= True;
+      }
+    }
+    facet= neighbor;
+  }
+  if (qh->CHECKfrequently) {
+    FOREACHneighbor_(vertex) {
+      if (!neighbor->seen2) {
+          qh_fprintf(qh, qh->ferr, 6217, "qhull internal error (qh_detvridge3): neighbors of vertex p%d are not connected at facet %d\n",
+                 qh_pointid(qh, vertex->point), neighbor->id);
+        qh_errexit(qh, qh_ERRqhull, neighbor, NULL);
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex)
+    neighbor->seen2= True;
+  qh_settempfree(qh, &tricenters);
+  return centers;
+} /* detvridge3 */
+
+/*---------------------------------
+
+  qh_eachvoronoi(qh, fp, printvridge, vertex, visitall, innerouter, inorder )
+    if visitall,
+      visit all Voronoi ridges for vertex (i.e., an input site)
+    else
+      visit all unvisited Voronoi ridges for vertex
+      all vertex->seen= False if unvisited
+    assumes
+      all facet->seen= False
+      all facet->seen2= True (for qh_detvridge3)
+      all facet->visitid == 0 if vertex_at_infinity
+                         == index of Voronoi vertex
+                         >= qh.num_facets if ignored
+    innerouter:
+      qh_RIDGEall--  both inner (bounded) and outer(unbounded) ridges
+      qh_RIDGEinner- only inner
+      qh_RIDGEouter- only outer
+
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+
+  returns:
+    number of visited ridges (does not include previously visited ridges)
+
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+        fp== any pointer (assumes FILE*)
+             fp may be NULL for QhullQh::qh_fprintf which calls appendQhullMessage
+        vertex,vertexA= pair of input sites that define a Voronoi ridge
+        centers= set of facets (i.e., Voronoi vertices)
+                 ->visitid == index or 0 if vertex_at_infinity
+                 ordered for 3-d Voronoi diagram
+  notes:
+    uses qh.vertex_visit
+
+  see:
+    qh_eachvoronoi_all()
+
+  design:
+    mark selected neighbors of atvertex
+    for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
+      for each unvisited vertex
+        if atvertex and vertex share more than d-1 neighbors
+          bump totalcount
+          if printvridge defined
+            build the set of shared neighbors (i.e., Voronoi vertices)
+            call printvridge
+*/
+int qh_eachvoronoi(qhT *qh, FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
+  boolT unbounded;
+  int count;
+  facetT *neighbor, **neighborp, *neighborA, **neighborAp;
+  setT *centers;
+  setT *tricenters= qh_settemp(qh, qh->TEMPsize);
+
+  vertexT *vertex, **vertexp;
+  boolT firstinf;
+  unsigned int numfacets= (unsigned int)qh->num_facets;
+  int totridges= 0;
+
+  qh->vertex_visit++;
+  atvertex->seen= True;
+  if (visitall) {
+    FORALLvertices
+      vertex->seen= False;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->visitid < numfacets)
+      neighbor->seen= True;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->seen) {
+      FOREACHvertex_(neighbor->vertices) {
+        if (vertex->visitid != qh->vertex_visit && !vertex->seen) {
+          vertex->visitid= qh->vertex_visit;
+          count= 0;
+          firstinf= True;
+          qh_settruncate(qh, tricenters, 0);
+          FOREACHneighborA_(vertex) {
+            if (neighborA->seen) {
+              if (neighborA->visitid) {
+                if (!neighborA->tricoplanar || qh_setunique(qh, &tricenters, neighborA->center))
+                  count++;
+              }else if (firstinf) {
+                count++;
+                firstinf= False;
+              }
+            }
+          }
+          if (count >= qh->hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
+            if (firstinf) {
+              if (innerouter == qh_RIDGEouter)
+                continue;
+              unbounded= False;
+            }else {
+              if (innerouter == qh_RIDGEinner)
+                continue;
+              unbounded= True;
+            }
+            totridges++;
+            trace4((qh, qh->ferr, 4017, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
+                  count, qh_pointid(qh, atvertex->point), qh_pointid(qh, vertex->point)));
+            if (printvridge) {
+              if (inorder && qh->hull_dim == 3+1) /* 3-d Voronoi diagram */
+                centers= qh_detvridge3(qh, atvertex, vertex);
+              else
+                centers= qh_detvridge(qh, vertex);
+              (*printvridge)(qh, fp, atvertex, vertex, centers, unbounded);
+              qh_settempfree(qh, ¢ers);
+            }
+          }
+        }
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex)
+    neighbor->seen= False;
+  qh_settempfree(qh, &tricenters);
+  return totridges;
+} /* eachvoronoi */
+
+
+/*---------------------------------
+
+  qh_eachvoronoi_all(qh, fp, printvridge, isUpper, innerouter, inorder )
+    visit all Voronoi ridges
+
+    innerouter:
+      see qh_eachvoronoi()
+
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+
+  returns
+    total number of ridges
+
+    if isUpper == facet->upperdelaunay  (i.e., a Vornoi vertex)
+      facet->visitid= Voronoi vertex index(same as 'o' format)
+    else
+      facet->visitid= 0
+
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+      [see qh_eachvoronoi]
+
+  notes:
+    Not used for qhull.exe
+    same effect as qh_printvdiagram but ridges not sorted by point id
+*/
+int qh_eachvoronoi_all(qhT *qh, FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder) {
+  facetT *facet;
+  vertexT *vertex;
+  int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
+  int totridges= 0;
+
+  qh_clearcenters(qh, qh_ASvoronoi);
+  qh_vertexneighbors(qh);
+  maximize_(qh->visit_id, (unsigned int)qh->num_facets);
+  FORALLfacets {
+    facet->visitid= 0;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  FORALLfacets {
+    if (facet->upperdelaunay == isUpper)
+      facet->visitid= (unsigned int)(numcenters++);
+  }
+  FORALLvertices
+    vertex->seen= False;
+  FORALLvertices {
+    if (qh->GOODvertex > 0 && qh_pointid(qh, vertex->point)+1 != qh->GOODvertex)
+      continue;
+    totridges += qh_eachvoronoi(qh, fp, printvridge, vertex,
+                   !qh_ALL, innerouter, inorder);
+  }
+  return totridges;
+} /* eachvoronoi_all */
+
+/*---------------------------------
+
+  qh_facet2point(qh, facet, point0, point1, mindist )
+    return two projected temporary vertices for a 2-d facet
+    may be non-simplicial
+
+  returns:
+    point0 and point1 oriented and projected to the facet
+    returns mindist (maximum distance below plane)
+*/
+void qh_facet2point(qhT *qh, facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
+  vertexT *vertex0, *vertex1;
+  realT dist;
+
+  if (facet->toporient ^ qh_ORIENTclock) {
+    vertex0= SETfirstt_(facet->vertices, vertexT);
+    vertex1= SETsecondt_(facet->vertices, vertexT);
+  }else {
+    vertex1= SETfirstt_(facet->vertices, vertexT);
+    vertex0= SETsecondt_(facet->vertices, vertexT);
+  }
+  zadd_(Zdistio, 2);
+  qh_distplane(qh, vertex0->point, facet, &dist);
+  *mindist= dist;
+  *point0= qh_projectpoint(qh, vertex0->point, facet, dist);
+  qh_distplane(qh, vertex1->point, facet, &dist);
+  minimize_(*mindist, dist);
+  *point1= qh_projectpoint(qh, vertex1->point, facet, dist);
+} /* facet2point */
+
+
+/*---------------------------------
+
+  qh_facetvertices(qh, facetlist, facets, allfacets )
+    returns temporary set of vertices in a set and/or list of facets
+    if allfacets, ignores qh_skipfacet()
+
+  returns:
+    vertices with qh.vertex_visit
+
+  notes:
+    optimized for allfacets of facet_list
+
+  design:
+    if allfacets of facet_list
+      create vertex set from vertex_list
+    else
+      for each selected facet in facets or facetlist
+        append unvisited vertices to vertex set
+*/
+setT *qh_facetvertices(qhT *qh, facetT *facetlist, setT *facets, boolT allfacets) {
+  setT *vertices;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+
+  qh->vertex_visit++;
+  if (facetlist == qh->facet_list && allfacets && !facets) {
+    vertices= qh_settemp(qh, qh->num_vertices);
+    FORALLvertices {
+      vertex->visitid= qh->vertex_visit;
+      qh_setappend(qh, &vertices, vertex);
+    }
+  }else {
+    vertices= qh_settemp(qh, qh->TEMPsize);
+    FORALLfacet_(facetlist) {
+      if (!allfacets && qh_skipfacet(qh, facet))
+        continue;
+      FOREACHvertex_(facet->vertices) {
+        if (vertex->visitid != qh->vertex_visit) {
+          vertex->visitid= qh->vertex_visit;
+          qh_setappend(qh, &vertices, vertex);
+        }
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (!allfacets && qh_skipfacet(qh, facet))
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh->vertex_visit) {
+        vertex->visitid= qh->vertex_visit;
+        qh_setappend(qh, &vertices, vertex);
+      }
+    }
+  }
+  return vertices;
+} /* facetvertices */
+
+/*---------------------------------
+
+  qh_geomplanes(qh, facet, outerplane, innerplane )
+    return outer and inner planes for Geomview
+    qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
+
+  notes:
+    assume precise calculations in io_r.c with roundoff covered by qh_GEOMepsilon
+*/
+void qh_geomplanes(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane) {
+  realT radius;
+
+  if (qh->MERGING || qh->JOGGLEmax < REALmax/2) {
+    qh_outerinner(qh, facet, outerplane, innerplane);
+    radius= qh->PRINTradius;
+    if (qh->JOGGLEmax < REALmax/2)
+      radius -= qh->JOGGLEmax * sqrt((realT)qh->hull_dim);  /* already accounted for in qh_outerinner() */
+    *outerplane += radius;
+    *innerplane -= radius;
+    if (qh->PRINTcoplanar || qh->PRINTspheres) {
+      *outerplane += qh->MAXabs_coord * qh_GEOMepsilon;
+      *innerplane -= qh->MAXabs_coord * qh_GEOMepsilon;
+    }
+  }else
+    *innerplane= *outerplane= 0;
+} /* geomplanes */
+
+
+/*---------------------------------
+
+  qh_markkeep(qh, facetlist )
+    restrict good facets for qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
+    ignores visible facets (!part of convex hull)
+
+  returns:
+    may clear facet->good
+    recomputes qh.num_good
+
+  notes:
+    only called by qh_prepare_output after qh_findgood_all
+    does not throw errors except memory/corruption of qset_r.c
+
+  design:
+    get set of good facets
+    if qh.KEEParea
+      sort facets by area
+      clear facet->good for all but n largest facets
+    if qh.KEEPmerge
+      sort facets by merge count
+      clear facet->good for all but n most merged facets
+    if qh.KEEPminarea
+      clear facet->good if area too small
+    update qh.num_good
+*/
+void qh_markkeep(qhT *qh, facetT *facetlist) {
+  facetT *facet, **facetp;
+  setT *facets= qh_settemp(qh, qh->num_facets);
+  int size, count;
+
+  trace2((qh, qh->ferr, 2006, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
+          qh->KEEParea, qh->KEEPmerge, qh->KEEPminArea));
+  FORALLfacet_(facetlist) {
+    if (!facet->visible && facet->good)
+      qh_setappend(qh, &facets, facet);
+  }
+  size= qh_setsize(qh, facets);
+  if (qh->KEEParea) {
+    qsort(SETaddr_(facets, facetT), (size_t)size,
+             sizeof(facetT *), qh_compare_facetarea);
+    if ((count= size - qh->KEEParea) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh->KEEPmerge) {
+    qsort(SETaddr_(facets, facetT), (size_t)size,
+             sizeof(facetT *), qh_compare_nummerge);
+    if ((count= size - qh->KEEPmerge) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh->KEEPminArea < REALmax/2) {
+    FOREACHfacet_(facets) {
+      if (!facet->isarea || facet->f.area < qh->KEEPminArea)
+        facet->good= False;
+    }
+  }
+  qh_settempfree(qh, &facets);
+  count= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      count++;
+  }
+  qh->num_good= count;
+} /* markkeep */
+
+
+/*---------------------------------
+
+  qh_markvoronoi(qh, facetlist, facets, printall, isLower, numcenters )
+    mark voronoi vertices for printing by site pairs
+
+  returns:
+    temporary set of vertices indexed by pointid
+    isLower set if printing lower hull (i.e., at least one facet is lower hull)
+    numcenters= total number of Voronoi vertices
+    bumps qh.printoutnum for vertex-at-infinity
+    clears all facet->seen and sets facet->seen2
+
+    if selected
+      facet->visitid= Voronoi vertex id
+    else if upper hull (or 'Qu' and lower hull)
+      facet->visitid= 0
+    else
+      facet->visitid >= qh->num_facets
+
+  notes:
+    ignores qh.ATinfinity, if defined
+*/
+setT *qh_markvoronoi(qhT *qh, facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp) {
+  int numcenters=0;
+  facetT *facet, **facetp;
+  setT *vertices;
+  boolT isLower= False;
+
+  qh->printoutnum++;
+  qh_clearcenters(qh, qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
+  qh_vertexneighbors(qh);
+  vertices= qh_pointvertex(qh);
+  if (qh->ATinfinity)
+    SETelem_(vertices, qh->num_points-1)= NULL;
+  qh->visit_id++;
+  maximize_(qh->visit_id, (unsigned int)qh->num_facets);
+  FORALLfacet_(facetlist) {
+    if (printall || !qh_skipfacet(qh, facet)) {
+      if (!facet->upperdelaunay) {
+        isLower= True;
+        break;
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet(qh, facet)) {
+      if (!facet->upperdelaunay) {
+        isLower= True;
+        break;
+      }
+    }
+  }
+  FORALLfacets {
+    if (facet->normal && (facet->upperdelaunay == isLower))
+      facet->visitid= 0;  /* facetlist or facets may overwrite */
+    else
+      facet->visitid= qh->visit_id;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  numcenters++;  /* qh_INFINITE */
+  FORALLfacet_(facetlist) {
+    if (printall || !qh_skipfacet(qh, facet))
+      facet->visitid= (unsigned int)(numcenters++);
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet(qh, facet))
+      facet->visitid= (unsigned int)(numcenters++);
+  }
+  *isLowerp= isLower;
+  *numcentersp= numcenters;
+  trace2((qh, qh->ferr, 2007, "qh_markvoronoi: isLower %d numcenters %d\n", isLower, numcenters));
+  return vertices;
+} /* markvoronoi */
+
+/*---------------------------------
+
+  qh_order_vertexneighbors(qh, vertex )
+    order facet neighbors of vertex by 2-d (orientation), 3-d (adjacency), or n-d (f.visitid,id)
+
+  notes:
+    error if qh_vertexneighbors not called beforehand
+    only 2-d orients the neighbors
+    for 4-d and higher
+      set or clear f.visitid for qh_compare_facetvisit
+      for example, use qh_markvoronoi (e.g., qh_printvornoi) or qh_countfacets (e.g., qh_printvneighbors)
+
+  design (2-d):
+    see qh_printextremes_2d
+  design (3-d):
+    initialize a new neighbor set with the first facet in vertex->neighbors
+    while vertex->neighbors non-empty
+      select next neighbor in the previous facet's neighbor set
+    set vertex->neighbors to the new neighbor set
+  design (n-d):
+    qsort by f.visitid, or f.facetid (qh_compare_facetvisit)
+    facet_id is negated (sorted before visit_id facets)
+*/
+void qh_order_vertexneighbors(qhT *qh, vertexT *vertex) {
+  setT *newset;
+  facetT *facet, *facetA, *facetB, *neighbor, **neighborp;
+  vertexT *vertexA;
+  int numneighbors;
+
+  trace4((qh, qh->ferr, 4018, "qh_order_vertexneighbors: order facet neighbors of v%d by 2-d (orientation), 3-d (adjacency), or n-d (f.visitid,id)\n", vertex->id));
+  if (!qh->VERTEXneighbors) {
+    qh_fprintf(qh, qh->ferr, 6428, "qhull internal error (qh_order_vertexneighbors): call qh_vertexneighbors before calling qh_order_vertexneighbors\n");
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (qh->hull_dim == 2) {
+    facetA= SETfirstt_(vertex->neighbors, facetT);
+    if (facetA->toporient ^ qh_ORIENTclock)
+      vertexA= SETfirstt_(facetA->vertices, vertexT);
+    else
+      vertexA= SETsecondt_(facetA->vertices, vertexT);
+    if (vertexA!=vertex) {
+      facetB= SETsecondt_(vertex->neighbors, facetT);
+      SETfirst_(vertex->neighbors)= facetB;
+      SETsecond_(vertex->neighbors)= facetA;
+    }
+  }else if (qh->hull_dim == 3) {
+    newset= qh_settemp(qh, qh_setsize(qh, vertex->neighbors));
+    facet= (facetT *)qh_setdellast(vertex->neighbors);
+    qh_setappend(qh, &newset, facet);
+    while (qh_setsize(qh, vertex->neighbors)) {
+      FOREACHneighbor_(vertex) {
+        if (qh_setin(facet->neighbors, neighbor)) {
+          qh_setdel(vertex->neighbors, neighbor);
+          qh_setappend(qh, &newset, neighbor);
+          facet= neighbor;
+          break;
+        }
+      }
+      if (!neighbor) {
+        qh_fprintf(qh, qh->ferr, 6066, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
+          vertex->id, facet->id);
+        qh_errexit(qh, qh_ERRqhull, facet, NULL);
+      }
+    }
+    qh_setfree(qh, &vertex->neighbors);
+    qh_settemppop(qh);
+    vertex->neighbors= newset;
+  }else { /* qh.hull_dim >= 4 */
+    numneighbors= qh_setsize(qh, vertex->neighbors);
+    qsort(SETaddr_(vertex->neighbors, facetT), (size_t)numneighbors,
+        sizeof(facetT *), qh_compare_facetvisit);
+  }
+} /* order_vertexneighbors */
+
+/*---------------------------------
+
+  qh_prepare_output(qh )
+    prepare for qh_produce_output2(qh) according to
+      qh.KEEPminArea, KEEParea, KEEPmerge, GOODvertex, GOODthreshold, GOODpoint, ONLYgood, SPLITthresholds
+    does not reset facet->good
+
+  notes
+    called by qh_produce_output, qh_new_qhull, Qhull.outputQhull
+    except for PRINTstatistics, no-op if previously called with same options
+*/
+void qh_prepare_output(qhT *qh) {
+  if (qh->VORONOI) {
+    qh_clearcenters(qh, qh_ASvoronoi);  /* must be before qh_triangulate */
+    qh_vertexneighbors(qh);
+  }
+  if (qh->TRIangulate && !qh->hasTriangulation) {
+    qh_triangulate(qh);
+    if (qh->VERIFYoutput && !qh->CHECKfrequently)
+      qh_checkpolygon(qh, qh->facet_list);
+  }
+  qh_findgood_all(qh, qh->facet_list);
+  if (qh->GETarea)
+    qh_getarea(qh, qh->facet_list);
+  if (qh->KEEParea || qh->KEEPmerge || qh->KEEPminArea < REALmax/2)
+    qh_markkeep(qh, qh->facet_list);
+  if (qh->PRINTstatistics)
+    qh_collectstatistics(qh);
+}
+
+/*---------------------------------
+
+  qh_printafacet(qh, fp, format, facet, printall )
+    print facet to fp in given output format (see qh.PRINTout)
+
+  returns:
+    nop if !printall and qh_skipfacet()
+    nop if visible facet and NEWfacets and format != PRINTfacets
+    must match qh_countfacets
+
+  notes
+    preserves qh.visit_id
+    facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
+
+  see
+    qh_printbegin() and qh_printend()
+
+  design:
+    test for printing facet
+    call appropriate routine for format
+    or output results directly
+*/
+void qh_printafacet(qhT *qh, FILE *fp, qh_PRINT format, facetT *facet, boolT printall) {
+  realT color[4], offset, dist, outerplane, innerplane;
+  boolT zerodiv;
+  coordT *point, *normp, *coordp, **pointp, *feasiblep;
+  int k;
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+
+  if (!printall && qh_skipfacet(qh, facet))
+    return;
+  if (facet->visible && qh->NEWfacets && format != qh_PRINTfacets)
+    return;
+  qh->printoutnum++;
+  switch (format) {
+  case qh_PRINTarea:
+    if (facet->isarea) {
+      qh_fprintf(qh, fp, 9009, qh_REAL_1, facet->f.area);
+      qh_fprintf(qh, fp, 9010, "\n");
+    }else
+      qh_fprintf(qh, fp, 9011, "0\n");
+    break;
+  case qh_PRINTcoplanars:
+    qh_fprintf(qh, fp, 9012, "%d", qh_setsize(qh, facet->coplanarset));
+    FOREACHpoint_(facet->coplanarset)
+      qh_fprintf(qh, fp, 9013, " %d", qh_pointid(qh, point));
+    qh_fprintf(qh, fp, 9014, "\n");
+    break;
+  case qh_PRINTcentrums:
+    qh_printcenter(qh, fp, format, NULL, facet);
+    break;
+  case qh_PRINTfacets:
+    qh_printfacet(qh, fp, facet);
+    break;
+  case qh_PRINTfacets_xridge:
+    qh_printfacetheader(qh, fp, facet);
+    break;
+  case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
+    if (!facet->normal)
+      break;
+    for (k=qh->hull_dim; k--; ) {
+      color[k]= (facet->normal[k]+1.0)/2.0;
+      maximize_(color[k], -1.0);
+      minimize_(color[k], +1.0);
+    }
+    qh_projectdim3(qh, color, color);
+    if (qh->PRINTdim != qh->hull_dim)
+      qh_normalize2(qh, color, 3, True, NULL, NULL);
+    if (qh->hull_dim <= 2)
+      qh_printfacet2geom(qh, fp, facet, color);
+    else if (qh->hull_dim == 3) {
+      if (facet->simplicial)
+        qh_printfacet3geom_simplicial(qh, fp, facet, color);
+      else
+        qh_printfacet3geom_nonsimplicial(qh, fp, facet, color);
+    }else {
+      if (facet->simplicial)
+        qh_printfacet4geom_simplicial(qh, fp, facet, color);
+      else
+        qh_printfacet4geom_nonsimplicial(qh, fp, facet, color);
+    }
+    break;
+  case qh_PRINTids:
+    qh_fprintf(qh, fp, 9015, "%d\n", facet->id);
+    break;
+  case qh_PRINTincidences:
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh->hull_dim == 3 && format != qh_PRINTtriangles)
+      qh_printfacet3vertex(qh, fp, facet, format);
+    else if (facet->simplicial || qh->hull_dim == 2 || format == qh_PRINToff)
+      qh_printfacetNvertex_simplicial(qh, fp, facet, format);
+    else
+      qh_printfacetNvertex_nonsimplicial(qh, fp, facet, qh->printoutvar++, format);
+    break;
+  case qh_PRINTinner:
+    qh_outerinner(qh, facet, NULL, &innerplane);
+    offset= facet->offset - innerplane;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTmerges:
+    qh_fprintf(qh, fp, 9016, "%d\n", facet->nummerge);
+    break;
+  case qh_PRINTnormals:
+    offset= facet->offset;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTouter:
+    qh_outerinner(qh, facet, &outerplane, NULL);
+    offset= facet->offset - outerplane;
+  LABELprintnorm:
+    if (!facet->normal) {
+      qh_fprintf(qh, fp, 9017, "no normal for facet f%d\n", facet->id);
+      break;
+    }
+    if (qh->CDDoutput) {
+      qh_fprintf(qh, fp, 9018, qh_REAL_1, -offset);
+      for (k=0; k < qh->hull_dim; k++)
+        qh_fprintf(qh, fp, 9019, qh_REAL_1, -facet->normal[k]);
+    }else {
+      for (k=0; k < qh->hull_dim; k++)
+        qh_fprintf(qh, fp, 9020, qh_REAL_1, facet->normal[k]);
+      qh_fprintf(qh, fp, 9021, qh_REAL_1, offset);
+    }
+    qh_fprintf(qh, fp, 9022, "\n");
+    break;
+  case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
+  case qh_PRINTmaple:
+    if (qh->hull_dim == 2)
+      qh_printfacet2math(qh, fp, facet, format, qh->printoutvar++);
+    else
+      qh_printfacet3math(qh, fp, facet, format, qh->printoutvar++);
+    break;
+  case qh_PRINTneighbors:
+    qh_fprintf(qh, fp, 9023, "%d", qh_setsize(qh, facet->neighbors));
+    FOREACHneighbor_(facet)
+      qh_fprintf(qh, fp, 9024, " %d",
+               neighbor->visitid ? neighbor->visitid - 1: 0 - neighbor->id);
+    qh_fprintf(qh, fp, 9025, "\n");
+    break;
+  case qh_PRINTpointintersect:
+    if (!qh->feasible_point) {
+      qh_fprintf(qh, qh->ferr, 6067, "qhull input error (qh_printafacet): option 'Fp' needs qh->feasible_point\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    if (facet->offset > 0)
+      goto LABELprintinfinite;
+    point= coordp= (coordT *)qh_memalloc(qh, qh->normal_size);
+    normp= facet->normal;
+    feasiblep= qh->feasible_point;
+    if (facet->offset < -qh->MINdenom) {
+      for (k=qh->hull_dim; k--; )
+        *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
+    }else {
+      for (k=qh->hull_dim; k--; ) {
+        *(coordp++)= qh_divzero(*(normp++), facet->offset, qh->MINdenom_1,
+                                 &zerodiv) + *(feasiblep++);
+        if (zerodiv) {
+          qh_memfree(qh, point, qh->normal_size);
+          goto LABELprintinfinite;
+        }
+      }
+    }
+    qh_printpoint(qh, fp, NULL, point);
+    qh_memfree(qh, point, qh->normal_size);
+    break;
+  LABELprintinfinite:
+    for (k=qh->hull_dim; k--; )
+      qh_fprintf(qh, fp, 9026, qh_REAL_1, qh_INFINITE);
+    qh_fprintf(qh, fp, 9027, "\n");
+    break;
+  case qh_PRINTpointnearest:
+    FOREACHpoint_(facet->coplanarset) {
+      int id, id2;
+      vertex= qh_nearvertex(qh, facet, point, &dist);
+      id= qh_pointid(qh, vertex->point);
+      id2= qh_pointid(qh, point);
+      qh_fprintf(qh, fp, 9028, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
+    }
+    break;
+  case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
+    if (qh->CDDoutput)
+      qh_fprintf(qh, fp, 9029, "1 ");
+    qh_printcenter(qh, fp, format, NULL, facet);
+    break;
+  case qh_PRINTvertices:
+    qh_fprintf(qh, fp, 9030, "%d", qh_setsize(qh, facet->vertices));
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(qh, fp, 9031, " %d", qh_pointid(qh, vertex->point));
+    qh_fprintf(qh, fp, 9032, "\n");
+    break;
+  default:
+    break;
+  }
+} /* printafacet */
+
+/*---------------------------------
+
+  qh_printbegin(qh )
+    prints header for all output formats
+
+  returns:
+    checks for valid format
+
+  notes:
+    uses qh.visit_id for 3/4off
+    changes qh.interior_point if printing centrums
+    qh_countfacets clears facet->visitid for non-good facets
+
+  see
+    qh_printend() and qh_printafacet()
+
+  design:
+    count facets and related statistics
+    print header for format
+*/
+void qh_printbegin(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  int i, num;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+  pointT *point, **pointp, *pointtemp;
+
+  qh->printoutnum= 0;
+  qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+  switch (format) {
+  case qh_PRINTnone:
+    break;
+  case qh_PRINTarea:
+    qh_fprintf(qh, fp, 9033, "%d\n", numfacets);
+    break;
+  case qh_PRINTcoplanars:
+    qh_fprintf(qh, fp, 9034, "%d\n", numfacets);
+    break;
+  case qh_PRINTcentrums:
+    if (qh->CENTERtype == qh_ASnone)
+      qh_clearcenters(qh, qh_AScentrum);
+    qh_fprintf(qh, fp, 9035, "%d\n%d\n", qh->hull_dim, numfacets);
+    break;
+  case qh_PRINTfacets:
+  case qh_PRINTfacets_xridge:
+    if (facetlist)
+      qh_printvertexlist(qh, fp, "Vertices and facets:\n", facetlist, facets, printall);
+    break;
+  case qh_PRINTgeom:
+    if (qh->hull_dim > 4)  /* qh_initqhull_globals also checks */
+      goto LABELnoformat;
+    if (qh->VORONOI && qh->hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
+      goto LABELnoformat;
+    if (qh->hull_dim == 2 && (qh->PRINTridges || qh->DOintersections))
+      qh_fprintf(qh, qh->ferr, 7049, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
+    if (qh->hull_dim == 4 && (qh->PRINTinner || qh->PRINTouter ||
+                             (qh->PRINTdim == 4 && qh->PRINTcentrums)))
+      qh_fprintf(qh, qh->ferr, 7050, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
+    if (qh->PRINTdim == 4 && (qh->PRINTspheres))
+      qh_fprintf(qh, qh->ferr, 7051, "qhull warning: output for vertices not implemented in 4-d\n");
+    if (qh->PRINTdim == 4 && qh->DOintersections && qh->PRINTnoplanes)
+      qh_fprintf(qh, qh->ferr, 7052, "qhull warning: 'Gnh' generates no output in 4-d\n");
+    if (qh->PRINTdim == 2) {
+      qh_fprintf(qh, fp, 9036, "{appearance {linewidth 3} LIST # %s | %s\n",
+              qh->rbox_command, qh->qhull_command);
+    }else if (qh->PRINTdim == 3) {
+      qh_fprintf(qh, fp, 9037, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
+              qh->rbox_command, qh->qhull_command);
+    }else if (qh->PRINTdim == 4) {
+      qh->visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)    /* get number of ridges to be printed */
+        qh_printend4geom(qh, NULL, facet, &num, printall);
+      FOREACHfacet_(facets)
+        qh_printend4geom(qh, NULL, facet, &num, printall);
+      qh->ridgeoutnum= num;
+      qh->printoutvar= 0;  /* counts number of ridges in output */
+      qh_fprintf(qh, fp, 9038, "LIST # %s | %s\n", qh->rbox_command, qh->qhull_command);
+    }
+
+    if (qh->PRINTdots) {
+      qh->printoutnum++;
+      num= qh->num_points + qh_setsize(qh, qh->other_points);
+      if (qh->DELAUNAY && qh->ATinfinity)
+        num--;
+      if (qh->PRINTdim == 4)
+        qh_fprintf(qh, fp, 9039, "4VECT %d %d 1\n", num, num);
+      else
+        qh_fprintf(qh, fp, 9040, "VECT %d %d 1\n", num, num);
+
+      for (i=num; i--; ) {
+        if (i % 20 == 0)
+          qh_fprintf(qh, fp, 9041, "\n");
+        qh_fprintf(qh, fp, 9042, "1 ");
+      }
+      qh_fprintf(qh, fp, 9043, "# 1 point per line\n1 ");
+      for (i=num-1; i--; ) { /* num at least 3 for D2 */
+        if (i % 20 == 0)
+          qh_fprintf(qh, fp, 9044, "\n");
+        qh_fprintf(qh, fp, 9045, "0 ");
+      }
+      qh_fprintf(qh, fp, 9046, "# 1 color for all\n");
+      FORALLpoints {
+        if (!qh->DELAUNAY || !qh->ATinfinity || qh_pointid(qh, point) != qh->num_points-1) {
+          if (qh->PRINTdim == 4)
+            qh_printpoint(qh, fp, NULL, point);
+            else
+              qh_printpoint3(qh, fp, point);
+        }
+      }
+      FOREACHpoint_(qh->other_points) {
+        if (qh->PRINTdim == 4)
+          qh_printpoint(qh, fp, NULL, point);
+        else
+          qh_printpoint3(qh, fp, point);
+      }
+      qh_fprintf(qh, fp, 9047, "0 1 1 1  # color of points\n");
+    }
+
+    if (qh->PRINTdim == 4  && !qh->PRINTnoplanes)
+      /* 4dview loads up multiple 4OFF objects slowly */
+      qh_fprintf(qh, fp, 9048, "4OFF %d %d 1\n", 3*qh->ridgeoutnum, qh->ridgeoutnum);
+    qh->PRINTcradius= 2 * qh->DISTround;  /* include test DISTround */
+    if (qh->PREmerge) {
+      maximize_(qh->PRINTcradius, qh->premerge_centrum + qh->DISTround);
+    }else if (qh->POSTmerge)
+      maximize_(qh->PRINTcradius, qh->postmerge_centrum + qh->DISTround);
+    qh->PRINTradius= qh->PRINTcradius;
+    if (qh->PRINTspheres + qh->PRINTcoplanar)
+      maximize_(qh->PRINTradius, qh->MAXabs_coord * qh_MINradius);
+    if (qh->premerge_cos < REALmax/2) {
+      maximize_(qh->PRINTradius, (1- qh->premerge_cos) * qh->MAXabs_coord);
+    }else if (!qh->PREmerge && qh->POSTmerge && qh->postmerge_cos < REALmax/2) {
+      maximize_(qh->PRINTradius, (1- qh->postmerge_cos) * qh->MAXabs_coord);
+    }
+    maximize_(qh->PRINTradius, qh->MINvisible);
+    if (qh->JOGGLEmax < REALmax/2)
+      qh->PRINTradius += qh->JOGGLEmax * sqrt((realT)qh->hull_dim);
+    if (qh->PRINTdim != 4 &&
+        (qh->PRINTcoplanar || qh->PRINTspheres || qh->PRINTcentrums)) {
+      vertices= qh_facetvertices(qh, facetlist, facets, printall);
+      if (qh->PRINTspheres && qh->PRINTdim <= 3)
+        qh_printspheres(qh, fp, vertices, qh->PRINTradius);
+      if (qh->PRINTcoplanar || qh->PRINTcentrums) {
+        qh->firstcentrum= True;
+        if (qh->PRINTcoplanar&& !qh->PRINTspheres) {
+          FOREACHvertex_(vertices)
+            qh_printpointvect2(qh, fp, vertex->point, NULL, qh->interior_point, qh->PRINTradius);
+        }
+        FORALLfacet_(facetlist) {
+          if (!printall && qh_skipfacet(qh, facet))
+            continue;
+          if (!facet->normal)
+            continue;
+          if (qh->PRINTcentrums && qh->PRINTdim <= 3)
+            qh_printcentrum(qh, fp, facet, qh->PRINTcradius);
+          if (!qh->PRINTcoplanar)
+            continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
+        }
+        FOREACHfacet_(facets) {
+          if (!printall && qh_skipfacet(qh, facet))
+            continue;
+          if (!facet->normal)
+            continue;
+          if (qh->PRINTcentrums && qh->PRINTdim <= 3)
+            qh_printcentrum(qh, fp, facet, qh->PRINTcradius);
+          if (!qh->PRINTcoplanar)
+            continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
+        }
+      }
+      qh_settempfree(qh, &vertices);
+    }
+    qh->visit_id++; /* for printing hyperplane intersections */
+    break;
+  case qh_PRINTids:
+    qh_fprintf(qh, fp, 9049, "%d\n", numfacets);
+    break;
+  case qh_PRINTincidences:
+    if (qh->VORONOI && qh->PRINTprecision)
+      qh_fprintf(qh, qh->ferr, 7053, "qhull warning: input sites of Delaunay regions (option 'i').  Use option 'p' or 'o' for Voronoi centers.  Disable warning with option 'Pp'\n");
+    qh->printoutvar= (int)qh->vertex_id;  /* centrum id for 4-d+, non-simplicial facets */
+    if (qh->hull_dim <= 3)
+      qh_fprintf(qh, fp, 9050, "%d\n", numfacets);
+    else
+      qh_fprintf(qh, fp, 9051, "%d\n", numsimplicial+numridges);
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh->CDDoutput)
+      qh_fprintf(qh, fp, 9052, "%s | %s\nbegin\n    %d %d real\n", qh->rbox_command,
+            qh->qhull_command, numfacets, qh->hull_dim+1);
+    else
+      qh_fprintf(qh, fp, 9053, "%d\n%d\n", qh->hull_dim+1, numfacets);
+    break;
+  case qh_PRINTmathematica:
+  case qh_PRINTmaple:
+    if (qh->hull_dim > 3)  /* qh_initbuffers also checks */
+      goto LABELnoformat;
+    if (qh->VORONOI)
+      qh_fprintf(qh, qh->ferr, 7054, "qhull warning: output is the Delaunay triangulation\n");
+    if (format == qh_PRINTmaple) {
+      if (qh->hull_dim == 2)
+        qh_fprintf(qh, fp, 9054, "PLOT(CURVES(\n");
+      else
+        qh_fprintf(qh, fp, 9055, "PLOT3D(POLYGONS(\n");
+    }else
+      qh_fprintf(qh, fp, 9056, "{\n");
+    qh->printoutvar= 0;   /* counts number of facets for notfirst */
+    break;
+  case qh_PRINTmerges:
+    qh_fprintf(qh, fp, 9057, "%d\n", numfacets);
+    break;
+  case qh_PRINTpointintersect:
+    qh_fprintf(qh, fp, 9058, "%d\n%d\n", qh->hull_dim, numfacets);
+    break;
+  case qh_PRINTneighbors:
+    qh_fprintf(qh, fp, 9059, "%d\n", numfacets);
+    break;
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh->VORONOI)
+      goto LABELnoformat;
+    num= qh->hull_dim;
+    if (format == qh_PRINToff || qh->hull_dim == 2)
+      qh_fprintf(qh, fp, 9060, "%d\n%d %d %d\n", num,
+        qh->num_points+qh_setsize(qh, qh->other_points), numfacets, totneighbors/2);
+    else { /* qh_PRINTtriangles */
+      qh->printoutvar= qh->num_points+qh_setsize(qh, qh->other_points); /* first centrum */
+      if (qh->DELAUNAY)
+        num--;  /* drop last dimension */
+      qh_fprintf(qh, fp, 9061, "%d\n%d %d %d\n", num, qh->printoutvar
+        + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
+    }
+    FORALLpoints
+      qh_printpointid(qh, qh->fout, NULL, num, point, qh_IDunknown);
+    FOREACHpoint_(qh->other_points)
+      qh_printpointid(qh, qh->fout, NULL, num, point, qh_IDunknown);
+    if (format == qh_PRINTtriangles && qh->hull_dim > 2) {
+      FORALLfacets {
+        if (!facet->simplicial && facet->visitid)
+          qh_printcenter(qh, qh->fout, format, NULL, facet);
+      }
+    }
+    break;
+  case qh_PRINTpointnearest:
+    qh_fprintf(qh, fp, 9062, "%d\n", numcoplanars);
+    break;
+  case qh_PRINTpoints:
+    if (!qh->VORONOI)
+      goto LABELnoformat;
+    if (qh->CDDoutput)
+      qh_fprintf(qh, fp, 9063, "%s | %s\nbegin\n%d %d real\n", qh->rbox_command,
+           qh->qhull_command, numfacets, qh->hull_dim);
+    else
+      qh_fprintf(qh, fp, 9064, "%d\n%d\n", qh->hull_dim-1, numfacets);
+    break;
+  case qh_PRINTvertices:
+    qh_fprintf(qh, fp, 9065, "%d\n", numfacets);
+    break;
+  case qh_PRINTsummary:
+  default:
+  LABELnoformat:
+    qh_fprintf(qh, qh->ferr, 6068, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
+         qh->hull_dim);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+} /* printbegin */
+
+/*---------------------------------
+
+  qh_printcenter(qh, fp, string, facet )
+    print facet->center as centrum or Voronoi center
+    string may be NULL.  Don't include '%' codes.
+    nop if qh->CENTERtype neither CENTERvoronoi nor CENTERcentrum
+    if upper envelope of Delaunay triangulation and point at-infinity
+      prints qh_INFINITE instead;
+
+  notes:
+    defines facet->center if needed
+    if format=PRINTgeom, adds a 0 if would otherwise be 2-d
+    Same as QhullFacet::printCenter
+*/
+void qh_printcenter(qhT *qh, FILE *fp, qh_PRINT format, const char *string, facetT *facet) {
+  int k, num;
+
+  if (qh->CENTERtype != qh_ASvoronoi && qh->CENTERtype != qh_AScentrum)
+    return;
+  if (string)
+    qh_fprintf(qh, fp, 9066, "%s", string);
+  if (qh->CENTERtype == qh_ASvoronoi) {
+    num= qh->hull_dim-1;
+    if (!facet->normal || !facet->upperdelaunay || !qh->ATinfinity) {
+      if (!facet->center)
+        facet->center= qh_facetcenter(qh, facet->vertices);
+      for (k=0; k < num; k++)
+        qh_fprintf(qh, fp, 9067, qh_REAL_1, facet->center[k]);
+    }else {
+      for (k=0; k < num; k++)
+        qh_fprintf(qh, fp, 9068, qh_REAL_1, qh_INFINITE);
+    }
+  }else /* qh.CENTERtype == qh_AScentrum */ {
+    num= qh->hull_dim;
+    if (format == qh_PRINTtriangles && qh->DELAUNAY)
+      num--;
+    if (!facet->center)
+      facet->center= qh_getcentrum(qh, facet);
+    for (k=0; k < num; k++)
+      qh_fprintf(qh, fp, 9069, qh_REAL_1, facet->center[k]);
+  }
+  if (format == qh_PRINTgeom && num == 2)
+    qh_fprintf(qh, fp, 9070, " 0\n");
+  else
+    qh_fprintf(qh, fp, 9071, "\n");
+} /* printcenter */
+
+/*---------------------------------
+
+  qh_printcentrum(qh, fp, facet, radius )
+    print centrum for a facet in OOGL format
+    radius defines size of centrum
+    2-d or 3-d only
+
+  returns:
+    defines facet->center if needed
+*/
+void qh_printcentrum(qhT *qh, FILE *fp, facetT *facet, realT radius) {
+  pointT *centrum, *projpt;
+  boolT tempcentrum= False;
+  realT xaxis[4], yaxis[4], normal[4], dist;
+  realT green[3]={0, 1, 0};
+  vertexT *apex;
+  int k;
+
+  if (qh->CENTERtype == qh_AScentrum) {
+    if (!facet->center)
+      facet->center= qh_getcentrum(qh, facet);
+    centrum= facet->center;
+  }else {
+    centrum= qh_getcentrum(qh, facet);
+    tempcentrum= True;
+  }
+  qh_fprintf(qh, fp, 9072, "{appearance {-normal -edge normscale 0} ");
+  if (qh->firstcentrum) {
+    qh->firstcentrum= False;
+    qh_fprintf(qh, fp, 9073, "{INST geom { define centrum CQUAD  # f%d\n\
+-0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3  0.3 0.0001     0 0 1 1\n\
+-0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
+  }else
+    qh_fprintf(qh, fp, 9074, "{INST geom { : centrum } transform { # f%d\n", facet->id);
+  apex= SETfirstt_(facet->vertices, vertexT);
+  qh_distplane(qh, apex->point, facet, &dist);
+  projpt= qh_projectpoint(qh, apex->point, facet, dist);
+  for (k=qh->hull_dim; k--; ) {
+    xaxis[k]= projpt[k] - centrum[k];
+    normal[k]= facet->normal[k];
+  }
+  if (qh->hull_dim == 2) {
+    xaxis[2]= 0;
+    normal[2]= 0;
+  }else if (qh->hull_dim == 4) {
+    qh_projectdim3(qh, xaxis, xaxis);
+    qh_projectdim3(qh, normal, normal);
+    qh_normalize2(qh, normal, qh->PRINTdim, True, NULL, NULL);
+  }
+  qh_crossproduct(3, xaxis, normal, yaxis);
+  qh_fprintf(qh, fp, 9075, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
+  qh_fprintf(qh, fp, 9076, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
+  qh_fprintf(qh, fp, 9077, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
+  qh_printpoint3(qh, fp, centrum);
+  qh_fprintf(qh, fp, 9078, "1 }}}\n");
+  qh_memfree(qh, projpt, qh->normal_size);
+  qh_printpointvect(qh, fp, centrum, facet->normal, NULL, radius, green);
+  if (tempcentrum)
+    qh_memfree(qh, centrum, qh->normal_size);
+} /* printcentrum */
+
+/*---------------------------------
+
+  qh_printend(qh, fp, format )
+    prints trailer for all output formats
+
+  see:
+    qh_printbegin() and qh_printafacet()
+
+*/
+void qh_printend(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int num;
+  facetT *facet, **facetp;
+
+  if (!qh->printoutnum)
+    qh_fprintf(qh, qh->ferr, 7055, "qhull warning: no facets printed\n");
+  switch (format) {
+  case qh_PRINTgeom:
+    if (qh->hull_dim == 4 && qh->DROPdim < 0  && !qh->PRINTnoplanes) {
+      qh->visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)
+        qh_printend4geom(qh, fp, facet,&num, printall);
+      FOREACHfacet_(facets)
+        qh_printend4geom(qh, fp, facet, &num, printall);
+      if (num != qh->ridgeoutnum || qh->printoutvar != qh->ridgeoutnum) {
+        qh_fprintf(qh, qh->ferr, 6069, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh->ridgeoutnum, qh->printoutvar, num);
+        qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+      }
+    }else
+      qh_fprintf(qh, fp, 9079, "}\n");
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh->CDDoutput)
+      qh_fprintf(qh, fp, 9080, "end\n");
+    break;
+  case qh_PRINTmaple:
+    qh_fprintf(qh, fp, 9081, "));\n");
+    break;
+  case qh_PRINTmathematica:
+    qh_fprintf(qh, fp, 9082, "}\n");
+    break;
+  case qh_PRINTpoints:
+    if (qh->CDDoutput)
+      qh_fprintf(qh, fp, 9083, "end\n");
+    break;
+  default:
+    break;
+  }
+} /* printend */
+
+/*---------------------------------
+
+  qh_printend4geom(qh, fp, facet, numridges, printall )
+    helper function for qh_printbegin/printend
+
+  returns:
+    number of printed ridges
+
+  notes:
+    just counts printed ridges if fp=NULL
+    uses facet->visitid
+    must agree with qh_printfacet4geom...
+
+  design:
+    computes color for facet from its normal
+    prints each ridge of facet
+*/
+void qh_printend4geom(qhT *qh, FILE *fp, facetT *facet, int *nump, boolT printall) {
+  realT color[3];
+  int i, num= *nump;
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+
+  if (!printall && qh_skipfacet(qh, facet))
+    return;
+  if (qh->PRINTnoplanes || (facet->visible && qh->NEWfacets))
+    return;
+  if (!facet->normal)
+    return;
+  if (fp) {
+    for (i=0; i < 3; i++) {
+      color[i]= (facet->normal[i]+1.0)/2.0;
+      maximize_(color[i], -1.0);
+      minimize_(color[i], +1.0);
+    }
+  }
+  facet->visitid= qh->visit_id;
+  if (facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh->visit_id) {
+        if (fp)
+          qh_fprintf(qh, fp, 9084, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
+                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+                 facet->id, neighbor->id);
+        num++;
+      }
+    }
+  }else {
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh->visit_id) {
+        if (fp)
+          qh_fprintf(qh, fp, 9085, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
+                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+                 ridge->id, facet->id, neighbor->id);
+        num++;
+      }
+    }
+  }
+  *nump= num;
+} /* printend4geom */
+
+/*---------------------------------
+
+  qh_printextremes(qh, fp, facetlist, facets, printall )
+    print extreme points for convex hulls or halfspace intersections
+
+  notes:
+    #points, followed by ids, one per line
+
+    sorted by id
+    same order as qh_printpoints_out if no coplanar/interior points
+*/
+void qh_printextremes(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices, *points;
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int id;
+  int numpoints=0, point_i, point_n;
+  int allpoints= qh->num_points + qh_setsize(qh, qh->other_points);
+
+  points= qh_settemp(qh, allpoints);
+  qh_setzero(qh, points, 0, allpoints);
+  vertices= qh_facetvertices(qh, facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid(qh, vertex->point);
+    if (id >= 0) {
+      SETelem_(points, id)= vertex->point;
+      numpoints++;
+    }
+  }
+  qh_settempfree(qh, &vertices);
+  qh_fprintf(qh, fp, 9086, "%d\n", numpoints);
+  FOREACHpoint_i_(qh, points) {
+    if (point)
+      qh_fprintf(qh, fp, 9087, "%d\n", point_i);
+  }
+  qh_settempfree(qh, &points);
+} /* printextremes */
+
+/*---------------------------------
+
+  qh_printextremes_2d(qh, fp, facetlist, facets, printall )
+    prints point ids for facets in qh_ORIENTclock order
+
+  notes:
+    #points, followed by ids, one per line
+    if facetlist/facets are disjoint than the output includes skips
+    errors if facets form a loop
+    does not print coplanar points
+*/
+void qh_printextremes_2d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
+  setT *vertices;
+  facetT *facet, *startfacet, *nextfacet;
+  vertexT *vertexA, *vertexB;
+
+  qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh->visit_id */
+  vertices= qh_facetvertices(qh, facetlist, facets, printall);
+  qh_fprintf(qh, fp, 9088, "%d\n", qh_setsize(qh, vertices));
+  qh_settempfree(qh, &vertices);
+  if (!numfacets)
+    return;
+  facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
+  qh->vertex_visit++;
+  qh->visit_id++;
+  do {
+    if (facet->toporient ^ qh_ORIENTclock) {
+      vertexA= SETfirstt_(facet->vertices, vertexT);
+      vertexB= SETsecondt_(facet->vertices, vertexT);
+      nextfacet= SETfirstt_(facet->neighbors, facetT);
+    }else {
+      vertexA= SETsecondt_(facet->vertices, vertexT);
+      vertexB= SETfirstt_(facet->vertices, vertexT);
+      nextfacet= SETsecondt_(facet->neighbors, facetT);
+    }
+    if (facet->visitid == qh->visit_id) {
+      qh_fprintf(qh, qh->ferr, 6218, "qhull internal error (qh_printextremes_2d): loop in facet list.  facet %d nextfacet %d\n",
+                 facet->id, nextfacet->id);
+      qh_errexit2(qh, qh_ERRqhull, facet, nextfacet);
+    }
+    if (facet->visitid) {
+      if (vertexA->visitid != qh->vertex_visit) {
+        vertexA->visitid= qh->vertex_visit;
+        qh_fprintf(qh, fp, 9089, "%d\n", qh_pointid(qh, vertexA->point));
+      }
+      if (vertexB->visitid != qh->vertex_visit) {
+        vertexB->visitid= qh->vertex_visit;
+        qh_fprintf(qh, fp, 9090, "%d\n", qh_pointid(qh, vertexB->point));
+      }
+    }
+    facet->visitid= qh->visit_id;
+    facet= nextfacet;
+  }while (facet && facet != startfacet);
+} /* printextremes_2d */
+
+/*---------------------------------
+
+  qh_printextremes_d(qh, fp, facetlist, facets, printall )
+    print extreme points of input sites for Delaunay triangulations
+
+  notes:
+    #points, followed by ids, one per line
+
+    unordered
+*/
+void qh_printextremes_d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices;
+  vertexT *vertex, **vertexp;
+  boolT upperseen, lowerseen;
+  facetT *neighbor, **neighborp;
+  int numpoints=0;
+
+  vertices= qh_facetvertices(qh, facetlist, facets, printall);
+  qh_vertexneighbors(qh);
+  FOREACHvertex_(vertices) {
+    upperseen= lowerseen= False;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay)
+        upperseen= True;
+      else
+        lowerseen= True;
+    }
+    if (upperseen && lowerseen) {
+      vertex->seen= True;
+      numpoints++;
+    }else
+      vertex->seen= False;
+  }
+  qh_fprintf(qh, fp, 9091, "%d\n", numpoints);
+  FOREACHvertex_(vertices) {
+    if (vertex->seen)
+      qh_fprintf(qh, fp, 9092, "%d\n", qh_pointid(qh, vertex->point));
+  }
+  qh_settempfree(qh, &vertices);
+} /* printextremes_d */
+
+/*---------------------------------
+
+  qh_printfacet(qh, fp, facet )
+    prints all fields of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+*/
+void qh_printfacet(qhT *qh, FILE *fp, facetT *facet) {
+
+  qh_printfacetheader(qh, fp, facet);
+  if (facet->ridges)
+    qh_printfacetridges(qh, fp, facet);
+} /* printfacet */
+
+
+/*---------------------------------
+
+  qh_printfacet2geom(qh, fp, facet, color )
+    print facet as part of a 2-d VECT for Geomview
+
+    notes:
+      assume precise calculations in io_r.c with roundoff covered by qh_GEOMepsilon
+      mindist is calculated within io_r.c.  maxoutside is calculated elsewhere
+      so a DISTround error may have occurred.
+*/
+void qh_printfacet2geom(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
+  pointT *point0, *point1;
+  realT mindist, innerplane, outerplane;
+  int k;
+
+  qh_facet2point(qh, facet, &point0, &point1, &mindist);
+  qh_geomplanes(qh, facet, &outerplane, &innerplane);
+  if (qh->PRINTouter || (!qh->PRINTnoplanes && !qh->PRINTinner))
+    qh_printfacet2geom_points(qh, fp, point0, point1, facet, outerplane, color);
+  if (qh->PRINTinner || (!qh->PRINTnoplanes && !qh->PRINTouter &&
+                outerplane - innerplane > 2 * qh->MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet2geom_points(qh, fp, point0, point1, facet, innerplane, color);
+  }
+  qh_memfree(qh, point1, qh->normal_size);
+  qh_memfree(qh, point0, qh->normal_size);
+} /* printfacet2geom */
+
+/*---------------------------------
+
+  qh_printfacet2geom_points(qh, fp, point1, point2, facet, offset, color )
+    prints a 2-d facet as a VECT with 2 points at some offset.
+    The points are on the facet's plane.
+*/
+void qh_printfacet2geom_points(qhT *qh, FILE *fp, pointT *point1, pointT *point2,
+                               facetT *facet, realT offset, realT color[3]) {
+  pointT *p1= point1, *p2= point2;
+
+  qh_fprintf(qh, fp, 9093, "VECT 1 2 1 2 1 # f%d\n", facet->id);
+  if (offset != 0.0) {
+    p1= qh_projectpoint(qh, p1, facet, -offset);
+    p2= qh_projectpoint(qh, p2, facet, -offset);
+  }
+  qh_fprintf(qh, fp, 9094, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
+           p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
+  if (offset != 0.0) {
+    qh_memfree(qh, p1, qh->normal_size);
+    qh_memfree(qh, p2, qh->normal_size);
+  }
+  qh_fprintf(qh, fp, 9095, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printfacet2geom_points */
+
+
+/*---------------------------------
+
+  qh_printfacet2math(qh, fp, facet, format, notfirst )
+    print 2-d Maple or Mathematica output for a facet
+    may be non-simplicial
+
+  notes:
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet3math
+*/
+void qh_printfacet2math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
+  pointT *point0, *point1;
+  realT mindist;
+  const char *pointfmt;
+
+  qh_facet2point(qh, facet, &point0, &point1, &mindist);
+  if (notfirst)
+    qh_fprintf(qh, fp, 9096, ",");
+  if (format == qh_PRINTmaple)
+    pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
+  else
+    pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
+  qh_fprintf(qh, fp, 9097, pointfmt, point0[0], point0[1], point1[0], point1[1]);
+  qh_memfree(qh, point1, qh->normal_size);
+  qh_memfree(qh, point0, qh->normal_size);
+} /* printfacet2math */
+
+
+/*---------------------------------
+
+  qh_printfacet3geom_nonsimplicial(qh, fp, facet, color )
+    print Geomview OFF for a 3-d nonsimplicial facet.
+    if DOintersections, prints ridges to unvisited neighbors(qh->visit_id)
+
+  notes
+    uses facet->visitid for intersections and ridges
+*/
+void qh_printfacet3geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
+  ridgeT *ridge, **ridgep;
+  setT *projectedpoints, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  pointT *projpt, *point, **pointp;
+  facetT *neighbor;
+  realT dist, outerplane, innerplane;
+  int cntvertices, k;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+
+  qh_geomplanes(qh, facet, &outerplane, &innerplane);
+  vertices= qh_facet3vertex(qh, facet); /* oriented */
+  cntvertices= qh_setsize(qh, vertices);
+  projectedpoints= qh_settemp(qh, cntvertices);
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(qh, vertex->point, facet, &dist);
+    projpt= qh_projectpoint(qh, vertex->point, facet, dist);
+    qh_setappend(qh, &projectedpoints, projpt);
+  }
+  if (qh->PRINTouter || (!qh->PRINTnoplanes && !qh->PRINTinner))
+    qh_printfacet3geom_points(qh, fp, projectedpoints, facet, outerplane, color);
+  if (qh->PRINTinner || (!qh->PRINTnoplanes && !qh->PRINTouter &&
+                outerplane - innerplane > 2 * qh->MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(qh, fp, projectedpoints, facet, innerplane, color);
+  }
+  FOREACHpoint_(projectedpoints)
+    qh_memfree(qh, point, qh->normal_size);
+  qh_settempfree(qh, &projectedpoints);
+  qh_settempfree(qh, &vertices);
+  if ((qh->DOintersections || qh->PRINTridges)
+  && (!facet->visible || !qh->NEWfacets)) {
+    facet->visitid= qh->visit_id;
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh->visit_id) {
+        if (qh->DOintersections)
+          qh_printhyperplaneintersection(qh, fp, facet, neighbor, ridge->vertices, black);
+        if (qh->PRINTridges) {
+          vertexA= SETfirstt_(ridge->vertices, vertexT);
+          vertexB= SETsecondt_(ridge->vertices, vertexT);
+          qh_printline3geom(qh, fp, vertexA->point, vertexB->point, green);
+        }
+      }
+    }
+  }
+} /* printfacet3geom_nonsimplicial */
+
+/*---------------------------------
+
+  qh_printfacet3geom_points(qh, fp, points, facet, offset )
+    prints a 3-d facet as OFF Geomview object.
+    offset is relative to the facet's hyperplane
+    Facet is determined as a list of points
+*/
+void qh_printfacet3geom_points(qhT *qh, FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
+  int k, n= qh_setsize(qh, points), i;
+  pointT *point, **pointp;
+  setT *printpoints;
+
+  qh_fprintf(qh, fp, 9098, "{ OFF %d 1 1 # f%d\n", n, facet->id);
+  if (offset != 0.0) {
+    printpoints= qh_settemp(qh, n);
+    FOREACHpoint_(points)
+      qh_setappend(qh, &printpoints, qh_projectpoint(qh, point, facet, -offset));
+  }else
+    printpoints= points;
+  FOREACHpoint_(printpoints) {
+    for (k=0; k < qh->hull_dim; k++) {
+      if (k == qh->DROPdim)
+        qh_fprintf(qh, fp, 9099, "0 ");
+      else
+        qh_fprintf(qh, fp, 9100, "%8.4g ", point[k]);
+    }
+    if (printpoints != points)
+      qh_memfree(qh, point, qh->normal_size);
+    qh_fprintf(qh, fp, 9101, "\n");
+  }
+  if (printpoints != points)
+    qh_settempfree(qh, &printpoints);
+  qh_fprintf(qh, fp, 9102, "%d ", n);
+  for (i=0; i < n; i++)
+    qh_fprintf(qh, fp, 9103, "%d ", i);
+  qh_fprintf(qh, fp, 9104, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
+} /* printfacet3geom_points */
+
+
+/*---------------------------------
+
+  qh_printfacet3geom_simplicial(qh )
+    print Geomview OFF for a 3-d simplicial facet.
+
+  notes:
+    may flip color
+    uses facet->visitid for intersections and ridges
+
+    assume precise calculations in io_r.c with roundoff covered by qh_GEOMepsilon
+    innerplane may be off by qh->DISTround.  Maxoutside is calculated elsewhere
+    so a DISTround error may have occurred.
+*/
+void qh_printfacet3geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
+  setT *points, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  facetT *neighbor, **neighborp;
+  realT outerplane, innerplane;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+  int k;
+
+  qh_geomplanes(qh, facet, &outerplane, &innerplane);
+  vertices= qh_facet3vertex(qh, facet);
+  points= qh_settemp(qh, qh->TEMPsize);
+  FOREACHvertex_(vertices)
+    qh_setappend(qh, &points, vertex->point);
+  if (qh->PRINTouter || (!qh->PRINTnoplanes && !qh->PRINTinner))
+    qh_printfacet3geom_points(qh, fp, points, facet, outerplane, color);
+  if (qh->PRINTinner || (!qh->PRINTnoplanes && !qh->PRINTouter &&
+              outerplane - innerplane > 2 * qh->MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(qh, fp, points, facet, innerplane, color);
+  }
+  qh_settempfree(qh, &points);
+  qh_settempfree(qh, &vertices);
+  if ((qh->DOintersections || qh->PRINTridges)
+  && (!facet->visible || !qh->NEWfacets)) {
+    facet->visitid= qh->visit_id;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh->visit_id) {
+        vertices= qh_setnew_delnthsorted(qh, facet->vertices, qh->hull_dim,
+                          SETindex_(facet->neighbors, neighbor), 0);
+        if (qh->DOintersections)
+           qh_printhyperplaneintersection(qh, fp, facet, neighbor, vertices, black);
+        if (qh->PRINTridges) {
+          vertexA= SETfirstt_(vertices, vertexT);
+          vertexB= SETsecondt_(vertices, vertexT);
+          qh_printline3geom(qh, fp, vertexA->point, vertexB->point, green);
+        }
+        qh_setfree(qh, &vertices);
+      }
+    }
+  }
+} /* printfacet3geom_simplicial */
+
+/*---------------------------------
+
+  qh_printfacet3math(qh, fp, facet, notfirst )
+    print 3-d Maple or Mathematica output for a facet
+
+  notes:
+    may be non-simplicial
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet2math
+*/
+void qh_printfacet3math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
+  vertexT *vertex, **vertexp;
+  setT *points, *vertices;
+  pointT *point, **pointp;
+  boolT firstpoint= True;
+  realT dist;
+  const char *pointfmt, *endfmt;
+
+  if (notfirst)
+    qh_fprintf(qh, fp, 9105, ",\n");
+  vertices= qh_facet3vertex(qh, facet);
+  points= qh_settemp(qh, qh_setsize(qh, vertices));
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(qh, vertex->point, facet, &dist);
+    point= qh_projectpoint(qh, vertex->point, facet, dist);
+    qh_setappend(qh, &points, point);
+  }
+  if (format == qh_PRINTmaple) {
+    qh_fprintf(qh, fp, 9106, "[");
+    pointfmt= "[%16.8f, %16.8f, %16.8f]";
+    endfmt= "]";
+  }else {
+    qh_fprintf(qh, fp, 9107, "Polygon[{");
+    pointfmt= "{%16.8f, %16.8f, %16.8f}";
+    endfmt= "}]";
+  }
+  FOREACHpoint_(points) {
+    if (firstpoint)
+      firstpoint= False;
+    else
+      qh_fprintf(qh, fp, 9108, ",\n");
+    qh_fprintf(qh, fp, 9109, pointfmt, point[0], point[1], point[2]);
+  }
+  FOREACHpoint_(points)
+    qh_memfree(qh, point, qh->normal_size);
+  qh_settempfree(qh, &points);
+  qh_settempfree(qh, &vertices);
+  qh_fprintf(qh, fp, 9110, "%s", endfmt);
+} /* printfacet3math */
+
+
+/*---------------------------------
+
+  qh_printfacet3vertex(qh, fp, facet, format )
+    print vertices in a 3-d facet as point ids
+
+  notes:
+    prints number of vertices first if format == qh_PRINToff
+    the facet may be non-simplicial
+*/
+void qh_printfacet3vertex(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+
+  vertices= qh_facet3vertex(qh, facet);
+  if (format == qh_PRINToff)
+    qh_fprintf(qh, fp, 9111, "%d ", qh_setsize(qh, vertices));
+  FOREACHvertex_(vertices)
+    qh_fprintf(qh, fp, 9112, "%d ", qh_pointid(qh, vertex->point));
+  qh_fprintf(qh, fp, 9113, "\n");
+  qh_settempfree(qh, &vertices);
+} /* printfacet3vertex */
+
+
+/*---------------------------------
+
+  qh_printfacet4geom_nonsimplicial(qh )
+    print Geomview 4OFF file for a 4d nonsimplicial facet
+    prints all ridges to unvisited neighbors (qh.visit_id)
+    if qh.DROPdim
+      prints in OFF format
+
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
+  facetT *neighbor;
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+  pointT *point;
+  int k;
+  realT dist;
+
+  facet->visitid= qh->visit_id;
+  if (qh->PRINTnoplanes || (facet->visible && qh->NEWfacets))
+    return;
+  FOREACHridge_(facet->ridges) {
+    neighbor= otherfacet_(ridge, facet);
+    if (neighbor->visitid == qh->visit_id)
+      continue;
+    if (qh->PRINTtransparent && !neighbor->good)
+      continue;
+    if (qh->DOintersections)
+      qh_printhyperplaneintersection(qh, fp, facet, neighbor, ridge->vertices, color);
+    else {
+      if (qh->DROPdim >= 0)
+        qh_fprintf(qh, fp, 9114, "OFF 3 1 1 # f%d\n", facet->id);
+      else {
+        qh->printoutvar++;
+        qh_fprintf(qh, fp, 9115, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
+      }
+      FOREACHvertex_(ridge->vertices) {
+        zinc_(Zdistio);
+        qh_distplane(qh, vertex->point,facet, &dist);
+        point=qh_projectpoint(qh, vertex->point,facet, dist);
+        for (k=0; k < qh->hull_dim; k++) {
+          if (k != qh->DROPdim)
+            qh_fprintf(qh, fp, 9116, "%8.4g ", point[k]);
+        }
+        qh_fprintf(qh, fp, 9117, "\n");
+        qh_memfree(qh, point, qh->normal_size);
+      }
+      if (qh->DROPdim >= 0)
+        qh_fprintf(qh, fp, 9118, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+  }
+} /* printfacet4geom_nonsimplicial */
+
+
+/*---------------------------------
+
+  qh_printfacet4geom_simplicial(qh, fp, facet, color )
+    print Geomview 4OFF file for a 4d simplicial facet
+    prints triangles for unvisited neighbors (qh.visit_id)
+
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
+  setT *vertices;
+  facetT *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  int k;
+
+  facet->visitid= qh->visit_id;
+  if (qh->PRINTnoplanes || (facet->visible && qh->NEWfacets))
+    return;
+  FOREACHneighbor_(facet) {
+    if (neighbor->visitid == qh->visit_id)
+      continue;
+    if (qh->PRINTtransparent && !neighbor->good)
+      continue;
+    vertices= qh_setnew_delnthsorted(qh, facet->vertices, qh->hull_dim,
+                          SETindex_(facet->neighbors, neighbor), 0);
+    if (qh->DOintersections)
+      qh_printhyperplaneintersection(qh, fp, facet, neighbor, vertices, color);
+    else {
+      if (qh->DROPdim >= 0)
+        qh_fprintf(qh, fp, 9119, "OFF 3 1 1 # ridge between f%d f%d\n",
+                facet->id, neighbor->id);
+      else {
+        qh->printoutvar++;
+        qh_fprintf(qh, fp, 9120, "# ridge between f%d f%d\n", facet->id, neighbor->id);
+      }
+      FOREACHvertex_(vertices) {
+        for (k=0; k < qh->hull_dim; k++) {
+          if (k != qh->DROPdim)
+            qh_fprintf(qh, fp, 9121, "%8.4g ", vertex->point[k]);
+        }
+        qh_fprintf(qh, fp, 9122, "\n");
+      }
+      if (qh->DROPdim >= 0)
+        qh_fprintf(qh, fp, 9123, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+    qh_setfree(qh, &vertices);
+  }
+} /* printfacet4geom_simplicial */
+
+
+/*---------------------------------
+
+  qh_printfacetNvertex_nonsimplicial(qh, fp, facet, id, format )
+    print vertices for an N-d non-simplicial facet
+    triangulates each ridge to the id
+*/
+void qh_printfacetNvertex_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, int id, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->visible && qh->NEWfacets)
+    return;
+  FOREACHridge_(facet->ridges) {
+    if (format == qh_PRINTtriangles)
+      qh_fprintf(qh, fp, 9124, "%d ", qh->hull_dim);
+    qh_fprintf(qh, fp, 9125, "%d ", id);
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      FOREACHvertex_(ridge->vertices)
+        qh_fprintf(qh, fp, 9126, "%d ", qh_pointid(qh, vertex->point));
+    }else {
+      FOREACHvertexreverse12_(ridge->vertices)
+        qh_fprintf(qh, fp, 9127, "%d ", qh_pointid(qh, vertex->point));
+    }
+    qh_fprintf(qh, fp, 9128, "\n");
+  }
+} /* printfacetNvertex_nonsimplicial */
+
+
+/*---------------------------------
+
+  qh_printfacetNvertex_simplicial(qh, fp, facet, format )
+    print vertices for an N-d simplicial facet
+    prints vertices for non-simplicial facets
+      2-d facets (orientation preserved by qh_mergefacet2d)
+      PRINToff ('o') for 4-d and higher
+*/
+void qh_printfacetNvertex_simplicial(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+
+  if (format == qh_PRINToff || format == qh_PRINTtriangles)
+    qh_fprintf(qh, fp, 9129, "%d ", qh_setsize(qh, facet->vertices));
+  if ((facet->toporient ^ qh_ORIENTclock)
+  || (qh->hull_dim > 2 && !facet->simplicial)) {
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(qh, fp, 9130, "%d ", qh_pointid(qh, vertex->point));
+  }else {
+    FOREACHvertexreverse12_(facet->vertices)
+      qh_fprintf(qh, fp, 9131, "%d ", qh_pointid(qh, vertex->point));
+  }
+  qh_fprintf(qh, fp, 9132, "\n");
+} /* printfacetNvertex_simplicial */
+
+
+/*---------------------------------
+
+  qh_printfacetheader(qh, fp, facet )
+    prints header fields of a facet to fp
+
+  notes:
+    for 'f' output and debugging
+    Same as QhullFacet::printHeader()
+*/
+void qh_printfacetheader(qhT *qh, FILE *fp, facetT *facet) {
+  pointT *point, **pointp, *furthest;
+  facetT *neighbor, **neighborp;
+  realT dist;
+
+  if (facet == qh_MERGEridge) {
+    qh_fprintf(qh, fp, 9133, " MERGEridge\n");
+    return;
+  }else if (facet == qh_DUPLICATEridge) {
+    qh_fprintf(qh, fp, 9134, " DUPLICATEridge\n");
+    return;
+  }else if (!facet) {
+    qh_fprintf(qh, fp, 9135, " NULLfacet\n");
+    return;
+  }
+  qh->old_randomdist= qh->RANDOMdist;
+  qh->RANDOMdist= False;
+  qh_fprintf(qh, fp, 9136, "- f%d\n", facet->id);
+  qh_fprintf(qh, fp, 9137, "    - flags:");
+  if (facet->toporient)
+    qh_fprintf(qh, fp, 9138, " top");
+  else
+    qh_fprintf(qh, fp, 9139, " bottom");
+  if (facet->simplicial)
+    qh_fprintf(qh, fp, 9140, " simplicial");
+  if (facet->tricoplanar)
+    qh_fprintf(qh, fp, 9141, " tricoplanar");
+  if (facet->upperdelaunay)
+    qh_fprintf(qh, fp, 9142, " upperDelaunay");
+  if (facet->visible)
+    qh_fprintf(qh, fp, 9143, " visible");
+  if (facet->newfacet)
+    qh_fprintf(qh, fp, 9144, " newfacet");
+  if (facet->tested)
+    qh_fprintf(qh, fp, 9145, " tested");
+  if (!facet->good)
+    qh_fprintf(qh, fp, 9146, " notG");
+  if (facet->seen && qh->IStracing)
+    qh_fprintf(qh, fp, 9147, " seen");
+  if (facet->seen2 && qh->IStracing)
+    qh_fprintf(qh, fp, 9418, " seen2");
+  if (facet->isarea)
+    qh_fprintf(qh, fp, 9419, " isarea");
+  if (facet->coplanarhorizon)
+    qh_fprintf(qh, fp, 9148, " coplanarhorizon");
+  if (facet->mergehorizon)
+    qh_fprintf(qh, fp, 9149, " mergehorizon");
+  if (facet->cycledone)
+    qh_fprintf(qh, fp, 9420, " cycledone");
+  if (facet->keepcentrum)
+    qh_fprintf(qh, fp, 9150, " keepcentrum");
+  if (facet->dupridge)
+    qh_fprintf(qh, fp, 9151, " dupridge");
+  if (facet->mergeridge && !facet->mergeridge2)
+    qh_fprintf(qh, fp, 9152, " mergeridge1");
+  if (facet->mergeridge2)
+    qh_fprintf(qh, fp, 9153, " mergeridge2");
+  if (facet->newmerge)
+    qh_fprintf(qh, fp, 9154, " newmerge");
+  if (facet->flipped)
+    qh_fprintf(qh, fp, 9155, " flipped");
+  if (facet->notfurthest)
+    qh_fprintf(qh, fp, 9156, " notfurthest");
+  if (facet->degenerate)
+    qh_fprintf(qh, fp, 9157, " degenerate");
+  if (facet->redundant)
+    qh_fprintf(qh, fp, 9158, " redundant");
+  qh_fprintf(qh, fp, 9159, "\n");
+  if (facet->isarea)
+    qh_fprintf(qh, fp, 9160, "    - area: %2.2g\n", facet->f.area);
+  else if (qh->NEWfacets && facet->visible && facet->f.replace)
+    qh_fprintf(qh, fp, 9161, "    - replacement: f%d\n", facet->f.replace->id);
+  else if (facet->newfacet) {
+    if (facet->f.samecycle && facet->f.samecycle != facet)
+      qh_fprintf(qh, fp, 9162, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
+  }else if (facet->tricoplanar /* !isarea */) {
+    if (facet->f.triowner)
+      qh_fprintf(qh, fp, 9163, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
+  }else if (facet->f.newcycle)
+    qh_fprintf(qh, fp, 9164, "    - was horizon to f%d\n", facet->f.newcycle->id);
+  if (facet->nummerge == qh_MAXnummerge)
+    qh_fprintf(qh, fp, 9427, "    - merges: %dmax\n", qh_MAXnummerge);
+  else if (facet->nummerge)
+    qh_fprintf(qh, fp, 9165, "    - merges: %d\n", facet->nummerge);
+  qh_printpointid(qh, fp, "    - normal: ", qh->hull_dim, facet->normal, qh_IDunknown);
+  qh_fprintf(qh, fp, 9166, "    - offset: %10.7g\n", facet->offset);
+  if (qh->CENTERtype == qh_ASvoronoi || facet->center)
+    qh_printcenter(qh, fp, qh_PRINTfacets, "    - center: ", facet);
+#if qh_MAXoutside
+  if (facet->maxoutside > qh->DISTround) /* initial value */
+    qh_fprintf(qh, fp, 9167, "    - maxoutside: %10.7g\n", facet->maxoutside);
+#endif
+  if (!SETempty_(facet->outsideset)) {
+    furthest= (pointT *)qh_setlast(facet->outsideset);
+    if (qh_setsize(qh, facet->outsideset) < 6) {
+      qh_fprintf(qh, fp, 9168, "    - outside set(furthest p%d):\n", qh_pointid(qh, furthest));
+      FOREACHpoint_(facet->outsideset)
+        qh_printpoint(qh, fp, "     ", point);
+    }else if (qh_setsize(qh, facet->outsideset) < 21) {
+      qh_printpoints(qh, fp, "    - outside set:", facet->outsideset);
+    }else {
+      qh_fprintf(qh, fp, 9169, "    - outside set:  %d points.", qh_setsize(qh, facet->outsideset));
+      qh_printpoint(qh, fp, "  Furthest", furthest);
+    }
+#if !qh_COMPUTEfurthest
+    qh_fprintf(qh, fp, 9170, "    - furthest distance= %2.2g\n", facet->furthestdist);
+#endif
+  }
+  if (!SETempty_(facet->coplanarset)) {
+    furthest= (pointT *)qh_setlast(facet->coplanarset);
+    if (qh_setsize(qh, facet->coplanarset) < 6) {
+      qh_fprintf(qh, fp, 9171, "    - coplanar set(furthest p%d):\n", qh_pointid(qh, furthest));
+      FOREACHpoint_(facet->coplanarset)
+        qh_printpoint(qh, fp, "     ", point);
+    }else if (qh_setsize(qh, facet->coplanarset) < 21) {
+      qh_printpoints(qh, fp, "    - coplanar set:", facet->coplanarset);
+    }else {
+      qh_fprintf(qh, fp, 9172, "    - coplanar set:  %d points.", qh_setsize(qh, facet->coplanarset));
+      qh_printpoint(qh, fp, "  Furthest", furthest);
+    }
+    zinc_(Zdistio);
+    qh_distplane(qh, furthest, facet, &dist);
+    qh_fprintf(qh, fp, 9173, "      furthest distance= %2.2g\n", dist);
+  }
+  qh_printvertices(qh, fp, "    - vertices:", facet->vertices);
+  qh_fprintf(qh, fp, 9174, "    - neighboring facets:");
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge)
+      qh_fprintf(qh, fp, 9175, " MERGEridge");
+    else if (neighbor == qh_DUPLICATEridge)
+      qh_fprintf(qh, fp, 9176, " DUPLICATEridge");
+    else
+      qh_fprintf(qh, fp, 9177, " f%d", neighbor->id);
+  }
+  qh_fprintf(qh, fp, 9178, "\n");
+  qh->RANDOMdist= qh->old_randomdist;
+} /* printfacetheader */
+
+
+/*---------------------------------
+
+  qh_printfacetridges(qh, fp, facet )
+    prints ridges of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+    assumes the ridges exist
+    for 'f' output
+    same as QhullFacet::printRidges
+*/
+void qh_printfacetridges(qhT *qh, FILE *fp, facetT *facet) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int numridges= 0;
+  int n;
+
+  if (facet->visible && qh->NEWfacets) {
+    qh_fprintf(qh, fp, 9179, "    - ridges (tentative ids):");
+    FOREACHridge_(facet->ridges)
+      qh_fprintf(qh, fp, 9180, " r%d", ridge->id);
+    qh_fprintf(qh, fp, 9181, "\n");
+  }else {
+    qh_fprintf(qh, fp, 9182, "    - ridges:\n");
+    FOREACHridge_(facet->ridges)
+      ridge->seen= False;
+    if (qh->hull_dim == 3) {
+      ridge= SETfirstt_(facet->ridges, ridgeT);
+      while (ridge && !ridge->seen) {
+        ridge->seen= True;
+        qh_printridge(qh, fp, ridge);
+        numridges++;
+        ridge= qh_nextridge3d(ridge, facet, NULL);
+        }
+    }else {
+      FOREACHneighbor_(facet) {
+        FOREACHridge_(facet->ridges) {
+          if (otherfacet_(ridge, facet) == neighbor && !ridge->seen) {
+            ridge->seen= True;
+            qh_printridge(qh, fp, ridge);
+            numridges++;
+          }
+        }
+      }
+    }
+    n= qh_setsize(qh, facet->ridges);
+    if (n == 1 && facet->newfacet && qh->NEWtentative) {
+      qh_fprintf(qh, fp, 9411, "     - horizon ridge to visible facet\n");
+    }
+    if (numridges != n) {
+      qh_fprintf(qh, fp, 9183, "     - all ridges:");
+      FOREACHridge_(facet->ridges)
+        qh_fprintf(qh, fp, 9184, " r%d", ridge->id);
+      qh_fprintf(qh, fp, 9185, "\n");
+    }
+    /* non-3d ridges w/o non-simplicial neighbors */
+    FOREACHridge_(facet->ridges) {
+      if (!ridge->seen)
+        qh_printridge(qh, fp, ridge);
+    }
+  }
+} /* printfacetridges */
+
+/*---------------------------------
+
+  qh_printfacets(qh, fp, format, facetlist, facets, printall )
+    prints facetlist and/or facet set in output format
+
+  notes:
+    also used for specialized formats ('FO' and summary)
+    turns off 'Rn' option since want actual numbers
+*/
+void qh_printfacets(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  facetT *facet, **facetp;
+  setT *vertices;
+  coordT *center;
+  realT outerplane, innerplane;
+
+  qh->old_randomdist= qh->RANDOMdist;
+  qh->RANDOMdist= False;
+  if (qh->CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
+    qh_fprintf(qh, qh->ferr, 7056, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
+  if (format == qh_PRINTnone)
+    ; /* print nothing */
+  else if (format == qh_PRINTaverage) {
+    vertices= qh_facetvertices(qh, facetlist, facets, printall);
+    center= qh_getcenter(qh, vertices);
+    qh_fprintf(qh, fp, 9186, "%d 1\n", qh->hull_dim);
+    qh_printpointid(qh, fp, NULL, qh->hull_dim, center, qh_IDunknown);
+    qh_memfree(qh, center, qh->normal_size);
+    qh_settempfree(qh, &vertices);
+  }else if (format == qh_PRINTextremes) {
+    if (qh->DELAUNAY)
+      qh_printextremes_d(qh, fp, facetlist, facets, printall);
+    else if (qh->hull_dim == 2)
+      qh_printextremes_2d(qh, fp, facetlist, facets, printall);
+    else
+      qh_printextremes(qh, fp, facetlist, facets, printall);
+  }else if (format == qh_PRINToptions)
+    qh_fprintf(qh, fp, 9187, "Options selected for Qhull %s:\n%s\n", qh_version, qh->qhull_options);
+  else if (format == qh_PRINTpoints && !qh->VORONOI)
+    qh_printpoints_out(qh, fp, facetlist, facets, printall);
+  else if (format == qh_PRINTqhull)
+    qh_fprintf(qh, fp, 9188, "%s | %s\n", qh->rbox_command, qh->qhull_command);
+  else if (format == qh_PRINTsize) {
+    qh_fprintf(qh, fp, 9189, "0\n2 ");
+    qh_fprintf(qh, fp, 9190, qh_REAL_1, qh->totarea);
+    qh_fprintf(qh, fp, 9191, qh_REAL_1, qh->totvol);
+    qh_fprintf(qh, fp, 9192, "\n");
+  }else if (format == qh_PRINTsummary) {
+    qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+    vertices= qh_facetvertices(qh, facetlist, facets, printall);
+    qh_fprintf(qh, fp, 9193, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh->hull_dim,
+                qh->num_points + qh_setsize(qh, qh->other_points),
+                qh->num_vertices, qh->num_facets - qh->num_visible,
+                qh_setsize(qh, vertices), numfacets, numcoplanars,
+                numfacets - numsimplicial, zzval_(Zdelvertextot),
+                numtricoplanars);
+    qh_settempfree(qh, &vertices);
+    qh_outerinner(qh, NULL, &outerplane, &innerplane);
+    qh_fprintf(qh, fp, 9194, qh_REAL_2n, outerplane, innerplane);
+  }else if (format == qh_PRINTvneighbors)
+    qh_printvneighbors(qh, fp, facetlist, facets, printall);
+  else if (qh->VORONOI && format == qh_PRINToff)
+    qh_printvoronoi(qh, fp, format, facetlist, facets, printall);
+  else if (qh->VORONOI && format == qh_PRINTgeom) {
+    qh_printbegin(qh, fp, format, facetlist, facets, printall);
+    qh_printvoronoi(qh, fp, format, facetlist, facets, printall);
+    qh_printend(qh, fp, format, facetlist, facets, printall);
+  }else if (qh->VORONOI
+  && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
+    qh_printvdiagram(qh, fp, format, facetlist, facets, printall);
+  else {
+    qh_printbegin(qh, fp, format, facetlist, facets, printall);
+    FORALLfacet_(facetlist)
+      qh_printafacet(qh, fp, format, facet, printall);
+    FOREACHfacet_(facets)
+      qh_printafacet(qh, fp, format, facet, printall);
+    qh_printend(qh, fp, format, facetlist, facets, printall);
+  }
+  qh->RANDOMdist= qh->old_randomdist;
+} /* printfacets */
+
+
+/*---------------------------------
+
+  qh_printhyperplaneintersection(qh, fp, facet1, facet2, vertices, color )
+    print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
+*/
+void qh_printhyperplaneintersection(qhT *qh, FILE *fp, facetT *facet1, facetT *facet2,
+                   setT *vertices, realT color[3]) {
+  realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
+  vertexT *vertex, **vertexp;
+  int i, k;
+  boolT nearzero1, nearzero2;
+
+  costheta= qh_getangle(qh, facet1->normal, facet2->normal);
+  denominator= 1 - costheta * costheta;
+  i= qh_setsize(qh, vertices);
+  if (qh->hull_dim == 3)
+    qh_fprintf(qh, fp, 9195, "VECT 1 %d 1 %d 1 ", i, i);
+  else if (qh->hull_dim == 4 && qh->DROPdim >= 0)
+    qh_fprintf(qh, fp, 9196, "OFF 3 1 1 ");
+  else
+    qh->printoutvar++;
+  qh_fprintf(qh, fp, 9197, "# intersect f%d f%d\n", facet1->id, facet2->id);
+  mindenom= 1 / (10.0 * qh->MAXabs_coord);
+  FOREACHvertex_(vertices) {
+    zadd_(Zdistio, 2);
+    qh_distplane(qh, vertex->point, facet1, &dist1);
+    qh_distplane(qh, vertex->point, facet2, &dist2);
+    s= qh_divzero(-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
+    t= qh_divzero(-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
+    if (nearzero1 || nearzero2)
+      s= t= 0.0;
+    for (k=qh->hull_dim; k--; )
+      p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
+    if (qh->PRINTdim <= 3) {
+      qh_projectdim3(qh, p, p);
+      qh_fprintf(qh, fp, 9198, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
+    }else
+      qh_fprintf(qh, fp, 9199, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
+    if (nearzero1+nearzero2)
+      qh_fprintf(qh, fp, 9200, "p%d(coplanar facets)\n", qh_pointid(qh, vertex->point));
+    else
+      qh_fprintf(qh, fp, 9201, "projected p%d\n", qh_pointid(qh, vertex->point));
+  }
+  if (qh->hull_dim == 3)
+    qh_fprintf(qh, fp, 9202, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+  else if (qh->hull_dim == 4 && qh->DROPdim >= 0)
+    qh_fprintf(qh, fp, 9203, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printhyperplaneintersection */
+
+/*---------------------------------
+
+  qh_printline3geom(qh, fp, pointA, pointB, color )
+    prints a line as a VECT
+    prints 0's for qh.DROPdim
+
+  notes:
+    if pointA == pointB,
+      it's a 1 point VECT
+*/
+void qh_printline3geom(qhT *qh, FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
+  int k;
+  realT pA[4], pB[4];
+
+  qh_projectdim3(qh, pointA, pA);
+  qh_projectdim3(qh, pointB, pB);
+  if ((fabs(pA[0] - pB[0]) > 1e-3) ||
+      (fabs(pA[1] - pB[1]) > 1e-3) ||
+      (fabs(pA[2] - pB[2]) > 1e-3)) {
+    qh_fprintf(qh, fp, 9204, "VECT 1 2 1 2 1\n");
+    for (k=0; k < 3; k++)
+       qh_fprintf(qh, fp, 9205, "%8.4g ", pB[k]);
+    qh_fprintf(qh, fp, 9206, " # p%d\n", qh_pointid(qh, pointB));
+  }else
+    qh_fprintf(qh, fp, 9207, "VECT 1 1 1 1 1\n");
+  for (k=0; k < 3; k++)
+    qh_fprintf(qh, fp, 9208, "%8.4g ", pA[k]);
+  qh_fprintf(qh, fp, 9209, " # p%d\n", qh_pointid(qh, pointA));
+  qh_fprintf(qh, fp, 9210, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
+}
+
+/*---------------------------------
+
+  qh_printneighborhood(qh, fp, format, facetA, facetB, printall )
+    print neighborhood of one or two facets
+
+  notes:
+    calls qh_findgood_all()
+    bumps qh.visit_id
+*/
+void qh_printneighborhood(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall) {
+  facetT *neighbor, **neighborp, *facet;
+  setT *facets;
+
+  if (format == qh_PRINTnone)
+    return;
+  qh_findgood_all(qh, qh->facet_list);
+  if (facetA == facetB)
+    facetB= NULL;
+  facets= qh_settemp(qh, 2*(qh_setsize(qh, facetA->neighbors)+1));
+  qh->visit_id++;
+  for (facet=facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
+    if (facet->visitid != qh->visit_id) {
+      facet->visitid= qh->visit_id;
+      qh_setappend(qh, &facets, facet);
+    }
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh->visit_id)
+        continue;
+      neighbor->visitid= qh->visit_id;
+      if (printall || !qh_skipfacet(qh, neighbor))
+        qh_setappend(qh, &facets, neighbor);
+    }
+  }
+  qh_printfacets(qh, fp, format, NULL, facets, printall);
+  qh_settempfree(qh, &facets);
+} /* printneighborhood */
+
+/*---------------------------------
+
+  qh_printpoint(qh, fp, string, point )
+  qh_printpointid(qh, fp, string, dim, point, id )
+    prints the coordinates of a point
+
+  returns:
+    if string is defined
+      prints 'string p%d'.  Skips p%d if id=qh_IDunknown(-1) or qh_IDnone(-3)
+
+  notes:
+    nop if point is NULL
+    Same as QhullPoint's printPoint
+*/
+void qh_printpoint(qhT *qh, FILE *fp, const char *string, pointT *point) {
+  int id= qh_pointid(qh, point);
+
+  qh_printpointid(qh, fp, string, qh->hull_dim, point, id);
+} /* printpoint */
+
+void qh_printpointid(qhT *qh, FILE *fp, const char *string, int dim, pointT *point, int id) {
+  int k;
+  realT r; /*bug fix*/
+
+  if (!point)
+    return;
+  if (string) {
+    qh_fprintf(qh, fp, 9211, "%s", string);
+    if (id != qh_IDunknown && id != qh_IDnone)
+      qh_fprintf(qh, fp, 9212, " p%d: ", id);
+  }
+  for (k=dim; k--; ) {
+    r= *point++;
+    if (string)
+      qh_fprintf(qh, fp, 9213, " %8.4g", r);
+    else
+      qh_fprintf(qh, fp, 9214, qh_REAL_1, r);
+  }
+  qh_fprintf(qh, fp, 9215, "\n");
+} /* printpointid */
+
+/*---------------------------------
+
+  qh_printpoint3(qh, fp, point )
+    prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
+*/
+void qh_printpoint3(qhT *qh, FILE *fp, pointT *point) {
+  int k;
+  realT p[4];
+
+  qh_projectdim3(qh, point, p);
+  for (k=0; k < 3; k++)
+    qh_fprintf(qh, fp, 9216, "%8.4g ", p[k]);
+  qh_fprintf(qh, fp, 9217, " # p%d\n", qh_pointid(qh, point));
+} /* printpoint3 */
+
+/*----------------------------------------
+-printpoints- print pointids for a set of points starting at index
+   see geom_r.c
+*/
+
+/*---------------------------------
+
+  qh_printpoints_out(qh, fp, facetlist, facets, printall )
+    prints vertices, coplanar/inside points, for facets by their point coordinates
+    allows qh.CDDoutput
+
+  notes:
+    same format as qhull input
+    if no coplanar/interior points,
+      same order as qh_printextremes
+*/
+void qh_printpoints_out(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  int allpoints= qh->num_points + qh_setsize(qh, qh->other_points);
+  int numpoints=0, point_i, point_n;
+  setT *vertices, *points;
+  facetT *facet, **facetp;
+  pointT *point, **pointp;
+  vertexT *vertex, **vertexp;
+  int id;
+
+  points= qh_settemp(qh, allpoints);
+  qh_setzero(qh, points, 0, allpoints);
+  vertices= qh_facetvertices(qh, facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid(qh, vertex->point);
+    if (id >= 0)
+      SETelem_(points, id)= vertex->point;
+  }
+  if (qh->KEEPinside || qh->KEEPcoplanar || qh->KEEPnearinside) {
+    FORALLfacet_(facetlist) {
+      if (!printall && qh_skipfacet(qh, facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid(qh, point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+    FOREACHfacet_(facets) {
+      if (!printall && qh_skipfacet(qh, facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid(qh, point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+  }
+  qh_settempfree(qh, &vertices);
+  FOREACHpoint_i_(qh, points) {
+    if (point)
+      numpoints++;
+  }
+  if (qh->CDDoutput)
+    qh_fprintf(qh, fp, 9218, "%s | %s\nbegin\n%d %d real\n", qh->rbox_command,
+             qh->qhull_command, numpoints, qh->hull_dim + 1);
+  else
+    qh_fprintf(qh, fp, 9219, "%d\n%d\n", qh->hull_dim, numpoints);
+  FOREACHpoint_i_(qh, points) {
+    if (point) {
+      if (qh->CDDoutput)
+        qh_fprintf(qh, fp, 9220, "1 ");
+      qh_printpoint(qh, fp, NULL, point);
+    }
+  }
+  if (qh->CDDoutput)
+    qh_fprintf(qh, fp, 9221, "end\n");
+  qh_settempfree(qh, &points);
+} /* printpoints_out */
+
+
+/*---------------------------------
+
+  qh_printpointvect(qh, fp, point, normal, center, radius, color )
+    prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
+*/
+void qh_printpointvect(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
+  realT diff[4], pointA[4];
+  int k;
+
+  for (k=qh->hull_dim; k--; ) {
+    if (center)
+      diff[k]= point[k]-center[k];
+    else if (normal)
+      diff[k]= normal[k];
+    else
+      diff[k]= 0;
+  }
+  if (center)
+    qh_normalize2(qh, diff, qh->hull_dim, True, NULL, NULL);
+  for (k=qh->hull_dim; k--; )
+    pointA[k]= point[k]+diff[k] * radius;
+  qh_printline3geom(qh, fp, point, pointA, color);
+} /* printpointvect */
+
+/*---------------------------------
+
+  qh_printpointvect2(qh, fp, point, normal, center, radius )
+    prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
+*/
+void qh_printpointvect2(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
+  realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
+
+  qh_printpointvect(qh, fp, point, normal, center, radius, red);
+  qh_printpointvect(qh, fp, point, normal, center, -radius, yellow);
+} /* printpointvect2 */
+
+/*---------------------------------
+
+  qh_printridge(qh, fp, ridge )
+    prints the information in a ridge
+
+  notes:
+    for qh_printfacetridges()
+    same as operator<< [QhullRidge.cpp]
+*/
+void qh_printridge(qhT *qh, FILE *fp, ridgeT *ridge) {
+
+  qh_fprintf(qh, fp, 9222, "     - r%d", ridge->id);
+  if (ridge->tested)
+    qh_fprintf(qh, fp, 9223, " tested");
+  if (ridge->nonconvex)
+    qh_fprintf(qh, fp, 9224, " nonconvex");
+  if (ridge->mergevertex)
+    qh_fprintf(qh, fp, 9421, " mergevertex");
+  if (ridge->mergevertex2)
+    qh_fprintf(qh, fp, 9422, " mergevertex2");
+  if (ridge->simplicialtop)
+    qh_fprintf(qh, fp, 9425, " simplicialtop");
+  if (ridge->simplicialbot)
+    qh_fprintf(qh, fp, 9423, " simplicialbot");
+  qh_fprintf(qh, fp, 9225, "\n");
+  qh_printvertices(qh, fp, "           vertices:", ridge->vertices);
+  if (ridge->top && ridge->bottom)
+    qh_fprintf(qh, fp, 9226, "           between f%d and f%d\n",
+            ridge->top->id, ridge->bottom->id);
+} /* printridge */
+
+/*---------------------------------
+
+  qh_printspheres(qh, fp, vertices, radius )
+    prints 3-d vertices as OFF spheres
+
+  notes:
+    inflated octahedron from Stuart Levy earth/mksphere2
+*/
+void qh_printspheres(qhT *qh, FILE *fp, setT *vertices, realT radius) {
+  vertexT *vertex, **vertexp;
+
+  qh->printoutnum++;
+  qh_fprintf(qh, fp, 9227, "{appearance {-edge -normal normscale 0} {\n\
+INST geom {define vsphere OFF\n\
+18 32 48\n\
+\n\
+0 0 1\n\
+1 0 0\n\
+0 1 0\n\
+-1 0 0\n\
+0 -1 0\n\
+0 0 -1\n\
+0.707107 0 0.707107\n\
+0 -0.707107 0.707107\n\
+0.707107 -0.707107 0\n\
+-0.707107 0 0.707107\n\
+-0.707107 -0.707107 0\n\
+0 0.707107 0.707107\n\
+-0.707107 0.707107 0\n\
+0.707107 0.707107 0\n\
+0.707107 0 -0.707107\n\
+0 0.707107 -0.707107\n\
+-0.707107 0 -0.707107\n\
+0 -0.707107 -0.707107\n\
+\n\
+3 0 6 11\n\
+3 0 7 6 \n\
+3 0 9 7 \n\
+3 0 11 9\n\
+3 1 6 8 \n\
+3 1 8 14\n\
+3 1 13 6\n\
+3 1 14 13\n\
+3 2 11 13\n\
+3 2 12 11\n\
+3 2 13 15\n\
+3 2 15 12\n\
+3 3 9 12\n\
+3 3 10 9\n\
+3 3 12 16\n\
+3 3 16 10\n\
+3 4 7 10\n\
+3 4 8 7\n\
+3 4 10 17\n\
+3 4 17 8\n\
+3 5 14 17\n\
+3 5 15 14\n\
+3 5 16 15\n\
+3 5 17 16\n\
+3 6 13 11\n\
+3 7 8 6\n\
+3 9 10 7\n\
+3 11 12 9\n\
+3 14 8 17\n\
+3 15 13 14\n\
+3 16 12 15\n\
+3 17 10 16\n} transforms { TLIST\n");
+  FOREACHvertex_(vertices) {
+    qh_fprintf(qh, fp, 9228, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
+      radius, vertex->id, radius, radius);
+    qh_printpoint3(qh, fp, vertex->point);
+    qh_fprintf(qh, fp, 9229, "1\n");
+  }
+  qh_fprintf(qh, fp, 9230, "}}}\n");
+} /* printspheres */
+
+
+/*----------------------------------------------
+-printsummary-
+                see libqhull_r.c
+*/
+
+/*---------------------------------
+
+  qh_printvdiagram(qh, fp, format, facetlist, facets, printall )
+    print voronoi diagram
+      # of pairs of input sites
+      #indices site1 site2 vertex1 ...
+
+    sites indexed by input point id
+      point 0 is the first input point
+    vertices indexed by 'o' and 'p' order
+      vertex 0 is the 'vertex-at-infinity'
+      vertex 1 is the first Voronoi vertex
+
+  see:
+    qh_printvoronoi()
+    qh_eachvoronoi_all()
+
+  notes:
+    if all facets are upperdelaunay,
+      prints upper hull (furthest-site Voronoi diagram)
+*/
+void qh_printvdiagram(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices;
+  int totcount, numcenters;
+  boolT isLower;
+  qh_RIDGE innerouter= qh_RIDGEall;
+  printvridgeT printvridge= NULL;
+
+  if (format == qh_PRINTvertices) {
+    innerouter= qh_RIDGEall;
+    printvridge= qh_printvridge;
+  }else if (format == qh_PRINTinner) {
+    innerouter= qh_RIDGEinner;
+    printvridge= qh_printvnorm;
+  }else if (format == qh_PRINTouter) {
+    innerouter= qh_RIDGEouter;
+    printvridge= qh_printvnorm;
+  }else {
+    qh_fprintf(qh, qh->ferr, 6219, "qhull internal error (qh_printvdiagram): unknown print format %d.\n", format);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  vertices= qh_markvoronoi(qh, facetlist, facets, printall, &isLower, &numcenters);
+  totcount= qh_printvdiagram2(qh, NULL, NULL, vertices, innerouter, False);
+  qh_fprintf(qh, fp, 9231, "%d\n", totcount);
+  totcount= qh_printvdiagram2(qh, fp, printvridge, vertices, innerouter, True /* inorder*/);
+  qh_settempfree(qh, &vertices);
+#if 0  /* for testing qh_eachvoronoi_all */
+  qh_fprintf(qh, fp, 9232, "\n");
+  totcount= qh_eachvoronoi_all(qh, fp, printvridge, qh->UPPERdelaunay, innerouter, True /* inorder*/);
+  qh_fprintf(qh, fp, 9233, "%d\n", totcount);
+#endif
+} /* printvdiagram */
+
+/*---------------------------------
+
+  qh_printvdiagram2(qh, fp, printvridge, vertices, innerouter, inorder )
+    visit all pairs of input sites (vertices) for selected Voronoi vertices
+    vertices may include NULLs
+
+  innerouter:
+    qh_RIDGEall   print inner ridges(bounded) and outer ridges(unbounded)
+    qh_RIDGEinner print only inner ridges
+    qh_RIDGEouter print only outer ridges
+
+  inorder:
+    print 3-d Voronoi vertices in order
+
+  assumes:
+    qh_markvoronoi marked facet->visitid for Voronoi vertices
+    all facet->seen= False
+    all facet->seen2= True
+
+  returns:
+    total number of Voronoi ridges
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers) for each ridge
+      [see qh_eachvoronoi()]
+
+  see:
+    qh_eachvoronoi_all()
+*/
+int qh_printvdiagram2(qhT *qh, FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
+  int totcount= 0;
+  int vertex_i, vertex_n;
+  vertexT *vertex;
+
+  FORALLvertices
+    vertex->seen= False;
+  FOREACHvertex_i_(qh, vertices) {
+    if (vertex) {
+      if (qh->GOODvertex > 0 && qh_pointid(qh, vertex->point)+1 != qh->GOODvertex)
+        continue;
+      totcount += qh_eachvoronoi(qh, fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
+    }
+  }
+  return totcount;
+} /* printvdiagram2 */
+
+/*---------------------------------
+
+  qh_printvertex(qh, fp, vertex )
+    prints the information in a vertex
+    Duplicated as operator<< [QhullVertex.cpp]
+*/
+void qh_printvertex(qhT *qh, FILE *fp, vertexT *vertex) {
+  pointT *point;
+  int k, count= 0;
+  facetT *neighbor, **neighborp;
+  realT r; /*bug fix*/
+
+  if (!vertex) {
+    qh_fprintf(qh, fp, 9234, "  NULLvertex\n");
+    return;
+  }
+  qh_fprintf(qh, fp, 9235, "- p%d(v%d):", qh_pointid(qh, vertex->point), vertex->id);
+  point= vertex->point;
+  if (point) {
+    for (k=qh->hull_dim; k--; ) {
+      r= *point++;
+      qh_fprintf(qh, fp, 9236, " %5.2g", r);
+    }
+  }
+  if (vertex->deleted)
+    qh_fprintf(qh, fp, 9237, " deleted");
+  if (vertex->delridge)
+    qh_fprintf(qh, fp, 9238, " delridge");
+  if (vertex->newfacet)
+    qh_fprintf(qh, fp, 9415, " newfacet");
+  if (vertex->seen && qh->IStracing)
+    qh_fprintf(qh, fp, 9416, " seen");
+  if (vertex->seen2 && qh->IStracing)
+    qh_fprintf(qh, fp, 9417, " seen2");
+  qh_fprintf(qh, fp, 9239, "\n");
+  if (vertex->neighbors) {
+    qh_fprintf(qh, fp, 9240, "  neighbors:");
+    FOREACHneighbor_(vertex) {
+      if (++count % 100 == 0)
+        qh_fprintf(qh, fp, 9241, "\n     ");
+      qh_fprintf(qh, fp, 9242, " f%d", neighbor->id);
+    }
+    qh_fprintf(qh, fp, 9243, "\n");
+  }
+} /* printvertex */
+
+
+/*---------------------------------
+
+  qh_printvertexlist(qh, fp, string, facetlist, facets, printall )
+    prints vertices used by a facetlist or facet set
+    tests qh_skipfacet() if !printall
+*/
+void qh_printvertexlist(qhT *qh, FILE *fp, const char* string, facetT *facetlist,
+                         setT *facets, boolT printall) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+
+  vertices= qh_facetvertices(qh, facetlist, facets, printall);
+  qh_fprintf(qh, fp, 9244, "%s", string);
+  FOREACHvertex_(vertices)
+    qh_printvertex(qh, fp, vertex);
+  qh_settempfree(qh, &vertices);
+} /* printvertexlist */
+
+
+/*---------------------------------
+
+  qh_printvertices(qh, fp, string, vertices )
+    prints vertices in a set
+    duplicated as printVertexSet [QhullVertex.cpp]
+*/
+void qh_printvertices(qhT *qh, FILE *fp, const char* string, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  qh_fprintf(qh, fp, 9245, "%s", string);
+  FOREACHvertex_(vertices)
+    qh_fprintf(qh, fp, 9246, " p%d(v%d)", qh_pointid(qh, vertex->point), vertex->id);
+  qh_fprintf(qh, fp, 9247, "\n");
+} /* printvertices */
+
+/*---------------------------------
+
+  qh_printvneighbors(qh, fp, facetlist, facets, printall )
+    print vertex neighbors of vertices in facetlist and facets ('FN')
+
+  notes:
+    qh_countfacets clears facet->visitid for non-printed facets
+
+  design:
+    collect facet count and related statistics
+    if necessary, build neighbor sets for each vertex
+    collect vertices in facetlist and facets
+    build a point array for point->vertex and point->coplanar facet
+    for each point
+      list vertex neighbors or coplanar facet
+*/
+void qh_printvneighbors(qhT *qh, FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
+  setT *vertices, *vertex_points, *coplanar_points;
+  int numpoints= qh->num_points + qh_setsize(qh, qh->other_points);
+  vertexT *vertex, **vertexp;
+  int vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  pointT *point, **pointp;
+
+  qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
+  qh_fprintf(qh, fp, 9248, "%d\n", numpoints);
+  qh_vertexneighbors(qh);
+  vertices= qh_facetvertices(qh, facetlist, facets, printall);
+  vertex_points= qh_settemp(qh, numpoints);
+  coplanar_points= qh_settemp(qh, numpoints);
+  qh_setzero(qh, vertex_points, 0, numpoints);
+  qh_setzero(qh, coplanar_points, 0, numpoints);
+  FOREACHvertex_(vertices)
+    qh_point_add(qh, vertex_points, vertex->point, vertex);
+  FORALLfacet_(facetlist) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(qh, coplanar_points, point, facet);
+  }
+  FOREACHfacet_(facets) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(qh, coplanar_points, point, facet);
+  }
+  FOREACHvertex_i_(qh, vertex_points) {
+    if (vertex) {
+      numneighbors= qh_setsize(qh, vertex->neighbors);
+      qh_fprintf(qh, fp, 9249, "%d", numneighbors);
+      qh_order_vertexneighbors(qh, vertex);
+      FOREACHneighbor_(vertex)
+        qh_fprintf(qh, fp, 9250, " %d",
+                 neighbor->visitid ? neighbor->visitid - 1 : 0 - neighbor->id);
+      qh_fprintf(qh, fp, 9251, "\n");
+    }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
+      qh_fprintf(qh, fp, 9252, "1 %d\n",
+                  facet->visitid ? facet->visitid - 1 : 0 - facet->id);
+    else
+      qh_fprintf(qh, fp, 9253, "0\n");
+  }
+  qh_settempfree(qh, &coplanar_points);
+  qh_settempfree(qh, &vertex_points);
+  qh_settempfree(qh, &vertices);
+} /* printvneighbors */
+
+/*---------------------------------
+
+  qh_printvoronoi(qh, fp, format, facetlist, facets, printall )
+    print voronoi diagram in 'o' or 'G' format
+    for 'o' format
+      prints voronoi centers for each facet and for infinity
+      for each vertex, lists ids of printed facets or infinity
+      assumes facetlist and facets are disjoint
+    for 'G' format
+      prints an OFF object
+      adds a 0 coordinate to center
+      prints infinity but does not list in vertices
+
+  see:
+    qh_printvdiagram()
+
+  notes:
+    if 'o',
+      prints a line for each point except "at-infinity"
+    if all facets are upperdelaunay,
+      reverses lower and upper hull
+*/
+void qh_printvoronoi(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  setT *vertices;
+  vertexT *vertex;
+  boolT isLower;
+  unsigned int numfacets= (unsigned int)qh->num_facets;
+
+  vertices= qh_markvoronoi(qh, facetlist, facets, printall, &isLower, &numcenters);
+  FOREACHvertex_i_(qh, vertices) {
+    if (vertex) {
+      numvertices++;
+      numneighbors= numinf= 0;
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+          numinf= 1;
+        else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+      if (numinf && !numneighbors) {
+        SETelem_(vertices, vertex_i)= NULL;
+        numvertices--;
+      }
+    }
+  }
+  if (format == qh_PRINTgeom)
+    qh_fprintf(qh, fp, 9254, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
+                numcenters, numvertices);
+  else
+    qh_fprintf(qh, fp, 9255, "%d\n%d %d 1\n", qh->hull_dim-1, numcenters, qh_setsize(qh, vertices));
+  if (format == qh_PRINTgeom) {
+    for (k=qh->hull_dim-1; k--; )
+      qh_fprintf(qh, fp, 9256, qh_REAL_1, 0.0);
+    qh_fprintf(qh, fp, 9257, " 0 # infinity not used\n");
+  }else {
+    for (k=qh->hull_dim-1; k--; )
+      qh_fprintf(qh, fp, 9258, qh_REAL_1, qh_INFINITE);
+    qh_fprintf(qh, fp, 9259, "\n");
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        qh_fprintf(qh, fp, 9260, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter(qh, fp, format, NULL, facet);
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        qh_fprintf(qh, fp, 9261, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter(qh, fp, format, NULL, facet);
+    }
+  }
+  FOREACHvertex_i_(qh, vertices) {
+    numneighbors= 0;
+    numinf=0;
+    if (vertex) {
+      qh_order_vertexneighbors(qh, vertex);
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+          numinf= 1;
+        else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+    }
+    if (format == qh_PRINTgeom) {
+      if (vertex) {
+        qh_fprintf(qh, fp, 9262, "%d", numneighbors);
+        FOREACHneighbor_(vertex) {
+          if (neighbor->visitid && neighbor->visitid < numfacets)
+            qh_fprintf(qh, fp, 9263, " %d", neighbor->visitid);
+        }
+        qh_fprintf(qh, fp, 9264, " # p%d(v%d)\n", vertex_i, vertex->id);
+      }else
+        qh_fprintf(qh, fp, 9265, " # p%d is coplanar or isolated\n", vertex_i);
+    }else {
+      if (numinf)
+        numneighbors++;
+      qh_fprintf(qh, fp, 9266, "%d", numneighbors);
+      if (vertex) {
+        FOREACHneighbor_(vertex) {
+          if (neighbor->visitid == 0) {
+            if (numinf) {
+              numinf= 0;
+              qh_fprintf(qh, fp, 9267, " %d", neighbor->visitid);
+            }
+          }else if (neighbor->visitid < numfacets)
+            qh_fprintf(qh, fp, 9268, " %d", neighbor->visitid);
+        }
+      }
+      qh_fprintf(qh, fp, 9269, "\n");
+    }
+  }
+  if (format == qh_PRINTgeom)
+    qh_fprintf(qh, fp, 9270, "}\n");
+  qh_settempfree(qh, &vertices);
+} /* printvoronoi */
+
+/*---------------------------------
+
+  qh_printvnorm(qh, fp, vertex, vertexA, centers, unbounded )
+    print one separating plane of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+
+  note:
+    parameter unbounded is UNUSED by this callback
+
+  see:
+    qh_printvdiagram()
+    qh_eachvoronoi()
+*/
+void qh_printvnorm(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  pointT *normal;
+  realT offset;
+  int k;
+  QHULL_UNUSED(unbounded);
+
+  normal= qh_detvnorm(qh, vertex, vertexA, centers, &offset);
+  qh_fprintf(qh, fp, 9271, "%d %d %d ",
+      2+qh->hull_dim, qh_pointid(qh, vertex->point), qh_pointid(qh, vertexA->point));
+  for (k=0; k< qh->hull_dim-1; k++)
+    qh_fprintf(qh, fp, 9272, qh_REAL_1, normal[k]);
+  qh_fprintf(qh, fp, 9273, qh_REAL_1, offset);
+  qh_fprintf(qh, fp, 9274, "\n");
+} /* printvnorm */
+
+/*---------------------------------
+
+  qh_printvridge(qh, fp, vertex, vertexA, centers, unbounded )
+    print one ridge of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+
+  see:
+    qh_printvdiagram()
+
+  notes:
+    the user may use a different function
+    parameter unbounded is UNUSED
+*/
+void qh_printvridge(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  facetT *facet, **facetp;
+  QHULL_UNUSED(unbounded);
+
+  qh_fprintf(qh, fp, 9275, "%d %d %d", qh_setsize(qh, centers)+2,
+       qh_pointid(qh, vertex->point), qh_pointid(qh, vertexA->point));
+  FOREACHfacet_(centers)
+    qh_fprintf(qh, fp, 9276, " %d", facet->visitid);
+  qh_fprintf(qh, fp, 9277, "\n");
+} /* printvridge */
+
+/*---------------------------------
+
+  qh_projectdim3(qh, source, destination )
+    project 2-d 3-d or 4-d point to a 3-d point
+    uses qh.DROPdim and qh.hull_dim
+    source and destination may be the same
+
+  notes:
+    allocate 4 elements to destination just in case
+*/
+void qh_projectdim3(qhT *qh, pointT *source, pointT *destination) {
+  int i,k;
+
+  for (k=0, i=0; k < qh->hull_dim; k++) {
+    if (qh->hull_dim == 4) {
+      if (k != qh->DROPdim)
+        destination[i++]= source[k];
+    }else if (k == qh->DROPdim)
+      destination[i++]= 0;
+    else
+      destination[i++]= source[k];
+  }
+  while (i < 3)
+    destination[i++]= 0.0;
+} /* projectdim3 */
+
+/*---------------------------------
+
+  qh_readfeasible(qh, dim, curline )
+    read feasible point from current line and qh.fin
+
+  returns:
+    number of lines read from qh.fin
+    sets qh.feasible_point with malloc'd coordinates
+
+  notes:
+    checks for qh.HALFspace
+    assumes dim > 1
+
+  see:
+    qh_setfeasible
+*/
+int qh_readfeasible(qhT *qh, int dim, const char *curline) {
+  boolT isfirst= True;
+  int linecount= 0, tokcount= 0;
+  const char *s;
+  char *t, firstline[qh_MAXfirst+1];
+  coordT *coords, value;
+
+  if (!qh->HALFspace) {
+    qh_fprintf(qh, qh->ferr, 6070, "qhull input error: feasible point(dim 1 coords) is only valid for halfspace intersection\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (qh->feasible_string)
+    qh_fprintf(qh, qh->ferr, 7057, "qhull input warning: feasible point(dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
+  if (!(qh->feasible_point= (coordT *)qh_malloc((size_t)dim * sizeof(coordT)))) {
+    qh_fprintf(qh, qh->ferr, 6071, "qhull error: insufficient memory for feasible point\n");
+    qh_errexit(qh, qh_ERRmem, NULL, NULL);
+  }
+  coords= qh->feasible_point;
+  while ((s= (isfirst ?  curline : fgets(firstline, qh_MAXfirst, qh->fin)))) {
+    if (isfirst)
+      isfirst= False;
+    else
+      linecount++;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod(s, &t);
+      if (s == t)
+        break;
+      s= t;
+      *(coords++)= value;
+      if (++tokcount == dim) {
+        while (isspace(*s))
+          s++;
+        qh_strtod(s, &t);
+        if (s != t) {
+          qh_fprintf(qh, qh->ferr, 6072, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
+               s);
+          qh_errexit(qh, qh_ERRinput, NULL, NULL);
+        }
+        return linecount;
+      }
+    }
+  }
+  qh_fprintf(qh, qh->ferr, 6073, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
+           tokcount, dim);
+  qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  return 0;
+} /* readfeasible */
+
+/*---------------------------------
+
+  qh_readpoints(qh, numpoints, dimension, ismalloc )
+    read points from qh.fin into qh.first_point, qh.num_points
+    qh.fin is lines of coordinates, one per vertex, first line number of points
+    if 'rbox D4',
+      gives message
+    if qh.ATinfinity,
+      adds point-at-infinity for Delaunay triangulations
+
+  returns:
+    number of points, array of point coordinates, dimension, ismalloc True
+    if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
+        and clears qh.PROJECTdelaunay
+    if qh.HALFspace, reads optional feasible point, reads halfspaces,
+        converts to dual.
+
+  for feasible point in "cdd format" in 3-d:
+    3 1
+    coordinates
+    comments
+    begin
+    n 4 real/integer
+    ...
+    end
+
+  notes:
+    dimension will change in qh_initqhull_globals if qh.PROJECTinput
+    uses malloc() since qh_mem not initialized
+    QH11012 FIX: qh_readpoints needs rewriting, too long
+*/
+coordT *qh_readpoints(qhT *qh, int *numpoints, int *dimension, boolT *ismalloc) {
+  coordT *points, *coords, *infinity= NULL;
+  realT paraboloid, maxboloid= -REALmax, value;
+  realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
+  char *s= 0, *t, firstline[qh_MAXfirst+1];
+  int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
+  int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
+  int tokcount= 0, linecount=0, maxcount, coordcount=0;
+  boolT islong, isfirst= True, wasbegin= False;
+  boolT isdelaunay= qh->DELAUNAY && !qh->PROJECTinput;
+
+  if (qh->CDDinput) {
+    while ((s= fgets(firstline, qh_MAXfirst, qh->fin))) {
+      linecount++;
+      if (qh->HALFspace && linecount == 1 && isdigit(*s)) {
+        dimfeasible= qh_strtol(s, &s);
+        while (isspace(*s))
+          s++;
+        if (qh_strtol(s, &s) == 1)
+          linecount += qh_readfeasible(qh, dimfeasible, s);
+        else
+          dimfeasible= 0;
+      }else if (!memcmp(firstline, "begin", (size_t)5) || !memcmp(firstline, "BEGIN", (size_t)5))
+        break;
+      else if (!*qh->rbox_command)
+        strncat(qh->rbox_command, s, sizeof(qh->rbox_command)-1);
+    }
+    if (!s) {
+      qh_fprintf(qh, qh->ferr, 6074, "qhull input error: missing \"begin\" for cdd-formated input\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+  }
+  while (!numinput && (s= fgets(firstline, qh_MAXfirst, qh->fin))) {
+    linecount++;
+    if (!memcmp(s, "begin", (size_t)5) || !memcmp(s, "BEGIN", (size_t)5))
+      wasbegin= True;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      if (!*s)
+        break;
+      if (!isdigit(*s)) {
+        if (!*qh->rbox_command) {
+          strncat(qh->rbox_command, s, sizeof(qh->rbox_command)-1);
+          firsttext= linecount;
+        }
+        break;
+      }
+      if (!diminput)
+        diminput= qh_strtol(s, &s);
+      else {
+        numinput= qh_strtol(s, &s);
+        if (numinput == 1 && diminput >= 2 && qh->HALFspace && !qh->CDDinput) {
+          linecount += qh_readfeasible(qh, diminput, s); /* checks if ok */
+          dimfeasible= diminput;
+          diminput= numinput= 0;
+        }else
+          break;
+      }
+    }
+  }
+  if (!s) {
+    qh_fprintf(qh, qh->ferr, 6075, "qhull input error: short input file.  Did not find dimension and number of points\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (diminput > numinput) {
+    tempi= diminput;    /* exchange dim and n, e.g., for cdd input format */
+    diminput= numinput;
+    numinput= tempi;
+  }
+  if (diminput < 2) {
+    qh_fprintf(qh, qh->ferr, 6220, "qhull input error: dimension %d (first or smaller number) should be at least 2\n",
+            diminput);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (numinput < 1 || numinput > qh_POINTSmax) {
+    qh_fprintf(qh, qh->ferr, 6411, "qhull input error: expecting between 1 and %d points.  Got %d %d-d points\n",
+      qh_POINTSmax, numinput, diminput);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    /* same error message in qh_initqhull_globals */
+  }
+
+  if (isdelaunay && qh->HALFspace) {
+    qh_fprintf(qh, qh->ferr, 6037, "qhull option error (qh_readpoints): can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    /* otherwise corrupted memory allocations, same error message as in qh_initqhull_globals */
+  }else if (isdelaunay) {
+    qh->PROJECTdelaunay= False;
+    if (qh->CDDinput)
+      *dimension= diminput;
+    else
+      *dimension= diminput+1;
+    *numpoints= numinput;
+    if (qh->ATinfinity)
+      (*numpoints)++;
+  }else if (qh->HALFspace) {
+    *dimension= diminput - 1;
+    *numpoints= numinput;
+    if (diminput < 3) {
+      qh_fprintf(qh, qh->ferr, 6221, "qhull input error: dimension %d (first number, includes offset) should be at least 3 for halfspaces\n",
+            diminput);
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    if (dimfeasible) {
+      if (dimfeasible != *dimension) {
+        qh_fprintf(qh, qh->ferr, 6222, "qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
+          dimfeasible, diminput);
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }
+    }else
+      qh_setfeasible(qh, *dimension);
+  }else {
+    if (qh->CDDinput)
+      *dimension= diminput-1;
+    else
+      *dimension= diminput;
+    *numpoints= numinput;
+  }
+  qh->normal_size= *dimension * (int)sizeof(coordT); /* for tracing with qh_printpoint */
+  if (qh->HALFspace) {
+    qh->half_space= coordp= (coordT *)qh_malloc((size_t)qh->normal_size + sizeof(coordT));
+    if (qh->CDDinput) {
+      offsetp= qh->half_space;
+      normalp= offsetp + 1;
+    }else {
+      normalp= qh->half_space;
+      offsetp= normalp + *dimension;
+    }
+  }
+  qh->maxline= diminput * (qh_REALdigits + 5);
+  maximize_(qh->maxline, 500);
+  qh->line= (char *)qh_malloc((size_t)(qh->maxline+1) * sizeof(char));
+  *ismalloc= True;  /* use malloc since memory not setup */
+  coords= points= qh->temp_malloc=  /* numinput and diminput >=2 by QH6220 */
+        (coordT *)qh_malloc((size_t)((*numpoints)*(*dimension))*sizeof(coordT));
+  if (!coords || !qh->line || (qh->HALFspace && !qh->half_space)) {
+    qh_fprintf(qh, qh->ferr, 6076, "qhull error: insufficient memory to read %d points\n",
+            numinput);
+    qh_errexit(qh, qh_ERRmem, NULL, NULL);
+  }
+  if (isdelaunay && qh->ATinfinity) {
+    infinity= points + numinput * (*dimension);
+    for (k= (*dimension) - 1; k--; )
+      infinity[k]= 0.0;
+  }
+  maxcount= numinput * diminput;
+  paraboloid= 0.0;
+  while ((s= (isfirst ?  s : fgets(qh->line, qh->maxline, qh->fin)))) {
+    if (!isfirst) {
+      linecount++;
+      if (*s == 'e' || *s == 'E') {
+        if (!memcmp(s, "end", (size_t)3) || !memcmp(s, "END", (size_t)3)) {
+          if (qh->CDDinput )
+            break;
+          else if (wasbegin)
+            qh_fprintf(qh, qh->ferr, 7058, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
+        }
+      }
+    }
+    islong= False;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod(s, &t);
+      if (s == t) {
+        if (!*qh->rbox_command)
+         strncat(qh->rbox_command, s, sizeof(qh->rbox_command)-1);
+        if (*s && !firsttext)
+          firsttext= linecount;
+        if (!islong && !firstshort && coordcount)
+          firstshort= linecount;
+        break;
+      }
+      if (!firstpoint)
+        firstpoint= linecount;
+      s= t;
+      if (++tokcount > maxcount)
+        continue;
+      if (qh->HALFspace) {
+        if (qh->CDDinput)
+          *(coordp++)= -value; /* both coefficients and offset */
+        else
+          *(coordp++)= value;
+      }else {
+        *(coords++)= value;
+        if (qh->CDDinput && !coordcount) {
+          if (value != 1.0) {
+            qh_fprintf(qh, qh->ferr, 6077, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
+                   linecount);
+            qh_errexit(qh, qh_ERRinput, NULL, NULL);
+          }
+          coords--;
+        }else if (isdelaunay) {
+          paraboloid += value * value;
+          if (qh->ATinfinity) {
+            if (qh->CDDinput)
+              infinity[coordcount-1] += value;
+            else
+              infinity[coordcount] += value;
+          }
+        }
+      }
+      if (++coordcount == diminput) {
+        coordcount= 0;
+        if (isdelaunay) {
+          *(coords++)= paraboloid;
+          maximize_(maxboloid, paraboloid);
+          paraboloid= 0.0;
+        }else if (qh->HALFspace) {
+          if (!qh_sethalfspace(qh, *dimension, coords, &coords, normalp, offsetp, qh->feasible_point)) {
+            qh_fprintf(qh, qh->ferr, 8048, "The halfspace was on line %d\n", linecount);
+            if (wasbegin)
+              qh_fprintf(qh, qh->ferr, 8049, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
+            qh_errexit(qh, qh_ERRinput, NULL, NULL);
+          }
+          coordp= qh->half_space;
+        }
+        while (isspace(*s))
+          s++;
+        if (*s) {
+          islong= True;
+          if (!firstlong)
+            firstlong= linecount;
+        }
+      }
+    }
+    if (!islong && !firstshort && coordcount)
+      firstshort= linecount;
+    if (!isfirst && s - qh->line >= qh->maxline) {
+      qh_fprintf(qh, qh->ferr, 6078, "qhull input error: line %d contained more than %d characters\n",
+              linecount, (int) (s - qh->line));   /* WARN64 */
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    isfirst= False;
+  }
+  if (qh->rbox_command[0])
+    qh->rbox_command[strlen(qh->rbox_command)-1]= '\0'; /* remove \n, previous qh_errexit's display command as two lines */
+  if (tokcount != maxcount) {
+    newnum= fmin_(numinput, tokcount/diminput);
+    if (qh->ALLOWshort)
+      qh_fprintf(qh, qh->ferr, 7073, "qhull warning: instead of %d points in %d-d, input contains %d points and %d extra coordinates.\n",
+          numinput, diminput, tokcount/diminput, tokcount % diminput);
+    else
+      qh_fprintf(qh, qh->ferr, 6410, "qhull error: instead of %d points in %d-d, input contains %d points and %d extra coordinates.\n",
+          numinput, diminput, tokcount/diminput, tokcount % diminput);
+    if (firsttext)
+      qh_fprintf(qh, qh->ferr, 8051, "    Line %d is the first comment.\n", firsttext);
+    qh_fprintf(qh, qh->ferr, 8033,   "    Line %d is the first point.\n", firstpoint);
+    if (firstshort)
+      qh_fprintf(qh, qh->ferr, 8052, "    Line %d is the first short line.\n", firstshort);
+    if (firstlong)
+      qh_fprintf(qh, qh->ferr, 8053, "    Line %d is the first long line.\n", firstlong);
+    if (qh->ALLOWshort)
+      qh_fprintf(qh, qh->ferr, 8054, "    Continuing with %d points.\n", newnum);
+    else {
+      qh_fprintf(qh, qh->ferr, 8077, "    Override with option 'Qa' (allow-short)\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    numinput= newnum;
+    if (isdelaunay && qh->ATinfinity) {
+      for (k= tokcount % diminput; k--; )
+        infinity[k] -= *(--coords);
+      *numpoints= newnum+1;
+    }else {
+      coords -= tokcount % diminput;
+      *numpoints= newnum;
+    }
+  }
+  if (isdelaunay && qh->ATinfinity) {
+    for (k= (*dimension) - 1; k--; )
+      infinity[k] /= numinput;
+    if (coords == infinity)
+      coords += (*dimension) -1;
+    else {
+      for (k=0; k < (*dimension) - 1; k++)
+        *(coords++)= infinity[k];
+    }
+    *(coords++)= maxboloid * 1.1;
+  }
+  if (!strcmp(qh->rbox_command, "./rbox D4"))
+    qh_fprintf(qh, qh->ferr, 8055, "\n\
+This is the qhull test case.  If any errors or core dumps occur,\n\
+recompile qhull with 'make new'.  If errors still occur, there is\n\
+an incompatibility.  You should try a different compiler.  You can also\n\
+change the choices in user_r.h.  If you discover the source of the problem,\n\
+please send mail to qhull_bug@qhull.org.\n\
+\n\
+Type 'qhull' for a short list of options.\n");
+  qh_free(qh->line);
+  qh->line= NULL;
+  if (qh->half_space) {
+    qh_free(qh->half_space);
+    qh->half_space= NULL;
+  }
+  qh->temp_malloc= NULL;
+  trace1((qh, qh->ferr, 1008,"qh_readpoints: read in %d %d-dimensional points\n",
+          numinput, diminput));
+  return(points);
+} /* readpoints */
+
+
+/*---------------------------------
+
+  qh_setfeasible(qh, dim )
+    set qh.feasible_point from qh.feasible_string in "n,n,n" or "n n n" format
+
+  notes:
+    "n,n,n" already checked by qh_initflags()
+    see qh_readfeasible()
+    called only once from qh_new_qhull, otherwise leaks memory
+*/
+void qh_setfeasible(qhT *qh, int dim) {
+  int tokcount= 0;
+  char *s;
+  coordT *coords, value;
+
+  if (!(s= qh->feasible_string)) {
+    qh_fprintf(qh, qh->ferr, 6223, "qhull input error: halfspace intersection needs a feasible point.  Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (!(qh->feasible_point= (pointT *)qh_malloc((size_t)dim * sizeof(coordT)))) {
+    qh_fprintf(qh, qh->ferr, 6079, "qhull error: insufficient memory for 'Hn,n,n'\n");
+    qh_errexit(qh, qh_ERRmem, NULL, NULL);
+  }
+  coords= qh->feasible_point;
+  while (*s) {
+    value= qh_strtod(s, &s);
+    if (++tokcount > dim) {
+      qh_fprintf(qh, qh->ferr, 7059, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
+          qh->feasible_string, dim);
+      break;
+    }
+    *(coords++)= value;
+    if (*s)
+      s++;
+  }
+  while (++tokcount <= dim)
+    *(coords++)= 0.0;
+} /* setfeasible */
+
+/*---------------------------------
+
+  qh_skipfacet(qh, facet )
+    returns 'True' if this facet is not to be printed
+
+  notes:
+    based on the user provided slice thresholds and 'good' specifications
+*/
+boolT qh_skipfacet(qhT *qh, facetT *facet) {
+  facetT *neighbor, **neighborp;
+
+  if (qh->PRINTneighbors) {
+    if (facet->good)
+      return !qh->PRINTgood;
+    FOREACHneighbor_(facet) {
+      if (neighbor->good)
+        return False;
+    }
+    return True;
+  }else if (qh->PRINTgood)
+    return !facet->good;
+  else if (!facet->normal)
+    return True;
+  return(!qh_inthresholds(qh, facet->normal, NULL));
+} /* skipfacet */
+
+/*---------------------------------
+
+  qh_skipfilename(qh, string )
+    returns pointer to character after filename
+
+  notes:
+    skips leading spaces
+    ends with spacing or eol
+    if starts with ' or " ends with the same, skipping \' or \"
+    For qhull, qh_argv_to_command() only uses double quotes
+*/
+char *qh_skipfilename(qhT *qh, char *filename) {
+  char *s= filename;  /* non-const due to return */
+  char c;
+
+  while (*s && isspace(*s))
+    s++;
+  c= *s++;
+  if (c == '\0') {
+    qh_fprintf(qh, qh->ferr, 6204, "qhull input error: filename expected, none found.\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  if (c == '\'' || c == '"') {
+    while (*s !=c || s[-1] == '\\') {
+      if (!*s) {
+        qh_fprintf(qh, qh->ferr, 6203, "qhull input error: missing quote after filename -- %s\n", filename);
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }
+      s++;
+    }
+    s++;
+  }
+  else while (*s && !isspace(*s))
+      s++;
+  return s;
+} /* skipfilename */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.h
new file mode 100644
index 00000000000..eb3c7514923
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/io_r.h
@@ -0,0 +1,166 @@
+/*
  ---------------------------------
+
+   io_r.h
+   declarations of Input/Output functions
+
+   see README, libqhull_r.h and io_r.c
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/io_r.h#3 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#ifndef qhDEFio
+#define qhDEFio 1
+
+#include "libqhull_r.h"
+
+/*============ constants and flags ==================*/
+
+/*----------------------------------
+
+  qh_MAXfirst
+    maximum length of first two lines of stdin
+*/
+#define qh_MAXfirst  200
+
+/*----------------------------------
+
+  qh_MINradius
+    min radius for Gp and Gv, fraction of maxcoord
+*/
+#define qh_MINradius 0.02
+
+/*----------------------------------
+
+  qh_GEOMepsilon
+    adjust outer planes for 'lines closer' and geomview roundoff.
+    This prevents bleed through.
+*/
+#define qh_GEOMepsilon 2e-3
+
+/*----------------------------------
+
+  qh_WHITESPACE
+    possible values of white space
+*/
+#define qh_WHITESPACE " \n\t\v\r\f"
+
+
+/*----------------------------------
+
+  qh_RIDGE
+    to select which ridges to print in qh_eachvoronoi
+*/
+typedef enum
+{
+    qh_RIDGEall= 0, qh_RIDGEinner, qh_RIDGEouter
+}
+qh_RIDGE;
+
+/*----------------------------------
+
+  printvridgeT
+    prints results of qh_printvdiagram
+
+  see:
+    qh_printvridge for an example
+*/
+typedef void (*printvridgeT)(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+
+/*============== -prototypes in alphabetical order =========*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    qh_dfacet(qhT *qh, unsigned int id);
+void    qh_dvertex(qhT *qh, unsigned int id);
+int     qh_compare_facetarea(const void *p1, const void *p2);
+int     qh_compare_facetvisit(const void *p1, const void *p2);
+int     qh_compare_nummerge(const void *p1, const void *p2);
+void    qh_copyfilename(qhT *qh, char *filename, int size, const char* source, int length);
+void    qh_countfacets(qhT *qh, facetT *facetlist, setT *facets, boolT printall,
+              int *numfacetsp, int *numsimplicialp, int *totneighborsp,
+              int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
+pointT *qh_detvnorm(qhT *qh, vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
+setT   *qh_detvridge(qhT *qh, vertexT *vertex);
+setT   *qh_detvridge3(qhT *qh, vertexT *atvertex, vertexT *vertex);
+int     qh_eachvoronoi(qhT *qh, FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
+int     qh_eachvoronoi_all(qhT *qh, FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder);
+void    qh_facet2point(qhT *qh, facetT *facet, pointT **point0, pointT **point1, realT *mindist);
+setT   *qh_facetvertices(qhT *qh, facetT *facetlist, setT *facets, boolT allfacets);
+void    qh_geomplanes(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane);
+void    qh_markkeep(qhT *qh, facetT *facetlist);
+setT   *qh_markvoronoi(qhT *qh, facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp);
+void    qh_order_vertexneighbors(qhT *qh, vertexT *vertex);
+void    qh_prepare_output(qhT *qh);
+void    qh_printafacet(qhT *qh, FILE *fp, qh_PRINT format, facetT *facet, boolT printall);
+void    qh_printbegin(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printcenter(qhT *qh, FILE *fp, qh_PRINT format, const char *string, facetT *facet);
+void    qh_printcentrum(qhT *qh, FILE *fp, facetT *facet, realT radius);
+void    qh_printend(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printend4geom(qhT *qh, FILE *fp, facetT *facet, int *num, boolT printall);
+void    qh_printextremes(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printextremes_2d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printextremes_d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printfacet(qhT *qh, FILE *fp, facetT *facet);
+void    qh_printfacet2math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
+void    qh_printfacet2geom(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet2geom_points(qhT *qh, FILE *fp, pointT *point1, pointT *point2,
+                               facetT *facet, realT offset, realT color[3]);
+void    qh_printfacet3math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
+void    qh_printfacet3geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet3geom_points(qhT *qh, FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
+void    qh_printfacet3geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet3vertex(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format);
+void    qh_printfacet4geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet4geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacetNvertex_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, int id, qh_PRINT format);
+void    qh_printfacetNvertex_simplicial(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format);
+void    qh_printfacetheader(qhT *qh, FILE *fp, facetT *facet);
+void    qh_printfacetridges(qhT *qh, FILE *fp, facetT *facet);
+void    qh_printfacets(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printhyperplaneintersection(qhT *qh, FILE *fp, facetT *facet1, facetT *facet2,
+                   setT *vertices, realT color[3]);
+void    qh_printline3geom(qhT *qh, FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
+void    qh_printneighborhood(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
+void    qh_printpoint(qhT *qh, FILE *fp, const char *string, pointT *point);
+void    qh_printpointid(qhT *qh, FILE *fp, const char *string, int dim, pointT *point, int id);
+void    qh_printpoint3(qhT *qh, FILE *fp, pointT *point);
+void    qh_printpoints_out(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printpointvect(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
+void    qh_printpointvect2(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
+void    qh_printridge(qhT *qh, FILE *fp, ridgeT *ridge);
+void    qh_printspheres(qhT *qh, FILE *fp, setT *vertices, realT radius);
+void    qh_printvdiagram(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+int     qh_printvdiagram2(qhT *qh, FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
+void    qh_printvertex(qhT *qh, FILE *fp, vertexT *vertex);
+void    qh_printvertexlist(qhT *qh, FILE *fp, const char* string, facetT *facetlist,
+                         setT *facets, boolT printall);
+void    qh_printvertices(qhT *qh, FILE *fp, const char* string, setT *vertices);
+void    qh_printvneighbors(qhT *qh, FILE *fp, facetT* facetlist, setT *facets, boolT printall);
+void    qh_printvoronoi(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printvnorm(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void    qh_printvridge(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void    qh_produce_output(qhT *qh);
+void    qh_produce_output2(qhT *qh);
+void    qh_projectdim3(qhT *qh, pointT *source, pointT *destination);
+int     qh_readfeasible(qhT *qh, int dim, const char *curline);
+coordT *qh_readpoints(qhT *qh, int *numpoints, int *dimension, boolT *ismalloc);
+void    qh_setfeasible(qhT *qh, int dim);
+boolT   qh_skipfacet(qhT *qh, facetT *facet);
+char   *qh_skipfilename(qhT *qh, char *filename);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFio */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.c
new file mode 100644
index 00000000000..0d41d7be053
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.c
@@ -0,0 +1,1754 @@
+/*
  ---------------------------------
+
+   libqhull_r.c
+   Quickhull algorithm for convex hulls
+
+   qhull() and top-level routines
+
+   see qh-qhull_r.htm, libqhull_r.h, unix_r.c
+
+   see qhull_ra.h for internal functions
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/libqhull_r.c#17 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#include "qhull_ra.h"
+
+/*============= functions in alphabetic order after qhull() =======*/
+
+/*---------------------------------
+
+  qh_qhull(qh)
+    compute DIM3 convex hull of qh.num_points starting at qh.first_point
+    qh->contains all global options and variables
+
+  returns:
+    returns polyhedron
+      qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices,
+
+    returns global variables
+      qh.hulltime, qh.max_outside, qh.interior_point, qh.max_vertex, qh.min_vertex
+
+    returns precision constants
+      qh.ANGLEround, centrum_radius, cos_max, DISTround, MAXabs_coord, ONEmerge
+
+  notes:
+    unless needed for output
+      qh.max_vertex and qh.min_vertex are max/min due to merges
+
+  see:
+    to add individual points to either qh.num_points
+      use qh_addpoint()
+
+    if qh.GETarea
+      qh_produceoutput() returns qh.totarea and qh.totvol via qh_getarea()
+
+  design:
+    record starting time
+    initialize hull and partition points
+    build convex hull
+    unless early termination
+      update facet->maxoutside for vertices, coplanar, and near-inside points
+    error if temporary sets exist
+    record end time
+*/
+
+void qh_qhull(qhT *qh) {
+  int numoutside;
+
+  qh->hulltime= qh_CPUclock;
+  if (qh->RERUN || qh->JOGGLEmax < REALmax/2)
+    qh_build_withrestart(qh);
+  else {
+    qh_initbuild(qh);
+    qh_buildhull(qh);
+  }
+  if (!qh->STOPadd && !qh->STOPcone && !qh->STOPpoint) {
+    if (qh->ZEROall_ok && !qh->TESTvneighbors && qh->MERGEexact)
+      qh_checkzero(qh, qh_ALL);
+    if (qh->ZEROall_ok && !qh->TESTvneighbors && !qh->WAScoplanar) {
+      trace2((qh, qh->ferr, 2055, "qh_qhull: all facets are clearly convex and no coplanar points.  Post-merging and check of maxout not needed.\n"));
+      qh->DOcheckmax= False;
+    }else {
+      qh_initmergesets(qh /* qh.facet_mergeset,degen_mergeset,vertex_mergeset */);
+      if (qh->MERGEexact || (qh->hull_dim > qh_DIMreduceBuild && qh->PREmerge))
+        qh_postmerge(qh, "First post-merge", qh->premerge_centrum, qh->premerge_cos,
+             (qh->POSTmerge ? False : qh->TESTvneighbors)); /* calls qh_reducevertices */
+      else if (!qh->POSTmerge && qh->TESTvneighbors)
+        qh_postmerge(qh, "For testing vertex neighbors", qh->premerge_centrum,
+             qh->premerge_cos, True);                       /* calls qh_test_vneighbors */
+      if (qh->POSTmerge)
+        qh_postmerge(qh, "For post-merging", qh->postmerge_centrum,
+             qh->postmerge_cos, qh->TESTvneighbors);
+      if (qh->visible_list == qh->facet_list) {            /* qh_postmerge was called */
+        qh->findbestnew= True;
+        qh_partitionvisible(qh, !qh_ALL, &numoutside /* qh.visible_list */);
+        qh->findbestnew= False;
+        qh_deletevisible(qh /* qh.visible_list */);        /* stops at first !f.visible */
+        qh_resetlists(qh, False, qh_RESETvisible /* qh.visible_list newvertex_list qh.newfacet_list */);
+      }
+      qh_all_vertexmerges(qh, -1, NULL, NULL);
+      qh_freemergesets(qh);
+    }
+    if (qh->TRACEpoint == qh_IDunknown && qh->TRACElevel > qh->IStracing) {
+      qh->IStracing= qh->TRACElevel;
+      qh_fprintf(qh, qh->ferr, 2112, "qh_qhull: finished qh_buildhull and qh_postmerge, start tracing (TP-1)\n");
+    }
+    if (qh->DOcheckmax){
+      if (qh->REPORTfreq) {
+        qh_buildtracing(qh, NULL, NULL);
+        qh_fprintf(qh, qh->ferr, 8115, "\nTesting all coplanar points.\n");
+      }
+      qh_check_maxout(qh);
+    }
+    if (qh->KEEPnearinside && !qh->maxoutdone)
+      qh_nearcoplanar(qh);
+  }
+  if (qh_setsize(qh, qh->qhmem.tempstack) != 0) {
+    qh_fprintf(qh, qh->ferr, 6164, "qhull internal error (qh_qhull): temporary sets not empty(%d) at end of Qhull\n",
+             qh_setsize(qh, qh->qhmem.tempstack));
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh->hulltime= qh_CPUclock - qh->hulltime;
+  qh->QHULLfinished= True;
+  trace1((qh, qh->ferr, 1036, "Qhull: algorithm completed\n"));
+} /* qhull */
+
+/*---------------------------------
+
+  qh_addpoint(qh, furthest, facet, checkdist )
+    add point (usually furthest point) above facet to hull
+    if checkdist,
+      check that point is above facet.
+      if point is not outside of the hull, uses qh_partitioncoplanar()
+      assumes that facet is defined by qh_findbestfacet()
+    else if facet specified,
+      assumes that point is above facet (major damage if below)
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    returns False if user requested an early termination
+      qh.visible_list, newfacet_list, delvertex_list, NEWfacets may be defined
+    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
+    clear qh.maxoutdone (will need to call qh_check_maxout() for facet->maxoutside)
+    if unknown point, adds a pointer to qh.other_points
+      do not deallocate the point's coordinates
+
+  notes:
+    called from qh_initbuild, qh_buildhull, and qh_addpoint
+    tail recursive call if merged a pinchedvertex due to a duplicated ridge
+      no more than qh.num_vertices calls (QH6296)
+    assumes point is near its best facet and not at a local minimum of a lens
+      distributions.  Use qh_findbestfacet to avoid this case.
+    uses qh.visible_list, qh.newfacet_list, qh.delvertex_list, qh.NEWfacets
+    if called from a user application after qh_qhull and 'QJ' (joggle),
+      facet merging for precision problems is disabled by default
+
+  design:
+    exit if qh.STOPadd vertices 'TAn'
+    add point to other_points if needed
+    if checkdist
+      if point not above facet
+        partition coplanar point
+        exit
+    exit if pre STOPpoint requested
+    find horizon and visible facets for point
+    build cone of new facets to the horizon
+    exit if build cone fails due to qh.ONLYgood
+    tail recursive call if build cone fails due to pinched vertices
+    exit if STOPcone requested
+    merge non-convex new facets
+    if merge found, many merges, or 'Qf'
+       use qh_findbestnew() instead of qh_findbest()
+    partition outside points from visible facets
+    delete visible facets
+    check polyhedron if requested
+    exit if post STOPpoint requested
+    reset working lists of facets and vertices
+*/
+boolT qh_addpoint(qhT *qh, pointT *furthest, facetT *facet, boolT checkdist) {
+  realT dist, pbalance;
+  facetT *replacefacet, *newfacet;
+  vertexT *apex;
+  boolT isoutside= False;
+  int numpart, numpoints, goodvisible, goodhorizon, apexpointid;
+
+  qh->maxoutdone= False;
+  if (qh_pointid(qh, furthest) == qh_IDunknown)
+    qh_setappend(qh, &qh->other_points, furthest);
+  if (!facet) {
+    qh_fprintf(qh, qh->ferr, 6213, "qhull internal error (qh_addpoint): NULL facet.  Need to call qh_findbestfacet first\n");
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh_detmaxoutside(qh);
+  if (checkdist) {
+    facet= qh_findbest(qh, furthest, facet, !qh_ALL, !qh_ISnewfacets, !qh_NOupper,
+                        &dist, &isoutside, &numpart);
+    zzadd_(Zpartition, numpart);
+    if (!isoutside) {
+      zinc_(Znotmax);  /* last point of outsideset is no longer furthest. */
+      facet->notfurthest= True;
+      qh_partitioncoplanar(qh, furthest, facet, &dist, qh->findbestnew);
+      return True;
+    }
+  }
+  qh_buildtracing(qh, furthest, facet);
+  if (qh->STOPpoint < 0 && qh->furthest_id == -qh->STOPpoint-1) {
+    facet->notfurthest= True;
+    return False;
+  }
+  qh_findhorizon(qh, furthest, facet, &goodvisible, &goodhorizon);
+  if (qh->ONLYgood && !qh->GOODclosest && !(goodvisible+goodhorizon)) {
+    zinc_(Znotgood);
+    facet->notfurthest= True;
+    /* last point of outsideset is no longer furthest.  This is ok
+        since all points of the outside are likely to be bad */
+    qh_resetlists(qh, False, qh_RESETvisible /* qh.visible_list newvertex_list qh.newfacet_list */);
+    return True;
+  }
+  apex= qh_buildcone(qh, furthest, facet, goodhorizon, &replacefacet);
+  /* qh.newfacet_list, visible_list, newvertex_list */
+  if (!apex) {
+    if (qh->ONLYgood)
+      return True; /* ignore this furthest point, a good new facet was not found */
+    if (replacefacet) {
+      if (qh->retry_addpoint++ >= qh->num_vertices) {
+        qh_fprintf(qh, qh->ferr, 6296, "qhull internal error (qh_addpoint): infinite loop (%d retries) of merging pinched vertices due to dupridge for point p%d, facet f%d, and %d vertices\n",
+          qh->retry_addpoint, qh_pointid(qh, furthest), facet->id, qh->num_vertices);
+        qh_errexit(qh, qh_ERRqhull, facet, NULL);
+      }
+      /* retry qh_addpoint after resolving a dupridge via qh_merge_pinchedvertices */
+      return qh_addpoint(qh, furthest, replacefacet, True /* checkdisk */);
+    }
+    qh->retry_addpoint= 0;
+    return True; /* ignore this furthest point, resolved a dupridge by making furthest a coplanar point */
+  }
+  if (qh->retry_addpoint) {
+    zinc_(Zretryadd);
+    zadd_(Zretryaddtot, qh->retry_addpoint);
+    zmax_(Zretryaddmax, qh->retry_addpoint);
+    qh->retry_addpoint= 0;
+  }
+  apexpointid= qh_pointid(qh, apex->point);
+  zzinc_(Zprocessed);
+  if (qh->STOPcone && qh->furthest_id == qh->STOPcone-1) {
+    facet->notfurthest= True;
+    return False;  /* visible_list etc. still defined */
+  }
+  qh->findbestnew= False;
+  if (qh->PREmerge || qh->MERGEexact) {
+    qh_initmergesets(qh /* qh.facet_mergeset,degen_mergeset,vertex_mergeset */);
+    qh_premerge(qh, apexpointid, qh->premerge_centrum, qh->premerge_cos /* qh.newfacet_list */);
+    if (qh_USEfindbestnew)
+      qh->findbestnew= True;
+    else {
+      FORALLnew_facets {
+        if (!newfacet->simplicial) {
+          qh->findbestnew= True;  /* use qh_findbestnew instead of qh_findbest*/
+          break;
+        }
+      }
+    }
+  }else if (qh->BESToutside)
+    qh->findbestnew= True;
+  if (qh->IStracing >= 4)
+    qh_checkpolygon(qh, qh->visible_list);
+  qh_partitionvisible(qh, !qh_ALL, &numpoints /* qh.visible_list */);
+  qh->findbestnew= False;
+  qh->findbest_notsharp= False;
+  zinc_(Zpbalance);
+  pbalance= numpoints - (realT) qh->hull_dim /* assumes all points extreme */
+                * (qh->num_points - qh->num_vertices)/qh->num_vertices;
+  wadd_(Wpbalance, pbalance);
+  wadd_(Wpbalance2, pbalance * pbalance);
+  qh_deletevisible(qh /* qh.visible_list */);
+  zmax_(Zmaxvertex, qh->num_vertices);
+  qh->NEWfacets= False;
+  if (qh->IStracing >= 4) {
+    if (qh->num_facets < 200)
+      qh_printlists(qh);
+    qh_printfacetlist(qh, qh->newfacet_list, NULL, True);
+    qh_checkpolygon(qh, qh->facet_list);
+  }else if (qh->CHECKfrequently) {
+    if (qh->num_facets < 1000)
+      qh_checkpolygon(qh, qh->facet_list);
+    else
+      qh_checkpolygon(qh, qh->newfacet_list);
+  }
+  if (qh->STOPpoint > 0 && qh->furthest_id == qh->STOPpoint-1 && qh_setsize(qh, qh->vertex_mergeset) > 0)
+    return False;
+  qh_resetlists(qh, True, qh_RESETvisible /* qh.visible_list newvertex_list qh.newfacet_list */);
+  if (qh->facet_mergeset) {
+    /* vertex merges occur after facet merges (qh_premerge) and qh_resetlists */
+    qh_all_vertexmerges(qh, apexpointid, NULL, NULL);
+    qh_freemergesets(qh);
+  }
+  /* qh_triangulate(qh); to test qh.TRInormals */
+  if (qh->STOPpoint > 0 && qh->furthest_id == qh->STOPpoint-1)
+    return False;
+  trace2((qh, qh->ferr, 2056, "qh_addpoint: added p%d to convex hull with point balance %2.2g\n",
+    qh_pointid(qh, furthest), pbalance));
+  return True;
+} /* addpoint */
+
+/*---------------------------------
+
+  qh_build_withrestart(qh)
+    allow restarts due to qh.JOGGLEmax while calling qh_buildhull()
+       qh_errexit always undoes qh_build_withrestart()
+    qh.FIRSTpoint/qh.NUMpoints is point array
+       it may be moved by qh_joggleinput
+*/
+void qh_build_withrestart(qhT *qh) {
+  int restart;
+  vertexT *vertex, **vertexp;
+
+  qh->ALLOWrestart= True;
+  while (True) {
+    restart= setjmp(qh->restartexit); /* simple statement for CRAY J916 */
+    if (restart) {       /* only from qh_joggle_restart() */
+      qh->last_errcode= qh_ERRnone;
+      zzinc_(Zretry);
+      wmax_(Wretrymax, qh->JOGGLEmax);
+      /* QH7078 warns about using 'TCn' with 'QJn' */
+      qh->STOPcone= qh_IDunknown; /* if break from joggle, prevents normal output */
+      FOREACHvertex_(qh->del_vertices) {
+        if (vertex->point && !vertex->partitioned)
+          vertex->partitioned= True; /* avoid error in qh_freebuild -> qh_delvertex */
+      }
+    }
+    if (!qh->RERUN && qh->JOGGLEmax < REALmax/2) {
+      if (qh->build_cnt > qh_JOGGLEmaxretry) {
+        qh_fprintf(qh, qh->ferr, 6229, "qhull input error: %d attempts to construct a convex hull with joggled input.  Increase joggle above 'QJ%2.2g' or modify qh_JOGGLE... parameters in user_r.h\n",
+           qh->build_cnt, qh->JOGGLEmax);
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }
+      if (qh->build_cnt && !restart)
+        break;
+    }else if (qh->build_cnt && qh->build_cnt >= qh->RERUN)
+      break;
+    qh->STOPcone= 0;
+    qh_freebuild(qh, True);  /* first call is a nop */
+    qh->build_cnt++;
+    if (!qh->qhull_optionsiz)
+      qh->qhull_optionsiz= (int)strlen(qh->qhull_options);   /* WARN64 */
+    else {
+      qh->qhull_options[qh->qhull_optionsiz]= '\0';
+      qh->qhull_optionlen= qh_OPTIONline;  /* starts a new line */
+    }
+    qh_option(qh, "_run", &qh->build_cnt, NULL);
+    if (qh->build_cnt == qh->RERUN) {
+      qh->IStracing= qh->TRACElastrun;  /* duplicated from qh_initqhull_globals */
+      if (qh->TRACEpoint != qh_IDnone || qh->TRACEdist < REALmax/2 || qh->TRACEmerge) {
+        qh->TRACElevel= (qh->IStracing? qh->IStracing : 3);
+        qh->IStracing= 0;
+      }
+      qh->qhmem.IStracing= qh->IStracing;
+    }
+    if (qh->JOGGLEmax < REALmax/2)
+      qh_joggleinput(qh);
+    qh_initbuild(qh);
+    qh_buildhull(qh);
+    if (qh->JOGGLEmax < REALmax/2 && !qh->MERGING)
+      qh_checkconvex(qh, qh->facet_list, qh_ALGORITHMfault);
+  }
+  qh->ALLOWrestart= False;
+} /* qh_build_withrestart */
+
+/*---------------------------------
+
+  qh_buildcone(qh, furthest, facet, goodhorizon, &replacefacet )
+    build cone of new facets from furthest to the horizon
+    goodhorizon is count of good, horizon facets from qh_find_horizon
+
+  returns:
+    returns apex of cone with qh.newfacet_list and qh.first_newfacet (f.id)
+    returns NULL if qh.ONLYgood and no good facets
+    returns NULL and retryfacet if merging pinched vertices will resolve a dupridge
+      a horizon vertex was nearly adjacent to another vertex
+      will retry qh_addpoint
+    returns NULL if resolve a dupridge by making furthest a coplanar point
+      furthest was nearly adjacent to an existing vertex
+    updates qh.degen_mergeset (MRGridge) if resolve a dupridge by merging facets
+    updates qh.newfacet_list, visible_list, newvertex_list
+    updates qh.facet_list, vertex_list, num_facets, num_vertices
+
+  notes:
+    called by qh_addpoint
+    see qh_triangulate, it triangulates non-simplicial facets in post-processing
+
+  design:
+    make new facets for point to horizon
+    compute balance statistics
+    make hyperplanes for point
+    exit if qh.ONLYgood and not good (qh_buildcone_onlygood)
+    match neighboring new facets
+    if dupridges
+      exit if !qh.IGNOREpinched and dupridge resolved by coplanar furthest
+      retry qh_buildcone if !qh.IGNOREpinched and dupridge resolved by qh_buildcone_mergepinched
+      otherwise dupridges resolved by merging facets
+    update vertex neighbors and delete interior vertices
+*/
+vertexT *qh_buildcone(qhT *qh, pointT *furthest, facetT *facet, int goodhorizon, facetT **retryfacet) {
+  vertexT *apex;
+  realT newbalance;
+  int numnew;
+
+  *retryfacet= NULL;
+  qh->first_newfacet= qh->facet_id;
+  qh->NEWtentative= (qh->MERGEpinched || qh->ONLYgood); /* cleared by qh_attachnewfacets or qh_resetlists */
+  apex= qh_makenewfacets(qh, furthest /* qh.newfacet_list visible_list, attaches new facets if !qh.NEWtentative */);
+  numnew= (int)(qh->facet_id - qh->first_newfacet);
+  newbalance= numnew - (realT)(qh->num_facets - qh->num_visible) * qh->hull_dim / qh->num_vertices;
+  /* newbalance statistics updated below if the new facets are accepted */
+  if (qh->ONLYgood) { /* qh.MERGEpinched is false by QH6362 */
+    if (!qh_buildcone_onlygood(qh, apex, goodhorizon /* qh.newfacet_list */)) {
+      facet->notfurthest= True;
+      return NULL;
+    }
+  }else if(qh->MERGEpinched) {
+#ifndef qh_NOmerge
+    if (qh_buildcone_mergepinched(qh, apex, facet, retryfacet /* qh.newfacet_list */))
+      return NULL;
+#else
+    qh_fprintf(qh, qh->ferr, 6375, "qhull option error (qh_buildcone): option 'Q14' (qh.MERGEpinched) is not available due to qh_NOmerge\n");
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+#endif
+  }else {
+    /* qh_makenewfacets attached new facets to the horizon */
+    qh_matchnewfacets(qh); /* ignore returned value.  qh_forcedmerges will merge dupridges if any */
+    qh_makenewplanes(qh /* qh.newfacet_list */);
+    qh_update_vertexneighbors_cone(qh);
+  }
+  wadd_(Wnewbalance, newbalance);
+  wadd_(Wnewbalance2, newbalance * newbalance);
+  trace2((qh, qh->ferr, 2067, "qh_buildcone: created %d newfacets for p%d(v%d) new facet balance %2.2g\n",
+    numnew, qh_pointid(qh, furthest), apex->id, newbalance));
+  return apex;
+} /* buildcone */
+
+#ifndef qh_NOmerge
+/*---------------------------------
+
+  qh_buildcone_mergepinched(qh, apex, facet, maxdupdist, &retryfacet )
+    build cone of new facets from furthest to the horizon
+    maxdupdist>0.0 for merging dupridges (qh_matchdupridge)
+
+  returns:
+    returns True if merged a pinched vertex and deleted the cone of new facets
+      if retryfacet is set
+        a dupridge was resolved by qh_merge_pinchedvertices
+        retry qh_addpoint
+      otherwise
+        apex/furthest was partitioned as a coplanar point
+        ignore this furthest point
+    returns False if no dupridges or if dupridges will be resolved by MRGridge
+    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
+
+  notes:
+    only called from qh_buildcone with qh.MERGEpinched
+
+  design:
+    match neighboring new facets
+    if matching detected dupridges with a wide merge (qh_RATIOtrypinched)
+      if pinched vertices (i.e., nearly adjacent)
+        delete the cone of new facets
+        delete the apex and reset the facet lists
+        if coplanar, pinched apex
+          partition the apex as a coplanar point
+        else
+           repeatedly merge the nearest pair of pinched vertices and subsequent facet merges
+        return True
+      otherwise
+        MRGridge are better than vertex merge, but may report an error
+    attach new facets
+    make hyperplanes for point
+    update vertex neighbors and delete interior vertices
+*/
+boolT qh_buildcone_mergepinched(qhT *qh, vertexT *apex, facetT *facet, facetT **retryfacet) {
+  facetT *newfacet, *nextfacet;
+  pointT *apexpoint;
+  coordT maxdupdist;
+  int apexpointid;
+  boolT iscoplanar;
+
+  *retryfacet= NULL;
+  maxdupdist= qh_matchnewfacets(qh);
+  if (maxdupdist > qh_RATIOtrypinched * qh->ONEmerge) { /* one or more dupridges with a wide merge */
+    if (qh->IStracing >= 4 && qh->num_facets < 1000)
+      qh_printlists(qh);
+    qh_initmergesets(qh /* qh.facet_mergeset,degen_mergeset,vertex_mergeset */);
+    if (qh_getpinchedmerges(qh, apex, maxdupdist, &iscoplanar /* qh.newfacet_list, qh.vertex_mergeset */)) {
+      for (newfacet=qh->newfacet_list; newfacet && newfacet->next; newfacet= nextfacet) {
+        nextfacet= newfacet->next;
+        qh_delfacet(qh, newfacet);
+      }
+      apexpoint= apex->point;
+      apexpointid= qh_pointid(qh, apexpoint);
+      qh_delvertex(qh, apex);
+      qh_resetlists(qh, False, qh_RESETvisible /* qh.visible_list newvertex_list qh.newfacet_list */);
+      if (iscoplanar) {
+        zinc_(Zpinchedapex);
+        facet->notfurthest= True;
+        qh_partitioncoplanar(qh, apexpoint, facet, NULL, qh->findbestnew);
+      }else {
+        qh_all_vertexmerges(qh, apexpointid, facet, retryfacet);
+      }
+      qh_freemergesets(qh); /* errors if not empty */
+      return True;
+    }
+    /* MRGridge are better than vertex merge, but may report an error */
+    qh_freemergesets(qh);
+  }
+  qh_attachnewfacets(qh /* qh.visible_list */);
+  qh_makenewplanes(qh /* qh.newfacet_list */);
+  qh_update_vertexneighbors_cone(qh);
+  return False;
+} /* buildcone_mergepinched */
+#endif /* !qh_NOmerge */
+
+/*---------------------------------
+
+  qh_buildcone_onlygood(qh, apex, goodhorizon )
+    build cone of good, new facets from apex and its qh.newfacet_list to the horizon
+    goodhorizon is count of good, horizon facets from qh_find_horizon
+
+  returns:
+    False if a f.good facet or a qh.GOODclosest facet is not found
+    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
+
+  notes:
+    called from qh_buildcone
+    QH11030 FIX: Review effect of qh.GOODclosest on qh_buildcone_onlygood ('Qg').  qh_findgood preserves old value if didn't find a good facet.  See qh_findgood_all for disabling
+
+  design:
+    make hyperplanes for point
+    if qh_findgood fails to find a f.good facet or a qh.GOODclosest facet
+      delete cone of new facets
+      return NULL (ignores apex)
+    else
+      attach cone to horizon
+      match neighboring new facets
+*/
+boolT qh_buildcone_onlygood(qhT *qh, vertexT *apex, int goodhorizon) {
+  facetT *newfacet, *nextfacet;
+
+  qh_makenewplanes(qh /* qh.newfacet_list */);
+  if(qh_findgood(qh, qh->newfacet_list, goodhorizon) == 0) {
+    if (!qh->GOODclosest) {
+      for (newfacet=qh->newfacet_list; newfacet && newfacet->next; newfacet= nextfacet) {
+        nextfacet= newfacet->next;
+        qh_delfacet(qh, newfacet);
+      }
+      qh_delvertex(qh, apex);
+      qh_resetlists(qh, False /*no stats*/, qh_RESETvisible /* qh.visible_list newvertex_list qh.newfacet_list */);
+      zinc_(Znotgoodnew);
+      /* !good outside points dropped from hull */
+      return False;
+    }
+  }
+  qh_attachnewfacets(qh /* qh.visible_list */);
+  qh_matchnewfacets(qh); /* ignore returned value.  qh_forcedmerges will merge dupridges if any */
+  qh_update_vertexneighbors_cone(qh);
+  return True;
+} /* buildcone_onlygood */
+
+/*---------------------------------
+
+  qh_buildhull(qh)
+    construct a convex hull by adding outside points one at a time
+
+  returns:
+
+  notes:
+    may be called multiple times
+    checks facet and vertex lists for incorrect flags
+    to recover from STOPcone, call qh_deletevisible and qh_resetlists
+
+  design:
+    check visible facet and newfacet flags
+    check newfacet vertex flags and qh.STOPcone/STOPpoint
+    for each facet with a furthest outside point
+      add point to facet
+      exit if qh.STOPcone or qh.STOPpoint requested
+    if qh.NARROWhull for initial simplex
+      partition remaining outside points to coplanar sets
+*/
+void qh_buildhull(qhT *qh) {
+  facetT *facet;
+  pointT *furthest;
+  vertexT *vertex;
+  int id;
+
+  trace1((qh, qh->ferr, 1037, "qh_buildhull: start build hull\n"));
+  FORALLfacets {
+    if (facet->visible || facet->newfacet) {
+      qh_fprintf(qh, qh->ferr, 6165, "qhull internal error (qh_buildhull): visible or new facet f%d in facet list\n",
+                   facet->id);
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+  }
+  FORALLvertices {
+    if (vertex->newfacet) {
+      qh_fprintf(qh, qh->ferr, 6166, "qhull internal error (qh_buildhull): new vertex f%d in vertex list\n",
+                   vertex->id);
+      qh_errprint(qh, "ERRONEOUS", NULL, NULL, NULL, vertex);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+    id= qh_pointid(qh, vertex->point);
+    if ((qh->STOPpoint>0 && id == qh->STOPpoint-1) ||
+        (qh->STOPpoint<0 && id == -qh->STOPpoint-1) ||
+        (qh->STOPcone>0 && id == qh->STOPcone-1)) {
+      trace1((qh, qh->ferr, 1038,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
+      return;
+    }
+  }
+  qh->facet_next= qh->facet_list;      /* advance facet when processed */
+  while ((furthest= qh_nextfurthest(qh, &facet))) {
+    qh->num_outside--;  /* if ONLYmax, furthest may not be outside */
+    if (qh->STOPadd>0 && (qh->num_vertices - qh->hull_dim - 1 >= qh->STOPadd - 1)) {
+      trace1((qh, qh->ferr, 1059, "qh_buildhull: stop after adding %d vertices\n", qh->STOPadd-1));
+      return;
+    }
+    if (!qh_addpoint(qh, furthest, facet, qh->ONLYmax))
+      break;
+  }
+  if (qh->NARROWhull) /* move points from outsideset to coplanarset */
+    qh_outcoplanar(qh /* facet_list */ );
+  if (qh->num_outside && !furthest) {
+    qh_fprintf(qh, qh->ferr, 6167, "qhull internal error (qh_buildhull): %d outside points were never processed.\n", qh->num_outside);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  trace1((qh, qh->ferr, 1039, "qh_buildhull: completed the hull construction\n"));
+} /* buildhull */
+
+
+/*---------------------------------
+
+  qh_buildtracing(qh, furthest, facet )
+    trace an iteration of qh_buildhull() for furthest point and facet
+    if !furthest, prints progress message
+
+  returns:
+    tracks progress with qh.lastreport, lastcpu, lastfacets, lastmerges, lastplanes, lastdist
+    updates qh.furthest_id (-3 if furthest is NULL)
+    also resets visit_id, vertext_visit on wrap around
+
+  see:
+    qh_tracemerging()
+
+  design:
+    if !furthest
+      print progress message
+      exit
+    if 'TFn' iteration
+      print progress message
+    else if tracing
+      trace furthest point and facet
+    reset qh.visit_id and qh.vertex_visit if overflow may occur
+    set qh.furthest_id for tracing
+*/
+void qh_buildtracing(qhT *qh, pointT *furthest, facetT *facet) {
+  realT dist= 0;
+  double cpu;
+  int total, furthestid;
+  time_t timedata;
+  struct tm *tp;
+  vertexT *vertex;
+
+  qh->old_randomdist= qh->RANDOMdist;
+  qh->RANDOMdist= False;
+  if (!furthest) {
+    time(&timedata);
+    tp= localtime(&timedata);
+    cpu= (double)qh_CPUclock - (double)qh->hulltime;
+    cpu /= (double)qh_SECticks;
+    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+    qh_fprintf(qh, qh->ferr, 8118, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices.  Last point was p%d\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh->facet_id -1,
+      total, qh->num_facets, qh->num_vertices, qh->furthest_id);
+    return;
+  }
+  furthestid= qh_pointid(qh, furthest);
+#ifndef qh_NOtrace
+  if (qh->TRACEpoint == furthestid) {
+    trace1((qh, qh->ferr, 1053, "qh_buildtracing: start trace T%d for point TP%d above facet f%d\n", qh->TRACElevel, furthestid, facet->id));
+    qh->IStracing= qh->TRACElevel;
+    qh->qhmem.IStracing= qh->TRACElevel;
+  }else if (qh->TRACEpoint != qh_IDnone && qh->TRACEdist < REALmax/2) {
+    qh->IStracing= 0;
+    qh->qhmem.IStracing= 0;
+  }
+#endif
+  if (qh->REPORTfreq && (qh->facet_id-1 > qh->lastreport + (unsigned int)qh->REPORTfreq)) {
+    qh->lastreport= qh->facet_id-1;
+    time(&timedata);
+    tp= localtime(&timedata);
+    cpu= (double)qh_CPUclock - (double)qh->hulltime;
+    cpu /= (double)qh_SECticks;
+    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+    zinc_(Zdistio);
+    qh_distplane(qh, furthest, facet, &dist);
+    qh_fprintf(qh, qh->ferr, 8119, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices.  There are %d\n\
+ outside points.  Next is point p%d(v%d), %2.2g above f%d.\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh->facet_id -1,
+      total, qh->num_facets, qh->num_vertices, qh->num_outside+1,
+      furthestid, qh->vertex_id, dist, getid_(facet));
+  }else if (qh->IStracing >=1) {
+    cpu= (double)qh_CPUclock - (double)qh->hulltime;
+    cpu /= (double)qh_SECticks;
+    qh_distplane(qh, furthest, facet, &dist);
+    qh_fprintf(qh, qh->ferr, 1049, "qh_addpoint: add p%d(v%d) %2.2g above f%d to hull of %d facets, %d merges, %d outside at %4.4g CPU secs.  Previous p%d(v%d) delta %4.4g CPU, %d facets, %d merges, %d hyperplanes, %d distplanes, %d retries\n",
+      furthestid, qh->vertex_id, dist, getid_(facet), qh->num_facets, zzval_(Ztotmerge), qh->num_outside+1, cpu, qh->furthest_id, qh->vertex_id - 1,
+      cpu - qh->lastcpu, qh->num_facets - qh->lastfacets,  zzval_(Ztotmerge) - qh->lastmerges, zzval_(Zsetplane) - qh->lastplanes, zzval_(Zdistplane) - qh->lastdist, qh->retry_addpoint);
+    qh->lastcpu= cpu;
+    qh->lastfacets= qh->num_facets;
+    qh->lastmerges= zzval_(Ztotmerge);
+    qh->lastplanes= zzval_(Zsetplane);
+    qh->lastdist= zzval_(Zdistplane);
+  }
+  zmax_(Zvisit2max, (int)qh->visit_id/2);
+  if (qh->visit_id > (unsigned int) INT_MAX) { /* 31 bits */
+    zinc_(Zvisit);
+    if (!qh_checklists(qh, qh->facet_list)) {
+      qh_fprintf(qh, qh->ferr, 6370, "qhull internal error: qh_checklists failed on reset of qh.visit_id %u\n", qh->visit_id);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+    qh->visit_id= 0;
+    FORALLfacets
+      facet->visitid= 0;
+  }
+  zmax_(Zvvisit2max, (int)qh->vertex_visit/2);
+  if (qh->vertex_visit > (unsigned int) INT_MAX) { /* 31 bits */
+    zinc_(Zvvisit);
+    if (qh->visit_id && !qh_checklists(qh, qh->facet_list)) {
+      qh_fprintf(qh, qh->ferr, 6371, "qhull internal error: qh_checklists failed on reset of qh.vertex_visit %u\n", qh->vertex_visit);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+    qh->vertex_visit= 0;
+    FORALLvertices
+      vertex->visitid= 0;
+  }
+  qh->furthest_id= furthestid;
+  qh->RANDOMdist= qh->old_randomdist;
+} /* buildtracing */
+
+/*---------------------------------
+
+  qh_errexit2(qh, exitcode, facet, otherfacet )
+    return exitcode to system after an error
+    report two facets
+
+  returns:
+    assumes exitcode non-zero
+
+  see:
+    normally use qh_errexit() in user_r.c(reports a facet and a ridge)
+*/
+void qh_errexit2(qhT *qh, int exitcode, facetT *facet, facetT *otherfacet) {
+  qh->tracefacet= NULL;  /* avoid infinite recursion through qh_fprintf */
+  qh->traceridge= NULL;
+  qh->tracevertex= NULL;
+  qh_errprint(qh, "ERRONEOUS", facet, otherfacet, NULL, NULL);
+  qh_errexit(qh, exitcode, NULL, NULL);
+} /* errexit2 */
+
+
+/*---------------------------------
+
+  qh_findhorizon(qh, point, facet, goodvisible, goodhorizon )
+    given a visible facet, find the point's horizon and visible facets
+    for all facets, !facet-visible
+
+  returns:
+    returns qh.visible_list/num_visible with all visible facets
+      marks visible facets with ->visible
+    updates count of good visible and good horizon facets
+    updates qh.max_outside, qh.max_vertex, facet->maxoutside
+
+  see:
+    similar to qh_delpoint()
+
+  design:
+    move facet to qh.visible_list at end of qh.facet_list
+    for all visible facets
+     for each unvisited neighbor of a visible facet
+       compute distance of point to neighbor
+       if point above neighbor
+         move neighbor to end of qh.visible_list
+       else if point is coplanar with neighbor
+         update qh.max_outside, qh.max_vertex, neighbor->maxoutside
+         mark neighbor coplanar (will create a samecycle later)
+         update horizon statistics
+*/
+void qh_findhorizon(qhT *qh, pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
+  facetT *neighbor, **neighborp, *visible;
+  int numhorizon= 0, coplanar= 0;
+  realT dist;
+
+  trace1((qh, qh->ferr, 1040, "qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(qh, point),facet->id));
+  *goodvisible= *goodhorizon= 0;
+  zinc_(Ztotvisible);
+  qh_removefacet(qh, facet);  /* visible_list at end of qh->facet_list */
+  qh_appendfacet(qh, facet);
+  qh->num_visible= 1;
+  if (facet->good)
+    (*goodvisible)++;
+  qh->visible_list= facet;
+  facet->visible= True;
+  facet->f.replace= NULL;
+  if (qh->IStracing >=4)
+    qh_errprint(qh, "visible", facet, NULL, NULL, NULL);
+  qh->visit_id++;
+  FORALLvisible_facets {
+    if (visible->tricoplanar && !qh->TRInormals) {
+      qh_fprintf(qh, qh->ferr, 6230, "qhull internal error (qh_findhorizon): does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit(qh, qh_ERRqhull, visible, NULL);
+    }
+    if (qh_setsize(qh, visible->neighbors) == 0) {
+      qh_fprintf(qh, qh->ferr, 6295, "qhull internal error (qh_findhorizon): visible facet f%d does not have neighbors\n", visible->id);
+      qh_errexit(qh, qh_ERRqhull, visible, NULL);
+    }
+    visible->visitid= qh->visit_id;
+    FOREACHneighbor_(visible) {
+      if (neighbor->visitid == qh->visit_id)
+        continue;
+      neighbor->visitid= qh->visit_id;
+      zzinc_(Znumvisibility);
+      qh_distplane(qh, point, neighbor, &dist);
+      if (dist > qh->MINvisible) {
+        zinc_(Ztotvisible);
+        qh_removefacet(qh, neighbor);  /* append to end of qh->visible_list */
+        qh_appendfacet(qh, neighbor);
+        neighbor->visible= True;
+        neighbor->f.replace= NULL;
+        qh->num_visible++;
+        if (neighbor->good)
+          (*goodvisible)++;
+        if (qh->IStracing >=4)
+          qh_errprint(qh, "visible", neighbor, NULL, NULL, NULL);
+      }else {
+        if (dist >= -qh->MAXcoplanar) {
+          neighbor->coplanarhorizon= True;
+          zzinc_(Zcoplanarhorizon);
+          qh_joggle_restart(qh, "coplanar horizon");
+          coplanar++;
+          if (qh->MERGING) {
+            if (dist > 0) {
+              maximize_(qh->max_outside, dist);
+              maximize_(qh->max_vertex, dist);
+#if qh_MAXoutside
+              maximize_(neighbor->maxoutside, dist);
+#endif
+            }else
+              minimize_(qh->min_vertex, dist);  /* due to merge later */
+          }
+          trace2((qh, qh->ferr, 2057, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh->MINvisible(%2.7g)\n",
+              qh_pointid(qh, point), neighbor->id, dist, qh->MINvisible));
+        }else
+          neighbor->coplanarhorizon= False;
+        zinc_(Ztothorizon);
+        numhorizon++;
+        if (neighbor->good)
+          (*goodhorizon)++;
+        if (qh->IStracing >=4)
+          qh_errprint(qh, "horizon", neighbor, NULL, NULL, NULL);
+      }
+    }
+  }
+  if (!numhorizon) {
+    qh_joggle_restart(qh, "empty horizon");
+    qh_fprintf(qh, qh->ferr, 6168, "qhull topology error (qh_findhorizon): empty horizon for p%d.  It was above all facets.\n", qh_pointid(qh, point));
+    if (qh->num_facets < 100) {
+      qh_printfacetlist(qh, qh->facet_list, NULL, True);
+    }
+    qh_errexit(qh, qh_ERRtopology, NULL, NULL);
+  }
+  trace1((qh, qh->ferr, 1041, "qh_findhorizon: %d horizon facets(good %d), %d visible(good %d), %d coplanar\n",
+       numhorizon, *goodhorizon, qh->num_visible, *goodvisible, coplanar));
+  if (qh->IStracing >= 4 && qh->num_facets < 100)
+    qh_printlists(qh);
+} /* findhorizon */
+
+/*---------------------------------
+
+  qh_joggle_restart(qh, reason )
+    if joggle ('QJn') and not merging, restart on precision and topology errors
+*/
+void qh_joggle_restart(qhT *qh, const char *reason) {
+
+  if (qh->JOGGLEmax < REALmax/2) {
+    if (qh->ALLOWrestart && !qh->PREmerge && !qh->MERGEexact) {
+      trace0((qh, qh->ferr, 26, "qh_joggle_restart: qhull restart because of %s\n", reason));
+      /* May be called repeatedly if qh->ALLOWrestart */
+      longjmp(qh->restartexit, qh_ERRprec);
+    }
+  }
+} /* qh_joggle_restart */
+
+/*---------------------------------
+
+  qh_nextfurthest(qh, visible )
+    returns next furthest point and visible facet for qh_addpoint()
+    starts search at qh.facet_next
+
+  returns:
+    removes furthest point from outside set
+    NULL if none available
+    advances qh.facet_next over facets with empty outside sets
+
+  design:
+    for each facet from qh.facet_next
+      if empty outside set
+        advance qh.facet_next
+      else if qh.NARROWhull
+        determine furthest outside point
+        if furthest point is not outside
+          advance qh.facet_next(point will be coplanar)
+    remove furthest point from outside set
+*/
+pointT *qh_nextfurthest(qhT *qh, facetT **visible) {
+  facetT *facet;
+  int size, idx, loopcount= 0;
+  realT randr, dist;
+  pointT *furthest;
+
+  while ((facet= qh->facet_next) != qh->facet_tail) {
+    if (!facet || loopcount++ > qh->num_facets) {
+      qh_fprintf(qh, qh->ferr, 6406, "qhull internal error (qh_nextfurthest): null facet or infinite loop detected for qh.facet_next f%d facet_tail f%d\n",
+        getid_(facet), getid_(qh->facet_tail));
+      qh_printlists(qh);
+      qh_errexit2(qh, qh_ERRqhull, facet, qh->facet_tail);
+    }
+    if (!facet->outsideset) {
+      qh->facet_next= facet->next;
+      continue;
+    }
+    SETreturnsize_(facet->outsideset, size);
+    if (!size) {
+      qh_setfree(qh, &facet->outsideset);
+      qh->facet_next= facet->next;
+      continue;
+    }
+    if (qh->NARROWhull) {
+      if (facet->notfurthest)
+        qh_furthestout(qh, facet);
+      furthest= (pointT *)qh_setlast(facet->outsideset);
+#if qh_COMPUTEfurthest
+      qh_distplane(qh, furthest, facet, &dist);
+      zinc_(Zcomputefurthest);
+#else
+      dist= facet->furthestdist;
+#endif
+      if (dist < qh->MINoutside) { /* remainder of outside set is coplanar for qh_outcoplanar */
+        qh->facet_next= facet->next;
+        continue;
+      }
+    }
+    if (!qh->RANDOMoutside && !qh->VIRTUALmemory) {
+      if (qh->PICKfurthest) {
+        qh_furthestnext(qh /* qh.facet_list */);
+        facet= qh->facet_next;
+      }
+      *visible= facet;
+      return ((pointT *)qh_setdellast(facet->outsideset));
+    }
+    if (qh->RANDOMoutside) {
+      int outcoplanar= 0;
+      if (qh->NARROWhull) {
+        FORALLfacets {
+          if (facet == qh->facet_next)
+            break;
+          if (facet->outsideset)
+            outcoplanar += qh_setsize(qh, facet->outsideset);
+        }
+      }
+      randr= qh_RANDOMint;
+      randr= randr/(qh_RANDOMmax+1);
+      randr= floor((qh->num_outside - outcoplanar) * randr);
+      idx= (int)randr;
+      FORALLfacet_(qh->facet_next) {
+        if (facet->outsideset) {
+          SETreturnsize_(facet->outsideset, size);
+          if (!size)
+            qh_setfree(qh, &facet->outsideset);
+          else if (size > idx) {
+            *visible= facet;
+            return ((pointT *)qh_setdelnth(qh, facet->outsideset, idx));
+          }else
+            idx -= size;
+        }
+      }
+      qh_fprintf(qh, qh->ferr, 6169, "qhull internal error (qh_nextfurthest): num_outside %d is too low\nby at least %d, or a random real %g >= 1.0\n",
+              qh->num_outside, idx+1, randr);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }else { /* VIRTUALmemory */
+      facet= qh->facet_tail->previous;
+      if (!(furthest= (pointT *)qh_setdellast(facet->outsideset))) {
+        if (facet->outsideset)
+          qh_setfree(qh, &facet->outsideset);
+        qh_removefacet(qh, facet);
+        qh_prependfacet(qh, facet, &qh->facet_list);
+        continue;
+      }
+      *visible= facet;
+      return furthest;
+    }
+  }
+  return NULL;
+} /* nextfurthest */
+
+/*---------------------------------
+
+  qh_partitionall(qh, vertices, points, numpoints )
+    partitions all points in points/numpoints to the outsidesets of facets
+    vertices= vertices in qh.facet_list(!partitioned)
+
+  returns:
+    builds facet->outsideset
+    does not partition qh.GOODpoint
+    if qh.ONLYgood && !qh.MERGING,
+      does not partition qh.GOODvertex
+
+  notes:
+    faster if qh.facet_list sorted by anticipated size of outside set
+
+  design:
+    initialize pointset with all points
+    remove vertices from pointset
+    remove qh.GOODpointp from pointset (unless it's qh.STOPcone or qh.STOPpoint)
+    for all facets
+      for all remaining points in pointset
+        compute distance from point to facet
+        if point is outside facet
+          remove point from pointset (by not reappending)
+          update bestpoint
+          append point or old bestpoint to facet's outside set
+      append bestpoint to facet's outside set (furthest)
+    for all points remaining in pointset
+      partition point into facets' outside sets and coplanar sets
+*/
+void qh_partitionall(qhT *qh, setT *vertices, pointT *points, int numpoints){
+  setT *pointset;
+  vertexT *vertex, **vertexp;
+  pointT *point, **pointp, *bestpoint;
+  int size, point_i, point_n, point_end, remaining, i, id;
+  facetT *facet;
+  realT bestdist= -REALmax, dist, distoutside;
+
+  trace1((qh, qh->ferr, 1042, "qh_partitionall: partition all points into outside sets\n"));
+  pointset= qh_settemp(qh, numpoints);
+  qh->num_outside= 0;
+  pointp= SETaddr_(pointset, pointT);
+  for (i=numpoints, point= points; i--; point += qh->hull_dim)
+    *(pointp++)= point;
+  qh_settruncate(qh, pointset, numpoints);
+  FOREACHvertex_(vertices) {
+    if ((id= qh_pointid(qh, vertex->point)) >= 0)
+      SETelem_(pointset, id)= NULL;
+  }
+  id= qh_pointid(qh, qh->GOODpointp);
+  if (id >=0 && qh->STOPcone-1 != id && -qh->STOPpoint-1 != id)
+    SETelem_(pointset, id)= NULL;
+  if (qh->GOODvertexp && qh->ONLYgood && !qh->MERGING) { /* matches qhull()*/
+    if ((id= qh_pointid(qh, qh->GOODvertexp)) >= 0)
+      SETelem_(pointset, id)= NULL;
+  }
+  if (!qh->BESToutside) {  /* matches conditional for qh_partitionpoint below */
+    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user_r.h */
+    zval_(Ztotpartition)= qh->num_points - qh->hull_dim - 1; /*misses GOOD... */
+    remaining= qh->num_facets;
+    point_end= numpoints;
+    FORALLfacets {
+      size= point_end/(remaining--) + 100;
+      facet->outsideset= qh_setnew(qh, size);
+      bestpoint= NULL;
+      point_end= 0;
+      FOREACHpoint_i_(qh, pointset) {
+        if (point) {
+          zzinc_(Zpartitionall);
+          qh_distplane(qh, point, facet, &dist);
+          if (dist < distoutside)
+            SETelem_(pointset, point_end++)= point;
+          else {
+            qh->num_outside++;
+            if (!bestpoint) {
+              bestpoint= point;
+              bestdist= dist;
+            }else if (dist > bestdist) {
+              qh_setappend(qh, &facet->outsideset, bestpoint);
+              bestpoint= point;
+              bestdist= dist;
+            }else
+              qh_setappend(qh, &facet->outsideset, point);
+          }
+        }
+      }
+      if (bestpoint) {
+        qh_setappend(qh, &facet->outsideset, bestpoint);
+#if !qh_COMPUTEfurthest
+        facet->furthestdist= bestdist;
+#endif
+      }else
+        qh_setfree(qh, &facet->outsideset);
+      qh_settruncate(qh, pointset, point_end);
+    }
+  }
+  /* if !qh->BESToutside, pointset contains points not assigned to outsideset */
+  if (qh->BESToutside || qh->MERGING || qh->KEEPcoplanar || qh->KEEPinside || qh->KEEPnearinside) {
+    qh->findbestnew= True;
+    FOREACHpoint_i_(qh, pointset) {
+      if (point)
+        qh_partitionpoint(qh, point, qh->facet_list);
+    }
+    qh->findbestnew= False;
+  }
+  zzadd_(Zpartitionall, zzval_(Zpartition));
+  zzval_(Zpartition)= 0;
+  qh_settempfree(qh, &pointset);
+  if (qh->IStracing >= 4)
+    qh_printfacetlist(qh, qh->facet_list, NULL, True);
+} /* partitionall */
+
+
+/*---------------------------------
+
+  qh_partitioncoplanar(qh, point, facet, dist, allnew )
+    partition coplanar point to a facet
+    dist is distance from point to facet
+    if dist NULL,
+      searches for bestfacet and does nothing if inside
+    if allnew (qh.findbestnew)
+      searches new facets instead of using qh_findbest()
+
+  returns:
+    qh.max_ouside updated
+    if qh.KEEPcoplanar or qh.KEEPinside
+      point assigned to best coplanarset
+    qh.repart_facetid==0 (for detecting infinite recursion via qh_partitionpoint)
+
+  notes:
+    facet->maxoutside is updated at end by qh_check_maxout
+
+  design:
+    if dist undefined
+      find best facet for point
+      if point sufficiently below facet (depends on qh.NEARinside and qh.KEEPinside)
+        exit
+    if keeping coplanar/nearinside/inside points
+      if point is above furthest coplanar point
+        append point to coplanar set (it is the new furthest)
+        update qh.max_outside
+      else
+        append point one before end of coplanar set
+    else if point is clearly outside of qh.max_outside and bestfacet->coplanarset
+    and bestfacet is more than perpendicular to facet
+      repartition the point using qh_findbest() -- it may be put on an outsideset
+    else
+      update qh.max_outside
+*/
+void qh_partitioncoplanar(qhT *qh, pointT *point, facetT *facet, realT *dist, boolT allnew) {
+  facetT *bestfacet;
+  pointT *oldfurthest;
+  realT bestdist, angle, nearest, dist2= 0.0;
+  int numpart= 0;
+  boolT isoutside, oldfindbest, repartition= False;
+
+  trace4((qh, qh->ferr, 4090, "qh_partitioncoplanar: partition coplanar point p%d starting with f%d dist? %2.2g, allnew? %d, gh.repart_facetid f%d\n",
+    qh_pointid(qh, point), facet->id, (dist ? *dist : 0.0), allnew, qh->repart_facetid));
+  qh->WAScoplanar= True;
+  if (!dist) {
+    if (allnew)
+      bestfacet= qh_findbestnew(qh, point, facet, &bestdist, qh_ALL, &isoutside, &numpart);
+    else
+      bestfacet= qh_findbest(qh, point, facet, qh_ALL, !qh_ISnewfacets, qh->DELAUNAY,
+                          &bestdist, &isoutside, &numpart);
+    zinc_(Ztotpartcoplanar);
+    zzadd_(Zpartcoplanar, numpart);
+    if (!qh->DELAUNAY && !qh->KEEPinside) { /*  for 'd', bestdist skips upperDelaunay facets */
+      if (qh->KEEPnearinside) {
+        if (bestdist < -qh->NEARinside) {
+          zinc_(Zcoplanarinside);
+          trace4((qh, qh->ferr, 4062, "qh_partitioncoplanar: point p%d is more than near-inside facet f%d dist %2.2g allnew? %d\n",
+                  qh_pointid(qh, point), bestfacet->id, bestdist, allnew));
+          qh->repart_facetid= 0;
+          return;
+        }
+      }else if (bestdist < -qh->MAXcoplanar) {
+          trace4((qh, qh->ferr, 4063, "qh_partitioncoplanar: point p%d is inside facet f%d dist %2.2g allnew? %d\n",
+                  qh_pointid(qh, point), bestfacet->id, bestdist, allnew));
+        zinc_(Zcoplanarinside);
+        qh->repart_facetid= 0;
+        return;
+      }
+    }
+  }else {
+    bestfacet= facet;
+    bestdist= *dist;
+  }
+  if(bestfacet->visible){
+    qh_fprintf(qh, qh->ferr, 6405, "qhull internal error (qh_partitioncoplanar): cannot partition coplanar p%d of f%d into visible facet f%d\n",
+        qh_pointid(qh, point), facet->id, bestfacet->id);
+    qh_errexit2(qh, qh_ERRqhull, facet, bestfacet);
+  }
+  if (bestdist > qh->max_outside) {
+    if (!dist && facet != bestfacet) { /* can't be recursive from qh_partitionpoint since facet != bestfacet */
+      zinc_(Zpartangle);
+      angle= qh_getangle(qh, facet->normal, bestfacet->normal);
+      if (angle < 0) {
+        nearest= qh_vertex_bestdist(qh, bestfacet->vertices);
+        /* typically due to deleted vertex and coplanar facets, e.g.,
+        RBOX 1000 s Z1 G1e-13 t1001185205 | QHULL Tv */
+        zinc_(Zpartcorner);
+        trace2((qh, qh->ferr, 2058, "qh_partitioncoplanar: repartition coplanar point p%d from f%d as an outside point above corner facet f%d dist %2.2g with angle %2.2g\n",
+          qh_pointid(qh, point), facet->id, bestfacet->id, bestdist, angle));
+        repartition= True;
+      }
+    }
+    if (!repartition) {
+      if (bestdist > qh->MAXoutside * qh_RATIOcoplanaroutside) {
+        nearest= qh_vertex_bestdist(qh, bestfacet->vertices);
+        if (facet->id == bestfacet->id) {
+          if (facet->id == qh->repart_facetid) {
+            qh_fprintf(qh, qh->ferr, 6404, "Qhull internal error (qh_partitioncoplanar): infinite loop due to recursive call to qh_partitionpoint.  Repartition point p%d from f%d as a outside point dist %2.2g nearest vertices %2.2g\n",
+              qh_pointid(qh, point), facet->id, bestdist, nearest);
+            qh_errexit(qh, qh_ERRqhull, facet, NULL);
+          }
+          qh->repart_facetid= facet->id; /* reset after call to qh_partitionpoint */
+        }
+        if (point == qh->coplanar_apex) {
+          /* otherwise may loop indefinitely, the point is well above a facet, yet near a vertex */
+          qh_fprintf(qh, qh->ferr, 6425, "Qhull topology error (qh_partitioncoplanar): can not repartition coplanar point p%d from f%d as outside point above f%d.  It previously failed to form a cone of facets, dist %2.2g, nearest vertices %2.2g\n",
+            qh_pointid(qh, point), facet->id, bestfacet->id, bestdist, nearest);
+          qh_errexit(qh, qh_ERRtopology, facet, NULL);
+        }
+        if (nearest < 2 * qh->MAXoutside * qh_RATIOcoplanaroutside) {
+          zinc_(Zparttwisted);
+          qh_fprintf(qh, qh->ferr, 7085, "Qhull precision warning: repartition coplanar point p%d from f%d as an outside point above twisted facet f%d dist %2.2g nearest vertices %2.2g\n",
+            qh_pointid(qh, point), facet->id, bestfacet->id, bestdist, nearest);
+        }else {
+          zinc_(Zparthidden);
+          qh_fprintf(qh, qh->ferr, 7086, "Qhull precision warning: repartition coplanar point p%d from f%d as an outside point above hidden facet f%d dist %2.2g nearest vertices %2.2g\n",
+            qh_pointid(qh, point), facet->id, bestfacet->id, bestdist, nearest);
+        }
+        repartition= True;
+      }
+    }
+    if (repartition) {
+      oldfindbest= qh->findbestnew;
+      qh->findbestnew= False;
+      qh_partitionpoint(qh, point, bestfacet);
+      qh->findbestnew= oldfindbest;
+      qh->repart_facetid= 0;
+      return;
+    }
+    qh->repart_facetid= 0;
+    qh->max_outside= bestdist;
+    if (bestdist > qh->TRACEdist || qh->IStracing >= 3) {
+      qh_fprintf(qh, qh->ferr, 3041, "qh_partitioncoplanar: == p%d from f%d increases qh.max_outside to %2.2g of f%d last p%d\n",
+                     qh_pointid(qh, point), facet->id, bestdist, bestfacet->id, qh->furthest_id);
+      qh_errprint(qh, "DISTANT", facet, bestfacet, NULL, NULL);
+    }
+  }
+  if (qh->KEEPcoplanar + qh->KEEPinside + qh->KEEPnearinside) {
+    oldfurthest= (pointT *)qh_setlast(bestfacet->coplanarset);
+    if (oldfurthest) {
+      zinc_(Zcomputefurthest);
+      qh_distplane(qh, oldfurthest, bestfacet, &dist2);
+    }
+    if (!oldfurthest || dist2 < bestdist)
+      qh_setappend(qh, &bestfacet->coplanarset, point);
+    else
+      qh_setappend2ndlast(qh, &bestfacet->coplanarset, point);
+  }
+  trace4((qh, qh->ferr, 4064, "qh_partitioncoplanar: point p%d is coplanar with facet f%d (or inside) dist %2.2g\n",
+          qh_pointid(qh, point), bestfacet->id, bestdist));
+} /* partitioncoplanar */
+
+/*---------------------------------
+
+  qh_partitionpoint(qh, point, facet )
+    assigns point to an outside set, coplanar set, or inside set (i.e., dropt)
+    if qh.findbestnew
+      uses qh_findbestnew() to search all new facets
+    else
+      uses qh_findbest()
+
+  notes:
+    after qh_distplane(), this and qh_findbest() are most expensive in 3-d
+
+  design:
+    find best facet for point
+      (either exhaustive search of new facets or directed search from facet)
+    if qh.NARROWhull
+      retain coplanar and nearinside points as outside points
+    if point is outside bestfacet
+      if point above furthest point for bestfacet
+        append point to outside set (it becomes the new furthest)
+        if outside set was empty
+          move bestfacet to end of qh.facet_list (i.e., after qh.facet_next)
+        update bestfacet->furthestdist
+      else
+        append point one before end of outside set
+    else if point is coplanar to bestfacet
+      if keeping coplanar points or need to update qh.max_outside
+        partition coplanar point into bestfacet
+    else if near-inside point
+      partition as coplanar point into bestfacet
+    else is an inside point
+      if keeping inside points
+        partition as coplanar point into bestfacet
+*/
+void qh_partitionpoint(qhT *qh, pointT *point, facetT *facet) {
+  realT bestdist, previousdist;
+  boolT isoutside, isnewoutside= False;
+  facetT *bestfacet;
+  int numpart;
+
+  if (qh->findbestnew)
+    bestfacet= qh_findbestnew(qh, point, facet, &bestdist, qh->BESToutside, &isoutside, &numpart);
+  else
+    bestfacet= qh_findbest(qh, point, facet, qh->BESToutside, qh_ISnewfacets, !qh_NOupper,
+                          &bestdist, &isoutside, &numpart);
+  zinc_(Ztotpartition);
+  zzadd_(Zpartition, numpart);
+  if(bestfacet->visible){
+    qh_fprintf(qh, qh->ferr, 6293, "qhull internal error (qh_partitionpoint): cannot partition p%d of f%d into visible facet f%d\n",
+      qh_pointid(qh, point), facet->id, bestfacet->id);
+    qh_errexit2(qh, qh_ERRqhull, facet, bestfacet);
+  }
+  if (qh->NARROWhull) {
+    if (qh->DELAUNAY && !isoutside && bestdist >= -qh->MAXcoplanar)
+      qh_joggle_restart(qh, "nearly incident point (narrow hull)");
+    if (qh->KEEPnearinside) {
+      if (bestdist >= -qh->NEARinside)
+        isoutside= True;
+    }else if (bestdist >= -qh->MAXcoplanar)
+      isoutside= True;
+  }
+
+  if (isoutside) {
+    if (!bestfacet->outsideset
+    || !qh_setlast(bestfacet->outsideset)) { /* empty outside set */
+      qh_setappend(qh, &(bestfacet->outsideset), point);
+      if (!qh->NARROWhull || bestdist > qh->MINoutside)
+        isnewoutside= True;
+#if !qh_COMPUTEfurthest
+      bestfacet->furthestdist= bestdist;
+#endif
+    }else {
+#if qh_COMPUTEfurthest
+      zinc_(Zcomputefurthest);
+      qh_distplane(qh, oldfurthest, bestfacet, &previousdist);
+      if (previousdist < bestdist)
+        qh_setappend(qh, &(bestfacet->outsideset), point);
+      else
+        qh_setappend2ndlast(qh, &(bestfacet->outsideset), point);
+#else
+      previousdist= bestfacet->furthestdist;
+      if (previousdist < bestdist) {
+        qh_setappend(qh, &(bestfacet->outsideset), point);
+        bestfacet->furthestdist= bestdist;
+        if (qh->NARROWhull && previousdist < qh->MINoutside && bestdist >= qh->MINoutside)
+          isnewoutside= True;
+      }else
+        qh_setappend2ndlast(qh, &(bestfacet->outsideset), point);
+#endif
+    }
+    if (isnewoutside && qh->facet_next != bestfacet) {
+      if (bestfacet->newfacet) {
+        if (qh->facet_next->newfacet)
+          qh->facet_next= qh->newfacet_list; /* make sure it's after qh.facet_next */
+      }else {
+        qh_removefacet(qh, bestfacet);  /* make sure it's after qh.facet_next */
+        qh_appendfacet(qh, bestfacet);
+        if(qh->newfacet_list){
+          bestfacet->newfacet= True;
+        }
+      }
+    }
+    qh->num_outside++;
+    trace4((qh, qh->ferr, 4065, "qh_partitionpoint: point p%d is outside facet f%d newfacet? %d, newoutside? %d (or narrowhull)\n",
+          qh_pointid(qh, point), bestfacet->id, bestfacet->newfacet, isnewoutside));
+  }else if (qh->DELAUNAY || bestdist >= -qh->MAXcoplanar) { /* for 'd', bestdist skips upperDelaunay facets */
+    if (qh->DELAUNAY)
+      qh_joggle_restart(qh, "nearly incident point");
+    /* allow coplanar points with joggle, may be interior */
+    zzinc_(Zcoplanarpart);
+    if ((qh->KEEPcoplanar + qh->KEEPnearinside) || bestdist > qh->max_outside)
+      qh_partitioncoplanar(qh, point, bestfacet, &bestdist, qh->findbestnew);
+    else {
+      trace4((qh, qh->ferr, 4066, "qh_partitionpoint: point p%d is coplanar to facet f%d (dropped)\n",
+          qh_pointid(qh, point), bestfacet->id));
+    }
+  }else if (qh->KEEPnearinside && bestdist >= -qh->NEARinside) {
+    zinc_(Zpartnear);
+    qh_partitioncoplanar(qh, point, bestfacet, &bestdist, qh->findbestnew);
+  }else {
+    zinc_(Zpartinside);
+    trace4((qh, qh->ferr, 4067, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
+          qh_pointid(qh, point), bestfacet->id, bestdist));
+    if (qh->KEEPinside)
+      qh_partitioncoplanar(qh, point, bestfacet, &bestdist, qh->findbestnew);
+  }
+} /* partitionpoint */
+
+/*---------------------------------
+
+  qh_partitionvisible(qh, allpoints, numoutside )
+    partitions outside points in visible facets (qh.visible_list) to qh.newfacet_list
+    if keeping coplanar/near-inside/inside points
+      partitions coplanar points; repartitions if 'allpoints' (not used)
+    1st neighbor (if any) of visible facets points to a horizon facet or a new facet
+
+  returns:
+    updates outside sets and coplanar sets of qh.newfacet_list
+    updates qh.num_outside (count of outside points)
+    does not truncate f.outsideset, f.coplanarset, or qh.del_vertices (see qh_deletevisible)
+
+  notes:
+    called by qh_qhull, qh_addpoint, and qh_all_vertexmerges
+    qh.findbest_notsharp should be clear (extra work if set)
+
+  design:
+    for all visible facets with outside set or coplanar set
+      select a newfacet for visible facet
+      if outside set
+        partition outside set into new facets
+      if coplanar set and keeping coplanar/near-inside/inside points
+        if allpoints
+          partition coplanar set into new facets, may be assigned outside
+        else
+          partition coplanar set into coplanar sets of new facets
+    for each deleted vertex
+      if allpoints
+        partition vertex into new facets, may be assigned outside
+      else
+        partition vertex into coplanar sets of new facets
+*/
+void qh_partitionvisible(qhT *qh, boolT allpoints, int *numoutside /* qh.visible_list */) {
+  facetT *visible, *newfacet;
+  pointT *point, **pointp;
+  int delsize, coplanar=0, size;
+  vertexT *vertex, **vertexp;
+
+  trace3((qh, qh->ferr, 3042, "qh_partitionvisible: partition outside and coplanar points of visible and merged facets f%d into new facets f%d\n",
+    qh->visible_list->id, qh->newfacet_list->id));
+  if (qh->ONLYmax)
+    maximize_(qh->MINoutside, qh->max_vertex);
+  *numoutside= 0;
+  FORALLvisible_facets {
+    if (!visible->outsideset && !visible->coplanarset)
+      continue;
+    newfacet= qh_getreplacement(qh, visible);
+    if (!newfacet)
+      newfacet= qh->newfacet_list;
+    if (!newfacet->next) {
+      qh_fprintf(qh, qh->ferr, 6170, "qhull topology error (qh_partitionvisible): all new facets deleted as\n       degenerate facets. Can not continue.\n");
+      qh_errexit(qh, qh_ERRtopology, NULL, NULL);
+    }
+    if (visible->outsideset) {
+      size= qh_setsize(qh, visible->outsideset);
+      *numoutside += size;
+      qh->num_outside -= size;
+      FOREACHpoint_(visible->outsideset)
+        qh_partitionpoint(qh, point, newfacet);
+    }
+    if (visible->coplanarset && (qh->KEEPcoplanar + qh->KEEPinside + qh->KEEPnearinside)) {
+      size= qh_setsize(qh, visible->coplanarset);
+      coplanar += size;
+      FOREACHpoint_(visible->coplanarset) {
+        if (allpoints) /* not used */
+          qh_partitionpoint(qh, point, newfacet);
+        else
+          qh_partitioncoplanar(qh, point, newfacet, NULL, qh->findbestnew);
+      }
+    }
+  }
+  delsize= qh_setsize(qh, qh->del_vertices);
+  if (delsize > 0) {
+    trace3((qh, qh->ferr, 3049, "qh_partitionvisible: partition %d deleted vertices as coplanar? %d points into new facets f%d\n",
+      delsize, !allpoints, qh->newfacet_list->id));
+    FOREACHvertex_(qh->del_vertices) {
+      if (vertex->point && !vertex->partitioned) {
+        if (!qh->newfacet_list || qh->newfacet_list == qh->facet_tail) {
+          qh_fprintf(qh, qh->ferr, 6284, "qhull internal error (qh_partitionvisible): all new facets deleted or none defined.  Can not partition deleted v%d.\n", vertex->id);
+          qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+        }
+        if (allpoints) /* not used */
+          /* [apr'2019] infinite loop if vertex recreates the same facets from the same horizon
+             e.g., qh_partitionpoint if qh.DELAUNAY with qh.MERGEindependent for all mergetype, ../eg/qtest.sh t427764 '1000 s W1e-13 D3' 'd' */
+          qh_partitionpoint(qh, vertex->point, qh->newfacet_list);
+        else
+          qh_partitioncoplanar(qh, vertex->point, qh->newfacet_list, NULL, qh_ALL); /* search all new facets */
+        vertex->partitioned= True;
+      }
+    }
+  }
+  trace1((qh, qh->ferr, 1043,"qh_partitionvisible: partitioned %d points from outsidesets, %d points from coplanarsets, and %d deleted vertices\n", *numoutside, coplanar, delsize));
+} /* partitionvisible */
+
+/*---------------------------------
+
+  qh_printsummary(qh, fp )
+    prints summary to fp
+
+  notes:
+    not in io_r.c so that user_eg.c can prevent io_r.c from loading
+    qh_printsummary and qh_countfacets must match counts
+    updates qh.facet_visit to detect infinite loop
+
+  design:
+    determine number of points, vertices, and coplanar points
+    print summary
+*/
+void qh_printsummary(qhT *qh, FILE *fp) {
+  realT ratio, outerplane, innerplane;
+  double cpu;
+  int size, id, nummerged, numpinched, numvertices, numcoplanars= 0, nonsimplicial=0, numdelaunay= 0;
+  facetT *facet;
+  const char *s;
+  int numdel= zzval_(Zdelvertextot);
+  int numtricoplanars= 0;
+  boolT goodused;
+
+  size= qh->num_points + qh_setsize(qh, qh->other_points);
+  numvertices= qh->num_vertices - qh_setsize(qh, qh->del_vertices);
+  id= qh_pointid(qh, qh->GOODpointp);
+  if (!qh_checklists(qh, qh->facet_list) && !qh->ERREXITcalled) {
+    qh_fprintf(qh, fp, 6372, "qhull internal error: qh_checklists failed at qh_printsummary\n");
+    if (qh->num_facets < 4000)
+      qh_printlists(qh);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (qh->DELAUNAY && qh->ERREXITcalled) {
+    /* update f.good and determine qh.num_good as in qh_findgood_all */
+    FORALLfacets {
+      if (facet->visible)
+        facet->good= False; /* will be deleted */
+      else if (facet->good) {
+        if (facet->normal && !qh_inthresholds(qh, facet->normal, NULL))
+          facet->good= False;
+        else
+          numdelaunay++;
+      }
+    }
+    qh->num_good= numdelaunay;
+  }
+  FORALLfacets {
+    if (facet->coplanarset)
+      numcoplanars += qh_setsize(qh, facet->coplanarset);
+    if (facet->good) {
+      if (facet->simplicial) {
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else if (qh_setsize(qh, facet->vertices) != qh->hull_dim)
+        nonsimplicial++;
+    }
+  }
+  if (id >=0 && qh->STOPcone-1 != id && -qh->STOPpoint-1 != id)
+    size--;
+  if (qh->STOPadd || qh->STOPcone || qh->STOPpoint)
+    qh_fprintf(qh, fp, 9288, "\nEarly exit due to 'TAn', 'TVn', 'TCn', 'TRn', or precision error with 'QJn'.");
+  goodused= False;
+  if (qh->ERREXITcalled)
+    ; /* qh_findgood_all not called */
+  else if (qh->UPPERdelaunay) {
+    if (qh->GOODvertex || qh->GOODpoint || qh->SPLITthresholds)
+      goodused= True;
+  }else if (qh->DELAUNAY) {
+    if (qh->GOODvertex || qh->GOODpoint || qh->GOODthreshold)
+      goodused= True;
+  }else if (qh->num_good > 0 || qh->GOODthreshold)
+    goodused= True;
+  nummerged= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+  if (qh->VORONOI) {
+    if (qh->UPPERdelaunay)
+      qh_fprintf(qh, fp, 9289, "\n\
+Furthest-site Voronoi vertices by the convex hull of %d points in %d-d:\n\n", size, qh->hull_dim);
+    else
+      qh_fprintf(qh, fp, 9290, "\n\
+Voronoi diagram by the convex hull of %d points in %d-d:\n\n", size, qh->hull_dim);
+    qh_fprintf(qh, fp, 9291, "  Number of Voronoi regions%s: %d\n",
+              qh->ATinfinity ? " and at-infinity" : "", numvertices);
+    if (numdel)
+      qh_fprintf(qh, fp, 9292, "  Total number of deleted points due to merging: %d\n", numdel);
+    if (numcoplanars - numdel > 0)
+      qh_fprintf(qh, fp, 9293, "  Number of nearly incident points: %d\n", numcoplanars - numdel);
+    else if (size - numvertices - numdel > 0)
+      qh_fprintf(qh, fp, 9294, "  Total number of nearly incident points: %d\n", size - numvertices - numdel);
+    qh_fprintf(qh, fp, 9295, "  Number of%s Voronoi vertices: %d\n",
+              goodused ? " 'good'" : "", qh->num_good);
+    if (nonsimplicial)
+      qh_fprintf(qh, fp, 9296, "  Number of%s non-simplicial Voronoi vertices: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else if (qh->DELAUNAY) {
+    if (qh->UPPERdelaunay)
+      qh_fprintf(qh, fp, 9297, "\n\
+Furthest-site Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh->hull_dim);
+    else
+      qh_fprintf(qh, fp, 9298, "\n\
+Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh->hull_dim);
+    qh_fprintf(qh, fp, 9299, "  Number of input sites%s: %d\n",
+              qh->ATinfinity ? " and at-infinity" : "", numvertices);
+    if (numdel)
+      qh_fprintf(qh, fp, 9300, "  Total number of deleted points due to merging: %d\n", numdel);
+    if (numcoplanars - numdel > 0)
+      qh_fprintf(qh, fp, 9301, "  Number of nearly incident points: %d\n", numcoplanars - numdel);
+    else if (size - numvertices - numdel > 0)
+      qh_fprintf(qh, fp, 9302, "  Total number of nearly incident points: %d\n", size - numvertices - numdel);
+    qh_fprintf(qh, fp, 9303, "  Number of%s Delaunay regions: %d\n",
+              goodused ? " 'good'" : "", qh->num_good);
+    if (nonsimplicial)
+      qh_fprintf(qh, fp, 9304, "  Number of%s non-simplicial Delaunay regions: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else if (qh->HALFspace) {
+    qh_fprintf(qh, fp, 9305, "\n\
+Halfspace intersection by the convex hull of %d points in %d-d:\n\n", size, qh->hull_dim);
+    qh_fprintf(qh, fp, 9306, "  Number of halfspaces: %d\n", size);
+    qh_fprintf(qh, fp, 9307, "  Number of non-redundant halfspaces: %d\n", numvertices);
+    if (numcoplanars) {
+      if (qh->KEEPinside && qh->KEEPcoplanar)
+        s= "similar and redundant";
+      else if (qh->KEEPinside)
+        s= "redundant";
+      else
+        s= "similar";
+      qh_fprintf(qh, fp, 9308, "  Number of %s halfspaces: %d\n", s, numcoplanars);
+    }
+    qh_fprintf(qh, fp, 9309, "  Number of intersection points: %d\n", qh->num_facets - qh->num_visible);
+    if (goodused)
+      qh_fprintf(qh, fp, 9310, "  Number of 'good' intersection points: %d\n", qh->num_good);
+    if (nonsimplicial)
+      qh_fprintf(qh, fp, 9311, "  Number of%s non-simplicial intersection points: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else {
+    qh_fprintf(qh, fp, 9312, "\n\
+Convex hull of %d points in %d-d:\n\n", size, qh->hull_dim);
+    qh_fprintf(qh, fp, 9313, "  Number of vertices: %d\n", numvertices);
+    if (numcoplanars) {
+      if (qh->KEEPinside && qh->KEEPcoplanar)
+        s= "coplanar and interior";
+      else if (qh->KEEPinside)
+        s= "interior";
+      else
+        s= "coplanar";
+      qh_fprintf(qh, fp, 9314, "  Number of %s points: %d\n", s, numcoplanars);
+    }
+    qh_fprintf(qh, fp, 9315, "  Number of facets: %d\n", qh->num_facets - qh->num_visible);
+    if (goodused)
+      qh_fprintf(qh, fp, 9316, "  Number of 'good' facets: %d\n", qh->num_good);
+    if (nonsimplicial)
+      qh_fprintf(qh, fp, 9317, "  Number of%s non-simplicial facets: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }
+  if (numtricoplanars)
+      qh_fprintf(qh, fp, 9318, "  Number of triangulated facets: %d\n", numtricoplanars);
+  qh_fprintf(qh, fp, 9319, "\nStatistics for: %s | %s",
+                      qh->rbox_command, qh->qhull_command);
+  if (qh->ROTATErandom != INT_MIN)
+    qh_fprintf(qh, fp, 9320, " QR%d\n\n", qh->ROTATErandom);
+  else
+    qh_fprintf(qh, fp, 9321, "\n\n");
+  qh_fprintf(qh, fp, 9322, "  Number of points processed: %d\n", zzval_(Zprocessed));
+  qh_fprintf(qh, fp, 9323, "  Number of hyperplanes created: %d\n", zzval_(Zsetplane));
+  if (qh->DELAUNAY)
+    qh_fprintf(qh, fp, 9324, "  Number of facets in hull: %d\n", qh->num_facets - qh->num_visible);
+  qh_fprintf(qh, fp, 9325, "  Number of distance tests for qhull: %d\n", zzval_(Zpartition)+
+      zzval_(Zpartitionall)+zzval_(Znumvisibility)+zzval_(Zpartcoplanar));
+#if 0  /* NOTE: must print before printstatistics() */
+  {realT stddev, ave;
+  qh_fprintf(qh, fp, 9326, "  average new facet balance: %2.2g\n",
+          wval_(Wnewbalance)/zval_(Zprocessed));
+  stddev= qh_stddev(zval_(Zprocessed), wval_(Wnewbalance),
+                                 wval_(Wnewbalance2), &ave);
+  qh_fprintf(qh, fp, 9327, "  new facet standard deviation: %2.2g\n", stddev);
+  qh_fprintf(qh, fp, 9328, "  average partition balance: %2.2g\n",
+          wval_(Wpbalance)/zval_(Zpbalance));
+  stddev= qh_stddev(zval_(Zpbalance), wval_(Wpbalance),
+                                 wval_(Wpbalance2), &ave);
+  qh_fprintf(qh, fp, 9329, "  partition standard deviation: %2.2g\n", stddev);
+  }
+#endif
+  if (nummerged) {
+    qh_fprintf(qh, fp, 9330,"  Number of distance tests for merging: %d\n",zzval_(Zbestdist)+
+          zzval_(Zcentrumtests)+zzval_(Zvertextests)+zzval_(Zdistcheck)+zzval_(Zdistzero));
+    qh_fprintf(qh, fp, 9331,"  Number of distance tests for checking: %d\n",zzval_(Zcheckpart)+zzval_(Zdistconvex));
+    qh_fprintf(qh, fp, 9332,"  Number of merged facets: %d\n", nummerged);
+  }
+  numpinched= zzval_(Zpinchduplicate) + zzval_(Zpinchedvertex);
+  if (numpinched)
+    qh_fprintf(qh, fp, 9375,"  Number of merged pinched vertices: %d\n", numpinched);
+  if (!qh->RANDOMoutside && qh->QHULLfinished) {
+    cpu= (double)qh->hulltime;
+    cpu /= (double)qh_SECticks;
+    wval_(Wcpu)= cpu;
+    qh_fprintf(qh, fp, 9333, "  CPU seconds to compute hull (after input): %2.4g\n", cpu);
+  }
+  if (qh->RERUN) {
+    if (!qh->PREmerge && !qh->MERGEexact)
+      qh_fprintf(qh, fp, 9334, "  Percentage of runs with precision errors: %4.1f\n",
+           zzval_(Zretry)*100.0/qh->build_cnt);  /* careful of order */
+  }else if (qh->JOGGLEmax < REALmax/2) {
+    if (zzval_(Zretry))
+      qh_fprintf(qh, fp, 9335, "  After %d retries, input joggled by: %2.2g\n",
+         zzval_(Zretry), qh->JOGGLEmax);
+    else
+      qh_fprintf(qh, fp, 9336, "  Input joggled by: %2.2g\n", qh->JOGGLEmax);
+  }
+  if (qh->totarea != 0.0)
+    qh_fprintf(qh, fp, 9337, "  %s facet area:   %2.8g\n",
+            zzval_(Ztotmerge) ? "Approximate" : "Total", qh->totarea);
+  if (qh->totvol != 0.0)
+    qh_fprintf(qh, fp, 9338, "  %s volume:       %2.8g\n",
+            zzval_(Ztotmerge) ? "Approximate" : "Total", qh->totvol);
+  if (qh->MERGING) {
+    qh_outerinner(qh, NULL, &outerplane, &innerplane);
+    if (outerplane > 2 * qh->DISTround) {
+      qh_fprintf(qh, fp, 9339, "  Maximum distance of point above facet: %2.2g", outerplane);
+      ratio= outerplane/(qh->ONEmerge + qh->DISTround);
+      /* don't report ratio if MINoutside is large */
+      if (ratio > 0.05 && 2* qh->ONEmerge > qh->MINoutside && qh->JOGGLEmax > REALmax/2)
+        qh_fprintf(qh, fp, 9340, " (%.1fx)\n", ratio);
+      else
+        qh_fprintf(qh, fp, 9341, "\n");
+    }
+    if (innerplane < -2 * qh->DISTround) {
+      qh_fprintf(qh, fp, 9342, "  Maximum distance of vertex below facet: %2.2g", innerplane);
+      ratio= -innerplane/(qh->ONEmerge+qh->DISTround);
+      if (ratio > 0.05 && qh->JOGGLEmax > REALmax/2)
+        qh_fprintf(qh, fp, 9343, " (%.1fx)\n", ratio);
+      else
+        qh_fprintf(qh, fp, 9344, "\n");
+    }
+  }
+  qh_fprintf(qh, fp, 9345, "\n");
+} /* printsummary */
+
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.h
new file mode 100644
index 00000000000..7193e2a5bed
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/libqhull_r.h
@@ -0,0 +1,1281 @@
+/*
  ---------------------------------
+
+   libqhull_r.h
+   user-level header file for using qhull.a library
+
+   see qh-qhull_r.htm, qhull_ra.h
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/libqhull_r.h#18 $$Change: 3664 $
+   $DateTime: 2024/07/22 23:55:01 $$Author: bbarber $
+
+   includes function prototypes for libqhull_r.c, geom_r.c, global_r.c, io_r.c, user_r.c
+
+   use mem_r.h for mem_r.c
+   use qset_r.h for qset_r.c
+
+   see unix_r.c for an example of using libqhull_r.h
+
+   recompile qhull if you change this file
+*/
+
+#ifndef qhDEFlibqhull
+#define qhDEFlibqhull 1
+
+/*=========================== -included files ==============*/
+
+/* user_r.h first for QHULL_CRTDBG */
+#include "user_r.h"      /* user definable constants (e.g., realT). */
+
+#include "mem_r.h"   /* Needed for qhT in libqhull_r.h */
+#include "qset_r.h"   /* Needed for QHULL_LIB_CHECK */
+/* include stat_r.h after defining boolT.  Needed for qhT in libqhull_r.h */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef __STDC__
+#ifndef __cplusplus
+#if     !defined(_MSC_VER)
+#error  Neither __STDC__ nor __cplusplus is defined.  Please use strict ANSI C or C++ to compile
+#error  Qhull.  You may need to turn off compiler extensions in your project configuration.  If
+#error  your compiler is a standard C compiler, you can delete this warning from libqhull_r.h
+#endif
+#endif
+#endif
+
+#if defined(__GNUC__)
+/* See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-format-function-attribute */
+#define QH_PRINTF_LIKE(string_index, first_to_check) __attribute__((format(printf, string_index, first_to_check)))
+#else
+#define QH_PRINTF_LIKE(string_index, first_to_check)
+#endif
+
+/* QH_NORETURN marks as a function as never returning. This is primarily
+   beneficial for aiding static analyzers and reducing compiler warnings.
+   It must come before function declarations, as MSVC only supports this syntax. */
+#if defined(__GNUC__)
+/* Compilers that support the GNU C syntax. Use __noreturn__ instead of 'noreturn' as the latter is a macro in C11. */
+#define QH_NORETURN __attribute__((__noreturn__))
+#elif defined(_MSC_VER)
+/* Compilers that support the MSVC syntax. */
+#define QH_NORETURN __declspec(noreturn)
+#else
+#define QH_NORETURN /* empty */
+#endif
+
+/*============ constants and basic types ====================*/
+
+extern const char qh_version[]; /* defined in global_r.c */
+extern const char qh_version2[]; /* defined in global_r.c */
+
+/*----------------------------------
+
+  coordT
+    coordinates and coefficients are stored as realT (i.e., double)
+
+  notes:
+    Qhull works well if realT is 'float'.  If so joggle (QJ) is not effective.
+
+    Could use 'float' for data and 'double' for calculations (realT vs. coordT)
+      This requires many type casts, and adjusted error bounds.
+      Also C compilers may do expressions in double anyway.
+*/
+#define coordT realT
+
+/*----------------------------------
+
+  pointT
+    a point is an array of coordinates, usually qh.hull_dim
+    qh_pointid returns
+      qh_IDnone if point==0 or qh is undefined
+      qh_IDinterior for qh.interior_point
+      qh_IDunknown if point is neither in qh.first_point... nor qh.other_points
+
+  notes:
+    qh.STOPcone and qh.STOPpoint assume that qh_IDunknown==-1 (other negative numbers indicate points)
+    qh_IDunknown is also returned by getid_() for unknown facet, ridge, or vertex
+*/
+#define pointT coordT
+typedef enum
+{
+    qh_IDnone= -3, qh_IDinterior= -2, qh_IDunknown= -1
+}
+qh_pointT;
+
+/*----------------------------------
+
+  flagT
+    Boolean flag as a bit
+*/
+#define flagT unsigned int
+
+/*----------------------------------
+
+  boolT
+    boolean value, either True or False
+
+  notes:
+    needed for portability
+    Use qh_False/qh_True as synonyms
+*/
+#define boolT unsigned int
+#ifdef False
+#undef False
+#endif
+#ifdef True
+#undef True
+#endif
+#define False 0
+#define True 1
+#define qh_False 0
+#define qh_True 1
+
+#include "stat_r.h"  /* needs boolT */
+
+/*----------------------------------
+
+  qh_CENTER
+    to distinguish facet->center
+*/
+typedef enum
+{
+    qh_ASnone= 0,    /* If not MERGING and not VORONOI */
+    qh_ASvoronoi,    /* Set by qh_clearcenters on qh_prepare_output, or if not MERGING and VORONOI */
+    qh_AScentrum     /* If MERGING (assumed during merging) */
+}
+qh_CENTER;
+
+/*----------------------------------
+
+  qh_PRINT
+    output formats for printing (qh.PRINTout).
+    'Fa' 'FV' 'Fc' 'FC'
+
+
+   notes:
+   some of these names are similar to qhT names.  The similar names are only
+   used in switch statements in qh_printbegin() etc.
+*/
+typedef enum {qh_PRINTnone= 0,
+  qh_PRINTarea, qh_PRINTaverage,           /* 'Fa' 'FV' 'Fc' 'FC' */
+  qh_PRINTcoplanars, qh_PRINTcentrums,
+  qh_PRINTfacets, qh_PRINTfacets_xridge,   /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
+  qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors,
+  qh_PRINTnormals, qh_PRINTouter, qh_PRINTmaple, /* 'n' 'Fo' 'i' 'm' 'Fm' 'FM', 'o' */
+  qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff,
+  qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
+  qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize,
+  qh_PRINTsummary, qh_PRINTtriangles,      /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
+  qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
+  qh_PRINTEND} qh_PRINT;
+
+/*----------------------------------
+
+  qh_ALL
+    argument flag for selecting everything
+*/
+#define qh_ALL      True
+#define qh_NOupper  True      /* argument for qh_findbest */
+#define qh_IScheckmax  True   /* argument for qh_findbesthorizon */
+#define qh_ISnewfacets  True  /* argument for qh_findbest */
+#define qh_RESETvisible  True /* argument for qh_resetlists */
+
+/*----------------------------------
+
+  qh_ERR...
+    Qhull exit status codes, for indicating errors
+    See: MSG_ERROR (6000) and MSG_WARNING (7000) [user_r.h]
+*/
+#define qh_ERRnone  0    /* no error occurred during qhull */
+#define qh_ERRinput 1    /* input inconsistency */
+#define qh_ERRsingular 2 /* singular input data, calls qh_printhelp_singular */
+#define qh_ERRprec  3    /* precision error, calls qh_printhelp_degenerate */
+#define qh_ERRmem   4    /* insufficient memory, matches mem_r.h */
+#define qh_ERRqhull 5    /* internal error detected, matches mem_r.h, calls qh_printhelp_internal */
+#define qh_ERRother 6    /* other error detected */
+#define qh_ERRtopology 7 /* topology error, maybe due to nearly adjacent vertices, calls qh_printhelp_topology */
+#define qh_ERRwide 8     /* wide facet error, maybe due to nearly adjacent vertices, calls qh_printhelp_wide */
+#define qh_ERRdebug 9    /* qh_errexit from debugging code */
+
+/*----------------------------------
+
+qh_FILEstderr
+Fake stderr to distinguish error output from normal output
+For C++ interface.  Must redefine qh_fprintf_qhull
+*/
+#define qh_FILEstderr ((FILE *)1)
+
+/* ============ -structures- ====================
+   each of the following structures is defined by a typedef
+   all realT and coordT fields occur at the beginning of a structure
+        (otherwise space may be wasted due to alignment)
+   define all flags together and pack into 32-bit number
+
+   DEFqhT and DEFsetT are likewise defined in mem_r.h, qset_r.h, and stat_r.h
+*/
+
+typedef struct vertexT vertexT;
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+
+#ifndef DEFqhT
+#define DEFqhT 1
+typedef struct qhT qhT;          /* defined below */
+#endif
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;        /* defined in qset_r.h */
+#endif
+
+/*----------------------------------
+
+  facetT
+    defines a facet
+
+  notes:
+   qhull() generates the hull as a list of facets.
+
+  topological information:
+    f.previous,next     doubly-linked list of facets, next is always defined
+    f.vertices          set of vertices
+    f.ridges            set of ridges
+    f.neighbors         set of neighbors
+    f.toporient         True if facet has top-orientation (else bottom)
+
+  geometric information:
+    f.offset,normal     hyperplane equation
+    f.maxoutside        offset to outer plane -- all points inside
+    f.center            centrum for testing convexity or Voronoi center for output
+    f.simplicial        True if facet is simplicial
+    f.flipped           True if facet does not include qh.interior_point
+
+  for constructing hull:
+    f.visible           True if facet on list of visible facets (will be deleted)
+    f.newfacet          True if facet on list of newly created facets
+    f.coplanarset       set of points coplanar with this facet
+                        (includes near-inside points for later testing)
+    f.outsideset        set of points outside of this facet
+    f.furthestdist      distance to furthest point of outside set
+    f.visitid           marks visited facets during a loop
+    f.replace           replacement facet for to-be-deleted, visible facets
+    f.samecycle,newcycle cycle of facets for merging into horizon facet
+
+  see below for other flags and fields
+*/
+/* QhullFacet.cpp -- Update static initializer list for s_empty_facet if add or remove fields */
+struct facetT {
+#if !qh_COMPUTEfurthest
+  coordT   furthestdist;/* distance to furthest point of outsideset */
+#endif
+#if qh_MAXoutside
+  coordT   maxoutside;  /* max computed distance of point to facet
+                        Before QHULLfinished this is an approximation
+                        since maxdist not always set for qh_mergefacet
+                        Actual outer plane is +DISTround and
+                        computed outer plane is +2*DISTround.
+                        Initial maxoutside is qh.DISTround, otherwise distance tests need to account for DISTround */
+#endif
+  coordT   offset;      /* exact offset of hyperplane from origin */
+  coordT  *normal;      /* normal of hyperplane, hull_dim coefficients */
+                        /*   if f.tricoplanar, shared with a neighbor */
+  union {               /* in order of testing */
+   realT   area;        /* area of facet, only in io_r.c if  f.isarea */
+   facetT *replace;     /* replacement facet for qh.NEWfacets with f.visible
+                             NULL if qh_mergedegen_redundant, interior, or !NEWfacets */
+   facetT *samecycle;   /* cycle of facets from the same visible/horizon intersection,
+                             if ->newfacet */
+   facetT *newcycle;    /*  in horizon facet, current samecycle of new facets */
+   facetT *trivisible;  /* visible facet for ->tricoplanar facets during qh_triangulate() */
+   facetT *triowner;    /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
+  }f;
+  coordT  *center;      /* set according to qh.CENTERtype */
+                        /*   qh_ASnone:    no center (not MERGING) */
+                        /*   qh_AScentrum: centrum for testing convexity (qh_getcentrum) */
+                        /*                 assumed qh_AScentrum while merging */
+                        /*   qh_ASvoronoi: Voronoi center (qh_facetcenter) */
+                        /* after constructing the hull, it may be changed (qh_clearcenter) */
+                        /* if tricoplanar and !keepcentrum, shared with a neighbor */
+  facetT  *previous;    /* previous facet in the facet_list or NULL, for C++ interface */
+  facetT  *next;        /* next facet in the facet_list or facet_tail */
+  setT    *vertices;    /* vertices for this facet, inverse sorted by ID
+                           if simplicial, 1st vertex was apex/furthest
+                           qh_reduce_vertices removes extraneous vertices via qh_remove_extravertices
+                           if f.visible, vertices may be on qh.del_vertices */
+  setT    *ridges;      /* explicit ridges for nonsimplicial facets or nonsimplicial neighbors.
+                           For simplicial facets, neighbors define the ridges
+                           qh_makeridges() converts simplicial facets by creating ridges prior to merging
+                           If qh.NEWtentative, new facets have horizon ridge, but not vice versa
+                           if f.visible && qh.NEWfacets, ridges is empty */
+  setT    *neighbors;   /* neighbors of the facet.  Neighbors may be f.visible
+                           If simplicial, the kth neighbor is opposite the kth vertex and the
+                           first neighbor is the horizon facet for the first vertex.
+                           dupridges marked by qh_DUPLICATEridge (0x01) and qh_MERGEridge (0x02)
+                           if f.visible && qh.NEWfacets, neighbors is empty */
+  setT    *outsideset;  /* set of points outside this facet
+                           if non-empty, last point is furthest
+                           if NARROWhull, includes coplanars (less than qh.MINoutside) for partitioning*/
+  setT    *coplanarset; /* set of points coplanar with this facet
+                           >= qh.min_vertex and <= facet->max_outside
+                           a point is assigned to the furthest facet
+                           if non-empty, last point is furthest away */
+  unsigned int visitid; /* visit_id, for visiting all neighbors,
+                           all uses are independent */
+  unsigned int id;      /* unique identifier from qh.facet_id, 1..qh.facet_id, 0 is sentinel, printed as 'f%d' */
+  unsigned int nummerge:9; /* number of merges */
+#define qh_MAXnummerge 511 /* 2^9-1 */
+                        /* 23 flags (at most 23 due to nummerge), printed by "flags:" in io_r.c */
+  flagT    tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
+                          /*   all tricoplanars share the same apex */
+                          /*   all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
+                          /*     ->keepcentrum is true for the owner.  It has the ->coplanareset */
+                          /*   if ->degenerate, does not span facet (one logical ridge) */
+                          /*   during qh_triangulate, f.trivisible points to original facet */
+  flagT    newfacet:1;  /* True if facet on qh.newfacet_list (new/qh.first_newfacet or merged) */
+  flagT    visible:1;   /* True if visible facet (will be deleted) */
+  flagT    toporient:1; /* True if created with top orientation
+                           after merging, use ridge orientation */
+  flagT    simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
+  flagT    seen:1;      /* used to perform operations only once, like visitid */
+  flagT    seen2:1;     /* used to perform operations only once, like visitid */
+  flagT    flipped:1;   /* True if facet is flipped */
+  flagT    upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
+  flagT    notfurthest:1; /* True if last point of outsideset is not furthest */
+
+/*-------- flags primarily for output ---------*/
+  flagT    good:1;      /* True if a facet marked good for output */
+  flagT    isarea:1;    /* True if facet->f.area is defined */
+
+/*-------- flags for merging ------------------*/
+  flagT    dupridge:1;  /* True if facet has one or more dupridge in a new facet (qh_matchneighbor),
+                             a dupridge has a subridge shared by more than one new facet */
+  flagT    mergeridge:1; /* True if facet or neighbor has a qh_MERGEridge (qh_mark_dupridges)
+                            ->normal defined for mergeridge and mergeridge2 */
+  flagT    mergeridge2:1; /* True if neighbor has a qh_MERGEridge (qh_mark_dupridges) */
+  flagT    coplanarhorizon:1;  /* True if horizon facet is coplanar at last use */
+  flagT     mergehorizon:1; /* True if will merge into horizon (its first neighbor w/ f.coplanarhorizon). */
+  flagT     cycledone:1;/* True if mergecycle_all already done */
+  flagT    tested:1;    /* True if facet convexity has been tested (false after merge */
+  flagT    keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar
+                             Set by qh_updatetested if more than qh_MAXnewcentrum extra vertices
+                             Set by qh_mergefacet if |maxdist| > qh.WIDEfacet */
+  flagT    newmerge:1;  /* True if facet is newly merged for reducevertices */
+  flagT    degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
+  flagT    redundant:1;  /* True if facet is redundant (degen_mergeset)
+                         Maybe merge degenerate and redundant to gain another flag */
+};
+
+
+/*----------------------------------
+
+  ridgeT
+    defines a ridge
+
+  notes:
+  a ridge is hull_dim-1 simplex between two neighboring facets.  If the
+  facets are non-simplicial, there may be more than one ridge between
+  two facets.  E.G. a 4-d hypercube has two triangles between each pair
+  of neighboring facets.
+
+  topological information:
+    vertices            a set of vertices
+    top,bottom          neighboring facets with orientation
+
+  geometric information:
+    tested              True if ridge is clearly convex
+    nonconvex           True if ridge is non-convex
+*/
+/* QhullRidge.cpp -- Update static initializer list for s_empty_ridge if add or remove fields */
+struct ridgeT {
+  setT    *vertices;    /* vertices belonging to this ridge, inverse sorted by ID
+                           NULL if a degen ridge (matchsame) */
+  facetT  *top;         /* top facet for this ridge */
+  facetT  *bottom;      /* bottom facet for this ridge
+                        ridge oriented by odd/even vertex order and top/bottom */
+  unsigned int id;      /* unique identifier.  Same size as vertex_id, printed as 'r%d' */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    tested:1;    /* True when ridge is tested for convexity by centrum or opposite vertices */
+  flagT    nonconvex:1; /* True if getmergeset detected a non-convex neighbor
+                           only one ridge between neighbors may have nonconvex */
+  flagT    mergevertex:1; /* True if pending qh_appendvertexmerge due to
+                             qh_maybe_duplicateridge or qh_maybe_duplicateridges
+                             disables check for duplicate vertices in qh_checkfacet */
+  flagT    mergevertex2:1; /* True if qh_drop_mergevertex of MRGvertices, printed but not used */
+  flagT    simplicialtop:1; /* True if top was simplicial (original vertices) */
+  flagT    simplicialbot:1; /* True if bottom was simplicial (original vertices)
+                             use qh_test_centrum_merge if top and bot, need to retest since centrum may change */
+};
+
+/*----------------------------------
+
+  vertexT
+     defines a vertex
+
+  topological information:
+    next,previous       doubly-linked list of all vertices
+    neighbors           set of adjacent facets (only if qh.VERTEXneighbors)
+
+  geometric information:
+    point               array of DIM3 coordinates
+*/
+/* QhullVertex.cpp -- Update static initializer list for s_empty_vertex if add or remove fields */
+struct vertexT {
+  vertexT *next;        /* next vertex in vertex_list or vertex_tail */
+  vertexT *previous;    /* previous vertex in vertex_list or NULL, for C++ interface */
+  pointT  *point;       /* hull_dim coordinates (coordT) */
+  setT    *neighbors;   /* neighboring facets of vertex, qh_vertexneighbors()
+                           initialized in io_r.c or after first merge
+                           qh_update_vertices for qh_addpoint or qh_triangulate
+                           updated by merges
+                           qh_order_vertexneighbors by 2-d (orientation) 3-d (adjacency), n-d (f.visitid,id) */
+  unsigned int id;      /* unique identifier, 1..qh.vertex_id,  0 for sentinel, printed as 'r%d' */
+  unsigned int visitid; /* for use with qh.vertex_visit, size must match */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    seen2:1;     /* another seen flag */
+  flagT    deleted:1;   /* vertex will be deleted via qh.del_vertices */
+  flagT    delridge:1;  /* vertex belonged to a deleted ridge, cleared by qh_reducevertices */
+  flagT    newfacet:1;  /* true if vertex is in a new facet
+                           vertex is on qh.newvertex_list and it has a facet on qh.newfacet_list
+                           or vertex is on qh.newvertex_list due to qh_newvertices while merging
+                           cleared by qh_resetlists */
+  flagT    partitioned:1; /* true if deleted vertex has been partitioned */
+};
+
+/*======= -global variables -qh ============================*/
+
+/*----------------------------------
+
+  qhT
+   All global variables for qhull are in qhT.  It includes qhmemT, qhstatT, and rbox globals
+
+   This version of Qhull is reentrant, but it is not thread-safe.
+
+   Do not run separate threads on the same instance of qhT.
+
+   QHULL_LIB_CHECK checks that a program and the corresponding
+   qhull library were built with the same type of header files.
+
+   QHULL_LIB_TYPE is QHULL_NON_REENTRANT, QHULL_QH_POINTER, or QHULL_REENTRANT
+*/
+
+#define QHULL_NON_REENTRANT 0
+#define QHULL_QH_POINTER 1
+#define QHULL_REENTRANT 2
+
+#define QHULL_LIB_TYPE QHULL_REENTRANT
+
+#define QHULL_LIB_CHECK qh_lib_check(QHULL_LIB_TYPE, sizeof(qhT), sizeof(vertexT), sizeof(ridgeT), sizeof(facetT), SETbasesize, sizeof(qhmemT));
+#define QHULL_LIB_CHECK_RBOX qh_lib_check(QHULL_LIB_TYPE, sizeof(qhT), sizeof(vertexT), sizeof(ridgeT), sizeof(facetT), 0, 0);
+
+struct qhT {
+
+/*----------------------------------
+
+  qh constants
+    configuration flags and constants for Qhull
+
+  notes:
+    The user configures Qhull by defining flags.  They are
+    copied into qh by qh_setflags().  qh-quick_r.htm#options defines the flags.
+*/
+  boolT ALLpoints;        /* true 'Qs' if search all points for initial simplex */
+  boolT ALLOWshort;       /* true 'Qa' allow input with fewer or more points than coordinates */
+  boolT ALLOWwarning;     /* true 'Qw' if allow option warnings */
+  boolT ALLOWwide;        /* true 'Q12' if allow wide facets and wide dupridges, c.f. qh_WIDEmaxoutside */
+  boolT ANGLEmerge;       /* true 'Q1' if sort potential merges by type/angle instead of type/distance  */
+  boolT APPROXhull;       /* true 'Wn' if MINoutside set */
+  realT MINoutside;       /*   Minimum distance for an outside point ('Wn' or 2*qh.MINvisible) */
+  boolT ANNOTATEoutput;   /* true 'Ta' if annotate output with message codes */
+  boolT ATinfinity;       /* true 'Qz' if point num_points-1 is "at-infinity"
+                             for improving precision in Delaunay triangulations */
+  boolT AVOIDold;         /* true 'Q4' if avoid old->new merges */
+  boolT BESToutside;      /* true 'Qf' if partition points into best outsideset */
+  boolT CDDinput;         /* true 'Pc' if input uses CDD format (1.0/offset first) */
+  boolT CDDoutput;        /* true 'PC' if print normals in CDD format (offset first) */
+  boolT CHECKduplicates;  /* true 'Q17' if qh_maybe_duplicateridges after each qh_mergefacet */
+  boolT CHECKfrequently;  /* true 'Tc' if checking frequently */
+  realT premerge_cos;     /*   'A-n'   cos_max when pre merging */
+  realT postmerge_cos;    /*   'An'    cos_max when post merging */
+  boolT DELAUNAY;         /* true 'd' or 'v' if computing DELAUNAY triangulation */
+  boolT DOintersections;  /* true 'Gh' if print hyperplane intersections */
+  int   DROPdim;          /* drops dim 'GDn' for 4-d -> 3-d output */
+  boolT FLUSHprint;       /* true 'Tf' if flush after qh_fprintf for segfaults */
+  boolT FORCEoutput;      /* true 'Po' if forcing output despite degeneracies */
+  int   GOODpoint;        /* 'QGn' or 'QG-n' (n+1, n-1), good facet if visible from point n (or not) */
+  pointT *GOODpointp;     /*   the actual point */
+  boolT GOODthreshold;    /* true 'Pd/PD' if qh.lower_threshold/upper_threshold defined
+                             set if qh.UPPERdelaunay (qh_initbuild)
+                             false if qh.SPLITthreshold */
+  int   GOODvertex;       /* 'QVn' or 'QV-n' (n+1, n-1), good facet if vertex for point n (or not) */
+  pointT *GOODvertexp;     /*   the actual point */
+  boolT HALFspace;        /* true 'Hn,n,n' if halfspace intersection */
+  boolT ISqhullQh;        /* Set by Qhull.cpp on initialization */
+  int   IStracing;        /* 'Tn' trace execution, 0=none, 1=least, 4=most, -1=events */
+  int   KEEParea;         /* 'PAn' number of largest facets to keep */
+  boolT KEEPcoplanar;     /* true 'Qc' if keeping nearest facet for coplanar points */
+  boolT KEEPinside;       /* true 'Qi' if keeping nearest facet for inside points
+                              set automatically if 'd Qc' */
+  int   KEEPmerge;        /* 'PMn' number of facets to keep with most merges */
+  realT KEEPminArea;      /* 'PFn' minimum facet area to keep */
+  realT MAXcoplanar;      /* 'Un' max distance below a facet to be coplanar*/
+  int   MAXwide;          /* 'QWn' max ratio for wide facet, otherwise error unless Q12-allow-wide */
+  boolT MERGEexact;       /* true 'Qx' if exact merges (concave, degen, dupridge, flipped)
+                             tested by qh_checkzero and qh_test_*_merge */
+  boolT MERGEindependent; /* true if merging independent sets of coplanar facets. 'Q2' disables */
+  boolT MERGING;          /* true if exact-, pre- or post-merging, with angle and centrum tests */
+  realT   premerge_centrum;  /*   'C-n' centrum_radius when pre merging.  Default is round-off */
+  realT   postmerge_centrum; /*   'Cn' centrum_radius when post merging.  Default is round-off */
+  boolT MERGEpinched;     /* true 'Q14' if merging pinched vertices due to dupridge */
+  boolT MERGEvertices;    /* true if merging redundant vertices, 'Q3' disables or qh.hull_dim > qh_DIMmergeVertex */
+  realT MINvisible;       /* 'Vn' min. distance for a facet to be visible */
+  boolT NOnarrow;         /* true 'Q10' if no special processing for narrow distributions */
+  boolT NOnearinside;     /* true 'Q8' if ignore near-inside points when partitioning, qh_check_points may fail */
+  boolT NOpremerge;       /* true 'Q0' if no defaults for C-0 or Qx */
+  boolT ONLYgood;         /* true 'Qg' if process points with good visible or horizon facets */
+  boolT ONLYmax;          /* true 'Qm' if only process points that increase max_outside */
+  boolT PICKfurthest;     /* true 'Q9' if process furthest of furthest points*/
+  boolT POSTmerge;        /* true if merging after buildhull ('Cn' or 'An') */
+  boolT PREmerge;         /* true if merging during buildhull ('C-n' or 'A-n') */
+                        /* NOTE: some of these names are similar to qh_PRINT names */
+  boolT PRINTcentrums;    /* true 'Gc' if printing centrums */
+  boolT PRINTcoplanar;    /* true 'Gp' if printing coplanar points */
+  int   PRINTdim;         /* print dimension for Geomview output */
+  boolT PRINTdots;        /* true 'Ga' if printing all points as dots */
+  boolT PRINTgood;        /* true 'Pg' if printing good facets
+                             PGood set if 'd', 'PAn', 'PFn', 'PMn', 'QGn', 'QG-n', 'QVn', or 'QV-n' */
+  boolT PRINTinner;       /* true 'Gi' if printing inner planes */
+  boolT PRINTneighbors;   /* true 'PG' if printing neighbors of good facets */
+  boolT PRINTnoplanes;    /* true 'Gn' if printing no planes */
+  boolT PRINToptions1st;  /* true 'FO' if printing options to stderr */
+  boolT PRINTouter;       /* true 'Go' if printing outer planes */
+  boolT PRINTprecision;   /* false 'Pp' if not reporting precision problems */
+  qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
+  boolT PRINTridges;      /* true 'Gr' if print ridges */
+  boolT PRINTspheres;     /* true 'Gv' if print vertices as spheres */
+  boolT PRINTstatistics;  /* true 'Ts' if printing statistics to stderr */
+  boolT PRINTsummary;     /* true 's' if printing summary to stderr */
+  boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
+  boolT PROJECTdelaunay;  /* true if DELAUNAY, no readpoints() and
+                             need projectinput() for Delaunay in qh_init_B */
+  int   PROJECTinput;     /* number of projected dimensions 'bn:0Bn:0' */
+  boolT RANDOMdist;       /* true 'Rn' if randomly change distplane and setfacetplane */
+  realT RANDOMfactor;     /*    maximum random perturbation */
+  realT RANDOMa;          /*    qh_randomfactor is randr * RANDOMa + RANDOMb */
+  realT RANDOMb;
+  boolT RANDOMoutside;    /* true 'Qr' if select a random outside point */
+  int   REPORTfreq;       /* 'TFn' buildtracing reports every n facets */
+  int   REPORTfreq2;      /* tracemerging reports every REPORTfreq/2 facets */
+  int   RERUN;            /* 'TRn' rerun qhull n times (qh.build_cnt) */
+  int   ROTATErandom;     /* 'QRn' n<-1 random seed, n==-1 time is seed, n==0 random rotation by time, n>0 rotate input */
+  boolT SCALEinput;       /* true 'Qbk' if scaling input */
+  boolT SCALElast;        /* true 'Qbb' if scale last coord to max prev coord */
+  boolT SETroundoff;      /* true 'En' if qh.DISTround is predefined */
+  boolT SKIPcheckmax;     /* true 'Q5' if skip qh_check_maxout, qh_check_points may fail */
+  boolT SKIPconvex;       /* true 'Q6' if skip convexity testing during pre-merge */
+  boolT SPLITthresholds;  /* true 'Pd/PD' if upper_/lower_threshold defines a region
+                               else qh.GOODthresholds
+                               set if qh.DELAUNAY (qh_initbuild)
+                               used only for printing (!for qh.ONLYgood) */
+  int   STOPadd;          /* 'TAn' 1+n for stop after adding n vertices */
+  int   STOPcone;         /* 'TCn' 1+n for stopping after cone for point n */
+                          /*       also used by qh_build_withresart for err exit*/
+  int   STOPpoint;        /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
+                                        adding point n */
+  int   TESTpoints;       /* 'QTn' num of test points after qh.num_points.  Test points always coplanar. */
+  boolT TESTvneighbors;   /*  true 'Qv' if test vertex neighbors at end */
+  int   TRACElevel;       /* 'Tn' conditional IStracing level */
+  int   TRACElastrun;     /*  qh.TRACElevel applies to last qh.RERUN */
+  int   TRACEpoint;       /* 'TPn' start tracing when point n is a vertex, use qh_IDunknown (-1) after qh_buildhull and qh_postmerge */
+  realT TRACEdist;        /* 'TWn' start tracing when merge distance too big */
+  int   TRACEmerge;       /* 'TMn' start tracing before this merge */
+  boolT TRIangulate;      /* true 'Qt' if triangulate non-simplicial facets */
+  boolT TRInormals;       /* true 'Q11' if triangulate duplicates ->normal and ->center (sets Qt) */
+  boolT UPPERdelaunay;    /* true 'Qu' if computing furthest-site Delaunay */
+  boolT USEstdout;        /* true 'Tz' if using stdout instead of stderr */
+  boolT VERIFYoutput;     /* true 'Tv' if verify output at end of qhull */
+  boolT VIRTUALmemory;    /* true 'Q7' if depth-first processing in buildhull */
+  boolT VORONOI;          /* true 'v' if computing Voronoi diagram, also sets qh.DELAUNAY */
+
+  /*--------input constants ---------*/
+  realT AREAfactor;       /* 1/(hull_dim-1)! for converting det's to area */
+  boolT DOcheckmax;       /* true if calling qh_check_maxout (!qh.SKIPcheckmax && qh.MERGING) */
+  char  *feasible_string;  /* feasible point 'Hn,n,n' for halfspace intersection */
+  coordT *feasible_point;  /*    as coordinates, both malloc'd */
+  boolT GETarea;          /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io_r.c */
+  boolT KEEPnearinside;   /* true if near-inside points in coplanarset */
+  int   hull_dim;         /* dimension of hull, set by initbuffers */
+  int   input_dim;        /* dimension of input, set by initbuffers */
+  int   num_points;       /* number of input points */
+  pointT *first_point;    /* array of input points, see POINTSmalloc */
+  boolT POINTSmalloc;     /*   true if qh.first_point/num_points allocated */
+  pointT *input_points;   /* copy of original qh.first_point for input points for qh_joggleinput */
+  boolT input_malloc;     /* true if qh.input_points malloc'd */
+  char  qhull_command[256];/* command line that invoked this program */
+  int   qhull_commandsiz2; /*    size of qhull_command at qh_clear_outputflags */
+  char  rbox_command[256]; /* command line that produced the input points */
+  char  qhull_options[512];/* descriptive list of options */
+  int   qhull_optionlen;  /*    length of last line */
+  int   qhull_optionsiz;  /*    size of qhull_options at qh_build_withrestart */
+  int   qhull_optionsiz2; /*    size of qhull_options at qh_clear_outputflags */
+  int   run_id;           /* non-zero, random identifier for this instance of qhull */
+  boolT VERTEXneighbors;  /* true if maintaining vertex neighbors */
+  boolT ZEROcentrum;      /* true if 'C-0' or 'C-0 Qx' and not post-merging or 'A-n'.  Sets ZEROall_ok */
+  realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
+                             must set either GOODthreshold or SPLITthreshold
+                             if qh.DELAUNAY, default is 0.0 for upper envelope (qh_initbuild) */
+  realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
+  realT *upper_bound;     /* scale point[k] to new upper bound */
+  realT *lower_bound;     /* scale point[k] to new lower bound
+                             project if both upper_ and lower_bound == 0 */
+
+/*----------------------------------
+
+  qh precision constants
+    precision constants for Qhull
+
+  notes:
+    qh_detroundoff [geom2_r.c] computes the maximum roundoff error for distance
+    and other computations.  It also sets default values for the
+    qh constants above.
+*/
+  realT ANGLEround;       /* max round off error for angles */
+  realT centrum_radius;   /* max centrum radius for convexity ('Cn' + 2*qh.DISTround) */
+  realT cos_max;          /* max cosine for convexity (roundoff added) */
+  realT DISTround;        /* max round off error for distances, qh.SETroundoff ('En') overrides qh_distround */
+  realT MAXabs_coord;     /* max absolute coordinate */
+  realT MAXlastcoord;     /* max last coordinate for qh_scalelast */
+  realT MAXoutside;       /* max target for qh.max_outside/f.maxoutside, base for qh_RATIO...
+                             recomputed at qh_addpoint, unrelated to qh_MAXoutside */
+  realT MAXsumcoord;      /* max sum of coordinates */
+  realT MAXwidth;         /* max rectilinear width of point coordinates */
+  realT MINdenom_1;       /* min. abs. value for 1/x */
+  realT MINdenom;         /*    use divzero if denominator < MINdenom */
+  realT MINdenom_1_2;     /* min. abs. val for 1/x that allows normalization */
+  realT MINdenom_2;       /*    use divzero if denominator < MINdenom_2 */
+  realT MINlastcoord;     /* min. last coordinate for qh_scalelast */
+  realT *NEARzero;        /* hull_dim array for near zero in gausselim */
+  realT NEARinside;       /* keep points for qh_check_maxout if close to facet */
+  realT ONEmerge;         /* max distance for merging simplicial facets */
+  realT outside_err;      /* application's epsilon for coplanar points
+                             qh_check_bestdist() qh_check_points() reports error if point outside */
+  realT WIDEfacet;        /* size of wide facet for skipping ridge in
+                             area computation and locking centrum */
+  boolT NARROWhull;       /* set in qh_initialhull if angle < qh_MAXnarrow */
+
+/*----------------------------------
+
+  qh internal constants
+    internal constants for Qhull
+*/
+  char qhull[sizeof("qhull")]; /* "qhull" for checking ownership while debugging */
+  jmp_buf errexit;        /* exit label for qh_errexit, defined by setjmp() and NOerrexit */
+  char    jmpXtra[40];    /* extra bytes in case jmp_buf is defined wrong by compiler */
+  jmp_buf restartexit;    /* restart label for qh_errexit, defined by setjmp() and ALLOWrestart */
+  char    jmpXtra2[40];   /* extra bytes in case jmp_buf is defined wrong by compiler*/
+  FILE *  fin;            /* pointer to input file, init by qh_initqhull_start2 */
+  FILE *  fout;           /* pointer to output file */
+  FILE *  ferr;           /* pointer to error file */
+  pointT *interior_point; /* center point of the initial simplex*/
+  int     normal_size;    /* size in bytes for facet normals and point coords */
+  int     center_size;    /* size in bytes for Voronoi centers */
+  int     TEMPsize;       /* size for small, temporary sets (in quick mem) */
+
+/*----------------------------------
+
+  qh facet and vertex lists
+    defines lists of facets, new facets, visible facets, vertices, and
+    new vertices.  Includes counts, next ids, and trace ids.
+  see:
+    qh_resetlists()
+*/
+  facetT *facet_list;     /* first facet */
+  facetT *facet_tail;     /* end of facet_list (dummy facet with id 0 and next==NULL) */
+  facetT *facet_next;     /* next facet for buildhull()
+                             previous facets do not have outside sets
+                             NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
+  facetT *newfacet_list;  /* list of new facets to end of facet_list
+                             qh_postmerge sets newfacet_list to facet_list */
+  facetT *visible_list;   /* list of visible facets preceding newfacet_list,
+                             end of visible list if !facet->visible, same as newfacet_list
+                             qh_findhorizon sets visible_list at end of facet_list
+                             qh_willdelete prepends to visible_list
+                             qh_triangulate appends mirror facets to visible_list at end of facet_list
+                             qh_postmerge sets visible_list to facet_list
+                             qh_deletevisible deletes the visible facets */
+  int       num_visible;  /* current number of visible facets */
+  unsigned int tracefacet_id; /* set at init, then can print whenever */
+  facetT  *tracefacet;    /*   set in newfacet/mergefacet, undone in delfacet and qh_errexit */
+  unsigned int traceridge_id; /* set at init, then can print whenever */
+  ridgeT  *traceridge;    /*   set in newridge, undone in delridge, errexit, errexit2, makenew_nonsimplicial, mergecycle_ridges */
+  unsigned int tracevertex_id; /* set at buildtracing, can print whenever */
+  vertexT *tracevertex;   /*   set in newvertex, undone in delvertex and qh_errexit */
+  vertexT *vertex_list;   /* list of all vertices, to vertex_tail */
+  vertexT *vertex_tail;   /*      end of vertex_list (dummy vertex with ID 0, next NULL) */
+  vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
+                             all vertices have 'newfacet' set */
+  int   num_facets;       /* number of facets in facet_list
+                             includes visible faces (num_visible) */
+  int   num_vertices;     /* number of vertices in facet_list */
+  int   num_outside;      /* number of points in outsidesets (for tracing and RANDOMoutside)
+                               includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
+  int   num_good;         /* number of good facets (after qh_findgood_all or qh_markkeep) */
+  unsigned int facet_id;  /* ID of next, new facet from newfacet() */
+  unsigned int ridge_id;  /* ID of next, new ridge from newridge() */
+  unsigned int vertex_id; /* ID of next, new vertex from newvertex() */
+  unsigned int first_newfacet; /* ID of first_newfacet for qh_buildcone, or 0 if none */
+
+/*----------------------------------
+
+  qh global variables
+    defines minimum and maximum distances, next visit ids, several flags,
+    and other global variables.
+    initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
+*/
+  unsigned long hulltime; /* ignore time to set up input and randomize */
+                          /*   use 'unsigned long' to avoid wrap-around errors */
+  boolT ALLOWrestart;     /* true if qh_joggle_restart can use qh.restartexit */
+  int   build_cnt;        /* number of calls to qh_initbuild */
+  qh_CENTER CENTERtype;   /* current type of facet->center, qh_CENTER */
+  int   furthest_id;      /* pointid of furthest point, for tracing */
+  int   last_errcode;     /* last errcode from qh_fprintf, reset in qh_build_withrestart */
+  facetT *GOODclosest;    /* closest facet to GOODthreshold in qh_findgood */
+  pointT *coplanar_apex;  /* last apex declared a coplanar point by qh_getpinchedmerges, prevents infinite loop */
+  boolT hasAreaVolume;    /* true if totarea, totvol was defined by qh_getarea */
+  boolT hasTriangulation; /* true if triangulation created by qh_triangulate */
+  boolT isRenameVertex;   /* true during qh_merge_pinchedvertices, disables duplicate ridge vertices in qh_checkfacet */
+  realT JOGGLEmax;        /* set 'QJn' if randomly joggle input. 'QJ'/'QJ0.0' sets default (qh_detjoggle) */
+  boolT maxoutdone;       /* set qh_check_maxout(), cleared by qh_addpoint() */
+  realT max_outside;      /* maximum distance from a point to a facet,
+                               before roundoff, not simplicial vertices
+                               actual outer plane is +DISTround and
+                               computed outer plane is +2*DISTround */
+  realT max_vertex;       /* maximum distance (>0) from vertex to a facet,
+                               before roundoff, due to a merge */
+  realT min_vertex;       /* minimum distance (<0) from vertex to a facet,
+                               before roundoff, due to a merge
+                               if qh.JOGGLEmax, qh_makenewplanes sets it
+                               recomputed if qh.DOcheckmax, default -qh.DISTround */
+  boolT NEWfacets;        /* true while visible facets invalid due to new or merge
+                              from qh_makecone/qh_attachnewfacets to qh_resetlists */
+  boolT NEWtentative;     /* true while new facets are tentative due to !qh.IGNOREpinched or qh.ONLYgood
+                              from qh_makecone to qh_attachnewfacets */
+  boolT findbestnew;      /* true if partitioning calls qh_findbestnew */
+  boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
+  boolT NOerrexit;        /* true if qh.errexit is not available, cleared after setjmp.  See qh.ERREXITcalled */
+  realT PRINTcradius;     /* radius for printing centrums */
+  realT PRINTradius;      /* radius for printing vertex spheres and points */
+  boolT POSTmerging;      /* true when post merging */
+  int   printoutvar;      /* temporary variable for qh_printbegin, etc. */
+  int   printoutnum;      /* number of facets printed */
+  unsigned int repart_facetid; /* previous facetid to prevent recursive qh_partitioncoplanar+qh_partitionpoint */
+  int   retry_addpoint;   /* number of retries of qh_addpoint due to merging pinched vertices */
+  boolT QHULLfinished;    /* True after qhull() is finished */
+  realT totarea;          /* 'FA': total facet area computed by qh_getarea, hasAreaVolume */
+  realT totvol;           /* 'FA': total volume computed by qh_getarea, hasAreaVolume */
+  unsigned int visit_id;  /* unique ID for searching neighborhoods, */
+  unsigned int vertex_visit; /* unique ID for searching vertices, reset with qh_buildtracing */
+  boolT WAScoplanar;      /* True if qh_partitioncoplanar (qh_check_maxout) */
+  boolT ZEROall_ok;       /* True if qh_checkzero always succeeds */
+
+/*----------------------------------
+
+  qh global sets
+    defines sets for merging, initial simplex, hashing, extra input points,
+    and deleted vertices
+*/
+  setT *facet_mergeset;   /* temporary set of merges to be done */
+  setT *degen_mergeset;   /* temporary set of degenerate and redundant merges */
+  setT *vertex_mergeset;  /* temporary set of vertex merges */
+  setT *hash_table;       /* hash table for matching ridges in qh_matchfacets
+                             size is setsize() */
+  setT *other_points;     /* additional points */
+  setT *del_vertices;     /* vertices to partition and delete with visible
+                             facets.  v.deleted is set for checkfacet */
+
+/*----------------------------------
+
+  qh global buffers
+    defines buffers for maxtrix operations, input, and error messages
+*/
+  coordT *gm_matrix;      /* (dim+1)Xdim matrix for geom_r.c */
+  coordT **gm_row;        /* array of gm_matrix rows */
+  char* line;             /* malloc'd input line of maxline+1 chars */
+  int maxline;
+  coordT *half_space;     /* malloc'd input array for halfspace (qh.normal_size+coordT) */
+  coordT *temp_malloc;    /* malloc'd input array for points */
+
+/*----------------------------------
+
+  qh static variables
+    defines static variables for individual functions
+
+  notes:
+    do not use 'static' within a function.  Multiple instances of qhull
+    may exist.
+
+    do not assume zero initialization, 'QPn' may cause a restart
+*/
+  boolT ERREXITcalled;    /* true during qh_errexit (prevents duplicate calls).  see qh.NOerrexit */
+  boolT firstcentrum;     /* for qh_printcentrum */
+  boolT old_randomdist;   /* save RANDOMdist flag during io, tracing, or statistics */
+  setT *coplanarfacetset; /* set of coplanar facets for searching qh_findbesthorizon() */
+  realT last_low;         /* qh_scalelast parameters for qh_setdelaunay */
+  realT last_high;
+  realT last_newhigh;
+  realT lastcpu;          /* for qh_buildtracing */
+  int   lastfacets;       /*   last qh.num_facets */
+  int   lastmerges;       /*   last zzval_(Ztotmerge) */
+  int   lastplanes;       /*   last zzval_(Zsetplane) */
+  int   lastdist;         /*   last zzval_(Zdistplane) */
+  unsigned int lastreport; /*  last qh.facet_id */
+  int mergereport;        /* for qh_tracemerging */
+  setT *old_tempstack;    /* for saving qh->qhmem.tempstack in save_qhull */
+  int   ridgeoutnum;      /* number of ridges for 4OFF output (qh_printbegin,etc) */
+
+/*----------------------------------
+
+  qh memory management, rbox globals, and statistics
+
+  Replaces global data structures defined for libqhull
+*/
+  int     last_random;    /* Last random number from qh_rand (random_r.c) */
+  jmp_buf rbox_errexit;   /* errexit from rboxlib_r.c, defined by qh_rboxpoints() only */
+  char    jmpXtra3[40];   /* extra bytes in case jmp_buf is defined wrong by compiler */
+  int     rbox_isinteger;
+  double  rbox_out_offset;
+  void *  cpp_object;     /* C++ pointer.  Currently used by RboxPoints.qh_fprintf_rbox */
+  void *  cpp_other;      /* C++ pointer.  Reserved for other users */
+  void *  cpp_user;       /* C++ pointer.  Currently used by QhullUser.qh_fprintf */
+
+  /* Last, otherwise zero'd by qh_initqhull_start2 (global_r.c */
+  qhmemT  qhmem;          /* Qhull managed memory (mem_r.h) */
+  /* After qhmem because its size depends on the number of statistics */
+  qhstatT qhstat;         /* Qhull statistics (stat_r.h) */
+};
+
+/*=========== -macros- =========================*/
+
+/*----------------------------------
+
+  otherfacet_(ridge, facet)
+    return neighboring facet for a ridge in facet
+*/
+#define otherfacet_(ridge, facet) \
+                        (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
+
+/*----------------------------------
+
+  getid_(p)
+    return int ID for facet, ridge, or vertex
+    return qh_IDunknown(-1) if NULL
+    return 0 if facet_tail or vertex_tail
+*/
+#define getid_(p)       ((p) ? (int)((p)->id) : qh_IDunknown)
+
+/*============== FORALL macros ===================*/
+
+/*----------------------------------
+
+  FORALLfacets { ... }
+    assign 'facet' to each facet in qh.facet_list
+
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+    assumes qh defined
+
+  see:
+    FORALLfacet_( facetlist )
+*/
+#define FORALLfacets for (facet=qh->facet_list;facet && facet->next;facet=facet->next)
+
+/*----------------------------------
+
+  FORALLpoints { ... }
+    assign 'point' to each point in qh.first_point, qh.num_points
+
+  notes:
+    assumes qh defined
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoints FORALLpoint_(qh, qh->first_point, qh->num_points)
+
+/*----------------------------------
+
+  FORALLpoint_(qh, points, num) { ... }
+    assign 'point' to each point in points array of num points
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoint_(qh, points, num) for (point=(points), \
+      pointtemp= (points)+qh->hull_dim*(num); point < pointtemp; point += qh->hull_dim)
+
+/*----------------------------------
+
+  FORALLvertices { ... }
+    assign 'vertex' to each vertex in qh.vertex_list
+
+  declare:
+    vertexT *vertex;
+
+  notes:
+    assumes qh.vertex_list terminated by NULL or a sentinel (v.next==NULL)
+    assumes qh defined
+*/
+#define FORALLvertices for (vertex=qh->vertex_list;vertex && vertex->next;vertex= vertex->next)
+
+/*----------------------------------
+
+  FOREACHfacet_( facets ) { ... }
+    assign 'facet' to each facet in facets
+
+  declare:
+    facetT *facet, **facetp;
+
+  notes:
+    assumes set is not modified
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHfacet_(facets)    FOREACHsetelement_(facetT, facets, facet)
+
+/*----------------------------------
+
+  FOREACHneighbor_( facet ) { ... }
+    assign 'neighbor' to each neighbor in facet->neighbors
+
+  FOREACHneighbor_( vertex ) { ... }
+    assign 'neighbor' to each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighbor, **neighborp;
+
+  notes:
+    assumes set is not modified
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHneighbor_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighbor)
+
+/*----------------------------------
+
+  FOREACHpoint_( points ) { ... }
+    assign 'point' to each point in points set
+
+  declare:
+    pointT *point, **pointp;
+
+  notes:
+    assumes set is not modified
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHpoint_(points)    FOREACHsetelement_(pointT, points, point)
+
+/*----------------------------------
+
+  FOREACHridge_( ridges ) { ... }
+    assign 'ridge' to each ridge in ridges set
+
+  declare:
+    ridgeT *ridge, **ridgep;
+
+  notes:
+    assumes set is not modified
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHridge_(ridges)    FOREACHsetelement_(ridgeT, ridges, ridge)
+
+/*----------------------------------
+
+  FOREACHvertex_( vertices ) { ... }
+    assign 'vertex' to each vertex in vertices set
+
+  declare:
+    vertexT *vertex, **vertexp;
+
+  notes:
+    assumes set is not modified
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
+
+/*----------------------------------
+
+  FOREACHfacet_i_(qh, facets ) { ... }
+    assign 'facet' and 'facet_i' for each facet in facets set
+
+  declare:
+    facetT *facet;
+    int     facet_n, facet_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHfacet_i_(qh, facets)    FOREACHsetelement_i_(qh, facetT, facets, facet)
+
+/*----------------------------------
+
+  FOREACHneighbor_i_(qh, facet ) { ... }
+    assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
+
+  declare:
+    facetT *neighbor;
+    int     neighbor_n, neighbor_i;
+
+  notes:
+    see FOREACHsetelement_i_
+    for facet neighbors of vertex, need to define a new macro
+*/
+#define FOREACHneighbor_i_(qh, facet)  FOREACHsetelement_i_(qh, facetT, facet->neighbors, neighbor)
+
+/*----------------------------------
+
+  FOREACHpoint_i_(qh, points ) { ... }
+    assign 'point' and 'point_i' for each point in points set
+
+  declare:
+    pointT *point;
+    int     point_n, point_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHpoint_i_(qh, points)    FOREACHsetelement_i_(qh, pointT, points, point)
+
+/*----------------------------------
+
+  FOREACHridge_i_(qh, ridges ) { ... }
+    assign 'ridge' and 'ridge_i' for each ridge in ridges set
+
+  declare:
+    ridgeT *ridge;
+    int     ridge_n, ridge_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHridge_i_(qh, ridges)    FOREACHsetelement_i_(qh, ridgeT, ridges, ridge)
+
+/*----------------------------------
+
+  FOREACHvertex_i_(qh, vertices ) { ... }
+    assign 'vertex' and 'vertex_i' for each vertex in vertices set
+
+  declare:
+    vertexT *vertex;
+    int     vertex_n, vertex_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHvertex_i_(qh, vertices) FOREACHsetelement_i_(qh, vertexT, vertices, vertex)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/********* -libqhull_r.c prototypes (duplicated from qhull_ra.h) **********************/
+
+void    qh_qhull(qhT *qh);
+boolT   qh_addpoint(qhT *qh, pointT *furthest, facetT *facet, boolT checkdist);
+void    QH_NORETURN qh_errexit2(qhT *qh, int exitcode, facetT *facet, facetT *otherfacet);
+void    qh_printsummary(qhT *qh, FILE *fp);
+
+/********* -user_r.c prototypes (alphabetical) **********************/
+
+void    QH_NORETURN qh_errexit(qhT *qh, int exitcode, facetT *facet, ridgeT *ridge);
+void    qh_errprint(qhT *qh, const char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
+int     qh_new_qhull(qhT *qh, int dim, int numpoints, coordT *points, boolT ismalloc,
+                char *qhull_cmd, FILE *outfile, FILE *errfile);
+void    qh_printfacetlist(qhT *qh, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printhelp_degenerate(qhT *qh, FILE *fp);
+void    qh_printhelp_internal(qhT *qh, FILE *fp);
+void    qh_printhelp_narrowhull(qhT *qh, FILE *fp, realT minangle);
+void    qh_printhelp_singular(qhT *qh, FILE *fp);
+void    qh_printhelp_topology(qhT *qh, FILE *fp);
+void    qh_printhelp_wide(qhT *qh, FILE *fp);
+void    qh_user_memsizes(qhT *qh);
+
+/********* -usermem_r.c prototypes (alphabetical) **********************/
+void    QH_NORETURN qh_exit(int exitcode);
+void    qh_fprintf_stderr(int msgcode, const char *fmt, ... ) QH_PRINTF_LIKE(2, 3);
+void    qh_free(void *mem);
+void   *qh_malloc(size_t size);
+
+/********* -userprintf_r.c and userprintf_rbox_r.c prototypes **********************/
+void    qh_fprintf(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... ) QH_PRINTF_LIKE(4, 5);
+void    qh_fprintf_rbox(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... ) QH_PRINTF_LIKE(4, 5);
+
+/***** -geom_r.c/geom2_r.c/random_r.c prototypes (duplicated from geom_r.h, random_r.h) ****************/
+
+facetT *qh_findbest(qhT *qh, pointT *point, facetT *startfacet,
+                     boolT bestoutside, boolT newfacets, boolT noupper,
+                     realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbestnew(qhT *qh, pointT *point, facetT *startfacet,
+                     realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
+boolT   qh_gram_schmidt(qhT *qh, int dim, realT **rows);
+void    qh_outerinner(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane);
+void    qh_projectinput(qhT *qh);
+void    qh_randommatrix(qhT *qh, realT *buffer, int dim, realT **row);
+void    qh_rotateinput(qhT *qh, realT **rows);
+void    qh_scaleinput(qhT *qh);
+void    qh_setdelaunay(qhT *qh, int dim, int count, pointT *points);
+coordT  *qh_sethalfspace_all(qhT *qh, int dim, int count, coordT *halfspaces, pointT *feasible);
+
+/***** -global_r.c prototypes (alphabetical) ***********************/
+
+unsigned long qh_clock(qhT *qh);
+void    qh_checkflags(qhT *qh, char *command, char *hiddenflags);
+void    qh_clear_outputflags(qhT *qh);
+void    qh_freebuffers(qhT *qh);
+void    qh_freeqhull(qhT *qh, boolT allmem);
+void    qh_init_A(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
+void    qh_init_B(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_init_qhull_command(qhT *qh, int argc, char *argv[]);
+void    qh_initbuffers(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_initflags(qhT *qh, char *command);
+void    qh_initqhull_buffers(qhT *qh);
+void    qh_initqhull_globals(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_initqhull_mem(qhT *qh);
+void    qh_initqhull_outputflags(qhT *qh);
+void    qh_initqhull_start(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile);
+void    qh_initqhull_start2(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile);
+void    qh_initthresholds(qhT *qh, char *command);
+void    qh_lib_check(int qhullLibraryType, int qhTsize, int vertexTsize, int ridgeTsize, int facetTsize, int setTsize, int qhmemTsize);
+void    qh_option(qhT *qh, const char *option, int *i, realT *r);
+void    qh_zero(qhT *qh, FILE *errfile);
+
+/***** -io_r.c prototypes (duplicated from io_r.h) ***********************/
+
+void    qh_dfacet(qhT *qh, unsigned int id);
+void    qh_dvertex(qhT *qh, unsigned int id);
+void    qh_printneighborhood(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
+void    qh_produce_output(qhT *qh);
+coordT *qh_readpoints(qhT *qh, int *numpoints, int *dimension, boolT *ismalloc);
+
+
+/********* -poly_r.c/poly2_r.c prototypes (duplicated from poly_r.h) **********************/
+
+void    qh_check_output(qhT *qh);
+void    qh_check_points(qhT *qh);
+setT   *qh_facetvertices(qhT *qh, facetT *facetlist, setT *facets, boolT allfacets);
+facetT *qh_findbestfacet(qhT *qh, pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+vertexT *qh_nearvertex(qhT *qh, facetT *facet, pointT *point, realT *bestdistp);
+pointT *qh_point(qhT *qh, int id);
+setT   *qh_pointfacet(qhT *qh /* qh.facet_list */);
+int     qh_pointid(qhT *qh, pointT *point);
+setT   *qh_pointvertex(qhT *qh /* qh.facet_list */);
+void    qh_setvoronoi_all(qhT *qh);
+void    qh_triangulate(qhT *qh /* qh.facet_list */);
+
+/********* -rboxlib_r.c prototypes **********************/
+int     qh_rboxpoints(qhT *qh, char* rbox_command);
+void    QH_NORETURN qh_errexit_rbox(qhT *qh, int exitcode);
+
+/************************** accessors.c prototypes ******************************/
+
+#define QH_GETTER(TYPE, FIELD) TYPE qh_get_##FIELD(const qhT *qh)
+#define QH_SETTER(TYPE, FIELD) void qh_set_##FIELD(qhT *qh, TYPE _val_)
+QH_GETTER(facetT*, facet_list);
+QH_GETTER(pointT*, first_point);
+QH_GETTER(int, hull_dim);
+QH_GETTER(int, num_facets);
+QH_GETTER(int, num_points);
+QH_GETTER(int, num_vertices);
+QH_GETTER(vertexT*, vertex_list);
+QH_GETTER(realT, totarea);
+QH_GETTER(realT, totvol);
+QH_GETTER(boolT, hasAreaVolume);
+QH_SETTER(boolT, hasAreaVolume);
+QH_GETTER(boolT, hasTriangulation);
+QH_SETTER(boolT, hasTriangulation);
+QH_GETTER(int, num_good);
+QH_GETTER(setT*, del_vertices);
+QH_GETTER(int, input_dim);
+QH_GETTER(boolT, DELAUNAY);
+QH_GETTER(boolT, SCALElast);
+QH_GETTER(boolT, KEEPcoplanar);
+QH_GETTER(boolT, MERGEexact);
+QH_GETTER(boolT, NOerrexit);
+QH_GETTER(boolT, PROJECTdelaunay);
+QH_GETTER(boolT, ATinfinity);
+QH_GETTER(boolT, UPPERdelaunay);
+QH_GETTER(int, normal_size);
+QH_GETTER(int, num_visible);
+QH_GETTER(int, center_size);
+QH_GETTER(const char *, qhull_command);
+QH_GETTER(facetT*, facet_tail);
+QH_GETTER(vertexT*, vertex_tail);
+QH_GETTER(unsigned int, facet_id);
+QH_GETTER(unsigned int, visit_id);
+QH_GETTER(unsigned int, vertex_visit);
+QH_GETTER(pointT*, input_points);
+QH_GETTER(coordT*, feasible_point);
+QH_GETTER(realT, last_low);
+QH_GETTER(realT, last_high);
+QH_GETTER(realT, last_newhigh);
+QH_GETTER(realT, max_outside);
+QH_GETTER(realT, MINoutside);
+QH_GETTER(realT, DISTround);
+QH_GETTER(setT*, other_points);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFlibqhull */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.c
new file mode 100644
index 00000000000..57e80edda9b
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.c
@@ -0,0 +1,566 @@
+/*
  ---------------------------------
+
+  mem_r.c
+    memory management routines for qhull
+
+  See libqhull/mem.c for a standalone program.
+
+  To initialize memory:
+
+    qh_meminit(qh, stderr);
+    qh_meminitbuffers(qh, qh->IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
+    qh_memsize(qh, (int)sizeof(facetT));
+    qh_memsize(qh, (int)sizeof(facetT));
+    ...
+    qh_memsetup(qh);
+
+  To free up all memory buffers:
+    qh_memfreeshort(qh, &curlong, &totlong);
+
+  if qh_NOmem,
+    malloc/free is used instead of mem_r.c
+
+  notes:
+    uses Quickfit algorithm (freelists for commonly allocated sizes)
+    assumes small sizes for freelists (it discards the tail of memory buffers)
+
+  see:
+    qh-mem_r.htm and mem_r.h
+    global_r.c (qh_initbuffers) for an example of using mem_r.c
+
+  Copyright (c) 1993-2020 The Geometry Center.
+  $Id: //main/2019/qhull/src/libqhull_r/mem_r.c#7 $$Change: 2953 $
+  $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#include "libqhull_r.h"  /* includes user_r.h and mem_r.h */
+
+#include 
+#include 
+#include 
+
+#ifndef qh_NOmem
+
+/*============= internal functions ==============*/
+
+static int qh_intcompare(const void *i, const void *j);
+
+/*========== functions in alphabetical order ======== */
+
+/*---------------------------------
+
+  qh_intcompare( i, j )
+    used by qsort and bsearch to compare two integers
+*/
+static int qh_intcompare(const void *i, const void *j) {
+  return(*((const int *)i) - *((const int *)j));
+} /* intcompare */
+
+
+/*----------------------------------
+
+  qh_memalloc(qh, insize )
+    returns object of insize bytes
+    qhmem is the global memory structure
+
+  returns:
+    pointer to allocated memory
+    errors if insufficient memory
+
+  notes:
+    use explicit type conversion to avoid type warnings on some compilers
+    actual object may be larger than insize
+    use qh_memalloc_() for inline code for quick allocations
+    logs allocations if 'T5'
+    caller is responsible for freeing the memory.
+    short memory is freed on shutdown by qh_memfreeshort unless qh_NOmem
+
+  design:
+    if size < qh->qhmem.LASTsize
+      if qh->qhmem.freelists[size] non-empty
+        return first object on freelist
+      else
+        round up request to size of qh->qhmem.freelists[size]
+        allocate new allocation buffer if necessary
+        allocate object from allocation buffer
+    else
+      allocate object with qh_malloc() in user_r.c
+*/
+void *qh_memalloc(qhT *qh, int insize) {
+  void **freelistp, *newbuffer;
+  int idx, size, n;
+  int outsize, bufsize;
+  void *object;
+
+  if (insize<0) {
+      qh_fprintf(qh, qh->qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d).  Did int overflow due to high-D?\n", insize); /* WARN64 */
+      qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+  }
+  if (insize>=0 && insize <= qh->qhmem.LASTsize) {
+    idx= qh->qhmem.indextable[insize];
+    outsize= qh->qhmem.sizetable[idx];
+    qh->qhmem.totshort += outsize;
+    freelistp= qh->qhmem.freelists+idx;
+    if ((object= *freelistp)) {
+      qh->qhmem.cntquick++;
+      qh->qhmem.totfree -= outsize;
+      *freelistp= *((void **)*freelistp);  /* replace freelist with next object */
+#ifdef qh_TRACEshort
+      n= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
+      if (qh->qhmem.IStracing >= 5)
+          qh_fprintf(qh, qh->qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
+#endif
+      return(object);
+    }else {
+      qh->qhmem.cntshort++;
+      if (outsize > qh->qhmem.freesize) {
+        qh->qhmem.totdropped += qh->qhmem.freesize;
+        if (!qh->qhmem.curbuffer)
+          bufsize= qh->qhmem.BUFinit;
+        else
+          bufsize= qh->qhmem.BUFsize;
+        if (!(newbuffer= qh_malloc((size_t)bufsize))) {
+          qh_fprintf(qh, qh->qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize);
+          qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+        }
+        *((void **)newbuffer)= qh->qhmem.curbuffer;  /* prepend newbuffer to curbuffer
+                                                    list.  newbuffer!=0 by QH6080 */
+        qh->qhmem.curbuffer= newbuffer;
+        size= ((int)sizeof(void **) + qh->qhmem.ALIGNmask) & ~qh->qhmem.ALIGNmask;
+        qh->qhmem.freemem= (void *)((char *)newbuffer+size);
+        qh->qhmem.freesize= bufsize - size;
+        qh->qhmem.totbuffer += bufsize - size; /* easier to check */
+        /* Periodically test totbuffer.  It matches at beginning and exit of every call */
+        n= qh->qhmem.totshort + qh->qhmem.totfree + qh->qhmem.totdropped + qh->qhmem.freesize - outsize;
+        if (qh->qhmem.totbuffer != n) {
+            qh_fprintf(qh, qh->qhmem.ferr, 6212, "qhull internal error (qh_memalloc): short totbuffer %d != totshort+totfree... %d\n", qh->qhmem.totbuffer, n);
+            qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+        }
+      }
+      object= qh->qhmem.freemem;
+      qh->qhmem.freemem= (void *)((char *)qh->qhmem.freemem + outsize);
+      qh->qhmem.freesize -= outsize;
+      qh->qhmem.totunused += outsize - insize;
+#ifdef qh_TRACEshort
+      n= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
+      if (qh->qhmem.IStracing >= 5)
+          qh_fprintf(qh, qh->qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
+#endif
+      return object;
+    }
+  }else {                     /* long allocation */
+    if (!qh->qhmem.indextable) {
+      qh_fprintf(qh, qh->qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
+      qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+    }
+    outsize= insize;
+    qh->qhmem.cntlong++;
+    qh->qhmem.totlong += outsize;
+    if (qh->qhmem.maxlong < qh->qhmem.totlong)
+      qh->qhmem.maxlong= qh->qhmem.totlong;
+    if (!(object= qh_malloc((size_t)outsize))) {
+      qh_fprintf(qh, qh->qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize);
+      qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+    }
+    if (qh->qhmem.IStracing >= 5)
+      qh_fprintf(qh, qh->qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, outsize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
+  }
+  return(object);
+} /* memalloc */
+
+
+/*----------------------------------
+
+  qh_memcheck(qh)
+*/
+void qh_memcheck(qhT *qh) {
+  int i, count, totfree= 0;
+  void *object;
+
+  if (!qh) {
+    qh_fprintf_stderr(6243, "qhull internal error (qh_memcheck): qh is 0.  It does not point to a qhT\n");
+    qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
+  }
+  if (qh->qhmem.ferr == 0 || qh->qhmem.IStracing < 0 || qh->qhmem.IStracing > 10 || (((qh->qhmem.ALIGNmask+1) & qh->qhmem.ALIGNmask) != 0)) {
+    qh_fprintf_stderr(6244, "qhull internal error (qh_memcheck): either qh->qhmem is overwritten or qh->qhmem is not initialized.  Call qh_meminit or qh_new_qhull before calling qh_mem routines.  ferr %p, IsTracing %d, ALIGNmask 0x%x\n",
+          (void *) qh->qhmem.ferr, qh->qhmem.IStracing, qh->qhmem.ALIGNmask);
+    qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
+  }
+  if (qh->qhmem.IStracing != 0)
+    qh_fprintf(qh, qh->qhmem.ferr, 8143, "qh_memcheck: check size of freelists on qh->qhmem\nqh_memcheck: A segmentation fault indicates an overwrite of qh->qhmem\n");
+  for (i=0; i < qh->qhmem.TABLEsize; i++) {
+    count=0;
+    for (object= qh->qhmem.freelists[i]; object; object= *((void **)object))
+      count++;
+    totfree += qh->qhmem.sizetable[i] * count;
+  }
+  if (totfree != qh->qhmem.totfree) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6211, "qhull internal error (qh_memcheck): totfree %d not equal to freelist total %d\n", qh->qhmem.totfree, totfree);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  if (qh->qhmem.IStracing != 0)
+    qh_fprintf(qh, qh->qhmem.ferr, 8144, "qh_memcheck: total size of freelists totfree (%d) is the same as qh->qhmem.totfree\n", totfree);
+} /* memcheck */
+
+/*----------------------------------
+
+  qh_memfree(qh, object, insize )
+    free up an object of size bytes
+    size is insize from qh_memalloc
+
+  notes:
+    object may be NULL
+    type checking warns if using (void **)object
+    use qh_memfree_() for quick free's of small objects
+
+  design:
+    if size <= qh->qhmem.LASTsize
+      append object to corresponding freelist
+    else
+      call qh_free(object)
+*/
+void qh_memfree(qhT *qh, void *object, int insize) {
+  void **freelistp;
+  int idx, outsize;
+
+  if (!object)
+    return;
+  if (insize <= qh->qhmem.LASTsize) {
+    qh->qhmem.freeshort++;
+    idx= qh->qhmem.indextable[insize];
+    outsize= qh->qhmem.sizetable[idx];
+    qh->qhmem.totfree += outsize;
+    qh->qhmem.totshort -= outsize;
+    freelistp= qh->qhmem.freelists + idx;
+    *((void **)object)= *freelistp;
+    *freelistp= object;
+#ifdef qh_TRACEshort
+    idx= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
+    if (qh->qhmem.IStracing >= 5)
+        qh_fprintf(qh, qh->qhmem.ferr, 8142, "qh_mem %p n %8d free short: %d bytes (tot %d cnt %d)\n", object, idx, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
+#endif
+  }else {
+    qh->qhmem.freelong++;
+    qh->qhmem.totlong -= insize;
+    if (qh->qhmem.IStracing >= 5)
+      qh_fprintf(qh, qh->qhmem.ferr, 8058, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
+    qh_free(object);
+  }
+} /* memfree */
+
+
+/*---------------------------------
+
+  qh_memfreeshort(qh, curlong, totlong )
+    frees up all short and qhmem memory allocations
+
+  returns:
+    number and size of current long allocations
+
+  notes:
+    if qh_NOmem (qh_malloc() for all allocations),
+       short objects (e.g., facetT) are not recovered.
+       use qh_freeqhull(qh, qh_ALL) instead.
+
+  see:
+    qh_freeqhull(qh, allMem)
+    qh_memtotal(qh, curlong, totlong, curshort, totshort, maxlong, totbuffer);
+*/
+void qh_memfreeshort(qhT *qh, int *curlong, int *totlong) {
+  void *buffer, *nextbuffer;
+  FILE *ferr;
+
+  *curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
+  *totlong= qh->qhmem.totlong;
+  for (buffer=qh->qhmem.curbuffer; buffer; buffer= nextbuffer) {
+    nextbuffer= *((void **) buffer);
+    qh_free(buffer);
+  }
+  qh->qhmem.curbuffer= NULL;
+  if (qh->qhmem.LASTsize) {
+    qh_free(qh->qhmem.indextable);
+    qh_free(qh->qhmem.freelists);
+    qh_free(qh->qhmem.sizetable);
+  }
+  ferr= qh->qhmem.ferr;
+  memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem));  /* every field is 0, FALSE, NULL */
+  qh->qhmem.ferr= ferr;
+} /* memfreeshort */
+
+
+/*----------------------------------
+
+  qh_meminit(qh, ferr )
+    initialize qhmem and test sizeof(void *)
+    Does not throw errors.  qh_exit on failure
+*/
+void qh_meminit(qhT *qh, FILE *ferr) {
+
+  memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem));  /* every field is 0, FALSE, NULL */
+  if (ferr)
+    qh->qhmem.ferr= ferr;
+  else
+    qh->qhmem.ferr= stderr;
+  if (sizeof(void *) < sizeof(int)) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6083, "qhull internal error (qh_meminit): sizeof(void *) %d < sizeof(int) %d.  qset_r.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
+    qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
+  }
+  if (sizeof(void *) > sizeof(ptr_intT)) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6084, "qhull internal error (qh_meminit): sizeof(void *) %d > sizeof(ptr_intT) %d. Change ptr_intT in mem_r.h to 'long long'\n", (int)sizeof(void*), (int)sizeof(ptr_intT));
+    qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
+  }
+  qh_memcheck(qh);
+} /* meminit */
+
+/*---------------------------------
+
+  qh_meminitbuffers(qh, tracelevel, alignment, numsizes, bufsize, bufinit )
+    initialize qhmem
+    if tracelevel >= 5, trace memory allocations
+    alignment= desired address alignment for memory allocations
+    numsizes= number of freelists
+    bufsize=  size of additional memory buffers for short allocations
+    bufinit=  size of initial memory buffer for short allocations
+*/
+void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+  qh->qhmem.IStracing= tracelevel;
+  qh->qhmem.NUMsizes= numsizes;
+  qh->qhmem.BUFsize= bufsize;
+  qh->qhmem.BUFinit= bufinit;
+  qh->qhmem.ALIGNmask= alignment-1;
+  if (qh->qhmem.ALIGNmask & ~qh->qhmem.ALIGNmask) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  qh->qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int));
+  qh->qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *));
+  if (!qh->qhmem.sizetable || !qh->qhmem.freelists) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n");
+    qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+  }
+  if (qh->qhmem.IStracing >= 1)
+    qh_fprintf(qh, qh->qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
+} /* meminitbuffers */
+
+/*---------------------------------
+
+  qh_memsetup(qh)
+    set up memory after running memsize()
+*/
+void qh_memsetup(qhT *qh) {
+  int k,i;
+
+  qsort(qh->qhmem.sizetable, (size_t)qh->qhmem.TABLEsize, sizeof(int), qh_intcompare);
+  qh->qhmem.LASTsize= qh->qhmem.sizetable[qh->qhmem.TABLEsize-1];
+  if (qh->qhmem.LASTsize >= qh->qhmem.BUFsize || qh->qhmem.LASTsize >= qh->qhmem.BUFinit) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
+            qh->qhmem.LASTsize, qh->qhmem.BUFsize, qh->qhmem.BUFinit);
+    qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+  }
+  if (!(qh->qhmem.indextable= (int *)qh_malloc((size_t)(qh->qhmem.LASTsize+1) * sizeof(int)))) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n");
+    qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+  }
+  for (k=qh->qhmem.LASTsize+1; k--; )
+    qh->qhmem.indextable[k]= k;
+  i= 0;
+  for (k=0; k <= qh->qhmem.LASTsize; k++) {
+    if (qh->qhmem.indextable[k] <= qh->qhmem.sizetable[i])
+      qh->qhmem.indextable[k]= i;
+    else
+      qh->qhmem.indextable[k]= ++i;
+  }
+} /* memsetup */
+
+/*---------------------------------
+
+  qh_memsize(qh, size )
+    define a free list for this size
+*/
+void qh_memsize(qhT *qh, int size) {
+  int k;
+
+  if (qh->qhmem.LASTsize) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6089, "qhull internal error (qh_memsize): qh_memsize called after qh_memsetup\n");
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  size= (size + qh->qhmem.ALIGNmask) & ~qh->qhmem.ALIGNmask;
+  if (qh->qhmem.IStracing >= 3)
+    qh_fprintf(qh, qh->qhmem.ferr, 3078, "qh_memsize: quick memory of %d bytes\n", size);
+  for (k=qh->qhmem.TABLEsize; k--; ) {
+    if (qh->qhmem.sizetable[k] == size)
+      return;
+  }
+  if (qh->qhmem.TABLEsize < qh->qhmem.NUMsizes)
+    qh->qhmem.sizetable[qh->qhmem.TABLEsize++]= size;
+  else
+    qh_fprintf(qh, qh->qhmem.ferr, 7060, "qhull warning (qh_memsize): free list table has room for only %d sizes\n", qh->qhmem.NUMsizes);
+} /* memsize */
+
+
+/*---------------------------------
+
+  qh_memstatistics(qh, fp )
+    print out memory statistics
+
+    Verifies that qh->qhmem.totfree == sum of freelists
+*/
+void qh_memstatistics(qhT *qh, FILE *fp) {
+  int i;
+  int count;
+  void *object;
+
+  qh_memcheck(qh);
+  qh_fprintf(qh, fp, 9278, "\nmemory statistics:\n\
+%7d quick allocations\n\
+%7d short allocations\n\
+%7d long allocations\n\
+%7d short frees\n\
+%7d long frees\n\
+%7d bytes of short memory in use\n\
+%7d bytes of short memory in freelists\n\
+%7d bytes of dropped short memory\n\
+%7d bytes of unused short memory (estimated)\n\
+%7d bytes of long memory allocated (max, except for input)\n\
+%7d bytes of long memory in use (in %d pieces)\n\
+%7d bytes of short memory buffers (minus links)\n\
+%7d bytes per short memory buffer (initially %d bytes)\n",
+           qh->qhmem.cntquick, qh->qhmem.cntshort, qh->qhmem.cntlong,
+           qh->qhmem.freeshort, qh->qhmem.freelong,
+           qh->qhmem.totshort, qh->qhmem.totfree,
+           qh->qhmem.totdropped + qh->qhmem.freesize, qh->qhmem.totunused,
+           qh->qhmem.maxlong, qh->qhmem.totlong, qh->qhmem.cntlong - qh->qhmem.freelong,
+           qh->qhmem.totbuffer, qh->qhmem.BUFsize, qh->qhmem.BUFinit);
+  if (qh->qhmem.cntlarger) {
+    qh_fprintf(qh, fp, 9279, "%7d calls to qh_setlarger\n%7.2g     average copy size\n",
+           qh->qhmem.cntlarger, ((double)qh->qhmem.totlarger)/(double)qh->qhmem.cntlarger);
+    qh_fprintf(qh, fp, 9280, "  freelists(bytes->count):");
+  }
+  for (i=0; i < qh->qhmem.TABLEsize; i++) {
+    count=0;
+    for (object= qh->qhmem.freelists[i]; object; object= *((void **)object))
+      count++;
+    qh_fprintf(qh, fp, 9281, " %d->%d", qh->qhmem.sizetable[i], count);
+  }
+  qh_fprintf(qh, fp, 9282, "\n\n");
+} /* memstatistics */
+
+
+/*---------------------------------
+
+  qh_NOmem
+    turn off quick-fit memory allocation
+
+  notes:
+    uses qh_malloc() and qh_free() instead
+*/
+#else /* qh_NOmem */
+
+void *qh_memalloc(qhT *qh, int insize) {
+  void *object;
+
+  if (!(object= qh_malloc((size_t)insize))) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n");
+    qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+  }
+  qh->qhmem.cntlong++;
+  qh->qhmem.totlong += insize;
+  if (qh->qhmem.maxlong < qh->qhmem.totlong)
+      qh->qhmem.maxlong= qh->qhmem.totlong;
+  if (qh->qhmem.IStracing >= 5)
+    qh_fprintf(qh, qh->qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
+  return object;
+}
+
+void qh_memcheck(qhT *qh) {
+}
+
+void qh_memfree(qhT *qh, void *object, int insize) {
+
+  if (!object)
+    return;
+  qh_free(object);
+  qh->qhmem.freelong++;
+  qh->qhmem.totlong -= insize;
+  if (qh->qhmem.IStracing >= 5)
+    qh_fprintf(qh, qh->qhmem.ferr, 8061, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
+}
+
+void qh_memfreeshort(qhT *qh, int *curlong, int *totlong) {
+  *totlong= qh->qhmem.totlong;
+  *curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
+  memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem));  /* every field is 0, FALSE, NULL */
+}
+
+void qh_meminit(qhT *qh, FILE *ferr) {
+
+  memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem));  /* every field is 0, FALSE, NULL */
+  if (ferr)
+      qh->qhmem.ferr= ferr;
+  else
+      qh->qhmem.ferr= stderr;
+  if (sizeof(void *) < sizeof(int)) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6091, "qhull internal error (qh_meminit): sizeof(void *) %d < sizeof(int) %d.  qset_r.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+}
+
+void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+  qh->qhmem.IStracing= tracelevel;
+}
+
+void qh_memsetup(qhT *qh) {
+}
+
+void qh_memsize(qhT *qh, int size) {
+}
+
+void qh_memstatistics(qhT *qh, FILE *fp) {
+
+  qh_fprintf(qh, fp, 9409, "\nmemory statistics:\n\
+%7d long allocations\n\
+%7d long frees\n\
+%7d bytes of long memory allocated (max, except for input)\n\
+%7d bytes of long memory in use (in %d pieces)\n",
+           qh->qhmem.cntlong,
+           qh->qhmem.freelong,
+           qh->qhmem.maxlong, qh->qhmem.totlong, qh->qhmem.cntlong - qh->qhmem.freelong);
+}
+
+#endif /* qh_NOmem */
+
+/*---------------------------------
+
+  qh_memtotal(qh, totlong, curlong, totshort, curshort, maxlong, totbuffer )
+    Return the total, allocated long and short memory
+
+  returns:
+    Returns the total current bytes of long and short allocations
+    Returns the current count of long and short allocations
+    Returns the maximum long memory and total short buffer (minus one link per buffer)
+    Does not error (for deprecated UsingLibQhull.cpp in libqhullpcpp)
+*/
+void qh_memtotal(qhT *qh, int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer) {
+    *totlong= qh->qhmem.totlong;
+    *curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
+    *totshort= qh->qhmem.totshort;
+    *curshort= qh->qhmem.cntshort + qh->qhmem.cntquick - qh->qhmem.freeshort;
+    *maxlong= qh->qhmem.maxlong;
+    *totbuffer= qh->qhmem.totbuffer;
+} /* memtotlong */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.h
new file mode 100644
index 00000000000..aeb761b100e
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/mem_r.h
@@ -0,0 +1,235 @@
+/*
  ---------------------------------
+
+   mem_r.h
+     prototypes for memory management functions
+
+   see qh-mem_r.htm, mem_r.c and qset_r.h
+
+   for error handling, writes message and calls
+     qh_errexit(qhT *qh, qhmem_ERRmem, NULL, NULL) if insufficient memory
+       and
+     qh_errexit(qhT *qh, qhmem_ERRqhull, NULL, NULL) otherwise
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/mem_r.h#6 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#ifndef qhDEFmem
+#define qhDEFmem 1
+
+#include 
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;          /* defined in qset_r.h */
+#endif
+
+#ifndef DEFqhT
+#define DEFqhT 1
+typedef struct qhT qhT;          /* defined in libqhull_r.h */
+#endif
+
+/*---------------------------------
+
+  qh_NOmem
+    turn off quick-fit memory allocation
+
+  notes:
+    mem_r.c implements Quickfit memory allocation for about 20% time
+    savings.  If it fails on your machine, try to locate the
+    problem, and send the answer to qhull@qhull.org.  If this can
+    not be done, define qh_NOmem to use malloc/free instead.
+
+    #define qh_NOmem
+*/
+
+/*---------------------------------
+
+qh_TRACEshort
+Trace short and quick memory allocations at T5
+
+*/
+#define qh_TRACEshort
+
+/*-------------------------------------------
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem_r.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers.  If gcc is available,
+    use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
+
+   see qh_MEMalign in user_r.h for qhull's alignment
+*/
+
+#define qhmem_ERRmem 4    /* matches qh_ERRmem in libqhull_r.h */
+#define qhmem_ERRqhull 5  /* matches qh_ERRqhull in libqhull_r.h */
+
+/*----------------------------------
+
+  ptr_intT
+    for casting a void * to an integer-type that holds a pointer
+    Used for integer expressions (e.g., computing qh_gethash() in poly_r.c)
+
+  notes:
+    WARN64 -- these notes indicate 64-bit issues
+    On 64-bit machines, a pointer may be larger than an 'int'.
+    qh_meminit()/mem_r.c checks that 'ptr_intT' holds a 'void*'
+    ptr_intT is typically a signed value, but not necessarily so
+    size_t is typically unsigned, but should match the parameter type
+    Qhull uses int instead of size_t except for system calls such as malloc, qsort, qh_malloc, etc.
+    This matches Qt convention and is easier to work with.
+*/
+#if (defined(__MINGW64__)) && defined(_WIN64)
+typedef long long ptr_intT;
+#elif defined(_MSC_VER) && defined(_WIN64)
+typedef long long ptr_intT;
+#else
+typedef long ptr_intT;
+#endif
+
+/*----------------------------------
+
+  qhmemT
+    global memory structure for mem_r.c
+
+ notes:
+   users should ignore qhmem except for writing extensions
+   qhmem is allocated in mem_r.c
+
+   qhmem could be swapable like qh and qhstat, but then
+   multiple qh's and qhmem's would need to keep in synch.
+   A swapable qhmem would also waste memory buffers.  As long
+   as memory operations are atomic, there is no problem with
+   multiple qh structures being active at the same time.
+   If you need separate address spaces, you can swap the
+   contents of qh->qhmem.
+*/
+typedef struct qhmemT qhmemT;
+
+struct qhmemT {               /* global memory management variables */
+  int      BUFsize;           /* size of memory allocation buffer */
+  int      BUFinit;           /* initial size of memory allocation buffer */
+  int      TABLEsize;         /* actual number of sizes in free list table */
+  int      NUMsizes;          /* maximum number of sizes in free list table */
+  int      LASTsize;          /* last size in free list table */
+  int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
+  void   **freelists;          /* free list table, linked by offset 0 */
+  int     *sizetable;         /* size of each freelist */
+  int     *indextable;        /* size->index table */
+  void    *curbuffer;         /* current buffer, linked by offset 0 */
+  void    *freemem;           /*   free memory in curbuffer */
+  int      freesize;          /*   size of freemem in bytes */
+  setT    *tempstack;         /* stack of temporary memory, managed by users */
+  FILE    *ferr;              /* file for reporting errors when 'qh' may be undefined */
+  int      IStracing;         /* =5 if tracing memory allocations */
+  int      cntquick;          /* count of quick allocations */
+                              /* Note: removing statistics doesn't effect speed */
+  int      cntshort;          /* count of short allocations */
+  int      cntlong;           /* count of long allocations */
+  int      freeshort;         /* count of short memfrees */
+  int      freelong;          /* count of long memfrees */
+  int      totbuffer;         /* total short memory buffers minus buffer links */
+  int      totdropped;        /* total dropped memory at end of short memory buffers (e.g., freesize) */
+  int      totfree;           /* total size of free, short memory on freelists */
+  int      totlong;           /* total size of long memory in use */
+  int      maxlong;           /*   maximum totlong */
+  int      totshort;          /* total size of short memory in use */
+  int      totunused;         /* total unused short memory (estimated, short size - request size of first allocations) */
+  int      cntlarger;         /* count of setlarger's */
+  int      totlarger;         /* total copied by setlarger */
+};
+
+
+/*==================== -macros ====================*/
+
+/*----------------------------------
+
+  qh_memalloc_(qh, insize, freelistp, object, type)
+    returns object of size bytes
+        assumes size<=qh->qhmem.LASTsize and void **freelistp is a temp
+*/
+
+#if defined qh_NOmem
+#define qh_memalloc_(qh, insize, freelistp, object, type) {\
+  (void)freelistp; /* Avoid warnings */ \
+  object= (type *)qh_memalloc(qh, insize); }
+#elif defined qh_TRACEshort
+#define qh_memalloc_(qh, insize, freelistp, object, type) {\
+  (void)freelistp; /* Avoid warnings */ \
+  object= (type *)qh_memalloc(qh, insize); }
+#else /* !qh_NOmem */
+
+#define qh_memalloc_(qh, insize, freelistp, object, type) {\
+  freelistp= qh->qhmem.freelists + qh->qhmem.indextable[insize];\
+  if ((object= (type *)*freelistp)) {\
+    qh->qhmem.totshort += qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
+    qh->qhmem.totfree -= qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
+    qh->qhmem.cntquick++;  \
+    *freelistp= *((void **)*freelistp);\
+  }else object= (type *)qh_memalloc(qh, insize);}
+#endif
+
+/*----------------------------------
+
+  qh_memfree_(qh, object, insize, freelistp)
+    free up an object
+
+  notes:
+    object may be NULL
+    assumes size<=qh->qhmem.LASTsize and void **freelistp is a temp
+*/
+#if defined qh_NOmem
+#define qh_memfree_(qh, object, insize, freelistp) {\
+  (void)freelistp; /* Avoid warnings */ \
+  qh_memfree(qh, object, insize); }
+#elif defined qh_TRACEshort
+#define qh_memfree_(qh, object, insize, freelistp) {\
+  (void)freelistp; /* Avoid warnings */ \
+  qh_memfree(qh, object, insize); }
+#else /* !qh_NOmem */
+
+#define qh_memfree_(qh, object, insize, freelistp) {\
+  if (object) { \
+    qh->qhmem.freeshort++;\
+    freelistp= qh->qhmem.freelists + qh->qhmem.indextable[insize];\
+    qh->qhmem.totshort -= qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
+    qh->qhmem.totfree += qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
+    *((void **)object)= *freelistp;\
+    *freelistp= object;}}
+#endif
+
+/*=============== prototypes in alphabetical order ============*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *qh_memalloc(qhT *qh, int insize);
+void qh_memcheck(qhT *qh);
+void qh_memfree(qhT *qh, void *object, int insize);
+void qh_memfreeshort(qhT *qh, int *curlong, int *totlong);
+void qh_meminit(qhT *qh, FILE *ferr);
+void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes,
+                        int bufsize, int bufinit);
+void qh_memsetup(qhT *qh);
+void qh_memsize(qhT *qh, int size);
+void qh_memstatistics(qhT *qh, FILE *fp);
+void qh_memtotal(qhT *qh, int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFmem */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.c
new file mode 100644
index 00000000000..f820cf80ea8
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.c
@@ -0,0 +1,5589 @@
+/*
  ---------------------------------
+
+   merge_r.c
+   merges non-convex facets
+
+   see qh-merge_r.htm and merge_r.h
+
+   other modules call qh_premerge() and qh_postmerge()
+
+   the user may call qh_postmerge() to perform additional merges.
+
+   To remove deleted facets and vertices (qhull() in libqhull_r.c):
+     qh_partitionvisible(qh, !qh_ALL, &numoutside);  // visible_list, newfacet_list
+     qh_deletevisible();         // qh.visible_list
+     qh_resetlists(qh, False, qh_RESETvisible);       // qh.visible_list newvertex_list newfacet_list
+
+   assumes qh.CENTERtype= centrum
+
+   merges occur in qh_mergefacet and in qh_mergecycle
+   vertex->neighbors not set until the first merge occurs
+
+   Copyright (c) 1993-2020 C.B. Barber.
+   $Id: //main/2019/qhull/src/libqhull_r/merge_r.c#15 $$Change: 3664 $
+   $DateTime: 2024/07/22 23:55:01 $$Author: bbarber $
+*/
+
+#include "qhull_ra.h"
+
+#ifndef qh_NOmerge
+
+/* MRGnone, etc. */
+const char *mergetypes[]= {
+  "none",
+  "coplanar",
+  "anglecoplanar",
+  "concave",
+  "concavecoplanar",
+  "twisted",
+  "flip",
+  "dupridge",
+  "subridge",
+  "vertices",
+  "degen",
+  "redundant",
+  "mirror",
+  "coplanarhorizon",
+};
+
+/*===== functions(alphabetical after premerge and postmerge) ======*/
+
+/*---------------------------------
+
+  qh_premerge(qh, apexpointid, maxcentrum )
+    pre-merge nonconvex facets in qh.newfacet_list for apexpointid
+    maxcentrum defines coplanar and concave (qh_test_appendmerge)
+
+  returns:
+    deleted facets added to qh.visible_list with facet->visible set
+
+  notes:
+    only called by qh_addpoint
+    uses globals, qh.MERGEexact, qh.PREmerge
+
+  design:
+    mark dupridges in qh.newfacet_list
+    merge facet cycles in qh.newfacet_list
+    merge dupridges and concave facets in qh.newfacet_list
+    check merged facet cycles for degenerate and redundant facets
+    merge degenerate and redundant facets
+    collect coplanar and concave facets
+    merge concave, coplanar, degenerate, and redundant facets
+*/
+void qh_premerge(qhT *qh, int apexpointid, realT maxcentrum, realT maxangle /* qh.newfacet_list */) {
+  boolT othermerge= False;
+
+  if (qh->ZEROcentrum && qh_checkzero(qh, !qh_ALL))
+    return;
+  trace2((qh, qh->ferr, 2008, "qh_premerge: premerge centrum %2.2g angle %4.4g for apex p%d newfacet_list f%d\n",
+            maxcentrum, maxangle, apexpointid, getid_(qh->newfacet_list)));
+  if (qh->IStracing >= 4 && qh->num_facets < 100)
+    qh_printlists(qh);
+  qh->centrum_radius= maxcentrum;
+  qh->cos_max= maxangle;
+  if (qh->hull_dim >=3) {
+    qh_mark_dupridges(qh, qh->newfacet_list, qh_ALL); /* facet_mergeset */
+    qh_mergecycle_all(qh, qh->newfacet_list, &othermerge);
+    qh_forcedmerges(qh, &othermerge /* qh.facet_mergeset */);
+  }else /* qh.hull_dim == 2 */
+    qh_mergecycle_all(qh, qh->newfacet_list, &othermerge);
+  qh_flippedmerges(qh, qh->newfacet_list, &othermerge);
+  if (!qh->MERGEexact || zzval_(Ztotmerge)) {
+    zinc_(Zpremergetot);
+    qh->POSTmerging= False;
+    qh_getmergeset_initial(qh, qh->newfacet_list);
+    qh_all_merges(qh, othermerge, False);
+  }
+} /* premerge */
+
+/*---------------------------------
+
+  qh_postmerge(qh, reason, maxcentrum, maxangle, vneighbors )
+    post-merge nonconvex facets as defined by maxcentrum and maxangle
+    'reason' is for reporting progress
+    if vneighbors ('Qv'),
+      calls qh_test_vneighbors at end of qh_all_merge from qh_postmerge
+
+  returns:
+    if first call (qh.visible_list != qh.facet_list),
+      builds qh.facet_newlist, qh.newvertex_list
+    deleted facets added to qh.visible_list with facet->visible
+    qh.visible_list == qh.facet_list
+
+  notes:
+    called by qh_qhull after qh_buildhull
+    called if a merge may be needed due to
+      qh.MERGEexact ('Qx'), qh_DIMreduceBuild, POSTmerge (e.g., 'Cn'), or TESTvneighbors ('Qv')
+    if firstmerge,
+      calls qh_reducevertices before qh_getmergeset
+
+  design:
+    if first call
+      set qh.visible_list and qh.newfacet_list to qh.facet_list
+      add all facets to qh.newfacet_list
+      mark non-simplicial facets, facet->newmerge
+      set qh.newvertext_list to qh.vertex_list
+      add all vertices to qh.newvertex_list
+      if a pre-merge occurred
+        set vertex->delridge {will retest the ridge}
+        if qh.MERGEexact
+          call qh_reducevertices()
+      if no pre-merging
+        merge flipped facets
+    determine non-convex facets
+    merge all non-convex facets
+*/
+void qh_postmerge(qhT *qh, const char *reason, realT maxcentrum, realT maxangle,
+                      boolT vneighbors) {
+  facetT *newfacet;
+  boolT othermerges= False;
+  vertexT *vertex;
+
+  if (qh->REPORTfreq || qh->IStracing) {
+    qh_buildtracing(qh, NULL, NULL);
+    qh_printsummary(qh, qh->ferr);
+    if (qh->PRINTstatistics)
+      qh_printallstatistics(qh, qh->ferr, "reason");
+    qh_fprintf(qh, qh->ferr, 8062, "\n%s with 'C%.2g' and 'A%.2g'\n",
+        reason, maxcentrum, maxangle);
+  }
+  trace2((qh, qh->ferr, 2009, "qh_postmerge: postmerge.  test vneighbors? %d\n",
+            vneighbors));
+  qh->centrum_radius= maxcentrum;
+  qh->cos_max= maxangle;
+  qh->POSTmerging= True;
+  if (qh->visible_list != qh->facet_list) {  /* first call due to qh_buildhull, multiple calls if qh.POSTmerge */
+    qh->NEWfacets= True;
+    qh->visible_list= qh->newfacet_list= qh->facet_list;
+    FORALLnew_facets {              /* all facets are new facets for qh_postmerge */
+      newfacet->newfacet= True;
+       if (!newfacet->simplicial)
+        newfacet->newmerge= True;   /* test f.vertices for 'delridge'.  'newmerge' was cleared at end of qh_all_merges */
+     zinc_(Zpostfacets);
+    }
+    qh->newvertex_list= qh->vertex_list;
+    FORALLvertices
+      vertex->newfacet= True;
+    if (qh->VERTEXneighbors) {  /* a merge has occurred */
+      if (qh->MERGEexact && qh->hull_dim <= qh_DIMreduceBuild)
+        qh_reducevertices(qh);  /* qh_all_merges did not call qh_reducevertices for v.delridge */
+    }
+    if (!qh->PREmerge && !qh->MERGEexact)
+      qh_flippedmerges(qh, qh->newfacet_list, &othermerges);
+  }
+  qh_getmergeset_initial(qh, qh->newfacet_list);
+  qh_all_merges(qh, False, vneighbors); /* calls qh_reducevertices before exiting */
+  FORALLnew_facets
+    newfacet->newmerge= False;   /* Was True if no vertex in f.vertices was 'delridge' */
+} /* post_merge */
+
+/*---------------------------------
+
+  qh_all_merges(qh, othermerge, vneighbors )
+    merge all non-convex facets
+
+    set othermerge if already merged facets (calls qh_reducevertices)
+    if vneighbors ('Qv' at qh.POSTmerge)
+      tests vertex neighbors for convexity at end (qh_test_vneighbors)
+    qh.facet_mergeset lists the non-convex ridges in qh_newfacet_list
+    qh.degen_mergeset is defined
+    if qh.MERGEexact && !qh.POSTmerging,
+      does not merge coplanar facets
+
+  returns:
+    deleted facets added to qh.visible_list with facet->visible
+    deleted vertices added qh.delvertex_list with vertex->delvertex
+
+  notes:
+    unless !qh.MERGEindependent,
+      merges facets in independent sets
+    uses qh.newfacet_list as implicit argument since merges call qh_removefacet()
+    [apr'19] restored qh_setdellast in place of qh_next_facetmerge.  Much faster for post-merge
+
+  design:
+    while merges occur
+      for each merge in qh.facet_mergeset
+        unless one of the facets was already merged in this pass
+          merge the facets
+        test merged facets for additional merges
+        add merges to qh.facet_mergeset
+        if qh.POSTmerging
+          periodically call qh_reducevertices to reduce extra vertices and redundant vertices
+      after each pass, if qh.VERTEXneighbors
+        if qh.POSTmerging or was a merge with qh.hull_dim<=5
+          call qh_reducevertices
+          update qh.facet_mergeset if degenredundant merges
+      if 'Qv' and qh.POSTmerging
+        test vertex neighbors for convexity
+*/
+void qh_all_merges(qhT *qh, boolT othermerge, boolT vneighbors) {
+  facetT *facet1, *facet2, *newfacet;
+  mergeT *merge;
+  boolT wasmerge= False, isreduce;
+  void **freelistp;  /* used if !qh_NOmem by qh_memfree_() */
+  vertexT *vertex;
+  realT angle, distance;
+  mergeType mergetype;
+  int numcoplanar=0, numconcave=0, numconcavecoplanar= 0, numdegenredun= 0, numnewmerges= 0, numtwisted= 0;
+
+  trace2((qh, qh->ferr, 2010, "qh_all_merges: starting to merge %d facet and %d degenerate merges for new facets f%d, othermerge? %d\n",
+            qh_setsize(qh, qh->facet_mergeset), qh_setsize(qh, qh->degen_mergeset), getid_(qh->newfacet_list), othermerge));
+
+  while (True) {
+    wasmerge= False;
+    while (qh_setsize(qh, qh->facet_mergeset) > 0 || qh_setsize(qh, qh->degen_mergeset) > 0) {
+      if (qh_setsize(qh, qh->degen_mergeset) > 0) {
+        numdegenredun += qh_merge_degenredundant(qh);
+        wasmerge= True;
+      }
+      while ((merge= (mergeT *)qh_setdellast(qh->facet_mergeset))) {
+        facet1= merge->facet1;
+        facet2= merge->facet2;
+        vertex= merge->vertex1;  /* not used for qh.facet_mergeset*/
+        mergetype= merge->mergetype;
+        angle= merge->angle;
+        distance= merge->distance;
+        qh_memfree_(qh, merge, (int)sizeof(mergeT), freelistp);   /* 'merge' is invalid */
+        if (facet1->visible || facet2->visible) {
+          trace3((qh, qh->ferr, 3045, "qh_all_merges: drop merge of f%d (del? %d) into f%d (del? %d) mergetype %d, dist %4.4g, angle %4.4g.  One or both facets is deleted\n",
+            facet1->id, facet1->visible, facet2->id, facet2->visible, mergetype, distance, angle));
+          continue;
+        }else if (mergetype == MRGcoplanar || mergetype == MRGanglecoplanar) {
+          if (qh->MERGEindependent) {
+            if ((!facet1->tested && facet1->newfacet)
+            || (!facet2->tested && facet2->newfacet)) {
+              trace3((qh, qh->ferr, 3064, "qh_all_merges: drop merge of f%d (tested? %d) into f%d (tested? %d) mergetype %d, dist %2.2g, angle %4.4g.  Merge independent sets of coplanar merges\n",
+                facet1->id, facet1->visible, facet2->id, facet2->visible, mergetype, distance, angle));
+              continue;
+            }
+          }
+        }
+        trace3((qh, qh->ferr, 3047, "qh_all_merges: merge f%d and f%d type %d dist %2.2g angle %4.4g\n",
+          facet1->id, facet2->id, mergetype, distance, angle));
+        if (mergetype == MRGtwisted)
+          qh_merge_twisted(qh, facet1, facet2);
+        else
+          qh_merge_nonconvex(qh, facet1, facet2, mergetype);
+        numnewmerges++;
+        numdegenredun += qh_merge_degenredundant(qh);
+        wasmerge= True;
+        if (mergetype == MRGconcave)
+          numconcave++;
+        else if (mergetype == MRGconcavecoplanar)
+          numconcavecoplanar++;
+        else if (mergetype == MRGtwisted)
+          numtwisted++;
+        else if (mergetype == MRGcoplanar || mergetype == MRGanglecoplanar)
+          numcoplanar++;
+        else {
+          qh_fprintf(qh, qh->ferr, 6394, "qhull internal error (qh_all_merges): expecting concave, coplanar, or twisted merge.  Got merge f%d f%d v%d mergetype %d\n",
+            getid_(facet1), getid_(facet2), getid_(vertex), mergetype);
+          qh_errexit2(qh, qh_ERRqhull, facet1, facet2);
+        }
+      } /* while qh_setdellast */
+      if (qh->POSTmerging && qh->hull_dim <= qh_DIMreduceBuild
+      && numnewmerges > qh_MAXnewmerges) {
+        numnewmerges= 0;
+        wasmerge= othermerge= False;
+        qh_reducevertices(qh);  /* otherwise large post merges too slow */
+      }
+      qh_getmergeset(qh, qh->newfacet_list); /* qh.facet_mergeset */
+    } /* while facet_mergeset or degen_mergeset */
+    if (qh->VERTEXneighbors) {  /* at least one merge */
+      isreduce= False;
+      if (qh->POSTmerging && qh->hull_dim >= 4) {
+        isreduce= True;
+      }else if (qh->POSTmerging || !qh->MERGEexact) {
+        if ((wasmerge || othermerge) && qh->hull_dim > 2 && qh->hull_dim <= qh_DIMreduceBuild)
+          isreduce= True;
+      }
+      if (isreduce) {
+        wasmerge= othermerge= False;
+        if (qh_reducevertices(qh)) {
+          qh_getmergeset(qh, qh->newfacet_list); /* facet_mergeset */
+          continue;
+        }
+      }
+    }
+    if (vneighbors && qh_test_vneighbors(qh /* qh.newfacet_list */))
+      continue;
+    break;
+  } /* while (True) */
+  if (wasmerge || othermerge) {
+    trace3((qh, qh->ferr, 3033, "qh_all_merges: skip qh_reducevertices due to post-merging, no qh.VERTEXneighbors (%d), or hull_dim %d ==2 or >%d\n", qh->VERTEXneighbors, qh->hull_dim, qh_DIMreduceBuild))
+    FORALLnew_facets {
+      newfacet->newmerge= False;
+    }
+  }
+  if (qh->CHECKfrequently && !qh->MERGEexact) {
+    qh->old_randomdist= qh->RANDOMdist;
+    qh->RANDOMdist= False;
+    qh_checkconvex(qh, qh->newfacet_list, qh_ALGORITHMfault);
+    /* qh_checkconnect(qh); [this is slow and it changes the facet order] */
+    qh->RANDOMdist= qh->old_randomdist;
+  }
+  trace1((qh, qh->ferr, 1009, "qh_all_merges: merged %d coplanar %d concave %d concavecoplanar %d twisted facets and %d degen or redundant facets.\n",
+    numcoplanar, numconcave, numconcavecoplanar, numtwisted, numdegenredun));
+  if (qh->IStracing >= 4 && qh->num_facets < 500)
+    qh_printlists(qh);
+} /* all_merges */
+
+/*---------------------------------
+
+  qh_all_vertexmerges(qh, apexpointid, facet, &retryfacet )
+    merge vertices in qh.vertex_mergeset and subsequent merges
+
+  returns:
+    returns retryfacet for facet (if defined)
+    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
+    mergesets are empty
+    if merges, resets facet lists
+
+  notes:
+    called from qh_qhull, qh_addpoint, and qh_buildcone_mergepinched
+    vertex merges occur after facet merges and qh_resetlists
+
+  design:
+    while merges in vertex_mergeset (MRGvertices)
+      merge a pair of pinched vertices
+      update vertex neighbors
+      merge non-convex and degenerate facets and check for ridges with duplicate vertices
+      partition outside points of deleted, "visible" facets
+*/
+void qh_all_vertexmerges(qhT *qh, int apexpointid, facetT *facet, facetT **retryfacet) {
+  int numpoints; /* ignore count of partitioned points.  Used by qh_addpoint for Zpbalance */
+
+  if (retryfacet)
+    *retryfacet= facet;
+  while (qh_setsize(qh, qh->vertex_mergeset) > 0) {
+    trace1((qh, qh->ferr, 1057, "qh_all_vertexmerges: starting to merge %d vertex merges for apex p%d facet f%d\n",
+            qh_setsize(qh, qh->vertex_mergeset), apexpointid, getid_(facet)));
+    if (qh->IStracing >= 4  && qh->num_facets < 1000)
+      qh_printlists(qh);
+    qh_merge_pinchedvertices(qh, apexpointid /* qh.vertex_mergeset, visible_list, newvertex_list, newfacet_list */);
+    qh_update_vertexneighbors(qh); /* update neighbors of qh.newvertex_list from qh_newvertices for deleted facets on qh.visible_list */
+                           /* test ridges and merge non-convex facets */
+    qh_getmergeset(qh, qh->newfacet_list);
+    qh_all_merges(qh, True, False); /* calls qh_reducevertices */
+    if (qh->CHECKfrequently)
+      qh_checkpolygon(qh, qh->facet_list);
+    qh_partitionvisible(qh, !qh_ALL, &numpoints /* qh.visible_list qh.del_vertices*/);
+    if (retryfacet)
+      *retryfacet= qh_getreplacement(qh, *retryfacet);
+    qh_deletevisible(qh /* qh.visible_list  qh.del_vertices*/);
+    qh_resetlists(qh, False, qh_RESETvisible /* qh.visible_list newvertex_list qh.newfacet_list */);
+    if (qh->IStracing >= 4  && qh->num_facets < 1000) {
+      qh_printlists(qh);
+      qh_checkpolygon(qh, qh->facet_list);
+    }
+  }
+} /* all_vertexmerges */
+
+/*---------------------------------
+
+  qh_appendmergeset(qh, facet, vertex, neighbor, mergetype, dist, angle )
+    appends an entry to qh.facet_mergeset or qh.degen_mergeset
+    if 'dist' is unknown, set it to 0.0
+        if 'angle' is unknown, set it to 1.0 (coplanar)
+
+  returns:
+    merge appended to facet_mergeset or degen_mergeset
+      sets ->degenerate or ->redundant if degen_mergeset
+
+  notes:
+    caller collects statistics and/or caller of qh_mergefacet
+    see: qh_test_appendmerge()
+
+  design:
+    allocate merge entry
+    if regular merge
+      append to qh.facet_mergeset
+    else if degenerate merge and qh.facet_mergeset is all degenerate
+      append to qh.degen_mergeset
+    else if degenerate merge
+      prepend to qh.degen_mergeset (merged last)
+    else if redundant merge
+      append to qh.degen_mergeset
+*/
+void qh_appendmergeset(qhT *qh, facetT *facet, facetT *neighbor, mergeType mergetype, coordT dist, realT angle) {
+  mergeT *merge, *lastmerge;
+  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
+  const char *mergename;
+
+  if ((facet->redundant && mergetype != MRGmirror) || neighbor->redundant) {
+    trace3((qh, qh->ferr, 3051, "qh_appendmergeset: f%d is already redundant (%d) or f%d is already redundant (%d).  Ignore merge f%d and f%d type %d\n",
+      facet->id, facet->redundant, neighbor->id, neighbor->redundant, facet->id, neighbor->id, mergetype));
+    return;
+  }
+  if (facet->degenerate && mergetype == MRGdegen) {
+    trace3((qh, qh->ferr, 3077, "qh_appendmergeset: f%d is already degenerate.  Ignore merge f%d type %d (MRGdegen)\n",
+      facet->id, facet->id, mergetype));
+    return;
+  }
+  if (!qh->facet_mergeset || !qh->degen_mergeset) {
+    qh_fprintf(qh, qh->ferr, 6403, "qhull internal error (qh_appendmergeset): expecting temp set defined for qh.facet_mergeset (%p) and qh.degen_mergeset (%p).  Got NULL\n",
+      (void *) qh->facet_mergeset, (void *) qh->degen_mergeset);
+    /* otherwise qh_setappend creates a new set that is not freed by qh_freebuild() */
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (neighbor->flipped && !facet->flipped) {
+    if (mergetype != MRGdupridge) {
+      qh_fprintf(qh, qh->ferr, 6355, "qhull internal error (qh_appendmergeset): except for MRGdupridge, cannot merge a non-flipped facet f%d into flipped f%d, mergetype %d, dist %4.4g\n",
+        facet->id, neighbor->id, mergetype, dist);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }else {
+      trace2((qh, qh->ferr, 2106, "qh_appendmergeset: dupridge will merge a non-flipped facet f%d into flipped f%d, dist %4.4g\n",
+        facet->id, neighbor->id, dist));
+    }
+  }
+  qh_memalloc_(qh, (int)sizeof(mergeT), freelistp, merge, mergeT);
+  merge->angle= angle;
+  merge->distance= dist;
+  merge->facet1= facet;
+  merge->facet2= neighbor;
+  merge->vertex1= NULL;
+  merge->vertex2= NULL;
+  merge->ridge1= NULL;
+  merge->ridge2= NULL;
+  merge->mergetype= mergetype;
+  if(mergetype > 0 && mergetype < sizeof(mergetypes)/sizeof(char *))
+    mergename= mergetypes[mergetype];
+  else
+    mergename= mergetypes[MRGnone];
+  if (mergetype < MRGdegen)
+    qh_setappend(qh, &(qh->facet_mergeset), merge);
+  else if (mergetype == MRGdegen) {
+    facet->degenerate= True;
+    if (!(lastmerge= (mergeT *)qh_setlast(qh->degen_mergeset))
+    || lastmerge->mergetype == MRGdegen)
+      qh_setappend(qh, &(qh->degen_mergeset), merge);
+    else
+      qh_setaddnth(qh, &(qh->degen_mergeset), 0, merge);    /* merged last */
+  }else if (mergetype == MRGredundant) {
+    facet->redundant= True;
+    qh_setappend(qh, &(qh->degen_mergeset), merge);
+  }else /* mergetype == MRGmirror */ {
+    if (facet->redundant || neighbor->redundant) {
+      qh_fprintf(qh, qh->ferr, 6092, "qhull internal error (qh_appendmergeset): facet f%d or f%d is already a mirrored facet (i.e., 'redundant')\n",
+           facet->id, neighbor->id);
+      qh_errexit2(qh, qh_ERRqhull, facet, neighbor);
+    }
+    if (!qh_setequal(facet->vertices, neighbor->vertices)) {
+      qh_fprintf(qh, qh->ferr, 6093, "qhull internal error (qh_appendmergeset): mirrored facets f%d and f%d do not have the same vertices\n",
+           facet->id, neighbor->id);
+      qh_errexit2(qh, qh_ERRqhull, facet, neighbor);
+    }
+    facet->redundant= True;
+    neighbor->redundant= True;
+    qh_setappend(qh, &(qh->degen_mergeset), merge);
+  }
+  if (merge->mergetype >= MRGdegen) {
+    trace3((qh, qh->ferr, 3044, "qh_appendmergeset: append merge f%d and f%d type %d (%s) to qh.degen_mergeset (size %d)\n",
+      merge->facet1->id, merge->facet2->id, merge->mergetype, mergename, qh_setsize(qh, qh->degen_mergeset)));
+  }else {
+    trace3((qh, qh->ferr, 3027, "qh_appendmergeset: append merge f%d and f%d type %d (%s) dist %2.2g angle %4.4g to qh.facet_mergeset (size %d)\n",
+      merge->facet1->id, merge->facet2->id, merge->mergetype, mergename, merge->distance, merge->angle, qh_setsize(qh, qh->facet_mergeset)));
+  }
+} /* appendmergeset */
+
+
+/*---------------------------------
+
+  qh_appendvertexmerge(qh, vertex, vertex2, mergetype, distance, ridge1, ridge2 )
+    appends a vertex merge to qh.vertex_mergeset
+    MRGsubridge includes two ridges (from MRGdupridge)
+    MRGvertices includes two ridges
+
+  notes:
+    called by qh_getpinchedmerges for MRGsubridge
+    called by qh_maybe_duplicateridge and qh_maybe_duplicateridges for MRGvertices
+    only way to add a vertex merge to qh.vertex_mergeset
+    checked by qh_next_vertexmerge
+*/
+void qh_appendvertexmerge(qhT *qh, vertexT *vertex, vertexT *destination, mergeType mergetype, realT distance, ridgeT *ridge1, ridgeT *ridge2) {
+  mergeT *merge;
+  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
+  const char *mergename;
+
+  if (!qh->vertex_mergeset) {
+    qh_fprintf(qh, qh->ferr, 6387, "qhull internal error (qh_appendvertexmerge): expecting temp set defined for qh.vertex_mergeset.  Got NULL\n");
+    /* otherwise qh_setappend creates a new set that is not freed by qh_freebuild() */
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh_memalloc_(qh, (int)sizeof(mergeT), freelistp, merge, mergeT);
+  merge->angle= qh_ANGLEnone;
+  merge->distance= distance;
+  merge->facet1= NULL;
+  merge->facet2= NULL;
+  merge->vertex1= vertex;
+  merge->vertex2= destination;
+  merge->ridge1= ridge1;
+  merge->ridge2= ridge2;
+  merge->mergetype= mergetype;
+  if(mergetype > 0 && mergetype < sizeof(mergetypes)/sizeof(char *))
+    mergename= mergetypes[mergetype];
+  else
+    mergename= mergetypes[MRGnone];
+  if (mergetype == MRGvertices) {
+    if (!ridge1 || !ridge2 || ridge1 == ridge2) {
+      qh_fprintf(qh, qh->ferr, 6106, "qhull internal error (qh_appendvertexmerge): expecting two distinct ridges for MRGvertices.  Got r%d r%d\n",
+        getid_(ridge1), getid_(ridge2));
+      qh_errexit(qh, qh_ERRqhull, NULL, ridge1);
+    }
+  }
+  qh_setappend(qh, &(qh->vertex_mergeset), merge);
+  trace3((qh, qh->ferr, 3034, "qh_appendvertexmerge: append merge v%d into v%d r%d r%d dist %2.2g type %d (%s)\n",
+    vertex->id, destination->id, getid_(ridge1), getid_(ridge2), distance, merge->mergetype, mergename));
+} /* appendvertexmerge */
+
+
+/*---------------------------------
+
+  qh_basevertices(qh, samecycle )
+    return temporary set of base vertices for samecycle
+    samecycle is first facet in the cycle
+    assumes apex is SETfirst_( samecycle->vertices )
+
+  returns:
+    vertices(settemp)
+    all ->seen are cleared
+
+  notes:
+    uses qh_vertex_visit;
+
+  design:
+    for each facet in samecycle
+      for each unseen vertex in facet->vertices
+        append to result
+*/
+setT *qh_basevertices(qhT *qh, facetT *samecycle) {
+  facetT *same;
+  vertexT *apex, *vertex, **vertexp;
+  setT *vertices= qh_settemp(qh, qh->TEMPsize);
+
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  apex->visitid= ++qh->vertex_visit;
+  FORALLsame_cycle_(samecycle) {
+    if (same->mergeridge)
+      continue;
+    FOREACHvertex_(same->vertices) {
+      if (vertex->visitid != qh->vertex_visit) {
+        qh_setappend(qh, &vertices, vertex);
+        vertex->visitid= qh->vertex_visit;
+        vertex->seen= False;
+      }
+    }
+  }
+  trace4((qh, qh->ferr, 4019, "qh_basevertices: found %d vertices\n",
+         qh_setsize(qh, vertices)));
+  return vertices;
+} /* basevertices */
+
+/*---------------------------------
+
+  qh_check_dupridge(qh, facet1, dist1, facet2, dist2 )
+    Check dupridge between facet1 and facet2 for wide merge
+    dist1 is the maximum distance of facet1's vertices to facet2
+    dist2 is the maximum distance of facet2's vertices to facet1
+
+  returns
+    Level 1 log of the dupridge with the minimum distance between vertices
+    Throws error if the merge will increase the maximum facet width by qh_WIDEduplicate (100x)
+
+  notes:
+    only called from qh_forcedmerges
+*/
+void qh_check_dupridge(qhT *qh, facetT *facet1, realT dist1, facetT *facet2, realT dist2) {
+  vertexT *vertex, **vertexp, *vertexA, **vertexAp;
+  realT dist, innerplane, mergedist, outerplane, prevdist, ratio, vertexratio;
+  realT minvertex= REALmax;
+
+  mergedist= fmin_(dist1, dist2);
+  qh_outerinner(qh, NULL, &outerplane, &innerplane);  /* ratio from qh_printsummary */
+  FOREACHvertex_(facet1->vertices) {     /* The dupridge is between facet1 and facet2, so either facet can be tested */
+    FOREACHvertexA_(facet1->vertices) {
+      if (vertex > vertexA){   /* Test each pair once */
+        dist= qh_pointdist(vertex->point, vertexA->point, qh->hull_dim);
+        minimize_(minvertex, dist);
+        /* Not quite correct.  A facet may have a dupridge and another pair of nearly adjacent vertices. */
+      }
+    }
+  }
+  prevdist= fmax_(outerplane, innerplane);
+  maximize_(prevdist, qh->ONEmerge + qh->DISTround);
+  maximize_(prevdist, qh->MINoutside + qh->DISTround);
+  ratio= mergedist/prevdist;
+  vertexratio= minvertex/prevdist;
+  trace0((qh, qh->ferr, 16, "qh_check_dupridge: dupridge between f%d and f%d (vertex dist %2.2g), dist %2.2g, reverse dist %2.2g, ratio %2.2g while processing p%d\n",
+        facet1->id, facet2->id, minvertex, dist1, dist2, ratio, qh->furthest_id));
+  if (ratio > qh_WIDEduplicate) {
+    qh_fprintf(qh, qh->ferr, 6271, "qhull topology error (qh_check_dupridge): wide merge (%.1fx wider) due to dupridge between f%d and f%d (vertex dist %2.2g), merge dist %2.2g, while processing p%d\n- Allow error with option 'Q12'\n",
+      ratio, facet1->id, facet2->id, minvertex, mergedist, qh->furthest_id);
+    if (vertexratio < qh_WIDEpinched)
+      qh_fprintf(qh, qh->ferr, 8145, "- Experimental option merge-pinched-vertices ('Q14') may avoid this error.  It merges nearly adjacent vertices.\n");
+    if (qh->DELAUNAY)
+      qh_fprintf(qh, qh->ferr, 8145, "- A bounding box for the input sites may alleviate this error.\n");
+    if (!qh->ALLOWwide)
+      qh_errexit2(qh, qh_ERRwide, facet1, facet2);
+  }
+} /* check_dupridge */
+
+/*---------------------------------
+
+  qh_checkconnect(qh)
+    check that new facets are connected
+    new facets are on qh.newfacet_list
+
+  notes:
+    this is slow and it changes the order of the facets
+    uses qh.visit_id
+
+  design:
+    move first new facet to end of qh.facet_list
+    for all newly appended facets
+      append unvisited neighbors to end of qh.facet_list
+    for all new facets
+      report error if unvisited
+*/
+void qh_checkconnect(qhT *qh /* qh.newfacet_list */) {
+  facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
+
+  facet= qh->newfacet_list;
+  qh_removefacet(qh, facet);
+  qh_appendfacet(qh, facet);
+  facet->visitid= ++qh->visit_id;
+  FORALLfacet_(facet) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh->visit_id) {
+        qh_removefacet(qh, neighbor);
+        qh_appendfacet(qh, neighbor);
+        neighbor->visitid= qh->visit_id;
+      }
+    }
+  }
+  FORALLnew_facets {
+    if (newfacet->visitid == qh->visit_id)
+      break;
+    qh_fprintf(qh, qh->ferr, 6094, "qhull internal error (qh_checkconnect): f%d is not attached to the new facets\n",
+         newfacet->id);
+    errfacet= newfacet;
+  }
+  if (errfacet)
+    qh_errexit(qh, qh_ERRqhull, errfacet, NULL);
+} /* checkconnect */
+
+/*---------------------------------
+
+  qh_checkdelfacet(qh, facet, mergeset )
+    check that mergeset does not reference facet
+
+*/
+void qh_checkdelfacet(qhT *qh, facetT *facet, setT *mergeset) {
+  mergeT *merge, **mergep;
+
+  FOREACHmerge_(mergeset) {
+    if (merge->facet1 == facet || merge->facet2 == facet) {
+      qh_fprintf(qh, qh->ferr, 6390, "qhull internal error (qh_checkdelfacet): cannot delete f%d.  It is referenced by merge f%d f%d mergetype %d\n",
+        facet->id, merge->facet1->id, getid_(merge->facet2), merge->mergetype);
+      qh_errexit2(qh, qh_ERRqhull, merge->facet1, merge->facet2);
+    }
+  }
+} /* checkdelfacet */
+
+/*---------------------------------
+
+  qh_checkdelridge(qh)
+    check that qh_delridge_merge is not needed for deleted ridges
+
+    notes:
+      called from qh_mergecycle, qh_makenewfacets, qh_attachnewfacets
+      errors if qh.vertex_mergeset is non-empty
+      errors if any visible or new facet has a ridge with r.nonconvex set
+      assumes that vertex.delfacet is not needed
+*/
+void qh_checkdelridge(qhT *qh /* qh.visible_facets, vertex_mergeset */) {
+  facetT *newfacet, *visible;
+  ridgeT *ridge, **ridgep;
+
+  if (!SETempty_(qh->vertex_mergeset)) {
+    qh_fprintf(qh, qh->ferr, 6382, "qhull internal error (qh_checkdelridge): expecting empty qh.vertex_mergeset in order to avoid calling qh_delridge_merge.  Got %d merges\n", qh_setsize(qh, qh->vertex_mergeset));
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+
+  FORALLnew_facets {
+    FOREACHridge_(newfacet->ridges) {
+      if (ridge->nonconvex) {
+        qh_fprintf(qh, qh->ferr, 6313, "qhull internal error (qh_checkdelridge): unexpected 'nonconvex' flag for ridge r%d in newfacet f%d.  Otherwise need to call qh_delridge_merge\n",
+           ridge->id, newfacet->id);
+        qh_errexit(qh, qh_ERRqhull, newfacet, ridge);
+      }
+    }
+  }
+
+  FORALLvisible_facets {
+    FOREACHridge_(visible->ridges) {
+      if (ridge->nonconvex) {
+        qh_fprintf(qh, qh->ferr, 6385, "qhull internal error (qh_checkdelridge): unexpected 'nonconvex' flag for ridge r%d in visible facet f%d.  Otherwise need to call qh_delridge_merge\n",
+          ridge->id, visible->id);
+        qh_errexit(qh, qh_ERRqhull, visible, ridge);
+      }
+    }
+  }
+} /* checkdelridge */
+
+
+/*---------------------------------
+
+  qh_checkzero(qh, testall )
+    check that facets are clearly convex for qh.DISTround with qh.MERGEexact
+
+    if testall,
+      test all facets for qh.MERGEexact post-merging
+    else
+      test qh.newfacet_list
+
+    if qh.MERGEexact,
+      allows coplanar ridges
+      skips convexity test while qh.ZEROall_ok
+
+  returns:
+    True if all facets !flipped, !dupridge, normal
+         if all horizon facets are simplicial
+         if all vertices are clearly below neighbor
+         if all opposite vertices of horizon are below
+    clears qh.ZEROall_ok if any problems or coplanar facets
+
+  notes:
+    called by qh_premerge (qh.CHECKzero, 'C-0') and qh_qhull ('Qx')
+    uses qh.vertex_visit
+    horizon facets may define multiple new facets
+
+  design:
+    for all facets in qh.newfacet_list or qh.facet_list
+      check for flagged faults (flipped, etc.)
+    for all facets in qh.newfacet_list or qh.facet_list
+      for each neighbor of facet
+        skip horizon facets for qh.newfacet_list
+        test the opposite vertex
+      if qh.newfacet_list
+        test the other vertices in the facet's horizon facet
+*/
+boolT qh_checkzero(qhT *qh, boolT testall) {
+  facetT *facet, *neighbor;
+  facetT *horizon, *facetlist;
+  int neighbor_i, neighbor_n;
+  vertexT *vertex, **vertexp;
+  realT dist;
+
+  if (testall)
+    facetlist= qh->facet_list;
+  else {
+    facetlist= qh->newfacet_list;
+    FORALLfacet_(facetlist) {
+      horizon= SETfirstt_(facet->neighbors, facetT);
+      if (!horizon->simplicial)
+        goto LABELproblem;
+      if (facet->flipped || facet->dupridge || !facet->normal)
+        goto LABELproblem;
+    }
+    if (qh->MERGEexact && qh->ZEROall_ok) {
+      trace2((qh, qh->ferr, 2011, "qh_checkzero: skip convexity check until first pre-merge\n"));
+      return True;
+    }
+  }
+  FORALLfacet_(facetlist) {
+    qh->vertex_visit++;
+    horizon= NULL;
+    FOREACHneighbor_i_(qh, facet) {
+      if (!neighbor_i && !testall) {
+        horizon= neighbor;
+        continue; /* horizon facet tested in qh_findhorizon */
+      }
+      vertex= SETelemt_(facet->vertices, neighbor_i, vertexT);
+      vertex->visitid= qh->vertex_visit;
+      zzinc_(Zdistzero);
+      qh_distplane(qh, vertex->point, neighbor, &dist);
+      if (dist >= -2 * qh->DISTround) {  /* need 2x for qh_distround and 'Rn' for qh_checkconvex, same as qh.premerge_centrum */
+        qh->ZEROall_ok= False;
+        if (!qh->MERGEexact || testall || dist > qh->DISTround)
+          goto LABELnonconvex;
+      }
+    }
+    if (!testall && horizon) {
+      FOREACHvertex_(horizon->vertices) {
+        if (vertex->visitid != qh->vertex_visit) {
+          zzinc_(Zdistzero);
+          qh_distplane(qh, vertex->point, facet, &dist);
+          if (dist >= -2 * qh->DISTround) {
+            qh->ZEROall_ok= False;
+            if (!qh->MERGEexact || dist > qh->DISTround)
+              goto LABELnonconvexhorizon;
+          }
+          break;
+        }
+      }
+    }
+  }
+  trace2((qh, qh->ferr, 2012, "qh_checkzero: testall %d, facets are %s\n", testall,
+        (qh->MERGEexact && !testall) ?
+           "not concave, flipped, or dupridge" : "clearly convex"));
+  return True;
+
+ LABELproblem:
+  qh->ZEROall_ok= False;
+  trace2((qh, qh->ferr, 2013, "qh_checkzero: qh_premerge is needed.  New facet f%d or its horizon f%d is non-simplicial, flipped, dupridge, or mergehorizon\n",
+       facet->id, horizon->id));
+  return False;
+
+ LABELnonconvex:
+  trace2((qh, qh->ferr, 2014, "qh_checkzero: facet f%d and f%d are not clearly convex.  v%d dist %.2g\n",
+         facet->id, neighbor->id, vertex->id, dist));
+  return False;
+
+ LABELnonconvexhorizon:
+  trace2((qh, qh->ferr, 2060, "qh_checkzero: facet f%d and horizon f%d are not clearly convex.  v%d dist %.2g\n",
+      facet->id, horizon->id, vertex->id, dist));
+  return False;
+} /* checkzero */
+
+/*---------------------------------
+
+  qh_compare_anglemerge( mergeA, mergeB )
+    used by qsort() to order qh.facet_mergeset by mergetype and angle (qh.ANGLEmerge, 'Q1')
+    lower numbered mergetypes done first (MRGcoplanar before MRGconcave)
+
+  notes:
+    qh_all_merges processes qh.facet_mergeset by qh_setdellast
+    [mar'19] evaluated various options with eg/q_benchmark and merging of pinched vertices (Q14)
+*/
+int qh_compare_anglemerge(const void *p1, const void *p2) {
+  const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
+
+  if (a->mergetype != b->mergetype)
+    return (a->mergetype < b->mergetype ? 1 : -1); /* select MRGcoplanar (1) before MRGconcave (3) */
+  else
+    return (a->angle > b->angle ? 1 : -1);         /* select coplanar merge (1.0) before sharp merge (-0.5) */
+} /* compare_anglemerge */
+
+/*---------------------------------
+
+  qh_compare_facetmerge( mergeA, mergeB )
+    used by qsort() to order merges by mergetype, first merge, first
+    lower numbered mergetypes done first (MRGcoplanar before MRGconcave)
+    if same merge type, flat merges are first
+
+  notes:
+    qh_all_merges processes qh.facet_mergeset by qh_setdellast
+    [mar'19] evaluated various options with eg/q_benchmark and merging of pinched vertices (Q14)
+*/
+int qh_compare_facetmerge(const void *p1, const void *p2) {
+  const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
+
+  if (a->mergetype != b->mergetype)
+    return (a->mergetype < b->mergetype ? 1 : -1); /* select MRGcoplanar (1) before MRGconcave (3) */
+  else if (a->mergetype == MRGanglecoplanar)
+    return (a->angle > b->angle ? 1 : -1);         /* if MRGanglecoplanar, select coplanar merge (1.0) before sharp merge (-0.5) */
+  else
+    return (a->distance < b->distance ? 1 : -1);   /* select flat (0.0) merge before wide (1e-10) merge */
+} /* compare_facetmerge */
+
+/*---------------------------------
+
+  qh_comparevisit( vertexA, vertexB )
+    used by qsort() to order vertices by their visitid
+
+  notes:
+    only called by qh_find_newvertex
+*/
+int qh_comparevisit(const void *p1, const void *p2) {
+  const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
+
+  if (a->visitid > b->visitid)
+    return 1;
+  return -1;
+} /* comparevisit */
+
+/*---------------------------------
+
+  qh_copynonconvex(qh, atridge )
+    set non-convex flag on other ridges (if any) between same neighbors
+
+  notes:
+    may be faster if use smaller ridge set
+
+  design:
+    for each ridge of atridge's top facet
+      if ridge shares the same neighbor
+        set nonconvex flag
+*/
+void qh_copynonconvex(qhT *qh, ridgeT *atridge) {
+  facetT *facet, *otherfacet;
+  ridgeT *ridge, **ridgep;
+
+  facet= atridge->top;
+  otherfacet= atridge->bottom;
+  atridge->nonconvex= False;
+  FOREACHridge_(facet->ridges) {
+    if (otherfacet == ridge->top || otherfacet == ridge->bottom) {
+      if (ridge != atridge) {
+        ridge->nonconvex= True;
+        trace4((qh, qh->ferr, 4020, "qh_copynonconvex: moved nonconvex flag from r%d to r%d between f%d and f%d\n",
+                atridge->id, ridge->id, facet->id, otherfacet->id));
+        break;
+      }
+    }
+  }
+} /* copynonconvex */
+
+/*---------------------------------
+
+  qh_degen_redundant_facet(qh, facet )
+    check for a degenerate (too few neighbors) or redundant (subset of vertices) facet
+
+  notes:
+    called at end of qh_mergefacet, qh_renamevertex, and qh_reducevertices
+    bumps vertex_visit
+    called if a facet was redundant but no longer is (qh_merge_degenredundant)
+    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
+    see: qh_test_redundant_neighbors, qh_maydropneighbor
+
+  design:
+    test for redundant neighbor
+    test for degenerate facet
+*/
+void qh_degen_redundant_facet(qhT *qh, facetT *facet) {
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+
+  trace3((qh, qh->ferr, 3028, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
+          facet->id));
+  if (facet->flipped) {
+    trace2((qh, qh->ferr, 3074, "qh_degen_redundant_facet: f%d is flipped, will merge later\n", facet->id));
+    return;
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor->flipped) /* disallow merge of non-flipped into flipped, neighbor will be merged later */
+      continue;
+    if (neighbor->visible) {
+      qh_fprintf(qh, qh->ferr, 6357, "qhull internal error (qh_degen_redundant_facet): facet f%d has deleted neighbor f%d (qh.visible_list)\n",
+        facet->id, neighbor->id);
+      qh_errexit2(qh, qh_ERRqhull, facet, neighbor);
+    }
+    qh->vertex_visit++;
+    FOREACHvertex_(neighbor->vertices)
+      vertex->visitid= qh->vertex_visit;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh->vertex_visit)
+        break;
+    }
+    if (!vertex) {
+      trace2((qh, qh->ferr, 2015, "qh_degen_redundant_facet: f%d is contained in f%d.  merge\n", facet->id, neighbor->id));
+      qh_appendmergeset(qh, facet, neighbor, MRGredundant, 0.0, 1.0);
+      return;
+    }
+  }
+  if (qh_setsize(qh, facet->neighbors) < qh->hull_dim) {
+    qh_appendmergeset(qh, facet, facet, MRGdegen, 0.0, 1.0);
+    trace2((qh, qh->ferr, 2016, "qh_degen_redundant_facet: f%d is degenerate.\n", facet->id));
+  }
+} /* degen_redundant_facet */
+
+
+/*---------------------------------
+
+  qh_delridge_merge(qh, ridge )
+    delete ridge due to a merge
+
+  notes:
+    only called by merge_r.c (qh_mergeridges, qh_renameridgevertex)
+    ridges also freed in qh_freeqhull and qh_mergecycle_ridges
+
+  design:
+    if needed, moves ridge.nonconvex to another ridge
+    sets vertex.delridge for qh_reducevertices
+    deletes ridge from qh.vertex_mergeset
+    deletes ridge from its neighboring facets
+    frees up its memory
+*/
+void qh_delridge_merge(qhT *qh, ridgeT *ridge) {
+  vertexT *vertex, **vertexp;
+  mergeT *merge;
+  int merge_i, merge_n;
+
+  trace3((qh, qh->ferr, 3036, "qh_delridge_merge: delete ridge r%d between f%d and f%d\n",
+    ridge->id, ridge->top->id, ridge->bottom->id));
+  if (ridge->nonconvex)
+    qh_copynonconvex(qh, ridge);
+  FOREACHvertex_(ridge->vertices)
+    vertex->delridge= True;
+  FOREACHmerge_i_(qh, qh->vertex_mergeset) {
+    if (merge->ridge1 == ridge || merge->ridge2 == ridge) {
+      trace3((qh, qh->ferr, 3029, "qh_delridge_merge: drop merge of v%d into v%d (dist %2.2g r%d r%d) due to deleted, duplicated ridge r%d\n",
+        merge->vertex1->id, merge->vertex2->id, merge->distance, merge->ridge1->id, merge->ridge2->id, ridge->id));
+      if (merge->ridge1 == ridge)
+        merge->ridge2->mergevertex= False;
+      else
+        merge->ridge1->mergevertex= False;
+      qh_setdelnth(qh, qh->vertex_mergeset, merge_i);
+      merge_i--; merge_n--; /* next merge after deleted */
+    }
+  }
+  qh_setdel(ridge->top->ridges, ridge);
+  qh_setdel(ridge->bottom->ridges, ridge);
+  qh_delridge(qh, ridge);
+} /* delridge_merge */
+
+
+/*---------------------------------
+
+  qh_drop_mergevertex(qh, merge )
+
+  clear mergevertex flags for ridges of a vertex merge
+*/
+void qh_drop_mergevertex(qhT *qh, mergeT *merge)
+{
+  if (merge->mergetype == MRGvertices) {
+    merge->ridge1->mergevertex= False;
+    merge->ridge1->mergevertex2= True;
+    merge->ridge2->mergevertex= False;
+    merge->ridge2->mergevertex2= True;
+    trace3((qh, qh->ferr, 3032, "qh_drop_mergevertex: unset mergevertex for r%d and r%d due to dropped vertex merge v%d to v%d.  Sets mergevertex2\n",
+      merge->ridge1->id, merge->ridge2->id, merge->vertex1->id, merge->vertex2->id));
+  }
+} /* drop_mergevertex */
+
+/*---------------------------------
+
+  qh_find_newvertex(qh, oldvertex, vertices, ridges )
+    locate new vertex for renaming old vertex
+    vertices is a set of possible new vertices
+      vertices sorted by number of deleted ridges
+
+  returns:
+    newvertex or NULL
+      each ridge includes both newvertex and oldvertex
+    vertices without oldvertex sorted by number of deleted ridges
+    qh.vertex_visit updated
+    sets v.seen
+
+  notes:
+    called by qh_redundant_vertex due to vertex->delridge and qh_rename_sharedvertex
+    sets vertex->visitid to 0..setsize() for vertices
+    new vertex is in one of the ridges
+    renaming will not cause a duplicate ridge
+    renaming will minimize the number of deleted ridges
+    newvertex may not be adjacent in the dual (though unlikely)
+
+  design:
+    for each vertex in vertices
+      set vertex->visitid to number of ridges
+    remove unvisited vertices
+    set qh.vertex_visit above all possible values
+    sort vertices by number of ridges (minimize ridges that need renaming
+    add each ridge to qh.hash_table
+    for each vertex in vertices
+      find the first vertex that would not cause a duplicate ridge after a rename
+*/
+vertexT *qh_find_newvertex(qhT *qh, vertexT *oldvertex, setT *vertices, setT *ridges) {
+  vertexT *vertex, **vertexp;
+  setT *newridges;
+  ridgeT *ridge, **ridgep;
+  int size, hashsize;
+  int hash;
+  unsigned int maxvisit;
+
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 4) {
+    qh_fprintf(qh, qh->ferr, 8063, "qh_find_newvertex: find new vertex for v%d from ",
+             oldvertex->id);
+    FOREACHvertex_(vertices)
+      qh_fprintf(qh, qh->ferr, 8064, "v%d ", vertex->id);
+    FOREACHridge_(ridges)
+      qh_fprintf(qh, qh->ferr, 8065, "r%d ", ridge->id);
+    qh_fprintf(qh, qh->ferr, 8066, "\n");
+  }
+#endif
+  FOREACHridge_(ridges) {
+    FOREACHvertex_(ridge->vertices)
+      vertex->seen= False;
+  }
+  FOREACHvertex_(vertices) {
+    vertex->visitid= 0;  /* v.visitid will be number of ridges */
+    vertex->seen= True;
+  }
+  FOREACHridge_(ridges) {
+    FOREACHvertex_(ridge->vertices) {
+      if (vertex->seen)
+        vertex->visitid++;
+    }
+  }
+  FOREACHvertex_(vertices) {
+    if (!vertex->visitid) {
+      qh_setdelnth(qh, vertices, SETindex_(vertices,vertex));
+      vertexp--; /* repeat since deleted this vertex */
+    }
+  }
+  maxvisit= (unsigned int)qh_setsize(qh, ridges);
+  maximize_(qh->vertex_visit, maxvisit);
+  if (!qh_setsize(qh, vertices)) {
+    trace4((qh, qh->ferr, 4023, "qh_find_newvertex: vertices not in ridges for v%d\n",
+            oldvertex->id));
+    return NULL;
+  }
+  qsort(SETaddr_(vertices, vertexT), (size_t)qh_setsize(qh, vertices),
+                sizeof(vertexT *), qh_comparevisit);
+  /* can now use qh->vertex_visit */
+  if (qh->PRINTstatistics) {
+    size= qh_setsize(qh, vertices);
+    zinc_(Zintersect);
+    zadd_(Zintersecttot, size);
+    zmax_(Zintersectmax, size);
+  }
+  hashsize= qh_newhashtable(qh, qh_setsize(qh, ridges));
+  FOREACHridge_(ridges)
+    qh_hashridge(qh, qh->hash_table, hashsize, ridge, oldvertex);
+  FOREACHvertex_(vertices) {
+    newridges= qh_vertexridges(qh, vertex, !qh_ALL);
+    FOREACHridge_(newridges) {
+      if (qh_hashridge_find(qh, qh->hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
+        zinc_(Zvertexridge);
+        break;
+      }
+    }
+    qh_settempfree(qh, &newridges);
+    if (!ridge)
+      break;  /* found a rename */
+  }
+  if (vertex) {
+    /* counted in qh_renamevertex */
+    trace2((qh, qh->ferr, 2020, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
+      vertex->id, oldvertex->id, qh_setsize(qh, vertices), qh_setsize(qh, ridges)));
+  }else {
+    zinc_(Zfindfail);
+    trace0((qh, qh->ferr, 14, "qh_find_newvertex: no vertex for renaming v%d (all duplicated ridges) during p%d\n",
+      oldvertex->id, qh->furthest_id));
+  }
+  qh_setfree(qh, &qh->hash_table);
+  return vertex;
+} /* find_newvertex */
+
+/*---------------------------------
+
+  qh_findbest_pinchedvertex(qh, merge, apex, nearestp, distp )
+    Determine the best pinched vertex to rename as its nearest neighboring vertex
+    Renaming will remove a duplicate MRGdupridge in newfacet_list
+
+  returns:
+    pinched vertex (either apex or subridge), nearest vertex (subridge or neighbor vertex), and the distance between them
+
+  notes:
+    only called by qh_getpinchedmerges
+    assumes qh.VERTEXneighbors
+    see qh_findbest_ridgevertex
+
+  design:
+    if the facets have the same vertices
+      return the nearest vertex pair
+    else
+      the subridge is the intersection of the two new facets minus the apex
+      the subridge consists of qh.hull_dim-2 horizon vertices
+      the subridge is also a matched ridge for the new facets (its duplicate)
+      determine the nearest vertex to the apex
+      determine the nearest pair of subridge vertices
+      for each vertex in the subridge
+        determine the nearest neighbor vertex (not in the subridge)
+*/
+vertexT *qh_findbest_pinchedvertex(qhT *qh, mergeT *merge, vertexT *apex, vertexT **nearestp, coordT *distp /* qh.newfacet_list */) {
+  vertexT *vertex, **vertexp, *vertexA, **vertexAp;
+  vertexT *bestvertex= NULL, *bestpinched= NULL;
+  setT *subridge, *maybepinched;
+  coordT dist, bestdist= REALmax;
+  coordT pincheddist= (qh->ONEmerge+qh->DISTround)*qh_RATIOpinchedsubridge;
+
+  if (!merge->facet1->simplicial || !merge->facet2->simplicial) {
+    qh_fprintf(qh, qh->ferr, 6351, "qhull internal error (qh_findbest_pinchedvertex): expecting merge of adjacent, simplicial new facets.  f%d or f%d is not simplicial\n",
+      merge->facet1->id, merge->facet2->id);
+    qh_errexit2(qh, qh_ERRqhull, merge->facet1, merge->facet2);
+  }
+  subridge= qh_vertexintersect_new(qh, merge->facet1->vertices, merge->facet2->vertices); /* new setT.  No error_exit() */
+  if (qh_setsize(qh, subridge) == qh->hull_dim) { /* duplicate vertices */
+    bestdist= qh_vertex_bestdist2(qh, subridge, &bestvertex, &bestpinched);
+    if(bestvertex == apex) {
+      bestvertex= bestpinched;
+      bestpinched= apex;
+    }
+  }else {
+    qh_setdel(subridge, apex);
+    if (qh_setsize(qh, subridge) != qh->hull_dim - 2) {
+      qh_fprintf(qh, qh->ferr, 6409, "qhull internal error (qh_findbest_pinchedvertex): expecting subridge of qh.hull_dim-2 vertices for the intersection of new facets f%d and f%d minus their apex.  Got %d vertices\n",
+          merge->facet1->id, merge->facet2->id, qh_setsize(qh, subridge));
+      qh_errexit2(qh, qh_ERRqhull, merge->facet1, merge->facet2);
+    }
+    FOREACHvertex_(subridge) {
+      dist= qh_pointdist(vertex->point, apex->point, qh->hull_dim);
+      if (dist < bestdist) {
+        bestpinched= apex;
+        bestvertex= vertex;
+        bestdist= dist;
+      }
+    }
+    if (bestdist > pincheddist) {
+      FOREACHvertex_(subridge) {
+        FOREACHvertexA_(subridge) {
+          if (vertexA->id > vertex->id) { /* once per vertex pair, do not compare addresses */
+            dist= qh_pointdist(vertexA->point, vertex->point, qh->hull_dim);
+            if (dist < bestdist) {
+              bestpinched= vertexA;
+              bestvertex= vertex;
+              bestdist= dist;
+            }
+          }
+        }
+      }
+    }
+    if (bestdist > pincheddist) {
+      FOREACHvertexA_(subridge) {
+        maybepinched= qh_neighbor_vertices(qh, vertexA, subridge); /* subridge and apex tested above */
+        FOREACHvertex_(maybepinched) {
+          dist= qh_pointdist(vertex->point, vertexA->point, qh->hull_dim);
+          if (dist < bestdist) {
+            bestvertex= vertex;
+            bestpinched= vertexA;
+            bestdist= dist;
+          }
+        }
+        qh_settempfree(qh, &maybepinched);
+      }
+    }
+  }
+  *distp= bestdist;
+  qh_setfree(qh, &subridge); /* qh_err_exit not called since allocated */
+  if (!bestvertex) {  /* should never happen if qh.hull_dim > 2 */
+    qh_fprintf(qh, qh->ferr, 6274, "qhull internal error (qh_findbest_pinchedvertex): did not find best vertex for subridge of dupridge between f%d and f%d, while processing p%d\n", merge->facet1->id, merge->facet2->id, qh->furthest_id);
+    qh_errexit2(qh, qh_ERRqhull, merge->facet1, merge->facet2);
+  }
+  *nearestp= bestvertex;
+  trace2((qh, qh->ferr, 2061, "qh_findbest_pinchedvertex: best pinched p%d(v%d) and vertex p%d(v%d) are closest (%2.2g) for duplicate subridge between f%d and f%d\n",
+      qh_pointid(qh, bestpinched->point), bestpinched->id, qh_pointid(qh, bestvertex->point), bestvertex->id, bestdist, merge->facet1->id, merge->facet2->id));
+  return bestpinched;
+} /* findbest_pinchedvertex */
+
+/*---------------------------------
+
+  qh_findbest_ridgevertex(qh, ridge, pinchedp, distp )
+    Determine the best vertex/pinched-vertex to merge for ridges with the same vertices
+
+  returns:
+    vertex, pinched vertex, and the distance between them
+
+  notes:
+    assumes qh.hull_dim>=3
+    see qh_findbest_pinchedvertex
+
+*/
+vertexT *qh_findbest_ridgevertex(qhT *qh, ridgeT *ridge, vertexT **pinchedp, coordT *distp) {
+  vertexT *bestvertex;
+
+  *distp= qh_vertex_bestdist2(qh, ridge->vertices, &bestvertex, pinchedp);
+  trace4((qh, qh->ferr, 4069, "qh_findbest_ridgevertex: best pinched p%d(v%d) and vertex p%d(v%d) are closest (%2.2g) for duplicated ridge r%d (same vertices) between f%d and f%d\n",
+      qh_pointid(qh, (*pinchedp)->point), (*pinchedp)->id, qh_pointid(qh, bestvertex->point), bestvertex->id, *distp, ridge->id, ridge->top->id, ridge->bottom->id));
+  return bestvertex;
+} /* findbest_ridgevertex */
+
+/*---------------------------------
+
+  qh_findbest_test(qh, testcentrum, facet, neighbor, &bestfacet, &dist, &mindist, &maxdist )
+    test neighbor of facet for qh_findbestneighbor()
+    if testcentrum,
+      tests centrum (assumes it is defined)
+    else
+      tests vertices
+    initially *bestfacet==NULL and *dist==REALmax
+
+  returns:
+    if a better facet (i.e., vertices/centrum of facet closer to neighbor)
+      updates bestfacet, dist, mindist, and maxdist
+
+  notes:
+    called by qh_findbestneighbor
+    ignores pairs of flipped facets, unless that's all there is
+*/
+void qh_findbest_test(qhT *qh, boolT testcentrum, facetT *facet, facetT *neighbor,
+      facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
+  realT dist, mindist, maxdist;
+
+  if (facet->flipped && neighbor->flipped && *bestfacet && !(*bestfacet)->flipped)
+    return; /* do not merge flipped into flipped facets */
+  if (testcentrum) {
+    zzinc_(Zbestdist);
+    qh_distplane(qh, facet->center, neighbor, &dist);
+    dist *= qh->hull_dim; /* estimate furthest vertex */
+    if (dist < 0) {
+      maxdist= 0;
+      mindist= dist;
+      dist= -dist;
+    }else {
+      mindist= 0;
+      maxdist= dist;
+    }
+  }else
+    dist= qh_getdistance(qh, facet, neighbor, &mindist, &maxdist);
+  if (dist < *distp) {
+    *bestfacet= neighbor;
+    *mindistp= mindist;
+    *maxdistp= maxdist;
+    *distp= dist;
+  }
+} /* findbest_test */
+
+/*---------------------------------
+
+  qh_findbestneighbor(qh, facet, dist, mindist, maxdist )
+    finds best neighbor (least dist) of a facet for merging
+
+  returns:
+    returns min and max distances and their max absolute value
+
+  notes:
+    error if qh_ASvoronoi
+    avoids merging old into new
+    assumes ridge->nonconvex only set on one ridge between a pair of facets
+    could use an early out predicate but not worth it
+
+  design:
+    if a large facet
+      will test centrum
+    else
+      will test vertices
+    if a large facet
+      test nonconvex neighbors for best merge
+    else
+      test all neighbors for the best merge
+    if testing centrum
+      get distance information
+*/
+facetT *qh_findbestneighbor(qhT *qh, facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
+  facetT *neighbor, **neighborp, *bestfacet= NULL;
+  ridgeT *ridge, **ridgep;
+  boolT nonconvex= True, testcentrum= False;
+  int size= qh_setsize(qh, facet->vertices);
+
+  if(qh->CENTERtype==qh_ASvoronoi){
+    qh_fprintf(qh, qh->ferr, 6272, "qhull internal error: cannot call qh_findbestneighor for f%d while qh.CENTERtype is qh_ASvoronoi\n", facet->id);
+    qh_errexit(qh, qh_ERRqhull, facet, NULL);
+  }
+  *distp= REALmax;
+  if (size > qh_BESTcentrum2 * qh->hull_dim + qh_BESTcentrum) {
+    testcentrum= True;
+    zinc_(Zbestcentrum);
+    if (!facet->center)
+       facet->center= qh_getcentrum(qh, facet);
+  }
+  if (size > qh->hull_dim + qh_BESTnonconvex) {
+    FOREACHridge_(facet->ridges) {
+      if (ridge->nonconvex) {
+        neighbor= otherfacet_(ridge, facet);
+        qh_findbest_test(qh, testcentrum, facet, neighbor,
+                          &bestfacet, distp, mindistp, maxdistp);
+      }
+    }
+  }
+  if (!bestfacet) {
+    nonconvex= False;
+    FOREACHneighbor_(facet)
+      qh_findbest_test(qh, testcentrum, facet, neighbor,
+                        &bestfacet, distp, mindistp, maxdistp);
+  }
+  if (!bestfacet) {
+    qh_fprintf(qh, qh->ferr, 6095, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
+    qh_errexit(qh, qh_ERRqhull, facet, NULL);
+  }
+  if (testcentrum)
+    qh_getdistance(qh, facet, bestfacet, mindistp, maxdistp);
+  trace3((qh, qh->ferr, 3002, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
+     bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
+  return(bestfacet);
+} /* findbestneighbor */
+
+
+/*---------------------------------
+
+  qh_flippedmerges(qh, facetlist, wasmerge )
+    merge flipped facets into best neighbor
+    assumes qh.facet_mergeset at top of temporary stack
+
+  returns:
+    no flipped facets on facetlist
+    sets wasmerge if merge occurred
+    degen/redundant merges passed through
+
+  notes:
+    othermerges not needed since qh.facet_mergeset is empty before & after
+      keep it in case of change
+
+  design:
+    append flipped facets to qh.facetmergeset
+    for each flipped merge
+      find best neighbor
+      merge facet into neighbor
+      merge degenerate and redundant facets
+    remove flipped merges from qh.facet_mergeset
+*/
+void qh_flippedmerges(qhT *qh, facetT *facetlist, boolT *wasmerge) {
+  facetT *facet, *neighbor, *facet1;
+  realT dist, mindist, maxdist;
+  mergeT *merge, **mergep;
+  setT *othermerges;
+  int nummerge= 0, numdegen= 0;
+
+  trace4((qh, qh->ferr, 4024, "qh_flippedmerges: begin\n"));
+  FORALLfacet_(facetlist) {
+    if (facet->flipped && !facet->visible)
+      qh_appendmergeset(qh, facet, facet, MRGflip, 0.0, 1.0);
+  }
+  othermerges= qh_settemppop(qh);
+  if(othermerges != qh->facet_mergeset) {
+    qh_fprintf(qh, qh->ferr, 6392, "qhull internal error (qh_flippedmerges): facet_mergeset (%d merges) not at top of tempstack (%d merges)\n",
+        qh_setsize(qh, qh->facet_mergeset), qh_setsize(qh, othermerges));
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh->facet_mergeset= qh_settemp(qh, qh->TEMPsize);
+  qh_settemppush(qh, othermerges);
+  FOREACHmerge_(othermerges) {
+    facet1= merge->facet1;
+    if (merge->mergetype != MRGflip || facet1->visible)
+      continue;
+    if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+      qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+    neighbor= qh_findbestneighbor(qh, facet1, &dist, &mindist, &maxdist);
+    trace0((qh, qh->ferr, 15, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
+      facet1->id, neighbor->id, dist, qh->furthest_id));
+    qh_mergefacet(qh, facet1, neighbor, merge->mergetype, &mindist, &maxdist, !qh_MERGEapex);
+    nummerge++;
+    if (qh->PRINTstatistics) {
+      zinc_(Zflipped);
+      wadd_(Wflippedtot, dist);
+      wmax_(Wflippedmax, dist);
+    }
+  }
+  FOREACHmerge_(othermerges) {
+    if (merge->facet1->visible || merge->facet2->visible)
+      qh_memfree(qh, merge, (int)sizeof(mergeT)); /* invalidates merge and othermerges */
+    else
+      qh_setappend(qh, &qh->facet_mergeset, merge);
+  }
+  qh_settempfree(qh, &othermerges);
+  numdegen += qh_merge_degenredundant(qh); /* somewhat better here than after each flipped merge -- qtest.sh 10 '500 C1,2e-13 D4' 'd Qbb' */
+  if (nummerge)
+    *wasmerge= True;
+  trace1((qh, qh->ferr, 1010, "qh_flippedmerges: merged %d flipped and %d degenredundant facets into a good neighbor\n",
+    nummerge, numdegen));
+} /* flippedmerges */
+
+
+/*---------------------------------
+
+  qh_forcedmerges(qh, wasmerge )
+    merge dupridges
+    calls qh_check_dupridge to report an error on wide merges
+    assumes qh_settemppop is qh.facet_mergeset
+
+  returns:
+    removes all dupridges on facet_mergeset
+    wasmerge set if merge
+    qh.facet_mergeset may include non-forced merges(none for now)
+    qh.degen_mergeset includes degen/redun merges
+
+  notes:
+    called by qh_premerge
+    dupridges occur when the horizon is pinched,
+        i.e. a subridge occurs in more than two horizon ridges.
+     could rename vertices that pinch the horizon
+    assumes qh_merge_degenredundant() has not be called
+    othermerges isn't needed since facet_mergeset is empty afterwards
+      keep it in case of change
+
+  design:
+    for each dupridge
+      find current facets by chasing f.replace links
+      check for wide merge due to dupridge
+      determine best direction for facet
+      merge one facet into the other
+      remove dupridges from qh.facet_mergeset
+*/
+void qh_forcedmerges(qhT *qh, boolT *wasmerge) {
+  facetT *facet1, *facet2, *merging, *merged, *newfacet;
+  mergeT *merge, **mergep;
+  realT dist, mindist, maxdist, dist2, mindist2, maxdist2;
+  setT *othermerges;
+  int nummerge=0, numflip=0, numdegen= 0;
+  boolT wasdupridge= False;
+
+  if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+    qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+  trace3((qh, qh->ferr, 3054, "qh_forcedmerges: merge dupridges\n"));
+  othermerges= qh_settemppop(qh); /* was facet_mergeset */
+  if (qh->facet_mergeset != othermerges ) {
+      qh_fprintf(qh, qh->ferr, 6279, "qhull internal error (qh_forcedmerges): qh_settemppop (size %d) is not qh->facet_mergeset (size %d)\n",
+          qh_setsize(qh, othermerges), qh_setsize(qh, qh->facet_mergeset));
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh->facet_mergeset= qh_settemp(qh, qh->TEMPsize);
+  qh_settemppush(qh, othermerges);
+  FOREACHmerge_(othermerges) {
+    if (merge->mergetype != MRGdupridge)
+        continue;
+    wasdupridge= True;
+    if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+        qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+    facet1= qh_getreplacement(qh, merge->facet1);  /* must exist, no qh_merge_degenredunant */
+    facet2= qh_getreplacement(qh, merge->facet2);  /* previously merged facet, if any */
+    if (facet1 == facet2)
+      continue;
+    if (!qh_setin(facet2->neighbors, facet1)) {
+      qh_fprintf(qh, qh->ferr, 6096, "qhull internal error (qh_forcedmerges): f%d and f%d had a dupridge but as f%d and f%d they are no longer neighbors\n",
+               merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
+      qh_errexit2(qh, qh_ERRqhull, facet1, facet2);
+    }
+    dist= qh_getdistance(qh, facet1, facet2, &mindist, &maxdist);
+    dist2= qh_getdistance(qh, facet2, facet1, &mindist2, &maxdist2);
+    qh_check_dupridge(qh, facet1, dist, facet2, dist2);
+    if (dist < dist2) {
+      if (facet2->flipped && !facet1->flipped && dist2 < qh_WIDEdupridge*(qh->ONEmerge+qh->DISTround)) { /* prefer merge of flipped facet */
+        merging= facet2;
+        merged= facet1;
+        dist= dist2;
+        mindist= mindist2;
+        maxdist= maxdist2;
+      }else {
+        merging= facet1;
+        merged= facet2;
+      }
+    }else {
+      if (facet1->flipped && !facet2->flipped && dist < qh_WIDEdupridge*(qh->ONEmerge+qh->DISTround)) { /* prefer merge of flipped facet */
+        merging= facet1;
+        merged= facet2;
+      }else {
+        merging= facet2;
+        merged= facet1;
+        dist= dist2;
+        mindist= mindist2;
+        maxdist= maxdist2;
+      }
+    }
+    qh_mergefacet(qh, merging, merged, merge->mergetype, &mindist, &maxdist, !qh_MERGEapex);
+    numdegen += qh_merge_degenredundant(qh); /* better here than at end -- qtest.sh 10 '500 C1,2e-13 D4' 'd Qbb' */
+    if (facet1->flipped) {
+      zinc_(Zmergeflipdup);
+      numflip++;
+    }else
+      nummerge++;
+    if (qh->PRINTstatistics) {
+      zinc_(Zduplicate);
+      wadd_(Wduplicatetot, dist);
+      wmax_(Wduplicatemax, dist);
+    }
+  }
+  FOREACHmerge_(othermerges) {
+    if (merge->mergetype == MRGdupridge)
+      qh_memfree(qh, merge, (int)sizeof(mergeT)); /* invalidates merge and othermerges */
+    else
+      qh_setappend(qh, &qh->facet_mergeset, merge);
+  }
+  qh_settempfree(qh, &othermerges);
+  if (wasdupridge) {
+    FORALLnew_facets {
+      if (newfacet->dupridge) {
+        newfacet->dupridge= False;
+        newfacet->mergeridge= False;
+        newfacet->mergeridge2= False;
+        if (qh_setsize(qh, newfacet->neighbors) < qh->hull_dim) { /* not tested for MRGdupridge */
+          qh_appendmergeset(qh, newfacet, newfacet, MRGdegen, 0.0, 1.0);
+          trace2((qh, qh->ferr, 2107, "qh_forcedmerges: dupridge f%d is degenerate with fewer than %d neighbors\n",
+                      newfacet->id, qh->hull_dim));
+        }
+      }
+    }
+    numdegen += qh_merge_degenredundant(qh);
+  }
+  if (nummerge || numflip) {
+    *wasmerge= True;
+    trace1((qh, qh->ferr, 1011, "qh_forcedmerges: merged %d facets, %d flipped facets, and %d degenredundant facets across dupridges\n",
+                  nummerge, numflip, numdegen));
+  }
+} /* forcedmerges */
+
+
+/*---------------------------------
+
+  qh_freemergesets(qh )
+    free the merge sets
+
+  notes:
+    matches qh_initmergesets
+*/
+void qh_freemergesets(qhT *qh) {
+
+  if (!qh->facet_mergeset || !qh->degen_mergeset || !qh->vertex_mergeset) {
+    qh_fprintf(qh, qh->ferr, 6388, "qhull internal error (qh_freemergesets): expecting mergesets.  Got a NULL mergeset, qh.facet_mergeset (%p), qh.degen_mergeset (%p), qh.vertex_mergeset (%p)\n",
+      (void *) qh->facet_mergeset, (void *) qh->degen_mergeset, (void *) qh->vertex_mergeset);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (!SETempty_(qh->facet_mergeset) || !SETempty_(qh->degen_mergeset) || !SETempty_(qh->vertex_mergeset)) {
+    qh_fprintf(qh, qh->ferr, 6389, "qhull internal error (qh_freemergesets): expecting empty mergesets.  Got qh.facet_mergeset (%d merges), qh.degen_mergeset (%d merges), qh.vertex_mergeset (%d merges)\n",
+      qh_setsize(qh, qh->facet_mergeset), qh_setsize(qh, qh->degen_mergeset), qh_setsize(qh, qh->vertex_mergeset));
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh_settempfree(qh, &qh->facet_mergeset);
+  qh_settempfree(qh, &qh->vertex_mergeset);
+  qh_settempfree(qh, &qh->degen_mergeset);
+} /* freemergesets */
+
+/*---------------------------------
+
+  qh_getmergeset(qh, facetlist )
+    determines nonconvex facets on facetlist
+    tests !tested ridges and nonconvex ridges of !tested facets
+
+  returns:
+    returns sorted qh.facet_mergeset of facet-neighbor pairs to be merged
+    all ridges tested
+
+  notes:
+    facetlist is qh.facet_newlist, use qh_getmergeset_initial for all facets
+    assumes no nonconvex ridges with both facets tested
+    uses facet->tested/ridge->tested to prevent duplicate tests
+    can not limit tests to modified ridges since the centrum changed
+    uses qh.visit_id
+
+  design:
+    for each facet on facetlist
+      for each ridge of facet
+        if untested ridge
+          test ridge for convexity
+          if non-convex
+            append ridge to qh.facet_mergeset
+    sort qh.facet_mergeset by mergetype and angle or distance
+*/
+void qh_getmergeset(qhT *qh, facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int nummerges;
+  boolT simplicial;
+
+  nummerges= qh_setsize(qh, qh->facet_mergeset);
+  trace4((qh, qh->ferr, 4026, "qh_getmergeset: started.\n"));
+  qh->visit_id++;
+  FORALLfacet_(facetlist) {
+    if (facet->tested)
+      continue;
+    facet->visitid= qh->visit_id;
+    FOREACHneighbor_(facet)
+      neighbor->seen= False;
+    /* facet must be non-simplicial due to merge to qh.facet_newlist */
+    FOREACHridge_(facet->ridges) {
+      if (ridge->tested && !ridge->nonconvex)
+        continue;
+      /* if r.tested & r.nonconvex, need to retest and append merge */
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->seen) { /* another ridge for this facet-neighbor pair was already tested in this loop */
+        ridge->tested= True;
+        ridge->nonconvex= False;   /* only one ridge is marked nonconvex per facet-neighbor pair */
+      }else if (neighbor->visitid != qh->visit_id) {
+        neighbor->seen= True;
+        ridge->nonconvex= False;
+        simplicial= False;
+        if (ridge->simplicialbot && ridge->simplicialtop)
+          simplicial= True;
+        if (qh_test_appendmerge(qh, facet, neighbor, simplicial))
+          ridge->nonconvex= True;
+        ridge->tested= True;
+      }
+    }
+    facet->tested= True;
+  }
+  nummerges= qh_setsize(qh, qh->facet_mergeset);
+  if (qh->ANGLEmerge)
+    qsort(SETaddr_(qh->facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compare_anglemerge);
+  else
+    qsort(SETaddr_(qh->facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compare_facetmerge);
+  nummerges += qh_setsize(qh, qh->degen_mergeset);
+  if (qh->POSTmerging) {
+    zadd_(Zmergesettot2, nummerges);
+  }else {
+    zadd_(Zmergesettot, nummerges);
+    zmax_(Zmergesetmax, nummerges);
+  }
+  trace2((qh, qh->ferr, 2021, "qh_getmergeset: %d merges found\n", nummerges));
+} /* getmergeset */
+
+
+/*---------------------------------
+
+  qh_getmergeset_initial(qh, facetlist )
+    determine initial qh.facet_mergeset for facets
+    tests all facet/neighbor pairs on facetlist
+
+  returns:
+    sorted qh.facet_mergeset with nonconvex ridges
+    sets facet->tested, ridge->tested, and ridge->nonconvex
+
+  notes:
+    uses visit_id, assumes ridge->nonconvex is False
+    see qh_getmergeset
+
+  design:
+    for each facet on facetlist
+      for each untested neighbor of facet
+        test facet and neighbor for convexity
+        if non-convex
+          append merge to qh.facet_mergeset
+          mark one of the ridges as nonconvex
+    sort qh.facet_mergeset by mergetype and angle or distance
+*/
+void qh_getmergeset_initial(qhT *qh, facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int nummerges;
+  boolT simplicial;
+
+  qh->visit_id++;
+  FORALLfacet_(facetlist) {
+    facet->visitid= qh->visit_id;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh->visit_id) {
+        simplicial= False; /* ignores r.simplicialtop/simplicialbot.  Need to test horizon facets */
+        if (facet->simplicial && neighbor->simplicial)
+          simplicial= True;
+        if (qh_test_appendmerge(qh, facet, neighbor, simplicial)) {
+          FOREACHridge_(neighbor->ridges) {
+            if (facet == otherfacet_(ridge, neighbor)) {
+              ridge->nonconvex= True;
+              break;    /* only one ridge is marked nonconvex */
+            }
+          }
+        }
+      }
+    }
+    facet->tested= True;
+    FOREACHridge_(facet->ridges)
+      ridge->tested= True;
+  }
+  nummerges= qh_setsize(qh, qh->facet_mergeset);
+  if (qh->ANGLEmerge)
+    qsort(SETaddr_(qh->facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compare_anglemerge);
+  else
+    qsort(SETaddr_(qh->facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compare_facetmerge);
+  nummerges += qh_setsize(qh, qh->degen_mergeset);
+  if (qh->POSTmerging) {
+    zadd_(Zmergeinittot2, nummerges);
+  }else {
+    zadd_(Zmergeinittot, nummerges);
+    zmax_(Zmergeinitmax, nummerges);
+  }
+  trace2((qh, qh->ferr, 2022, "qh_getmergeset_initial: %d merges found\n", nummerges));
+} /* getmergeset_initial */
+
+/*---------------------------------
+
+  qh_getpinchedmerges(qh, apex, maxdist, iscoplanar )
+    get pinched merges for dupridges in qh.facet_mergeset
+    qh.NEWtentative==True
+      qh.newfacet_list with apex
+      qh.horizon_list is attached to qh.visible_list instead of qh.newfacet_list
+      maxdist for vertex-facet of a dupridge
+    qh.facet_mergeset is empty
+    qh.vertex_mergeset is a temporary set
+
+  returns:
+    False if nearest vertex would increase facet width by more than maxdist or qh_WIDEpinched
+    True and iscoplanar, if the pinched vertex is the apex (i.e., make the apex a coplanar point)
+    True and !iscoplanar, if should merge a pinched vertex of a dupridge
+      qh.vertex_mergeset contains one or more MRGsubridge with a pinched vertex and a nearby, neighboring vertex
+    qh.facet_mergeset is empty
+
+  notes:
+    called by qh_buildcone_mergepinched
+    hull_dim >= 3
+    a pinched vertex is in a dupridge and the horizon
+    selects the pinched vertex that is closest to its neighbor
+
+  design:
+    for each dupridge
+        determine the best pinched vertex to be merged into a neighboring vertex
+        if merging the pinched vertex would produce a wide merge (qh_WIDEpinched)
+           ignore pinched vertex with a warning, and use qh_merge_degenredundant instead
+        else
+           append the pinched vertex to vertex_mergeset for merging
+*/
+boolT qh_getpinchedmerges(qhT *qh, vertexT *apex, coordT maxdupdist, boolT *iscoplanar /* qh.newfacet_list, qh.vertex_mergeset */) {
+  mergeT *merge, **mergep, *bestmerge= NULL;
+  vertexT *nearest, *pinched, *bestvertex= NULL, *bestpinched= NULL;
+  boolT result;
+  coordT dist, prevdist, bestdist= REALmax/(qh_RATIOcoplanarapex+1.0); /* allow *3.0 */
+  realT ratio;
+
+  trace2((qh, qh->ferr, 2062, "qh_getpinchedmerges: try to merge pinched vertices for dupridges in new facets with apex p%d(v%d) max dupdist %2.2g\n",
+      qh_pointid(qh, apex->point), apex->id, maxdupdist));
+  *iscoplanar= False;
+  prevdist= fmax_(qh->ONEmerge + qh->DISTround, qh->MINoutside + qh->DISTround);
+  maximize_(prevdist, qh->max_outside);
+  maximize_(prevdist, -qh->min_vertex);
+  qh_mark_dupridges(qh, qh->newfacet_list, !qh_ALL); /* qh.facet_mergeset, creates ridges */
+  /* qh_mark_dupridges is called a second time in qh_premerge */
+  FOREACHmerge_(qh->facet_mergeset) {  /* read-only */
+    if (merge->mergetype != MRGdupridge) {
+      qh_fprintf(qh, qh->ferr, 6393, "qhull internal error (qh_getpinchedmerges): expecting MRGdupridge from qh_mark_dupridges.  Got merge f%d f%d type %d\n",
+        getid_(merge->facet1), getid_(merge->facet2), merge->mergetype);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+    /* dist is distance between vertices */
+    pinched= qh_findbest_pinchedvertex(qh, merge, apex, &nearest, &dist /* qh.newfacet_list */);
+    if (pinched == apex && dist < qh_RATIOcoplanarapex*bestdist) { /* prefer coplanar apex since it always works */
+      bestdist= dist/qh_RATIOcoplanarapex;
+      bestmerge= merge;
+      bestpinched= pinched;
+      bestvertex= nearest;
+    }else if (dist < bestdist) {
+      bestdist= dist;
+      bestmerge= merge;
+      bestpinched= pinched;
+      bestvertex= nearest;
+    }
+  }
+  result= False;
+  if (bestmerge && bestdist < maxdupdist) {
+    ratio= bestdist / prevdist;
+    if (ratio > qh_WIDEpinched) {
+      if (bestmerge->facet1->mergehorizon || bestmerge->facet2->mergehorizon) { /* e.g., rbox 175 C3,2e-13 t1539182828 | qhull d */
+        trace1((qh, qh->ferr, 1051, "qh_getpinchedmerges: dupridge (MRGdupridge) of coplanar horizon would produce a wide merge (%.0fx) due to pinched vertices v%d and v%d (dist %2.2g) for f%d and f%d.  qh_mergecycle_all will merge one or both facets\n",
+          ratio, bestpinched->id, bestvertex->id, bestdist, bestmerge->facet1->id, bestmerge->facet2->id));
+      }else {
+        qh_fprintf(qh, qh->ferr, 7081, "qhull precision warning (qh_getpinchedmerges): pinched vertices v%d and v%d (dist %2.2g, %.0fx) would produce a wide merge for f%d and f%d.  Will merge dupridge instead\n",
+          bestpinched->id, bestvertex->id, bestdist, ratio, bestmerge->facet1->id, bestmerge->facet2->id);
+      }
+    }else {
+      if (bestpinched == apex) {
+        trace2((qh, qh->ferr, 2063, "qh_getpinchedmerges: will make the apex a coplanar point.  apex p%d(v%d) is the nearest vertex to v%d on dupridge.  Dist %2.2g\n",
+          qh_pointid(qh, apex->point), apex->id, bestvertex->id, bestdist*qh_RATIOcoplanarapex));
+        qh->coplanar_apex= apex->point;
+        *iscoplanar= True;
+        result= True;
+      }else if (qh_setin(bestmerge->facet1->vertices, bestpinched) != qh_setin(bestmerge->facet2->vertices, bestpinched)) { /* pinched in one facet but not the other facet */
+        trace2((qh, qh->ferr, 2064, "qh_getpinchedmerges: will merge new facets to resolve dupridge between f%d and f%d with pinched v%d and v%d\n",
+          bestmerge->facet1->id, bestmerge->facet2->id, bestpinched->id, bestvertex->id));
+        qh_appendvertexmerge(qh, bestpinched, bestvertex, MRGsubridge, bestdist, NULL, NULL);
+        result= True;
+      }else {
+        trace2((qh, qh->ferr, 2065, "qh_getpinchedmerges: will merge pinched v%d into v%d to resolve dupridge between f%d and f%d\n",
+          bestpinched->id, bestvertex->id, bestmerge->facet1->id, bestmerge->facet2->id));
+        qh_appendvertexmerge(qh, bestpinched, bestvertex, MRGsubridge, bestdist, NULL, NULL);
+        result= True;
+      }
+    }
+  }
+  /* delete MRGdupridge, qh_mark_dupridges is called a second time in qh_premerge */
+  while ((merge= (mergeT *)qh_setdellast(qh->facet_mergeset)))
+    qh_memfree(qh, merge, (int)sizeof(mergeT));
+  return result;
+}/* getpinchedmerges */
+
+/*---------------------------------
+
+  qh_hasmerge( mergeset, mergetype, facetA, facetB )
+    True if mergeset has mergetype for facetA and facetB
+*/
+boolT   qh_hasmerge(setT *mergeset, mergeType type, facetT *facetA, facetT *facetB) {
+  mergeT *merge, **mergep;
+
+  FOREACHmerge_(mergeset) {
+    if (merge->mergetype == type) {
+      if (merge->facet1 == facetA && merge->facet2 == facetB)
+        return True;
+      if (merge->facet1 == facetB && merge->facet2 == facetA)
+        return True;
+    }
+  }
+  return False;
+}/* hasmerge */
+
+/*---------------------------------
+
+  qh_hashridge(qh, hashtable, hashsize, ridge, oldvertex )
+    add ridge to hashtable without oldvertex
+
+  notes:
+    assumes hashtable is large enough
+
+  design:
+    determine hash value for ridge without oldvertex
+    find next empty slot for ridge
+*/
+void qh_hashridge(qhT *qh, setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
+  int hash;
+  ridgeT *ridgeA;
+
+  hash= qh_gethash(qh, hashsize, ridge->vertices, qh->hull_dim-1, 0, oldvertex);
+  while (True) {
+    if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+      SETelem_(hashtable, hash)= ridge;
+      break;
+    }else if (ridgeA == ridge)
+      break;
+    if (++hash == hashsize)
+      hash= 0;
+  }
+} /* hashridge */
+
+
+/*---------------------------------
+
+  qh_hashridge_find(qh, hashtable, hashsize, ridge, vertex, oldvertex, hashslot )
+    returns matching ridge without oldvertex in hashtable
+      for ridge without vertex
+    if oldvertex is NULL
+      matches with any one skip
+
+  returns:
+    matching ridge or NULL
+    if no match,
+      if ridge already in   table
+        hashslot= -1
+      else
+        hashslot= next NULL index
+
+  notes:
+    assumes hashtable is large enough
+    can't match ridge to itself
+
+  design:
+    get hash value for ridge without vertex
+    for each hashslot
+      return match if ridge matches ridgeA without oldvertex
+*/
+ridgeT *qh_hashridge_find(qhT *qh, setT *hashtable, int hashsize, ridgeT *ridge,
+              vertexT *vertex, vertexT *oldvertex, int *hashslot) {
+  int hash;
+  ridgeT *ridgeA;
+
+  *hashslot= 0;
+  zinc_(Zhashridge);
+  hash= qh_gethash(qh, hashsize, ridge->vertices, qh->hull_dim-1, 0, vertex);
+  while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+    if (ridgeA == ridge)
+      *hashslot= -1;
+    else {
+      zinc_(Zhashridgetest);
+      if (qh_setequal_except(ridge->vertices, vertex, ridgeA->vertices, oldvertex))
+        return ridgeA;
+    }
+    if (++hash == hashsize)
+      hash= 0;
+  }
+  if (!*hashslot)
+    *hashslot= hash;
+  return NULL;
+} /* hashridge_find */
+
+
+/*---------------------------------
+
+  qh_initmergesets(qh )
+    initialize the merge sets
+    if 'all', include qh.degen_mergeset
+
+  notes:
+    matches qh_freemergesets
+*/
+void qh_initmergesets(qhT *qh /* qh.facet_mergeset,degen_mergeset,vertex_mergeset */) {
+
+  if (qh->facet_mergeset || qh->degen_mergeset || qh->vertex_mergeset) {
+    qh_fprintf(qh, qh->ferr, 6386, "qhull internal error (qh_initmergesets): expecting NULL mergesets.  Got qh.facet_mergeset (%p), qh.degen_mergeset (%p), qh.vertex_mergeset (%p)\n",
+      (void *) qh->facet_mergeset, (void *) qh->degen_mergeset, (void *) qh->vertex_mergeset);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh->degen_mergeset= qh_settemp(qh, qh->TEMPsize);
+  qh->vertex_mergeset= qh_settemp(qh, qh->TEMPsize);
+  qh->facet_mergeset= qh_settemp(qh, qh->TEMPsize); /* last temporary set for qh_forcedmerges */
+} /* initmergesets */
+
+/*---------------------------------
+
+  qh_makeridges(qh, facet )
+    creates explicit ridges between simplicial facets
+
+  returns:
+    facet with ridges and without qh_MERGEridge
+    ->simplicial is False
+    if facet was tested, new ridges are tested
+
+  notes:
+    allows qh_MERGEridge flag
+    uses existing ridges
+    duplicate neighbors ok if ridges already exist (qh_mergecycle_ridges)
+
+  see:
+    qh_mergecycle_ridges()
+    qh_rename_adjacentvertex for qh_merge_pinchedvertices
+
+  design:
+    look for qh_MERGEridge neighbors
+    mark neighbors that already have ridges
+    for each unprocessed neighbor of facet
+      create a ridge for neighbor and facet
+    if any qh_MERGEridge neighbors
+      delete qh_MERGEridge flags (previously processed by qh_mark_dupridges)
+*/
+void qh_makeridges(qhT *qh, facetT *facet) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int neighbor_i, neighbor_n;
+  boolT toporient, mergeridge= False;
+
+  if (!facet->simplicial)
+    return;
+  trace4((qh, qh->ferr, 4027, "qh_makeridges: make ridges for f%d\n", facet->id));
+  facet->simplicial= False;
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge)
+      mergeridge= True;
+    else
+      neighbor->seen= False;
+  }
+  FOREACHridge_(facet->ridges)
+    otherfacet_(ridge, facet)->seen= True;
+  FOREACHneighbor_i_(qh, facet) {
+    if (neighbor == qh_MERGEridge)
+      continue;  /* fixed by qh_mark_dupridges */
+    else if (!neighbor->seen) {  /* no current ridges */
+      ridge= qh_newridge(qh);
+      ridge->vertices= qh_setnew_delnthsorted(qh, facet->vertices, qh->hull_dim,
+                                                          neighbor_i, 0);
+      toporient= (boolT)(facet->toporient ^ (neighbor_i & 0x1));
+      if (toporient) {
+        ridge->top= facet;
+        ridge->bottom= neighbor;
+        ridge->simplicialtop= True;
+        ridge->simplicialbot= neighbor->simplicial;
+      }else {
+        ridge->top= neighbor;
+        ridge->bottom= facet;
+        ridge->simplicialtop= neighbor->simplicial;
+        ridge->simplicialbot= True;
+      }
+      if (facet->tested && !mergeridge)
+        ridge->tested= True;
+#if 0 /* this also works */
+      flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
+      if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
+        ridge->top= neighbor;
+        ridge->bottom= facet;
+        ridge->simplicialtop= True;
+        ridge->simplicialbot= neighbor->simplicial;
+      }else {
+        ridge->top= facet;
+        ridge->bottom= neighbor;
+        ridge->simplicialtop= neighbor->simplicial;
+        ridge->simplicialbot= True;
+      }
+#endif
+      qh_setappend(qh, &(facet->ridges), ridge);
+      trace5((qh, qh->ferr, 5005, "makeridges: appended r%d to ridges for f%d.  Next is ridges for neighbor f%d\n",
+            ridge->id, facet->id, neighbor->id));
+      qh_setappend(qh, &(neighbor->ridges), ridge);
+      if (qh->ridge_id == qh->traceridge_id)
+        qh->traceridge= ridge;
+    }
+  }
+  if (mergeridge) {
+    while (qh_setdel(facet->neighbors, qh_MERGEridge))
+      ; /* delete each one */
+  }
+} /* makeridges */
+
+
+/*---------------------------------
+
+  qh_mark_dupridges(qh, facetlist, allmerges )
+    add duplicated ridges to qh.facet_mergeset
+    facet-dupridge is true if it contains a subridge shared by more than one new facet
+    for each such facet, one has a neighbor marked qh_MERGEridge
+    allmerges is true if merging dupridges
+    allmerges is false if merging pinched vertices followed by retry addpoint
+      qh_mark_dupridges will be called again if pinched vertices not found
+
+  returns:
+    dupridges on qh.facet_mergeset (MRGdupridge)
+    f.mergeridge and f.mergeridge2 set for facet
+    f.mergeridge set for neighbor
+    if allmerges is true
+      make ridges for facets with dupridges as marked by qh_MERGEridge and both sides facet->dupridge
+      removes qh_MERGEridge from neighbor sets
+
+  notes:
+    called by qh_premerge and qh_getpinchedmerges
+    dupridges are due to duplicate subridges
+        i.e. a subridge occurs in more than two horizon ridges.
+        i.e., a ridge has more than two neighboring facets
+    dupridges occur in at least two cases
+    1) a pinched horizon with nearly adjacent vertices -> merge the vertices (qh_getpinchedmerges)
+    2) more than one newfacet for a horizon face -> merge coplanar facets (qh_premerge)
+    qh_matchdupridge previously identified the furthest apart pair of facets to retain
+       they must have a matching subridge and the same orientation
+    only way to set facet->mergeridge and mergeridge2
+    uses qh.visit_id
+
+  design:
+    for all facets on facetlist
+      if facet contains a dupridge
+        for each neighbor of facet
+          if neighbor marked qh_MERGEridge (one side of the merge)
+            set facet->mergeridge
+          else
+            if neighbor contains a dupridge
+            and the back link is qh_MERGEridge
+              append dupridge to qh.facet_mergeset
+   exit if !allmerges for repeating qh_mark_dupridges later
+   for each dupridge
+     make ridge sets in preparation for merging
+     remove qh_MERGEridge from neighbor set
+   for each dupridge
+     restore the missing neighbor from the neighbor set that was qh_MERGEridge
+     add the missing ridge for this neighbor
+*/
+void qh_mark_dupridges(qhT *qh, facetT *facetlist, boolT allmerges) {
+  facetT *facet, *neighbor, **neighborp;
+  int nummerge=0;
+  mergeT *merge, **mergep;
+
+  trace4((qh, qh->ferr, 4028, "qh_mark_dupridges: identify dupridges in facetlist f%d, allmerges? %d\n",
+    facetlist->id, allmerges));
+  FORALLfacet_(facetlist) {  /* not necessary for first call */
+    facet->mergeridge2= False;
+    facet->mergeridge= False;
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->dupridge) {
+      FOREACHneighbor_(facet) {
+        if (neighbor == qh_MERGEridge) {
+          facet->mergeridge= True;
+          continue;
+        }
+        if (neighbor->dupridge) {
+          if (!qh_setin(neighbor->neighbors, facet)) { /* i.e., it is qh_MERGEridge, neighbors are distinct */
+            qh_appendmergeset(qh, facet, neighbor, MRGdupridge, 0.0, 1.0);
+            facet->mergeridge2= True;
+            facet->mergeridge= True;
+            nummerge++;
+          }else if (qh_setequal(facet->vertices, neighbor->vertices)) { /* neighbors are the same except for horizon and qh_MERGEridge, see QH7085 */
+            trace3((qh, qh->ferr, 3043, "qh_mark_dupridges): dupridge due to duplicate vertices for subridges f%d and f%d\n",
+                 facet->id, neighbor->id));
+            qh_appendmergeset(qh, facet, neighbor, MRGdupridge, 0.0, 1.0);
+            facet->mergeridge2= True;
+            facet->mergeridge= True;
+            nummerge++;
+            break; /* same for all neighbors */
+          }
+        }
+      }
+    }
+  }
+  if (!nummerge)
+    return;
+  if (!allmerges) {
+    trace1((qh, qh->ferr, 1012, "qh_mark_dupridges: found %d duplicated ridges (MRGdupridge) for qh_getpinchedmerges\n", nummerge));
+    return;
+  }
+  trace1((qh, qh->ferr, 1048, "qh_mark_dupridges: found %d duplicated ridges (MRGdupridge) for qh_premerge.  Prepare facets for merging\n", nummerge));
+  /* make ridges in preparation for merging */
+  FORALLfacet_(facetlist) {
+    if (facet->mergeridge && !facet->mergeridge2)
+      qh_makeridges(qh, facet);
+  }
+  trace3((qh, qh->ferr, 3075, "qh_mark_dupridges: restore missing neighbors and ridges due to qh_MERGEridge\n"));
+  FOREACHmerge_(qh->facet_mergeset) {   /* restore the missing neighbors */
+    if (merge->mergetype == MRGdupridge) { /* only between simplicial facets */
+      if (merge->facet2->mergeridge2 && qh_setin(merge->facet2->neighbors, merge->facet1)) {
+        /* Due to duplicate or multiple subridges, e.g., ../eg/qtest.sh t712682 '200 s W1e-13  C1,1e-13 D5' 'd'
+            merge->facet1:    - neighboring facets: f27779 f59186 f59186 f59186 MERGEridge f59186
+            merge->facet2:    - neighboring facets: f27779 f59100 f59100 f59100 f59100 f59100
+           or, ../eg/qtest.sh 100 '500 s W1e-13 C1,1e-13 D4' 'd'
+           both facets will be degenerate after merge, consider for special case handling
+        */
+        qh_fprintf(qh, qh->ferr, 6361, "qhull topological error (qh_mark_dupridges): multiple dupridges for f%d and f%d, including reverse\n",
+          merge->facet1->id, merge->facet2->id);
+        qh_errexit2(qh, qh_ERRtopology, merge->facet1, merge->facet2);
+      }else
+        qh_setappend(qh, &merge->facet2->neighbors, merge->facet1);
+      qh_makeridges(qh, merge->facet1);   /* and the missing ridges */
+    }
+  }
+} /* mark_dupridges */
+
+/*---------------------------------
+
+  qh_maybe_duplicateridge(qh, ridge )
+    add MRGvertices if neighboring facet has another ridge with the same vertices
+
+  returns:
+    adds rename requests to qh.vertex_mergeset
+
+  notes:
+    called by qh_renamevertex
+    nop if 2-D
+    expensive test
+    Duplicate ridges may lead to new facets with same vertex set (QH7084), will try merging vertices
+    same as qh_maybe_duplicateridges
+
+  design:
+    for the two neighbors
+      if non-simplicial
+        for each ridge with the same first and last vertices (max id and min id)
+          if the remaining vertices are the same
+            get the closest pair of vertices
+            add to vertex_mergeset for merging
+*/
+void qh_maybe_duplicateridge(qhT *qh, ridgeT *ridgeA) {
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, *pinched;
+  facetT *neighbor;
+  coordT dist;
+  int i, k, last= qh->hull_dim-2;
+
+  if (qh->hull_dim < 3 )
+    return;
+
+  for (neighbor= ridgeA->top, i=0; i<2; neighbor= ridgeA->bottom, i++) {
+    if (!neighbor->simplicial && neighbor->nummerge > 0) { /* skip degenerate neighbors with both new and old vertices that will be merged */
+      FOREACHridge_(neighbor->ridges) {
+        if (ridge != ridgeA && SETfirst_(ridge->vertices) == SETfirst_(ridgeA->vertices)) {
+          if (SETelem_(ridge->vertices, last) == SETelem_(ridgeA->vertices, last)) {
+            for (k=1; kvertices, k) != SETelem_(ridgeA->vertices, k))
+                break;
+            }
+            if (k == last) {
+              vertex= qh_findbest_ridgevertex(qh, ridge, &pinched, &dist);
+              trace2((qh, qh->ferr, 2069, "qh_maybe_duplicateridge: will merge v%d into v%d (dist %2.2g) due to duplicate ridges r%d/r%d with the same vertices.  mergevertex set\n",
+                pinched->id, vertex->id, dist, ridgeA->id, ridge->id));
+              qh_appendvertexmerge(qh, pinched, vertex, MRGvertices, dist, ridgeA, ridge);
+              ridge->mergevertex= True; /* disables check for duplicate vertices in qh_checkfacet */
+              ridgeA->mergevertex= True;
+            }
+          }
+        }
+      }
+    }
+  }
+} /* maybe_duplicateridge */
+
+/*---------------------------------
+
+  qh_maybe_duplicateridges(qh, facet )
+    if Q17, add MRGvertices if facet has ridges with the same vertices
+
+  returns:
+    adds rename requests to qh.vertex_mergeset
+
+  notes:
+    called at end of qh_mergefacet and qh_mergecycle_all
+    only enabled if qh.CHECKduplicates ('Q17') and 3-D or more
+    expensive test, not worth it
+    same as qh_maybe_duplicateridge
+
+  design:
+    for all ridge pairs in facet
+        if the same first and last vertices (max id and min id)
+          if the remaining vertices are the same
+            get the closest pair of vertices
+            add to vertex_mergeset for merging
+*/
+void qh_maybe_duplicateridges(qhT *qh, facetT *facet) {
+  facetT *otherfacet;
+  ridgeT *ridge, *ridge2;
+  vertexT *vertex, *pinched;
+  coordT dist;
+  int ridge_i, ridge_n, i, k, last_v= qh->hull_dim-2;
+
+  if (qh->hull_dim < 3 || !qh->CHECKduplicates)
+    return;
+
+  FOREACHridge_i_(qh, facet->ridges) {
+    otherfacet= otherfacet_(ridge, facet);
+    if (otherfacet->degenerate || otherfacet->redundant || otherfacet->dupridge || otherfacet->flipped) /* will merge */
+      continue;
+    for (i=ridge_i+1; i < ridge_n; i++) {
+      ridge2= SETelemt_(facet->ridges, i, ridgeT);
+      otherfacet= otherfacet_(ridge2, facet);
+      if (otherfacet->degenerate || otherfacet->redundant || otherfacet->dupridge || otherfacet->flipped) /* will merge */
+        continue;
+      /* optimize qh_setequal(ridge->vertices, ridge2->vertices) */
+      if (SETelem_(ridge->vertices, last_v) == SETelem_(ridge2->vertices, last_v)) { /* SETfirst is likely to be the same */
+        if (SETfirst_(ridge->vertices) == SETfirst_(ridge2->vertices)) {
+          for (k=1; kvertices, k) != SETelem_(ridge2->vertices, k))
+              break;
+          }
+          if (k == last_v) {
+            vertex= qh_findbest_ridgevertex(qh, ridge, &pinched, &dist);
+            if (ridge->top == ridge2->bottom && ridge->bottom == ridge2->top) {
+              /* proof that ridges may have opposite orientation */
+              trace2((qh, qh->ferr, 2088, "qh_maybe_duplicateridges: will merge v%d into v%d (dist %2.2g) due to opposite oriented ridges r%d/r%d for f%d and f%d\n",
+                pinched->id, vertex->id, dist, ridge->id, ridge2->id, ridge->top->id, ridge->bottom->id));
+            }else {
+              trace2((qh, qh->ferr, 2083, "qh_maybe_duplicateridges: will merge v%d into v%d (dist %2.2g) due to duplicate ridges with the same vertices r%d/r%d in merged facet f%d\n",
+                pinched->id, vertex->id, dist, ridge->id, ridge2->id, facet->id));
+            }
+            qh_appendvertexmerge(qh, pinched, vertex, MRGvertices, dist, ridge, ridge2);
+            ridge->mergevertex= True; /* disables check for duplicate vertices in qh_checkfacet */
+            ridge2->mergevertex= True;
+          }
+        }
+      }
+    }
+  }
+} /* maybe_duplicateridges */
+
+/*---------------------------------
+
+  qh_maydropneighbor(qh, facet )
+    drop neighbor relationship if ridge was deleted between a non-simplicial facet and its neighbors
+
+  returns:
+    for deleted ridges
+      ridges made for simplicial neighbors
+      neighbor sets updated
+      appends degenerate facets to qh.facet_mergeset
+
+  notes:
+    called by qh_renamevertex
+    assumes neighbors do not include qh_MERGEridge (qh_makeridges)
+    won't cause redundant facets since vertex inclusion is the same
+    may drop vertex and neighbor if no ridge
+    uses qh.visit_id
+
+  design:
+    visit all neighbors with ridges
+    for each unvisited neighbor of facet
+      delete neighbor and facet from the non-simplicial neighbor sets
+      if neighbor becomes degenerate
+        append neighbor to qh.degen_mergeset
+    if facet is degenerate
+      append facet to qh.degen_mergeset
+*/
+void qh_maydropneighbor(qhT *qh, facetT *facet) {
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor, **neighborp;
+
+  qh->visit_id++;
+  trace4((qh, qh->ferr, 4029, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
+          facet->id));
+  if (facet->simplicial) {
+    qh_fprintf(qh, qh->ferr, 6278, "qhull internal error (qh_maydropneighbor): not valid for simplicial f%d while adding furthest p%d\n",
+      facet->id, qh->furthest_id);
+    qh_errexit(qh, qh_ERRqhull, facet, NULL);
+  }
+  FOREACHridge_(facet->ridges) {
+    ridge->top->visitid= qh->visit_id;
+    ridge->bottom->visitid= qh->visit_id;
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor->visible) {
+      qh_fprintf(qh, qh->ferr, 6358, "qhull internal error (qh_maydropneighbor): facet f%d has deleted neighbor f%d (qh.visible_list)\n",
+            facet->id, neighbor->id);
+      qh_errexit2(qh, qh_ERRqhull, facet, neighbor);
+    }
+    if (neighbor->visitid != qh->visit_id) {
+      trace2((qh, qh->ferr, 2104, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors while adding furthest p%d\n",
+            facet->id, neighbor->id, qh->furthest_id));
+      if (neighbor->simplicial) {
+        qh_fprintf(qh, qh->ferr, 6280, "qhull internal error (qh_maydropneighbor): not valid for simplicial neighbor f%d of f%d while adding furthest p%d\n",
+            neighbor->id, facet->id, qh->furthest_id);
+        qh_errexit2(qh, qh_ERRqhull, neighbor, facet);
+      }
+      zinc_(Zdropneighbor);
+      qh_setdel(neighbor->neighbors, facet);
+      if (qh_setsize(qh, neighbor->neighbors) < qh->hull_dim) {
+        zinc_(Zdropdegen);
+        qh_appendmergeset(qh, neighbor, neighbor, MRGdegen, 0.0, qh_ANGLEnone);
+        trace2((qh, qh->ferr, 2023, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
+      }
+      qh_setdel(facet->neighbors, neighbor);
+      neighborp--;  /* repeat, deleted a neighbor */
+    }
+  }
+  if (qh_setsize(qh, facet->neighbors) < qh->hull_dim) {
+    zinc_(Zdropdegen);
+    qh_appendmergeset(qh, facet, facet, MRGdegen, 0.0, qh_ANGLEnone);
+    trace2((qh, qh->ferr, 2024, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
+  }
+} /* maydropneighbor */
+
+
+/*---------------------------------
+
+  qh_merge_degenredundant(qh)
+    merge all degenerate and redundant facets
+    qh.degen_mergeset contains merges from  qh_test_degen_neighbors, qh_test_redundant_neighbors, and qh_degen_redundant_facet
+
+  returns:
+    number of merges performed
+    resets facet->degenerate/redundant
+    if deleted (visible) facet has no neighbors
+      sets ->f.replace to NULL
+
+  notes:
+    redundant merges happen before degenerate ones
+    merging and renaming vertices can result in degen/redundant facets
+    check for coplanar and convex neighbors afterwards
+
+  design:
+    for each merge on qh.degen_mergeset
+      if redundant merge
+        if non-redundant facet merged into redundant facet
+          recheck facet for redundancy
+        else
+          merge redundant facet into other facet
+*/
+int qh_merge_degenredundant(qhT *qh) {
+  int size;
+  mergeT *merge;
+  facetT *bestneighbor, *facet1, *facet2, *facet3;
+  realT dist, mindist, maxdist;
+  vertexT *vertex, **vertexp;
+  int nummerges= 0;
+  mergeType mergetype;
+  setT *mergedfacets;
+
+  trace2((qh, qh->ferr, 2095, "qh_merge_degenredundant: merge %d degenerate, redundant, and mirror facets\n",
+    qh_setsize(qh, qh->degen_mergeset)));
+  mergedfacets= qh_settemp(qh, qh->TEMPsize);
+  while ((merge= (mergeT *)qh_setdellast(qh->degen_mergeset))) {
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    mergetype= merge->mergetype;
+    qh_memfree(qh, merge, (int)sizeof(mergeT)); /* 'merge' is invalidated */
+    if (facet1->visible)
+      continue;
+    facet1->degenerate= False;
+    facet1->redundant= False;
+    if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+      qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+    if (mergetype == MRGredundant) {
+      zinc_(Zredundant);
+      facet3= qh_getreplacement(qh, facet2); /* the same facet if !facet2.visible */
+      if (!facet3) {
+          qh_fprintf(qh, qh->ferr, 6097, "qhull internal error (qh_merge_degenredunant): f%d is redundant but visible f%d has no replacement\n",
+               facet1->id, getid_(facet2));
+          qh_errexit2(qh, qh_ERRqhull, facet1, facet2);
+      }
+      qh_setunique(qh, &mergedfacets, facet3);
+      if (facet1 == facet3) {
+        continue;
+      }
+      trace2((qh, qh->ferr, 2025, "qh_merge_degenredundant: merge redundant f%d into f%d (arg f%d)\n",
+            facet1->id, facet3->id, facet2->id));
+      qh_mergefacet(qh, facet1, facet3, mergetype, NULL, NULL, !qh_MERGEapex);
+      /* merge distance is already accounted for */
+      nummerges++;
+    }else {  /* mergetype == MRGdegen or MRGmirror, other merges may have fixed */
+      if (!(size= qh_setsize(qh, facet1->neighbors))) {
+        zinc_(Zdelfacetdup);
+        trace2((qh, qh->ferr, 2026, "qh_merge_degenredundant: facet f%d has no neighbors.  Deleted\n", facet1->id));
+        qh_willdelete(qh, facet1, NULL);
+        FOREACHvertex_(facet1->vertices) {
+          qh_setdel(vertex->neighbors, facet1);
+          if (!SETfirst_(vertex->neighbors)) {
+            zinc_(Zdegenvertex);
+            trace2((qh, qh->ferr, 2027, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
+                 vertex->id, facet1->id));
+            vertex->deleted= True;
+            qh_setappend(qh, &qh->del_vertices, vertex);
+          }
+        }
+        nummerges++;
+      }else if (size < qh->hull_dim) {
+        bestneighbor= qh_findbestneighbor(qh, facet1, &dist, &mindist, &maxdist);
+        trace2((qh, qh->ferr, 2028, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
+              facet1->id, size, bestneighbor->id, dist));
+        qh_mergefacet(qh, facet1, bestneighbor, mergetype, &mindist, &maxdist, !qh_MERGEapex);
+        nummerges++;
+        if (qh->PRINTstatistics) {
+          zinc_(Zdegen);
+          wadd_(Wdegentot, dist);
+          wmax_(Wdegenmax, dist);
+        }
+      } /* else, another merge fixed the degeneracy and redundancy tested */
+    }
+  }
+  qh_settempfree(qh, &mergedfacets);
+  return nummerges;
+} /* merge_degenredundant */
+
+/*---------------------------------
+
+  qh_merge_nonconvex(qh, facet1, facet2, mergetype )
+    remove non-convex ridge between facet1 into facet2
+    mergetype gives why the facet's are non-convex
+
+  returns:
+    merges one of the facets into the best neighbor
+
+  notes:
+    mergetype is MRGcoplanar..MRGconvex
+
+  design:
+    if one of the facets is a new facet
+      prefer merging new facet into old facet
+    find best neighbors for both facets
+    merge the nearest facet into its best neighbor
+    update the statistics
+*/
+void qh_merge_nonconvex(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype) {
+  facetT *bestfacet, *bestneighbor, *neighbor, *merging, *merged;
+  realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
+
+  if (mergetype < MRGcoplanar || mergetype > MRGconcavecoplanar) {
+    qh_fprintf(qh, qh->ferr, 6398, "qhull internal error (qh_merge_nonconvex): expecting mergetype MRGcoplanar..MRGconcavecoplanar.  Got merge f%d and f%d type %d\n",
+      facet1->id, facet2->id, mergetype);
+    qh_errexit2(qh, qh_ERRqhull, facet1, facet2);
+  }
+  if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+    qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+  trace3((qh, qh->ferr, 3003, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
+      zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
+  /* concave or coplanar */
+  if (!facet1->newfacet) {
+    bestfacet= facet2;   /* avoid merging old facet if new is ok */
+    facet2= facet1;
+    facet1= bestfacet;
+  }else
+    bestfacet= facet1;
+  bestneighbor= qh_findbestneighbor(qh, bestfacet, &dist, &mindist, &maxdist);
+  neighbor= qh_findbestneighbor(qh, facet2, &dist2, &mindist2, &maxdist2);
+  if (dist < dist2) {
+    merging= bestfacet;
+    merged= bestneighbor;
+  }else if (qh->AVOIDold && !facet2->newfacet
+  && ((mindist >= -qh->MAXcoplanar && maxdist <= qh->max_outside)
+       || dist * 1.5 < dist2)) {
+    zinc_(Zavoidold);
+    wadd_(Wavoidoldtot, dist);
+    wmax_(Wavoidoldmax, dist);
+    trace2((qh, qh->ferr, 2029, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g.  Use f%d dist %2.2g instead\n",
+           facet2->id, dist2, facet1->id, dist2));
+    merging= bestfacet;
+    merged= bestneighbor;
+  }else {
+    merging= facet2;
+    merged= neighbor;
+    dist= dist2;
+    mindist= mindist2;
+    maxdist= maxdist2;
+  }
+  qh_mergefacet(qh, merging, merged, mergetype, &mindist, &maxdist, !qh_MERGEapex);
+  /* caller merges qh_degenredundant */
+  if (qh->PRINTstatistics) {
+    if (mergetype == MRGanglecoplanar) {
+      zinc_(Zacoplanar);
+      wadd_(Wacoplanartot, dist);
+      wmax_(Wacoplanarmax, dist);
+    }else if (mergetype == MRGconcave) {
+      zinc_(Zconcave);
+      wadd_(Wconcavetot, dist);
+      wmax_(Wconcavemax, dist);
+    }else if (mergetype == MRGconcavecoplanar) {
+      zinc_(Zconcavecoplanar);
+      wadd_(Wconcavecoplanartot, dist);
+      wmax_(Wconcavecoplanarmax, dist);
+    }else { /* MRGcoplanar */
+      zinc_(Zcoplanar);
+      wadd_(Wcoplanartot, dist);
+      wmax_(Wcoplanarmax, dist);
+    }
+  }
+} /* merge_nonconvex */
+
+/*---------------------------------
+
+  qh_merge_pinchedvertices(qh, apex )
+    merge pinched vertices in qh.vertex_mergeset to avoid qh_forcedmerges of dupridges
+
+  notes:
+    only called by qh_all_vertexmerges
+    hull_dim >= 3
+
+  design:
+    make vertex neighbors if necessary
+    for each pinched vertex
+      determine the ridges for the pinched vertex (make ridges as needed)
+      merge the pinched vertex into the horizon vertex
+      merge the degenerate and redundant facets that result
+    check and resolve new dupridges
+*/
+void qh_merge_pinchedvertices(qhT *qh, int apexpointid /* qh.newfacet_list */) {
+  mergeT *merge, *mergeA, **mergeAp;
+  vertexT *vertex, *vertex2;
+  realT dist;
+  boolT firstmerge= True;
+
+  qh_vertexneighbors(qh);
+  if (qh->visible_list || qh->newfacet_list || qh->newvertex_list) {
+    qh_fprintf(qh, qh->ferr, 6402, "qhull internal error (qh_merge_pinchedvertices): qh.visible_list (f%d), newfacet_list (f%d), or newvertex_list (v%d) not empty\n",
+      getid_(qh->visible_list), getid_(qh->newfacet_list), getid_(qh->newvertex_list));
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh->visible_list= qh->newfacet_list= qh->facet_tail;
+  qh->newvertex_list= qh->vertex_tail;
+  qh->isRenameVertex= True; /* disable duplicate ridge vertices check in qh_checkfacet */
+  while ((merge= qh_next_vertexmerge(qh /* qh.vertex_mergeset */))) { /* only one at a time from qh_getpinchedmerges */
+    if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+      qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+    if (merge->mergetype == MRGsubridge) {
+      zzinc_(Zpinchedvertex);
+      trace1((qh, qh->ferr, 1050, "qh_merge_pinchedvertices: merge one of %d pinched vertices before adding apex p%d.  Try to resolve duplicate ridges in newfacets\n",
+        qh_setsize(qh, qh->vertex_mergeset)+1, apexpointid));
+      qh_remove_mergetype(qh, qh->vertex_mergeset, MRGsubridge);
+    }else {
+      zzinc_(Zpinchduplicate);
+      if (firstmerge)
+        trace1((qh, qh->ferr, 1056, "qh_merge_pinchedvertices: merge %d pinched vertices from dupridges in merged facets, apex p%d\n",
+           qh_setsize(qh, qh->vertex_mergeset)+1, apexpointid));
+      firstmerge= False;
+    }
+    vertex= merge->vertex1;
+    vertex2= merge->vertex2;
+    dist= merge->distance;
+    qh_memfree(qh, merge, (int)sizeof(mergeT)); /* merge is invalidated */
+    qh_rename_adjacentvertex(qh, vertex, vertex2, dist);
+#ifndef qh_NOtrace
+    if (qh->IStracing >= 2) {
+      FOREACHmergeA_(qh->degen_mergeset) {
+        if (mergeA->mergetype== MRGdegen) {
+          qh_fprintf(qh, qh->ferr, 2072, "qh_merge_pinchedvertices: merge degenerate f%d into an adjacent facet\n", mergeA->facet1->id);
+        }else {
+          qh_fprintf(qh, qh->ferr, 2084, "qh_merge_pinchedvertices: merge f%d into f%d mergeType %d\n", mergeA->facet1->id, mergeA->facet2->id, mergeA->mergetype);
+        }
+      }
+    }
+#endif
+    qh_merge_degenredundant(qh); /* simplicial facets with both old and new vertices */
+  }
+  qh->isRenameVertex= False;
+}/* merge_pinchedvertices */
+
+/*---------------------------------
+
+  qh_merge_twisted(qh, facet1, facet2 )
+    remove twisted ridge between facet1 into facet2 or report error
+
+  returns:
+    merges one of the facets into the best neighbor
+
+  notes:
+    a twisted ridge has opposite vertices that are convex and concave
+
+  design:
+    find best neighbors for both facets
+    error if wide merge
+    merge the nearest facet into its best neighbor
+    update statistics
+*/
+void qh_merge_twisted(qhT *qh, facetT *facet1, facetT *facet2) {
+  facetT *neighbor2, *neighbor, *merging, *merged;
+  vertexT *bestvertex, *bestpinched;
+  realT dist, dist2, mindist, mindist2, maxdist, maxdist2, mintwisted, bestdist;
+
+  if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+    qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+  trace3((qh, qh->ferr, 3050, "qh_merge_twisted: merge #%d for twisted f%d and f%d\n",
+      zzval_(Ztotmerge) + 1, facet1->id, facet2->id));
+  /* twisted */
+  neighbor= qh_findbestneighbor(qh, facet1, &dist, &mindist, &maxdist);
+  neighbor2= qh_findbestneighbor(qh, facet2, &dist2, &mindist2, &maxdist2);
+  mintwisted= qh_RATIOtwisted * qh->ONEmerge;
+  maximize_(mintwisted, facet1->maxoutside);
+  maximize_(mintwisted, facet2->maxoutside);
+  if (dist > mintwisted && dist2 > mintwisted) {
+    bestdist= qh_vertex_bestdist2(qh, facet1->vertices, &bestvertex, &bestpinched);
+    if (bestdist > mintwisted) {
+      qh_fprintf(qh, qh->ferr, 6417, "qhull precision error (qh_merge_twisted): twisted facet f%d does not contain pinched vertices.  Too wide to merge into neighbor.  mindist %2.2g maxdist %2.2g vertexdist %2.2g maxpinched %2.2g neighbor f%d mindist %2.2g maxdist %2.2g\n",
+        facet1->id, mindist, maxdist, bestdist, mintwisted, facet2->id, mindist2, maxdist2);
+    }else {
+      qh_fprintf(qh, qh->ferr, 6418, "qhull precision error (qh_merge_twisted): twisted facet f%d with pinched vertices.  Could merge vertices, but too wide to merge into neighbor.   mindist %2.2g maxdist %2.2g vertexdist %2.2g neighbor f%d mindist %2.2g maxdist %2.2g\n",
+        facet1->id, mindist, maxdist, bestdist, facet2->id, mindist2, maxdist2);
+    }
+    qh_errexit2(qh, qh_ERRwide, facet1, facet2);
+  }
+  if (dist < dist2) {
+    merging= facet1;
+    merged= neighbor;
+  }else {
+    /* ignores qh.AVOIDold ('Q4') */
+    merging= facet2;
+    merged= neighbor2;
+    dist= dist2;
+    mindist= mindist2;
+    maxdist= maxdist2;
+  }
+  qh_mergefacet(qh, merging, merged, MRGtwisted, &mindist, &maxdist, !qh_MERGEapex);
+  /* caller merges qh_degenredundant */
+  zinc_(Ztwisted);
+  wadd_(Wtwistedtot, dist);
+  wmax_(Wtwistedmax, dist);
+} /* merge_twisted */
+
+/*---------------------------------
+
+  qh_mergecycle(qh, samecycle, newfacet )
+    merge a cycle of facets starting at samecycle into a newfacet
+    newfacet is a horizon facet with ->normal
+    samecycle facets are simplicial from an apex
+
+  returns:
+    initializes vertex neighbors on first merge
+    samecycle deleted (placed on qh.visible_list)
+    newfacet at end of qh.facet_list
+    deleted vertices on qh.del_vertices
+
+  notes:
+    only called by qh_mergecycle_all for multiple, same cycle facets
+    see qh_mergefacet
+
+  design:
+    make vertex neighbors if necessary
+    make ridges for newfacet
+    merge neighbor sets of samecycle into newfacet
+    merge ridges of samecycle into newfacet
+    merge vertex neighbors of samecycle into newfacet
+    make apex of samecycle the apex of newfacet
+    if newfacet wasn't a new facet
+      add its vertices to qh.newvertex_list
+    delete samecycle facets a make newfacet a newfacet
+*/
+void qh_mergecycle(qhT *qh, facetT *samecycle, facetT *newfacet) {
+  int traceonce= False, tracerestore= 0;
+  vertexT *apex;
+#ifndef qh_NOtrace
+  facetT *same;
+#endif
+
+  zzinc_(Ztotmerge);
+  if (qh->REPORTfreq2 && qh->POSTmerging) {
+    if (zzval_(Ztotmerge) > qh->mergereport + qh->REPORTfreq2)
+      qh_tracemerging(qh);
+  }
+#ifndef qh_NOtrace
+  if (qh->TRACEmerge == zzval_(Ztotmerge))
+    qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+  trace2((qh, qh->ferr, 2030, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n",
+        zzval_(Ztotmerge), samecycle->id, newfacet->id));
+  if (newfacet == qh->tracefacet) {
+    tracerestore= qh->IStracing;
+    qh->IStracing= 4;
+    qh_fprintf(qh, qh->ferr, 8068, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
+               zzval_(Ztotmerge), samecycle->id, newfacet->id,  qh->furthest_id);
+    traceonce= True;
+  }
+  if (qh->IStracing >=4) {
+    qh_fprintf(qh, qh->ferr, 8069, "  same cycle:");
+    FORALLsame_cycle_(samecycle)
+      qh_fprintf(qh, qh->ferr, 8070, " f%d", same->id);
+    qh_fprintf(qh, qh->ferr, 8071, "\n");
+  }
+  if (qh->IStracing >=4)
+    qh_errprint(qh, "MERGING CYCLE", samecycle, newfacet, NULL, NULL);
+#endif /* !qh_NOtrace */
+  if (newfacet->tricoplanar) {
+    if (!qh->TRInormals) {
+      qh_fprintf(qh, qh->ferr, 6224, "qhull internal error (qh_mergecycle): does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit(qh, qh_ERRqhull, newfacet, NULL);
+    }
+    newfacet->tricoplanar= False;
+    newfacet->keepcentrum= False;
+  }
+  if (qh->CHECKfrequently)
+    qh_checkdelridge(qh);
+  if (!qh->VERTEXneighbors)
+    qh_vertexneighbors(qh);
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  qh_makeridges(qh, newfacet);
+  qh_mergecycle_neighbors(qh, samecycle, newfacet);
+  qh_mergecycle_ridges(qh, samecycle, newfacet);
+  qh_mergecycle_vneighbors(qh, samecycle, newfacet);
+  if (SETfirstt_(newfacet->vertices, vertexT) != apex)
+    qh_setaddnth(qh, &newfacet->vertices, 0, apex);  /* apex has last id */
+  if (!newfacet->newfacet)
+    qh_newvertices(qh, newfacet->vertices);
+  qh_mergecycle_facets(qh, samecycle, newfacet);
+  qh_tracemerge(qh, samecycle, newfacet, MRGcoplanarhorizon);
+  /* check for degen_redundant_neighbors after qh_forcedmerges() */
+  if (traceonce) {
+    qh_fprintf(qh, qh->ferr, 8072, "qh_mergecycle: end of trace facet\n");
+    qh->IStracing= tracerestore;
+  }
+} /* mergecycle */
+
+/*---------------------------------
+
+  qh_mergecycle_all(qh, facetlist, wasmerge )
+    merge all samecycles of coplanar facets into horizon
+    don't merge facets with ->mergeridge (these already have ->normal)
+    all facets are simplicial from apex
+    all facet->cycledone == False
+
+  returns:
+    all newfacets merged into coplanar horizon facets
+    deleted vertices on  qh.del_vertices
+    sets wasmerge if any merge
+
+  notes:
+    called by qh_premerge
+    calls qh_mergecycle for multiple, same cycle facets
+
+  design:
+    for each facet on facetlist
+      skip facets with dupridges and normals
+      check that facet is in a samecycle (->mergehorizon)
+      if facet only member of samecycle
+        sets vertex->delridge for all vertices except apex
+        merge facet into horizon
+      else
+        mark all facets in samecycle
+        remove facets with dupridges from samecycle
+        merge samecycle into horizon (deletes facets from facetlist)
+*/
+void qh_mergecycle_all(qhT *qh, facetT *facetlist, boolT *wasmerge) {
+  facetT *facet, *same, *prev, *horizon, *newfacet;
+  facetT *samecycle= NULL, *nextfacet, *nextsame;
+  vertexT *apex, *vertex, **vertexp;
+  int cycles=0, total=0, facets, nummerge, numdegen= 0;
+
+  trace2((qh, qh->ferr, 2031, "qh_mergecycle_all: merge new facets into coplanar horizon facets.  Bulk merge a cycle of facets with the same horizon facet\n"));
+  for (facet=facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
+    if (facet->normal)
+      continue;
+    if (!facet->mergehorizon) {
+      qh_fprintf(qh, qh->ferr, 6225, "qhull internal error (qh_mergecycle_all): f%d without normal\n", facet->id);
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    horizon= SETfirstt_(facet->neighbors, facetT);
+    if (facet->f.samecycle == facet) {
+      if (qh->TRACEmerge-1 == zzval_(Ztotmerge))
+        qh->qhmem.IStracing= qh->IStracing= qh->TRACElevel;
+      zinc_(Zonehorizon);
+      /* merge distance done in qh_findhorizon */
+      apex= SETfirstt_(facet->vertices, vertexT);
+      FOREACHvertex_(facet->vertices) {
+        if (vertex != apex)
+          vertex->delridge= True;
+      }
+      horizon->f.newcycle= NULL;
+      qh_mergefacet(qh, facet, horizon, MRGcoplanarhorizon, NULL, NULL, qh_MERGEapex);
+    }else {
+      samecycle= facet;
+      facets= 0;
+      prev= facet;
+      for (same= facet->f.samecycle; same;  /* FORALLsame_cycle_(facet) */
+           same= (same == facet ? NULL :nextsame)) { /* ends at facet */
+        nextsame= same->f.samecycle;
+        if (same->cycledone || same->visible)
+          qh_infiniteloop(qh, same);
+        same->cycledone= True;
+        if (same->normal) {
+          prev->f.samecycle= same->f.samecycle; /* unlink ->mergeridge */
+          same->f.samecycle= NULL;
+        }else {
+          prev= same;
+          facets++;
+        }
+      }
+      while (nextfacet && nextfacet->cycledone)  /* will delete samecycle */
+        nextfacet= nextfacet->next;
+      horizon->f.newcycle= NULL;
+      qh_mergecycle(qh, samecycle, horizon);
+      nummerge= horizon->nummerge + facets;
+      if (nummerge > qh_MAXnummerge)
+        horizon->nummerge= qh_MAXnummerge;
+      else
+        horizon->nummerge= (short unsigned int)nummerge; /* limited to 9 bits by qh_MAXnummerge, -Wconversion */
+      zzinc_(Zcyclehorizon);
+      total += facets;
+      zzadd_(Zcyclefacettot, facets);
+      zmax_(Zcyclefacetmax, facets);
+    }
+    cycles++;
+  }
+  if (cycles) {
+    FORALLnew_facets {
+      /* qh_maybe_duplicateridges postponed since qh_mergecycle_ridges deletes ridges without calling qh_delridge_merge */
+      if (newfacet->coplanarhorizon) {
+        qh_test_redundant_neighbors(qh, newfacet);
+        qh_maybe_duplicateridges(qh, newfacet);
+        newfacet->coplanarhorizon= False;
+      }
+    }
+    numdegen += qh_merge_degenredundant(qh);
+    *wasmerge= True;
+    trace1((qh, qh->ferr, 1013, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons and %d degenredundant facets\n",
+      cycles, numdegen));
+  }
+} /* mergecycle_all */
+
+/*---------------------------------
+
+  qh_mergecycle_facets(qh, samecycle, newfacet )
+    finish merge of samecycle into newfacet
+
+  returns:
+    samecycle prepended to visible_list for later deletion and partitioning
+      each facet->f.replace == newfacet
+
+    newfacet moved to end of qh.facet_list
+      makes newfacet a newfacet (get's facet1->id if it was old)
+      sets newfacet->newmerge
+      clears newfacet->center (unless merging into a large facet)
+      clears newfacet->tested and ridge->tested for facet1
+
+    adds neighboring facets to facet_mergeset if redundant or degenerate
+
+  design:
+    make newfacet a new facet and set its flags
+    move samecycle facets to qh.visible_list for later deletion
+    unless newfacet is large
+      remove its centrum
+*/
+void qh_mergecycle_facets(qhT *qh, facetT *samecycle, facetT *newfacet) {
+  facetT *same, *next;
+
+  trace4((qh, qh->ferr, 4030, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));
+  qh_removefacet(qh, newfacet);  /* append as a newfacet to end of qh->facet_list */
+  qh_appendfacet(qh, newfacet);
+  newfacet->newfacet= True;
+  newfacet->simplicial= False;
+  newfacet->newmerge= True;
+
+  for (same= samecycle->f.samecycle; same; same= (same == samecycle ?  NULL : next)) {
+    next= same->f.samecycle;  /* reused by willdelete */
+    qh_willdelete(qh, same, newfacet);
+  }
+  if (newfacet->center
+      && qh_setsize(qh, newfacet->vertices) <= qh->hull_dim + qh_MAXnewcentrum) {
+    qh_memfree(qh, newfacet->center, qh->normal_size);
+    newfacet->center= NULL;
+  }
+  trace3((qh, qh->ferr, 3004, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n",
+             samecycle->id, newfacet->id));
+} /* mergecycle_facets */
+
+/*---------------------------------
+
+  qh_mergecycle_neighbors(qh, samecycle, newfacet )
+    add neighbors for samecycle facets to newfacet
+
+  returns:
+    newfacet with updated neighbors and vice-versa
+    newfacet has ridges
+    all neighbors of newfacet marked with qh.visit_id
+    samecycle facets marked with qh.visit_id-1
+    ridges updated for simplicial neighbors of samecycle with a ridge
+
+  notes:
+    assumes newfacet not in samecycle
+    usually, samecycle facets are new, simplicial facets without internal ridges
+      not so if horizon facet is coplanar to two different samecycles
+
+  see:
+    qh_mergeneighbors()
+
+  design:
+    check samecycle
+    delete neighbors from newfacet that are also in samecycle
+    for each neighbor of a facet in samecycle
+      if neighbor is simplicial
+        if first visit
+          move the neighbor relation to newfacet
+          update facet links for its ridges
+        else
+          make ridges for neighbor
+          remove samecycle reference
+      else
+        update neighbor sets
+*/
+void qh_mergecycle_neighbors(qhT *qh, facetT *samecycle, facetT *newfacet) {
+  facetT *same, *neighbor, **neighborp;
+  int delneighbors= 0, newneighbors= 0;
+  unsigned int samevisitid;
+  ridgeT *ridge, **ridgep;
+
+  samevisitid= ++qh->visit_id;
+  FORALLsame_cycle_(samecycle) {
+    if (same->visitid == samevisitid || same->visible)
+      qh_infiniteloop(qh, samecycle);
+    same->visitid= samevisitid;
+  }
+  newfacet->visitid= ++qh->visit_id;
+  trace4((qh, qh->ferr, 4031, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));
+  FOREACHneighbor_(newfacet) {
+    if (neighbor->visitid == samevisitid) {
+      SETref_(neighbor)= NULL;  /* samecycle neighbors deleted */
+      delneighbors++;
+    }else
+      neighbor->visitid= qh->visit_id;
+  }
+  qh_setcompact(qh, newfacet->neighbors);
+
+  trace4((qh, qh->ferr, 4032, "qh_mergecycle_neighbors: update neighbors\n"));
+  FORALLsame_cycle_(samecycle) {
+    FOREACHneighbor_(same) {
+      if (neighbor->visitid == samevisitid)
+        continue;
+      if (neighbor->simplicial) {
+        if (neighbor->visitid != qh->visit_id) {
+          qh_setappend(qh, &newfacet->neighbors, neighbor);
+          qh_setreplace(qh, neighbor->neighbors, same, newfacet);
+          newneighbors++;
+          neighbor->visitid= qh->visit_id;
+          FOREACHridge_(neighbor->ridges) { /* update ridge in case of qh_makeridges */
+            if (ridge->top == same) {
+              ridge->top= newfacet;
+              break;
+            }else if (ridge->bottom == same) {
+              ridge->bottom= newfacet;
+              break;
+            }
+          }
+        }else {
+          qh_makeridges(qh, neighbor);
+          qh_setdel(neighbor->neighbors, same);
+          /* same can't be horizon facet for neighbor */
+        }
+      }else { /* non-simplicial neighbor */
+        qh_setdel(neighbor->neighbors, same);
+        if (neighbor->visitid != qh->visit_id) {
+          qh_setappend(qh, &neighbor->neighbors, newfacet);
+          qh_setappend(qh, &newfacet->neighbors, neighbor);
+          neighbor->visitid= qh->visit_id;
+          newneighbors++;
+        }
+      }
+    }
+  }
+  trace2((qh, qh->ferr, 2032, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n",
+             delneighbors, newneighbors));
+} /* mergecycle_neighbors */
+
+/*---------------------------------
+
+  qh_mergecycle_ridges(qh, samecycle, newfacet )
+    add ridges/neighbors for facets in samecycle to newfacet
+    all new/old neighbors of newfacet marked with qh.visit_id
+    facets in samecycle marked with qh.visit_id-1
+    newfacet marked with qh.visit_id
+
+  returns:
+    newfacet has merged ridges
+
+  notes:
+    ridge already updated for simplicial neighbors of samecycle with a ridge
+    qh_checkdelridge called by qh_mergecycle
+
+  see:
+    qh_mergeridges()
+    qh_makeridges()
+
+  design:
+    remove ridges between newfacet and samecycle
+    for each facet in samecycle
+      for each ridge in facet
+        update facet pointers in ridge
+        skip ridges processed in qh_mergecycle_neighors
+        free ridges between newfacet and samecycle
+        free ridges between facets of samecycle (on 2nd visit)
+        append remaining ridges to newfacet
+      if simplicial facet
+        for each neighbor of facet
+          if simplicial facet
+          and not samecycle facet or newfacet
+            make ridge between neighbor and newfacet
+*/
+void qh_mergecycle_ridges(qhT *qh, facetT *samecycle, facetT *newfacet) {
+  facetT *same, *neighbor= NULL;
+  int numold=0, numnew=0;
+  int neighbor_i, neighbor_n;
+  unsigned int samevisitid;
+  ridgeT *ridge, **ridgep;
+  boolT toporient;
+  void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
+
+  trace4((qh, qh->ferr, 4033, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));
+  samevisitid= qh->visit_id -1;
+  FOREACHridge_(newfacet->ridges) {
+    neighbor= otherfacet_(ridge, newfacet);
+    if (neighbor->visitid == samevisitid)
+      SETref_(ridge)= NULL; /* ridge free'd below */
+  }
+  qh_setcompact(qh, newfacet->ridges);
+
+  trace4((qh, qh->ferr, 4034, "qh_mergecycle_ridges: add ridges to newfacet\n"));
+  FORALLsame_cycle_(samecycle) {
+    FOREACHridge_(same->ridges) {
+      if (ridge->top == same) {
+        ridge->top= newfacet;
+        neighbor= ridge->bottom;
+      }else if (ridge->bottom == same) {
+        ridge->bottom= newfacet;
+        neighbor= ridge->top;
+      }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
+        qh_setappend(qh, &newfacet->ridges, ridge);
+        numold++;  /* already set by qh_mergecycle_neighbors */
+        continue;
+      }else {
+        qh_fprintf(qh, qh->ferr, 6098, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
+        qh_errexit(qh, qh_ERRqhull, NULL, ridge);
+      }
+      if (neighbor == newfacet) {
+        if (qh->traceridge == ridge)
+          qh->traceridge= NULL;
+        qh_setfree(qh, &(ridge->vertices));
+        qh_memfree_(qh, ridge, (int)sizeof(ridgeT), freelistp);
+        numold++;
+      }else if (neighbor->visitid == samevisitid) {
+        qh_setdel(neighbor->ridges, ridge);
+        if (qh->traceridge == ridge)
+          qh->traceridge= NULL;
+        qh_setfree(qh, &(ridge->vertices));
+        qh_memfree_(qh, ridge, (int)sizeof(ridgeT), freelistp);
+        numold++;
+      }else {
+        qh_setappend(qh, &newfacet->ridges, ridge);
+        numold++;
+      }
+    }
+    if (same->ridges)
+      qh_settruncate(qh, same->ridges, 0);
+    if (!same->simplicial)
+      continue;
+    FOREACHneighbor_i_(qh, same) {       /* note: !newfact->simplicial */
+      if (neighbor->visitid != samevisitid && neighbor->simplicial) {
+        ridge= qh_newridge(qh);
+        ridge->vertices= qh_setnew_delnthsorted(qh, same->vertices, qh->hull_dim,
+                                                          neighbor_i, 0);
+        toporient= (boolT)(same->toporient ^ (neighbor_i & 0x1));
+        if (toporient) {
+          ridge->top= newfacet;
+          ridge->bottom= neighbor;
+          ridge->simplicialbot= True;
+        }else {
+          ridge->top= neighbor;
+          ridge->bottom= newfacet;
+          ridge->simplicialtop= True;
+        }
+        qh_setappend(qh, &(newfacet->ridges), ridge);
+        qh_setappend(qh, &(neighbor->ridges), ridge);
+        if (qh->ridge_id == qh->traceridge_id)
+          qh->traceridge= ridge;
+        numnew++;
+      }
+    }
+  }
+
+  trace2((qh, qh->ferr, 2033, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n",
+             numold, numnew));
+} /* mergecycle_ridges */
+
+/*---------------------------------
+
+  qh_mergecycle_vneighbors(qh, samecycle, newfacet )
+    create vertex neighbors for newfacet from vertices of facets in samecycle
+    samecycle marked with visitid == qh.visit_id - 1
+
+  returns:
+    newfacet vertices with updated neighbors
+    marks newfacet with qh.visit_id-1
+    deletes vertices that are merged away
+    sets delridge on all vertices (faster here than in mergecycle_ridges)
+
+  see:
+    qh_mergevertex_neighbors()
+
+  design:
+    for each vertex of samecycle facet
+      set vertex->delridge
+      delete samecycle facets from vertex neighbors
+      append newfacet to vertex neighbors
+      if vertex only in newfacet
+        delete it from newfacet
+        add it to qh.del_vertices for later deletion
+*/
+void qh_mergecycle_vneighbors(qhT *qh, facetT *samecycle, facetT *newfacet) {
+  facetT *neighbor, **neighborp;
+  unsigned int mergeid;
+  vertexT *vertex, **vertexp, *apex;
+  setT *vertices;
+
+  trace4((qh, qh->ferr, 4035, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));
+  mergeid= qh->visit_id - 1;
+  newfacet->visitid= mergeid;
+  vertices= qh_basevertices(qh, samecycle); /* temp */
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  qh_setappend(qh, &vertices, apex);
+  FOREACHvertex_(vertices) {
+    vertex->delridge= True;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->visitid == mergeid)
+        SETref_(neighbor)= NULL;
+    }
+    qh_setcompact(qh, vertex->neighbors);
+    qh_setappend(qh, &vertex->neighbors, newfacet);
+    if (!SETsecond_(vertex->neighbors)) {
+      zinc_(Zcyclevertex);
+      trace2((qh, qh->ferr, 2034, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
+        vertex->id, samecycle->id, newfacet->id));
+      qh_setdelsorted(newfacet->vertices, vertex);
+      vertex->deleted= True;
+      qh_setappend(qh, &qh->del_vertices, vertex);
+    }
+  }
+  qh_settempfree(qh, &vertices);
+  trace3((qh, qh->ferr, 3005, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n",
+             samecycle->id, newfacet->id));
+} /* mergecycle_vneighbors */
+
+/*---------------------------------
+
+  qh_mergefacet(qh, facet1, facet2, mergetype, mindist, maxdist, mergeapex )
+    merges facet1 into facet2
+    mergeapex==qh_MERGEapex if merging new facet into coplanar horizon (optimizes qh_mergesimplex)
+
+  returns:
+    qh.max_outside and qh.min_vertex updated
+    initializes vertex neighbors on first merge
+
+  note:
+    mergetype only used for logging and error reporting
+
+  returns:
+    facet2 contains facet1's vertices, neighbors, and ridges
+      facet2 moved to end of qh.facet_list
+      makes facet2 a newfacet
+      sets facet2->newmerge set
+      clears facet2->center (unless merging into a large facet)
+      clears facet2->tested and ridge->tested for facet1
+
+    facet1 prepended to visible_list for later deletion and partitioning
+      facet1->f.replace == facet2
+
+    adds neighboring facets to facet_mergeset if redundant or degenerate
+
+  notes:
+    when done, tests facet1 and facet2 for degenerate or redundant neighbors and dupridges
+    mindist/maxdist may be NULL (only if both NULL)
+    traces merge if fmax_(maxdist,-mindist) > TRACEdist
+
+  see:
+    qh_mergecycle()
+
+  design:
+    trace merge and check for degenerate simplex
+    make ridges for both facets
+    update qh.max_outside, qh.max_vertex, qh.min_vertex
+    update facet2->maxoutside and keepcentrum
+    update facet2->nummerge
+    update tested flags for facet2
+    if facet1 is simplicial
+      merge facet1 into facet2
+    else
+      merge facet1's neighbors into facet2
+      merge facet1's ridges into facet2
+      merge facet1's vertices into facet2
+      merge facet1's vertex neighbors into facet2
+      add facet2's vertices to qh.new_vertexlist
+    move facet2 to end of qh.newfacet_list
+    unless MRGcoplanarhorizon
+      test facet2 for redundant neighbors
+      test facet1 for degenerate neighbors
+      test for redundant facet2
+      maybe test for duplicate ridges ('Q17')
+    move facet1 to qh.visible_list for later deletion
+*/
+void qh_mergefacet(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype, realT *mindist, realT *maxdist, boolT mergeapex) {
+  boolT traceonce= False;
+  vertexT *vertex, **vertexp;
+  realT mintwisted, vertexdist;
+  realT onemerge;
+  int tracerestore=0, nummerge;
+  const char *mergename;
+
+  if(mergetype > 0 && mergetype < sizeof(mergetypes)/sizeof(char *))
+    mergename= mergetypes[mergetype];
+  else
+    mergename= mergetypes[MRGnone];
+  if (facet1->tricoplanar || facet2->tricoplanar) {
+    if (!qh->TRInormals) {
+      qh_fprintf(qh, qh->ferr, 6226, "qhull internal error (qh_mergefacet): merge f%d into f%d for mergetype %d (%s) does not work for tricoplanar facets.  Use option 'Q11'\n",
+        facet1->id, facet2->id, mergetype, mergename);
+      qh_errexit2(qh, qh_ERRqhull, facet1, facet2);
+    }
+    if (facet2->tricoplanar) {
+      facet2->tricoplanar= False;
+      facet2->keepcentrum= False;
+    }
+  }
+  zzinc_(Ztotmerge);
+  if (qh->REPORTfreq2 && qh->POSTmerging) {
+    if (zzval_(Ztotmerge) > qh->mergereport + qh->REPORTfreq2)
+      qh_tracemerging(qh);
+  }
+#ifndef qh_NOtrace
+  if (qh->build_cnt >= qh->RERUN) {
+    if (mindist && (-*mindist > qh->TRACEdist || *maxdist > qh->TRACEdist)) {
+      tracerestore= 0;
+      qh->IStracing= qh->TRACElevel;
+      traceonce= True;
+      qh_fprintf(qh, qh->ferr, 8075, "qh_mergefacet: ========= trace wide merge #%d(%2.2g) for f%d into f%d for mergetype %d (%s), last point was p%d\n",
+          zzval_(Ztotmerge), fmax_(-*mindist, *maxdist), facet1->id, facet2->id, mergetype, mergename, qh->furthest_id);
+    }else if (facet1 == qh->tracefacet || facet2 == qh->tracefacet) {
+      tracerestore= qh->IStracing;
+      qh->IStracing= 4;
+      traceonce= True;
+      qh_fprintf(qh, qh->ferr, 8076, "qh_mergefacet: ========= trace merge #%d for f%d into f%d for mergetype %d (%s), furthest is p%d\n",
+                 zzval_(Ztotmerge), facet1->id, facet2->id, mergetype, mergename, qh->furthest_id);
+    }
+  }
+  if (qh->IStracing >= 2) {
+    realT mergemin= -2;
+    realT mergemax= -2;
+
+    if (mindist) {
+      mergemin= *mindist;
+      mergemax= *maxdist;
+    }
+    qh_fprintf(qh, qh->ferr, 2081, "qh_mergefacet: #%d merge f%d into f%d for merge for mergetype %d (%s), mindist= %2.2g, maxdist= %2.2g, max_outside %2.2g\n",
+    zzval_(Ztotmerge), facet1->id, facet2->id, mergetype, mergename, mergemin, mergemax, qh->max_outside);
+  }
+#endif /* !qh_NOtrace */
+  if(!qh->ALLOWwide && mindist) {
+    mintwisted= qh_WIDEmaxoutside * qh->ONEmerge;  /* same as qh_merge_twisted and qh_check_maxout (poly2) */
+    maximize_(mintwisted, facet1->maxoutside);
+    maximize_(mintwisted, facet2->maxoutside);
+    if (*maxdist > mintwisted || -*mindist > mintwisted) {
+      vertexdist= qh_vertex_bestdist(qh, facet1->vertices);
+      onemerge= qh->ONEmerge + qh->DISTround;
+      if (vertexdist > mintwisted) {
+        qh_fprintf(qh, qh->ferr, 6347, "qhull precision error (qh_mergefacet): wide merge for facet f%d into f%d for mergetype %d (%s).  maxdist %2.2g (%.1fx) mindist %2.2g (%.1fx) vertexdist %2.2g  Allow with 'Q12' (allow-wide)\n",
+          facet1->id, facet2->id, mergetype, mergename, *maxdist, *maxdist/onemerge, *mindist, -*mindist/onemerge, vertexdist);
+      }else {
+        qh_fprintf(qh, qh->ferr, 6348, "qhull precision error (qh_mergefacet): wide merge for pinched facet f%d into f%d for mergetype %d (%s).  maxdist %2.2g (%.fx) mindist %2.2g (%.1fx) vertexdist %2.2g  Allow with 'Q12' (allow-wide)\n",
+          facet1->id, facet2->id, mergetype, mergename, *maxdist, *maxdist/onemerge, *mindist, -*mindist/onemerge, vertexdist);
+      }
+      qh_errexit2(qh, qh_ERRwide, facet1, facet2);
+    }
+  }
+  if (facet1 == facet2 || facet1->visible || facet2->visible) {
+    qh_fprintf(qh, qh->ferr, 6099, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet, mergetype %d (%s)\n",
+             facet1->id, facet2->id, mergetype, mergename);
+    qh_errexit2(qh, qh_ERRqhull, facet1, facet2);
+  }
+  if (qh->num_facets - qh->num_visible <= qh->hull_dim + 1) {
+    qh_fprintf(qh, qh->ferr, 6227, "qhull topology error: Only %d facets remain.  The input is too degenerate or the convexity constraints are too strong.\n",
+          qh->hull_dim+1);
+    if (qh->hull_dim >= 5 && !qh->MERGEexact)
+      qh_fprintf(qh, qh->ferr, 8079, "    Option 'Qx' may avoid this problem.\n");
+    qh_errexit(qh, qh_ERRtopology, NULL, NULL);
+  }
+  if (!qh->VERTEXneighbors)
+    qh_vertexneighbors(qh);
+  qh_makeridges(qh, facet1);
+  qh_makeridges(qh, facet2);
+  if (qh->IStracing >=4)
+    qh_errprint(qh, "MERGING", facet1, facet2, NULL, NULL);
+  if (mindist) {
+    maximize_(qh->max_outside, *maxdist);
+    maximize_(qh->max_vertex, *maxdist);
+#if qh_MAXoutside
+    maximize_(facet2->maxoutside, *maxdist);
+#endif
+    minimize_(qh->min_vertex, *mindist);
+    if (!facet2->keepcentrum
+    && (*maxdist > qh->WIDEfacet || *mindist < -qh->WIDEfacet)) {
+      facet2->keepcentrum= True;
+      zinc_(Zwidefacet);
+    }
+  }
+  nummerge= facet1->nummerge + facet2->nummerge + 1;
+  if (nummerge >= qh_MAXnummerge)
+    facet2->nummerge= qh_MAXnummerge;
+  else
+    facet2->nummerge= (short unsigned int)nummerge; /* limited to 9 bits by qh_MAXnummerge, -Wconversion */
+  facet2->newmerge= True;
+  facet2->dupridge= False;
+  qh_updatetested(qh, facet1, facet2);
+  if (qh->hull_dim > 2 && qh_setsize(qh, facet1->vertices) == qh->hull_dim)
+    qh_mergesimplex(qh, facet1, facet2, mergeapex);
+  else {
+    qh->vertex_visit++;
+    FOREACHvertex_(facet2->vertices)
+      vertex->visitid= qh->vertex_visit;
+    if (qh->hull_dim == 2)
+      qh_mergefacet2d(qh, facet1, facet2);
+    else {
+      qh_mergeneighbors(qh, facet1, facet2);
+      qh_mergevertices(qh, facet1->vertices, &facet2->vertices);
+    }
+    qh_mergeridges(qh, facet1, facet2);
+    qh_mergevertex_neighbors(qh, facet1, facet2);
+    if (!facet2->newfacet)
+      qh_newvertices(qh, facet2->vertices);
+  }
+  if (facet2->coplanarhorizon) {
+    zinc_(Zmergeintocoplanar);
+  }else if (!facet2->newfacet) {
+    zinc_(Zmergeintohorizon);
+  }else if (!facet1->newfacet && facet2->newfacet) {
+    zinc_(Zmergehorizon);
+  }else {
+    zinc_(Zmergenew);
+  }
+  qh_removefacet(qh, facet2);  /* append as a newfacet to end of qh->facet_list */
+  qh_appendfacet(qh, facet2);
+  facet2->newfacet= True;
+  facet2->tested= False;
+  qh_tracemerge(qh, facet1, facet2, mergetype);
+  if (traceonce) {
+    qh_fprintf(qh, qh->ferr, 8080, "qh_mergefacet: end of wide tracing\n");
+    qh->IStracing= tracerestore;
+  }
+  if (mergetype != MRGcoplanarhorizon) {
+    trace3((qh, qh->ferr, 3076, "qh_mergefacet: check f%d and f%d for redundant and degenerate neighbors\n",
+        facet1->id, facet2->id));
+    qh_test_redundant_neighbors(qh, facet2);
+    qh_test_degen_neighbors(qh, facet1);  /* after qh_test_redundant_neighbors since MRGdegen more difficult than MRGredundant
+                                             and before qh_willdelete which clears facet1.neighbors */
+    qh_degen_redundant_facet(qh, facet2); /* may occur in qh_merge_pinchedvertices, e.g., rbox 175 C3,2e-13 D4 t1545228104 | qhull d */
+    qh_maybe_duplicateridges(qh, facet2);
+  }
+  qh_willdelete(qh, facet1, facet2);
+} /* mergefacet */
+
+
+/*---------------------------------
+
+  qh_mergefacet2d(qh, facet1, facet2 )
+    in 2d, merges neighbors and vertices of facet1 into facet2
+
+  returns:
+    build ridges for neighbors if necessary
+    facet2 looks like a simplicial facet except for centrum, ridges
+      neighbors are opposite the corresponding vertex
+      maintains orientation of facet2
+
+  notes:
+    qh_mergefacet() retains non-simplicial structures
+      they are not needed in 2d, but later routines may use them
+    preserves qh.vertex_visit for qh_mergevertex_neighbors()
+
+  design:
+    get vertices and neighbors
+    determine new vertices and neighbors
+    set new vertices and neighbors and adjust orientation
+    make ridges for new neighbor if needed
+*/
+void qh_mergefacet2d(qhT *qh, facetT *facet1, facetT *facet2) {
+  vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
+  facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
+
+  vertex1A= SETfirstt_(facet1->vertices, vertexT);
+  vertex1B= SETsecondt_(facet1->vertices, vertexT);
+  vertex2A= SETfirstt_(facet2->vertices, vertexT);
+  vertex2B= SETsecondt_(facet2->vertices, vertexT);
+  neighbor1A= SETfirstt_(facet1->neighbors, facetT);
+  neighbor1B= SETsecondt_(facet1->neighbors, facetT);
+  neighbor2A= SETfirstt_(facet2->neighbors, facetT);
+  neighbor2B= SETsecondt_(facet2->neighbors, facetT);
+  if (vertex1A == vertex2A) {
+    vertexA= vertex1B;
+    vertexB= vertex2B;
+    neighborA= neighbor2A;
+    neighborB= neighbor1A;
+  }else if (vertex1A == vertex2B) {
+    vertexA= vertex1B;
+    vertexB= vertex2A;
+    neighborA= neighbor2B;
+    neighborB= neighbor1A;
+  }else if (vertex1B == vertex2A) {
+    vertexA= vertex1A;
+    vertexB= vertex2B;
+    neighborA= neighbor2A;
+    neighborB= neighbor1B;
+  }else { /* 1B == 2B */
+    vertexA= vertex1A;
+    vertexB= vertex2A;
+    neighborA= neighbor2B;
+    neighborB= neighbor1B;
+  }
+  /* vertexB always from facet2, neighborB always from facet1 */
+  if (vertexA->id > vertexB->id) {
+    SETfirst_(facet2->vertices)= vertexA;
+    SETsecond_(facet2->vertices)= vertexB;
+    if (vertexB == vertex2A)
+      facet2->toporient= !facet2->toporient;
+    SETfirst_(facet2->neighbors)= neighborA;
+    SETsecond_(facet2->neighbors)= neighborB;
+  }else {
+    SETfirst_(facet2->vertices)= vertexB;
+    SETsecond_(facet2->vertices)= vertexA;
+    if (vertexB == vertex2B)
+      facet2->toporient= !facet2->toporient;
+    SETfirst_(facet2->neighbors)= neighborB;
+    SETsecond_(facet2->neighbors)= neighborA;
+  }
+  /* qh_makeridges not needed since neighborB is not degenerate */
+  qh_setreplace(qh, neighborB->neighbors, facet1, facet2);
+  trace4((qh, qh->ferr, 4036, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
+       vertexA->id, neighborB->id, facet1->id, facet2->id));
+} /* mergefacet2d */
+
+
+/*---------------------------------
+
+  qh_mergeneighbors(qh, facet1, facet2 )
+    merges the neighbors of facet1 into facet2
+
+  notes:
+    only called by qh_mergefacet
+    qh.hull_dim >= 3
+    see qh_mergecycle_neighbors
+
+  design:
+    for each neighbor of facet1
+      if neighbor is also a neighbor of facet2
+        if neighbor is simplicial
+          make ridges for later deletion as a degenerate facet
+        update its neighbor set
+      else
+        move the neighbor relation to facet2
+    remove the neighbor relation for facet1 and facet2
+*/
+void qh_mergeneighbors(qhT *qh, facetT *facet1, facetT *facet2) {
+  facetT *neighbor, **neighborp;
+
+  trace4((qh, qh->ferr, 4037, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
+          facet1->id, facet2->id));
+  qh->visit_id++;
+  FOREACHneighbor_(facet2) {
+    neighbor->visitid= qh->visit_id;
+  }
+  FOREACHneighbor_(facet1) {
+    if (neighbor->visitid == qh->visit_id) {
+      if (neighbor->simplicial)    /* is degen, needs ridges */
+        qh_makeridges(qh, neighbor);
+      if (SETfirstt_(neighbor->neighbors, facetT) != facet1) /*keep newfacet->horizon*/
+        qh_setdel(neighbor->neighbors, facet1);
+      else {
+        qh_setdel(neighbor->neighbors, facet2);
+        qh_setreplace(qh, neighbor->neighbors, facet1, facet2);
+      }
+    }else if (neighbor != facet2) {
+      qh_setappend(qh, &(facet2->neighbors), neighbor);
+      qh_setreplace(qh, neighbor->neighbors, facet1, facet2);
+    }
+  }
+  qh_setdel(facet1->neighbors, facet2);  /* here for makeridges */
+  qh_setdel(facet2->neighbors, facet1);
+} /* mergeneighbors */
+
+
+/*---------------------------------
+
+  qh_mergeridges(qh, facet1, facet2 )
+    merges the ridge set of facet1 into facet2
+
+  returns:
+    may delete all ridges for a vertex
+    sets vertex->delridge on deleted ridges
+
+  see:
+    qh_mergecycle_ridges()
+
+  design:
+    delete ridges between facet1 and facet2
+      mark (delridge) vertices on these ridges for later testing
+    for each remaining ridge
+      rename facet1 to facet2
+*/
+void qh_mergeridges(qhT *qh, facetT *facet1, facetT *facet2) {
+  ridgeT *ridge, **ridgep;
+
+  trace4((qh, qh->ferr, 4038, "qh_mergeridges: merge ridges of f%d into f%d\n",
+          facet1->id, facet2->id));
+  FOREACHridge_(facet2->ridges) {
+    if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
+      /* ridge.nonconvex is irrelevant due to merge */
+      qh_delridge_merge(qh, ridge);  /* expensive in high-d, could rebuild */
+      ridgep--; /* deleted this ridge, repeat with next ridge*/
+    }
+  }
+  FOREACHridge_(facet1->ridges) {
+    if (ridge->top == facet1) {
+      ridge->top= facet2;
+      ridge->simplicialtop= False;
+    }else { /* ridge.bottom is facet1 */
+      ridge->bottom= facet2;
+      ridge->simplicialbot= False;
+    }
+    qh_setappend(qh, &(facet2->ridges), ridge);
+  }
+} /* mergeridges */
+
+
+/*---------------------------------
+
+  qh_mergesimplex(qh, facet1, facet2, mergeapex )
+    merge simplicial facet1 into facet2
+    mergeapex==qh_MERGEapex if merging samecycle into horizon facet
+      vertex id is latest (most recently created)
+    facet1 may be contained in facet2
+    ridges exist for both facets
+
+  returns:
+    facet2 with updated vertices, ridges, neighbors
+    updated neighbors for facet1's vertices
+    facet1 not deleted
+    sets vertex->delridge on deleted ridges
+
+  notes:
+    special case code since this is the most common merge
+    called from qh_mergefacet()
+
+  design:
+    if qh_MERGEapex
+      add vertices of facet2 to qh.new_vertexlist if necessary
+      add apex to facet2
+    else
+      for each ridge between facet1 and facet2
+        set vertex->delridge
+      determine the apex for facet1 (i.e., vertex to be merged)
+      unless apex already in facet2
+        insert apex into vertices for facet2
+      add vertices of facet2 to qh.new_vertexlist if necessary
+      add apex to qh.new_vertexlist if necessary
+      for each vertex of facet1
+        if apex
+          rename facet1 to facet2 in its vertex neighbors
+        else
+          delete facet1 from vertex neighbors
+          if only in facet2
+            add vertex to qh.del_vertices for later deletion
+      for each ridge of facet1
+        delete ridges between facet1 and facet2
+        append other ridges to facet2 after renaming facet to facet2
+*/
+void qh_mergesimplex(qhT *qh, facetT *facet1, facetT *facet2, boolT mergeapex) {
+  vertexT *vertex, **vertexp, *opposite;
+  ridgeT *ridge, **ridgep;
+  boolT isnew= False;
+  facetT *neighbor, **neighborp, *otherfacet;
+
+  if (mergeapex) {
+    opposite= SETfirstt_(facet1->vertices, vertexT); /* apex is opposite facet2.  It has the last vertex id */
+    trace4((qh, qh->ferr, 4086, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
+      opposite->id, facet1->id, facet2->id));
+    if (!facet2->newfacet)
+      qh_newvertices(qh, facet2->vertices);  /* apex, the first vertex, is already new */
+    if (SETfirstt_(facet2->vertices, vertexT) != opposite) {
+      qh_setaddnth(qh, &facet2->vertices, 0, opposite);
+      isnew= True;
+    }
+  }else {
+    zinc_(Zmergesimplex);
+    FOREACHvertex_(facet1->vertices)
+      vertex->seen= False;
+    FOREACHridge_(facet1->ridges) {
+      if (otherfacet_(ridge, facet1) == facet2) {
+        FOREACHvertex_(ridge->vertices) {
+          vertex->seen= True;
+          vertex->delridge= True;
+        }
+        break;
+      }
+    }
+    FOREACHvertex_(facet1->vertices) {
+      if (!vertex->seen)
+        break;  /* must occur */
+    }
+    opposite= vertex;
+    trace4((qh, qh->ferr, 4039, "qh_mergesimplex: merge opposite v%d of f%d into facet f%d\n",
+          opposite->id, facet1->id, facet2->id));
+    isnew= qh_addfacetvertex(qh, facet2, opposite);
+    if (!facet2->newfacet)
+      qh_newvertices(qh, facet2->vertices);
+    else if (!opposite->newfacet) {
+      qh_removevertex(qh, opposite);
+      qh_appendvertex(qh, opposite);
+    }
+  }
+  trace4((qh, qh->ferr, 4040, "qh_mergesimplex: update vertex neighbors of f%d\n",
+          facet1->id));
+  FOREACHvertex_(facet1->vertices) {
+    if (vertex == opposite && isnew)
+      qh_setreplace(qh, vertex->neighbors, facet1, facet2);
+    else {
+      qh_setdel(vertex->neighbors, facet1);
+      if (!SETsecond_(vertex->neighbors))
+        qh_mergevertex_del(qh, vertex, facet1, facet2);
+    }
+  }
+  trace4((qh, qh->ferr, 4041, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
+          facet1->id, facet2->id));
+  qh->visit_id++;
+  FOREACHneighbor_(facet2)
+    neighbor->visitid= qh->visit_id;
+  FOREACHridge_(facet1->ridges) {
+    otherfacet= otherfacet_(ridge, facet1);
+    if (otherfacet == facet2) {
+      /* ridge.nonconvex is irrelevant due to merge */
+      qh_delridge_merge(qh, ridge);  /* expensive in high-d, could rebuild */
+      ridgep--; /* deleted this ridge, repeat with next ridge*/
+      qh_setdel(facet2->neighbors, facet1); /* a simplicial facet may have duplicate neighbors, need to delete each one */
+    }else if (otherfacet->dupridge && !qh_setin(otherfacet->neighbors, facet1)) {
+      qh_fprintf(qh, qh->ferr, 6356, "qhull topology error (qh_mergesimplex): f%d is a dupridge of f%d, cannot merge f%d into f%d\n",
+        facet1->id, otherfacet->id, facet1->id, facet2->id);
+      qh_errexit2(qh, qh_ERRqhull, facet1, otherfacet);
+    }else {
+      trace4((qh, qh->ferr, 4059, "qh_mergesimplex: move r%d with f%d to f%d, new neighbor? %d, maybe horizon? %d\n",
+        ridge->id, otherfacet->id, facet2->id, (otherfacet->visitid != qh->visit_id), (SETfirstt_(otherfacet->neighbors, facetT) == facet1)));
+      qh_setappend(qh, &facet2->ridges, ridge);
+      if (otherfacet->visitid != qh->visit_id) {
+        qh_setappend(qh, &facet2->neighbors, otherfacet);
+        qh_setreplace(qh, otherfacet->neighbors, facet1, facet2);
+        otherfacet->visitid= qh->visit_id;
+      }else {
+        if (otherfacet->simplicial)    /* is degen, needs ridges */
+          qh_makeridges(qh, otherfacet);
+        if (SETfirstt_(otherfacet->neighbors, facetT) == facet1) {
+          /* keep new, otherfacet->neighbors->horizon */
+          qh_setdel(otherfacet->neighbors, facet2);
+          qh_setreplace(qh, otherfacet->neighbors, facet1, facet2);
+        }else {
+          /* facet2 is already a neighbor of otherfacet, by f.visitid */
+          qh_setdel(otherfacet->neighbors, facet1);
+        }
+      }
+      if (ridge->top == facet1) { /* wait until after qh_makeridges */
+        ridge->top= facet2;
+        ridge->simplicialtop= False;
+      }else {
+        ridge->bottom= facet2;
+        ridge->simplicialbot= False;
+      }
+    }
+  }
+  trace3((qh, qh->ferr, 3006, "qh_mergesimplex: merged simplex f%d v%d into facet f%d\n",
+          facet1->id, opposite->id, facet2->id));
+} /* mergesimplex */
+
+/*---------------------------------
+
+  qh_mergevertex_del(qh, vertex, facet1, facet2 )
+    delete a vertex because of merging facet1 into facet2
+
+  returns:
+    deletes vertex from facet2
+    adds vertex to qh.del_vertices for later deletion
+*/
+void qh_mergevertex_del(qhT *qh, vertexT *vertex, facetT *facet1, facetT *facet2) {
+
+  zinc_(Zmergevertex);
+  trace2((qh, qh->ferr, 2035, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
+          vertex->id, facet1->id, facet2->id));
+  qh_setdelsorted(facet2->vertices, vertex);
+  vertex->deleted= True;
+  qh_setappend(qh, &qh->del_vertices, vertex);
+} /* mergevertex_del */
+
+/*---------------------------------
+
+  qh_mergevertex_neighbors(qh, facet1, facet2 )
+    merge the vertex neighbors of facet1 to facet2
+
+  returns:
+    if vertex is current qh.vertex_visit
+      deletes facet1 from vertex->neighbors
+    else
+      renames facet1 to facet2 in vertex->neighbors
+    deletes vertices if only one neighbor
+
+  notes:
+    assumes vertex neighbor sets are good
+*/
+void qh_mergevertex_neighbors(qhT *qh, facetT *facet1, facetT *facet2) {
+  vertexT *vertex, **vertexp;
+
+  trace4((qh, qh->ferr, 4042, "qh_mergevertex_neighbors: merge vertex neighborset for f%d into f%d\n",
+          facet1->id, facet2->id));
+  if (qh->tracevertex) {
+    qh_fprintf(qh, qh->ferr, 8081, "qh_mergevertex_neighbors: of f%d into f%d at furthest p%d f0= %p\n",
+             facet1->id, facet2->id, qh->furthest_id, (void *) qh->tracevertex->neighbors->e[0].p);
+    qh_errprint(qh, "TRACE", NULL, NULL, NULL, qh->tracevertex);
+  }
+  FOREACHvertex_(facet1->vertices) {
+    if (vertex->visitid != qh->vertex_visit)
+      qh_setreplace(qh, vertex->neighbors, facet1, facet2);
+    else {
+      qh_setdel(vertex->neighbors, facet1);
+      if (!SETsecond_(vertex->neighbors))
+        qh_mergevertex_del(qh, vertex, facet1, facet2);
+    }
+  }
+  if (qh->tracevertex)
+    qh_errprint(qh, "TRACE", NULL, NULL, NULL, qh->tracevertex);
+} /* mergevertex_neighbors */
+
+
+/*---------------------------------
+
+  qh_mergevertices(qh, vertices1, vertices2 )
+    merges the vertex set of facet1 into facet2
+
+  returns:
+    replaces vertices2 with merged set
+    preserves vertex_visit for qh_mergevertex_neighbors
+    updates qh.newvertex_list
+
+  design:
+    create a merged set of both vertices (in inverse id order)
+*/
+void qh_mergevertices(qhT *qh, setT *vertices1, setT **vertices2) {
+  int newsize= qh_setsize(qh, vertices1)+qh_setsize(qh, *vertices2) - qh->hull_dim + 1;
+  setT *mergedvertices;
+  vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
+
+  mergedvertices= qh_settemp(qh, newsize);
+  FOREACHvertex_(vertices1) {
+    if (!*vertex2 || vertex->id > (*vertex2)->id)
+      qh_setappend(qh, &mergedvertices, vertex);
+    else {
+      while (*vertex2 && (*vertex2)->id > vertex->id)
+        qh_setappend(qh, &mergedvertices, *vertex2++);
+      if (!*vertex2 || (*vertex2)->id < vertex->id)
+        qh_setappend(qh, &mergedvertices, vertex);
+      else
+        qh_setappend(qh, &mergedvertices, *vertex2++);
+    }
+  }
+  while (*vertex2)
+    qh_setappend(qh, &mergedvertices, *vertex2++);
+  if (newsize < qh_setsize(qh, mergedvertices)) {
+    qh_fprintf(qh, qh->ferr, 6100, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh_setfree(qh, vertices2);
+  *vertices2= mergedvertices;
+  qh_settemppop(qh);
+} /* mergevertices */
+
+
+/*---------------------------------
+
+  qh_neighbor_intersections(qh, vertex )
+    return intersection of all vertices in vertex->neighbors except for vertex
+
+  returns:
+    returns temporary set of vertices
+    does not include vertex
+    NULL if a neighbor is simplicial
+    NULL if empty set
+
+  notes:
+    only called by qh_redundant_vertex for qh_reducevertices
+      so f.vertices does not contain extraneous vertices that are not in f.ridges
+    used for renaming vertices
+
+  design:
+    initialize the intersection set with vertices of the first two neighbors
+    delete vertex from the intersection
+    for each remaining neighbor
+      intersect its vertex set with the intersection set
+      return NULL if empty
+    return the intersection set
+*/
+setT *qh_neighbor_intersections(qhT *qh, vertexT *vertex) {
+  facetT *neighbor, **neighborp, *neighborA, *neighborB;
+  setT *intersect;
+  int neighbor_i, neighbor_n;
+
+  FOREACHneighbor_(vertex) {
+    if (neighbor->simplicial)
+      return NULL;
+  }
+  neighborA= SETfirstt_(vertex->neighbors, facetT);
+  neighborB= SETsecondt_(vertex->neighbors, facetT);
+  zinc_(Zintersectnum);
+  if (!neighborA)
+    return NULL;
+  if (!neighborB)
+    intersect= qh_setcopy(qh, neighborA->vertices, 0);
+  else
+    intersect= qh_vertexintersect_new(qh, neighborA->vertices, neighborB->vertices);
+  qh_settemppush(qh, intersect);
+  qh_setdelsorted(intersect, vertex);
+  FOREACHneighbor_i_(qh, vertex) {
+    if (neighbor_i >= 2) {
+      zinc_(Zintersectnum);
+      qh_vertexintersect(qh, &intersect, neighbor->vertices);
+      if (!SETfirst_(intersect)) {
+        zinc_(Zintersectfail);
+        qh_settempfree(qh, &intersect);
+        return NULL;
+      }
+    }
+  }
+  trace3((qh, qh->ferr, 3007, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n",
+          qh_setsize(qh, intersect), vertex->id));
+  return intersect;
+} /* neighbor_intersections */
+
+/*---------------------------------
+
+  qh_neighbor_vertices(qh, vertex )
+    return neighboring vertices for a vertex (not in subridge)
+    assumes vertices have full vertex->neighbors
+
+  returns:
+    temporary set of vertices
+
+  notes:
+    updates qh.visit_id and qh.vertex_visit
+    similar to qh_vertexridges
+
+*/
+setT *qh_neighbor_vertices(qhT *qh, vertexT *vertexA, setT *subridge) {
+  facetT *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  setT *vertices= qh_settemp(qh, qh->TEMPsize);
+
+  qh->visit_id++;
+  FOREACHneighbor_(vertexA)
+    neighbor->visitid= qh->visit_id;
+  qh->vertex_visit++;
+  vertexA->visitid= qh->vertex_visit;
+  FOREACHvertex_(subridge) {
+    vertex->visitid= qh->vertex_visit;
+  }
+  FOREACHneighbor_(vertexA) {
+    if (*neighborp)   /* no new ridges in last neighbor */
+      qh_neighbor_vertices_facet(qh, vertexA, neighbor, &vertices);
+  }
+  trace3((qh, qh->ferr, 3035, "qh_neighbor_vertices: %d non-subridge, vertex neighbors for v%d\n",
+    qh_setsize(qh, vertices), vertexA->id));
+  return vertices;
+} /* neighbor_vertices */
+
+/*---------------------------------
+
+  qh_neighbor_vertices_facet(qh, vertex, facet, vertices )
+    add neighboring vertices on ridges for vertex in facet
+    neighbor->visitid==qh.visit_id if it hasn't been visited
+    v.visitid==qh.vertex_visit if it is already in vertices
+
+  returns:
+    vertices updated
+    sets facet->visitid to qh.visit_id-1
+
+  notes:
+    only called by qh_neighbor_vertices
+    similar to qh_vertexridges_facet
+
+  design:
+    for each ridge of facet
+      if ridge of visited neighbor (i.e., unprocessed)
+        if vertex in ridge
+          append unprocessed vertices of ridge
+    mark facet processed
+*/
+void qh_neighbor_vertices_facet(qhT *qh, vertexT *vertexA, facetT *facet, setT **vertices) {
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor;
+  vertexT *second, *last, *vertex, **vertexp;
+  int last_i= qh->hull_dim-2, count= 0;
+  boolT isridge;
+
+  if (facet->simplicial) {
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh->vertex_visit) {
+        vertex->visitid= qh->vertex_visit;
+        qh_setappend(qh, vertices, vertex);
+        count++;
+      }
+    }
+  }else {
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid == qh->visit_id) {
+        isridge= False;
+        if (SETfirst_(ridge->vertices) == vertexA) {
+          isridge= True;
+        }else if (last_i > 2) {
+          second= SETsecondt_(ridge->vertices, vertexT);
+          last= SETelemt_(ridge->vertices, last_i, vertexT);
+          if (second->id >= vertexA->id && last->id <= vertexA->id) { /* vertices inverse sorted by id */
+            if (second == vertexA || last == vertexA)
+              isridge= True;
+            else if (qh_setin(ridge->vertices, vertexA))
+              isridge= True;
+          }
+        }else if (SETelem_(ridge->vertices, last_i) == vertexA) {
+          isridge= True;
+        }else if (last_i > 1 && SETsecond_(ridge->vertices) == vertexA) {
+          isridge= True;
+        }
+        if (isridge) {
+          FOREACHvertex_(ridge->vertices) {
+            if (vertex->visitid != qh->vertex_visit) {
+              vertex->visitid= qh->vertex_visit;
+              qh_setappend(qh, vertices, vertex);
+              count++;
+            }
+          }
+        }
+      }
+    }
+  }
+  facet->visitid= qh->visit_id-1;
+  if (count) {
+    trace4((qh, qh->ferr, 4079, "qh_neighbor_vertices_facet: found %d vertex neighbors for v%d in f%d (simplicial? %d)\n",
+      count, vertexA->id, facet->id, facet->simplicial));
+  }
+} /* neighbor_vertices_facet */
+
+
+/*---------------------------------
+
+  qh_newvertices(qh, vertices )
+    add vertices to end of qh.vertex_list (marks as new vertices)
+
+  returns:
+    vertices on qh.newvertex_list
+    vertex->newfacet set
+*/
+void qh_newvertices(qhT *qh, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (!vertex->newfacet) {
+      qh_removevertex(qh, vertex);
+      qh_appendvertex(qh, vertex);
+    }
+  }
+} /* newvertices */
+
+/*---------------------------------
+
+  qh_next_vertexmerge(qh )
+    return next vertex merge from qh.vertex_mergeset
+
+  returns:
+    vertex merge either MRGvertices or MRGsubridge
+    drops merges of deleted vertices
+
+  notes:
+    called from qh_merge_pinchedvertices
+*/
+mergeT *qh_next_vertexmerge(qhT *qh /* qh.vertex_mergeset */) {
+  mergeT *merge;
+  int merge_i, merge_n, best_i= -1;
+  realT bestdist= REALmax;
+
+  FOREACHmerge_i_(qh, qh->vertex_mergeset) {
+    if (!merge->vertex1 || !merge->vertex2) {
+      qh_fprintf(qh, qh->ferr, 6299, "qhull internal error (qh_next_vertexmerge): expecting two vertices for vertex merge.  Got v%d v%d and optional f%d\n",
+        getid_(merge->vertex1), getid_(merge->vertex2), getid_(merge->facet1));
+      qh_errexit(qh, qh_ERRqhull, merge->facet1, NULL);
+    }
+    if (merge->vertex1->deleted || merge->vertex2->deleted) {
+      trace3((qh, qh->ferr, 3030, "qh_next_vertexmerge: drop merge of v%d (del? %d) into v%d (del? %d) due to deleted vertex of r%d and r%d\n",
+        merge->vertex1->id, merge->vertex1->deleted, merge->vertex2->id, merge->vertex2->deleted, getid_(merge->ridge1), getid_(merge->ridge2)));
+      qh_drop_mergevertex(qh, merge);
+      qh_setdelnth(qh, qh->vertex_mergeset, merge_i);
+      merge_i--; merge_n--;
+      qh_memfree(qh, merge, (int)sizeof(mergeT));
+    }else if (merge->distance < bestdist) {
+      bestdist= merge->distance;
+      best_i= merge_i;
+    }
+  }
+  merge= NULL;
+  if (best_i >= 0) {
+    merge= SETelemt_(qh->vertex_mergeset, best_i, mergeT);
+    if (bestdist/qh->ONEmerge > qh_WIDEpinched) {
+      if (merge->mergetype==MRGvertices) {
+        if (merge->ridge1->top == merge->ridge2->bottom && merge->ridge1->bottom == merge->ridge2->top)
+          qh_fprintf(qh, qh->ferr, 6391, "qhull topology error (qh_next_vertexmerge): no nearly adjacent vertices to resolve opposite oriented ridges r%d and r%d in f%d and f%d.  Nearest v%d and v%d dist %2.2g (%.1fx)\n",
+            merge->ridge1->id, merge->ridge2->id, merge->ridge1->top->id, merge->ridge1->bottom->id, merge->vertex1->id, merge->vertex2->id, bestdist, bestdist/qh->ONEmerge);
+        else
+          qh_fprintf(qh, qh->ferr, 6381, "qhull topology error (qh_next_vertexmerge): no nearly adjacent vertices to resolve duplicate ridges r%d and r%d.  Nearest v%d and v%d dist %2.2g (%.1fx)\n",
+            merge->ridge1->id, merge->ridge2->id, merge->vertex1->id, merge->vertex2->id, bestdist, bestdist/qh->ONEmerge);
+      }else {
+        qh_fprintf(qh, qh->ferr, 6208, "qhull topology error (qh_next_vertexmerge): no nearly adjacent vertices to resolve dupridge.  Nearest v%d and v%d dist %2.2g (%.1fx)\n",
+          merge->vertex1->id, merge->vertex2->id, bestdist, bestdist/qh->ONEmerge);
+      }
+      /* it may be possible to find a different vertex, after other vertex merges have occurred */
+      qh_errexit(qh, qh_ERRtopology, NULL, merge->ridge1);
+    }
+    qh_setdelnth(qh, qh->vertex_mergeset, best_i);
+  }
+  return merge;
+} /* next_vertexmerge */
+
+/*---------------------------------
+
+  qh_opposite_horizonfacet(qh, merge, opposite )
+    return horizon facet for one of the merge facets, and its opposite vertex across the ridge
+    assumes either facet1 or facet2 of merge is 'mergehorizon'
+    assumes both facets are simplicial facets on qh.new_facetlist
+
+  returns:
+    horizon facet and opposite vertex
+
+  notes:
+    called by qh_getpinchedmerges
+*/
+facetT *qh_opposite_horizonfacet(qhT *qh, mergeT *merge, vertexT **opposite) {
+  facetT *facet, *horizon, *otherfacet;
+  int neighbor_i;
+
+  if (!merge->facet1->simplicial || !merge->facet2->simplicial || (!merge->facet1->mergehorizon && !merge->facet2->mergehorizon)) {
+    qh_fprintf(qh, qh->ferr, 6273, "qhull internal error (qh_opposite_horizonfacet): expecting merge of simplicial facets, at least one of which is mergehorizon.  Either simplicial or mergehorizon is wrong\n");
+    qh_errexit2(qh, qh_ERRqhull, merge->facet1, merge->facet2);
+  }
+  if (merge->facet1->mergehorizon) {
+    facet= merge->facet1;
+    otherfacet= merge->facet2;
+  }else {
+    facet= merge->facet2;
+    otherfacet= merge->facet1;
+  }
+  horizon= SETfirstt_(facet->neighbors, facetT);
+  neighbor_i= qh_setindex(otherfacet->neighbors, facet);
+  if (neighbor_i==-1)
+    neighbor_i= qh_setindex(otherfacet->neighbors, qh_MERGEridge);
+  if (neighbor_i==-1) {
+    qh_fprintf(qh, qh->ferr, 6238, "qhull internal error (qh_opposite_horizonfacet): merge facet f%d not connected to mergehorizon f%d\n",
+      otherfacet->id, facet->id);
+    qh_errexit2(qh, qh_ERRqhull, otherfacet, facet);
+  }
+  *opposite= SETelemt_(otherfacet->vertices, neighbor_i, vertexT);
+  return horizon;
+} /* opposite_horizonfacet */
+
+
+/*---------------------------------
+
+  qh_reducevertices(qh)
+    reduce extra vertices, shared vertices, and redundant vertices
+    facet->newmerge is set if merged since last call
+    vertex->delridge is set if vertex was on a deleted ridge
+    if !qh.MERGEvertices, only removes extra vertices
+
+  returns:
+    True if also merged degen_redundant facets
+    vertices are renamed if possible
+    clears facet->newmerge and vertex->delridge
+
+  notes:
+    called by qh_all_merges and qh_postmerge
+    ignored if 2-d
+
+  design:
+    merge any degenerate or redundant facets
+    repeat until no more degenerate or redundant facets
+      for each newly merged facet
+        remove extra vertices
+      if qh.MERGEvertices
+        for each newly merged facet
+          for each vertex
+            if vertex was on a deleted ridge
+              rename vertex if it is shared
+        for each new, undeleted vertex
+          remove delridge flag
+          if vertex is redundant
+            merge degenerate or redundant facets
+*/
+boolT qh_reducevertices(qhT *qh) {
+  int numshare=0, numrename= 0;
+  boolT degenredun= False;
+  facetT *newfacet;
+  vertexT *vertex, **vertexp;
+
+  if (qh->hull_dim == 2)
+    return False;
+  trace2((qh, qh->ferr, 2101, "qh_reducevertices: reduce extra vertices, shared vertices, and redundant vertices\n"));
+  if (qh_merge_degenredundant(qh))
+    degenredun= True;
+LABELrestart:
+  FORALLnew_facets {
+    if (newfacet->newmerge) {
+      if (!qh->MERGEvertices)
+        newfacet->newmerge= False;
+      if (qh_remove_extravertices(qh, newfacet)) {
+        qh_degen_redundant_facet(qh, newfacet);
+        if (qh_merge_degenredundant(qh)) {
+          degenredun= True;
+          goto LABELrestart;
+        }
+      }
+    }
+  }
+  if (!qh->MERGEvertices)
+    return False;
+  FORALLnew_facets {
+    if (newfacet->newmerge) {
+      newfacet->newmerge= False;
+      FOREACHvertex_(newfacet->vertices) {
+        if (vertex->delridge) {
+          if (qh_rename_sharedvertex(qh, vertex, newfacet)) {
+            numshare++;
+            if (qh_merge_degenredundant(qh)) {
+              degenredun= True;
+              goto LABELrestart;
+            }
+            vertexp--; /* repeat since deleted vertex */
+          }
+        }
+      }
+    }
+  }
+  FORALLvertex_(qh->newvertex_list) {
+    if (vertex->delridge && !vertex->deleted) {
+      vertex->delridge= False;
+      if (qh->hull_dim >= 4 && qh_redundant_vertex(qh, vertex)) {
+        numrename++;
+        if (qh_merge_degenredundant(qh)) {
+          degenredun= True;
+          goto LABELrestart;
+        }
+      }
+    }
+  }
+  trace1((qh, qh->ferr, 1014, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
+          numshare, numrename, degenredun));
+  return degenredun;
+} /* reducevertices */
+
+/*---------------------------------
+
+  qh_redundant_vertex(qh, vertex )
+    rename a redundant vertex if qh_find_newvertex succeeds
+    assumes vertices have full vertex->neighbors
+
+  returns:
+    if find a replacement vertex
+      returns new vertex
+      qh_renamevertex sets vertex->deleted for redundant vertex
+
+  notes:
+    only called by qh_reducevertices for vertex->delridge and hull_dim >= 4
+    may add degenerate facets to qh.facet_mergeset
+    doesn't change vertex->neighbors or create redundant facets
+
+  design:
+    intersect vertices of all facet neighbors of vertex
+    determine ridges for these vertices
+    if find a new vertex for vertex among these ridges and vertices
+      rename vertex to the new vertex
+*/
+vertexT *qh_redundant_vertex(qhT *qh, vertexT *vertex) {
+  vertexT *newvertex= NULL;
+  setT *vertices, *ridges;
+
+  trace3((qh, qh->ferr, 3008, "qh_redundant_vertex: check if v%d from a deleted ridge can be renamed\n", vertex->id));
+  if ((vertices= qh_neighbor_intersections(qh, vertex))) {
+    ridges= qh_vertexridges(qh, vertex, !qh_ALL);
+    if ((newvertex= qh_find_newvertex(qh, vertex, vertices, ridges))) {
+      zinc_(Zrenameall);
+      qh_renamevertex(qh, vertex, newvertex, ridges, NULL, NULL); /* ridges invalidated */
+    }
+    qh_settempfree(qh, &ridges);
+    qh_settempfree(qh, &vertices);
+  }
+  return newvertex;
+} /* redundant_vertex */
+
+/*---------------------------------
+
+  qh_remove_extravertices(qh, facet )
+    remove extra vertices from non-simplicial facets
+
+  returns:
+    returns True if it finds them
+      deletes facet from vertex neighbors
+      facet may be redundant (test with qh_degen_redundant)
+
+  notes:
+    called by qh_renamevertex and qh_reducevertices
+    a merge (qh_reducevertices) or qh_renamevertex may drop all ridges for a vertex in a facet
+
+  design:
+    for each vertex in facet
+      if vertex not in a ridge (i.e., no longer used)
+        delete vertex from facet
+        delete facet from vertex's neighbors
+        unless vertex in another facet
+          add vertex to qh.del_vertices for later deletion
+*/
+boolT qh_remove_extravertices(qhT *qh, facetT *facet) {
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+  boolT foundrem= False;
+
+  if (facet->simplicial) {
+    return False;
+  }
+  trace4((qh, qh->ferr, 4043, "qh_remove_extravertices: test non-simplicial f%d for extra vertices\n",
+          facet->id));
+  FOREACHvertex_(facet->vertices)
+    vertex->seen= False;
+  FOREACHridge_(facet->ridges) {
+    FOREACHvertex_(ridge->vertices)
+      vertex->seen= True;
+  }
+  FOREACHvertex_(facet->vertices) {
+    if (!vertex->seen) {
+      foundrem= True;
+      zinc_(Zremvertex);
+      qh_setdelsorted(facet->vertices, vertex);
+      qh_setdel(vertex->neighbors, facet);
+      if (!qh_setsize(qh, vertex->neighbors)) {
+        vertex->deleted= True;
+        qh_setappend(qh, &qh->del_vertices, vertex);
+        zinc_(Zremvertexdel);
+        trace2((qh, qh->ferr, 2036, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
+      }else
+        trace3((qh, qh->ferr, 3009, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
+      vertexp--; /*repeat*/
+    }
+  }
+  return foundrem;
+} /* remove_extravertices */
+
+/*---------------------------------
+
+  qh_remove_mergetype(qh, mergeset, mergetype )
+    Remove mergetype merges from mergeset
+
+  notes:
+    Does not preserve order
+*/
+void qh_remove_mergetype(qhT *qh, setT *mergeset, mergeType type) {
+  mergeT *merge;
+  int merge_i, merge_n;
+
+  FOREACHmerge_i_(qh, mergeset) {
+    if (merge->mergetype == type) {
+        trace3((qh, qh->ferr, 3037, "qh_remove_mergetype: remove merge f%d f%d v%d v%d r%d r%d dist %2.2g type %d",
+            getid_(merge->facet1), getid_(merge->facet2), getid_(merge->vertex1), getid_(merge->vertex2), getid_(merge->ridge1), getid_(merge->ridge2), merge->distance, type));
+        qh_setdelnth(qh, mergeset, merge_i);
+        merge_i--; merge_n--;  /* repeat with next merge */
+    }
+  }
+} /* remove_mergetype */
+
+/*---------------------------------
+
+  qh_rename_adjacentvertex(qh, oldvertex, newvertex )
+    renames oldvertex as newvertex.  Must be adjacent (i.e., in the same subridge)
+    no-op if either vertex is deleted
+
+  notes:
+    called from qh_merge_pinchedvertices
+
+  design:
+    for all neighbors of oldvertex
+      if simplicial, rename oldvertex to newvertex and drop if degenerate
+      if needed, add oldvertex neighbor to newvertex
+    determine ridges for oldvertex
+    rename oldvertex as newvertex in ridges (qh_renamevertex)
+*/
+void qh_rename_adjacentvertex(qhT *qh, vertexT *oldvertex, vertexT *newvertex, realT dist) {
+  setT *ridges;
+  facetT *neighbor, **neighborp, *maxfacet= NULL;
+  ridgeT *ridge, **ridgep;
+  boolT istrace= False;
+  int oldsize= qh_setsize(qh, oldvertex->neighbors);
+  int newsize= qh_setsize(qh, newvertex->neighbors);
+  coordT maxdist2= -REALmax, dist2;
+
+  if (qh->IStracing >= 4 || oldvertex->id == qh->tracevertex_id || newvertex->id == qh->tracevertex_id) {
+    istrace= True;
+  }
+  zzinc_(Ztotmerge);
+  if (istrace) {
+    qh_fprintf(qh, qh->ferr, 2071, "qh_rename_adjacentvertex: merge #%d rename v%d (%d neighbors) to v%d (%d neighbors) dist %2.2g\n",
+      zzval_(Ztotmerge), oldvertex->id, oldsize, newvertex->id, newsize, dist);
+  }
+  if (oldvertex->deleted || newvertex->deleted) {
+    if (istrace || qh->IStracing >= 2) {
+      qh_fprintf(qh, qh->ferr, 2072, "qh_rename_adjacentvertex: ignore rename.  Either v%d (%d) or v%d (%d) is deleted\n",
+        oldvertex->id, oldvertex->deleted, newvertex->id, newvertex->deleted);
+    }
+    return;
+  }
+  if (oldsize == 0 || newsize == 0) {
+    qh_fprintf(qh, qh->ferr, 2072, "qhull internal error (qh_rename_adjacentvertex): expecting neighbor facets for v%d and v%d.  Got %d and %d neighbors resp.\n",
+      oldvertex->id, newvertex->id, oldsize, newsize);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  FOREACHneighbor_(oldvertex) {
+    if (neighbor->simplicial) {
+      if (qh_setin(neighbor->vertices, newvertex)) {
+        if (istrace || qh->IStracing >= 2) {
+          qh_fprintf(qh, qh->ferr, 2070, "qh_rename_adjacentvertex: simplicial f%d contains old v%d and new v%d.  Will be marked degenerate by qh_renamevertex\n",
+            neighbor->id, oldvertex->id, newvertex->id);
+        }
+        qh_makeridges(qh, neighbor); /* no longer simplicial, nummerge==0, skipped by qh_maybe_duplicateridge */
+      }else {
+        qh_replacefacetvertex(qh, neighbor, oldvertex, newvertex);
+        qh_setunique(qh, &newvertex->neighbors, neighbor);
+        qh_newvertices(qh, neighbor->vertices);  /* for qh_update_vertexneighbors of vertex neighbors */
+      }
+    }
+  }
+  ridges= qh_vertexridges(qh, oldvertex, qh_ALL);
+  if (istrace) {
+    FOREACHridge_(ridges) {
+      qh_printridge(qh, qh->ferr, ridge);
+    }
+  }
+  FOREACHneighbor_(oldvertex) {
+    if (!neighbor->simplicial){
+      qh_addfacetvertex(qh, neighbor, newvertex);
+      qh_setunique(qh, &newvertex->neighbors, neighbor);
+      qh_newvertices(qh, neighbor->vertices);  /* for qh_update_vertexneighbors of vertex neighbors */
+      if (qh->newfacet_list == qh->facet_tail) {
+        qh_removefacet(qh, neighbor);  /* add a neighbor to newfacet_list so that qh_partitionvisible has a newfacet */
+        qh_appendfacet(qh, neighbor);
+        neighbor->newfacet= True;
+      }
+    }
+  }
+  qh_renamevertex(qh, oldvertex, newvertex, ridges, NULL, NULL);  /* ridges invalidated */
+  if (oldvertex->deleted && !oldvertex->partitioned) {
+    FOREACHneighbor_(newvertex) {
+      if (!neighbor->visible) {
+        qh_distplane(qh, oldvertex->point, neighbor, &dist2);
+        if (dist2>maxdist2) {
+          maxdist2= dist2;
+          maxfacet= neighbor;
+        }
+      }
+    }
+    trace2((qh, qh->ferr, 2096, "qh_rename_adjacentvertex: partition old p%d(v%d) as a coplanar point for furthest f%d dist %2.2g.  Maybe repartition later (QH0031)\n",
+      qh_pointid(qh, oldvertex->point), oldvertex->id, maxfacet->id, maxdist2))
+    qh_partitioncoplanar(qh, oldvertex->point, maxfacet, NULL, !qh_ALL);  /* faster with maxdist2, otherwise duplicates distance tests from maxdist2/dist2 */
+    oldvertex->partitioned= True;
+  }
+  qh_settempfree(qh, &ridges);
+} /* rename_adjacentvertex */
+
+/*---------------------------------
+
+  qh_rename_sharedvertex(qh, vertex, facet )
+    detect and rename if shared vertex in facet
+    vertices have full ->neighbors
+
+  returns:
+    newvertex or NULL
+    the vertex may still exist in other facets (i.e., a neighbor was pinched)
+    does not change facet->neighbors
+    updates vertex->neighbors
+
+  notes:
+    only called by qh_reducevertices after qh_remove_extravertices
+       so f.vertices does not contain extraneous vertices
+    a shared vertex for a facet is only in ridges to one neighbor
+    this may undo a pinched facet
+
+    it does not catch pinches involving multiple facets.  These appear
+      to be difficult to detect, since an exhaustive search is too expensive.
+
+  design:
+    if vertex only has two neighbors
+      determine the ridges that contain the vertex
+      determine the vertices shared by both neighbors
+      if can find a new vertex in this set
+        rename the vertex to the new vertex
+*/
+vertexT *qh_rename_sharedvertex(qhT *qh, vertexT *vertex, facetT *facet) {
+  facetT *neighbor, **neighborp, *neighborA= NULL;
+  setT *vertices, *ridges;
+  vertexT *newvertex= NULL;
+
+  if (qh_setsize(qh, vertex->neighbors) == 2) {
+    neighborA= SETfirstt_(vertex->neighbors, facetT);
+    if (neighborA == facet)
+      neighborA= SETsecondt_(vertex->neighbors, facetT);
+  }else if (qh->hull_dim == 3)
+    return NULL;
+  else {
+    qh->visit_id++;
+    FOREACHneighbor_(facet)
+      neighbor->visitid= qh->visit_id;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->visitid == qh->visit_id) {
+        if (neighborA)
+          return NULL;
+        neighborA= neighbor;
+      }
+    }
+  }
+  if (!neighborA) {
+    qh_fprintf(qh, qh->ferr, 6101, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
+        vertex->id, facet->id);
+    qh_errprint(qh, "ERRONEOUS", facet, NULL, NULL, vertex);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (neighborA) { /* avoid warning */
+    /* the vertex is shared by facet and neighborA */
+    ridges= qh_settemp(qh, qh->TEMPsize);
+    neighborA->visitid= ++qh->visit_id;
+    qh_vertexridges_facet(qh, vertex, facet, &ridges);
+    trace2((qh, qh->ferr, 2037, "qh_rename_sharedvertex: p%d(v%d) is shared by f%d(%d ridges) and f%d\n",
+      qh_pointid(qh, vertex->point), vertex->id, facet->id, qh_setsize(qh, ridges), neighborA->id));
+    zinc_(Zintersectnum);
+    vertices= qh_vertexintersect_new(qh, facet->vertices, neighborA->vertices);
+    qh_setdel(vertices, vertex);
+    qh_settemppush(qh, vertices);
+    if ((newvertex= qh_find_newvertex(qh, vertex, vertices, ridges)))
+      qh_renamevertex(qh, vertex, newvertex, ridges, facet, neighborA);  /* ridges invalidated */
+    qh_settempfree(qh, &vertices);
+    qh_settempfree(qh, &ridges);
+  }
+  return newvertex;
+} /* rename_sharedvertex */
+
+/*---------------------------------
+
+  qh_renameridgevertex(qh, ridge, oldvertex, newvertex )
+    renames oldvertex as newvertex in ridge
+
+  returns:
+    True if renames oldvertex
+    False if deleted the ridge
+
+  notes:
+    called by qh_renamevertex
+    caller sets newvertex->delridge for deleted ridges (qh_reducevertices)
+
+  design:
+    delete oldvertex from ridge
+    if newvertex already in ridge
+      copy ridge->noconvex to another ridge if possible
+      delete the ridge
+    else
+      insert newvertex into the ridge
+      adjust the ridge's orientation
+*/
+boolT qh_renameridgevertex(qhT *qh, ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
+  int nth= 0, oldnth;
+  facetT *temp;
+  vertexT *vertex, **vertexp;
+
+  oldnth= qh_setindex(ridge->vertices, oldvertex);
+  if (oldnth < 0) {
+    qh_fprintf(qh, qh->ferr, 6424, "qhull internal error (qh_renameridgevertex): oldvertex v%d not found in r%d.  Cannot rename to v%d\n",
+        oldvertex->id, ridge->id, newvertex->id);
+    qh_errexit(qh, qh_ERRqhull, NULL, ridge);
+  }
+  qh_setdelnthsorted(qh, ridge->vertices, oldnth);
+  FOREACHvertex_(ridge->vertices) {
+    if (vertex == newvertex) {
+      zinc_(Zdelridge);
+      if (ridge->nonconvex) /* only one ridge has nonconvex set */
+        qh_copynonconvex(qh, ridge);
+      trace2((qh, qh->ferr, 2038, "qh_renameridgevertex: ridge r%d deleted.  It contained both v%d and v%d\n",
+        ridge->id, oldvertex->id, newvertex->id));
+      qh_delridge_merge(qh, ridge); /* ridge.vertices deleted */
+      return False;
+    }
+    if (vertex->id < newvertex->id)
+      break;
+    nth++;
+  }
+  qh_setaddnth(qh, &ridge->vertices, nth, newvertex);
+  ridge->simplicialtop= False;
+  ridge->simplicialbot= False;
+  if (abs(oldnth - nth)%2) {
+    trace3((qh, qh->ferr, 3010, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n",
+            ridge->id));
+    temp= ridge->top;
+    ridge->top= ridge->bottom;
+    ridge->bottom= temp;
+  }
+  return True;
+} /* renameridgevertex */
+
+
+/*---------------------------------
+
+  qh_renamevertex(qh, oldvertex, newvertex, ridges, oldfacet, neighborA )
+    renames oldvertex as newvertex in ridges of non-simplicial neighbors
+    set oldfacet/neighborA if oldvertex is shared between two facets (qh_rename_sharedvertex)
+    otherwise qh_redundant_vertex or qh_rename_adjacentvertex
+
+  returns:
+    if oldfacet and multiple neighbors, oldvertex may still exist afterwards
+    otherwise sets oldvertex->deleted for later deletion
+    one or more ridges maybe deleted
+    ridges is invalidated
+    merges may be added to degen_mergeset via qh_maydropneighbor or qh_degen_redundant_facet
+
+  notes:
+    qh_rename_sharedvertex can not change neighbors of newvertex (since it's a subset)
+    qh_redundant_vertex due to vertex->delridge for qh_reducevertices
+    qh_rename_adjacentvertex for complete renames
+
+  design:
+    for each ridge in ridges
+      rename oldvertex to newvertex and delete degenerate ridges
+    if oldfacet not defined
+      for each non-simplicial neighbor of oldvertex
+        delete oldvertex from neighbor's vertices
+        remove extra vertices from neighbor
+      add oldvertex to qh.del_vertices
+    else if oldvertex only between oldfacet and neighborA
+      delete oldvertex from oldfacet and neighborA
+      add oldvertex to qh.del_vertices
+    else oldvertex is in oldfacet and neighborA and other facets (i.e., pinched)
+      delete oldvertex from oldfacet
+      delete oldfacet from old vertex's neighbors
+      remove extra vertices (e.g., oldvertex) from neighborA
+*/
+void qh_renamevertex(qhT *qh, vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int topsize, bottomsize;
+  boolT istrace= False;
+
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 2 || oldvertex->id == qh->tracevertex_id ||
+        newvertex->id == qh->tracevertex_id) {
+    istrace= True;
+    qh_fprintf(qh, qh->ferr, 2086, "qh_renamevertex: rename v%d to v%d in %d ridges with old f%d and neighbor f%d\n",
+      oldvertex->id, newvertex->id, qh_setsize(qh, ridges), getid_(oldfacet), getid_(neighborA));
+  }
+#endif
+  FOREACHridge_(ridges) {
+    if (qh_renameridgevertex(qh, ridge, oldvertex, newvertex)) { /* ridge is deleted if False, invalidating ridges */
+      topsize= qh_setsize(qh, ridge->top->vertices);
+      bottomsize= qh_setsize(qh, ridge->bottom->vertices);
+      if (topsize < qh->hull_dim || (topsize == qh->hull_dim && !ridge->top->simplicial && qh_setin(ridge->top->vertices, newvertex))) {
+        trace4((qh, qh->ferr, 4070, "qh_renamevertex: ignore duplicate check for r%d.  top f%d (size %d) will be degenerate after rename v%d to v%d\n",
+          ridge->id, ridge->top->id, topsize, oldvertex->id, newvertex->id));
+      }else if (bottomsize < qh->hull_dim || (bottomsize == qh->hull_dim && !ridge->bottom->simplicial && qh_setin(ridge->bottom->vertices, newvertex))) {
+        trace4((qh, qh->ferr, 4071, "qh_renamevertex: ignore duplicate check for r%d.  bottom f%d (size %d) will be degenerate after rename v%d to v%d\n",
+          ridge->id, ridge->bottom->id, bottomsize, oldvertex->id, newvertex->id));
+      }else
+        qh_maybe_duplicateridge(qh, ridge);
+    }
+  }
+  if (!oldfacet) {
+    /* stat Zrenameall or Zpinchduplicate */
+    if (istrace)
+      qh_fprintf(qh, qh->ferr, 2087, "qh_renamevertex: renaming v%d to v%d in several facets for qh_redundant_vertex or MRGsubridge\n",
+               oldvertex->id, newvertex->id);
+    FOREACHneighbor_(oldvertex) {
+      if (neighbor->simplicial) {
+        qh_degen_redundant_facet(qh, neighbor); /* e.g., rbox 175 C3,2e-13 D4 t1545235541 | qhull d */
+      }else {
+        if (istrace)
+          qh_fprintf(qh, qh->ferr, 4080, "qh_renamevertex: rename vertices in non-simplicial neighbor f%d of v%d\n", neighbor->id, oldvertex->id);
+        qh_maydropneighbor(qh, neighbor);
+        qh_setdelsorted(neighbor->vertices, oldvertex); /* if degenerate, qh_degen_redundant_facet will add to mergeset */
+        if (qh_remove_extravertices(qh, neighbor))
+          neighborp--; /* neighbor deleted from oldvertex neighborset */
+        qh_degen_redundant_facet(qh, neighbor); /* either direction may be redundant, faster if combine? */
+        qh_test_redundant_neighbors(qh, neighbor);
+        qh_test_degen_neighbors(qh, neighbor);
+      }
+    }
+    if (!oldvertex->deleted) {
+      oldvertex->deleted= True;
+      qh_setappend(qh, &qh->del_vertices, oldvertex);
+    }
+  }else if (qh_setsize(qh, oldvertex->neighbors) == 2) {
+    zinc_(Zrenameshare);
+    if (istrace)
+      qh_fprintf(qh, qh->ferr, 3039, "qh_renamevertex: renaming v%d to v%d in oldfacet f%d for qh_rename_sharedvertex\n",
+               oldvertex->id, newvertex->id, oldfacet->id);
+    FOREACHneighbor_(oldvertex) {
+      qh_setdelsorted(neighbor->vertices, oldvertex);
+      qh_degen_redundant_facet(qh, neighbor);
+    }
+    oldvertex->deleted= True;
+    qh_setappend(qh, &qh->del_vertices, oldvertex);
+  }else {
+    zinc_(Zrenamepinch);
+    if (istrace || qh->IStracing >= 1)
+      qh_fprintf(qh, qh->ferr, 3040, "qh_renamevertex: renaming pinched v%d to v%d between f%d and f%d\n",
+               oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
+    qh_setdelsorted(oldfacet->vertices, oldvertex);
+    qh_setdel(oldvertex->neighbors, oldfacet);
+    if (qh_remove_extravertices(qh, neighborA))
+      qh_degen_redundant_facet(qh, neighborA);
+  }
+  if (oldfacet)
+    qh_degen_redundant_facet(qh, oldfacet);
+} /* renamevertex */
+
+/*---------------------------------
+
+  qh_test_appendmerge(qh, facet, neighbor, simplicial )
+    test convexity and append to qh.facet_mergeset if non-convex
+    if pre-merging,
+      no-op if qh.SKIPconvex, or qh.MERGEexact and coplanar
+    if simplicial, assumes centrum test is valid (e.g., adjacent, simplicial new facets)
+
+  returns:
+    true if appends facet/neighbor to qh.facet_mergeset
+    sets facet->center as needed
+    does not change facet->seen
+
+  notes:
+    called from qh_getmergeset_initial, qh_getmergeset, and qh_test_vneighbors
+    must be at least as strong as qh_checkconvex (poly2_r.c)
+    assumes !f.flipped
+
+  design:
+    exit if qh.SKIPconvex ('Q0') and !qh.POSTmerging
+    if qh.cos_max ('An') is defined and merging coplanars
+      if the angle between facet normals is too shallow
+        append an angle-coplanar merge to qh.mergeset
+        return True
+    test convexity of facet and neighbor
+*/
+boolT qh_test_appendmerge(qhT *qh, facetT *facet, facetT *neighbor, boolT simplicial) {
+  realT angle= -REALmax;
+  boolT okangle= False;
+
+  if (qh->SKIPconvex && !qh->POSTmerging)
+    return False;
+  if (qh->cos_max < REALmax/2 && (!qh->MERGEexact || qh->POSTmerging)) {
+    angle= qh_getangle(qh, facet->normal, neighbor->normal);
+    okangle= True;
+    zinc_(Zangletests);
+    if (angle > qh->cos_max) {
+      zinc_(Zcoplanarangle);
+      qh_appendmergeset(qh, facet, neighbor, MRGanglecoplanar, 0.0, angle);
+      trace2((qh, qh->ferr, 2039, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
+         angle, facet->id, neighbor->id));
+      return True;
+    }
+  }
+  if (simplicial || qh->hull_dim <= 3)
+    return qh_test_centrum_merge(qh, facet, neighbor, angle, okangle);
+  else
+    return qh_test_nonsimplicial_merge(qh, facet, neighbor, angle, okangle);
+} /* test_appendmerge */
+
+/*---------------------------------
+
+  qh_test_centrum_merge(qh, facet, neighbor, angle, okangle )
+    test centrum convexity and append non-convex facets to qh.facet_mergeset
+    'angle' is angle between facets if okangle is true, otherwise use 0.0
+
+  returns:
+    true if append facet/neighbor to qh.facet_mergeset
+    sets facet->center as needed
+    does not change facet->seen
+
+  notes:
+    called from test_appendmerge if adjacent simplicial facets or 2-d/3-d
+    at least as strict as qh_checkconvex, including qh.DISTround ('En' and 'Rn')
+
+  design:
+    make facet's centrum if needed
+    if facet's centrum is above the neighbor (qh.centrum_radius)
+      set isconcave
+
+    if facet's centrum is not below the neighbor (-qh.centrum_radius)
+      set iscoplanar
+    make neighbor's centrum if needed
+    if neighbor's centrum is above the facet
+      set isconcave
+    else if neighbor's centrum is not below the facet
+      set iscoplanar
+    if isconcave or iscoplanar and merging coplanars
+      get angle if needed (qh.ANGLEmerge 'An')
+      append concave-coplanar, concave ,or coplanar merge to qh.mergeset
+*/
+boolT qh_test_centrum_merge(qhT *qh, facetT *facet, facetT *neighbor, realT angle, boolT okangle) {
+  coordT dist, dist2, mergedist;
+  boolT isconcave= False, iscoplanar= False;
+
+  if (!facet->center)
+    facet->center= qh_getcentrum(qh, facet);
+  zzinc_(Zcentrumtests);
+  qh_distplane(qh, facet->center, neighbor, &dist);
+  if (dist > qh->centrum_radius)
+    isconcave= True;
+  else if (dist >= -qh->centrum_radius)
+    iscoplanar= True;
+  if (!neighbor->center)
+    neighbor->center= qh_getcentrum(qh, neighbor);
+  zzinc_(Zcentrumtests);
+  qh_distplane(qh, neighbor->center, facet, &dist2);
+  if (dist2 > qh->centrum_radius)
+    isconcave= True;
+  else if (!iscoplanar && dist2 >= -qh->centrum_radius)
+    iscoplanar= True;
+  if (!isconcave && (!iscoplanar || (qh->MERGEexact && !qh->POSTmerging)))
+    return False;
+  if (!okangle && qh->ANGLEmerge) {
+    angle= qh_getangle(qh, facet->normal, neighbor->normal);
+    zinc_(Zangletests);
+  }
+  if (isconcave && iscoplanar) {
+    zinc_(Zconcavecoplanarridge);
+    if (dist > dist2)
+      qh_appendmergeset(qh, facet, neighbor, MRGconcavecoplanar, dist, angle);
+    else
+      qh_appendmergeset(qh, neighbor, facet, MRGconcavecoplanar, dist2, angle);
+    trace0((qh, qh->ferr, 36, "qh_test_centrum_merge: concave f%d to coplanar f%d, dist %4.4g and reverse dist %4.4g, angle %4.4g during p%d\n",
+           facet->id, neighbor->id, dist, dist2, angle, qh->furthest_id));
+  }else if (isconcave) {
+    mergedist= fmax_(dist, dist2);
+    zinc_(Zconcaveridge);
+    qh_appendmergeset(qh, facet, neighbor, MRGconcave, mergedist, angle);
+    trace0((qh, qh->ferr, 37, "qh_test_centrum_merge: concave f%d to f%d, dist %4.4g and reverse dist %4.4g, angle %4.4g during p%d\n",
+      facet->id, neighbor->id, dist, dist2, angle, qh->furthest_id));
+  }else /* iscoplanar */ {
+    mergedist= fmin_(fabs_(dist), fabs_(dist2));
+    zinc_(Zcoplanarcentrum);
+    qh_appendmergeset(qh, facet, neighbor, MRGcoplanar, mergedist, angle);
+    trace2((qh, qh->ferr, 2097, "qh_test_centrum_merge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
+              facet->id, neighbor->id, dist, dist2, angle));
+  }
+  return True;
+} /* test_centrum_merge */
+
+/*---------------------------------
+
+  qh_test_degen_neighbors(qh, facet )
+    append degenerate neighbors to qh.degen_mergeset
+
+  notes:
+  called at end of qh_mergefacet() and qh_renamevertex()
+  call after test_redundant_facet() since MRGredundant is less expensive then MRGdegen
+    a degenerate facet has fewer than hull_dim neighbors
+    see: qh_merge_degenredundant()
+
+*/
+void qh_test_degen_neighbors(qhT *qh, facetT *facet) {
+  facetT *neighbor, **neighborp;
+  int size;
+
+  trace4((qh, qh->ferr, 4073, "qh_test_degen_neighbors: test for degenerate neighbors of f%d\n", facet->id));
+  FOREACHneighbor_(facet) {
+    if (neighbor->visible) {
+      qh_fprintf(qh, qh->ferr, 6359, "qhull internal error (qh_test_degen_neighbors): facet f%d has deleted neighbor f%d (qh.visible_list)\n",
+        facet->id, neighbor->id);
+      qh_errexit2(qh, qh_ERRqhull, facet, neighbor);
+    }
+    if (neighbor->degenerate || neighbor->redundant || neighbor->dupridge) /* will merge or delete */
+      continue;
+    /* merge flipped-degenerate facet before flipped facets */
+    if ((size= qh_setsize(qh, neighbor->neighbors)) < qh->hull_dim) {
+      qh_appendmergeset(qh, neighbor, neighbor, MRGdegen, 0.0, 1.0);
+      trace2((qh, qh->ferr, 2019, "qh_test_degen_neighbors: f%d is degenerate with %d neighbors.  Neighbor of f%d.\n", neighbor->id, size, facet->id));
+    }
+  }
+} /* test_degen_neighbors */
+
+
+/*---------------------------------
+
+  qh_test_nonsimplicial_merge(qh, facet, neighbor, angle, okangle )
+    test centrum and vertex convexity and append non-convex or redundant facets to qh.facet_mergeset
+    'angle' is angle between facets if okangle is true, otherwise use 0.0
+    skips coplanar merges if pre-merging with qh.MERGEexact ('Qx')
+
+  returns:
+    true if appends facet/neighbor to qh.facet_mergeset
+    sets facet->center as needed
+    does not change facet->seen
+
+  notes:
+    only called from test_appendmerge if a non-simplicial facet and at least 4-d
+    at least as strict as qh_checkconvex, including qh.DISTround ('En' and 'Rn')
+      centrums must be < -qh.centrum_radius
+    tests vertices as well as centrums since a facet may be twisted relative to its neighbor
+
+  design:
+    set precision constants for maxoutside, clearlyconcave, minvertex, and coplanarcentrum
+      use maxoutside for coplanarcentrum if premerging with 'Qx' and qh_MAXcoplanarcentrum merges
+      otherwise use qh.centrum_radious for coplanarcentrum
+    make facet and neighbor centrums if needed
+    isconcave if a centrum is above neighbor (coplanarcentrum)
+    iscoplanar if a centrum is not below neighbor (-qh.centrum_radius)
+    maybeconvex if a centrum is clearly below neighbor (-clearyconvex)
+    return False if both centrums clearly below neighbor (-clearyconvex)
+    return MRGconcave if isconcave
+
+    facets are neither clearly convex nor clearly concave
+    test vertices as well as centrums
+    if maybeconvex
+      determine mindist and maxdist for vertices of the other facet
+      maybe MRGredundant
+    otherwise
+      determine mindist and maxdist for vertices of either facet
+      maybe MRGredundant
+      maybeconvex if a vertex is clearly below neighbor (-clearconvex)
+
+    vertices are concave if dist > clearlyconcave
+    vertices are twisted if dist > maxoutside (isconcave and maybeconvex)
+    return False if not concave and pre-merge of 'Qx' (qh.MERGEexact)
+    vertices are coplanar if dist in -minvertex..maxoutside
+    if !isconcave, vertices are coplanar if dist >= -qh.MAXcoplanar (n*qh.premerge_centrum)
+
+    return False if neither concave nor coplanar
+    return MRGtwisted if isconcave and maybeconvex
+    return MRGconcavecoplanar if isconcave and isconvex
+    return MRGconcave if isconcave
+    return MRGcoplanar if iscoplanar
+*/
+boolT qh_test_nonsimplicial_merge(qhT *qh, facetT *facet, facetT *neighbor, realT angle, boolT okangle) {
+  coordT dist, mindist, maxdist, mindist2, maxdist2, dist2, maxoutside, clearlyconcave, minvertex, clearlyconvex, mergedist, coplanarcentrum;
+  boolT isconcave= False, iscoplanar= False, maybeconvex= False, isredundant= False;
+  vertexT *maxvertex= NULL, *maxvertex2= NULL;
+
+  maxoutside= fmax_(neighbor->maxoutside, qh->ONEmerge + qh->DISTround);
+  maxoutside= fmax_(maxoutside, facet->maxoutside);
+  clearlyconcave= qh_RATIOconcavehorizon * maxoutside;
+  minvertex= fmax_(-qh->min_vertex, qh->MAXcoplanar); /* non-negative, not available per facet, not used for iscoplanar */
+  clearlyconvex= qh_RATIOconvexmerge * minvertex; /* must be convex for MRGtwisted */
+  if (qh->MERGEexact && !qh->POSTmerging && (facet->nummerge > qh_MAXcoplanarcentrum || neighbor->nummerge > qh_MAXcoplanarcentrum))
+    coplanarcentrum= maxoutside;
+  else
+    coplanarcentrum= qh->centrum_radius;
+
+  if (!facet->center)
+    facet->center= qh_getcentrum(qh, facet);
+  zzinc_(Zcentrumtests);
+  qh_distplane(qh, facet->center, neighbor, &dist);
+  if (dist > coplanarcentrum)
+    isconcave= True;
+  else if (dist >= -qh->centrum_radius)
+    iscoplanar= True;
+  else if (dist < -clearlyconvex)
+    maybeconvex= True;
+  if (!neighbor->center)
+    neighbor->center= qh_getcentrum(qh, neighbor);
+  zzinc_(Zcentrumtests);
+  qh_distplane(qh, neighbor->center, facet, &dist2);
+  if (dist2 > coplanarcentrum)
+    isconcave= True;
+  else if (dist2 >= -qh->centrum_radius)
+    iscoplanar= True;
+  else if (dist2 < -clearlyconvex) {
+    if (maybeconvex)
+      return False; /* both centrums clearly convex */
+    maybeconvex= True;
+  }
+  if (isconcave) {
+    if (!okangle && qh->ANGLEmerge) {
+      angle= qh_getangle(qh, facet->normal, neighbor->normal);
+      zinc_(Zangletests);
+    }
+    mergedist= fmax_(dist, dist2);
+    zinc_(Zconcaveridge);
+    qh_appendmergeset(qh, facet, neighbor, MRGconcave, mergedist, angle);
+    trace0((qh, qh->ferr, 18, "qh_test_nonsimplicial_merge: concave centrum for f%d or f%d, dist %4.4g and reverse dist %4.4g, angle %4.4g during p%d\n",
+      facet->id, neighbor->id, dist, dist2, angle, qh->furthest_id));
+    return True;
+  }
+  /* neither clearly convex nor clearly concave, test vertices as well as centrums */
+  if (maybeconvex) {
+    if (dist < -clearlyconvex) {
+      maxdist= dist;  /* facet centrum clearly convex, no need to test its vertex distance */
+      mindist= dist;
+      maxvertex2= qh_furthestvertex(qh, neighbor, facet, &maxdist2, &mindist2);
+      if (!maxvertex2) {
+        qh_appendmergeset(qh, neighbor, facet, MRGredundant, maxdist2, qh_ANGLEnone);
+        isredundant= True;
+      }
+    }else { /* dist2 < -clearlyconvex */
+      maxdist2= dist2;   /* neighbor centrum clearly convex, no need to test its vertex distance */
+      mindist2= dist2;
+      maxvertex= qh_furthestvertex(qh, facet, neighbor, &maxdist, &mindist);
+      if (!maxvertex) {
+        qh_appendmergeset(qh, facet, neighbor, MRGredundant, maxdist, qh_ANGLEnone);
+        isredundant= True;
+      }
+    }
+  }else {
+    maxvertex= qh_furthestvertex(qh, facet, neighbor, &maxdist, &mindist);
+    if (maxvertex) {
+      maxvertex2= qh_furthestvertex(qh, neighbor, facet, &maxdist2, &mindist2);
+      if (!maxvertex2) {
+        qh_appendmergeset(qh, neighbor, facet, MRGredundant, maxdist2, qh_ANGLEnone);
+        isredundant= True;
+      }else if (mindist < -clearlyconvex || mindist2 < -clearlyconvex)
+        maybeconvex= True;
+    }else { /* !maxvertex */
+      qh_appendmergeset(qh, facet, neighbor, MRGredundant, maxdist, qh_ANGLEnone);
+      isredundant= True;
+    }
+  }
+  if (isredundant) {
+    zinc_(Zredundantmerge);
+    return True;
+  }
+
+  if (maxdist > clearlyconcave || maxdist2 > clearlyconcave)
+    isconcave= True;
+  else if (maybeconvex) {
+    if (maxdist > maxoutside || maxdist2 > maxoutside)
+      isconcave= True;  /* MRGtwisted */
+  }
+  if (!isconcave && qh->MERGEexact && !qh->POSTmerging)
+    return False;
+  if (isconcave && !iscoplanar) {
+    if (maxdist < maxoutside && (-qh->MAXcoplanar || (maxdist2 < maxoutside && mindist2 >= -qh->MAXcoplanar)))
+      iscoplanar= True; /* MRGconcavecoplanar */
+  }else if (!iscoplanar) {
+    if (mindist >= -qh->MAXcoplanar || mindist2 >= -qh->MAXcoplanar)
+      iscoplanar= True;  /* MRGcoplanar */
+  }
+  if (!isconcave && !iscoplanar)
+    return False;
+  if (!okangle && qh->ANGLEmerge) {
+    angle= qh_getangle(qh, facet->normal, neighbor->normal);
+    zinc_(Zangletests);
+  }
+  if (isconcave && maybeconvex) {
+    zinc_(Ztwistedridge);
+    if (maxdist > maxdist2)
+      qh_appendmergeset(qh, facet, neighbor, MRGtwisted, maxdist, angle);
+    else
+      qh_appendmergeset(qh, neighbor, facet, MRGtwisted, maxdist2, angle);
+    trace0((qh, qh->ferr, 27, "qh_test_nonsimplicial_merge: twisted concave f%d v%d to f%d v%d, dist %4.4g and reverse dist %4.4g, angle %4.4g during p%d\n",
+           facet->id, getid_(maxvertex), neighbor->id, getid_(maxvertex2), maxdist, maxdist2, angle, qh->furthest_id));
+  }else if (isconcave && iscoplanar) {
+    zinc_(Zconcavecoplanarridge);
+    if (maxdist > maxdist2)
+      qh_appendmergeset(qh, facet, neighbor, MRGconcavecoplanar, maxdist, angle);
+    else
+      qh_appendmergeset(qh, neighbor, facet, MRGconcavecoplanar, maxdist2, angle);
+    trace0((qh, qh->ferr, 28, "qh_test_nonsimplicial_merge: concave coplanar f%d v%d to f%d v%d, dist %4.4g and reverse dist %4.4g, angle %4.4g during p%d\n",
+      facet->id, getid_(maxvertex), neighbor->id, getid_(maxvertex2), maxdist, maxdist2, angle, qh->furthest_id));
+  }else if (isconcave) {
+    mergedist= fmax_(maxdist, maxdist2);
+    zinc_(Zconcaveridge);
+    qh_appendmergeset(qh, facet, neighbor, MRGconcave, mergedist, angle);
+    trace0((qh, qh->ferr, 29, "qh_test_nonsimplicial_merge: concave f%d v%d to f%d v%d, dist %4.4g and reverse dist %4.4g, angle %4.4g during p%d\n",
+      facet->id, getid_(maxvertex), neighbor->id, getid_(maxvertex2), maxdist, maxdist2, angle, qh->furthest_id));
+  }else /* iscoplanar */ {
+    mergedist= fmax_(fmax_(maxdist, maxdist2), fmax_(-mindist, -mindist2));
+    zinc_(Zcoplanarcentrum);
+    qh_appendmergeset(qh, facet, neighbor, MRGcoplanar, mergedist, angle);
+    trace2((qh, qh->ferr, 2099, "qh_test_nonsimplicial_merge: coplanar f%d v%d to f%d v%d, dist %4.4g and reverse dist %4.4g, angle %4.4g during p%d\n",
+      facet->id, getid_(maxvertex), neighbor->id, getid_(maxvertex2), maxdist, maxdist2, angle, qh->furthest_id));
+  }
+  return True;
+} /* test_nonsimplicial_merge */
+
+/*---------------------------------
+
+  qh_test_redundant_neighbors(qh, facet )
+    append degenerate facet or its redundant neighbors to qh.degen_mergeset
+
+  returns:
+    bumps vertex_visit
+
+  notes:
+    called at end of qh_mergefacet(), qh_mergecycle_all(), and qh_renamevertex
+    call before qh_test_degen_neighbors (MRGdegen are more likely to cause problems)
+    a redundant neighbor's vertices is a subset of the facet's vertices
+    with pinched and flipped facets, a redundant neighbor may have a wildly different normal
+
+    see qh_merge_degenredundant() and qh_-_facet()
+
+  design:
+    if facet is degenerate
+       appends facet to degen_mergeset
+    else
+       appends redundant neighbors of facet to degen_mergeset
+*/
+void qh_test_redundant_neighbors(qhT *qh, facetT *facet) {
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+  int size;
+
+  trace4((qh, qh->ferr, 4022, "qh_test_redundant_neighbors: test neighbors of f%d vertex_visit %d\n",
+          facet->id, qh->vertex_visit+1));
+  if ((size= qh_setsize(qh, facet->neighbors)) < qh->hull_dim) {
+    qh_appendmergeset(qh, facet, facet, MRGdegen, 0.0, 1.0);
+    trace2((qh, qh->ferr, 2017, "qh_test_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
+  }else {
+    qh->vertex_visit++;
+    FOREACHvertex_(facet->vertices)
+      vertex->visitid= qh->vertex_visit;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visible) {
+        qh_fprintf(qh, qh->ferr, 6360, "qhull internal error (qh_test_redundant_neighbors): facet f%d has deleted neighbor f%d (qh.visible_list)\n",
+          facet->id, neighbor->id);
+        qh_errexit2(qh, qh_ERRqhull, facet, neighbor);
+      }
+      if (neighbor->degenerate || neighbor->redundant || neighbor->dupridge) /* will merge or delete */
+        continue;
+      if (facet->flipped && !neighbor->flipped) /* do not merge non-flipped into flipped */
+        continue;
+      /* merge redundant-flipped facet first */
+      /* uses early out instead of checking vertex count */
+      FOREACHvertex_(neighbor->vertices) {
+        if (vertex->visitid != qh->vertex_visit)
+          break;
+      }
+      if (!vertex) {
+        qh_appendmergeset(qh, neighbor, facet, MRGredundant, 0.0, 1.0);
+        trace2((qh, qh->ferr, 2018, "qh_test_redundant_neighbors: f%d is contained in f%d.  merge\n", neighbor->id, facet->id));
+      }
+    }
+  }
+} /* test_redundant_neighbors */
+
+/*---------------------------------
+
+  qh_test_vneighbors(qh)
+    test vertex neighbors for convexity
+    tests all facets on qh.newfacet_list
+
+  returns:
+    true if non-convex vneighbors appended to qh.facet_mergeset
+    initializes vertex neighbors if needed
+
+  notes:
+    called by qh_all_merges from qh_postmerge if qh.TESTvneighbors ('Qv')
+    assumes all facet neighbors have been tested
+    this can be expensive
+    this does not guarantee that a centrum is below all facets
+      but it is unlikely
+    uses qh.visit_id
+
+  design:
+    build vertex neighbors if necessary
+    for all new facets
+      for all vertices
+        for each unvisited facet neighbor of the vertex
+          test new facet and neighbor for convexity
+*/
+boolT qh_test_vneighbors(qhT *qh /* qh.newfacet_list */) {
+  facetT *newfacet, *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  int nummerges= 0;
+
+  trace1((qh, qh->ferr, 1015, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
+  if (!qh->VERTEXneighbors)
+    qh_vertexneighbors(qh);
+  FORALLnew_facets
+    newfacet->seen= False;
+  FORALLnew_facets {
+    newfacet->seen= True;
+    newfacet->visitid= qh->visit_id++;
+    FOREACHneighbor_(newfacet)
+      newfacet->visitid= qh->visit_id;
+    FOREACHvertex_(newfacet->vertices) {
+      FOREACHneighbor_(vertex) {
+        if (neighbor->seen || neighbor->visitid == qh->visit_id)
+          continue;
+        if (qh_test_appendmerge(qh, newfacet, neighbor, False)) /* ignores optimization for simplicial ridges */
+          nummerges++;
+      }
+    }
+  }
+  zadd_(Ztestvneighbor, nummerges);
+  trace1((qh, qh->ferr, 1016, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
+           nummerges));
+  return (nummerges > 0);
+} /* test_vneighbors */
+
+/*---------------------------------
+
+  qh_tracemerge(qh, facet1, facet2 )
+    print trace message after merge
+*/
+void qh_tracemerge(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype) {
+  boolT waserror= False;
+  const char *mergename;
+
+#ifndef qh_NOtrace
+  if(mergetype > 0 && mergetype < sizeof(mergetypes)/sizeof(char *))
+    mergename= mergetypes[mergetype];
+  else
+    mergename= mergetypes[MRGnone];
+  if (qh->IStracing >= 4)
+    qh_errprint(qh, "MERGED", facet2, NULL, NULL, NULL);
+  if (facet2 == qh->tracefacet || (qh->tracevertex && qh->tracevertex->newfacet)) {
+    qh_fprintf(qh, qh->ferr, 8085, "qh_tracemerge: trace facet and vertex after merge of f%d into f%d type %d (%s), furthest p%d\n",
+      facet1->id, facet2->id, mergetype, mergename, qh->furthest_id);
+    if (facet2 != qh->tracefacet)
+      qh_errprint(qh, "TRACE", qh->tracefacet,
+        (qh->tracevertex && qh->tracevertex->neighbors) ?
+           SETfirstt_(qh->tracevertex->neighbors, facetT) : NULL,
+        NULL, qh->tracevertex);
+  }
+  if (qh->tracevertex) {
+    if (qh->tracevertex->deleted)
+      qh_fprintf(qh, qh->ferr, 8086, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
+            qh->furthest_id);
+    else
+      qh_checkvertex(qh, qh->tracevertex, qh_ALL, &waserror);
+  }
+  if (qh->tracefacet && qh->tracefacet->normal && !qh->tracefacet->visible)
+    qh_checkfacet(qh, qh->tracefacet, True /* newmerge */, &waserror);
+#endif /* !qh_NOtrace */
+  if (qh->CHECKfrequently || qh->IStracing >= 4) { /* can't check polygon here */
+    if (qh->IStracing >= 4 && qh->num_facets < 500) {
+      qh_printlists(qh);
+    }
+    qh_checkfacet(qh, facet2, True /* newmerge */, &waserror);
+  }
+  if (waserror)
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL); /* erroneous facet logged by qh_checkfacet */
+} /* tracemerge */
+
+/*---------------------------------
+
+  qh_tracemerging(qh)
+    print trace message during POSTmerging
+
+  returns:
+    updates qh.mergereport
+
+  notes:
+    called from qh_mergecycle() and qh_mergefacet()
+
+  see:
+    qh_buildtracing()
+*/
+void qh_tracemerging(qhT *qh) {
+  realT cpu;
+  int total;
+  time_t timedata;
+  struct tm *tp;
+
+  qh->mergereport= zzval_(Ztotmerge);
+  time(&timedata);
+  tp= localtime(&timedata);
+  cpu= qh_CPUclock;
+  cpu /= qh_SECticks;
+  total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+  qh_fprintf(qh, qh->ferr, 8087, "\n\
+At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets with max_outside %2.2g, min_vertex %2.2g.\n\
+  The hull contains %d facets and %d vertices.\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, total, qh->max_outside, qh->min_vertex,
+      qh->num_facets - qh->num_visible,
+      qh->num_vertices-qh_setsize(qh, qh->del_vertices));
+} /* tracemerging */
+
+/*---------------------------------
+
+  qh_updatetested(qh, facet1, facet2 )
+    clear facet2->tested and facet1->ridge->tested for merge
+
+  returns:
+    deletes facet2->center unless it's already large
+      if so, clears facet2->ridge->tested
+
+  notes:
+    only called by qh_mergefacet
+
+  design:
+    clear facet2->tested
+    clear ridge->tested for facet1's ridges
+    if facet2 has a centrum
+      if facet2 is large
+        set facet2->keepcentrum
+      else if facet2 has 3 vertices due to many merges, or not large and post merging
+        clear facet2->keepcentrum
+      unless facet2->keepcentrum
+        clear facet2->center to recompute centrum later
+        clear ridge->tested for facet2's ridges
+*/
+void qh_updatetested(qhT *qh, facetT *facet1, facetT *facet2) {
+  ridgeT *ridge, **ridgep;
+  int size;
+
+  facet2->tested= False;
+  FOREACHridge_(facet1->ridges)
+    ridge->tested= False;
+  if (!facet2->center)
+    return;
+  size= qh_setsize(qh, facet2->vertices);
+  if (!facet2->keepcentrum) {
+    if (size > qh->hull_dim + qh_MAXnewcentrum) {
+      facet2->keepcentrum= True;
+      zinc_(Zwidevertices);
+    }
+  }else if (size <= qh->hull_dim + qh_MAXnewcentrum) {
+    /* center and keepcentrum was set */
+    if (size == qh->hull_dim || qh->POSTmerging)
+      facet2->keepcentrum= False; /* if many merges need to recompute centrum */
+  }
+  if (!facet2->keepcentrum) {
+    qh_memfree(qh, facet2->center, qh->normal_size);
+    facet2->center= NULL;
+    FOREACHridge_(facet2->ridges)
+      ridge->tested= False;
+  }
+} /* updatetested */
+
+/*---------------------------------
+
+  qh_vertexridges(qh, vertex, allneighbors )
+    return temporary set of ridges adjacent to a vertex
+    vertex->neighbors defined (qh_vertexneighbors)
+
+  notes:
+    uses qh.visit_id
+    does not include implicit ridges for simplicial facets
+    skips last neighbor, unless allneighbors.  For new facets, the last neighbor shares ridges with adjacent neighbors
+    if the last neighbor is not simplicial, it will have ridges for its simplicial neighbors
+    Use allneighbors when a new cone is attached to an existing convex hull
+    similar to qh_neighbor_vertices
+
+  design:
+    for each neighbor of vertex
+      add ridges that include the vertex to ridges
+*/
+setT *qh_vertexridges(qhT *qh, vertexT *vertex, boolT allneighbors) {
+  facetT *neighbor, **neighborp;
+  setT *ridges= qh_settemp(qh, qh->TEMPsize);
+  int size;
+
+  qh->visit_id += 2;  /* visit_id for vertex neighbors, visit_id-1 for facets of visited ridges */
+  FOREACHneighbor_(vertex)
+    neighbor->visitid= qh->visit_id;
+  FOREACHneighbor_(vertex) {
+    if (*neighborp || allneighbors)   /* no new ridges in last neighbor */
+      qh_vertexridges_facet(qh, vertex, neighbor, &ridges);
+  }
+  if (qh->PRINTstatistics || qh->IStracing) {
+    size= qh_setsize(qh, ridges);
+    zinc_(Zvertexridge);
+    zadd_(Zvertexridgetot, size);
+    zmax_(Zvertexridgemax, size);
+    trace3((qh, qh->ferr, 3011, "qh_vertexridges: found %d ridges for v%d\n",
+             size, vertex->id));
+  }
+  return ridges;
+} /* vertexridges */
+
+/*---------------------------------
+
+  qh_vertexridges_facet(qh, vertex, facet, ridges )
+    add adjacent ridges for vertex in facet
+    neighbor->visitid==qh.visit_id if it hasn't been visited
+
+  returns:
+    ridges updated
+    sets facet->visitid to qh.visit_id-1
+
+  design:
+    for each ridge of facet
+      if ridge of visited neighbor (i.e., unprocessed)
+        if vertex in ridge
+          append ridge
+    mark facet processed
+*/
+void qh_vertexridges_facet(qhT *qh, vertexT *vertex, facetT *facet, setT **ridges) {
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor;
+  int last_i= qh->hull_dim-2;
+  vertexT *second, *last;
+
+  FOREACHridge_(facet->ridges) {
+    neighbor= otherfacet_(ridge, facet);
+    if (neighbor->visitid == qh->visit_id) {
+      if (SETfirst_(ridge->vertices) == vertex) {
+        qh_setappend(qh, ridges, ridge);
+      }else if (last_i > 2) {
+        second= SETsecondt_(ridge->vertices, vertexT);
+        last= SETelemt_(ridge->vertices, last_i, vertexT);
+        if (second->id >= vertex->id && last->id <= vertex->id) { /* vertices inverse sorted by id */
+          if (second == vertex || last == vertex)
+            qh_setappend(qh, ridges, ridge);
+          else if (qh_setin(ridge->vertices, vertex))
+            qh_setappend(qh, ridges, ridge);
+        }
+      }else if (SETelem_(ridge->vertices, last_i) == vertex
+          || (last_i > 1 && SETsecond_(ridge->vertices) == vertex)) {
+        qh_setappend(qh, ridges, ridge);
+      }
+    }
+  }
+  facet->visitid= qh->visit_id-1;
+} /* vertexridges_facet */
+
+/*---------------------------------
+
+  qh_willdelete(qh, facet, replace )
+    moves facet to visible list for qh_deletevisible
+    sets facet->f.replace to replace (may be NULL)
+    clears f.ridges and f.neighbors -- no longer valid
+
+  returns:
+    bumps qh.num_visible
+*/
+void qh_willdelete(qhT *qh, facetT *facet, facetT *replace) {
+
+  trace4((qh, qh->ferr, 4081, "qh_willdelete: move f%d to visible list, set its replacement as f%d, and clear f.neighbors and f.ridges\n", facet->id, getid_(replace)));
+  if (!qh->visible_list && qh->newfacet_list) {
+    qh_fprintf(qh, qh->ferr, 6378, "qhull internal error (qh_willdelete): expecting qh.visible_list at before qh.newfacet_list f%d.   Got NULL\n",
+        qh->newfacet_list->id);
+    qh_errexit2(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh_removefacet(qh, facet);
+  qh_prependfacet(qh, facet, &qh->visible_list);
+  qh->num_visible++;
+  facet->visible= True;
+  facet->f.replace= replace;
+  if (facet->ridges)
+    SETfirst_(facet->ridges)= NULL;
+  if (facet->neighbors)
+    SETfirst_(facet->neighbors)= NULL;
+} /* willdelete */
+
+#else /* qh_NOmerge */
+
+void qh_all_vertexmerges(qhT *qh, int apexpointid, facetT *facet, facetT **retryfacet) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(apexpointid)
+  QHULL_UNUSED(facet)
+  QHULL_UNUSED(retryfacet)
+}
+void qh_premerge(qhT *qh, int apexpointid, realT maxcentrum, realT maxangle) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(apexpointid)
+  QHULL_UNUSED(maxcentrum)
+  QHULL_UNUSED(maxangle)
+}
+void qh_postmerge(qhT *qh, const char *reason, realT maxcentrum, realT maxangle,
+                      boolT vneighbors) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(reason)
+  QHULL_UNUSED(maxcentrum)
+  QHULL_UNUSED(maxangle)
+  QHULL_UNUSED(vneighbors)
+}
+void qh_checkdelfacet(qhT *qh, facetT *facet, setT *mergeset) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(facet)
+  QHULL_UNUSED(mergeset)
+}
+void qh_checkdelridge(qhT *qh /* qh.visible_facets, vertex_mergeset */) {
+  QHULL_UNUSED(qh)
+}
+boolT qh_checkzero(qhT *qh, boolT testall) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(testall)
+
+  return True;
+}
+void qh_freemergesets(qhT *qh) {
+  QHULL_UNUSED(qh)
+}
+void qh_initmergesets(qhT *qh) {
+  QHULL_UNUSED(qh)
+}
+void qh_merge_pinchedvertices(qhT *qh, int apexpointid /* qh.newfacet_list */) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(apexpointid)
+}
+#endif /* qh_NOmerge */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.h
new file mode 100644
index 00000000000..a0d4091ec87
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/merge_r.h
@@ -0,0 +1,238 @@
+/*
  ---------------------------------
+
+   merge_r.h
+   header file for merge_r.c
+
+   see qh-merge_r.htm and merge_r.c
+
+   Copyright (c) 1993-2020 C.B. Barber.
+   $Id: //main/2019/qhull/src/libqhull_r/merge_r.h#2 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#ifndef qhDEFmerge
+#define qhDEFmerge 1
+
+#include "libqhull_r.h"
+
+
+/*============ -constants- ==============*/
+
+/*----------------------------------
+
+  qh_ANGLEnone
+    indicates missing angle for mergeT->angle
+*/
+#define qh_ANGLEnone 2.0
+
+/*----------------------------------
+
+  MRG... (mergeType)
+    indicates the type of a merge (mergeT->type)
+    MRGcoplanar...MRGtwisted set by qh_test_centrum_merge, qh_test_nonsimplicial_merge
+*/
+typedef enum {  /* must match mergetypes[] */
+  MRGnone= 0,
+                  /* MRGcoplanar..MRGtwisted go into qh.facet_mergeset for qh_all_merges 
+                     qh_compare_facetmerge selects lower mergetypes for merging first */
+  MRGcoplanar,          /* (1) centrum coplanar if centrum ('Cn') or vertex not clearly above or below neighbor */
+  MRGanglecoplanar,     /* (2) angle coplanar if angle ('An') is coplanar */
+  MRGconcave,           /* (3) concave ridge */
+  MRGconcavecoplanar,   /* (4) concave and coplanar ridge, one side concave, other side coplanar */
+  MRGtwisted,           /* (5) twisted ridge, both concave and convex, facet1 is wider */
+                  /* MRGflip go into qh.facet_mergeset for qh_flipped_merges */
+  MRGflip,              /* (6) flipped facet if qh.interior_point is above facet, w/ facet1 == facet2 */
+                  /* MRGdupridge go into qh.facet_mergeset for qh_forcedmerges */
+  MRGdupridge,          /* (7) dupridge if more than two neighbors.  Set by qh_mark_dupridges for qh_MERGEridge */
+                  /* MRGsubridge and MRGvertices go into vertex_mergeset */
+  MRGsubridge,          /* (8) merge pinched vertex to remove the subridge of a MRGdupridge */
+  MRGvertices,          /* (9) merge pinched vertex to remove a facet's ridges with the same vertices */
+                  /* MRGdegen, MRGredundant, and MRGmirror go into qh.degen_mergeset */
+  MRGdegen,             /* (10) degenerate facet (!enough neighbors) facet1 == facet2 */
+  MRGredundant,         /* (11) redundant facet (vertex subset) */
+                        /* merge_degenredundant assumes degen < redundant */
+  MRGmirror,            /* (12) mirror facets: same vertices due to null facets in qh_triangulate 
+                           f.redundant for both facets*/
+                  /* MRGcoplanarhorizon for qh_mergecycle_all only */
+  MRGcoplanarhorizon,   /* (13) new facet coplanar with the horizon (qh_mergecycle_all) */
+  ENDmrg
+} mergeType;
+
+/*----------------------------------
+
+  qh_MERGEapex
+    flag for qh_mergefacet() to indicate an apex merge
+*/
+#define qh_MERGEapex     True
+
+/*============ -structures- ====================*/
+
+/*----------------------------------
+
+  mergeT
+    structure used to merge facets
+*/
+
+typedef struct mergeT mergeT;
+struct mergeT {         /* initialize in qh_appendmergeset */
+  realT   angle;        /* cosine of angle between normals of facet1 and facet2, 
+                           null value and right angle is 0.0, coplanar is 1.0, narrow is -1.0 */
+  realT   distance;     /* absolute value of distance between vertices, centrum and facet, or vertex and facet */
+  facetT *facet1;       /* will merge facet1 into facet2 */
+  facetT *facet2;
+  vertexT *vertex1;     /* will merge vertext1 into vertex2 for MRGsubridge or MRGvertices */
+  vertexT *vertex2;
+  ridgeT  *ridge1;      /* the duplicate ridges resolved by MRGvertices */
+  ridgeT  *ridge2;      /* merge is deleted if either ridge is deleted (qh_delridge) */
+  mergeType mergetype;
+};
+
+
+/*=========== -macros- =========================*/
+
+/*----------------------------------
+
+  FOREACHmerge_( merges ) {...}
+    assign 'merge' to each merge in merges
+
+  notes:
+    uses 'mergeT *merge, **mergep;'
+    if qh_mergefacet(),
+      restart or use qh_setdellast() since qh.facet_mergeset may change
+    see FOREACHsetelement_
+*/
+#define FOREACHmerge_(merges) FOREACHsetelement_(mergeT, merges, merge)
+
+/*----------------------------------
+
+  FOREACHmergeA_( vertices ) { ... }
+    assign 'mergeA' to each merge in merges
+
+  notes:
+    uses 'mergeT *mergeA, *mergeAp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHmergeA_(merges) FOREACHsetelement_(mergeT, merges, mergeA)
+
+/*----------------------------------
+
+  FOREACHmerge_i_(qh, vertices ) { ... }
+    assign 'merge' and 'merge_i' for each merge in mergeset
+
+  declare:
+    mergeT *merge;
+    int     merge_n, merge_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHmerge_i_(qh, mergeset) FOREACHsetelement_i_(qh, mergeT, mergeset, merge)
+
+/*============ prototypes in alphabetical order after pre/postmerge =======*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    qh_premerge(qhT *qh, int apexpointid, realT maxcentrum, realT maxangle);
+void    qh_postmerge(qhT *qh, const char *reason, realT maxcentrum, realT maxangle,
+             boolT vneighbors);
+void    qh_all_merges(qhT *qh, boolT othermerge, boolT vneighbors);
+void    qh_all_vertexmerges(qhT *qh, int apexpointid, facetT *facet, facetT **retryfacet);
+void    qh_appendmergeset(qhT *qh, facetT *facet, facetT *neighbor, mergeType mergetype, coordT dist, realT angle);
+void    qh_appendvertexmerge(qhT *qh, vertexT *vertex, vertexT *destination, mergeType mergetype, realT distance, ridgeT *ridge1, ridgeT *ridge2);
+setT   *qh_basevertices(qhT *qh, facetT *samecycle);
+void    qh_check_dupridge(qhT *qh, facetT *facet1, realT dist1, facetT *facet2, realT dist2);
+void    qh_checkconnect(qhT *qh /* qh.new_facets */);
+void    qh_checkdelfacet(qhT *qh, facetT *facet, setT *mergeset);
+void    qh_checkdelridge(qhT *qh /* qh.visible_facets, vertex_mergeset */);
+boolT   qh_checkzero(qhT *qh, boolT testall);
+int     qh_compare_anglemerge(const void *p1, const void *p2);
+int     qh_compare_facetmerge(const void *p1, const void *p2);
+int     qh_comparevisit(const void *p1, const void *p2);
+void    qh_copynonconvex(qhT *qh, ridgeT *atridge);
+void    qh_degen_redundant_facet(qhT *qh, facetT *facet);
+void    qh_drop_mergevertex(qhT *qh, mergeT *merge);
+void    qh_delridge_merge(qhT *qh, ridgeT *ridge);
+vertexT *qh_find_newvertex(qhT *qh, vertexT *oldvertex, setT *vertices, setT *ridges);
+vertexT *qh_findbest_pinchedvertex(qhT *qh, mergeT *merge, vertexT *apex, vertexT **pinchedp, realT *distp /* qh.newfacet_list */);
+vertexT *qh_findbest_ridgevertex(qhT *qh, ridgeT *ridge, vertexT **pinchedp, coordT *distp);
+void    qh_findbest_test(qhT *qh, boolT testcentrum, facetT *facet, facetT *neighbor,
+           facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
+facetT *qh_findbestneighbor(qhT *qh, facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
+void    qh_flippedmerges(qhT *qh, facetT *facetlist, boolT *wasmerge);
+void    qh_forcedmerges(qhT *qh, boolT *wasmerge);
+void    qh_freemergesets(qhT *qh);
+void    qh_getmergeset(qhT *qh, facetT *facetlist);
+void    qh_getmergeset_initial(qhT *qh, facetT *facetlist);
+boolT   qh_getpinchedmerges(qhT *qh, vertexT *apex, coordT maxdupdist, boolT *iscoplanar /* qh.newfacet_list, vertex_mergeset */);
+boolT   qh_hasmerge(setT *mergeset, mergeType type, facetT *facetA, facetT *facetB);
+void    qh_hashridge(qhT *qh, setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
+ridgeT *qh_hashridge_find(qhT *qh, setT *hashtable, int hashsize, ridgeT *ridge,
+              vertexT *vertex, vertexT *oldvertex, int *hashslot);
+void    qh_initmergesets(qhT *qh);
+void    qh_makeridges(qhT *qh, facetT *facet);
+void    qh_mark_dupridges(qhT *qh, facetT *facetlist, boolT allmerges);
+void    qh_maybe_duplicateridge(qhT *qh, ridgeT *ridge);
+void    qh_maybe_duplicateridges(qhT *qh, facetT *facet);
+void    qh_maydropneighbor(qhT *qh, facetT *facet);
+int     qh_merge_degenredundant(qhT *qh);
+void    qh_merge_nonconvex(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype);
+void    qh_merge_pinchedvertices(qhT *qh, int apexpointid /* qh.newfacet_list */);
+void    qh_merge_twisted(qhT *qh, facetT *facet1, facetT *facet2);
+void    qh_mergecycle(qhT *qh, facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_all(qhT *qh, facetT *facetlist, boolT *wasmerge);
+void    qh_mergecycle_facets(qhT *qh, facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_neighbors(qhT *qh, facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_ridges(qhT *qh, facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_vneighbors(qhT *qh, facetT *samecycle, facetT *newfacet);
+void    qh_mergefacet(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype, realT *mindist, realT *maxdist, boolT mergeapex);
+void    qh_mergefacet2d(qhT *qh, facetT *facet1, facetT *facet2);
+void    qh_mergeneighbors(qhT *qh, facetT *facet1, facetT *facet2);
+void    qh_mergeridges(qhT *qh, facetT *facet1, facetT *facet2);
+void    qh_mergesimplex(qhT *qh, facetT *facet1, facetT *facet2, boolT mergeapex);
+void    qh_mergevertex_del(qhT *qh, vertexT *vertex, facetT *facet1, facetT *facet2);
+void    qh_mergevertex_neighbors(qhT *qh, facetT *facet1, facetT *facet2);
+void    qh_mergevertices(qhT *qh, setT *vertices1, setT **vertices);
+setT   *qh_neighbor_intersections(qhT *qh, vertexT *vertex);
+setT   *qh_neighbor_vertices(qhT *qh, vertexT *vertex, setT *subridge);
+void    qh_neighbor_vertices_facet(qhT *qh, vertexT *vertexA, facetT *facet, setT **vertices);
+void    qh_newvertices(qhT *qh, setT *vertices);
+mergeT *qh_next_vertexmerge(qhT *qh);
+facetT *qh_opposite_horizonfacet(qhT *qh, mergeT *merge, vertexT **vertex);
+boolT   qh_reducevertices(qhT *qh);
+vertexT *qh_redundant_vertex(qhT *qh, vertexT *vertex);
+boolT   qh_remove_extravertices(qhT *qh, facetT *facet);
+void    qh_remove_mergetype(qhT *qh, setT *mergeset, mergeType type);
+void    qh_rename_adjacentvertex(qhT *qh, vertexT *oldvertex, vertexT *newvertex, realT dist);
+vertexT *qh_rename_sharedvertex(qhT *qh, vertexT *vertex, facetT *facet);
+boolT   qh_renameridgevertex(qhT *qh, ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
+void    qh_renamevertex(qhT *qh, vertexT *oldvertex, vertexT *newvertex, setT *ridges,
+                        facetT *oldfacet, facetT *neighborA);
+boolT   qh_test_appendmerge(qhT *qh, facetT *facet, facetT *neighbor, boolT simplicial);
+void    qh_test_degen_neighbors(qhT *qh, facetT *facet);
+boolT   qh_test_centrum_merge(qhT *qh, facetT *facet, facetT *neighbor, realT angle, boolT okangle);
+boolT   qh_test_nonsimplicial_merge(qhT *qh, facetT *facet, facetT *neighbor, realT angle, boolT okangle);
+void    qh_test_redundant_neighbors(qhT *qh, facetT *facet);
+boolT   qh_test_vneighbors(qhT *qh /* qh.newfacet_list */);
+void    qh_tracemerge(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype);
+void    qh_tracemerging(qhT *qh);
+void    qh_undo_newfacets(qhT *qh);
+void    qh_updatetested(qhT *qh, facetT *facet1, facetT *facet2);
+setT   *qh_vertexridges(qhT *qh, vertexT *vertex, boolT allneighbors);
+void    qh_vertexridges_facet(qhT *qh, vertexT *vertex, facetT *facet, setT **ridges);
+void    qh_willdelete(qhT *qh, facetT *facet, facetT *replace);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFmerge */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/poly2_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/poly2_r.c
new file mode 100644
index 00000000000..aed77e001f7
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/poly2_r.c
@@ -0,0 +1,3959 @@
+/*
  ---------------------------------
+
+   poly2_r.c
+   implements polygons and simplicies
+
+   see qh-poly_r.htm, poly_r.h and libqhull_r.h
+
+   frequently used code is in poly_r.c
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/poly2_r.c#22 $$Change: 3978 $
+   $DateTime: 2025/08/24 21:38:45 $$Author: bbarber $
+*/
+
+#include "qhull_ra.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*---------------------------------
+
+  qh_addfacetvertex(qh, facet, newvertex )
+    add newvertex to facet.vertices if not already there
+    vertices are inverse sorted by vertex->id
+
+  returns:
+    True if new vertex for facet
+
+  notes:
+    see qh_replacefacetvertex
+*/
+boolT qh_addfacetvertex(qhT *qh, facetT *facet, vertexT *newvertex) {
+  vertexT *vertex;
+  int vertex_i= 0, vertex_n;
+  boolT isnew= True;
+
+  FOREACHvertex_i_(qh, facet->vertices) {
+    if (vertex->id < newvertex->id) {
+      break;
+    }else if (vertex->id == newvertex->id) {
+      isnew= False;
+      break;
+    }
+  }
+  if (isnew)
+    qh_setaddnth(qh, &facet->vertices, vertex_i, newvertex);
+  return isnew;
+} /* addfacetvertex */
+
+/*---------------------------------
+
+  qh_addhash( newelem, hashtable, hashsize, hash )
+    add newelem to linear hash table at hash if not already there
+*/
+void qh_addhash(void *newelem, setT *hashtable, int hashsize, int hash) {
+  int scan;
+  void *elem;
+
+  for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (elem == newelem)
+      break;
+  }
+  /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
+  if (!elem)
+    SETelem_(hashtable, scan)= newelem;
+} /* addhash */
+
+/*---------------------------------
+
+  qh_check_bestdist(qh)
+    check that all points are within max_outside of the nearest facet
+    if qh.ONLYgood,
+      ignores !good facets
+
+  see:
+    qh_check_maxout(), qh_outerinner()
+
+  notes:
+    only called from qh_check_points()
+      seldom used since qh.MERGING is almost always set
+    if notverified>0 at end of routine
+      some points were well inside the hull.  If the hull contains
+      a lens-shaped component, these points were not verified.  Use
+      options 'Qi Tv' to verify all points.  (Exhaustive check also verifies)
+
+  design:
+    determine facet for each point (if any)
+    for each point
+      start with the assigned facet or with the first facet
+      find the best facet for the point and check all coplanar facets
+      error if point is outside of facet
+*/
+void qh_check_bestdist(qhT *qh) {
+  boolT waserror= False, unassigned;
+  facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
+  facetT *facetlist;
+  realT dist, maxoutside, maxdist= -REALmax;
+  pointT *point;
+  int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
+  setT *facets;
+
+  trace1((qh, qh->ferr, 1020, "qh_check_bestdist: check points below nearest facet.  Facet_list f%d\n",
+      qh->facet_list->id));
+  maxoutside= qh_maxouter(qh);
+  maxoutside += qh->DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh, qh->ferr, 1021, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
+  facets= qh_pointfacet(qh /* qh.facet_list */);
+  if (!qh_QUICKhelp && qh->PRINTprecision)
+    qh_fprintf(qh, qh->ferr, 8091, "\n\
+qhull output completed.  Verifying that %d points are\n\
+below %2.2g of the nearest %sfacet.\n",
+             qh_setsize(qh, facets), maxoutside, (qh->ONLYgood ?  "good " : ""));
+  FOREACHfacet_i_(qh, facets) {  /* for each point with facet assignment */
+    if (facet)
+      unassigned= False;
+    else {
+      unassigned= True;
+      facet= qh->facet_list;
+    }
+    point= qh_point(qh, facet_i);
+    if (point == qh->GOODpointp)
+      continue;
+    qh_distplane(qh, point, facet, &dist);
+    numpart++;
+    bestfacet= qh_findbesthorizon(qh, !qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
+    /* occurs after statistics reported */
+    maximize_(maxdist, dist);
+    if (dist > maxoutside) {
+      if (qh->ONLYgood && !bestfacet->good
+      && !((bestfacet= qh_findgooddist(qh, point, bestfacet, &dist, &facetlist))
+      && dist > maxoutside))
+        notgood++;
+      else {
+        waserror= True;
+        qh_fprintf(qh, qh->ferr, 6109, "qhull precision error (qh_check_bestdist): point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
+                facet_i, bestfacet->id, dist, maxoutside);
+        if (errfacet1 != bestfacet) {
+          errfacet2= errfacet1;
+          errfacet1= bestfacet;
+        }
+      }
+    }else if (unassigned && dist < -qh->MAXcoplanar)
+      notverified++;
+  }
+  qh_settempfree(qh, &facets);
+  if (notverified && !qh->DELAUNAY && !qh_QUICKhelp && qh->PRINTprecision)
+    qh_fprintf(qh, qh->ferr, 8092, "\n%d points were well inside the hull.  If the hull contains\n\
+a lens-shaped component, these points were not verified.  Use\n\
+options 'Qci Tv' to verify all points.\n", notverified);
+  if (maxdist > qh->outside_err) {
+    qh_fprintf(qh, qh->ferr, 6110, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull.  The maximum value is qh.outside_err (%6.2g)\n",
+              maxdist, qh->outside_err);
+    qh_errexit2(qh, qh_ERRprec, errfacet1, errfacet2);
+  }else if (waserror && qh->outside_err > REALmax/2)
+    qh_errexit2(qh, qh_ERRprec, errfacet1, errfacet2);
+  /* else if waserror, the error was logged to qh.ferr but does not effect the output */
+  trace0((qh, qh->ferr, 20, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
+} /* check_bestdist */
+
+#ifndef qh_NOmerge
+/*---------------------------------
+
+  qh_check_maxout(qh)
+    updates qh.max_outside by checking all points against bestfacet
+    if qh.ONLYgood, ignores !good facets
+
+  returns:
+    updates facet->maxoutside via qh_findbesthorizon()
+    sets qh.maxoutdone
+    if printing qh.min_vertex (qh_outerinner),
+      it is updated to the current vertices
+    removes inside/coplanar points from coplanarset as needed
+
+  notes:
+    defines coplanar as qh.min_vertex instead of qh.MAXcoplanar
+    may not need to check near-inside points because of qh.MAXcoplanar
+      and qh.KEEPnearinside (before it was -qh.DISTround)
+
+  see also:
+    qh_check_bestdist()
+
+  design:
+    if qh.min_vertex is needed
+      for all neighbors of all vertices
+        test distance from vertex to neighbor
+    determine facet for each point (if any)
+    for each point with an assigned facet
+      find the best facet for the point and check all coplanar facets
+        (updates outer planes)
+    remove near-inside points from coplanar sets
+*/
+void qh_check_maxout(qhT *qh) {
+  facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist, *maxbestfacet= NULL, *minfacet, *maxfacet, *maxpointfacet;
+  realT dist, maxoutside, mindist, nearest;
+  realT maxoutside_base, minvertex_base;
+  pointT *point, *maxpoint= NULL;
+  int numpart= 0, facet_i, facet_n, notgood= 0;
+  setT *facets, *vertices;
+  vertexT *vertex, *minvertex;
+
+  trace1((qh, qh->ferr, 1022, "qh_check_maxout: check and update qh.min_vertex %2.2g and qh.max_outside %2.2g\n", qh->min_vertex, qh->max_outside));
+  minvertex_base= fmin_(qh->min_vertex, -(qh->ONEmerge+qh->DISTround));
+  maxoutside= mindist= 0.0;
+  minvertex= qh->vertex_list;
+  maxfacet= minfacet= maxpointfacet= qh->facet_list;
+  if (qh->VERTEXneighbors
+  && (qh->PRINTsummary || qh->KEEPinside || qh->KEEPcoplanar
+        || qh->TRACElevel || qh->PRINTstatistics || qh->VERIFYoutput || qh->CHECKfrequently
+        || qh->PRINTout[0] == qh_PRINTsummary || qh->PRINTout[0] == qh_PRINTnone)) {
+    trace1((qh, qh->ferr, 1023, "qh_check_maxout: determine actual minvertex\n"));
+    vertices= qh_pointvertex(qh /* qh.facet_list */);
+    FORALLvertices {
+      FOREACHneighbor_(vertex) {
+        zinc_(Zdistvertex);  /* distance also computed by main loop below */
+        qh_distplane(qh, vertex->point, neighbor, &dist);
+        if (dist < mindist) {
+          if (qh->min_vertex/minvertex_base > qh_WIDEmaxoutside && (qh->PRINTprecision || !qh->ALLOWwide)) {
+            nearest= qh_vertex_bestdist(qh, neighbor->vertices);
+            /* should be caught in qh_mergefacet */
+            qh_fprintf(qh, qh->ferr, 7083, "Qhull precision warning: in post-processing (qh_check_maxout) p%d(v%d) is %2.2g below f%d nearest vertices %2.2g\n",
+              qh_pointid(qh, vertex->point), vertex->id, dist, neighbor->id, nearest);
+          }
+          mindist= dist;
+          minvertex= vertex;
+          minfacet= neighbor;
+        }
+#ifndef qh_NOtrace
+        if (-dist > qh->TRACEdist || dist > qh->TRACEdist
+        || neighbor == qh->tracefacet || vertex == qh->tracevertex) {
+          nearest= qh_vertex_bestdist(qh, neighbor->vertices);
+          qh_fprintf(qh, qh->ferr, 8093, "qh_check_maxout: p%d(v%d) is %.2g from f%d nearest vertices %2.2g\n",
+                    qh_pointid(qh, vertex->point), vertex->id, dist, neighbor->id, nearest);
+        }
+#endif
+      }
+    }
+    if (qh->MERGING) {
+      wmin_(Wminvertex, qh->min_vertex);
+    }
+    qh->min_vertex= mindist;
+    qh_settempfree(qh, &vertices);
+  }
+  trace1((qh, qh->ferr, 1055, "qh_check_maxout: determine actual maxoutside\n"));
+  maxoutside_base= fmax_(qh->max_outside, qh->ONEmerge+qh->DISTround);
+  /* maxoutside_base is same as qh.MAXoutside without qh.MINoutside (qh_detmaxoutside) */
+  facets= qh_pointfacet(qh /* qh.facet_list */);
+  FOREACHfacet_i_(qh, facets) {     /* for each point with facet assignment */
+    if (facet) {
+      point= qh_point(qh, facet_i);
+      if (point == qh->GOODpointp)
+        continue;
+      zzinc_(Ztotcheck);
+      qh_distplane(qh, point, facet, &dist);
+      numpart++;
+      bestfacet= qh_findbesthorizon(qh, qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
+      if (bestfacet && dist >= maxoutside) {
+        if (qh->ONLYgood && !bestfacet->good
+        && !((bestfacet= qh_findgooddist(qh, point, bestfacet, &dist, &facetlist))
+        && dist > maxoutside)) {
+          notgood++;
+        }else if (dist/maxoutside_base > qh_WIDEmaxoutside && (qh->PRINTprecision || !qh->ALLOWwide)) {
+          nearest= qh_vertex_bestdist(qh, bestfacet->vertices);
+          if (nearest < fmax_(qh->ONEmerge, qh->max_outside) * qh_RATIOcoplanaroutside * 2) {
+            qh_fprintf(qh, qh->ferr, 7087, "Qhull precision warning: in post-processing (qh_check_maxout) p%d for f%d is %2.2g above twisted facet f%d nearest vertices %2.2g\n",
+              qh_pointid(qh, point), facet->id, dist, bestfacet->id, nearest);
+          }else {
+            qh_fprintf(qh, qh->ferr, 7088, "Qhull precision warning: in post-processing (qh_check_maxout) p%d for f%d is %2.2g above hidden facet f%d nearest vertices %2.2g\n",
+              qh_pointid(qh, point), facet->id, dist, bestfacet->id, nearest);
+          }
+          maxbestfacet= bestfacet;
+        }
+        maxoutside= dist;
+        maxfacet= bestfacet;
+        maxpoint= point;
+        maxpointfacet= facet;
+      }
+      if (dist > qh->TRACEdist || (bestfacet && bestfacet == qh->tracefacet))
+        qh_fprintf(qh, qh->ferr, 8094, "qh_check_maxout: p%d is %.2g above f%d\n",
+              qh_pointid(qh, point), dist, (bestfacet ? bestfacet->id : UINT_MAX));
+    }
+  }
+  zzadd_(Zcheckpart, numpart);
+  qh_settempfree(qh, &facets);
+  wval_(Wmaxout)= maxoutside - qh->max_outside;
+  wmax_(Wmaxoutside, qh->max_outside);
+  if (!qh->APPROXhull && maxoutside > qh->DISTround) { /* initial value for f.maxoutside */
+    FORALLfacets {
+      if (maxoutside < facet->maxoutside) {
+        if (!qh->KEEPcoplanar) {
+          maxoutside= facet->maxoutside;
+        }else if (maxoutside + qh->DISTround < facet->maxoutside) { /* maxoutside is computed distance, e.g., rbox 100 s D3 t1547136913 | qhull R1e-3 Tcv Qc */
+          qh_fprintf(qh, qh->ferr, 7082, "Qhull precision warning (qh_check_maxout): f%d.maxoutside (%4.4g) is greater than computed qh.max_outside (%2.2g) + qh.DISTround (%2.2g).  It should be less than or equal\n",
+            facet->id, facet->maxoutside, maxoutside, qh->DISTround);
+        }
+      }
+    }
+  }
+  qh->max_outside= maxoutside;
+  qh_nearcoplanar(qh /* qh.facet_list */);
+  qh->maxoutdone= True;
+  trace1((qh, qh->ferr, 1024, "qh_check_maxout:  p%d(v%d) is qh.min_vertex %2.2g below facet f%d.  Point p%d for f%d is qh.max_outside %2.2g above f%d.  %d points are outside of not-good facets\n",
+    qh_pointid(qh, minvertex->point), minvertex->id, qh->min_vertex, minfacet->id, qh_pointid(qh, maxpoint), maxpointfacet->id, qh->max_outside, maxfacet->id, notgood));
+  if(!qh->ALLOWwide) {
+    if (maxoutside/maxoutside_base > qh_WIDEmaxoutside) {
+      qh_fprintf(qh, qh->ferr, 6297, "Qhull precision error (qh_check_maxout): large increase in qh.max_outside during post-processing dist %2.2g (%.1fx).  See warning QH0032/QH0033.  Allow with 'Q12' (allow-wide) and 'Pp'\n",
+        maxoutside, maxoutside/maxoutside_base);
+      qh_errexit(qh, qh_ERRwide, maxbestfacet, NULL);
+    }else if (!qh->APPROXhull && maxoutside_base > (qh->ONEmerge * qh_WIDEmaxoutside2)) {
+      if (maxoutside > (qh->ONEmerge * qh_WIDEmaxoutside2)) {  /* wide facets may have been deleted */
+        qh_fprintf(qh, qh->ferr, 6298, "Qhull precision error (qh_check_maxout): a facet merge, vertex merge, vertex, or coplanar point produced a wide facet %2.2g (%.1fx). Trace with option 'TWn' to identify the merge.   Allow with 'Q12' (allow-wide)\n",
+          maxoutside_base, maxoutside_base/(qh->ONEmerge + qh->DISTround));
+        qh_errexit(qh, qh_ERRwide, maxbestfacet, NULL);
+      }
+    }else if (qh->min_vertex/minvertex_base > qh_WIDEmaxoutside) {
+      qh_fprintf(qh, qh->ferr, 6354, "Qhull precision error (qh_check_maxout): large increase in qh.min_vertex during post-processing dist %2.2g (%.1fx).  See warning QH7083.  Allow with 'Q12' (allow-wide) and 'Pp'\n",
+        qh->min_vertex, qh->min_vertex/minvertex_base);
+      qh_errexit(qh, qh_ERRwide, minfacet, NULL);
+    }else if (minvertex_base < -(qh->ONEmerge * qh_WIDEmaxoutside2)) {
+      if (qh->min_vertex < -(qh->ONEmerge * qh_WIDEmaxoutside2)) {  /* wide facets may have been deleted */
+        qh_fprintf(qh, qh->ferr, 6380, "Qhull precision error (qh_check_maxout): a facet or vertex merge produced a wide facet: v%d below f%d distance %2.2g (%.1fx). Trace with option 'TWn' to identify the merge.  Allow with 'Q12' (allow-wide)\n",
+          minvertex->id, minfacet->id, mindist, -qh->min_vertex/(qh->ONEmerge + qh->DISTround));
+        qh_errexit(qh, qh_ERRwide, minfacet, NULL);
+      }
+    }
+  }
+} /* check_maxout */
+#else /* qh_NOmerge */
+void qh_check_maxout(qhT *qh) {
+  QHULL_UNUSED(qh)
+}
+#endif
+
+/*---------------------------------
+
+  qh_check_output(qh)
+    performs the checks at the end of qhull algorithm
+    Maybe called after Voronoi output.  If so, it recomputes centrums since they are Voronoi centers instead.
+*/
+void qh_check_output(qhT *qh) {
+  int i;
+
+  if (qh->STOPcone)
+    return;
+  if (qh->VERIFYoutput || qh->IStracing || qh->CHECKfrequently) {
+    qh_checkpolygon(qh, qh->facet_list);
+    qh_checkflipped_all(qh, qh->facet_list);
+    qh_checkconvex(qh, qh->facet_list, qh_ALGORITHMfault);
+  }else if (!qh->MERGING && qh_newstats(qh, qh->qhstat.precision, &i)) {
+    qh_checkflipped_all(qh, qh->facet_list);
+    qh_checkconvex(qh, qh->facet_list, qh_ALGORITHMfault);
+  }
+} /* check_output */
+
+
+
+/*---------------------------------
+
+  qh_check_point(qh, point, facet, maxoutside, maxdist, errfacet1, errfacet2, errcount )
+    check that point is less than maxoutside from facet
+
+  notes:
+    only called from qh_checkpoints
+    reports up to qh_MAXcheckpoint-1 errors per facet
+*/
+void qh_check_point(qhT *qh, pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2, int *errcount) {
+  realT dist, nearest;
+
+  /* occurs after statistics reported */
+  qh_distplane(qh, point, facet, &dist);
+  maximize_(*maxdist, dist);
+  if (dist > *maxoutside) {
+    (*errcount)++;
+    if (*errfacet1 != facet) {
+      *errfacet2= *errfacet1;
+      *errfacet1= facet;
+    }
+    if (*errcount < qh_MAXcheckpoint) {
+      nearest= qh_vertex_bestdist(qh, facet->vertices);
+      qh_fprintf(qh, qh->ferr, 6111, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g nearest vertices %2.2g\n",
+                qh_pointid(qh, point), facet->id, dist, *maxoutside, nearest);
+    }
+  }
+} /* qh_check_point */
+
+
+/*---------------------------------
+
+  qh_check_points(qh)
+    checks that all points are inside all facets
+
+  notes:
+    if many points and qh_check_maxout not called (i.e., !qh.MERGING),
+       calls qh_findbesthorizon via qh_check_bestdist (seldom done).
+    ignores flipped facets
+    maxoutside includes 2 qh.DISTrounds
+      one qh.DISTround for the computed distances in qh_check_points
+    qh_printafacet and qh_printsummary needs only one qh.DISTround
+    the computation for qh.VERIFYdirect does not account for qh.other_points
+
+  design:
+    if many points
+      use qh_check_bestdist()
+    else
+      for all facets
+        for all points
+          check that point is inside facet
+*/
+void qh_check_points(qhT *qh) {
+  facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
+  realT total, maxoutside, maxdist= -REALmax;
+  pointT *point, **pointp, *pointtemp;
+  int errcount;
+  boolT testouter;
+
+  maxoutside= qh_maxouter(qh);
+  maxoutside += qh->DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh, qh->ferr, 1025, "qh_check_points: check all points below %2.2g of all facet planes\n",
+          maxoutside));
+  if (qh->num_good)   /* miss counts other_points and !good facets */
+     total= (realT)qh->num_good * (realT)qh->num_points;
+  else
+     total= (realT)qh->num_facets * (realT)qh->num_points;
+  if (total >= qh_VERIFYdirect && !qh->maxoutdone) {
+    if (!qh_QUICKhelp && qh->SKIPcheckmax && qh->MERGING)
+      qh_fprintf(qh, qh->ferr, 7075, "qhull input warning: merging without checking outer planes('Q5' or 'Po').  Verify may report that a point is outside of a facet.\n");
+    qh_check_bestdist(qh);
+  }else {
+    if (qh_MAXoutside && qh->maxoutdone)
+      testouter= True;
+    else
+      testouter= False;
+    if (!qh_QUICKhelp) {
+      if (qh->MERGEexact)
+        qh_fprintf(qh, qh->ferr, 7076, "qhull input warning: exact merge ('Qx').  Verify may report that a point is outside of a facet.  See qh-optq.htm#Qx\n");
+      else if (qh->SKIPcheckmax || qh->NOnearinside)
+        qh_fprintf(qh, qh->ferr, 7077, "qhull input warning: no outer plane check ('Q5') or no processing of near-inside points ('Q8').  Verify may report that a point is outside of a facet.\n");
+    }
+    if (qh->PRINTprecision) {
+      if (testouter)
+        qh_fprintf(qh, qh->ferr, 8098, "\n\
+Output completed.  Verifying that all points are below outer planes of\n\
+all %sfacets.  Will make %2.0f distance computations.\n",
+              (qh->ONLYgood ?  "good " : ""), total);
+      else
+        qh_fprintf(qh, qh->ferr, 8099, "\n\
+Output completed.  Verifying that all points are below %2.2g of\n\
+all %sfacets.  Will make %2.0f distance computations.\n",
+              maxoutside, (qh->ONLYgood ?  "good " : ""), total);
+    }
+    FORALLfacets {
+      if (!facet->good && qh->ONLYgood)
+        continue;
+      if (facet->flipped)
+        continue;
+      if (!facet->normal) {
+        qh_fprintf(qh, qh->ferr, 7061, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
+        if (!errfacet1)
+          errfacet1= facet;
+        continue;
+      }
+      if (testouter) {
+#if qh_MAXoutside
+        maxoutside= facet->maxoutside + 2 * qh->DISTround;
+        /* one DISTround to actual point and another to computed point */
+#endif
+      }
+      errcount= 0;
+      FORALLpoints {
+        if (point != qh->GOODpointp)
+          qh_check_point(qh, point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2, &errcount);
+      }
+      FOREACHpoint_(qh->other_points) {
+        if (point != qh->GOODpointp)
+          qh_check_point(qh, point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2, &errcount);
+      }
+      if (errcount >= qh_MAXcheckpoint) {
+        qh_fprintf(qh, qh->ferr, 6422, "qhull precision error (qh_check_points): %d additional points outside facet f%d, maxdist= %6.8g\n",
+             errcount-qh_MAXcheckpoint+1, facet->id, maxdist);
+      }
+    }
+    if (maxdist > qh->outside_err) {
+      qh_fprintf(qh, qh->ferr, 6112, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
+                maxdist, qh->outside_err );
+      qh_errexit2(qh, qh_ERRprec, errfacet1, errfacet2 );
+    }else if (errfacet1 && qh->outside_err > REALmax/2)
+        qh_errexit2(qh, qh_ERRprec, errfacet1, errfacet2 );
+    /* else if errfacet1, the error was logged to qh.ferr but does not effect the output */
+    trace0((qh, qh->ferr, 21, "qh_check_points: max distance outside %2.2g\n", maxdist));
+  }
+} /* check_points */
+
+
+/*---------------------------------
+
+  qh_checkconvex(qh, facetlist, fault )
+    check that each ridge in facetlist is convex
+    fault = qh_DATAfault if reporting errors from qh_initialhull with qh.ZEROcentrum
+          = qh_ALGORITHMfault otherwise
+
+  returns:
+    counts Zconcaveridges and Zcoplanarridges
+    errors if !qh.FORCEoutput ('Fo') and concaveridge or if merging a coplanar ridge
+    overwrites Voronoi centers if set by qh_setvoronoi_all/qh_ASvoronoi
+
+  notes:
+    called by qh_initial_hull, qh_check_output, qh_all_merges ('Tc'), qh_build_withrestart ('QJ')
+    does not test f.tricoplanar facets (qh_triangulate)
+    must be no stronger than qh_test_appendmerge
+    if not merging,
+      tests vertices for neighboring simplicial facets < -qh.DISTround
+    else if ZEROcentrum and simplicial facet,
+      tests vertices for neighboring simplicial facets < 0.0
+      tests centrums of neighboring nonsimplicial facets < 0.0
+    else if ZEROcentrum
+      tests centrums of neighboring facets < 0.0
+    else
+      tests centrums of neighboring facets < -qh.DISTround ('En' 'Rn')
+    Does not test against -qh.centrum_radius since repeated computations may have different round-off errors (e.g., 'Rn')
+
+  design:
+    for all facets
+      report flipped facets
+      if ZEROcentrum and simplicial neighbors
+        test vertices against neighbor
+      else
+        test centrum against neighbor
+*/
+void qh_checkconvex(qhT *qh, facetT *facetlist, int fault) {
+  facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
+  vertexT *vertex;
+  realT dist;
+  pointT *centrum;
+  boolT waserror= False, centrum_warning= False, tempcentrum= False, first_nonsimplicial= False, tested_simplicial, allsimplicial;
+  int neighbor_i, neighbor_n;
+
+  if (qh->ZEROcentrum) {
+    trace1((qh, qh->ferr, 1064, "qh_checkconvex: check that facets are not-flipped and for qh.ZEROcentrum that simplicial vertices are below their neighbor (dist<0.0)\n"));
+    first_nonsimplicial= True;
+  }else if (!qh->MERGING) {
+    trace1((qh, qh->ferr, 1026, "qh_checkconvex: check that facets are not-flipped and that simplicial vertices are convex by qh.DISTround ('En', 'Rn')\n"));
+    first_nonsimplicial= True;
+  }else
+    trace1((qh, qh->ferr, 1062, "qh_checkconvex: check that facets are not-flipped and that their centrums are convex by qh.DISTround ('En', 'Rn') \n"));
+  if (!qh->RERUN) {
+    zzval_(Zconcaveridges)= 0;
+    zzval_(Zcoplanarridges)= 0;
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->flipped) {
+      qh_joggle_restart(qh, "flipped facet"); /* also tested by qh_checkflipped */
+      qh_fprintf(qh, qh->ferr, 6113, "qhull precision error: f%d is flipped (interior point is outside)\n",
+               facet->id);
+      errfacet1= facet;
+      waserror= True;
+      continue;
+    }
+    if (facet->tricoplanar)
+      continue;
+    if (qh->MERGING && (!qh->ZEROcentrum || !facet->simplicial)) {
+      allsimplicial= False;
+      tested_simplicial= False;
+    }else {
+      allsimplicial= True;
+      tested_simplicial= True;
+      FOREACHneighbor_i_(qh, facet) {
+        if (neighbor->tricoplanar)
+          continue;
+        if (!neighbor->simplicial) {
+          allsimplicial= False;
+          continue;
+        }
+        vertex= SETelemt_(facet->vertices, neighbor_i, vertexT);
+        qh_distplane(qh, vertex->point, neighbor, &dist);
+        if (dist >= -qh->DISTround) {
+          if (fault == qh_DATAfault) {
+            qh_joggle_restart(qh, "non-convex initial simplex");
+            if (dist > qh->DISTround)
+              qh_fprintf(qh, qh->ferr, 6114, "qhull precision error: initial simplex is not convex, since p%d(v%d) is %6.4g above opposite f%d\n",
+                  qh_pointid(qh, vertex->point), vertex->id, dist, neighbor->id);
+            else
+              qh_fprintf(qh, qh->ferr, 6379, "qhull precision error: initial simplex is not convex, since p%d(v%d) is within roundoff of opposite facet f%d (dist %6.4g)\n",
+                  qh_pointid(qh, vertex->point), vertex->id, neighbor->id, dist);
+            qh_errexit(qh, qh_ERRsingular, neighbor, NULL);
+          }
+          if (dist > qh->DISTround) {
+            zzinc_(Zconcaveridges);
+            qh_joggle_restart(qh, "concave ridge");
+            qh_fprintf(qh, qh->ferr, 6115, "qhull precision error: f%d is concave to f%d, since p%d(v%d) is %6.4g above f%d\n",
+              facet->id, neighbor->id, qh_pointid(qh, vertex->point), vertex->id, dist, neighbor->id);
+            errfacet1= facet;
+            errfacet2= neighbor;
+            waserror= True;
+          }else if (qh->ZEROcentrum) {
+            if (dist > 0.0) {     /* qh_checkzero checked convex (dist < (- 2*qh->DISTround)), computation may differ e.g. 'Rn' */
+              zzinc_(Zcoplanarridges);
+              qh_joggle_restart(qh, "coplanar ridge");
+              qh_fprintf(qh, qh->ferr, 6116, "qhull precision error: f%d is clearly not convex to f%d, since p%d(v%d) is %6.4g above or coplanar with f%d with qh.ZEROcentrum\n",
+                facet->id, neighbor->id, qh_pointid(qh, vertex->point), vertex->id, dist, neighbor->id);
+              errfacet1= facet;
+              errfacet2= neighbor;
+              waserror= True;
+            }
+          }else {
+            zzinc_(Zcoplanarridges);
+            qh_joggle_restart(qh, "coplanar ridge");
+            trace0((qh, qh->ferr, 22, "qhull precision error: f%d is coplanar to f%d, since p%d(v%d) is within %6.4g of f%d, during p%d\n",
+              facet->id, neighbor->id, qh_pointid(qh, vertex->point), vertex->id, dist, neighbor->id, qh->furthest_id));
+          }
+        }
+      }
+    }
+    if (!allsimplicial) {
+      if (first_nonsimplicial) {
+        trace1((qh, qh->ferr, 1063, "qh_checkconvex: starting with f%d, also check that centrums of non-simplicial ridges are below their neighbors (dist<0.0)\n",
+             facet->id));
+        first_nonsimplicial= False;
+      }
+      if (qh->CENTERtype == qh_AScentrum) {
+        if (!facet->center)
+          facet->center= qh_getcentrum(qh, facet);
+        centrum= facet->center;
+      }else {
+        if (!centrum_warning && !facet->simplicial) {  /* recomputed centrum correct for simplicial facets */
+           centrum_warning= True;
+           qh_fprintf(qh, qh->ferr, 7062, "qhull warning: recomputing centrums for convexity test.  This may lead to false, precision errors.\n");
+        }
+        centrum= qh_getcentrum(qh, facet);
+        tempcentrum= True;
+      }
+      FOREACHneighbor_(facet) {
+        if (neighbor->simplicial && tested_simplicial) /* tested above since f.simplicial */
+          continue;
+        if (neighbor->tricoplanar)
+          continue;
+        zzinc_(Zdistconvex);
+        qh_distplane(qh, centrum, neighbor, &dist);
+        if (dist > qh->DISTround) {
+          zzinc_(Zconcaveridges);
+          qh_joggle_restart(qh, "concave ridge");
+          qh_fprintf(qh, qh->ferr, 6117, "qhull precision error: f%d is concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+          errfacet1= facet;
+          errfacet2= neighbor;
+          waserror= True;
+        }else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
+                                     can test against centrum radius instead */
+          zzinc_(Zcoplanarridges);
+          qh_joggle_restart(qh, "coplanar ridge");
+          qh_fprintf(qh, qh->ferr, 6118, "qhull precision error: f%d is coplanar or concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+          errfacet1= facet;
+          errfacet2= neighbor;
+          waserror= True;
+        }
+      }
+      if (tempcentrum)
+        qh_memfree(qh, centrum, qh->normal_size);
+    }
+  }
+  if (waserror && !qh->FORCEoutput)
+    qh_errexit2(qh, qh_ERRprec, errfacet1, errfacet2);
+} /* checkconvex */
+
+
+/*---------------------------------
+
+  qh_checkfacet(qh, facet, newmerge, waserror )
+    checks for consistency errors in facet
+    newmerge set if from merge_r.c
+
+  returns:
+    sets waserror if any error occurs
+
+  checks:
+    vertex ids are inverse sorted
+    unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
+    if non-simplicial, at least as many ridges as neighbors
+    neighbors are not duplicated
+    ridges are not duplicated
+    in 3-d, ridges=verticies
+    (qh.hull_dim-1) ridge vertices
+    neighbors are reciprocated
+    ridge neighbors are facet neighbors and a ridge for every neighbor
+    simplicial neighbors match facetintersect
+    vertex intersection matches vertices of common ridges
+    vertex neighbors and facet vertices agree
+    all ridges have distinct vertex sets
+
+  notes:
+    called by qh_tracemerge and qh_checkpolygon
+    uses neighbor->seen
+
+  design:
+    check sets
+    check vertices
+    check sizes of neighbors and vertices
+    check for qh_MERGEridge and qh_DUPLICATEridge flags
+    check neighbor set
+    check ridge set
+    check ridges, neighbors, and vertices
+*/
+void qh_checkfacet(qhT *qh, facetT *facet, boolT newmerge, boolT *waserrorp) {
+  facetT *neighbor, **neighborp, *errother=NULL;
+  ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
+  vertexT *vertex, **vertexp;
+  unsigned int previousid= INT_MAX;
+  int numneighbors, numvertices, numridges=0, numRvertices=0;
+  boolT waserror= False;
+  int skipA, skipB, ridge_i, ridge_n, i, last_v= qh->hull_dim-2;
+  setT *intersection;
+
+  trace4((qh, qh->ferr, 4088, "qh_checkfacet: check f%d newmerge? %d\n", facet->id, newmerge));
+  if (facet->id >= qh->facet_id) {
+    qh_fprintf(qh, qh->ferr, 6414, "qhull internal error (qh_checkfacet): unknown facet id f%d >= qh.facet_id (%d)\n", facet->id, qh->facet_id);
+    waserror= True;
+  }
+  if (facet->visitid > qh->visit_id) {
+    qh_fprintf(qh, qh->ferr, 6415, "qhull internal error (qh_checkfacet): expecting f%d.visitid <= qh.visit_id (%d).  Got visitid %d\n", facet->id, qh->visit_id, facet->visitid);
+    waserror= True;
+  }
+  if (facet->visible && !qh->NEWtentative) {
+    qh_fprintf(qh, qh->ferr, 6119, "qhull internal error (qh_checkfacet): facet f%d is on qh.visible_list\n",
+      facet->id);
+    qh_errexit(qh, qh_ERRqhull, facet, NULL);
+  }
+  if (facet->redundant && !facet->visible && qh_setsize(qh, qh->degen_mergeset)==0) {
+    qh_fprintf(qh, qh->ferr, 6399, "qhull internal error (qh_checkfacet): redundant facet f%d not on qh.visible_list\n",
+      facet->id);
+    waserror= True;
+  }
+  if (facet->degenerate && !facet->visible && qh_setsize(qh, qh->degen_mergeset)==0) {
+    qh_fprintf(qh, qh->ferr, 6400, "qhull internal error (qh_checkfacet): degenerate facet f%d is not on qh.visible_list and qh.degen_mergeset is empty\n",
+      facet->id);
+    waserror= True;
+  }
+  if (!facet->normal) {
+    qh_fprintf(qh, qh->ferr, 6120, "qhull internal error (qh_checkfacet): facet f%d does not have a normal\n",
+      facet->id);
+    waserror= True;
+  }
+  if (!facet->newfacet) {
+    if (facet->dupridge) {
+      qh_fprintf(qh, qh->ferr, 6349, "qhull internal error (qh_checkfacet): f%d is 'dupridge' but it is not a newfacet on qh.newfacet_list f%d\n",
+        facet->id, getid_(qh->newfacet_list));
+      waserror= True;
+    }
+    if (facet->newmerge) {
+      qh_fprintf(qh, qh->ferr, 6383, "qhull internal error (qh_checkfacet): f%d is 'newmerge' but it is not a newfacet on qh.newfacet_list f%d.  Missing call to qh_reducevertices\n",
+        facet->id, getid_(qh->newfacet_list));
+      waserror= True;
+    }
+  }
+  qh_setcheck(qh, facet->vertices, "vertices for f", facet->id);
+  qh_setcheck(qh, facet->ridges, "ridges for f", facet->id);
+  qh_setcheck(qh, facet->outsideset, "outsideset for f", facet->id);
+  qh_setcheck(qh, facet->coplanarset, "coplanarset for f", facet->id);
+  qh_setcheck(qh, facet->neighbors, "neighbors for f", facet->id);
+  FOREACHvertex_(facet->vertices) {
+    if (vertex->deleted) {
+      qh_fprintf(qh, qh->ferr, 6121, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
+      qh_errprint(qh, "ERRONEOUS", NULL, NULL, NULL, vertex);
+      waserror= True;
+    }
+    if (vertex->id >= previousid) {
+      qh_fprintf(qh, qh->ferr, 6122, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
+      waserror= True;
+      break;
+    }
+    previousid= vertex->id;
+  }
+  numneighbors= qh_setsize(qh, facet->neighbors);
+  numvertices= qh_setsize(qh, facet->vertices);
+  numridges= qh_setsize(qh, facet->ridges);
+  if (facet->simplicial) {
+    if (numvertices+numneighbors != 2*qh->hull_dim
+    && !facet->degenerate && !facet->redundant) {
+      qh_fprintf(qh, qh->ferr, 6123, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh->hull_dim\n",
+                facet->id, numvertices, numneighbors);
+      qh_setprint(qh, qh->ferr, "", facet->neighbors);
+      waserror= True;
+    }
+  }else { /* non-simplicial */
+    if (!newmerge
+    &&(numvertices < qh->hull_dim || numneighbors < qh->hull_dim)
+    && !facet->degenerate && !facet->redundant) {
+      qh_fprintf(qh, qh->ferr, 6124, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh->hull_dim\n",
+         facet->id, numvertices, numneighbors);
+       waserror= True;
+    }
+    /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
+    if (numridges < numneighbors
+    ||(qh->hull_dim == 3 && numvertices > numridges && !qh->NEWfacets)
+    ||(qh->hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
+      if (!facet->degenerate && !facet->redundant) {
+        qh_fprintf(qh, qh->ferr, 6125, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or(3-d) > #vertices %d or(2-d) not all 2\n",
+            facet->id, numridges, numneighbors, numvertices);
+        waserror= True;
+      }
+    }
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
+      qh_fprintf(qh, qh->ferr, 6126, "qhull internal error (qh_checkfacet): facet f%d still has a MERGEridge or DUPLICATEridge neighbor\n", facet->id);
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    if (neighbor->visible) {
+      qh_fprintf(qh, qh->ferr, 6401, "qhull internal error (qh_checkfacet): facet f%d has deleted neighbor f%d (qh.visible_list)\n",
+        facet->id, neighbor->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    neighbor->seen= True;
+  }
+  FOREACHneighbor_(facet) {
+    if (!qh_setin(neighbor->neighbors, facet)) {
+      qh_fprintf(qh, qh->ferr, 6127, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
+              facet->id, neighbor->id, neighbor->id, facet->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    if (!neighbor->seen) {
+      qh_fprintf(qh, qh->ferr, 6128, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
+              facet->id, neighbor->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    neighbor->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    qh_setcheck(qh, ridge->vertices, "vertices for r", ridge->id);
+    ridge->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    if (ridge->seen) {
+      qh_fprintf(qh, qh->ferr, 6129, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
+              facet->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }
+    ridge->seen= True;
+    numRvertices= qh_setsize(qh, ridge->vertices);
+    if (numRvertices != qh->hull_dim - 1) {
+      qh_fprintf(qh, qh->ferr, 6130, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
+                ridge->top->id, ridge->bottom->id, numRvertices);
+      errridge= ridge;
+      waserror= True;
+    }
+    neighbor= otherfacet_(ridge, facet);
+    neighbor->seen= True;
+    if (!qh_setin(facet->neighbors, neighbor)) {
+      qh_fprintf(qh, qh->ferr, 6131, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
+           facet->id, neighbor->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }
+    if (!facet->newfacet && !neighbor->newfacet) {
+      if ((!ridge->tested) | ridge->nonconvex | ridge->mergevertex) {
+        qh_fprintf(qh, qh->ferr, 6384, "qhull internal error (qh_checkfacet): ridge r%d is nonconvex (%d), mergevertex (%d) or not tested (%d) for facet f%d, neighbor f%d\n",
+          ridge->id, ridge->nonconvex, ridge->mergevertex, ridge->tested, facet->id, neighbor->id);
+        errridge= ridge;
+        waserror= True;
+      }
+    }
+  }
+  if (!facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen) {
+        qh_fprintf(qh, qh->ferr, 6132, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
+              facet->id, neighbor->id);
+        errother= neighbor;
+        waserror= True;
+      }
+      intersection= qh_vertexintersect_new(qh, facet->vertices, neighbor->vertices);
+      qh_settemppush(qh, intersection);
+      FOREACHvertex_(facet->vertices) {
+        vertex->seen= False;
+        vertex->seen2= False;
+      }
+      FOREACHvertex_(intersection)
+        vertex->seen= True;
+      FOREACHridge_(facet->ridges) {
+        if (neighbor != otherfacet_(ridge, facet))
+            continue;
+        FOREACHvertex_(ridge->vertices) {
+          if (!vertex->seen) {
+            qh_fprintf(qh, qh->ferr, 6133, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
+                  vertex->id, ridge->id, facet->id, neighbor->id);
+            qh_errexit(qh, qh_ERRqhull, facet, ridge);
+          }
+          vertex->seen2= True;
+        }
+      }
+      if (!newmerge) {
+        FOREACHvertex_(intersection) {
+          if (!vertex->seen2) {
+            if (!qh->MERGING) {
+              qh_fprintf(qh, qh->ferr, 6420, "qhull topology error (qh_checkfacet): vertex v%d in f%d intersect f%d but not in a ridge.  Last point was p%d\n",
+                     vertex->id, facet->id, neighbor->id, qh->furthest_id);
+              if (!qh->FORCEoutput) {
+                qh_errprint(qh, "ERRONEOUS", facet, neighbor, NULL, vertex);
+                qh_errexit(qh, qh_ERRtopology, NULL, NULL);
+              }
+            }else {
+              trace4((qh, qh->ferr, 4025, "qh_checkfacet: vertex v%d in f%d intersect f%d but not in a ridge.  Repaired by qh_remove_extravertices in qh_reducevertices\n",
+                vertex->id, facet->id, neighbor->id));
+            }
+          }
+        }
+      }
+      qh_settempfree(qh, &intersection);
+    }
+  }else { /* simplicial */
+    FOREACHneighbor_(facet) {
+      if (neighbor->simplicial && !facet->degenerate && !neighbor->degenerate) {
+        skipA= SETindex_(facet->neighbors, neighbor);
+        skipB= qh_setindex(neighbor->neighbors, facet);
+        if (skipA<0 || skipB<0 || !qh_setequal_skip(facet->vertices, skipA, neighbor->vertices, skipB)) {
+          qh_fprintf(qh, qh->ferr, 6135, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
+                   facet->id, skipA, neighbor->id, skipB);
+          errother= neighbor;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (!newmerge && qh->CHECKduplicates && qh->hull_dim < 5 && (qh->IStracing > 2 || qh->CHECKfrequently)) {
+    FOREACHridge_i_(qh, facet->ridges) {           /* expensive, if was merge and qh_maybe_duplicateridges hasn't been called yet */
+      if (!ridge->mergevertex) {
+        for (i=ridge_i+1; i < ridge_n; i++) {
+          ridge2= SETelemt_(facet->ridges, i, ridgeT);
+          if (SETelem_(ridge->vertices, last_v) == SETelem_(ridge2->vertices, last_v)) { /* SETfirst is likely to be the same */
+            if (SETfirst_(ridge->vertices) == SETfirst_(ridge2->vertices)) {
+              if (qh_setequal(ridge->vertices, ridge2->vertices)) {
+                qh_fprintf(qh, qh->ferr, 6294, "qhull internal error (qh_checkfacet): ridges r%d and r%d (f%d) have the same vertices\n", /* same as duplicate ridge */
+                    ridge->id, ridge2->id, facet->id);
+                errridge= ridge;
+                waserror= True;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint(qh, "ERRONEOUS", facet, errother, errridge, NULL);
+    *waserrorp= True;
+  }
+} /* checkfacet */
+
+/*---------------------------------
+
+  qh_checkflipped_all(qh, facetlist )
+    checks orientation of facets in list against interior point
+
+  notes:
+    called by qh_checkoutput
+*/
+void qh_checkflipped_all(qhT *qh, facetT *facetlist) {
+  facetT *facet;
+  boolT waserror= False;
+  realT dist;
+
+  if (facetlist == qh->facet_list)
+    zzval_(Zflippedfacets)= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->normal && !qh_checkflipped(qh, facet, &dist, !qh_ALL)) {
+      qh_fprintf(qh, qh->ferr, 6136, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
+              facet->id, dist);
+      if (!qh->FORCEoutput) {
+        qh_errprint(qh, "ERRONEOUS", facet, NULL, NULL, NULL);
+        waserror= True;
+      }
+    }
+  }
+  if (waserror) {
+    qh_fprintf(qh, qh->ferr, 8101, "\n\
+A flipped facet occurs when its distance to the interior point is\n\
+greater than or equal to %2.2g, the maximum roundoff error.\n", -qh->DISTround);
+    qh_errexit(qh, qh_ERRprec, NULL, NULL);
+  }
+} /* checkflipped_all */
+
+/*---------------------------------
+
+  qh_checklists(qh, facetlist )
+    Check and repair facetlist and qh.vertex_list for infinite loops or overwritten facets
+    Checks that qh.newvertex_list is on qh.vertex_list
+    if facetlist is qh.facet_list
+      Checks that qh.visible_list and qh.newfacet_list are on qh.facet_list
+    Updates qh.facetvisit and qh.vertexvisit
+
+  returns:
+    True if no errors found
+    If false, repairs erroneous lists to prevent infinite loops by FORALL macros
+
+  notes:
+    called by qh_buildtracing, qh_checkpolygon, qh_collectstatistics, qh_printfacetlist, qh_printsummary
+    not called by qh_printlists
+
+  design:
+    if facetlist
+      check qh.facet_tail
+      for each facet
+        check for infinite loop or overwritten facet
+        check previous facet
+      if facetlist is qh.facet_list
+        check qh.next_facet, qh.visible_list and qh.newfacet_list
+    if vertexlist
+      check qh.vertex_tail
+      for each vertex
+        check for infinite loop or overwritten vertex
+        check previous vertex
+      check qh.newvertex_list
+*/
+boolT qh_checklists(qhT *qh, facetT *facetlist) {
+  facetT *facet, *errorfacet= NULL, *errorfacet2= NULL, *previousfacet;
+  vertexT *vertex, *vertexlist, *previousvertex, *errorvertex= NULL;
+  boolT waserror= False, newseen= False, nextseen= False, newvertexseen= False, visibleseen= False;
+
+  if (facetlist == qh->newfacet_list || facetlist == qh->visible_list) {
+    vertexlist= qh->vertex_list;
+    previousvertex= NULL;
+    trace2((qh, qh->ferr, 2110, "qh_checklists: check qh.%s_list f%d and qh.vertex_list v%d\n",
+        (facetlist == qh->newfacet_list ? "newfacet" : "visible"), facetlist->id, getid_(vertexlist)));
+  }else {
+    vertexlist= qh->vertex_list;
+    previousvertex= NULL;
+    trace2((qh, qh->ferr, 2111, "qh_checklists: check %slist f%d and qh.vertex_list v%d\n",
+        (facetlist == qh->facet_list ? "qh.facet_" : "facet"), getid_(facetlist), getid_(vertexlist)));
+  }
+  if (facetlist) {
+    if (qh->facet_tail == NULL || qh->facet_tail->id != 0 || qh->facet_tail->next != NULL) {
+      qh_fprintf(qh, qh->ferr, 6397, "qhull internal error (qh_checklists): either qh.facet_tail f%d is NULL, or its id is not 0, or its next is not NULL\n",
+          getid_(qh->facet_tail));
+      qh_errexit(qh, qh_ERRqhull, qh->facet_tail, NULL);
+    }
+    previousfacet= (facetlist == qh->facet_list ? NULL : facetlist->previous);
+    qh->visit_id++;
+    FORALLfacet_(facetlist) {
+      if (facet->visitid >= qh->visit_id || facet->id >= qh->facet_id) {
+        waserror= True;
+        errorfacet= facet;
+        errorfacet2= previousfacet;
+        if (facet->visitid == qh->visit_id)
+          qh_fprintf(qh, qh->ferr, 6039, "qhull internal error (qh_checklists): f%d already in facetlist causing an infinite loop ... f%d > f%d ... > f%d > f%d.  Truncate facetlist at f%d\n",
+            facet->id, facet->id, facet->next->id, getid_(previousfacet), facet->id, getid_(previousfacet));
+        else
+          qh_fprintf(qh, qh->ferr, 6350, "qhull internal error (qh_checklists): unknown or overwritten facet f%d, either id >= qh.facet_id (%d) or f.visitid %u > qh.visit_id %u.  Facetlist terminated at previous facet f%d\n",
+              facet->id, qh->facet_id, facet->visitid, qh->visit_id, getid_(previousfacet));
+        if (previousfacet)
+          previousfacet->next= qh->facet_tail;
+        else
+          facetlist= qh->facet_tail;
+        break;
+      }
+      facet->visitid= qh->visit_id;
+      if (facet->previous != previousfacet) {
+        qh_fprintf(qh, qh->ferr, 6416, "qhull internal error (qh_checklists): expecting f%d.previous == f%d.  Got f%d\n",
+          facet->id, getid_(previousfacet), getid_(facet->previous));
+        waserror= True;
+        errorfacet= facet;
+        errorfacet2= facet->previous;
+      }
+      previousfacet= facet;
+      if (facetlist == qh->facet_list) {
+        if (facet == qh->visible_list) {
+          if(newseen){
+            qh_fprintf(qh, qh->ferr, 6285, "qhull internal error (qh_checklists): qh.visible_list f%d is after qh.newfacet_list f%d.  It should be at, before, or NULL\n",
+              facet->id, getid_(qh->newfacet_list));
+            waserror= True;
+            errorfacet= facet;
+            errorfacet2= qh->newfacet_list;
+          }
+          visibleseen= True;
+        }
+        if (facet == qh->newfacet_list)
+          newseen= True;
+        if (facet == qh->facet_next)
+          nextseen= True;
+      }
+    }
+    if (facetlist == qh->facet_list) {
+      if (!nextseen && qh->facet_next && qh->facet_next->next) {
+        qh_fprintf(qh, qh->ferr, 6369, "qhull internal error (qh_checklists): qh.facet_next f%d for qh_addpoint is not on qh.facet_list f%d\n",
+          qh->facet_next->id, facetlist->id);
+        waserror= True;
+        errorfacet= qh->facet_next;
+        errorfacet2= facetlist;
+      }
+      if (!newseen && qh->newfacet_list && qh->newfacet_list->next) {
+        qh_fprintf(qh, qh->ferr, 6286, "qhull internal error (qh_checklists): qh.newfacet_list f%d is not on qh.facet_list f%d\n",
+          qh->newfacet_list->id, facetlist->id);
+        waserror= True;
+        errorfacet= qh->newfacet_list;
+        errorfacet2= facetlist;
+      }
+      if (!visibleseen && qh->visible_list && qh->visible_list->next) {
+        qh_fprintf(qh, qh->ferr, 6138, "qhull internal error (qh_checklists): qh.visible_list f%d is not on qh.facet_list f%d\n",
+          qh->visible_list->id, facetlist->id);
+        waserror= True;
+        errorfacet= qh->visible_list;
+        errorfacet2= facetlist;
+      }
+    }
+  }
+  if (vertexlist) {
+    if (qh->vertex_tail == NULL || qh->vertex_tail->id != 0 || qh->vertex_tail->next != NULL) {
+      qh_fprintf(qh, qh->ferr, 6366, "qhull internal error (qh_checklists): either qh.vertex_tail v%d is NULL, or its id is not 0, or its next is not NULL\n",
+           getid_(qh->vertex_tail));
+      qh_errprint(qh, "ERRONEOUS", errorfacet, errorfacet2, NULL, qh->vertex_tail);
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+    }
+    qh->vertex_visit++;
+    FORALLvertex_(vertexlist) {
+      if (vertex->visitid >= qh->vertex_visit || vertex->id >= qh->vertex_id) {
+        waserror= True;
+        errorvertex= vertex;
+        if (vertex->visitid == qh->visit_id)
+          qh_fprintf(qh, qh->ferr, 6367, "qhull internal error (qh_checklists): v%d already in vertexlist causing an infinite loop ... v%d > v%d ... > v%d > v%d.  Truncate vertexlist at v%d\n",
+            vertex->id, vertex->id, vertex->next->id, getid_(previousvertex), vertex->id, getid_(previousvertex));
+        else
+          qh_fprintf(qh, qh->ferr, 6368, "qhull internal error (qh_checklists): unknown or overwritten vertex v%d, either id >= qh.vertex_id (%d) or v.visitid %u > qh.visit_id %u.  vertexlist terminated at previous vertex v%d\n",
+            vertex->id, qh->vertex_id, vertex->visitid, qh->visit_id, getid_(previousvertex));
+        if (previousvertex)
+          previousvertex->next= qh->vertex_tail;
+        else
+          vertexlist= qh->vertex_tail;
+        break;
+      }
+      vertex->visitid= qh->vertex_visit;
+      if (vertex->previous != previousvertex) {
+        qh_fprintf(qh, qh->ferr, 6427, "qhull internal error (qh_checklists): expecting v%d.previous == v%d.  Got v%d\n",
+              vertex->id, getid_(previousvertex), getid_(vertex->previous));
+        waserror= True;
+        errorvertex= vertex;
+      }
+      previousvertex= vertex;
+      if(vertex == qh->newvertex_list)
+        newvertexseen= True;
+    }
+    if(!newvertexseen && qh->newvertex_list && qh->newvertex_list->next) {
+      qh_fprintf(qh, qh->ferr, 6287, "qhull internal error (qh_checklists): new vertex list v%d is not on vertex list\n", qh->newvertex_list->id);
+      waserror= True;
+      errorvertex= qh->newvertex_list;
+    }
+  }
+  if (waserror) {
+    qh_errprint(qh, "ERRONEOUS", errorfacet, errorfacet2, NULL, errorvertex);
+    return False;
+  }
+  return True;
+} /* checklists */
+
+/*---------------------------------
+
+  qh_checkpolygon(qh, facetlist )
+    checks the correctness of the structure
+
+  notes:
+    called by qh_addpoint, qh_all_vertexmerge, qh_check_output, qh_initialhull, qh_prepare_output, qh_triangulate
+    call with qh.facet_list or qh.newfacet_list or another list
+    checks num_facets and num_vertices if qh.facet_list
+
+  design:
+    check and repair lists for infinite loop
+    for each facet
+      check f.newfacet and f.visible
+      check facet and outside set if qh.NEWtentative and not f.newfacet, or not f.visible
+    initializes vertexlist for qh.facet_list or qh.newfacet_list
+    for each vertex
+      check vertex
+      check v.newfacet
+    for each facet
+      count f.ridges
+      check and count f.vertices
+    if checking qh.facet_list
+      check facet count
+      if qh.VERTEXneighbors
+        check and count v.neighbors for all vertices
+        check v.neighbors count and report possible causes of mismatch
+        check that facets are in their v.neighbors
+      check vertex count
+*/
+void qh_checkpolygon(qhT *qh, facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  facetT *errorfacet= NULL, *errorfacet2= NULL;
+  vertexT *vertex, **vertexp, *vertexlist;
+  int numfacets= 0, numvertices= 0, numridges= 0;
+  int totvneighbors= 0, totfacetvertices= 0;
+  boolT waserror= False, newseen= False, newvertexseen= False, nextseen= False, visibleseen= False;
+  boolT checkfacet;
+
+  trace1((qh, qh->ferr, 1027, "qh_checkpolygon: check all facets from f%d, qh.NEWtentative? %d\n", facetlist->id, qh->NEWtentative));
+  if (!qh_checklists(qh, facetlist)) {
+    waserror= True;
+    qh_fprintf(qh, qh->ferr, 6374, "qhull internal error: qh_checklists failed in qh_checkpolygon\n");
+    if (qh->num_facets < 4000)
+      qh_printlists(qh);
+  }
+  if (facetlist != qh->facet_list || qh->ONLYgood)
+    nextseen= True; /* allow f.outsideset */
+  FORALLfacet_(facetlist) {
+    if (facet == qh->visible_list)
+      visibleseen= True;
+    if (facet == qh->newfacet_list)
+      newseen= True;
+    if (facet->newfacet && !newseen && !visibleseen) {
+        qh_fprintf(qh, qh->ferr, 6289, "qhull internal error (qh_checkpolygon): f%d is 'newfacet' but it is not on qh.newfacet_list f%d or visible_list f%d\n",  facet->id, getid_(qh->newfacet_list), getid_(qh->visible_list));
+        qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    if (!facet->newfacet && newseen) {
+        qh_fprintf(qh, qh->ferr, 6292, "qhull internal error (qh_checkpolygon): f%d is on qh.newfacet_list f%d but it is not 'newfacet'\n",  facet->id, getid_(qh->newfacet_list));
+        qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    if (facet->visible != (visibleseen & !newseen)) {
+      if(facet->visible)
+        qh_fprintf(qh, qh->ferr, 6290, "qhull internal error (qh_checkpolygon): f%d is 'visible' but it is not on qh.visible_list f%d\n", facet->id, getid_(qh->visible_list));
+      else
+        qh_fprintf(qh, qh->ferr, 6291, "qhull internal error (qh_checkpolygon): f%d is on qh.visible_list f%d but it is not 'visible'\n", facet->id, qh->newfacet_list->id);
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    if (qh->NEWtentative) {
+      checkfacet= !facet->newfacet;
+    }else {
+      checkfacet= !facet->visible;
+    }
+    if(checkfacet) {
+      if (!nextseen) {
+        if (facet == qh->facet_next)  /* previous facets do not have outsideset */
+          nextseen= True;
+        else if (qh_setsize(qh, facet->outsideset)) {
+          if (!qh->NARROWhull
+#if !qh_COMPUTEfurthest
+          || facet->furthestdist >= qh->MINoutside
+#endif
+          ) {
+            qh_fprintf(qh, qh->ferr, 6137, "qhull internal error (qh_checkpolygon): f%d has outside points before qh.facet_next f%d\n",
+                     facet->id, getid_(qh->facet_next));
+            qh_errexit2(qh, qh_ERRqhull, facet, qh->facet_next);
+          }
+        }
+      }
+      numfacets++;
+      qh_checkfacet(qh, facet, False, &waserror);
+    }else if (facet->visible && qh->NEWfacets) {
+      if (!SETempty_(facet->neighbors) || !SETempty_(facet->ridges)) {
+        qh_fprintf(qh, qh->ferr, 6376, "qhull internal error (qh_checkpolygon): expecting empty f.neighbors and f.ridges for visible facet f%d.  Got %d neighbors and %d ridges\n",
+          facet->id, qh_setsize(qh, facet->neighbors), qh_setsize(qh, facet->ridges));
+        qh_errexit(qh, qh_ERRqhull, facet, NULL);
+      }
+    }
+  }
+  if (facetlist == qh->facet_list) {
+    vertexlist= qh->vertex_list;
+  }else if (facetlist == qh->newfacet_list) {
+    vertexlist= qh->newvertex_list;
+  }else {
+    vertexlist= NULL;
+  }
+  FORALLvertex_(vertexlist) {
+    qh_checkvertex(qh, vertex, !qh_ALL, &waserror);
+    if(vertex == qh->newvertex_list)
+      newvertexseen= True;
+    vertex->seen= False;
+    vertex->visitid= 0;
+    if(vertex->newfacet && !newvertexseen && !vertex->deleted) {
+      qh_fprintf(qh, qh->ferr, 6288, "qhull internal error (qh_checkpolygon): v%d is 'newfacet' but it is not on new vertex list v%d\n", vertex->id, getid_(qh->newvertex_list));
+      qh_errexit(qh, qh_ERRqhull, qh->visible_list, NULL);
+    }
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->visible)
+      continue;
+    if (facet->simplicial)
+      numridges += qh->hull_dim;
+    else
+      numridges += qh_setsize(qh, facet->ridges);
+    FOREACHvertex_(facet->vertices) {
+      vertex->visitid++;
+      if (!vertex->seen) {
+        vertex->seen= True;
+        numvertices++;
+        if (qh_pointid(qh, vertex->point) == qh_IDunknown) {
+          qh_fprintf(qh, qh->ferr, 6139, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
+                   (void *) vertex->point, vertex->id, (void *) qh->first_point);
+          waserror= True;
+        }
+      }
+    }
+  }
+  qh->vertex_visit += (unsigned int)numfacets;
+  if (facetlist == qh->facet_list) {
+    if (numfacets != qh->num_facets - qh->num_visible) {
+      qh_fprintf(qh, qh->ferr, 6140, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
+              numfacets, qh->num_facets, qh->num_visible);
+      waserror= True;
+    }
+    qh->vertex_visit++;
+    if (qh->VERTEXneighbors) {
+      FORALLvertices {
+        if (!vertex->neighbors) {
+          qh_fprintf(qh, qh->ferr, 6407, "qhull internal error (qh_checkpolygon): missing vertex neighbors for v%d\n", vertex->id);
+          waserror= True;
+        }
+        qh_setcheck(qh, vertex->neighbors, "neighbors for v", vertex->id);
+        if (vertex->deleted)
+          continue;
+        totvneighbors += qh_setsize(qh, vertex->neighbors);
+      }
+      FORALLfacet_(facetlist) {
+        if (!facet->visible)
+          totfacetvertices += qh_setsize(qh, facet->vertices);
+      }
+      if (totvneighbors != totfacetvertices) {
+        qh_fprintf(qh, qh->ferr, 6141, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent (tot_vneighbors %d != tot_facetvertices %d).  Maybe duplicate or missing vertex\n",
+                totvneighbors, totfacetvertices);
+        waserror= True;
+        FORALLvertices {
+          if (vertex->deleted)
+            continue;
+          qh->visit_id++;
+          FOREACHneighbor_(vertex) {
+            if (neighbor->visitid==qh->visit_id) {
+              qh_fprintf(qh, qh->ferr, 6275, "qhull internal error (qh_checkpolygon): facet f%d occurs twice in neighbors of vertex v%d\n",
+                  neighbor->id, vertex->id);
+              errorfacet2= errorfacet;
+              errorfacet= neighbor;
+            }
+            neighbor->visitid= qh->visit_id;
+            if (!qh_setin(neighbor->vertices, vertex)) {
+              qh_fprintf(qh, qh->ferr, 6276, "qhull internal error (qh_checkpolygon): facet f%d is a neighbor of vertex v%d but v%d is not a vertex of f%d\n",
+                  neighbor->id, vertex->id, vertex->id, neighbor->id);
+              errorfacet2= errorfacet;
+              errorfacet= neighbor;
+            }
+          }
+        }
+        FORALLfacet_(facetlist){
+          if (!facet->visible) {
+            /* vertices are inverse sorted and are unlikely to be duplicated */
+            FOREACHvertex_(facet->vertices){
+              if (!qh_setin(vertex->neighbors, facet)) {
+                qh_fprintf(qh, qh->ferr, 6277, "qhull internal error (qh_checkpolygon): v%d is a vertex of facet f%d but f%d is not a neighbor of v%d\n",
+                  vertex->id, facet->id, facet->id, vertex->id);
+                errorfacet2= errorfacet;
+                errorfacet= facet;
+              }
+            }
+          }
+        }
+      }
+    }
+    if (numvertices != qh->num_vertices - qh_setsize(qh, qh->del_vertices)) {
+      qh_fprintf(qh, qh->ferr, 6142, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
+              numvertices, qh->num_vertices - qh_setsize(qh, qh->del_vertices));
+      waserror= True;
+    }
+    if (qh->hull_dim == 2 && numvertices != numfacets) {
+      qh_fprintf(qh, qh->ferr, 6143, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
+        numvertices, numfacets);
+      waserror= True;
+    }
+    if (qh->hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
+      qh_fprintf(qh, qh->ferr, 7063, "qhull warning: #vertices %d + #facets %d - #edges %d != 2.  A vertex appears twice in a edge list.  May occur during merging.\n",
+          numvertices, numfacets, numridges/2);
+      /* occurs if lots of merging and a vertex ends up twice in an edge list.  e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
+    }
+  }
+  if (waserror)
+    qh_errexit2(qh, qh_ERRqhull, errorfacet, errorfacet2);
+} /* checkpolygon */
+
+
+/*---------------------------------
+
+  qh_checkvertex(qh, vertex, allchecks, &waserror )
+    check vertex for consistency
+    if allchecks, checks vertex->neighbors
+
+  returns:
+    sets waserror if any error occurs
+
+  notes:
+    called by qh_tracemerge and qh_checkpolygon
+    neighbors checked efficiently in qh_checkpolygon
+*/
+void qh_checkvertex(qhT *qh, vertexT *vertex, boolT allchecks, boolT *waserrorp) {
+  boolT waserror= False;
+  facetT *neighbor, **neighborp, *errfacet=NULL;
+
+  if (qh_pointid(qh, vertex->point) == qh_IDunknown) {
+    qh_fprintf(qh, qh->ferr, 6144, "qhull internal error (qh_checkvertex): unknown point id %p\n", (void *) vertex->point);
+    waserror= True;
+  }
+  if (vertex->id >= qh->vertex_id) {
+    qh_fprintf(qh, qh->ferr, 6145, "qhull internal error (qh_checkvertex): unknown vertex id v%d >= qh.vertex_id (%d)\n", vertex->id, qh->vertex_id);
+    waserror= True;
+  }
+  if (vertex->visitid > qh->vertex_visit) {
+    qh_fprintf(qh, qh->ferr, 6413, "qhull internal error (qh_checkvertex): expecting v%d.visitid <= qh.vertex_visit (%d).  Got visitid %d\n", vertex->id, qh->vertex_visit, vertex->visitid);
+    waserror= True;
+  }
+  if (allchecks && !waserror && !vertex->deleted) {
+    if (qh_setsize(qh, vertex->neighbors)) {
+      FOREACHneighbor_(vertex) {
+        if (!qh_setin(neighbor->vertices, vertex)) {
+          qh_fprintf(qh, qh->ferr, 6146, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
+          errfacet= neighbor;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint(qh, "ERRONEOUS", NULL, NULL, NULL, vertex);
+    if (errfacet)
+      qh_errexit(qh, qh_ERRqhull, errfacet, NULL);
+    *waserrorp= True;
+  }
+} /* checkvertex */
+
+/*---------------------------------
+
+  qh_clearcenters(qh, type )
+    clear old data from facet->center
+
+  notes:
+    sets new centertype
+    nop if CENTERtype is the same
+*/
+void qh_clearcenters(qhT *qh, qh_CENTER type) {
+  facetT *facet;
+
+  if (qh->CENTERtype != type) {
+    FORALLfacets {
+      if (facet->tricoplanar && !facet->keepcentrum)
+          facet->center= NULL;  /* center is owned by the ->keepcentrum facet */
+      else if (qh->CENTERtype == qh_ASvoronoi){
+        if (facet->center) {
+          qh_memfree(qh, facet->center, qh->center_size);
+          facet->center= NULL;
+        }
+      }else /* qh.CENTERtype == qh_AScentrum */ {
+        if (facet->center) {
+          qh_memfree(qh, facet->center, qh->normal_size);
+          facet->center= NULL;
+        }
+      }
+    }
+    qh->CENTERtype= type;
+  }
+  trace2((qh, qh->ferr, 2043, "qh_clearcenters: switched to center type %d\n", type));
+} /* clearcenters */
+
+/*---------------------------------
+
+  qh_createsimplex(qh, vertices )
+    creates a simplex from a set of vertices
+
+  returns:
+    initializes qh.facet_list to the simplex
+
+  notes:
+    only called by qh_initialhull
+
+  design:
+    for each vertex
+      create a new facet
+    for each new facet
+      create its neighbor set
+*/
+void qh_createsimplex(qhT *qh, setT *vertices /* qh.facet_list */) {
+  facetT *facet= NULL, *newfacet;
+  boolT toporient= True;
+  int vertex_i, vertex_n, nth;
+  setT *newfacets= qh_settemp(qh, qh->hull_dim+1);
+  vertexT *vertex;
+
+  FOREACHvertex_i_(qh, vertices) {
+    newfacet= qh_newfacet(qh);
+    newfacet->vertices= qh_setnew_delnthsorted(qh, vertices, vertex_n, vertex_i, 0);
+    if (toporient)
+      newfacet->toporient= True;
+    qh_appendfacet(qh, newfacet);
+    newfacet->newfacet= True;
+    qh_appendvertex(qh, vertex);
+    qh_setappend(qh, &newfacets, newfacet);
+    toporient ^= True;
+  }
+  FORALLnew_facets {
+    nth= 0;
+    FORALLfacet_(qh->newfacet_list) {
+      if (facet != newfacet)
+        SETelem_(newfacet->neighbors, nth++)= facet;
+    }
+    qh_settruncate(qh, newfacet->neighbors, qh->hull_dim);
+  }
+  qh_settempfree(qh, &newfacets);
+  trace1((qh, qh->ferr, 1028, "qh_createsimplex: created simplex\n"));
+} /* createsimplex */
+
+/*---------------------------------
+
+  qh_delridge(qh, ridge )
+    delete a ridge's vertices and frees its memory
+
+  notes:
+    assumes r.top->ridges and r.bottom->ridges have been updated
+*/
+void qh_delridge(qhT *qh, ridgeT *ridge) {
+
+  if (ridge == qh->traceridge)
+    qh->traceridge= NULL;
+  qh_setfree(qh, &(ridge->vertices));
+  qh_memfree(qh, ridge, (int)sizeof(ridgeT));
+} /* delridge */
+
+/*---------------------------------
+
+  qh_delvertex(qh, vertex )
+    deletes a vertex and frees its memory
+
+  notes:
+    assumes vertex->adjacencies have been updated if needed
+    unlinks from vertex_list
+*/
+void qh_delvertex(qhT *qh, vertexT *vertex) {
+
+  if (vertex->deleted && !vertex->partitioned && !qh->NOerrexit) {
+    qh_fprintf(qh, qh->ferr, 6395, "qhull internal error (qh_delvertex): vertex v%d was deleted but it was not partitioned as a coplanar point\n",
+      vertex->id);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  if (vertex == qh->tracevertex)
+    qh->tracevertex= NULL;
+  qh_removevertex(qh, vertex);
+  qh_setfree(qh, &vertex->neighbors);
+  qh_memfree(qh, vertex, (int)sizeof(vertexT));
+} /* delvertex */
+
+
+/*---------------------------------
+
+  qh_facet3vertex(qh )
+    return temporary set of 3-d vertices in qh_ORIENTclock order
+
+  design:
+    if simplicial facet
+      build set from facet->vertices with facet->toporient
+    else
+      for each ridge in order
+        build set from ridge's vertices
+*/
+setT *qh_facet3vertex(qhT *qh, facetT *facet) {
+  ridgeT *ridge, *firstridge;
+  vertexT *vertex;
+  int cntvertices, cntprojected=0;
+  setT *vertices;
+
+  cntvertices= qh_setsize(qh, facet->vertices);
+  vertices= qh_settemp(qh, cntvertices);
+  if (facet->simplicial) {
+    if (cntvertices != 3) {
+      qh_fprintf(qh, qh->ferr, 6147, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
+                  cntvertices, facet->id);
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    qh_setappend(qh, &vertices, SETfirst_(facet->vertices));
+    if (facet->toporient ^ qh_ORIENTclock)
+      qh_setappend(qh, &vertices, SETsecond_(facet->vertices));
+    else
+      qh_setaddnth(qh, &vertices, 0, SETsecond_(facet->vertices));
+    qh_setappend(qh, &vertices, SETelem_(facet->vertices, 2));
+  }else {
+    ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);   /* no infinite */
+    while ((ridge= qh_nextridge3d(ridge, facet, &vertex))) {
+      qh_setappend(qh, &vertices, vertex);
+      if (++cntprojected > cntvertices || ridge == firstridge)
+        break;
+    }
+    if (!ridge || cntprojected != cntvertices) {
+      qh_fprintf(qh, qh->ferr, 6148, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up.  got at least %d\n",
+                  facet->id, cntprojected);
+      qh_errexit(qh, qh_ERRqhull, facet, ridge);
+    }
+  }
+  return vertices;
+} /* facet3vertex */
+
+/*---------------------------------
+
+  qh_findbestfacet(qh, point, bestoutside, bestdist, isoutside )
+    find facet that is furthest below a point
+
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    if bestoutside is set (e.g., qh_ALL)
+      returns best facet that is not upperdelaunay
+      if Delaunay and inside, point is outside circumsphere of bestfacet
+    else
+      returns first facet below point
+      if point is inside, returns nearest, !upperdelaunay facet
+    distance to facet
+    isoutside set if outside of facet
+
+  notes:
+    Distance is measured by distance to the facet's hyperplane.  For
+    Delaunay facets, this is not the same as the containing facet.  It may
+    be an adjacent facet or a different tricoplanar facet.  See
+    locate a facet with qh_findbestfacet()
+
+    For tricoplanar facets, this finds one of the tricoplanar facets closest
+    to the point.
+
+    If inside, qh_findbestfacet performs an exhaustive search
+       this may be too conservative.  Sometimes it is clearly required.
+
+    qh_findbestfacet is not used by qhull.
+    uses qh.visit_id and qh.coplanarset
+
+  see:
+    qh_findbest
+*/
+facetT *qh_findbestfacet(qhT *qh, pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside) {
+  facetT *bestfacet= NULL;
+  int numpart, totpart= 0;
+
+  bestfacet= qh_findbest(qh, point, qh->facet_list,
+                            bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
+                            bestdist, isoutside, &totpart);
+  if (*bestdist < -qh->DISTround) {
+    bestfacet= qh_findfacet_all(qh, point, !qh_NOupper, bestdist, isoutside, &numpart);
+    totpart += numpart;
+    if ((isoutside && *isoutside && bestoutside)
+    || (isoutside && !*isoutside && bestfacet->upperdelaunay)) {
+      bestfacet= qh_findbest(qh, point, bestfacet,
+                            bestoutside, False, bestoutside,
+                            bestdist, isoutside, &totpart);
+      totpart += numpart;
+    }
+  }
+  trace3((qh, qh->ferr, 3014, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
+          bestfacet->id, *bestdist, (isoutside ? *isoutside : UINT_MAX), totpart));
+  return bestfacet;
+} /* findbestfacet */
+
+/*---------------------------------
+
+  qh_findbestlower(qh, facet, point, bestdist, numpart )
+    returns best non-upper, non-flipped neighbor of facet for point
+    if needed, searches vertex neighbors
+
+  returns:
+    returns bestdist and updates numpart
+
+  notes:
+    called by qh_findbest() for points above an upperdelaunay facet
+    if Delaunay and inside, point is outside of circumsphere of bestfacet
+
+*/
+facetT *qh_findbestlower(qhT *qh, facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart) {
+  facetT *neighbor, **neighborp, *bestfacet= NULL;
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  realT dist;
+  vertexT *vertex;
+  boolT isoutside= False;  /* not used */
+
+  zinc_(Zbestlower);
+  FOREACHneighbor_(upperfacet) {
+    if (neighbor->upperdelaunay || neighbor->flipped)
+      continue;
+    (*numpart)++;
+    qh_distplane(qh, point, neighbor, &dist);
+    if (dist > bestdist) {
+      bestfacet= neighbor;
+      bestdist= dist;
+    }
+  }
+  if (!bestfacet) {
+    zinc_(Zbestlowerv);
+    /* rarely called, numpart does not count nearvertex computations */
+    vertex= qh_nearvertex(qh, upperfacet, point, &dist);
+    qh_vertexneighbors(qh);
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay || neighbor->flipped)
+        continue;
+      (*numpart)++;
+      qh_distplane(qh, point, neighbor, &dist);
+      if (dist > bestdist) {
+        bestfacet= neighbor;
+        bestdist= dist;
+      }
+    }
+  }
+  if (!bestfacet) {
+    zinc_(Zbestlowerall);  /* invoked once per point in outsideset */
+    zmax_(Zbestloweralln, qh->num_facets);
+    /* [dec'15] Previously reported as QH6228 */
+    trace3((qh, qh->ferr, 3025, "qh_findbestlower: all neighbors of facet %d are flipped or upper Delaunay.  Search all facets\n",
+        upperfacet->id));
+    /* rarely called */
+    bestfacet= qh_findfacet_all(qh, point, qh_NOupper, &bestdist, &isoutside, numpart);
+  }
+  *bestdistp= bestdist;
+  trace3((qh, qh->ferr, 3015, "qh_findbestlower: f%d dist %2.2g for f%d p%d\n",
+          bestfacet->id, bestdist, upperfacet->id, qh_pointid(qh, point)));
+  return bestfacet;
+} /* findbestlower */
+
+/*---------------------------------
+
+  qh_findfacet_all(qh, point, noupper, bestdist, isoutside, numpart )
+    exhaustive search for facet below a point
+    ignore flipped and visible facets, f.normal==NULL, and if noupper, f.upperdelaunay facets
+
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    returns first facet below point
+    if point is inside,
+      returns nearest facet
+    distance to facet
+    isoutside if point is outside of the hull
+    number of distance tests
+
+  notes:
+    called by qh_findbestlower if all neighbors are flipped or upper Delaunay (QH3025)
+    primarily for library users (qh_findbestfacet), rarely used by Qhull
+*/
+facetT *qh_findfacet_all(qhT *qh, pointT *point, boolT noupper, realT *bestdist, boolT *isoutside,
+                          int *numpart) {
+  facetT *bestfacet= NULL, *facet;
+  realT dist;
+  int totpart= 0;
+
+  *bestdist= -REALmax;
+  *isoutside= False;
+  FORALLfacets {
+    if (facet->flipped || !facet->normal || facet->visible)
+      continue;
+    if (noupper && facet->upperdelaunay)
+      continue;
+    totpart++;
+    qh_distplane(qh, point, facet, &dist);
+    if (dist > *bestdist) {
+      *bestdist= dist;
+      bestfacet= facet;
+      if (dist > qh->MINoutside) {
+        *isoutside= True;
+        break;
+      }
+    }
+  }
+  *numpart= totpart;
+  trace3((qh, qh->ferr, 3016, "qh_findfacet_all: p%d, noupper? %d, f%d, dist %2.2g, isoutside %d, totpart %d\n",
+      qh_pointid(qh, point), noupper, getid_(bestfacet), *bestdist, *isoutside, totpart));
+  return bestfacet;
+} /* findfacet_all */
+
+/*---------------------------------
+
+  qh_findgood(qh, facetlist, goodhorizon )
+    identify good facets for qh.PRINTgood and qh_buildcone_onlygood
+    goodhorizon is count of good, horizon facets from qh_find_horizon, otherwise 0 from qh_findgood_all
+    if not qh.MERGING and qh.GOODvertex>0
+      facet includes point as vertex
+      if !match, returns goodhorizon
+    if qh.GOODpoint
+      facet is visible or coplanar (>0) or not visible (<0)
+    if qh.GOODthreshold
+      facet->normal matches threshold
+    if !goodhorizon and !match,
+      selects facet with closest angle to thresholds
+      sets GOODclosest
+
+  returns:
+    number of new, good facets found
+    determines facet->good
+    may update qh.GOODclosest
+
+  notes:
+    called from qh_initbuild, qh_buildcone_onlygood, and qh_findgood_all
+    qh_findgood_all (called from qh_prepare_output) further reduces the good region
+
+  design:
+    count good facets
+    if not merging, clear good facets that fail qh.GOODvertex ('QVn', but not 'QV-n')
+    clear good facets that fail qh.GOODpoint ('QGn' or 'QG-n')
+    clear good facets that fail qh.GOODthreshold
+    if !goodhorizon and !find f.good,
+      sets GOODclosest to facet with closest angle to thresholds
+*/
+int qh_findgood(qhT *qh, facetT *facetlist, int goodhorizon) {
+  facetT *facet, *bestfacet= NULL;
+  realT angle, bestangle= REALmax, dist;
+  int  numgood=0;
+
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh->GOODvertex>0 && !qh->MERGING) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && !qh_isvertex(qh->GOODvertexp, facet->vertices)) {
+        facet->good= False;
+        numgood--;
+      }
+    }
+  }
+  if (qh->GOODpoint && numgood) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        zinc_(Zdistgood);
+        qh_distplane(qh, qh->GOODpointp, facet, &dist);
+        if ((qh->GOODpoint > 0) ^ (dist > 0.0)) {
+          facet->good= False;
+          numgood--;
+        }
+      }
+    }
+  }
+  if (qh->GOODthreshold && (numgood || goodhorizon || qh->GOODclosest)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        if (!qh_inthresholds(qh, facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (numgood == 0 && (goodhorizon == 0 || qh->GOODclosest)) {
+      if (qh->GOODclosest) {
+        if (qh->GOODclosest->visible)
+          qh->GOODclosest= NULL;
+        else {
+          qh_inthresholds(qh, qh->GOODclosest->normal, &angle);
+          if (angle < bestangle)
+            bestfacet= qh->GOODclosest;
+        }
+      }
+      if (bestfacet && bestfacet != qh->GOODclosest) {   /* numgood == 0 */
+        if (qh->GOODclosest)
+          qh->GOODclosest->good= False;
+        qh->GOODclosest= bestfacet;
+        bestfacet->good= True;
+        numgood++;
+        trace2((qh, qh->ferr, 2044, "qh_findgood: f%d is closest(%2.2g) to thresholds\n",
+           bestfacet->id, bestangle));
+        return numgood;
+      }
+    }else if (qh->GOODclosest) { /* numgood > 0 */
+      qh->GOODclosest->good= False;
+      qh->GOODclosest= NULL;
+    }
+  }
+  zadd_(Zgoodfacet, numgood);
+  trace2((qh, qh->ferr, 2045, "qh_findgood: found %d good facets with %d good horizon and qh.GOODclosest f%d\n",
+               numgood, goodhorizon, getid_(qh->GOODclosest)));
+  if (!numgood && qh->GOODvertex>0 && !qh->MERGING)
+    return goodhorizon;
+  return numgood;
+} /* findgood */
+
+/*---------------------------------
+
+  qh_findgood_all(qh, facetlist )
+    apply other constraints for good facets (used by qh.PRINTgood)
+    if qh.GOODvertex
+      facet includes (>0) or doesn't include (<0) point as vertex
+      if last good facet and ONLYgood, prints warning and continues
+    if qh.SPLITthresholds (e.g., qh.DELAUNAY)
+      facet->normal matches threshold, or if none, the closest one
+    calls qh_findgood
+    nop if good not used
+
+  returns:
+    clears facet->good if not good
+    sets qh.num_good
+
+  notes:
+    called by qh_prepare_output and qh_printneighborhood
+    unless qh.ONLYgood, calls qh_findgood first
+
+  design:
+    uses qh_findgood to mark good facets
+    clear f.good for failed qh.GOODvertex
+    clear f.good for failed qh.SPLITthreholds
+       if no more good facets, select best of qh.SPLITthresholds
+*/
+void qh_findgood_all(qhT *qh, facetT *facetlist) {
+  facetT *facet, *bestfacet=NULL;
+  realT angle, bestangle= REALmax;
+  int  numgood=0, startgood;
+
+  if (!qh->GOODvertex && !qh->GOODthreshold && !qh->GOODpoint
+  && !qh->SPLITthresholds)
+    return;
+  if (!qh->ONLYgood)
+    qh_findgood(qh, qh->facet_list, 0);
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh->GOODvertex <0 || (qh->GOODvertex > 0 && qh->MERGING)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && ((qh->GOODvertex > 0) ^ !!qh_isvertex(qh->GOODvertexp, facet->vertices))) { /* convert to bool */
+        if (!--numgood) {
+          if (qh->ONLYgood) {
+            qh_fprintf(qh, qh->ferr, 7064, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
+               qh_pointid(qh, qh->GOODvertexp), facet->id);
+            return;
+          }else if (qh->GOODvertex > 0)
+            qh_fprintf(qh, qh->ferr, 7065, "qhull warning: point p%d is not a vertex('QV%d').\n",
+                qh->GOODvertex-1, qh->GOODvertex-1);
+          else
+            qh_fprintf(qh, qh->ferr, 7066, "qhull warning: point p%d is a vertex for every facet('QV-%d').\n",
+                -qh->GOODvertex - 1, -qh->GOODvertex - 1);
+        }
+        facet->good= False;
+      }
+    }
+  }
+  startgood= numgood;
+  if (qh->SPLITthresholds) {
+    FORALLfacet_(facetlist) {
+      if (facet->good) {
+        if (!qh_inthresholds(qh, facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (!numgood && bestfacet) {
+      bestfacet->good= True;
+      numgood++;
+      trace0((qh, qh->ferr, 23, "qh_findgood_all: f%d is closest(%2.2g) to split thresholds\n",
+           bestfacet->id, bestangle));
+      return;
+    }
+  }
+  if (numgood == 1 && !qh->PRINTgood && qh->GOODclosest && qh->GOODclosest->good) {
+    trace2((qh, qh->ferr, 2109, "qh_findgood_all: undo selection of qh.GOODclosest f%d since it would fail qh_inthresholds in qh_skipfacet\n",
+      qh->GOODclosest->id));
+    qh->GOODclosest->good= False;
+    numgood= 0;
+  }
+  qh->num_good= numgood;
+  trace0((qh, qh->ferr, 24, "qh_findgood_all: %d good facets remain out of %d facets\n",
+        numgood, startgood));
+} /* findgood_all */
+
+/*---------------------------------
+
+  qh_furthestnext()
+    set qh.facet_next to facet with furthest of all furthest points
+    searches all facets on qh.facet_list
+
+  notes:
+    this may help avoid precision problems
+*/
+void qh_furthestnext(qhT *qh /* qh.facet_list */) {
+  facetT *facet, *bestfacet= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FORALLfacets {
+    if (facet->outsideset) {
+#if qh_COMPUTEfurthest
+      pointT *furthest;
+      furthest= (pointT *)qh_setlast(facet->outsideset);
+      zinc_(Zcomputefurthest);
+      qh_distplane(qh, furthest, facet, &dist);
+#else
+      dist= facet->furthestdist;
+#endif
+      if (dist > bestdist) {
+        bestfacet= facet;
+        bestdist= dist;
+      }
+    }
+  }
+  if (bestfacet) {
+    qh_removefacet(qh, bestfacet);
+    qh_prependfacet(qh, bestfacet, &qh->facet_next);
+    trace1((qh, qh->ferr, 1029, "qh_furthestnext: made f%d next facet(dist %.2g)\n",
+            bestfacet->id, bestdist));
+  }
+} /* furthestnext */
+
+/*---------------------------------
+
+  qh_furthestout(qh, facet )
+    make furthest outside point the last point of outsideset
+
+  returns:
+    updates facet->outsideset
+    clears facet->notfurthest
+    sets facet->furthestdist
+
+  design:
+    determine best point of outsideset
+    make it the last point of outsideset
+*/
+void qh_furthestout(qhT *qh, facetT *facet) {
+  pointT *point, **pointp, *bestpoint= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FOREACHpoint_(facet->outsideset) {
+    qh_distplane(qh, point, facet, &dist);
+    zinc_(Zcomputefurthest);
+    if (dist > bestdist) {
+      bestpoint= point;
+      bestdist= dist;
+    }
+  }
+  if (bestpoint) {
+    qh_setdel(facet->outsideset, point);
+    qh_setappend(qh, &facet->outsideset, point);
+#if !qh_COMPUTEfurthest
+    facet->furthestdist= bestdist;
+#endif
+  }
+  facet->notfurthest= False;
+  trace3((qh, qh->ferr, 3017, "qh_furthestout: p%d is furthest outside point of f%d\n",
+          qh_pointid(qh, point), facet->id));
+} /* furthestout */
+
+
+/*---------------------------------
+
+  qh_infiniteloop(qh, facet )
+    report infinite loop error due to facet
+*/
+void qh_infiniteloop(qhT *qh, facetT *facet) {
+
+  qh_fprintf(qh, qh->ferr, 6149, "qhull internal error (qh_infiniteloop): potential infinite loop detected.  If visible, f.replace. If newfacet, f.samecycle\n");
+  qh_errexit(qh, qh_ERRqhull, facet, NULL);
+} /* qh_infiniteloop */
+
+/*---------------------------------
+
+  qh_initbuild()
+    initialize hull and outside sets with point array
+    qh.FIRSTpoint/qh.NUMpoints is point array
+    if qh.GOODpoint
+      adds qh.GOODpoint to initial hull
+
+  returns:
+    qh_facetlist with initial hull
+    points partitioned into outside sets, coplanar sets, or inside
+    initializes qh.GOODpointp, qh.GOODvertexp,
+
+  design:
+    initialize global variables used during qh_buildhull
+    determine precision constants and points with max/min coordinate values
+      if qh.SCALElast, scale last coordinate(for 'd')
+    initialize qh.newfacet_list, qh.facet_tail
+    initialize qh.vertex_list, qh.newvertex_list, qh.vertex_tail
+    determine initial vertices
+    build initial simplex
+    partition input points into facets of initial simplex
+    set up lists
+    if qh.ONLYgood
+      check consistency
+      add qh.GOODvertex if defined
+*/
+void qh_initbuild(qhT *qh) {
+  setT *maxpoints, *vertices;
+  facetT *facet;
+  int i, numpart;
+  realT dist;
+  boolT isoutside;
+
+  if (qh->PRINTstatistics) {
+    qh_fprintf(qh, qh->ferr, 9350, "qhull %s Statistics: %s | %s\n",
+      qh_version, qh->rbox_command, qh->qhull_command);
+    fflush(NULL);
+  }
+  qh->furthest_id= qh_IDunknown;
+  qh->lastreport= 0;
+  qh->lastfacets= 0;
+  qh->lastmerges= 0;
+  qh->lastplanes= 0;
+  qh->lastdist= 0;
+  qh->facet_id= qh->vertex_id= qh->ridge_id= 0;
+  qh->visit_id= qh->vertex_visit= 0;
+  qh->maxoutdone= False;
+
+  if (qh->GOODpoint > 0)
+    qh->GOODpointp= qh_point(qh, qh->GOODpoint-1);
+  else if (qh->GOODpoint < 0)
+    qh->GOODpointp= qh_point(qh, -qh->GOODpoint-1);
+  if (qh->GOODvertex > 0)
+    qh->GOODvertexp= qh_point(qh, qh->GOODvertex-1);
+  else if (qh->GOODvertex < 0)
+    qh->GOODvertexp= qh_point(qh, -qh->GOODvertex-1);
+  if ((qh->GOODpoint
+       && (qh->GOODpointp < qh->first_point  /* also catches !GOODpointp */
+           || qh->GOODpointp > qh_point(qh, qh->num_points-1)))
+  || (qh->GOODvertex
+       && (qh->GOODvertexp < qh->first_point  /* also catches !GOODvertexp */
+           || qh->GOODvertexp > qh_point(qh, qh->num_points-1)))) {
+    qh_fprintf(qh, qh->ferr, 6150, "qhull input error: either QGn or QVn point is > p%d\n",
+             qh->num_points-1);
+    qh_errexit(qh, qh_ERRinput, NULL, NULL);
+  }
+  maxpoints= qh_maxmin(qh, qh->first_point, qh->num_points, qh->hull_dim);
+  if (qh->SCALElast)
+    qh_scalelast(qh, qh->first_point, qh->num_points, qh->hull_dim, qh->MINlastcoord, qh->MAXlastcoord, qh->MAXabs_coord);
+  qh_detroundoff(qh);
+  if (qh->DELAUNAY && qh->upper_threshold[qh->hull_dim-1] > REALmax/2
+                  && qh->lower_threshold[qh->hull_dim-1] < -REALmax/2) {
+    for (i=qh_PRINTEND; i--; ) {
+      if (qh->PRINTout[i] == qh_PRINTgeom && qh->DROPdim < 0
+          && !qh->GOODthreshold && !qh->SPLITthresholds)
+        break;  /* in this case, don't set upper_threshold */
+    }
+    if (i < 0) {
+      if (qh->UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
+        qh->lower_threshold[qh->hull_dim-1]= qh->ANGLEround * qh_ZEROdelaunay;
+        qh->GOODthreshold= True;
+      }else {
+        qh->upper_threshold[qh->hull_dim-1]= -qh->ANGLEround * qh_ZEROdelaunay;
+        if (!qh->GOODthreshold)
+          qh->SPLITthresholds= True; /* build upper-convex hull even if Qg */
+          /* qh_initqhull_globals errors if Qg without Pdk/etc. */
+      }
+    }
+  }
+  trace4((qh, qh->ferr, 4091, "qh_initbuild: create sentinels for qh.facet_tail and qh.vertex_tail\n"));
+  qh->facet_list= qh->newfacet_list= qh->facet_tail= qh_newfacet(qh);
+  qh->num_facets= qh->num_vertices= qh->num_visible= 0;
+  qh->vertex_list= qh->newvertex_list= qh->vertex_tail= qh_newvertex(qh, NULL);
+  vertices= qh_initialvertices(qh, qh->hull_dim, maxpoints, qh->first_point, qh->num_points);
+  qh_initialhull(qh, vertices);  /* initial qh->facet_list */
+  qh_partitionall(qh, vertices, qh->first_point, qh->num_points);
+  if (qh->PRINToptions1st || qh->TRACElevel || qh->IStracing) {
+    if (qh->TRACElevel || qh->IStracing)
+      qh_fprintf(qh, qh->ferr, 8103, "\nTrace level T%d, IStracing %d, point TP%d, merge TM%d, dist TW%2.2g, qh.tracefacet_id %d, traceridge_id %d, tracevertex_id %d, last qh.RERUN %d, %s | %s\n",
+         qh->TRACElevel, qh->IStracing, qh->TRACEpoint, qh->TRACEmerge, qh->TRACEdist, qh->tracefacet_id, qh->traceridge_id, qh->tracevertex_id, qh->TRACElastrun, qh->rbox_command, qh->qhull_command);
+    qh_fprintf(qh, qh->ferr, 8104, "Options selected for Qhull %s:\n%s\n", qh_version, qh->qhull_options);
+  }
+  qh_resetlists(qh, False, qh_RESETvisible /* qh.visible_list newvertex_list qh.newfacet_list */);
+  qh->facet_next= qh->facet_list;
+  qh_furthestnext(qh /* qh.facet_list */);
+  if (qh->PREmerge) {
+    qh->cos_max= qh->premerge_cos;
+    qh->centrum_radius= qh->premerge_centrum; /* overwritten by qh_premerge */
+  }
+  if (qh->ONLYgood) {
+    if (qh->GOODvertex > 0 && qh->MERGING) {
+      qh_fprintf(qh, qh->ferr, 6151, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    if (!(qh->GOODthreshold || qh->GOODpoint
+         || (!qh->MERGEexact && !qh->PREmerge && qh->GOODvertexp))) {
+      qh_fprintf(qh, qh->ferr, 6152, "qhull input error: 'Qg' (ONLYgood) needs a good threshold('Pd0D0'), a good point(QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
+      qh_errexit(qh, qh_ERRinput, NULL, NULL);
+    }
+    if (qh->GOODvertex > 0  && !qh->MERGING  /* matches qh_partitionall */
+    && !qh_isvertex(qh->GOODvertexp, vertices)) {
+      facet= qh_findbestnew(qh, qh->GOODvertexp, qh->facet_list,
+                          &dist, !qh_ALL, &isoutside, &numpart);
+      zadd_(Zdistgood, numpart);
+      if (!isoutside) {
+        qh_fprintf(qh, qh->ferr, 6153, "qhull input error: point for QV%d is inside initial simplex.  It can not be made a vertex.\n",
+               qh_pointid(qh, qh->GOODvertexp));
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }
+      if (!qh_addpoint(qh, qh->GOODvertexp, facet, False)) {
+        qh_settempfree(qh, &vertices);
+        qh_settempfree(qh, &maxpoints);
+        return;
+      }
+    }
+    qh_findgood(qh, qh->facet_list, 0);
+  }
+  qh_settempfree(qh, &vertices);
+  qh_settempfree(qh, &maxpoints);
+  trace1((qh, qh->ferr, 1030, "qh_initbuild: initial hull created and points partitioned\n"));
+} /* initbuild */
+
+/*---------------------------------
+
+  qh_initialhull(qh, vertices )
+    constructs the initial hull as a DIM3 simplex of vertices
+
+  notes:
+    only called by qh_initbuild
+
+  design:
+    creates a simplex (initializes lists)
+    determines orientation of simplex
+    sets hyperplanes for facets
+    doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
+    checks for flipped facets and qh.NARROWhull
+    checks the result
+*/
+void qh_initialhull(qhT *qh, setT *vertices) {
+  facetT *facet, *firstfacet, *neighbor, **neighborp;
+  realT angle, minangle= REALmax, dist;
+
+  qh_createsimplex(qh, vertices /* qh.facet_list */);
+  qh_resetlists(qh, False, qh_RESETvisible);
+  qh->facet_next= qh->facet_list;      /* advance facet when processed */
+  qh->interior_point= qh_getcenter(qh, vertices);
+  if (qh->IStracing) {
+    qh_fprintf(qh, qh->ferr, 8105, "qh_initialhull: ");
+    qh_printpoint(qh, qh->ferr, "qh.interior_point", qh->interior_point);
+  }
+  firstfacet= qh->facet_list;
+  qh_setfacetplane(qh, firstfacet);   /* qh_joggle_restart if flipped */
+  if (firstfacet->flipped) {
+    trace1((qh, qh->ferr, 1065, "qh_initialhull: ignore f%d flipped.  Test qh.interior_point (p-2) for clearly flipped\n", firstfacet->id));
+    firstfacet->flipped= False;
+  }
+  zzinc_(Zdistcheck);
+  qh_distplane(qh, qh->interior_point, firstfacet, &dist);
+  if (dist > qh->DISTround) {  /* clearly flipped */
+    trace1((qh, qh->ferr, 1060, "qh_initialhull: initial orientation incorrect, qh.interior_point is %2.2g from f%d.  Reversing orientation of all facets\n",
+          dist, firstfacet->id));
+    FORALLfacets
+      facet->toporient ^= (unsigned char)True;
+    qh_setfacetplane(qh, firstfacet);
+  }
+  FORALLfacets {
+    if (facet != firstfacet)
+      qh_setfacetplane(qh, facet);    /* qh_joggle_restart if flipped */
+  }
+  FORALLfacets {
+    if (facet->flipped) {
+      trace1((qh, qh->ferr, 1066, "qh_initialhull: ignore f%d flipped.  Test qh.interior_point (p-2) for clearly flipped\n", facet->id));
+      facet->flipped= False;
+    }
+    zzinc_(Zdistcheck);
+    qh_distplane(qh, qh->interior_point, facet, &dist);  /* duplicates qh_setfacetplane */
+    if (dist > qh->DISTround) {  /* clearly flipped, due to axis-parallel facet or coplanar firstfacet */
+      trace1((qh, qh->ferr, 1031, "qh_initialhull: initial orientation incorrect, qh.interior_point is %2.2g from f%d.  Either axis-parallel facet or coplanar firstfacet f%d.  Force outside orientation of all facets\n",
+        dist, facet->id, firstfacet->id));
+      FORALLfacets { /* reuse facet, then 'break' */
+        facet->flipped= False;
+        facet->toporient ^= (unsigned char)True;
+        qh_orientoutside(qh, facet);  /* force outside orientation for f.normal */
+      }
+      break;
+    }
+  }
+  FORALLfacets {
+    if (!qh_checkflipped(qh, facet, NULL, qh_ALL)) {
+      if (qh->DELAUNAY && ! qh->ATinfinity) {
+        qh_joggle_restart(qh, "initial Delaunay cocircular or cospherical");
+        if (qh->UPPERdelaunay)
+          qh_fprintf(qh, qh->ferr, 6240, "Qhull precision error: initial Delaunay input sites are cocircular or cospherical.  Option 'Qs' searches all points.  Use option 'QJ' to joggle the input, otherwise cannot compute the upper Delaunay triangulation or upper Voronoi diagram of cocircular/cospherical points.\n");
+        else
+          qh_fprintf(qh, qh->ferr, 6239, "Qhull precision error: initial Delaunay input sites are cocircular or cospherical.  Use option 'Qz' for the Delaunay triangulation or Voronoi diagram of cocircular/cospherical points; it adds a point \"at infinity\".  Alternatively use option 'QJ' to joggle the input.  Use option 'Qs' to search all points for the initial simplex.\n");
+        qh_printvertexlist(qh, qh->ferr, "\ninput sites with last coordinate projected to a paraboloid\n", qh->facet_list, NULL, qh_ALL);
+        qh_errexit(qh, qh_ERRinput, NULL, NULL);
+      }else {
+        qh_joggle_restart(qh, "initial simplex is flat");
+        qh_fprintf(qh, qh->ferr, 6154, "Qhull precision error: Initial simplex is flat (facet %d is coplanar with the interior point)\n",
+                   facet->id);
+        qh_errexit(qh, qh_ERRsingular, NULL, NULL);  /* calls qh_printhelp_singular */
+      }
+    }
+    FOREACHneighbor_(facet) {
+      angle= qh_getangle(qh, facet->normal, neighbor->normal);
+      minimize_( minangle, angle);
+    }
+  }
+  if (minangle < qh_MAXnarrow && !qh->NOnarrow) {
+    realT diff= 1.0 + minangle;
+
+    qh->NARROWhull= True;
+    qh_option(qh, "_narrow-hull", NULL, &diff);
+    if (minangle < qh_WARNnarrow && !qh->RERUN && qh->PRINTprecision)
+      qh_printhelp_narrowhull(qh, qh->ferr, minangle);
+  }
+  zzval_(Zprocessed)= qh->hull_dim+1;
+  qh_checkpolygon(qh, qh->facet_list);
+  qh_checkconvex(qh, qh->facet_list, qh_DATAfault);
+  if (qh->IStracing >= 1) {
+    qh_fprintf(qh, qh->ferr, 8105, "qh_initialhull: simplex constructed\n");
+  }
+} /* initialhull */
+
+/*---------------------------------
+
+  qh_initialvertices(qh, dim, maxpoints, points, numpoints )
+    determines a non-singular set of initial vertices
+    maxpoints may include duplicate points
+
+  returns:
+    temporary set of dim+1 vertices in descending order by vertex id
+    if qh.RANDOMoutside && !qh.ALLpoints
+      picks random points
+    if dim >= qh_INITIALmax,
+      uses min/max x and max points with non-zero determinants
+
+  notes:
+    unless qh.ALLpoints,
+      uses maxpoints as long as determinate is non-zero
+*/
+setT *qh_initialvertices(qhT *qh, int dim, setT *maxpoints, pointT *points, int numpoints) {
+  pointT *point, **pointp;
+  setT *vertices, *simplex, *tested;
+  realT randr;
+  int idx, point_i, point_n, k;
+  boolT nearzero= False;
+
+  vertices= qh_settemp(qh, dim + 1);
+  simplex= qh_settemp(qh, dim + 1);
+  if (qh->ALLpoints)
+    qh_maxsimplex(qh, dim, NULL, points, numpoints, &simplex);
+  else if (qh->RANDOMoutside) {
+    while (qh_setsize(qh, simplex) != dim+1) {
+      randr= qh_RANDOMint;
+      randr= randr/(qh_RANDOMmax+1);
+      randr= floor(qh->num_points * randr);
+      idx= (int)randr;
+      while (qh_setin(simplex, qh_point(qh, idx))) {
+        idx++; /* in case qh_RANDOMint always returns the same value */
+        idx= idx < qh->num_points ? idx : 0;
+      }
+      qh_setappend(qh, &simplex, qh_point(qh, idx));
+    }
+  }else if (qh->hull_dim >= qh_INITIALmax) {
+    tested= qh_settemp(qh, dim+1);
+    qh_setappend(qh, &simplex, SETfirst_(maxpoints));   /* max and min X coord */
+    qh_setappend(qh, &simplex, SETsecond_(maxpoints));
+    qh_maxsimplex(qh, fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
+    k= qh_setsize(qh, simplex);
+    FOREACHpoint_i_(qh, maxpoints) {
+      if (k >= dim)  /* qh_maxsimplex for last point */
+        break;
+      if (point_i & 0x1) {     /* first try up to dim, max. coord. points */
+        if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+          qh_detsimplex(qh, point, simplex, k, &nearzero);
+          if (nearzero)
+            qh_setappend(qh, &tested, point);
+          else {
+            qh_setappend(qh, &simplex, point);
+            k++;
+          }
+        }
+      }
+    }
+    FOREACHpoint_i_(qh, maxpoints) {
+      if (k >= dim)  /* qh_maxsimplex for last point */
+        break;
+      if ((point_i & 0x1) == 0) {  /* then test min. coord points */
+        if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+          qh_detsimplex(qh, point, simplex, k, &nearzero);
+          if (nearzero)
+            qh_setappend(qh, &tested, point);
+          else {
+            qh_setappend(qh, &simplex, point);
+            k++;
+          }
+        }
+      }
+    }
+    /* remove tested points from maxpoints */
+    FOREACHpoint_i_(qh, maxpoints) {
+      if (qh_setin(simplex, point) || qh_setin(tested, point))
+        SETelem_(maxpoints, point_i)= NULL;
+    }
+    qh_setcompact(qh, maxpoints);
+    idx= 0;
+    while (k < dim && (point= qh_point(qh, idx++))) {
+      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+        qh_detsimplex(qh, point, simplex, k, &nearzero);
+        if (!nearzero){
+          qh_setappend(qh, &simplex, point);
+          k++;
+        }
+      }
+    }
+    qh_settempfree(qh, &tested);
+    qh_maxsimplex(qh, dim, maxpoints, points, numpoints, &simplex);
+  }else /* qh.hull_dim < qh_INITIALmax */
+    qh_maxsimplex(qh, dim, maxpoints, points, numpoints, &simplex);
+  FOREACHpoint_(simplex)
+    qh_setaddnth(qh, &vertices, 0, qh_newvertex(qh, point)); /* descending order */
+  qh_settempfree(qh, &simplex);
+  return vertices;
+} /* initialvertices */
+
+
+/*---------------------------------
+
+  qh_isvertex( point, vertices )
+    returns vertex if point is in vertex set, else returns NULL
+
+  notes:
+    for qh.GOODvertex
+*/
+vertexT *qh_isvertex(pointT *point, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (vertex->point == point)
+      return vertex;
+  }
+  return NULL;
+} /* isvertex */
+
+/*---------------------------------
+
+  qh_makenewfacets(qh, point )
+    make new facets from point and qh.visible_list
+
+  returns:
+    apex (point) of the new facets
+    qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
+    qh.newvertex_list= list of vertices in new facets with ->newfacet set
+
+    if (qh.NEWtentative)
+      newfacets reference horizon facets, but not vice versa
+      ridges reference non-simplicial horizon ridges, but not vice versa
+      does not change existing facets
+    else
+      sets qh.NEWfacets
+      new facets attached to horizon facets and ridges
+      for visible facets,
+        visible->r.replace is corresponding new facet
+
+  see also:
+    qh_makenewplanes() -- make hyperplanes for facets
+    qh_attachnewfacets() -- attachnewfacets if not done here qh->NEWtentative
+    qh_matchnewfacets() -- match up neighbors
+    qh_update_vertexneighbors() -- update vertex neighbors and delvertices
+    qh_deletevisible() -- delete visible facets
+    qh_checkpolygon() --check the result
+    qh_triangulate() -- triangulate a non-simplicial facet
+
+  design:
+    for each visible facet
+      make new facets to its horizon facets
+      update its f.replace
+      clear its neighbor set
+*/
+vertexT *qh_makenewfacets(qhT *qh, pointT *point /* qh.visible_list */) {
+  facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  if (qh->CHECKfrequently) {
+    qh_checkdelridge(qh);
+  }
+  qh->newfacet_list= qh->facet_tail;
+  qh->newvertex_list= qh->vertex_tail;
+  apex= qh_newvertex(qh, point);
+  qh_appendvertex(qh, apex);
+  qh->visit_id++;
+  FORALLvisible_facets {
+    FOREACHneighbor_(visible)
+      neighbor->seen= False;
+    if (visible->ridges) {
+      visible->visitid= qh->visit_id;
+      newfacet2= qh_makenew_nonsimplicial(qh, visible, apex, &numnew);
+    }
+    if (visible->simplicial)
+      newfacet= qh_makenew_simplicial(qh, visible, apex, &numnew);
+    if (!qh->NEWtentative) {
+      if (newfacet2)  /* newfacet is null if all ridges defined */
+        newfacet= newfacet2;
+      if (newfacet)
+        visible->f.replace= newfacet;
+      else
+        zinc_(Zinsidevisible);
+      if (visible->ridges)      /* ridges and neighbors are no longer valid for visible facet */
+        SETfirst_(visible->ridges)= NULL;
+      SETfirst_(visible->neighbors)= NULL;
+    }
+  }
+  if (!qh->NEWtentative)
+    qh->NEWfacets= True;
+  trace1((qh, qh->ferr, 1032, "qh_makenewfacets: created %d new facets f%d..f%d from point p%d to horizon\n",
+    numnew, qh->first_newfacet, qh->facet_id-1, qh_pointid(qh, point)));
+  if (qh->IStracing >= 4)
+    qh_printfacetlist(qh, qh->newfacet_list, NULL, qh_ALL);
+  return apex;
+} /* makenewfacets */
+
+#ifndef qh_NOmerge
+/*---------------------------------
+
+  qh_matchdupridge(qh, atfacet, atskip, hashsize, hashcount )
+    match duplicate ridges in qh.hash_table for atfacet@atskip
+    duplicates marked with ->dupridge and qh_DUPLICATEridge
+
+  returns:
+    vertex-facet distance (>0.0) for qh_MERGEridge ridge
+    updates hashcount
+    set newfacet, facet, matchfacet's hyperplane (removes from mergecycle of coplanarhorizon facets)
+
+  see also:
+    qh_matchneighbor
+
+  notes:
+    only called by qh_matchnewfacets for qh_buildcone and qh_triangulate_facet
+    assumes atfacet is simplicial
+    assumes atfacet->neighbors @ atskip == qh_DUPLICATEridge
+    usually keeps ridge with the widest merge
+    both MRGdupridge and MRGflipped are required merges -- rbox 100 C1,2e-13 D4 t1 | qhull d Qbb
+      can merge flipped f11842 skip 3 into f11862 skip 2 and vice versa (forced by goodmatch/goodmatch2)
+         blocks -- cannot merge f11862 skip 2 and f11863 skip2 (the widest merge)
+         must block -- can merge f11843 skip 3 into f11842 flipped skip 3, but not vice versa
+      can merge f11843 skip 3 into f11863 skip 2, but not vice versa
+    working/unused.h: [jan'19] Dropped qh_matchdupridge_coplanarhorizon, it was the same or slightly worse.  Complex addition, rarely occurs
+
+  design:
+    compute hash value for atfacet and atskip
+    repeat twice -- once to make best matches, once to match the rest
+      for each possible facet in qh.hash_table
+        if it is a matching facet with the same orientation and pass 2
+          make match
+          unless tricoplanar, mark match for merging (qh_MERGEridge)
+          [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
+        if it is a matching facet with the same orientation and pass 1
+          test if this is a better match
+      if pass 1,
+        make best match (it will not be merged)
+        set newfacet, facet, matchfacet's hyperplane (removes from mergecycle of coplanarhorizon facets)
+
+*/
+coordT qh_matchdupridge(qhT *qh, facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+  boolT same, ismatch, isduplicate= False;
+  int hash, scan;
+  facetT *facet, *newfacet, *nextfacet;
+  facetT *maxmatch= NULL, *maxmatch2= NULL, *goodmatch= NULL, *goodmatch2= NULL;
+  int skip, newskip, nextskip= 0, makematch;
+  int maxskip= 0, maxskip2= 0, goodskip= 0, goodskip2= 0;
+  coordT maxdist= -REALmax, maxdist2= 0.0, dupdist, dupdist2, low, high, maxgood, gooddist= 0.0;
+
+  maxgood= qh_WIDEdupridge * (qh->ONEmerge + qh->DISTround);
+  hash= qh_gethash(qh, hashsize, atfacet->vertices, qh->hull_dim, 1,
+                     SETelem_(atfacet->vertices, atskip));
+  trace2((qh, qh->ferr, 2046, "qh_matchdupridge: find dupridge matches for f%d skip %d hash %d hashcount %d\n",
+          atfacet->id, atskip, hash, *hashcount));
+  for (makematch=0; makematch < 2; makematch++) { /* makematch is false on the first pass and 1 on the second */
+    qh->visit_id++;
+    for (newfacet=atfacet, newskip=atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
+      zinc_(Zhashlookup);
+      nextfacet= NULL; /* exit when ismatch found */
+      newfacet->visitid= qh->visit_id;
+      for (scan=hash; (facet= SETelemt_(qh->hash_table, scan, facetT));
+           scan= (++scan >= hashsize ? 0 : scan)) {
+        if (!facet->dupridge || facet->visitid == qh->visit_id)
+          continue;
+        zinc_(Zhashtests);
+        if (qh_matchvertices(qh, 1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+          if (SETelem_(newfacet->vertices, newskip) == SETelem_(facet->vertices, skip)) {
+            trace3((qh, qh->ferr, 3053, "qh_matchdupridge: duplicate ridge due to duplicate facets (f%d skip %d and f%d skip %d) previously reported as QH7084.  Maximize dupdist to force vertex merge\n",
+              newfacet->id, newskip, facet->id, skip));
+            isduplicate= True;
+          }
+          ismatch= (same == (boolT)(newfacet->toporient ^ facet->toporient));
+          if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
+            if (!makematch) {  /* occurs if many merges, e.g., rbox 100 W0 C2,1e-13 D6 t1546872462 | qhull C0 Qt Tcv */
+              qh_fprintf(qh, qh->ferr, 6155, "qhull topology error (qh_matchdupridge): missing qh_DUPLICATEridge at f%d skip %d for new f%d skip %d hash %d ismatch %d.  Set by qh_matchneighbor\n",
+                facet->id, skip, newfacet->id, newskip, hash, ismatch);
+              qh_errexit2(qh, qh_ERRtopology, facet, newfacet);
+            }
+          }else if (!ismatch) {
+            nextfacet= facet;
+            nextskip= skip;
+          }else if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
+            if (makematch) {
+              if (newfacet->tricoplanar) {
+                SETelem_(facet->neighbors, skip)= newfacet;
+                SETelem_(newfacet->neighbors, newskip)= facet;
+                *hashcount -= 2; /* removed two unmatched facets */
+                trace2((qh, qh->ferr, 2075, "qh_matchdupridge: allow tricoplanar dupridge for new f%d skip %d and f%d skip %d\n",
+                    newfacet->id, newskip, facet->id, skip));
+              }else if (goodmatch && goodmatch2) {
+                SETelem_(goodmatch2->neighbors, goodskip2)= qh_MERGEridge;  /* undo selection of goodmatch */
+                SETelem_(facet->neighbors, skip)= newfacet;
+                SETelem_(newfacet->neighbors, newskip)= facet;
+                *hashcount -= 2; /* removed two unmatched facets */
+                trace2((qh, qh->ferr, 2105, "qh_matchdupridge: make good forced merge of dupridge f%d skip %d into f%d skip %d, keep new f%d skip %d and f%d skip %d, dist %4.4g\n",
+                  goodmatch->id, goodskip, goodmatch2->id, goodskip2, newfacet->id, newskip, facet->id, skip, gooddist));
+                goodmatch2= NULL;
+              }else {
+                SETelem_(facet->neighbors, skip)= newfacet;
+                SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;  /* resolved by qh_mark_dupridges */
+                *hashcount -= 2; /* removed two unmatched facets */
+                trace3((qh, qh->ferr, 3073, "qh_matchdupridge: make forced merge of dupridge for new f%d skip %d and f%d skip %d, maxdist %4.4g in qh_forcedmerges\n",
+                  newfacet->id, newskip, facet->id, skip, maxdist2));
+              }
+            }else { /* !makematch */
+              if (!facet->normal)
+                qh_setfacetplane(qh, facet); /* qh_mergecycle will ignore 'mergehorizon' facets with normals, too many cases otherwise */
+              if (!newfacet->normal)
+                qh_setfacetplane(qh, newfacet);
+              dupdist= qh_getdistance(qh, facet, newfacet, &low, &high); /* ignore low/high */
+              dupdist2= qh_getdistance(qh, newfacet, facet, &low, &high);
+              if (isduplicate) {
+                goodmatch= NULL;
+                minimize_(dupdist, dupdist2);
+                maxdist= dupdist;
+                maxdist2= REALmax/2;
+                maxmatch= facet;
+                maxskip= skip;
+                maxmatch2= newfacet;
+                maxskip2= newskip;
+                break; /* force maxmatch */
+              }else if (facet->flipped && !newfacet->flipped && dupdist < maxgood) {
+                if (!goodmatch || !goodmatch->flipped || dupdist < gooddist) {
+                  goodmatch= facet;
+                  goodskip= skip;
+                  goodmatch2= newfacet;
+                  goodskip2= newskip;
+                  gooddist= dupdist;
+                  trace3((qh, qh->ferr, 3070, "qh_matchdupridge: try good dupridge flipped f%d skip %d into new f%d skip %d at dist %2.2g otherdist %2.2g\n",
+                    goodmatch->id, goodskip, goodmatch2->id, goodskip2, gooddist, dupdist2));
+                }
+              }else if (newfacet->flipped && !facet->flipped && dupdist2 < maxgood) {
+                if (!goodmatch || !goodmatch->flipped || dupdist2 < gooddist) {
+                  goodmatch= newfacet;
+                  goodskip= newskip;
+                  goodmatch2= facet;
+                  goodskip2= skip;
+                  gooddist= dupdist2;
+                  trace3((qh, qh->ferr, 3071, "qh_matchdupridge: try good dupridge flipped new f%d skip %d into f%d skip %d at dist %2.2g otherdist %2.2g\n",
+                    goodmatch->id, goodskip, goodmatch2->id, goodskip2, gooddist, dupdist));
+                }
+              }else if (dupdist < maxgood && (!newfacet->flipped || facet->flipped)) { /* disallow not-flipped->flipped */
+                if (!goodmatch || (!goodmatch->flipped && dupdist < gooddist)) {
+                  goodmatch= facet;
+                  goodskip= skip;
+                  goodmatch2= newfacet;
+                  goodskip2= newskip;
+                  gooddist= dupdist;
+                  trace3((qh, qh->ferr, 3072, "qh_matchdupridge: try good dupridge f%d skip %d into new f%d skip %d at dist %2.2g otherdist %2.2g\n",
+                    goodmatch->id, goodskip, goodmatch2->id, goodskip2, gooddist, dupdist2));
+                }
+              }else if (dupdist2 < maxgood && (!facet->flipped || newfacet->flipped)) { /* disallow not-flipped->flipped */
+                if (!goodmatch || (!goodmatch->flipped && dupdist2 < gooddist)) {
+                  goodmatch= newfacet;
+                  goodskip= newskip;
+                  goodmatch2= facet;
+                  goodskip2= skip;
+                  gooddist= dupdist2;
+                  trace3((qh, qh->ferr, 3018, "qh_matchdupridge: try good dupridge new f%d skip %d into f%d skip %d at dist %2.2g otherdist %2.2g\n",
+                    goodmatch->id, goodskip, goodmatch2->id, goodskip2, gooddist, dupdist));
+                }
+              }else if (!goodmatch) { /* otherwise match the furthest apart facets */
+                if (!newfacet->flipped || facet->flipped) {
+                  minimize_(dupdist, dupdist2);
+                }
+                if (dupdist > maxdist) { /* could keep !flipped->flipped, but probably lost anyway */
+                  maxdist2= maxdist;
+                  maxdist= dupdist;
+                  maxmatch= facet;
+                  maxskip= skip;
+                  maxmatch2= newfacet;
+                  maxskip2= newskip;
+                  trace3((qh, qh->ferr, 3055, "qh_matchdupridge: try furthest dupridge f%d skip %d new f%d skip %d at dist %2.2g\n",
+                    maxmatch->id, maxskip, maxmatch2->id, maxskip2, maxdist));
+                }else if (dupdist > maxdist2)
+                  maxdist2= dupdist;
+              }
+            }
+          }
+        }
+      } /* end of foreach entry in qh.hash_table starting at 'hash' */
+      if (makematch && SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
+        qh_fprintf(qh, qh->ferr, 6156, "qhull internal error (qh_matchdupridge): no MERGEridge match for dupridge new f%d skip %d at hash %d..%d\n",
+                    newfacet->id, newskip, hash, scan);
+        qh_errexit(qh, qh_ERRqhull, newfacet, NULL);
+      }
+    } /* end of foreach newfacet at 'hash' */
+    if (!makematch) {
+      if (!maxmatch && !goodmatch) {
+        qh_fprintf(qh, qh->ferr, 6157, "qhull internal error (qh_matchdupridge): no maximum or good match for dupridge new f%d skip %d at hash %d..%d\n",
+          atfacet->id, atskip, hash, scan);
+        qh_errexit(qh, qh_ERRqhull, atfacet, NULL);
+      }
+      if (goodmatch) {
+        SETelem_(goodmatch->neighbors, goodskip)= goodmatch2;
+        SETelem_(goodmatch2->neighbors, goodskip2)= goodmatch;
+        *hashcount -= 2; /* removed two unmatched facets */
+        if (goodmatch->flipped) {
+          if (!goodmatch2->flipped) {
+            zzinc_(Zflipridge);
+          }else {
+            zzinc_(Zflipridge2);
+            /* qh_joggle_restart called by qh_matchneighbor if qh_DUPLICATEridge */
+          }
+        }
+        /* previously traced */
+      }else {
+        SETelem_(maxmatch->neighbors, maxskip)= maxmatch2; /* maxmatch!=NULL by QH6157 */
+        SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
+        *hashcount -= 2; /* removed two unmatched facets */
+        zzinc_(Zmultiridge);
+        /* qh_joggle_restart called by qh_matchneighbor if qh_DUPLICATEridge */
+        trace0((qh, qh->ferr, 25, "qh_matchdupridge: keep dupridge f%d skip %d and f%d skip %d, dist %4.4g\n",
+          maxmatch2->id, maxskip2, maxmatch->id, maxskip, maxdist));
+      }
+    }
+  }
+  if (goodmatch)
+    return gooddist;
+  return maxdist2;
+} /* matchdupridge */
+
+#else /* qh_NOmerge */
+coordT qh_matchdupridge(qhT *qh, facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(atfacet)
+  QHULL_UNUSED(atskip)
+  QHULL_UNUSED(hashsize)
+  QHULL_UNUSED(hashcount)
+
+  return 0.0;
+}
+#endif /* qh_NOmerge */
+
+/*---------------------------------
+
+  qh_nearcoplanar()
+    for all facets, remove near-inside points from facet->coplanarset
+    coplanar points defined by innerplane from qh_outerinner()
+
+  returns:
+    if qh->KEEPcoplanar && !qh->KEEPinside
+      facet->coplanarset only contains coplanar points
+    if qh.JOGGLEmax
+      drops inner plane by another qh.JOGGLEmax diagonal since a
+        vertex could shift out while a coplanar point shifts in
+
+  notes:
+    used for qh.PREmerge and qh.JOGGLEmax
+    must agree with computation of qh.NEARcoplanar in qh_detroundoff
+
+  design:
+    if not keeping coplanar or inside points
+      free all coplanar sets
+    else if not keeping both coplanar and inside points
+      remove !coplanar or !inside points from coplanar sets
+*/
+void qh_nearcoplanar(qhT *qh /* qh.facet_list */) {
+  facetT *facet;
+  pointT *point, **pointp;
+  int numpart;
+  realT dist, innerplane;
+
+  if (!qh->KEEPcoplanar && !qh->KEEPinside) {
+    FORALLfacets {
+      if (facet->coplanarset)
+        qh_setfree(qh, &facet->coplanarset);
+    }
+  }else if (!qh->KEEPcoplanar || !qh->KEEPinside) {
+    qh_outerinner(qh, NULL, NULL, &innerplane);
+    if (qh->JOGGLEmax < REALmax/2)
+      innerplane -= qh->JOGGLEmax * sqrt((realT)qh->hull_dim);
+    numpart= 0;
+    FORALLfacets {
+      if (facet->coplanarset) {
+        FOREACHpoint_(facet->coplanarset) {
+          numpart++;
+          qh_distplane(qh, point, facet, &dist);
+          if (dist < innerplane) {
+            if (!qh->KEEPinside)
+              SETref_(point)= NULL;
+          }else if (!qh->KEEPcoplanar)
+            SETref_(point)= NULL;
+        }
+        qh_setcompact(qh, facet->coplanarset);
+      }
+    }
+    zzadd_(Zcheckpart, numpart);
+  }
+} /* nearcoplanar */
+
+/*---------------------------------
+
+  qh_nearvertex(qh, facet, point, bestdist )
+    return nearest vertex in facet to point
+
+  returns:
+    vertex and its distance
+
+  notes:
+    if qh.DELAUNAY
+      distance is measured in the input set
+    searches neighboring tricoplanar facets (requires vertexneighbors)
+      Slow implementation.  Recomputes vertex set for each point.
+    The vertex set could be stored in the qh.keepcentrum facet.
+*/
+vertexT *qh_nearvertex(qhT *qh, facetT *facet, pointT *point, realT *bestdistp) {
+  realT bestdist= REALmax, dist;
+  vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
+  coordT *center;
+  facetT *neighbor, **neighborp;
+  setT *vertices;
+  int dim= qh->hull_dim;
+
+  if (qh->DELAUNAY)
+    dim--;
+  if (facet->tricoplanar) {
+    if (!qh->VERTEXneighbors || !facet->center) {
+      qh_fprintf(qh, qh->ferr, 6158, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    vertices= qh_settemp(qh, qh->TEMPsize);
+    apex= SETfirstt_(facet->vertices, vertexT);
+    center= facet->center;
+    FOREACHneighbor_(apex) {
+      if (neighbor->center == center) {
+        FOREACHvertex_(neighbor->vertices)
+          qh_setappend(qh, &vertices, vertex);
+      }
+    }
+  }else
+    vertices= facet->vertices;
+  FOREACHvertex_(vertices) {
+    dist= qh_pointdist(vertex->point, point, -dim);
+    if (dist < bestdist) {
+      bestdist= dist;
+      bestvertex= vertex;
+    }
+  }
+  if (facet->tricoplanar)
+    qh_settempfree(qh, &vertices);
+  *bestdistp= sqrt(bestdist);
+  if (!bestvertex) {
+      qh_fprintf(qh, qh->ferr, 6261, "qhull internal error (qh_nearvertex): did not find bestvertex for f%d p%d\n", facet->id, qh_pointid(qh, point));
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+  }
+  trace3((qh, qh->ferr, 3019, "qh_nearvertex: v%d dist %2.2g for f%d p%d\n",
+        bestvertex->id, *bestdistp, facet->id, qh_pointid(qh, point))); /* bestvertex!=0 by QH2161 */
+  return bestvertex;
+} /* nearvertex */
+
+/*---------------------------------
+
+  qh_newhashtable(qh, newsize )
+    returns size of qh.hash_table of at least newsize slots
+
+  notes:
+    assumes qh.hash_table is NULL
+    qh_HASHfactor determines the number of extra slots
+    size is not divisible by 2, 3, or 5
+*/
+int qh_newhashtable(qhT *qh, int newsize) {
+  int size;
+
+  size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
+  while (True) {
+    if (newsize<0 || size<0) {
+        qh_fprintf(qh, qh->qhmem.ferr, 6236, "qhull error (qh_newhashtable): negative request (%d) or size (%d).  Did int overflow due to high-D?\n", newsize, size); /* WARN64 */
+        qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
+    }
+    if ((size%3) && (size%5))
+      break;
+    size += 2;
+    /* loop terminates because there is an infinite number of primes */
+  }
+  qh->hash_table= qh_setnew(qh, size);
+  qh_setzero(qh, qh->hash_table, 0, size);
+  return size;
+} /* newhashtable */
+
+/*---------------------------------
+
+  qh_newvertex(qh, point )
+    returns a new vertex for point
+*/
+vertexT *qh_newvertex(qhT *qh, pointT *point) {
+  vertexT *vertex;
+
+  zinc_(Ztotvertices);
+  vertex= (vertexT *)qh_memalloc(qh, (int)sizeof(vertexT));
+  memset((char *) vertex, (size_t)0, sizeof(vertexT));
+  if (qh->vertex_id == UINT_MAX) {
+    qh_memfree(qh, vertex, (int)sizeof(vertexT));
+    qh_fprintf(qh, qh->ferr, 6159, "qhull error: 2^32 or more vertices.  vertexT.id field overflows.  Vertices would not be sorted correctly.\n");
+    qh_errexit(qh, qh_ERRother, NULL, NULL);
+  }
+  if (qh->vertex_id == qh->tracevertex_id)
+    qh->tracevertex= vertex;
+  vertex->id= qh->vertex_id++;
+  vertex->point= point;
+  trace4((qh, qh->ferr, 4060, "qh_newvertex: vertex p%d(v%d) created\n", qh_pointid(qh, vertex->point),
+          vertex->id));
+  return(vertex);
+} /* newvertex */
+
+/*---------------------------------
+
+  qh_nextfacet2d( facet, &nextvertex )
+    return next facet and vertex for a 2d facet in qh_ORIENTclock order
+    returns NULL on error
+
+  notes:
+    in qh_ORIENTclock order (default counter-clockwise)
+    nextvertex is in between the two facets
+    does not use qhT or qh_errexit [QhullFacet.cpp]
+
+  design:
+    see io_r.c/qh_printextremes_2d
+*/
+facetT *qh_nextfacet2d(facetT *facet, vertexT **nextvertexp) {
+  facetT *nextfacet;
+
+  if (facet->toporient ^ qh_ORIENTclock) {
+    *nextvertexp= SETfirstt_(facet->vertices, vertexT);
+    nextfacet= SETfirstt_(facet->neighbors, facetT);
+  }else {
+    *nextvertexp= SETsecondt_(facet->vertices, vertexT);
+    nextfacet= SETsecondt_(facet->neighbors, facetT);
+  }
+  return nextfacet;
+} /* nextfacet2d */
+
+/*---------------------------------
+
+  qh_nextridge3d( atridge, facet, &vertex )
+    return next ridge and vertex for a 3d facet
+    returns NULL on error
+    [for QhullFacet::nextRidge3d] Does not call qh_errexit nor access qhT.
+
+  notes:
+    in qh_ORIENTclock order
+    this is a O(n^2) implementation to trace all ridges
+    be sure to stop on any 2nd visit
+    same as QhullRidge::nextRidge3d
+    does not use qhT or qh_errexit [QhullFacet.cpp]
+
+  design:
+    for each ridge
+      exit if it is the ridge after atridge
+*/
+ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+  vertexT *atvertex, *vertex, *othervertex;
+  ridgeT *ridge, **ridgep;
+
+  if ((atridge->top == facet) ^ qh_ORIENTclock)
+    atvertex= SETsecondt_(atridge->vertices, vertexT);
+  else
+    atvertex= SETfirstt_(atridge->vertices, vertexT);
+  FOREACHridge_(facet->ridges) {
+    if (ridge == atridge)
+      continue;
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      othervertex= SETsecondt_(ridge->vertices, vertexT);
+      vertex= SETfirstt_(ridge->vertices, vertexT);
+    }else {
+      vertex= SETsecondt_(ridge->vertices, vertexT);
+      othervertex= SETfirstt_(ridge->vertices, vertexT);
+    }
+    if (vertex == atvertex) {
+      if (vertexp)
+        *vertexp= othervertex;
+      return ridge;
+    }
+  }
+  return NULL;
+} /* nextridge3d */
+
+/*---------------------------------
+
+  qh_opposite_vertex(qh, facetA, neighbor )
+    return the opposite vertex in facetA to neighbor
+
+*/
+vertexT *qh_opposite_vertex(qhT *qh, facetT *facetA,  facetT *neighbor) {
+    vertexT *opposite= NULL;
+    facetT *facet;
+    int facet_i, facet_n;
+
+    if (facetA->simplicial) {
+      FOREACHfacet_i_(qh, facetA->neighbors) {
+        if (facet == neighbor) {
+          opposite= SETelemt_(facetA->vertices, facet_i, vertexT);
+          break;
+        }
+      }
+    }
+    if (!opposite) {
+      qh_fprintf(qh, qh->ferr, 6396, "qhull internal error (qh_opposite_vertex): opposite vertex in facet f%d to neighbor f%d is not defined.  Either is facet is not simplicial or neighbor not found\n",
+        facetA->id, neighbor->id);
+      qh_errexit2(qh, qh_ERRqhull, facetA, neighbor);
+    }
+    return opposite;
+} /* opposite_vertex */
+
+/*---------------------------------
+
+  qh_outcoplanar()
+    move points from all facets' outsidesets to their coplanarsets
+
+  notes:
+    for post-processing under qh.NARROWhull
+
+  design:
+    for each facet
+      for each outside point for facet
+        partition point into coplanar set
+*/
+void qh_outcoplanar(qhT *qh /* facet_list */) {
+  pointT *point, **pointp;
+  facetT *facet;
+  realT dist;
+
+  trace1((qh, qh->ferr, 1033, "qh_outcoplanar: move outsideset to coplanarset for qh->NARROWhull\n"));
+  FORALLfacets {
+    FOREACHpoint_(facet->outsideset) {
+      qh->num_outside--;
+      if (qh->KEEPcoplanar || qh->KEEPnearinside) {
+        qh_distplane(qh, point, facet, &dist);
+        zinc_(Zpartition);
+        qh_partitioncoplanar(qh, point, facet, &dist, qh->findbestnew);
+      }
+    }
+    qh_setfree(qh, &facet->outsideset);
+  }
+} /* outcoplanar */
+
+/*---------------------------------
+
+  qh_point(qh, id )
+    return point for a point id, or NULL if unknown
+
+  alternative code:
+    return((pointT *)((unsigned long)qh.first_point
+           + (unsigned long)((id)*qh.normal_size)));
+*/
+pointT *qh_point(qhT *qh, int id) {
+
+  if (id < 0)
+    return NULL;
+  if (id < qh->num_points)
+    return qh->first_point + id * qh->hull_dim;
+  id -= qh->num_points;
+  if (id < qh_setsize(qh, qh->other_points))
+    return SETelemt_(qh->other_points, id, pointT);
+  return NULL;
+} /* point */
+
+/*---------------------------------
+
+  qh_point_add(qh, set, point, elem )
+    stores elem at set[point.id]
+
+  returns:
+    access function for qh_pointfacet and qh_pointvertex
+
+  notes:
+    checks point.id
+*/
+void qh_point_add(qhT *qh, setT *set, pointT *point, void *elem) {
+  int id, size;
+
+  SETreturnsize_(set, size);
+  if ((id= qh_pointid(qh, point)) < 0)
+    qh_fprintf(qh, qh->ferr, 7067, "qhull internal warning (point_add): unknown point %p id %d\n",
+      (void *) point, id);
+  else if (id >= size) {
+    qh_fprintf(qh, qh->ferr, 6160, "qhull internal error (point_add): point p%d is out of bounds(%d)\n",
+             id, size);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }else
+    SETelem_(set, id)= elem;
+} /* point_add */
+
+
+/*---------------------------------
+
+  qh_pointfacet()
+    return temporary set of facet for each point
+    the set is indexed by point id
+    at most one facet per point, arbitrary selection
+
+  notes:
+    each point is assigned to at most one of vertices, coplanarset, or outsideset
+    unassigned points are interior points or
+    vertices assigned to one of its facets
+    coplanarset assigned to the facet
+    outside set assigned to the facet
+    NULL if no facet for point (inside)
+      includes qh.GOODpointp
+
+  access:
+    FOREACHfacet_i_(qh, facets) { ... }
+    SETelem_(facets, i)
+
+  design:
+    for each facet
+      add each vertex
+      add each coplanar point
+      add each outside point
+*/
+setT *qh_pointfacet(qhT *qh /* qh.facet_list */) {
+  int numpoints= qh->num_points + qh_setsize(qh, qh->other_points);
+  setT *facets;
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+  pointT *point, **pointp;
+
+  facets= qh_settemp(qh, numpoints);
+  qh_setzero(qh, facets, 0, numpoints);
+  qh->vertex_visit++;
+  FORALLfacets {
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh->vertex_visit) {
+        vertex->visitid= qh->vertex_visit;
+        qh_point_add(qh, facets, vertex->point, facet);
+      }
+    }
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(qh, facets, point, facet);
+    FOREACHpoint_(facet->outsideset)
+      qh_point_add(qh, facets, point, facet);
+  }
+  return facets;
+} /* pointfacet */
+
+/*---------------------------------
+
+  qh_pointvertex(qh )
+    return temporary set of vertices indexed by point id
+    entry is NULL if no vertex for a point
+      this will include qh.GOODpointp
+
+  access:
+    FOREACHvertex_i_(qh, vertices) { ... }
+    SETelem_(vertices, i)
+*/
+setT *qh_pointvertex(qhT *qh /* qh.facet_list */) {
+  int numpoints= qh->num_points + qh_setsize(qh, qh->other_points);
+  setT *vertices;
+  vertexT *vertex;
+
+  vertices= qh_settemp(qh, numpoints);
+  qh_setzero(qh, vertices, 0, numpoints);
+  FORALLvertices
+    qh_point_add(qh, vertices, vertex->point, vertex);
+  return vertices;
+} /* pointvertex */
+
+
+/*---------------------------------
+
+  qh_prependfacet(qh, facet, facetlist )
+    prepend facet to the start of a facetlist
+
+  returns:
+    increments qh.numfacets
+    updates facetlist, qh.facet_list, facet_next
+
+  notes:
+    be careful of prepending since it can lose a pointer.
+      e.g., can lose _next by deleting and then prepending before _next
+*/
+void qh_prependfacet(qhT *qh, facetT *facet, facetT **facetlist) {
+  facetT *prevfacet, *list;
+
+  trace4((qh, qh->ferr, 4061, "qh_prependfacet: prepend f%d before f%d\n",
+          facet->id, getid_(*facetlist)));
+  if (!*facetlist)
+    (*facetlist)= qh->facet_tail;
+  list= *facetlist;
+  prevfacet= list->previous;
+  facet->previous= prevfacet;
+  if (prevfacet)
+    prevfacet->next= facet;
+  list->previous= facet;
+  facet->next= *facetlist;
+  if (qh->facet_list == list)  /* this may change *facetlist */
+    qh->facet_list= facet;
+  if (qh->facet_next == list)
+    qh->facet_next= facet;
+  *facetlist= facet;
+  qh->num_facets++;
+} /* prependfacet */
+
+
+/*---------------------------------
+
+  qh_printhashtable(qh, fp )
+    print hash table to fp
+
+  notes:
+    not in I/O to avoid bringing io_r.c in
+
+  design:
+    for each hash entry
+      if defined
+        if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
+          print entry and neighbors
+*/
+void qh_printhashtable(qhT *qh, FILE *fp) {
+  facetT *facet, *neighbor;
+  int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
+  vertexT *vertex, **vertexp;
+
+  FOREACHfacet_i_(qh, qh->hash_table) {
+    if (facet) {
+      FOREACHneighbor_i_(qh, facet) {
+        if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
+          break;
+      }
+      if (neighbor_i == neighbor_n)
+        continue;
+      qh_fprintf(qh, fp, 9283, "hash %d f%d ", facet_i, facet->id);
+      FOREACHvertex_(facet->vertices)
+        qh_fprintf(qh, fp, 9284, "v%d ", vertex->id);
+      qh_fprintf(qh, fp, 9285, "\n neighbors:");
+      FOREACHneighbor_i_(qh, facet) {
+        if (neighbor == qh_MERGEridge)
+          id= -3;
+        else if (neighbor == qh_DUPLICATEridge)
+          id= -2;
+        else
+          id= getid_(neighbor);
+        qh_fprintf(qh, fp, 9286, " %d", id);
+      }
+      qh_fprintf(qh, fp, 9287, "\n");
+    }
+  }
+} /* printhashtable */
+
+/*---------------------------------
+
+  qh_printlists(qh)
+    print out facet and vertex lists for debugging (without 'f/v' tags)
+
+  notes:
+    not in I/O to avoid bringing io_r.c in
+*/
+void qh_printlists(qhT *qh) {
+  facetT *facet;
+  vertexT *vertex;
+  int count= 0;
+
+  qh_fprintf(qh, qh->ferr, 3062, "qh_printlists: max_outside %2.2g all facets:", qh->max_outside);
+  FORALLfacets{
+    if (++count % 100 == 0)
+      qh_fprintf(qh, qh->ferr, 8109, "\n     ");
+    qh_fprintf(qh, qh->ferr, 8110, " %d", facet->id);
+  }
+    qh_fprintf(qh, qh->ferr, 8111, "\n  qh.visible_list f%d, newfacet_list f%d, facet_next f%d for qh_addpoint\n  qh.newvertex_list v%d all vertices:",
+      getid_(qh->visible_list), getid_(qh->newfacet_list), getid_(qh->facet_next), getid_(qh->newvertex_list));
+  count= 0;
+  FORALLvertices{
+    if (++count % 100 == 0)
+      qh_fprintf(qh, qh->ferr, 8112, "\n     ");
+    qh_fprintf(qh, qh->ferr, 8113, " %d", vertex->id);
+  }
+  qh_fprintf(qh, qh->ferr, 8114, "\n");
+} /* printlists */
+
+/*---------------------------------
+
+  qh_replacefacetvertex(qh, facet, oldvertex, newvertex )
+    replace oldvertex with newvertex in f.vertices
+    vertices are inverse sorted by vertex->id
+
+  returns:
+    toporient is flipped if an odd parity, position change
+
+  notes:
+    for simplicial facets in qh_rename_adjacentvertex
+    see qh_addfacetvertex
+*/
+void qh_replacefacetvertex(qhT *qh, facetT *facet, vertexT *oldvertex, vertexT *newvertex) {
+  vertexT *vertex;
+  facetT *neighbor;
+  int vertex_i, vertex_n= 0;
+  int old_i= -1, new_i= -1;
+
+  trace3((qh, qh->ferr, 3038, "qh_replacefacetvertex: replace v%d with v%d in f%d\n", oldvertex->id, newvertex->id, facet->id));
+  if (!facet->simplicial) {
+    qh_fprintf(qh, qh->ferr, 6283, "qhull internal error (qh_replacefacetvertex): f%d is not simplicial\n", facet->id);
+    qh_errexit(qh, qh_ERRqhull, facet, NULL);
+  }
+  FOREACHvertex_i_(qh, facet->vertices) {
+    if (new_i == -1 && vertex->id < newvertex->id) {
+      new_i= vertex_i;
+    }else if (vertex->id == newvertex->id) {
+      qh_fprintf(qh, qh->ferr, 6281, "qhull internal error (qh_replacefacetvertex): f%d already contains new v%d\n", facet->id, newvertex->id);
+      qh_errexit(qh, qh_ERRqhull, facet, NULL);
+    }
+    if (vertex->id == oldvertex->id) {
+      old_i= vertex_i;
+    }
+  }
+  if (old_i == -1) {
+    qh_fprintf(qh, qh->ferr, 6282, "qhull internal error (qh_replacefacetvertex): f%d does not contain old v%d\n", facet->id, oldvertex->id);
+    qh_errexit(qh, qh_ERRqhull, facet, NULL);
+  }
+  if (new_i == -1) {
+    new_i= vertex_n;
+  }
+  if (old_i < new_i)
+    new_i--;
+  if ((old_i & 0x1) != (new_i & 0x1))
+    facet->toporient ^= 1;
+  qh_setdelnthsorted(qh, facet->vertices, old_i);
+  qh_setaddnth(qh, &facet->vertices, new_i, newvertex);
+  neighbor= SETelemt_(facet->neighbors, old_i, facetT);
+  qh_setdelnthsorted(qh, facet->neighbors, old_i);
+  qh_setaddnth(qh, &facet->neighbors, new_i, neighbor);
+} /* replacefacetvertex */
+
+/*---------------------------------
+
+  qh_resetlists(qh, stats, qh_RESETvisible )
+    reset newvertex_list, newfacet_list, visible_list, NEWfacets, NEWtentative
+    if stats,
+      maintains statistics
+    if resetVisible,
+      visible_list is restored to facet_list
+      otherwise, f.visible/f.replace is retained
+
+  returns:
+    newvertex_list, newfacet_list, visible_list are NULL
+
+  notes:
+    To delete visible facets, call qh_deletevisible before qh_resetlists
+*/
+void qh_resetlists(qhT *qh, boolT stats, boolT resetVisible /* qh.newvertex_list newfacet_list visible_list */) {
+  vertexT *vertex;
+  facetT *newfacet, *visible;
+  int totnew=0, totver=0;
+
+  trace2((qh, qh->ferr, 2066, "qh_resetlists: reset newvertex_list v%d, newfacet_list f%d, visible_list f%d, facet_list f%d next f%d vertex_list v%d -- NEWfacets? %d, NEWtentative? %d, stats? %d\n",
+    getid_(qh->newvertex_list), getid_(qh->newfacet_list), getid_(qh->visible_list), getid_(qh->facet_list), getid_(qh->facet_next), getid_(qh->vertex_list), qh->NEWfacets, qh->NEWtentative, stats));
+  if (stats) {
+    FORALLvertex_(qh->newvertex_list)
+      totver++;
+    FORALLnew_facets
+      totnew++;
+    zadd_(Zvisvertextot, totver);
+    zmax_(Zvisvertexmax, totver);
+    zadd_(Znewfacettot, totnew);
+    zmax_(Znewfacetmax, totnew);
+  }
+  FORALLvertex_(qh->newvertex_list)
+    vertex->newfacet= False;
+  qh->newvertex_list= NULL;
+  qh->first_newfacet= 0;
+  FORALLnew_facets {
+    newfacet->newfacet= False;
+    newfacet->dupridge= False;
+  }
+  qh->newfacet_list= NULL;
+  if (resetVisible) {
+    FORALLvisible_facets {
+      visible->f.replace= NULL;
+      visible->visible= False;
+    }
+    qh->num_visible= 0;
+  }
+  qh->visible_list= NULL;
+  qh->NEWfacets= False;
+  qh->NEWtentative= False;
+} /* resetlists */
+
+/*---------------------------------
+
+  qh_setvoronoi_all(qh)
+    compute Voronoi centers for all facets
+    includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
+
+  returns:
+    facet->center is the Voronoi center
+
+  notes:
+    unused/untested code: please email bradb@shore.net if this works ok for you
+
+  use:
+    FORALLvertices {...} to locate the vertex for a point.
+    FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
+*/
+void qh_setvoronoi_all(qhT *qh) {
+  facetT *facet;
+
+  qh_clearcenters(qh, qh_ASvoronoi);
+  qh_vertexneighbors(qh);
+
+  FORALLfacets {
+    if (!facet->normal || !facet->upperdelaunay || qh->UPPERdelaunay) {
+      if (!facet->center)
+        facet->center= qh_facetcenter(qh, facet->vertices);
+    }
+  }
+} /* setvoronoi_all */
+
+#ifndef qh_NOmerge
+/*---------------------------------
+
+  qh_triangulate()
+    triangulate non-simplicial facets on qh.facet_list,
+    if qh->VORONOI, sets Voronoi centers of non-simplicial facets
+    nop if hasTriangulation
+
+  returns:
+    all facets simplicial
+    each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
+    resets qh.newfacet_list and visible_list
+
+  notes:
+    called by qh_prepare_output and user_eg2_r.c
+    call after qh_check_output since may switch to Voronoi centers, and qh_checkconvex skips f.tricoplanar facets
+    Output may overwrite ->f.triowner with ->f.area
+    while running, 'triangulated_facet_list' is a list of
+       one non-simplicial facet followed by its 'f.tricoplanar' triangulated facets
+    See qh_buildcone
+*/
+void qh_triangulate(qhT *qh /* qh.facet_list */) {
+  facetT *facet, *nextfacet, *owner;
+  facetT *neighbor, *visible= NULL, *facet1, *facet2, *triangulated_facet_list= NULL;
+  facetT *orig_neighbor= NULL, *otherfacet;
+  vertexT *triangulated_vertex_list= NULL;
+  mergeT *merge;
+  mergeType mergetype;
+  int neighbor_i, neighbor_n;
+  boolT onlygood= qh->ONLYgood;
+
+  if (qh->hasTriangulation)
+      return;
+  trace1((qh, qh->ferr, 1034, "qh_triangulate: triangulate non-simplicial facets\n"));
+  if (qh->hull_dim == 2)
+    return;
+  if (qh->VORONOI) {  /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
+    qh_clearcenters(qh, qh_ASvoronoi);
+    qh_vertexneighbors(qh);
+  }
+  qh->ONLYgood= False; /* for makenew_nonsimplicial */
+  qh->visit_id++;
+  qh_initmergesets(qh /* qh.facet_mergeset,degen_mergeset,vertex_mergeset */);
+  qh->newvertex_list= qh->vertex_tail;
+  for (facet=qh->facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
+    nextfacet= facet->next;
+    if (facet->visible || facet->simplicial)
+      continue;
+    /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
+    if (!triangulated_facet_list)
+      triangulated_facet_list= facet;  /* will be first triangulated facet */
+    qh_triangulate_facet(qh, facet, &triangulated_vertex_list); /* qh_resetlists ! */
+  }
+  /* qh_checkpolygon invalid due to f.visible without qh.visible_list */
+  trace2((qh, qh->ferr, 2047, "qh_triangulate: delete null facets from facetlist f%d.  A null facet has the same first (apex) and second vertices\n", getid_(triangulated_facet_list)));
+  for (facet=triangulated_facet_list; facet && facet->next; facet= nextfacet) {
+    nextfacet= facet->next;
+    if (facet->visible)
+      continue;
+    if (facet->ridges) {
+      if (qh_setsize(qh, facet->ridges) > 0) {
+        qh_fprintf(qh, qh->ferr, 6161, "qhull internal error (qh_triangulate): ridges still defined for f%d\n", facet->id);
+        qh_errexit(qh, qh_ERRqhull, facet, NULL);
+      }
+      qh_setfree(qh, &facet->ridges);
+    }
+    if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
+      zinc_(Ztrinull);
+      qh_triangulate_null(qh, facet); /* will delete facet */
+    }
+  }
+  trace2((qh, qh->ferr, 2048, "qh_triangulate: delete %d or more mirrored facets.  Mirrored facets have the same vertices due to a null facet\n", qh_setsize(qh, qh->degen_mergeset)));
+  qh->visible_list= qh->facet_tail;
+  while ((merge= (mergeT *)qh_setdellast(qh->degen_mergeset))) {
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    mergetype= merge->mergetype;
+    qh_memfree(qh, merge, (int)sizeof(mergeT));
+    if (mergetype == MRGmirror) {
+      zinc_(Ztrimirror);
+      qh_triangulate_mirror(qh, facet1, facet2);  /* will delete both facets */
+    }
+  }
+  qh_freemergesets(qh);
+  trace2((qh, qh->ferr, 2049, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(triangulated_vertex_list)));
+  qh->newvertex_list= triangulated_vertex_list;  /* all vertices of triangulated facets */
+  qh->visible_list= NULL;
+  qh_update_vertexneighbors(qh /* qh.newvertex_list, empty newfacet_list and visible_list */);
+  qh_resetlists(qh, False, !qh_RESETvisible /* qh.newvertex_list, empty newfacet_list and visible_list */);
+
+  trace2((qh, qh->ferr, 2050, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(triangulated_facet_list)));
+  trace2((qh, qh->ferr, 2051, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
+  FORALLfacet_(triangulated_facet_list) {
+    if (facet->tricoplanar && !facet->visible) {
+      FOREACHneighbor_i_(qh, facet) {
+        if (neighbor_i == 0) {  /* first iteration */
+          if (neighbor->tricoplanar)
+            orig_neighbor= neighbor->f.triowner;
+          else
+            orig_neighbor= neighbor;
+        }else {
+          if (neighbor->tricoplanar)
+            otherfacet= neighbor->f.triowner;
+          else
+            otherfacet= neighbor;
+          if (orig_neighbor == otherfacet) {
+            zinc_(Ztridegen);
+            facet->degenerate= True;
+            break;
+          }
+        }
+      }
+    }
+  }
+  if (qh->IStracing >= 4)
+    qh_printlists(qh);
+  trace2((qh, qh->ferr, 2052, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
+  owner= NULL;
+  visible= NULL;
+  for (facet=triangulated_facet_list; facet && facet->next; facet= nextfacet) {
+    /* deleting facets, triangulated_facet_list is no longer valid */
+    nextfacet= facet->next;
+    if (facet->visible) {
+      if (facet->tricoplanar) { /* a null or mirrored facet */
+        qh_delfacet(qh, facet);
+        qh->num_visible--;
+      }else {  /* a non-simplicial facet followed by its tricoplanars */
+        if (visible && !owner) {
+          /*  RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
+          trace2((qh, qh->ferr, 2053, "qh_triangulate: delete f%d.  All tricoplanar facets degenerate for non-simplicial facet\n",
+                       visible->id));
+          qh_delfacet(qh, visible);
+          qh->num_visible--;
+        }
+        visible= facet;
+        owner= NULL;
+      }
+    }else if (facet->tricoplanar) {
+      if (facet->f.triowner != visible || visible==NULL) {
+        qh_fprintf(qh, qh->ferr, 6162, "qhull internal error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
+        qh_errexit2(qh, qh_ERRqhull, facet, visible);
+      }
+      if (owner)
+        facet->f.triowner= owner;
+      else if (!facet->degenerate) {
+        owner= facet;
+        nextfacet= visible->next; /* rescan tricoplanar facets with owner, visible!=0 by QH6162 */
+        facet->keepcentrum= True;  /* one facet owns ->normal, etc. */
+        facet->coplanarset= visible->coplanarset;
+        facet->outsideset= visible->outsideset;
+        visible->coplanarset= NULL;
+        visible->outsideset= NULL;
+        if (!qh->TRInormals) { /* center and normal copied to tricoplanar facets */
+          visible->center= NULL;
+          visible->normal= NULL;
+        }
+        qh_delfacet(qh, visible);
+        qh->num_visible--;
+      }
+    }
+    facet->degenerate= False; /* reset f.degenerate set by qh_triangulate*/
+  }
+  if (visible && !owner) {
+    trace2((qh, qh->ferr, 2054, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
+                 visible->id));
+    qh_delfacet(qh, visible);
+    qh->num_visible--;
+  }
+  qh->ONLYgood= onlygood; /* restore value */
+  if (qh->CHECKfrequently)
+    qh_checkpolygon(qh, qh->facet_list);
+  qh->hasTriangulation= True;
+} /* triangulate */
+
+
+/*---------------------------------
+
+  qh_triangulate_facet(qh, facetA, &firstVertex )
+    triangulate a non-simplicial facet
+      if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
+  returns:
+    qh.newfacet_list == simplicial facets
+      facet->tricoplanar set and ->keepcentrum false
+      facet->degenerate set if duplicated apex
+      facet->f.trivisible set to facetA
+      facet->center copied from facetA (created if qh_ASvoronoi)
+        qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
+      facet->normal,offset,maxoutside copied from facetA
+
+  notes:
+      only called by qh_triangulate
+      qh_makenew_nonsimplicial uses neighbor->seen for the same
+      if qh.TRInormals, newfacet->normal will need qh_free
+        if qh.TRInormals and qh_AScentrum, newfacet->center will need qh_free
+        keepcentrum is also set on Zwidefacet in qh_mergefacet
+        freed by qh_clearcenters
+
+  see also:
+      qh_addpoint() -- add a point
+      qh_makenewfacets() -- construct a cone of facets for a new vertex
+
+  design:
+      if qh_ASvoronoi,
+         compute Voronoi center (facet->center)
+      select first vertex (highest ID to preserve ID ordering of ->vertices)
+      triangulate from vertex to ridges
+      copy facet->center, normal, offset
+      update vertex neighbors
+*/
+void qh_triangulate_facet(qhT *qh, facetT *facetA, vertexT **first_vertex) {
+  facetT *newfacet;
+  facetT *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  trace3((qh, qh->ferr, 3020, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
+
+  qh->first_newfacet= qh->facet_id;
+  if (qh->IStracing >= 4)
+    qh_printfacet(qh, qh->ferr, facetA);
+  FOREACHneighbor_(facetA) {
+    neighbor->seen= False;
+    neighbor->coplanarhorizon= False;
+  }
+  if (qh->CENTERtype == qh_ASvoronoi && !facetA->center  /* matches upperdelaunay in qh_setfacetplane() */
+  && fabs_(facetA->normal[qh->hull_dim -1]) >= qh->ANGLEround * qh_ZEROdelaunay) {
+    facetA->center= qh_facetcenter(qh, facetA->vertices);
+  }
+  qh->visible_list= qh->newfacet_list= qh->facet_tail;
+  facetA->visitid= qh->visit_id;
+  apex= SETfirstt_(facetA->vertices, vertexT);
+  qh_makenew_nonsimplicial(qh, facetA, apex, &numnew);
+  qh_willdelete(qh, facetA, NULL);
+  FORALLnew_facets {
+    newfacet->tricoplanar= True;
+    newfacet->f.trivisible= facetA;
+    newfacet->degenerate= False;
+    newfacet->upperdelaunay= facetA->upperdelaunay;
+    newfacet->good= facetA->good;
+    if (qh->TRInormals) { /* 'Q11' triangulate duplicates ->normal and ->center */
+      newfacet->keepcentrum= True;
+      if(facetA->normal){
+        newfacet->normal= (coordT *)qh_memalloc(qh, qh->normal_size);
+        memcpy((char *)newfacet->normal, facetA->normal, (size_t)qh->normal_size);
+      }
+      if (qh->CENTERtype == qh_AScentrum)
+        newfacet->center= qh_getcentrum(qh, newfacet);
+      else if (qh->CENTERtype == qh_ASvoronoi && facetA->center){
+        newfacet->center= (coordT *)qh_memalloc(qh, qh->center_size);
+        memcpy((char *)newfacet->center, facetA->center, (size_t)qh->center_size);
+      }
+    }else {
+      newfacet->keepcentrum= False;
+      /* one facet will have keepcentrum=True at end of qh_triangulate */
+      newfacet->normal= facetA->normal;
+      newfacet->center= facetA->center;
+    }
+    newfacet->offset= facetA->offset;
+#if qh_MAXoutside
+    newfacet->maxoutside= facetA->maxoutside;
+#endif
+  }
+  qh_matchnewfacets(qh /* qh.newfacet_list */); /* ignore returned value, maxdupdist */
+  zinc_(Ztricoplanar);
+  zadd_(Ztricoplanartot, numnew);
+  zmax_(Ztricoplanarmax, numnew);
+  if (!(*first_vertex))
+    (*first_vertex)= qh->newvertex_list;
+  qh->newvertex_list= NULL;
+  qh->visible_list= NULL;
+  /* only update v.neighbors for qh.newfacet_list.  qh.visible_list and qh.newvertex_list are NULL */
+  qh_update_vertexneighbors(qh /* qh.newfacet_list */);
+  qh_resetlists(qh, False, !qh_RESETvisible /* qh.newfacet_list */);
+} /* triangulate_facet */
+
+/*---------------------------------
+
+  qh_triangulate_link(qh, oldfacetA, facetA, oldfacetB, facetB)
+    relink facetA to facetB via null oldfacetA or mirrored oldfacetA and oldfacetB
+  returns:
+    if neighbors are already linked, will merge as MRGmirror (qh.degen_mergeset, 4-d and up)
+*/
+void qh_triangulate_link(qhT *qh, facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
+  int errmirror= False;
+
+  if (oldfacetA == oldfacetB) {
+    trace3((qh, qh->ferr, 3052, "qh_triangulate_link: relink neighbors f%d and f%d of null facet f%d\n",
+      facetA->id, facetB->id, oldfacetA->id));
+  }else {
+    trace3((qh, qh->ferr, 3021, "qh_triangulate_link: relink neighbors f%d and f%d of mirrored facets f%d and f%d\n",
+      facetA->id, facetB->id, oldfacetA->id, oldfacetB->id));
+  }
+  if (qh_setin(facetA->neighbors, facetB)) {
+    if (!qh_setin(facetB->neighbors, facetA))
+      errmirror= True;
+    else if (!facetA->redundant || !facetB->redundant || !qh_hasmerge(qh->degen_mergeset, MRGmirror, facetA, facetB))
+      qh_appendmergeset(qh, facetA, facetB, MRGmirror, 0.0, 1.0);
+  }else if (qh_setin(facetB->neighbors, facetA))
+    errmirror= True;
+  if (errmirror) {
+    qh_fprintf(qh, qh->ferr, 6163, "qhull internal error (qh_triangulate_link): neighbors f%d and f%d do not match for null facet or mirrored facets f%d and f%d\n",
+       facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
+    qh_errexit2(qh, qh_ERRqhull, facetA, facetB);
+  }
+  qh_setreplace(qh, facetB->neighbors, oldfacetB, facetA);
+  qh_setreplace(qh, facetA->neighbors, oldfacetA, facetB);
+} /* triangulate_link */
+
+/*---------------------------------
+
+  qh_triangulate_mirror(qh, facetA, facetB)
+    delete two mirrored facets identified by qh_triangulate_null() and itself
+      a mirrored facet shares the same vertices of a logical ridge
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_mirror(qhT *qh, facetT *facetA, facetT *facetB) {
+  facetT *neighbor, *neighborB;
+  int neighbor_i, neighbor_n;
+
+  trace3((qh, qh->ferr, 3022, "qh_triangulate_mirror: delete mirrored facets f%d and f%d and link their neighbors\n",
+         facetA->id, facetB->id));
+  FOREACHneighbor_i_(qh, facetA) {
+    neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
+    if (neighbor == facetB && neighborB == facetA)
+      continue; /* occurs twice */
+    else if (neighbor->redundant && neighborB->redundant) { /* also mirrored facets (D5+) */
+      if (qh_hasmerge(qh->degen_mergeset, MRGmirror, neighbor, neighborB))
+        continue;
+    }
+    if (neighbor->visible && neighborB->visible) /* previously deleted as mirrored facets */
+      continue;
+    qh_triangulate_link(qh, facetA, neighbor, facetB, neighborB);
+  }
+  qh_willdelete(qh, facetA, NULL);
+  qh_willdelete(qh, facetB, NULL);
+} /* triangulate_mirror */
+
+/*---------------------------------
+
+  qh_triangulate_null(qh, facetA)
+    remove null facetA from qh_triangulate_facet()
+      a null facet has vertex #1 (apex) == vertex #2
+  returns:
+    adds facetA to ->visible for deletion after qh_update_vertexneighbors
+    qh->degen_mergeset contains mirror facets (4-d and up only)
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors will be merged (MRGmirror)
+*/
+void qh_triangulate_null(qhT *qh, facetT *facetA) {
+  facetT *neighbor, *otherfacet;
+
+  trace3((qh, qh->ferr, 3023, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
+  neighbor= SETfirstt_(facetA->neighbors, facetT);
+  otherfacet= SETsecondt_(facetA->neighbors, facetT);
+  qh_triangulate_link(qh, facetA, neighbor, facetA, otherfacet);
+  qh_willdelete(qh, facetA, NULL);
+} /* triangulate_null */
+
+#else /* qh_NOmerge */
+void qh_triangulate(qhT *qh) {
+  QHULL_UNUSED(qh)
+}
+#endif /* qh_NOmerge */
+
+/*---------------------------------
+
+  qh_vertexintersect(qh, verticesA, verticesB )
+    intersects two vertex sets (inverse id ordered)
+    vertexsetA is a temporary set at the top of qh->qhmem.tempstack
+
+  returns:
+    replaces vertexsetA with the intersection
+
+  notes:
+    only called by qh_neighbor_intersections
+    if !qh.QHULLfinished, non-simplicial facets may have f.vertices with extraneous vertices
+      cleaned by qh_remove_extravertices in qh_reduce_vertices
+    could optimize by overwriting vertexsetA
+*/
+void qh_vertexintersect(qhT *qh, setT **vertexsetA, setT *vertexsetB) {
+  setT *intersection;
+
+  intersection= qh_vertexintersect_new(qh, *vertexsetA, vertexsetB);
+  qh_settempfree(qh, vertexsetA);
+  *vertexsetA= intersection;
+  qh_settemppush(qh, intersection);
+} /* vertexintersect */
+
+/*---------------------------------
+
+  qh_vertexintersect_new(qh, verticesA, verticesB )
+    intersects two vertex sets (inverse id ordered)
+
+  returns:
+    a new set
+
+  notes:
+    called by qh_checkfacet, qh_vertexintersect, qh_rename_sharedvertex, qh_findbest_pinchedvertex, qh_neighbor_intersections
+    if !qh.QHULLfinished, non-simplicial facets may have f.vertices with extraneous vertices
+       cleaned by qh_remove_extravertices in qh_reduce_vertices
+*/
+setT *qh_vertexintersect_new(qhT *qh, setT *vertexsetA, setT *vertexsetB) {
+  setT *intersection= qh_setnew(qh, qh->hull_dim - 1);
+  vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
+  vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
+
+  while (*vertexA && *vertexB) {
+    if (*vertexA  == *vertexB) {
+      qh_setappend(qh, &intersection, *vertexA);
+      vertexA++; vertexB++;
+    }else {
+      if ((*vertexA)->id > (*vertexB)->id)
+        vertexA++;
+      else
+        vertexB++;
+    }
+  }
+  return intersection;
+} /* vertexintersect_new */
+
+/*---------------------------------
+
+  qh_vertexneighbors(qh)
+    for each vertex in qh.facet_list,
+      determine its neighboring facets
+
+  returns:
+    sets qh.VERTEXneighbors
+      nop if qh.VERTEXneighbors already set
+      qh_addpoint() will maintain them
+
+  notes:
+    assumes all vertex->neighbors are NULL
+
+  design:
+    for each facet
+      for each vertex
+        append facet to vertex->neighbors
+*/
+void qh_vertexneighbors(qhT *qh /* qh.facet_list */) {
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+
+  if (qh->VERTEXneighbors)
+    return;
+  trace1((qh, qh->ferr, 1035, "qh_vertexneighbors: determining neighboring facets for each vertex\n"));
+  qh->vertex_visit++;
+  FORALLfacets {
+    if (facet->visible)
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh->vertex_visit) {
+        vertex->visitid= qh->vertex_visit;
+        vertex->neighbors= qh_setnew(qh, qh->hull_dim);
+      }
+      qh_setappend(qh, &vertex->neighbors, facet);
+    }
+  }
+  qh->VERTEXneighbors= True;
+} /* vertexneighbors */
+
+/*---------------------------------
+
+  qh_vertexsubset( vertexsetA, vertexsetB )
+    returns True if vertexsetA is a subset of vertexsetB
+    assumes vertexsets are sorted
+
+  note:
+    empty set is a subset of any other set
+*/
+boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
+  vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
+  vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
+
+  while (True) {
+    if (!*vertexA)
+      return True;
+    if (!*vertexB)
+      return False;
+    if ((*vertexA)->id > (*vertexB)->id)
+      return False;
+    if (*vertexA  == *vertexB)
+      vertexA++;
+    vertexB++;
+  }
+  return False; /* avoid warnings */
+} /* vertexsubset */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.c
new file mode 100644
index 00000000000..d6a5e7a3d8c
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.c
@@ -0,0 +1,1448 @@
+/*
  ---------------------------------
+
+   poly_r.c
+   implements polygons and simplices
+
+   see qh-poly_r.htm, poly_r.h and libqhull_r.h
+
+   infrequent code is in poly2_r.c
+   (all but top 50 and their callers 12/3/95)
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/poly_r.c#8 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#include "qhull_ra.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*---------------------------------
+
+  qh_appendfacet(qh, facet )
+    appends facet to end of qh.facet_list,
+
+  returns:
+    updates qh.newfacet_list, facet_next, facet_list
+    increments qh.numfacets
+
+  notes:
+    assumes qh.facet_list/facet_tail is defined (createsimplex)
+
+  see:
+    qh_removefacet()
+
+*/
+void qh_appendfacet(qhT *qh, facetT *facet) {
+  facetT *tail= qh->facet_tail;
+
+  if (tail == qh->newfacet_list) {
+    qh->newfacet_list= facet;
+    if (tail == qh->visible_list) /* visible_list is at or before newfacet_list */
+      qh->visible_list= facet;
+  }
+  if (tail == qh->facet_next)
+    qh->facet_next= facet;
+  facet->previous= tail->previous;
+  facet->next= tail;
+  if (tail->previous)
+    tail->previous->next= facet;
+  else
+    qh->facet_list= facet;
+  tail->previous= facet;
+  qh->num_facets++;
+  trace4((qh, qh->ferr, 4044, "qh_appendfacet: append f%d to facet_list\n", facet->id));
+} /* appendfacet */
+
+
+/*---------------------------------
+
+  qh_appendvertex(qh, vertex )
+    appends vertex to end of qh.vertex_list,
+
+  returns:
+    sets vertex->newfacet
+    updates qh.vertex_list, newvertex_list
+    increments qh.num_vertices
+
+  notes:
+    assumes qh.vertex_list/vertex_tail is defined (createsimplex)
+
+*/
+void qh_appendvertex(qhT *qh, vertexT *vertex) {
+  vertexT *tail= qh->vertex_tail;
+
+  if (tail == qh->newvertex_list)
+    qh->newvertex_list= vertex;
+  vertex->newfacet= True;
+  vertex->previous= tail->previous;
+  vertex->next= tail;
+  if (tail->previous)
+    tail->previous->next= vertex;
+  else
+    qh->vertex_list= vertex;
+  tail->previous= vertex;
+  qh->num_vertices++;
+  trace4((qh, qh->ferr, 4045, "qh_appendvertex: append v%d to qh.newvertex_list and set v.newfacet\n", vertex->id));
+} /* appendvertex */
+
+
+/*---------------------------------
+
+  qh_attachnewfacets(qh)
+    attach horizon facets to new facets in qh.newfacet_list
+    newfacets have neighbor and ridge links to horizon but not vice versa
+
+  returns:
+    clears qh.NEWtentative
+    set qh.NEWfacets
+    horizon facets linked to new facets
+      ridges changed from visible facets to new facets
+      simplicial ridges deleted
+    qh.visible_list, no ridges valid
+    facet->f.replace is a newfacet (if any)
+
+  notes:
+    used for qh.NEWtentative, otherwise see qh_makenew_nonsimplicial and qh_makenew_simplicial
+    qh_delridge_merge not needed (as tested by qh_checkdelridge)
+
+  design:
+    delete interior ridges and neighbor sets by
+      for each visible, non-simplicial facet
+        for each ridge
+          if last visit or if neighbor is simplicial
+            if horizon neighbor
+              delete ridge for horizon's ridge set
+            delete ridge
+        erase neighbor set
+    attach horizon facets and new facets by
+      for all new facets
+        if corresponding horizon facet is simplicial
+          locate corresponding visible facet {may be more than one}
+          link visible facet to new facet
+          replace visible facet with new facet in horizon
+        else it is non-simplicial
+          for all visible neighbors of the horizon facet
+            link visible neighbor to new facet
+            delete visible neighbor from horizon facet
+          append new facet to horizon's neighbors
+          the first ridge of the new facet is the horizon ridge
+          link the new facet into the horizon ridge
+*/
+void qh_attachnewfacets(qhT *qh /* qh.visible_list, qh.newfacet_list */) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
+  ridgeT *ridge, **ridgep;
+
+  trace3((qh, qh->ferr, 3012, "qh_attachnewfacets: delete interior ridges\n"));
+  if (qh->CHECKfrequently) {
+    qh_checkdelridge(qh);
+  }
+  qh->visit_id++;
+  FORALLvisible_facets {
+    visible->visitid= qh->visit_id;
+    if (visible->ridges) {
+      FOREACHridge_(visible->ridges) {
+        neighbor= otherfacet_(ridge, visible);
+        if (neighbor->visitid == qh->visit_id
+            || (!neighbor->visible && neighbor->simplicial)) {
+          if (!neighbor->visible)  /* delete ridge for simplicial horizon */
+            qh_setdel(neighbor->ridges, ridge);
+          qh_delridge(qh, ridge); /* delete on second visit */
+        }
+      }
+    }
+  }
+  trace1((qh, qh->ferr, 1017, "qh_attachnewfacets: attach horizon facets to new facets\n"));
+  FORALLnew_facets {
+    horizon= SETfirstt_(newfacet->neighbors, facetT);
+    if (horizon->simplicial) {
+      visible= NULL;
+      FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
+        if (neighbor->visible) {
+          if (visible) {
+            if (qh_setequal_skip(newfacet->vertices, 0, horizon->vertices,
+                                  SETindex_(horizon->neighbors, neighbor))) {
+              visible= neighbor;
+              break;
+            }
+          }else
+            visible= neighbor;
+        }
+      }
+      if (visible) {
+        visible->f.replace= newfacet;
+        qh_setreplace(qh, horizon->neighbors, visible, newfacet);
+      }else {
+        qh_fprintf(qh, qh->ferr, 6102, "qhull internal error (qh_attachnewfacets): could not find visible facet for horizon f%d of newfacet f%d\n",
+                 horizon->id, newfacet->id);
+        qh_errexit2(qh, qh_ERRqhull, horizon, newfacet);
+      }
+    }else { /* non-simplicial, with a ridge for newfacet */
+      FOREACHneighbor_(horizon) {    /* may hold for many new facets */
+        if (neighbor->visible) {
+          neighbor->f.replace= newfacet;
+          qh_setdelnth(qh, horizon->neighbors, SETindex_(horizon->neighbors, neighbor));
+          neighborp--; /* repeat */
+        }
+      }
+      qh_setappend(qh, &horizon->neighbors, newfacet);
+      ridge= SETfirstt_(newfacet->ridges, ridgeT);
+      if (ridge->top == horizon) {
+        ridge->bottom= newfacet;
+        ridge->simplicialbot= True;
+      }else {
+        ridge->top= newfacet;
+        ridge->simplicialtop= True;
+      }
+    }
+  } /* newfacets */
+  trace4((qh, qh->ferr, 4094, "qh_attachnewfacets: clear f.ridges and f.neighbors for visible facets, may become invalid before qh_deletevisible\n"));
+  FORALLvisible_facets {
+    if (visible->ridges)
+      SETfirst_(visible->ridges)= NULL; 
+    SETfirst_(visible->neighbors)= NULL;
+  }
+  qh->NEWtentative= False;
+  qh->NEWfacets= True;
+  if (qh->PRINTstatistics) {
+    FORALLvisible_facets {
+      if (!visible->f.replace)
+        zinc_(Zinsidevisible);
+    }
+  }
+} /* attachnewfacets */
+
+/*---------------------------------
+
+  qh_checkflipped(qh, facet, dist, allerror )
+    checks facet orientation to interior point
+
+    if allerror set,
+      tests against -qh.DISTround
+    else
+      tests against 0.0 since tested against -qh.DISTround before
+
+  returns:
+    False if it flipped orientation (sets facet->flipped)
+    distance if non-NULL
+
+  notes:
+    called by qh_setfacetplane, qh_initialhull, and qh_checkflipped_all
+*/
+boolT qh_checkflipped(qhT *qh, facetT *facet, realT *distp, boolT allerror) {
+  realT dist;
+
+  if (facet->flipped && !distp)
+    return False;
+  zzinc_(Zdistcheck);
+  qh_distplane(qh, qh->interior_point, facet, &dist);
+  if (distp)
+    *distp= dist;
+  if ((allerror && dist >= -qh->DISTround) || (!allerror && dist > 0.0)) {
+    facet->flipped= True;
+    trace0((qh, qh->ferr, 19, "qh_checkflipped: facet f%d flipped, allerror? %d, distance= %6.12g during p%d\n",
+              facet->id, allerror, dist, qh->furthest_id));
+    if (qh->num_facets > qh->hull_dim+1) { /* qh_initialhull reverses orientation if !qh_checkflipped */
+      zzinc_(Zflippedfacets);
+      qh_joggle_restart(qh, "flipped facet");
+    }
+    return False;
+  }
+  return True;
+} /* checkflipped */
+
+/*---------------------------------
+
+  qh_delfacet(qh, facet )
+    removes facet from facet_list and frees up its memory
+
+  notes:
+    assumes vertices and ridges already freed or referenced elsewhere
+*/
+void qh_delfacet(qhT *qh, facetT *facet) {
+  void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
+
+  trace3((qh, qh->ferr, 3057, "qh_delfacet: delete f%d\n", facet->id));
+  if (qh->CHECKfrequently || qh->VERIFYoutput) { 
+    if (!qh->NOerrexit) {
+      qh_checkdelfacet(qh, facet, qh->facet_mergeset);
+      qh_checkdelfacet(qh, facet, qh->degen_mergeset);
+      qh_checkdelfacet(qh, facet, qh->vertex_mergeset);
+    }
+  }
+  if (facet == qh->tracefacet)
+    qh->tracefacet= NULL;
+  if (facet == qh->GOODclosest)
+    qh->GOODclosest= NULL;
+  qh_removefacet(qh, facet);
+  if (!facet->tricoplanar || facet->keepcentrum) {
+    qh_memfree_(qh, facet->normal, qh->normal_size, freelistp);
+    if (qh->CENTERtype == qh_ASvoronoi) {   /* braces for macro calls */
+      qh_memfree_(qh, facet->center, qh->center_size, freelistp);
+    }else /* AScentrum */ {
+      qh_memfree_(qh, facet->center, qh->normal_size, freelistp);
+    }
+  }
+  qh_setfree(qh, &(facet->neighbors));
+  if (facet->ridges)
+    qh_setfree(qh, &(facet->ridges));
+  qh_setfree(qh, &(facet->vertices));
+  if (facet->outsideset)
+    qh_setfree(qh, &(facet->outsideset));
+  if (facet->coplanarset)
+    qh_setfree(qh, &(facet->coplanarset));
+  qh_memfree_(qh, facet, (int)sizeof(facetT), freelistp);
+} /* delfacet */
+
+
+/*---------------------------------
+
+  qh_deletevisible()
+    delete visible facets and vertices
+
+  returns:
+    deletes each facet and removes from facetlist
+    deletes vertices on qh.del_vertices and ridges in qh.del_ridges
+    at exit, qh.visible_list empty (== qh.newfacet_list)
+
+  notes:
+    called by qh_all_vertexmerges, qh_addpoint, and qh_qhull
+    ridges already deleted or moved elsewhere
+    deleted vertices on qh.del_vertices
+    horizon facets do not reference facets on qh.visible_list
+    new facets in qh.newfacet_list
+    uses   qh.visit_id;
+*/
+void qh_deletevisible(qhT *qh /* qh.visible_list */) {
+  facetT *visible, *nextfacet;
+  vertexT *vertex, **vertexp;
+  int numvisible= 0, numdel= qh_setsize(qh, qh->del_vertices);
+
+  trace1((qh, qh->ferr, 1018, "qh_deletevisible: delete %d visible facets and %d vertices\n",
+         qh->num_visible, numdel));
+  for (visible=qh->visible_list; visible && visible->visible;
+                visible= nextfacet) { /* deleting current */
+    nextfacet= visible->next;
+    numvisible++;
+    qh_delfacet(qh, visible);  /* f.ridges deleted or moved elsewhere, deleted f.vertices on qh.del_vertices */
+  }
+  if (numvisible != qh->num_visible) {
+    qh_fprintf(qh, qh->ferr, 6103, "qhull internal error (qh_deletevisible): qh->num_visible %d is not number of visible facets %d\n",
+             qh->num_visible, numvisible);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  qh->num_visible= 0;
+  zadd_(Zvisfacettot, numvisible);
+  zmax_(Zvisfacetmax, numvisible);
+  zzadd_(Zdelvertextot, numdel);
+  zmax_(Zdelvertexmax, numdel);
+  FOREACHvertex_(qh->del_vertices)
+    qh_delvertex(qh, vertex);
+  qh_settruncate(qh, qh->del_vertices, 0);
+} /* deletevisible */
+
+/*---------------------------------
+
+  qh_facetintersect(qh, facetA, facetB, skipa, skipB, prepend )
+    return vertices for intersection of two simplicial facets
+    may include 1 prepended entry (if more, need to settemppush)
+
+  returns:
+    returns set of qh.hull_dim-1 + prepend vertices
+    returns skipped index for each test and checks for exactly one
+
+  notes:
+    does not need settemp since set in quick memory
+
+  see also:
+    qh_vertexintersect and qh_vertexintersect_new
+    use qh_setnew_delnthsorted to get nth ridge (no skip information)
+
+  design:
+    locate skipped vertex by scanning facet A's neighbors
+    locate skipped vertex by scanning facet B's neighbors
+    intersect the vertex sets
+*/
+setT *qh_facetintersect(qhT *qh, facetT *facetA, facetT *facetB,
+                         int *skipA,int *skipB, int prepend) {
+  setT *intersect;
+  int dim= qh->hull_dim, i, j;
+  facetT **neighborsA, **neighborsB;
+
+  neighborsA= SETaddr_(facetA->neighbors, facetT);
+  neighborsB= SETaddr_(facetB->neighbors, facetT);
+  i= j= 0;
+  if (facetB == *neighborsA++)
+    *skipA= 0;
+  else if (facetB == *neighborsA++)
+    *skipA= 1;
+  else if (facetB == *neighborsA++)
+    *skipA= 2;
+  else {
+    for (i=3; i < dim; i++) {
+      if (facetB == *neighborsA++) {
+        *skipA= i;
+        break;
+      }
+    }
+  }
+  if (facetA == *neighborsB++)
+    *skipB= 0;
+  else if (facetA == *neighborsB++)
+    *skipB= 1;
+  else if (facetA == *neighborsB++)
+    *skipB= 2;
+  else {
+    for (j=3; j < dim; j++) {
+      if (facetA == *neighborsB++) {
+        *skipB= j;
+        break;
+      }
+    }
+  }
+  if (i >= dim || j >= dim) {
+    qh_fprintf(qh, qh->ferr, 6104, "qhull internal error (qh_facetintersect): f%d or f%d not in other's neighbors\n",
+            facetA->id, facetB->id);
+    qh_errexit2(qh, qh_ERRqhull, facetA, facetB);
+  }
+  intersect= qh_setnew_delnthsorted(qh, facetA->vertices, qh->hull_dim, *skipA, prepend);
+  trace4((qh, qh->ferr, 4047, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
+          facetA->id, *skipA, facetB->id, *skipB));
+  return(intersect);
+} /* facetintersect */
+
+/*---------------------------------
+
+  qh_gethash(qh, hashsize, set, size, firstindex, skipelem )
+    return hashvalue for a set with firstindex and skipelem
+
+  notes:
+    returned hash is in [0,hashsize)
+    assumes at least firstindex+1 elements
+    assumes skipelem is NULL, in set, or part of hash
+
+    hashes memory addresses which may change over different runs of the same data
+    using sum for hash does badly in high d
+*/
+int qh_gethash(qhT *qh, int hashsize, setT *set, int size, int firstindex, void *skipelem) {
+  void **elemp= SETelemaddr_(set, firstindex, void);
+  ptr_intT hash= 0, elem;
+  unsigned int uresult;
+  int i;
+#ifdef _MSC_VER                   /* Microsoft Visual C++ -- warn about 64-bit issues */
+#pragma warning( push)            /* WARN64 -- ptr_intT holds a 64-bit pointer */
+#pragma warning( disable : 4311)  /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */
+#endif
+
+  switch (size-firstindex) {
+  case 1:
+    hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
+    break;
+  case 2:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
+    break;
+  case 3:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      - (ptr_intT) skipelem;
+    break;
+  case 4:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
+    break;
+  case 5:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
+    break;
+  case 6:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
+      - (ptr_intT) skipelem;
+    break;
+  default:
+    hash= 0;
+    i= 3;
+    do {     /* this is about 10% in 10-d */
+      if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
+        hash ^= (elem << i) + (elem >> (32-i));
+        i += 3;
+        if (i >= 32)
+          i -= 32;
+      }
+    }while (*elemp);
+    break;
+  }
+  if (hashsize<0) {
+    qh_fprintf(qh, qh->ferr, 6202, "qhull internal error: negative hashsize %d passed to qh_gethash [poly_r.c]\n", hashsize);
+    qh_errexit2(qh, qh_ERRqhull, NULL, NULL);
+  }
+  uresult= (unsigned int)hash;
+  uresult %= (unsigned int)hashsize;
+  /* result= 0; for debugging */
+  return (int)uresult;
+#ifdef _MSC_VER
+#pragma warning( pop)
+#endif
+} /* gethash */
+
+/*---------------------------------
+
+  qh_getreplacement(qh, visible )
+    get replacement for visible facet
+
+  returns:
+    valid facet from visible.replace (may be chained)
+*/
+facetT *qh_getreplacement(qhT *qh, facetT *visible) {
+  unsigned int count= 0;
+
+  facetT *result= visible;
+  while (result && result->visible) {
+    result= result->f.replace;
+    if (count++ > qh->facet_id)
+      qh_infiniteloop(qh, visible);
+  }
+  return result;
+}
+
+/*---------------------------------
+
+  qh_makenewfacet(qh, vertices, toporient, horizon )
+    creates a toporient? facet from vertices
+
+  returns:
+    returns newfacet
+      adds newfacet to qh.facet_list
+      newfacet->vertices= vertices
+      if horizon
+        newfacet->neighbor= horizon, but not vice versa
+    newvertex_list updated with vertices
+*/
+facetT *qh_makenewfacet(qhT *qh, setT *vertices, boolT toporient, facetT *horizon) {
+  facetT *newfacet;
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (!vertex->newfacet) {
+      qh_removevertex(qh, vertex);
+      qh_appendvertex(qh, vertex);
+    }
+  }
+  newfacet= qh_newfacet(qh);
+  newfacet->vertices= vertices;
+  if (toporient)
+    newfacet->toporient= True;
+  if (horizon)
+    qh_setappend(qh, &(newfacet->neighbors), horizon);
+  qh_appendfacet(qh, newfacet);
+  return(newfacet);
+} /* makenewfacet */
+
+
+/*---------------------------------
+
+  qh_makenewplanes()
+    make new hyperplanes for facets on qh.newfacet_list
+
+  returns:
+    all facets have hyperplanes or are marked for   merging
+    doesn't create hyperplane if horizon is coplanar (will merge)
+    updates qh.min_vertex if qh.JOGGLEmax
+
+  notes:
+    facet->f.samecycle is defined for facet->mergehorizon facets
+*/
+void qh_makenewplanes(qhT *qh /* qh.newfacet_list */) {
+  facetT *newfacet;
+
+  trace4((qh, qh->ferr, 4074, "qh_makenewplanes: make new hyperplanes for facets on qh.newfacet_list f%d\n",
+    qh->newfacet_list->id));
+  FORALLnew_facets {
+    if (!newfacet->mergehorizon)
+      qh_setfacetplane(qh, newfacet); /* updates Wnewvertexmax */
+  }
+  if (qh->JOGGLEmax < REALmax/2)
+    minimize_(qh->min_vertex, -wwval_(Wnewvertexmax));
+} /* makenewplanes */
+
+#ifndef qh_NOmerge
+/*---------------------------------
+
+  qh_makenew_nonsimplicial(qh, visible, apex, numnew )
+    make new facets for ridges of a visible facet
+
+  returns:
+    first newfacet, bumps numnew as needed
+    attaches new facets if !qh->NEWtentative
+    marks ridge neighbors for simplicial visible
+    if (qh.NEWtentative)
+      ridges on newfacet, horizon, and visible
+    else
+      ridge and neighbors between newfacet and horizon
+      visible facet's ridges are deleted
+      visible facet's f.neighbors is empty
+
+  notes:
+    called by qh_makenewfacets and qh_triangulatefacet
+    qh.visit_id if visible has already been processed
+    sets neighbor->seen for building f.samecycle
+      assumes all 'seen' flags initially false
+    qh_delridge_merge not needed (as tested by qh_checkdelridge in qh_makenewfacets)
+
+  design:
+    for each ridge of visible facet
+      get neighbor of visible facet
+      if neighbor was already processed
+        delete the ridge (will delete all visible facets later)
+      if neighbor is a horizon facet
+        create a new facet
+        if neighbor coplanar
+          adds newfacet to f.samecycle for later merging
+        else
+          updates neighbor's neighbor set
+          (checks for non-simplicial facet with multiple ridges to visible facet)
+        updates neighbor's ridge set
+        (checks for simplicial neighbor to non-simplicial visible facet)
+        (deletes ridge if neighbor is simplicial)
+
+*/
+facetT *qh_makenew_nonsimplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew) {
+  void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor, *newfacet= NULL, *samecycle;
+  setT *vertices;
+  boolT toporient;
+  unsigned int ridgeid;
+
+  FOREACHridge_(visible->ridges) {
+    ridgeid= ridge->id;
+    neighbor= otherfacet_(ridge, visible);
+    if (neighbor->visible) {
+      if (!qh->NEWtentative) {
+        if (neighbor->visitid == qh->visit_id) {
+          if (qh->traceridge == ridge)
+            qh->traceridge= NULL;
+          qh_setfree(qh, &(ridge->vertices));  /* delete on 2nd visit */
+          qh_memfree_(qh, ridge, (int)sizeof(ridgeT), freelistp);
+        }
+      }
+    }else {  /* neighbor is an horizon facet */
+      toporient= (ridge->top == visible);
+      vertices= qh_setnew(qh, qh->hull_dim); /* makes sure this is quick */
+      qh_setappend(qh, &vertices, apex);
+      qh_setappend_set(qh, &vertices, ridge->vertices);
+      newfacet= qh_makenewfacet(qh, vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanarhorizon) {
+        newfacet->mergehorizon= True;
+        if (!neighbor->seen) {
+          newfacet->f.samecycle= newfacet;
+          neighbor->f.newcycle= newfacet;
+        }else {
+          samecycle= neighbor->f.newcycle;
+          newfacet->f.samecycle= samecycle->f.samecycle;
+          samecycle->f.samecycle= newfacet;
+        }
+      }
+      if (qh->NEWtentative) {
+        if (!neighbor->simplicial)
+          qh_setappend(qh, &(newfacet->ridges), ridge);
+      }else {  /* qh_attachnewfacets */
+        if (neighbor->seen) {
+          if (neighbor->simplicial) {
+            qh_fprintf(qh, qh->ferr, 6105, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
+                   neighbor->id, visible->id);
+            qh_errexit2(qh, qh_ERRqhull, neighbor, visible);
+          }
+          qh_setappend(qh, &(neighbor->neighbors), newfacet);
+        }else
+          qh_setreplace(qh, neighbor->neighbors, visible, newfacet);
+        if (neighbor->simplicial) {
+          qh_setdel(neighbor->ridges, ridge);
+          qh_delridge(qh, ridge);
+        }else {
+          qh_setappend(qh, &(newfacet->ridges), ridge);
+          if (toporient) {
+            ridge->top= newfacet;
+            ridge->simplicialtop= True;
+          }else {
+            ridge->bottom= newfacet;
+            ridge->simplicialbot= True;
+          }
+        }
+      }
+      trace4((qh, qh->ferr, 4048, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
+          newfacet->id, apex->id, ridgeid, neighbor->id));
+    }
+    neighbor->seen= True;
+  } /* for each ridge */
+  return newfacet;
+} /* makenew_nonsimplicial */
+
+#else /* qh_NOmerge */
+facetT *qh_makenew_nonsimplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew) {
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(visible)
+  QHULL_UNUSED(apex)
+  QHULL_UNUSED(numnew)
+
+  return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*---------------------------------
+
+  qh_makenew_simplicial(qh, visible, apex, numnew )
+    make new facets for simplicial visible facet and apex
+
+  returns:
+    attaches new facets if !qh.NEWtentative
+      neighbors between newfacet and horizon
+
+  notes:
+    nop if neighbor->seen or neighbor->visible(see qh_makenew_nonsimplicial)
+
+  design:
+    locate neighboring horizon facet for visible facet
+    determine vertices and orientation
+    create new facet
+    if coplanar,
+      add new facet to f.samecycle
+    update horizon facet's neighbor list
+*/
+facetT *qh_makenew_simplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew) {
+  facetT *neighbor, **neighborp, *newfacet= NULL;
+  setT *vertices;
+  boolT flip, toporient;
+  int horizonskip= 0, visibleskip= 0;
+
+  FOREACHneighbor_(visible) {
+    if (!neighbor->seen && !neighbor->visible) {
+      vertices= qh_facetintersect(qh, neighbor,visible, &horizonskip, &visibleskip, 1);
+      SETfirst_(vertices)= apex;
+      flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
+      if (neighbor->toporient)
+        toporient= horizonskip & 0x1;
+      else
+        toporient= (horizonskip & 0x1) ^ 0x1;
+      newfacet= qh_makenewfacet(qh, vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanarhorizon && (qh->PREmerge || qh->MERGEexact)) {
+#ifndef qh_NOmerge
+        newfacet->f.samecycle= newfacet;
+        newfacet->mergehorizon= True;
+#endif
+      }
+      if (!qh->NEWtentative)
+        SETelem_(neighbor->neighbors, horizonskip)= newfacet;
+      trace4((qh, qh->ferr, 4049, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
+            newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
+              neighbor->toporient, visible->id, visibleskip, flip));
+    }
+  }
+  return newfacet;
+} /* makenew_simplicial */
+
+/*---------------------------------
+
+  qh_matchneighbor(qh, newfacet, newskip, hashsize, hashcount )
+    either match subridge of newfacet with neighbor or add to hash_table
+
+  returns:
+    matched ridges of newfacet, except for duplicate ridges
+    duplicate ridges marked by qh_DUPLICATEridge for qh_matchdupridge
+
+  notes:
+    called by qh_matchnewfacets
+    assumes newfacet is simplicial
+    ridge is newfacet->vertices w/o newskip vertex
+    do not allocate memory (need to free hash_table cleanly)
+    uses linear hash chains
+    see qh_matchdupridge (poly2_r.c)
+
+  design:
+    for each possible matching facet in qh.hash_table
+      if vertices match
+        set ismatch, if facets have opposite orientation
+        if ismatch and matching facet doesn't have a match
+          match the facets by updating their neighbor sets
+        else
+          note: dupridge detected when a match 'f&d skip %d' has already been seen 
+                need to mark all of the dupridges for qh_matchdupridge
+          indicate a duplicate ridge by qh_DUPLICATEridge and f.dupridge
+          add facet to hashtable
+          unless the other facet was already a duplicate ridge
+            mark both facets with a duplicate ridge
+            add other facet (if defined) to hash table
+
+  state at "indicate a duplicate ridge":
+    newfacet@newskip= the argument
+    facet= the hashed facet@skip that has the same vertices as newfacet@newskip
+    same= true if matched vertices have the same orientation
+    matchfacet= neighbor at facet@skip
+    matchfacet=qh_DUPLICATEridge, matchfacet was previously detected as a dupridge of facet@skip
+    ismatch if 'vertex orientation (same) matches facet/newfacet orientation (toporient)
+    unknown facet will match later
+
+  details at "indicate a duplicate ridge":
+    if !ismatch and matchfacet,
+      dupridge is between hashed facet@skip/matchfacet@matchskip and arg newfacet@newskip/unknown 
+      set newfacet@newskip, facet@skip, and matchfacet@matchskip to qh_DUPLICATEridge
+      add newfacet and matchfacet to hash_table
+      if ismatch and matchfacet, 
+        same as !ismatch and matchfacet -- it matches facet instead of matchfacet
+      if !ismatch and !matchfacet
+        dupridge between hashed facet@skip/unknown and arg newfacet@newskip/unknown 
+        set newfacet@newskip and facet@skip to qh_DUPLICATEridge
+        add newfacet to hash_table
+      if ismatch and matchfacet==qh_DUPLICATEridge
+        dupridge with already duplicated hashed facet@skip and arg newfacet@newskip/unknown
+        set newfacet@newskip to qh_DUPLICATEridge
+        add newfacet to hash_table
+        facet's hyperplane already set
+*/
+void qh_matchneighbor(qhT *qh, facetT *newfacet, int newskip, int hashsize, int *hashcount) {
+  boolT newfound= False;   /* True, if new facet is already in hash chain */
+  boolT same, ismatch;
+  int hash, scan;
+  facetT *facet, *matchfacet;
+  int skip, matchskip;
+
+  hash= qh_gethash(qh, hashsize, newfacet->vertices, qh->hull_dim, 1,
+                     SETelem_(newfacet->vertices, newskip));
+  trace4((qh, qh->ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
+          newfacet->id, newskip, hash, *hashcount));
+  zinc_(Zhashlookup);
+  for (scan=hash; (facet= SETelemt_(qh->hash_table, scan, facetT));
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (facet == newfacet) {
+      newfound= True;
+      continue;
+    }
+    zinc_(Zhashtests);
+    if (qh_matchvertices(qh, 1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+      if (SETelem_(newfacet->vertices, newskip) == SETelem_(facet->vertices, skip)) {
+        qh_joggle_restart(qh, "two new facets with the same vertices");
+        /* duplicated for multiple skips, not easily avoided */
+        qh_fprintf(qh, qh->ferr, 7084, "qhull topology warning (qh_matchneighbor): will merge vertices to undo new facets -- f%d and f%d have the same vertices (skip %d, skip %d) and same horizon ridges to f%d and f%d\n",
+          facet->id, newfacet->id, skip, newskip, SETfirstt_(facet->neighbors, facetT)->id, SETfirstt_(newfacet->neighbors, facetT)->id);
+        /* will rename a vertex (QH3053).  The fault was duplicate ridges (same vertices) in different facets due to a previous rename.  Expensive to detect beforehand */
+      }
+      ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient)));
+      matchfacet= SETelemt_(facet->neighbors, skip, facetT);
+      if (ismatch && !matchfacet) {
+        SETelem_(facet->neighbors, skip)= newfacet;
+        SETelem_(newfacet->neighbors, newskip)= facet;
+        (*hashcount)--;
+        trace4((qh, qh->ferr, 4051, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
+           facet->id, skip, newfacet->id, newskip));
+        return;
+      }
+      if (!qh->PREmerge && !qh->MERGEexact) {
+        qh_joggle_restart(qh, "a ridge with more than two neighbors");
+        qh_fprintf(qh, qh->ferr, 6107, "qhull topology error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors.  Can not continue due to no qh.PREmerge and no 'Qx' (MERGEexact)\n",
+                 facet->id, newfacet->id, getid_(matchfacet));
+        qh_errexit2(qh, qh_ERRtopology, facet, newfacet);
+      }
+      SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
+      newfacet->dupridge= True;
+      qh_addhash(newfacet, qh->hash_table, hashsize, hash);
+      (*hashcount)++;
+      if (matchfacet != qh_DUPLICATEridge) {
+        SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
+        facet->dupridge= True;
+        if (matchfacet) {
+          matchskip= qh_setindex(matchfacet->neighbors, facet);
+          if (matchskip<0) {
+              qh_fprintf(qh, qh->ferr, 6260, "qhull topology error (qh_matchneighbor): matchfacet f%d is in f%d neighbors but not vice versa.  Can not continue.\n",
+                  matchfacet->id, facet->id);
+              qh_errexit2(qh, qh_ERRtopology, matchfacet, facet);
+          }
+          SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge; /* matchskip>=0 by QH6260 */
+          matchfacet->dupridge= True;
+          qh_addhash(matchfacet, qh->hash_table, hashsize, hash);
+          *hashcount += 2;
+        }
+      }
+      trace4((qh, qh->ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
+           newfacet->id, newskip, facet->id, skip,
+           (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
+           ismatch, hash));
+      return; /* end of duplicate ridge */
+    }
+  }
+  if (!newfound)
+    SETelem_(qh->hash_table, scan)= newfacet;  /* same as qh_addhash */
+  (*hashcount)++;
+  trace4((qh, qh->ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
+           newfacet->id, newskip, hash));
+} /* matchneighbor */
+
+
+/*---------------------------------
+
+  qh_matchnewfacets(qh )
+    match new facets in qh.newfacet_list to their newfacet neighbors
+    all facets are simplicial
+
+  returns:
+    if dupridges and merging 
+      returns maxdupdist (>=0.0) from vertex to opposite facet
+      sets facet->dupridge
+      missing neighbor links identify dupridges to be merged (qh_DUPLICATEridge)
+    else  
+      qh.newfacet_list with full neighbor sets
+        vertices for the nth neighbor match all but the nth vertex
+    if not merging and qh.FORCEoutput
+      for facets with normals (i.e., with dupridges)
+      sets facet->flippped for flipped normals, also prevents point partitioning
+
+  notes:
+    called by qh_buildcone* and qh_triangulate_facet
+    neighbor[0] of new facets is the horizon facet
+    if NEWtentative, new facets not attached to the horizon
+    assumes qh.hash_table is NULL
+    vertex->neighbors has not been updated yet
+    do not allocate memory after qh.hash_table (need to free it cleanly)
+    
+  design:
+    truncate neighbor sets to horizon facet for all new facets
+    initialize a hash table
+    for all new facets
+      match facet with neighbors
+    if unmatched facets (due to duplicate ridges)
+      for each new facet with a duplicate ridge
+        try to match facets with the same coplanar horizon
+    if not all matched
+      for each new facet with a duplicate ridge
+        match it with a coplanar facet, or identify a pinched vertex
+    if not merging and qh.FORCEoutput
+      check for flipped facets
+*/
+coordT qh_matchnewfacets(qhT *qh /* qh.newfacet_list */) {
+  int numnew=0, hashcount=0, newskip;
+  facetT *newfacet, *neighbor;
+  coordT maxdupdist= 0.0, maxdist2;
+  int dim= qh->hull_dim, hashsize, neighbor_i, neighbor_n;
+  setT *neighbors;
+#ifndef qh_NOtrace
+  int facet_i, facet_n, numunused= 0;
+  facetT *facet;
+#endif
+
+  trace1((qh, qh->ferr, 1019, "qh_matchnewfacets: match neighbors for new facets.\n"));
+  FORALLnew_facets {
+    numnew++;
+    {  /* inline qh_setzero(qh, newfacet->neighbors, 1, qh->hull_dim); */
+      neighbors= newfacet->neighbors;
+      neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
+      memset((char *)SETelemaddr_(neighbors, 1, void), 0, (size_t)(dim * SETelemsize));
+    }
+  }
+
+  qh_newhashtable(qh, numnew*(qh->hull_dim-1)); /* twice what is normally needed,
+                                     but every ridge could be DUPLICATEridge */
+  hashsize= qh_setsize(qh, qh->hash_table);
+  FORALLnew_facets {
+    if (!newfacet->simplicial) {
+      qh_fprintf(qh, qh->ferr, 6377, "qhull internal error (qh_matchnewfacets): expecting simplicial facets on qh.newfacet_list f%d for qh_matchneighbors, qh_matchneighbor, and qh_matchdupridge.  Got non-simplicial f%d\n",
+        qh->newfacet_list->id, newfacet->id);
+      qh_errexit2(qh, qh_ERRqhull, newfacet, qh->newfacet_list);
+    }
+    for (newskip=1; newskiphull_dim; newskip++) /* furthest/horizon already matched */
+      /* hashsize>0 because hull_dim>1 and numnew>0 */
+      qh_matchneighbor(qh, newfacet, newskip, hashsize, &hashcount);
+#if 0   /* use the following to trap hashcount errors */
+    {
+      int count= 0, k;
+      facetT *facet, *neighbor;
+
+      count= 0;
+      FORALLfacet_(qh->newfacet_list) {  /* newfacet already in use */
+        for (k=1; k < qh->hull_dim; k++) {
+          neighbor= SETelemt_(facet->neighbors, k, facetT);
+          if (!neighbor || neighbor == qh_DUPLICATEridge)
+            count++;
+        }
+        if (facet == newfacet)
+          break;
+      }
+      if (count != hashcount) {
+        qh_fprintf(qh, qh->ferr, 6266, "qhull error (qh_matchnewfacets): after adding facet %d, hashcount %d != count %d\n",
+                 newfacet->id, hashcount, count);
+        qh_errexit(qh, qh_ERRdebug, newfacet, NULL);
+      }
+    }
+#endif  /* end of trap code */
+  } /* end FORALLnew_facets */
+  if (hashcount) { /* all neighbors matched, except for qh_DUPLICATEridge neighbors */
+    qh_joggle_restart(qh, "ridge with multiple neighbors");
+    if (hashcount) {
+      FORALLnew_facets {
+        if (newfacet->dupridge) {
+          FOREACHneighbor_i_(qh, newfacet) {
+            if (neighbor == qh_DUPLICATEridge) {
+              maxdist2= qh_matchdupridge(qh, newfacet, neighbor_i, hashsize, &hashcount);
+              maximize_(maxdupdist, maxdist2);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (hashcount) {
+    qh_fprintf(qh, qh->ferr, 6108, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
+        hashcount);
+    qh_printhashtable(qh, qh->ferr);
+    qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+#ifndef qh_NOtrace
+  if (qh->IStracing >= 3) {
+    FOREACHfacet_i_(qh, qh->hash_table) {
+      if (!facet)
+        numunused++;
+    }
+    qh_fprintf(qh, qh->ferr, 3063, "qh_matchnewfacets: maxdupdist %2.2g, new facets %d, unused hash entries %d, hashsize %d\n",
+             maxdupdist, numnew, numunused, qh_setsize(qh, qh->hash_table));
+  }
+#endif /* !qh_NOtrace */
+  qh_setfree(qh, &qh->hash_table);
+  if (qh->PREmerge || qh->MERGEexact) {
+    if (qh->IStracing >= 4)
+      qh_printfacetlist(qh, qh->newfacet_list, NULL, qh_ALL);
+  }
+  return maxdupdist;
+} /* matchnewfacets */
+
+
+/*---------------------------------
+
+  qh_matchvertices(qh, firstindex, verticesA, skipA, verticesB, skipB, same )
+    tests whether vertices match with a single skip
+    starts match at firstindex since all new facets have a common vertex
+
+  returns:
+    true if matched vertices
+    skip index for skipB
+    sets same iff vertices have the same orientation
+
+  notes:
+    called by qh_matchneighbor and qh_matchdupridge
+    assumes skipA is in A and both sets are the same size
+
+  design:
+    set up pointers
+    scan both sets checking for a match
+    test orientation
+*/
+boolT qh_matchvertices(qhT *qh, int firstindex, setT *verticesA, int skipA,
+       setT *verticesB, int *skipB, boolT *same) {
+  vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
+
+  elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
+  elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
+  skipAp= SETelemaddr_(verticesA, skipA, vertexT);
+  do if (elemAp != skipAp) {
+    while (*elemAp != *elemBp++) {
+      if (skipBp)
+        return False;
+      skipBp= elemBp;  /* one extra like FOREACH */
+    }
+  }while (*(++elemAp));
+  if (!skipBp)
+    skipBp= ++elemBp;
+  *skipB= SETindex_(verticesB, skipB); /* i.e., skipBp - verticesB
+                                       verticesA and verticesB are the same size, otherwise trace4 may segfault */
+  *same= !((skipA & 0x1) ^ (*skipB & 0x1)); /* result is 0 or 1 */
+  trace4((qh, qh->ferr, 4054, "qh_matchvertices: matched by skip %d(v%d) and skip %d(v%d) same? %d\n",
+          skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
+  return(True);
+} /* matchvertices */
+
+/*---------------------------------
+
+  qh_newfacet(qh)
+    return a new facet
+
+  returns:
+    all fields initialized or cleared   (NULL)
+    preallocates neighbors set
+*/
+facetT *qh_newfacet(qhT *qh) {
+  facetT *facet;
+  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
+
+  qh_memalloc_(qh, (int)sizeof(facetT), freelistp, facet, facetT);
+  memset((char *)facet, (size_t)0, sizeof(facetT));
+  if (qh->facet_id == qh->tracefacet_id)
+    qh->tracefacet= facet;
+  facet->id= qh->facet_id++;
+  facet->neighbors= qh_setnew(qh, qh->hull_dim);
+#if !qh_COMPUTEfurthest
+  facet->furthestdist= 0.0;
+#endif
+#if qh_MAXoutside
+  if (qh->FORCEoutput && qh->APPROXhull)
+    facet->maxoutside= qh->MINoutside;
+  else
+    facet->maxoutside= qh->DISTround; /* same value as test for QH7082 */
+#endif
+  facet->simplicial= True;
+  facet->good= True;
+  facet->newfacet= True;
+  trace4((qh, qh->ferr, 4055, "qh_newfacet: created facet f%d\n", facet->id));
+  return(facet);
+} /* newfacet */
+
+
+/*---------------------------------
+
+  qh_newridge()
+    return a new ridge
+  notes:
+    caller sets qh.traceridge
+*/
+ridgeT *qh_newridge(qhT *qh) {
+  ridgeT *ridge;
+  void **freelistp;   /* used if !qh_NOmem by qh_memalloc_() */
+
+  qh_memalloc_(qh, (int)sizeof(ridgeT), freelistp, ridge, ridgeT);
+  memset((char *)ridge, (size_t)0, sizeof(ridgeT));
+  zinc_(Ztotridges);
+  if (qh->ridge_id == UINT_MAX) {
+    qh_fprintf(qh, qh->ferr, 7074, "qhull warning: more than 2^32 ridges.  Qhull results are OK.  Since the ridge ID wraps around to 0, two ridges may have the same identifier.\n");
+  }
+  ridge->id= qh->ridge_id++;
+  trace4((qh, qh->ferr, 4056, "qh_newridge: created ridge r%d\n", ridge->id));
+  return(ridge);
+} /* newridge */
+
+
+/*---------------------------------
+
+  qh_pointid(qh, point )
+    return id for a point,
+    returns qh_IDnone(-3) if null, qh_IDinterior(-2) if interior, or qh_IDunknown(-1) if not known
+
+  alternative code if point is in qh.first_point...
+    unsigned long id;
+    id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
+
+  notes:
+    Valid points are non-negative
+    WARN64 -- id truncated to 32-bits, at most 2G points
+    NOerrors returned (QhullPoint::id)
+    if point not in point array
+      the code does a comparison of unrelated pointers.
+*/
+int qh_pointid(qhT *qh, pointT *point) {
+  ptr_intT offset, id;
+
+  if (!point || !qh)
+    return qh_IDnone;
+  else if (point == qh->interior_point)
+    return qh_IDinterior;
+  else if (point >= qh->first_point
+  && point < qh->first_point + qh->num_points * qh->hull_dim) {
+    offset= (ptr_intT)(point - qh->first_point);
+    id= offset / qh->hull_dim;
+  }else if ((id= qh_setindex(qh->other_points, point)) != -1)
+    id += qh->num_points;
+  else
+    return qh_IDunknown;
+  return (int)id;
+} /* pointid */
+
+/*---------------------------------
+
+  qh_removefacet(qh, facet )
+    unlinks facet from qh.facet_list,
+
+  returns:
+    updates qh.facet_list .newfacet_list .facet_next visible_list
+    decrements qh.num_facets
+
+  see:
+    qh_appendfacet
+*/
+void qh_removefacet(qhT *qh, facetT *facet) {
+  facetT *next= facet->next, *previous= facet->previous; /* next is always defined */
+
+  if (facet == qh->newfacet_list)
+    qh->newfacet_list= next;
+  if (facet == qh->facet_next)
+    qh->facet_next= next;
+  if (facet == qh->visible_list)
+    qh->visible_list= next;
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st facet in qh->facet_list */
+    qh->facet_list= next;
+    qh->facet_list->previous= NULL;
+  }
+  qh->num_facets--;
+  trace4((qh, qh->ferr, 4057, "qh_removefacet: removed f%d from facet_list, newfacet_list, and visible_list\n", facet->id));
+} /* removefacet */
+
+
+/*---------------------------------
+
+  qh_removevertex(qh, vertex )
+    unlinks vertex from qh.vertex_list,
+
+  returns:
+    updates qh.vertex_list .newvertex_list
+    decrements qh.num_vertices
+*/
+void qh_removevertex(qhT *qh, vertexT *vertex) {
+  vertexT *next= vertex->next, *previous= vertex->previous; /* next is always defined */
+
+  trace4((qh, qh->ferr, 4058, "qh_removevertex: remove v%d from qh.vertex_list\n", vertex->id));
+  if (vertex == qh->newvertex_list)
+    qh->newvertex_list= next;
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st vertex in qh->vertex_list */
+    qh->vertex_list= next;
+    qh->vertex_list->previous= NULL;
+  }
+  qh->num_vertices--;
+} /* removevertex */
+
+
+/*---------------------------------
+
+  qh_update_vertexneighbors(qh )
+    update vertex neighbors and delete interior vertices
+
+  returns:
+    if qh.VERTEXneighbors, 
+      if qh.newvertex_list,
+         removes visible neighbors from vertex neighbors
+      if qh.newfacet_list
+         adds new facets to vertex neighbors
+      if qh.visible_list
+         interior vertices added to qh.del_vertices for later partitioning as coplanar points
+    if not qh.VERTEXneighbors (not merging)
+      interior vertices of visible facets added to qh.del_vertices for later partitioning as coplanar points
+  
+  notes
+    [jan'19] split off qh_update_vertexneighbors_cone.  Optimize the remaining cases in a future release
+    called by qh_triangulate_facet after triangulating a non-simplicial facet, followed by reset_lists
+    called by qh_triangulate after triangulating null and mirror facets
+    called by qh_all_vertexmerges after calling qh_merge_pinchedvertices
+
+  design:
+    if qh.VERTEXneighbors
+      for each vertex on newvertex_list (i.e., new vertices and vertices of new facets)
+        delete visible facets from vertex neighbors
+      for each new facet on newfacet_list
+        for each vertex of facet
+          append facet to vertex neighbors
+      for each visible facet on qh.visible_list
+        for each vertex of facet
+          if the vertex is not on a new facet and not itself deleted
+            if the vertex has a not-visible neighbor (due to merging)
+               remove the visible facet from the vertex's neighbors
+            otherwise
+               add the vertex to qh.del_vertices for later deletion
+
+    if not qh.VERTEXneighbors (not merging)
+      for each vertex of a visible facet
+        if the vertex is not on a new facet and not itself deleted
+           add the vertex to qh.del_vertices for later deletion
+*/
+void qh_update_vertexneighbors(qhT *qh /* qh.newvertex_list, newfacet_list, visible_list */) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
+  vertexT *vertex, **vertexp;
+  int neighborcount= 0;
+
+  if (qh->VERTEXneighbors) {
+    trace3((qh, qh->ferr, 3013, "qh_update_vertexneighbors: update v.neighbors for qh.newvertex_list (v%d) and qh.newfacet_list (f%d)\n",
+         getid_(qh->newvertex_list), getid_(qh->newfacet_list)));
+    FORALLvertex_(qh->newvertex_list) {
+      neighborcount= 0;
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visible) {
+          neighborcount++;
+          SETref_(neighbor)= NULL;
+        }
+      }
+      if (neighborcount) {
+        trace4((qh, qh->ferr, 4046, "qh_update_vertexneighbors: delete %d of %d vertex neighbors for v%d.  Removes to-be-deleted, visible facets\n",
+          neighborcount, qh_setsize(qh, vertex->neighbors), vertex->id));
+        qh_setcompact(qh, vertex->neighbors);
+      }
+    }
+    FORALLnew_facets {
+      if (qh->first_newfacet && newfacet->id >= qh->first_newfacet) {
+        FOREACHvertex_(newfacet->vertices)
+          qh_setappend(qh, &vertex->neighbors, newfacet);
+      }else {  /* called after qh_merge_pinchedvertices.  In 7-D, many more neighbors than new facets.  qh_setin is expensive */
+        FOREACHvertex_(newfacet->vertices)
+          qh_setunique(qh, &vertex->neighbors, newfacet); 
+      }
+    }
+    trace3((qh, qh->ferr, 3058, "qh_update_vertexneighbors: delete interior vertices for qh.visible_list (f%d)\n",
+        getid_(qh->visible_list)));
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newfacet && !vertex->deleted) {
+          FOREACHneighbor_(vertex) { /* this can happen under merging */
+            if (!neighbor->visible)
+              break;
+          }
+          if (neighbor)
+            qh_setdel(vertex->neighbors, visible);
+          else {
+            vertex->deleted= True;
+            qh_setappend(qh, &qh->del_vertices, vertex);
+            trace2((qh, qh->ferr, 2041, "qh_update_vertexneighbors: delete interior vertex p%d(v%d) of visible f%d\n",
+                  qh_pointid(qh, vertex->point), vertex->id, visible->id));
+          }
+        }
+      }
+    }
+  }else {  /* !VERTEXneighbors */
+    trace3((qh, qh->ferr, 3058, "qh_update_vertexneighbors: delete old vertices for qh.visible_list (f%d)\n",
+      getid_(qh->visible_list)));
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newfacet && !vertex->deleted) {
+          vertex->deleted= True;
+          qh_setappend(qh, &qh->del_vertices, vertex);
+          trace2((qh, qh->ferr, 2042, "qh_update_vertexneighbors: will delete interior vertex p%d(v%d) of visible f%d\n",
+                  qh_pointid(qh, vertex->point), vertex->id, visible->id));
+        }
+      }
+    }
+  }
+} /* update_vertexneighbors */
+
+/*---------------------------------
+
+  qh_update_vertexneighbors_cone(qh )
+    update vertex neighbors for a cone of new facets and delete interior vertices
+
+  returns:
+    if qh.VERTEXneighbors, 
+      if qh.newvertex_list,
+         removes visible neighbors from vertex neighbors
+      if qh.newfacet_list
+         adds new facets to vertex neighbors
+      if qh.visible_list
+         interior vertices added to qh.del_vertices for later partitioning as coplanar points
+    if not qh.VERTEXneighbors (not merging)
+      interior vertices of visible facets added to qh.del_vertices for later partitioning as coplanar points
+  
+  notes
+    called by qh_addpoint after create cone and before premerge
+
+  design:
+    if qh.VERTEXneighbors
+      for each vertex on newvertex_list (i.e., new vertices and vertices of new facets)
+        delete visible facets from vertex neighbors
+      for each new facet on newfacet_list
+        for each vertex of facet
+          append facet to vertex neighbors
+      for each visible facet on qh.visible_list
+        for each vertex of facet
+          if the vertex is not on a new facet and not itself deleted
+            if the vertex has a not-visible neighbor (due to merging)
+               remove the visible facet from the vertex's neighbors
+            otherwise
+               add the vertex to qh.del_vertices for later deletion
+
+    if not qh.VERTEXneighbors (not merging)
+      for each vertex of a visible facet
+        if the vertex is not on a new facet and not itself deleted
+           add the vertex to qh.del_vertices for later deletion
+
+*/
+void qh_update_vertexneighbors_cone(qhT *qh /* qh.newvertex_list, newfacet_list, visible_list */) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
+  vertexT *vertex, **vertexp;
+  int delcount= 0;
+
+  if (qh->VERTEXneighbors) {
+    trace3((qh, qh->ferr, 3059, "qh_update_vertexneighbors_cone: update v.neighbors for qh.newvertex_list (v%d) and qh.newfacet_list (f%d)\n",
+         getid_(qh->newvertex_list), getid_(qh->newfacet_list)));
+    FORALLvertex_(qh->newvertex_list) {
+      delcount= 0;
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visible) { /* alternative design is a loop over visible facets, but needs qh_setdel() */
+          delcount++;
+          qh_setdelnth(qh, vertex->neighbors, SETindex_(vertex->neighbors, neighbor));
+          neighborp--; /* repeat */
+        }
+      }
+      if (delcount) {
+        trace4((qh, qh->ferr, 4021, "qh_update_vertexneighbors_cone: deleted %d visible vertexneighbors of v%d\n",
+          delcount, vertex->id));
+      }
+    }
+    FORALLnew_facets {
+      FOREACHvertex_(newfacet->vertices)
+        qh_setappend(qh, &vertex->neighbors, newfacet);
+    }
+    trace3((qh, qh->ferr, 3065, "qh_update_vertexneighbors_cone: delete interior vertices, if any, for qh.visible_list (f%d)\n",
+        getid_(qh->visible_list)));
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newfacet && !vertex->deleted) {
+          FOREACHneighbor_(vertex) { /* this can happen under merging, qh_checkfacet QH4025 */
+            if (!neighbor->visible)
+              break;
+          }
+          if (neighbor)
+            qh_setdel(vertex->neighbors, visible);
+          else {
+            vertex->deleted= True;
+            qh_setappend(qh, &qh->del_vertices, vertex);
+            trace2((qh, qh->ferr, 2102, "qh_update_vertexneighbors_cone: will delete interior vertex p%d(v%d) of visible f%d\n",
+              qh_pointid(qh, vertex->point), vertex->id, visible->id));
+          }
+        }
+      }
+    }
+  }else {  /* !VERTEXneighbors */
+    trace3((qh, qh->ferr, 3066, "qh_update_vertexneighbors_cone: delete interior vertices for qh.visible_list (f%d)\n",
+      getid_(qh->visible_list)));
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newfacet && !vertex->deleted) {
+          vertex->deleted= True;
+          qh_setappend(qh, &qh->del_vertices, vertex);
+          trace2((qh, qh->ferr, 2059, "qh_update_vertexneighbors_cone: will delete interior vertex p%d(v%d) of visible f%d\n",
+                  qh_pointid(qh, vertex->point), vertex->id, visible->id));
+        }
+      }
+    }
+  }
+} /* update_vertexneighbors_cone */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.h
new file mode 100644
index 00000000000..83c59140de7
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/poly_r.h
@@ -0,0 +1,310 @@
+/*
  ---------------------------------
+
+   poly_r.h
+   header file for poly_r.c and poly2_r.c
+
+   see qh-poly_r.htm, libqhull_r.h and poly_r.c
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/poly_r.h#5 $$Change: 2963 $
+   $DateTime: 2020/06/03 19:31:01 $$Author: bbarber $
+*/
+
+#ifndef qhDEFpoly
+#define qhDEFpoly 1
+
+#include "libqhull_r.h"
+
+/*===============   constants ========================== */
+
+/*----------------------------------
+
+  qh_ALGORITHMfault
+    use as argument to checkconvex() to report errors during buildhull
+*/
+#define qh_ALGORITHMfault 0
+
+/*----------------------------------
+
+  qh_DATAfault
+    use as argument to checkconvex() to report errors during initialhull
+*/
+#define qh_DATAfault 1
+
+/*----------------------------------
+
+  qh_DUPLICATEridge
+    special value for facet->neighbor to indicate a duplicate ridge
+
+  notes:
+    set by qh_matchneighbor for qh_matchdupridge
+*/
+#define qh_DUPLICATEridge (facetT *)1L
+
+/*----------------------------------
+
+  qh_MERGEridge       flag in facet
+    special value for facet->neighbor to indicate a duplicate ridge that needs merging
+
+  notes:
+    set by qh_matchnewfacets..qh_matchdupridge from qh_DUPLICATEridge
+    used by qh_mark_dupridges to set facet->mergeridge, facet->mergeridge2 from facet->dupridge
+*/
+#define qh_MERGEridge (facetT *)2L
+
+
+/*============ -structures- ====================*/
+
+/*=========== -macros- =========================*/
+
+/*----------------------------------
+
+  FORALLfacet_( facetlist ) { ... }
+    assign 'facet' to each facet in facetlist
+
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+
+  see:
+    FORALLfacets
+*/
+#define FORALLfacet_( facetlist ) if (facetlist) for ( facet=(facetlist); facet && facet->next; facet= facet->next )
+
+/*----------------------------------
+
+  FORALLnew_facets { ... }
+    assign 'newfacet' to each facet in qh.newfacet_list
+
+  notes:
+    uses 'facetT *newfacet;'
+    at exit, newfacet==NULL
+*/
+#define FORALLnew_facets for ( newfacet=qh->newfacet_list; newfacet && newfacet->next; newfacet=newfacet->next )
+
+/*----------------------------------
+
+  FORALLvertex_( vertexlist ) { ... }
+    assign 'vertex' to each vertex in vertexlist
+
+  notes:
+    uses 'vertexT *vertex;'
+    at exit, vertex==NULL
+*/
+#define FORALLvertex_( vertexlist ) for (vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
+
+/*----------------------------------
+
+  FORALLvisible_facets { ... }
+    assign 'visible' to each visible facet in qh.visible_list
+
+  notes:
+    uses 'vacetT *visible;'
+    at exit, visible==NULL
+*/
+#define FORALLvisible_facets for (visible=qh->visible_list; visible && visible->visible; visible= visible->next)
+
+/*----------------------------------
+
+  FORALLsame_( newfacet ) { ... }
+    assign 'same' to each facet in newfacet->f.samecycle
+
+  notes:
+    uses 'facetT *same;'
+    stops when it returns to newfacet
+*/
+#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
+
+/*----------------------------------
+
+  FORALLsame_cycle_( newfacet ) { ... }
+    assign 'same' to each facet in newfacet->f.samecycle
+
+  notes:
+    uses 'facetT *same;'
+    at exit, same == NULL
+*/
+#define FORALLsame_cycle_(newfacet) \
+     for (same= newfacet->f.samecycle; \
+         same; same= (same == newfacet ?  NULL : same->f.samecycle))
+
+/*----------------------------------
+
+  FOREACHneighborA_( facet ) { ... }
+    assign 'neighborA' to each neighbor in facet->neighbors
+
+  FOREACHneighborA_( vertex ) { ... }
+    assign 'neighborA' to each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighborA, **neighborAp;
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)
+
+/*----------------------------------
+
+  FOREACHvisible_( facets ) { ... }
+    assign 'visible' to each facet in facets
+
+  notes:
+    uses 'facetT *facet, *facetp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
+
+/*----------------------------------
+
+  FOREACHnewfacet_( facets ) { ... }
+    assign 'newfacet' to each facet in facets
+
+  notes:
+    uses 'facetT *newfacet, *newfacetp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
+
+/*----------------------------------
+
+  FOREACHvertexA_( vertices ) { ... }
+    assign 'vertexA' to each vertex in vertices
+
+  notes:
+    uses 'vertexT *vertexA, *vertexAp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
+
+/*----------------------------------
+
+  FOREACHvertexreverse12_( vertices ) { ... }
+    assign 'vertex' to each vertex in vertices
+    reverse order of first two vertices
+
+  notes:
+    uses 'vertexT *vertex, *vertexp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
+
+
+/*=============== prototypes poly_r.c in alphabetical order ================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    qh_appendfacet(qhT *qh, facetT *facet);
+void    qh_appendvertex(qhT *qh, vertexT *vertex);
+void    qh_attachnewfacets(qhT *qh /* qh.visible_list, qh.newfacet_list */);
+boolT   qh_checkflipped(qhT *qh, facetT *facet, realT *dist, boolT allerror);
+void    qh_delfacet(qhT *qh, facetT *facet);
+void    qh_deletevisible(qhT *qh /* qh.visible_list, qh.horizon_list */);
+setT   *qh_facetintersect(qhT *qh, facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
+int     qh_gethash(qhT *qh, int hashsize, setT *set, int size, int firstindex, void *skipelem);
+facetT *qh_getreplacement(qhT *qh, facetT *visible);
+facetT *qh_makenewfacet(qhT *qh, setT *vertices, boolT toporient, facetT *facet);
+void    qh_makenewplanes(qhT *qh /* qh.newfacet_list */);
+facetT *qh_makenew_nonsimplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew);
+facetT *qh_makenew_simplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew);
+void    qh_matchneighbor(qhT *qh, facetT *newfacet, int newskip, int hashsize,
+                          int *hashcount);
+coordT  qh_matchnewfacets(qhT *qh);
+boolT   qh_matchvertices(qhT *qh, int firstindex, setT *verticesA, int skipA,
+                          setT *verticesB, int *skipB, boolT *same);
+facetT *qh_newfacet(qhT *qh);
+ridgeT *qh_newridge(qhT *qh);
+int     qh_pointid(qhT *qh, pointT *point);
+void    qh_removefacet(qhT *qh, facetT *facet);
+void    qh_removevertex(qhT *qh, vertexT *vertex);
+void    qh_update_vertexneighbors(qhT *qh);
+void    qh_update_vertexneighbors_cone(qhT *qh);
+
+
+/*========== -prototypes poly2_r.c in alphabetical order ===========*/
+
+boolT   qh_addfacetvertex(qhT *qh, facetT *facet, vertexT *newvertex);
+void    qh_addhash(void *newelem, setT *hashtable, int hashsize, int hash);
+void    qh_check_bestdist(qhT *qh);
+void    qh_check_maxout(qhT *qh);
+void    qh_check_output(qhT *qh);
+void    qh_check_point(qhT *qh, pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2, int *errcount);
+void    qh_check_points(qhT *qh);
+void    qh_checkconvex(qhT *qh, facetT *facetlist, int fault);
+void    qh_checkfacet(qhT *qh, facetT *facet, boolT newmerge, boolT *waserrorp);
+void    qh_checkflipped_all(qhT *qh, facetT *facetlist);
+boolT   qh_checklists(qhT *qh, facetT *facetlist);
+void    qh_checkpolygon(qhT *qh, facetT *facetlist);
+void    qh_checkvertex(qhT *qh, vertexT *vertex, boolT allchecks, boolT *waserrorp);
+void    qh_clearcenters(qhT *qh, qh_CENTER type);
+void    qh_createsimplex(qhT *qh, setT *vertices);
+void    qh_delridge(qhT *qh, ridgeT *ridge);
+void    qh_delvertex(qhT *qh, vertexT *vertex);
+setT   *qh_facet3vertex(qhT *qh, facetT *facet);
+facetT *qh_findbestfacet(qhT *qh, pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+facetT *qh_findbestlower(qhT *qh, facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart);
+facetT *qh_findfacet_all(qhT *qh, pointT *point, boolT noupper, realT *bestdist, boolT *isoutside,
+                          int *numpart);
+int     qh_findgood(qhT *qh, facetT *facetlist, int goodhorizon);
+void    qh_findgood_all(qhT *qh, facetT *facetlist);
+void    qh_furthestnext(qhT *qh /* qh.facet_list */);
+void    qh_furthestout(qhT *qh, facetT *facet);
+void    qh_infiniteloop(qhT *qh, facetT *facet);
+void    qh_initbuild(qhT *qh);
+void    qh_initialhull(qhT *qh, setT *vertices);
+setT   *qh_initialvertices(qhT *qh, int dim, setT *maxpoints, pointT *points, int numpoints);
+vertexT *qh_isvertex(pointT *point, setT *vertices);
+vertexT *qh_makenewfacets(qhT *qh, pointT *point /* qh.horizon_list, visible_list */);
+coordT  qh_matchdupridge(qhT *qh, facetT *atfacet, int atskip, int hashsize, int *hashcount);
+void    qh_nearcoplanar(qhT *qh /* qh.facet_list */);
+vertexT *qh_nearvertex(qhT *qh, facetT *facet, pointT *point, realT *bestdistp);
+int     qh_newhashtable(qhT *qh, int newsize);
+vertexT *qh_newvertex(qhT *qh, pointT *point);
+facetT *qh_nextfacet2d(facetT *facet, vertexT **nextvertexp);
+ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp);
+vertexT *qh_opposite_vertex(qhT *qh, facetT *facetA,  facetT *neighbor);
+void    qh_outcoplanar(qhT *qh /* qh.facet_list */);
+pointT *qh_point(qhT *qh, int id);
+void    qh_point_add(qhT *qh, setT *set, pointT *point, void *elem);
+setT   *qh_pointfacet(qhT *qh /* qh.facet_list */);
+setT   *qh_pointvertex(qhT *qh /* qh.facet_list */);
+void    qh_prependfacet(qhT *qh, facetT *facet, facetT **facetlist);
+void    qh_printhashtable(qhT *qh, FILE *fp);
+void    qh_printlists(qhT *qh);
+void    qh_replacefacetvertex(qhT *qh, facetT *facet, vertexT *oldvertex, vertexT *newvertex);
+void    qh_resetlists(qhT *qh, boolT stats, boolT resetVisible /* qh.newvertex_list qh.newfacet_list qh.visible_list */);
+void    qh_setvoronoi_all(qhT *qh);
+void    qh_triangulate(qhT *qh /* qh.facet_list */);
+void    qh_triangulate_facet(qhT *qh, facetT *facetA, vertexT **first_vertex);
+void    qh_triangulate_link(qhT *qh, facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
+void    qh_triangulate_mirror(qhT *qh, facetT *facetA, facetT *facetB);
+void    qh_triangulate_null(qhT *qh, facetT *facetA);
+void    qh_vertexintersect(qhT *qh, setT **vertexsetA,setT *vertexsetB);
+setT   *qh_vertexintersect_new(qhT *qh, setT *vertexsetA,setT *vertexsetB);
+void    qh_vertexneighbors(qhT *qh /* qh.facet_list */);
+boolT   qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFpoly */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/qhull_ra.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/qhull_ra.h
new file mode 100644
index 00000000000..52ccd85a02a
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/qhull_ra.h
@@ -0,0 +1,161 @@
+/*
  ---------------------------------
+
+   qhull_ra.h
+   all header files for compiling qhull with reentrant code
+   included before C++ headers for user_r.h:QHULL_CRTDBG
+
+   see qh-qhull.htm
+
+   see libqhull_r.h for user-level definitions
+
+   see user_r.h for user-definable constants
+
+   defines internal functions for libqhull_r.c global_r.c
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/qhull_ra.h#2 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+
+   Notes:  grep for ((" and (" to catch fprintf("lkasdjf");
+           full parens around (x?y:z)
+           use '#include "libqhull_r/qhull_ra.h"' to avoid name clashes
+*/
+
+#ifndef qhDEFqhulla
+#define qhDEFqhulla 1
+
+#include "libqhull_r.h"  /* Includes user_r.h and data types */
+
+#include "stat_r.h"
+#include "random_r.h"
+#include "mem_r.h"
+#include "qset_r.h"
+#include "geom_r.h"
+#include "merge_r.h"
+#include "poly_r.h"
+#include "io_r.h"
+
+#include 
+#include 
+#include 
+#include     /* some compilers will not need float.h */
+#include 
+#include 
+#include 
+#include 
+#include 
+/*** uncomment here and qset_r.c
+     if string.h does not define memcpy()
+#include 
+*/
+
+#if qh_CLOCKtype == 2  /* defined in user_r.h from libqhull_r.h */
+#include 
+#include 
+#include 
+#endif
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
+#pragma warning( disable : 4100)  /* unreferenced formal parameter */
+#pragma warning( disable : 4127)  /* conditional expression is constant */
+#pragma warning( disable : 4706)  /* assignment within conditional function */
+#pragma warning( disable : 4996)  /* function was declared deprecated(strcpy, localtime, etc.) */
+#endif
+
+/* ======= -macros- =========== */
+
+/*----------------------------------
+
+  traceN((qh, qh->ferr, 0Nnnn, "format\n", vars));
+    calls qh_fprintf if qh.IStracing >= N
+
+    Add debugging traps to the end of qh_fprintf
+
+  notes:
+    removing tracing reduces code size but doesn't change execution speed
+*/
+#ifndef qh_NOtrace
+#define trace0(args) {if (qh->IStracing) qh_fprintf args;}
+#define trace1(args) {if (qh->IStracing >= 1) qh_fprintf args;}
+#define trace2(args) {if (qh->IStracing >= 2) qh_fprintf args;}
+#define trace3(args) {if (qh->IStracing >= 3) qh_fprintf args;}
+#define trace4(args) {if (qh->IStracing >= 4) qh_fprintf args;}
+#define trace5(args) {if (qh->IStracing >= 5) qh_fprintf args;}
+#else /* qh_NOtrace */
+#define trace0(args) {}
+#define trace1(args) {}
+#define trace2(args) {}
+#define trace3(args) {}
+#define trace4(args) {}
+#define trace5(args) {}
+#endif /* qh_NOtrace */
+
+/*----------------------------------
+
+  Define an unused variable to avoid compiler warnings
+
+  Derived from Qt's corelib/global/qglobal.h
+
+*/
+
+#if defined(__cplusplus) && defined(__INTEL_COMPILER) && !defined(QHULL_OS_WIN)
+template 
+inline void qhullUnused(T &x) { (void)x; }
+#  define QHULL_UNUSED(x) qhullUnused(x);
+#else
+#  define QHULL_UNUSED(x) (void)x;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***** -libqhull_r.c prototypes (alphabetical after qhull) ********************/
+
+void    qh_qhull(qhT *qh);
+boolT   qh_addpoint(qhT *qh, pointT *furthest, facetT *facet, boolT checkdist);
+void    qh_build_withrestart(qhT *qh);
+vertexT *qh_buildcone(qhT *qh, pointT *furthest, facetT *facet, int goodhorizon, facetT **retryfacet);
+boolT   qh_buildcone_mergepinched(qhT *qh, vertexT *apex, facetT *facet, facetT **retryfacet);
+boolT   qh_buildcone_onlygood(qhT *qh, vertexT *apex, int goodhorizon);
+void    qh_buildhull(qhT *qh);
+void    qh_buildtracing(qhT *qh, pointT *furthest, facetT *facet);
+void    qh_errexit2(qhT *qh, int exitcode, facetT *facet, facetT *otherfacet);
+void    qh_findhorizon(qhT *qh, pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
+pointT *qh_nextfurthest(qhT *qh, facetT **visible);
+void    qh_partitionall(qhT *qh, setT *vertices, pointT *points,int npoints);
+void    qh_partitioncoplanar(qhT *qh, pointT *point, facetT *facet, realT *dist, boolT allnew);
+void    qh_partitionpoint(qhT *qh, pointT *point, facetT *facet);
+void    qh_partitionvisible(qhT *qh, boolT allpoints, int *numpoints);
+void    qh_joggle_restart(qhT *qh, const char *reason);
+void    qh_printsummary(qhT *qh, FILE *fp);
+
+/***** -global_r.c internal prototypes (alphabetical) ***********************/
+
+void    qh_appendprint(qhT *qh, qh_PRINT format);
+void    qh_freebuild(qhT *qh, boolT allmem);
+void    qh_freebuffers(qhT *qh);
+void    qh_initbuffers(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc);
+
+/***** -stat_r.c internal prototypes (alphabetical) ***********************/
+
+void    qh_allstatA(qhT *qh);
+void    qh_allstatB(qhT *qh);
+void    qh_allstatC(qhT *qh);
+void    qh_allstatD(qhT *qh);
+void    qh_allstatE(qhT *qh);
+void    qh_allstatE2(qhT *qh);
+void    qh_allstatF(qhT *qh);
+void    qh_allstatG(qhT *qh);
+void    qh_allstatH(qhT *qh);
+void    qh_freebuffers(qhT *qh);
+void    qh_initbuffers(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFqhulla */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.c
new file mode 100644
index 00000000000..50cdb215c09
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.c
@@ -0,0 +1,1383 @@
+/*
  ---------------------------------
+
+   qset_r.c
+   implements set manipulations needed for quickhull
+
+   see qh-set_r.htm and qset_r.h
+
+   Be careful of strict aliasing (two pointers of different types
+   that reference the same location).  The last slot of a set is
+   either the actual size of the set plus 1, or the NULL terminator
+   of the set (i.e., setelemT).
+
+   Only reference qh for qhmem or qhstat.  Otherwise the matching code in qset.c will bring in qhT
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/qset_r.c#8 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#include "libqhull_r.h" /* for qhT and QHULL_CRTDBG */
+#include "qset_r.h"
+#include "mem_r.h"
+#include 
+#include 
+/*** uncomment here and qhull_ra.h
+     if string.h does not define memcpy()
+#include 
+*/
+
+#ifndef qhDEFlibqhull
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+void    qh_errexit(qhT *qh, int exitcode, facetT *, ridgeT *);
+void    qh_fprintf(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... );
+#  ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
+#  pragma warning( disable : 4127)  /* conditional expression is constant */
+#  pragma warning( disable : 4706)  /* assignment within conditional function */
+#  endif
+#endif
+
+/*=============== internal macros ===========================*/
+
+/*============ functions in alphabetical order ===================*/
+
+/*----------------------------------
+
+  qh_setaddnth(qh, setp, nth, newelem )
+    adds newelem as n'th element of sorted or unsorted *setp
+
+  notes:
+    *setp and newelem must be defined
+    *setp may be a temp set
+    nth=0 is first element
+    errors if nth is out of bounds
+
+  design:
+    expand *setp if empty or full
+    move tail of *setp up one
+    insert newelem
+*/
+void qh_setaddnth(qhT *qh, setT **setp, int nth, void *newelem) {
+  int oldsize, i;
+  setelemT *sizep;          /* avoid strict aliasing */
+  setelemT *oldp, *newp;
+
+  if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
+    qh_setlarger(qh, setp);
+    sizep= SETsizeaddr_(*setp);
+  }
+  oldsize= sizep->i - 1;
+  if (nth < 0 || nth > oldsize) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6171, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qh, qh->qhmem.ferr, "", *setp);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  sizep->i++;
+  oldp= (setelemT *)SETelemaddr_(*setp, oldsize, void);   /* NULL */
+  newp= oldp+1;
+  for (i=oldsize-nth+1; i--; )  /* move at least NULL  */
+    (newp--)->p= (oldp--)->p;       /* may overwrite *sizep */
+  newp->p= newelem;
+} /* setaddnth */
+
+
+/*----------------------------------
+
+  setaddsorted( setp, newelem )
+    adds an newelem into sorted *setp
+
+  notes:
+    *setp and newelem must be defined
+    *setp may be a temp set
+    nop if newelem already in set
+
+  design:
+    find newelem's position in *setp
+    insert newelem
+*/
+void qh_setaddsorted(qhT *qh, setT **setp, void *newelem) {
+  int newindex=0;
+  void *elem, **elemp;
+
+  FOREACHelem_(*setp) {          /* could use binary search instead */
+    if (elem < newelem)
+      newindex++;
+    else if (elem == newelem)
+      return;
+    else
+      break;
+  }
+  qh_setaddnth(qh, setp, newindex, newelem);
+} /* setaddsorted */
+
+
+/*---------------------------------
+
+  qh_setappend(qh, setp, newelem )
+    append newelem to *setp
+
+  notes:
+    *setp may be a temp set
+    *setp and newelem may be NULL
+
+  design:
+    expand *setp if empty or full
+    append newelem to *setp
+
+*/
+void qh_setappend(qhT *qh, setT **setp, void *newelem) {
+  setelemT *sizep;  /* Avoid strict aliasing.  Writing to *endp may overwrite *sizep */
+  setelemT *endp;
+  int count;
+
+  if (!newelem)
+    return;
+  if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
+    qh_setlarger(qh, setp);
+    sizep= SETsizeaddr_(*setp);
+  }
+  count= (sizep->i)++ - 1;
+  endp= (setelemT *)SETelemaddr_(*setp, count, void);
+  (endp++)->p= newelem;
+  endp->p= NULL;
+} /* setappend */
+
+/*---------------------------------
+
+  qh_setappend_set(qh, setp, setA )
+    appends setA to *setp
+
+  notes:
+    *setp can not be a temp set
+    *setp and setA may be NULL
+
+  design:
+    setup for copy
+    expand *setp if it is too small
+    append all elements of setA to *setp
+*/
+void qh_setappend_set(qhT *qh, setT **setp, setT *setA) {
+  int sizeA, size;
+  setT *oldset;
+  setelemT *sizep;
+
+  if (!setA)
+    return;
+  SETreturnsize_(setA, sizeA);
+  if (!*setp)
+    *setp= qh_setnew(qh, sizeA);
+  sizep= SETsizeaddr_(*setp);
+  if (!(size= sizep->i))
+    size= (*setp)->maxsize;
+  else
+    size--;
+  if (size + sizeA > (*setp)->maxsize) {
+    oldset= *setp;
+    *setp= qh_setcopy(qh, oldset, sizeA);
+    qh_setfree(qh, &oldset);
+    sizep= SETsizeaddr_(*setp);
+  }
+  if (sizeA > 0) {
+    sizep->i= size+sizeA+1;   /* memcpy may overwrite */
+    memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), (size_t)(sizeA+1) * SETelemsize);
+  }
+} /* setappend_set */
+
+
+/*---------------------------------
+
+  qh_setappend2ndlast(qh, setp, newelem )
+    makes newelem the next to the last element in *setp
+
+  notes:
+    *setp must have at least one element
+    newelem must be defined
+    *setp may be a temp set
+
+  design:
+    expand *setp if empty or full
+    move last element of *setp up one
+    insert newelem
+*/
+void qh_setappend2ndlast(qhT *qh, setT **setp, void *newelem) {
+    setelemT *sizep;  /* Avoid strict aliasing.  Writing to *endp may overwrite *sizep */
+    setelemT *endp, *lastp;
+    int count;
+
+    if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
+        qh_setlarger(qh, setp);
+        sizep= SETsizeaddr_(*setp);
+    }
+    count= (sizep->i)++ - 1;
+    endp= (setelemT *)SETelemaddr_(*setp, count, void); /* NULL */
+    lastp= endp-1;
+    *(endp++)= *lastp;
+    endp->p= NULL;    /* may overwrite *sizep */
+    lastp->p= newelem;
+} /* setappend2ndlast */
+
+/*---------------------------------
+
+  qh_setcheck(qh, set, typename, id )
+    check set for validity
+    report errors with typename and id
+
+  design:
+    checks that maxsize, actual size, and NULL terminator agree
+*/
+void qh_setcheck(qhT *qh, setT *set, const char *tname, unsigned int id) {
+  int maxsize, size;
+  int waserr= 0;
+
+  if (!set)
+    return;
+  SETreturnsize_(set, size);
+  maxsize= set->maxsize;
+  if (size > maxsize || !maxsize) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6172, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
+             size, tname, id, maxsize);
+    waserr= 1;
+  }else if (set->e[size].p) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6173, "qhull internal error (qh_setcheck): %s%d(size %d max %d) is not null terminated.\n",
+             tname, id, size-1, maxsize);
+    waserr= 1;
+  }
+  if (waserr) {
+    qh_setprint(qh, qh->qhmem.ferr, "ERRONEOUS", set);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+} /* setcheck */
+
+
+/*---------------------------------
+
+  qh_setcompact(qh, set )
+    remove internal NULLs from an unsorted set
+
+  returns:
+    updated set
+
+  notes:
+    set may be NULL
+    it would be faster to swap tail of set into holes, like qh_setdel
+
+  design:
+    setup pointers into set
+    skip NULLs while copying elements to start of set
+    update the actual size
+*/
+void qh_setcompact(qhT *qh, setT *set) {
+  int size;
+  void **destp, **elemp, **endp, **firstp;
+
+  if (!set)
+    return;
+  SETreturnsize_(set, size);
+  destp= elemp= firstp= SETaddr_(set, void);
+  endp= destp + size;
+  while (1) {
+    if (!(*destp++= *elemp++)) {
+      destp--;
+      if (elemp > endp)
+        break;
+    }
+  }
+  qh_settruncate(qh, set, (int)(destp-firstp));   /* WARN64 */
+} /* setcompact */
+
+
+/*---------------------------------
+
+  qh_setcopy(qh, set, extra )
+    make a copy of a sorted or unsorted set with extra slots
+
+  returns:
+    new set
+
+  design:
+    create a newset with extra slots
+    copy the elements to the newset
+
+*/
+setT *qh_setcopy(qhT *qh, setT *set, int extra) {
+  setT *newset;
+  int size;
+
+  if (extra < 0)
+    extra= 0;
+  SETreturnsize_(set, size);
+  newset= qh_setnew(qh, size+extra);
+  SETsizeaddr_(newset)->i= size+1;    /* memcpy may overwrite */
+  memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), (size_t)(size+1) * SETelemsize);
+  return(newset);
+} /* setcopy */
+
+
+/*---------------------------------
+
+  qh_setdel(set, oldelem )
+    delete oldelem from an unsorted set
+
+  returns:
+    returns oldelem if found
+    returns NULL otherwise
+
+  notes:
+    set may be NULL
+    oldelem must not be NULL;
+    only deletes one copy of oldelem in set
+
+  design:
+    locate oldelem
+    update actual size if it was full
+    move the last element to the oldelem's location
+*/
+void *qh_setdel(setT *set, void *oldelem) {
+  setelemT *sizep;
+  setelemT *elemp;
+  setelemT *lastp;
+
+  if (!set)
+    return NULL;
+  elemp= (setelemT *)SETaddr_(set, void);
+  while (elemp->p != oldelem && elemp->p)
+    elemp++;
+  if (elemp->p) {
+    sizep= SETsizeaddr_(set);
+    if (!(sizep->i)--)         /*  if was a full set */
+      sizep->i= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
+    lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
+    elemp->p= lastp->p;      /* may overwrite itself */
+    lastp->p= NULL;
+    return oldelem;
+  }
+  return NULL;
+} /* setdel */
+
+
+/*---------------------------------
+
+  qh_setdellast( set )
+    return last element of set or NULL
+
+  notes:
+    deletes element from set
+    set may be NULL
+
+  design:
+    return NULL if empty
+    if full set
+      delete last element and set actual size
+    else
+      delete last element and update actual size
+*/
+void *qh_setdellast(setT *set) {
+  int setsize;  /* actually, actual_size + 1 */
+  int maxsize;
+  setelemT *sizep;
+  void *returnvalue;
+
+  if (!set || !(set->e[0].p))
+    return NULL;
+  sizep= SETsizeaddr_(set);
+  if ((setsize= sizep->i)) {
+    returnvalue= set->e[setsize - 2].p;
+    set->e[setsize - 2].p= NULL;
+    sizep->i--;
+  }else {
+    maxsize= set->maxsize;
+    returnvalue= set->e[maxsize - 1].p;
+    set->e[maxsize - 1].p= NULL;
+    sizep->i= maxsize;
+  }
+  return returnvalue;
+} /* setdellast */
+
+
+/*---------------------------------
+
+  qh_setdelnth(qh, set, nth )
+    deletes nth element from unsorted set
+    0 is first element
+
+  returns:
+    returns the element (needs type conversion)
+
+  notes:
+    errors if nth invalid
+
+  design:
+    setup points and check nth
+    delete nth element and overwrite with last element
+*/
+void *qh_setdelnth(qhT *qh, setT *set, int nth) {
+  void *elem;
+  setelemT *sizep;
+  setelemT *elemp, *lastp;
+
+  sizep= SETsizeaddr_(set);
+  if ((sizep->i--)==0)         /*  if was a full set */
+    sizep->i= set->maxsize;    /*    *sizep= (maxsize-1)+ 1 */
+  if (nth < 0 || nth >= sizep->i) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6174, "qhull internal error (qh_setdelnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qh, qh->qhmem.ferr, "", set);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  elemp= (setelemT *)SETelemaddr_(set, nth, void); /* nth valid by QH6174 */
+  lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
+  elem= elemp->p;
+  elemp->p= lastp->p;      /* may overwrite itself */
+  lastp->p= NULL;
+  return elem;
+} /* setdelnth */
+
+/*---------------------------------
+
+  qh_setdelnthsorted(qh, set, nth )
+    deletes nth element from sorted set
+
+  returns:
+    returns the element (use type conversion)
+
+  notes:
+    errors if nth invalid
+
+  see also:
+    setnew_delnthsorted
+
+  design:
+    setup points and check nth
+    copy remaining elements down one
+    update actual size
+*/
+void *qh_setdelnthsorted(qhT *qh, setT *set, int nth) {
+  void *elem;
+  setelemT *sizep;
+  setelemT *newp, *oldp;
+
+  sizep= SETsizeaddr_(set);
+  if (nth < 0 || (sizep->i && nth >= sizep->i-1) || nth >= set->maxsize) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6175, "qhull internal error (qh_setdelnthsorted): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qh, qh->qhmem.ferr, "", set);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  newp= (setelemT *)SETelemaddr_(set, nth, void);
+  elem= newp->p;
+  oldp= newp+1;
+  while (((newp++)->p= (oldp++)->p))
+    ; /* copy remaining elements and NULL */
+  if ((sizep->i--)==0)         /*  if was a full set */
+    sizep->i= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
+  return elem;
+} /* setdelnthsorted */
+
+
+/*---------------------------------
+
+  qh_setdelsorted( set, oldelem )
+    deletes oldelem from sorted set
+
+  returns:
+    returns oldelem if it was deleted
+
+  notes:
+    set may be NULL
+
+  design:
+    locate oldelem in set
+    copy remaining elements down one
+    update actual size
+*/
+void *qh_setdelsorted(setT *set, void *oldelem) {
+  setelemT *sizep;
+  setelemT *newp, *oldp;
+
+  if (!set)
+    return NULL;
+  newp= (setelemT *)SETaddr_(set, void);
+  while(newp->p != oldelem && newp->p)
+    newp++;
+  if (newp->p) {
+    oldp= newp+1;
+    while (((newp++)->p= (oldp++)->p))
+      ; /* copy remaining elements */
+    sizep= SETsizeaddr_(set);
+    if ((sizep->i--)==0)    /*  if was a full set */
+      sizep->i= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
+    return oldelem;
+  }
+  return NULL;
+} /* setdelsorted */
+
+
+/*---------------------------------
+
+  qh_setduplicate(qh, set, elemsize )
+    duplicate a set of elemsize elements
+
+  notes:
+    use setcopy if retaining old elements
+
+  design:
+    create a new set
+    for each elem of the old set
+      create a newelem
+      append newelem to newset
+*/
+setT *qh_setduplicate(qhT *qh, setT *set, int elemsize) {
+  void          *elem, **elemp, *newElem;
+  setT          *newSet;
+  int           size;
+
+  if (!(size= qh_setsize(qh, set)))
+    return NULL;
+  newSet= qh_setnew(qh, size);
+  FOREACHelem_(set) {
+    newElem= qh_memalloc(qh, elemsize);
+    memcpy(newElem, elem, (size_t)elemsize);
+    qh_setappend(qh, &newSet, newElem);
+  }
+  return newSet;
+} /* setduplicate */
+
+
+/*---------------------------------
+
+  qh_setendpointer( set )
+    Returns pointer to NULL terminator of a set's elements
+    set can not be NULL
+
+*/
+void **qh_setendpointer(setT *set) {
+
+  setelemT *sizep= SETsizeaddr_(set);
+  int n= sizep->i;
+  return (n ? &set->e[n-1].p : &sizep->p);
+} /* qh_setendpointer */
+
+/*---------------------------------
+
+  qh_setequal( setA, setB )
+    returns 1 if two sorted sets are equal, otherwise returns 0
+
+  notes:
+    either set may be NULL
+
+  design:
+    check size of each set
+    setup pointers
+    compare elements of each set
+*/
+int qh_setequal(setT *setA, setT *setB) {
+  void **elemAp, **elemBp;
+  int sizeA= 0, sizeB= 0;
+
+  if (setA) {
+    SETreturnsize_(setA, sizeA);
+  }
+  if (setB) {
+    SETreturnsize_(setB, sizeB);
+  }
+  if (sizeA != sizeB)
+    return 0;
+  if (!sizeA)
+    return 1;
+  elemAp= SETaddr_(setA, void);
+  elemBp= SETaddr_(setB, void);
+  if (!memcmp((char *)elemAp, (char *)elemBp, (size_t)(sizeA * SETelemsize)))
+    return 1;
+  return 0;
+} /* setequal */
+
+
+/*---------------------------------
+
+  qh_setequal_except( setA, skipelemA, setB, skipelemB )
+    returns 1 if sorted setA and setB are equal except for skipelemA & B
+
+  returns:
+    false if either skipelemA or skipelemB are missing
+
+  notes:
+    neither set may be NULL
+
+    if skipelemB is NULL,
+      can skip any one element of setB
+
+  design:
+    setup pointers
+    search for skipelemA, skipelemB, and mismatches
+    check results
+*/
+int qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
+  void **elemA, **elemB;
+  int skip=0;
+
+  elemA= SETaddr_(setA, void);
+  elemB= SETaddr_(setB, void);
+  while (1) {
+    if (*elemA == skipelemA) {
+      skip++;
+      elemA++;
+    }
+    if (skipelemB) {
+      if (*elemB == skipelemB) {
+        skip++;
+        elemB++;
+      }
+    }else if (*elemA != *elemB) {
+      skip++;
+      if (!(skipelemB= *elemB++))
+        return 0;
+    }
+    if (!*elemA)
+      break;
+    if (*elemA++ != *elemB++)
+      return 0;
+  }
+  if (skip != 2 || *elemB)
+    return 0;
+  return 1;
+} /* setequal_except */
+
+
+/*---------------------------------
+
+  qh_setequal_skip( setA, skipA, setB, skipB )
+    returns 1 if sorted setA and setB are equal except for elements skipA & B
+
+  returns:
+    false if different size
+
+  notes:
+    neither set may be NULL
+
+  design:
+    setup pointers
+    search for mismatches while skipping skipA and skipB
+*/
+int qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB) {
+  void **elemA, **elemB, **skipAp, **skipBp;
+
+  elemA= SETaddr_(setA, void);
+  elemB= SETaddr_(setB, void);
+  skipAp= SETelemaddr_(setA, skipA, void);
+  skipBp= SETelemaddr_(setB, skipB, void);
+  while (1) {
+    if (elemA == skipAp)
+      elemA++;
+    if (elemB == skipBp)
+      elemB++;
+    if (!*elemA)
+      break;
+    if (*elemA++ != *elemB++)
+      return 0;
+  }
+  if (*elemB)
+    return 0;
+  return 1;
+} /* setequal_skip */
+
+
+/*---------------------------------
+
+  qh_setfree(qh, setp )
+    frees the space occupied by a sorted or unsorted set
+
+  returns:
+    sets setp to NULL
+
+  notes:
+    set may be NULL
+
+  design:
+    free array
+    free set
+*/
+void qh_setfree(qhT *qh, setT **setp) {
+  int size;
+  void **freelistp;  /* used if !qh_NOmem by qh_memfree_() */
+
+  if (*setp) {
+    size= SETbasesize + ((*setp)->maxsize)*SETelemsize;
+    if (size <= qh->qhmem.LASTsize) {
+      qh_memfree_(qh, *setp, size, freelistp);
+    }else
+      qh_memfree(qh, *setp, size);
+    *setp= NULL;
+  }
+} /* setfree */
+
+
+/*---------------------------------
+
+  qh_setfree2(qh, setp, elemsize )
+    frees the space occupied by a set and its elements
+
+  notes:
+    set may be NULL
+
+  design:
+    free each element
+    free set
+*/
+void qh_setfree2(qhT *qh, setT **setp, int elemsize) {
+  void          *elem, **elemp;
+
+  FOREACHelem_(*setp)
+    qh_memfree(qh, elem, elemsize);
+  qh_setfree(qh, setp);
+} /* setfree2 */
+
+
+
+/*---------------------------------
+
+  qh_setfreelong(qh, setp )
+    frees a set only if it's in long memory
+
+  returns:
+    sets setp to NULL if it is freed
+
+  notes:
+    set may be NULL
+
+  design:
+    if set is large
+      free it
+*/
+void qh_setfreelong(qhT *qh, setT **setp) {
+  int size;
+
+  if (*setp) {
+    size= SETbasesize + ((*setp)->maxsize)*SETelemsize;
+    if (size > qh->qhmem.LASTsize) {
+      qh_memfree(qh, *setp, size);
+      *setp= NULL;
+    }
+  }
+} /* setfreelong */
+
+
+/*---------------------------------
+
+  qh_setin( set, setelem )
+    returns 1 if setelem is in a set, 0 otherwise
+
+  notes:
+    set may be NULL or unsorted
+
+  design:
+    scans set for setelem
+*/
+int qh_setin(setT *set, void *setelem) {
+  void *elem, **elemp;
+
+  FOREACHelem_(set) {
+    if (elem == setelem)
+      return 1;
+  }
+  return 0;
+} /* setin */
+
+
+/*---------------------------------
+
+  qh_setindex(set, atelem )
+    returns the index of atelem in set.
+    returns -1, if not in set or maxsize wrong
+
+  notes:
+    set may be NULL and may contain nulls.
+    NOerrors returned (qh_pointid, QhullPoint::id)
+
+  design:
+    checks maxsize
+    scans set for atelem
+*/
+int qh_setindex(setT *set, void *atelem) {
+  void **elem;
+  int size, i;
+
+  if (!set)
+    return -1;
+  SETreturnsize_(set, size);
+  if (size > set->maxsize)
+    return -1;
+  elem= SETaddr_(set, void);
+  for (i=0; i < size; i++) {
+    if (*elem++ == atelem)
+      return i;
+  }
+  return -1;
+} /* setindex */
+
+
+/*---------------------------------
+
+  qh_setlarger(qh, oldsetp )
+    returns a larger set that contains all elements of *oldsetp
+
+  notes:
+    if long memory,
+      the new set is 2x larger
+    if qhmem.LASTsize is between 1.5x and 2x
+      the new set is qhmem.LASTsize
+    otherwise use quick memory,
+      the new set is 2x larger, rounded up to next qh_memsize
+       
+    if temp set, updates qh->qhmem.tempstack
+
+  design:
+    creates a new set
+    copies the old set to the new set
+    updates pointers in tempstack
+    deletes the old set
+*/
+void qh_setlarger(qhT *qh, setT **oldsetp) {
+  int setsize= 1, newsize;
+  setT *newset, *set, **setp, *oldset;
+  setelemT *sizep;
+  setelemT *newp, *oldp;
+
+  if (*oldsetp) {
+    oldset= *oldsetp;
+    SETreturnsize_(oldset, setsize);
+    qh->qhmem.cntlarger++;
+    qh->qhmem.totlarger += setsize+1;
+    qh_setlarger_quick(qh, setsize, &newsize);
+    newset= qh_setnew(qh, newsize);
+    oldp= (setelemT *)SETaddr_(oldset, void);
+    newp= (setelemT *)SETaddr_(newset, void);
+    memcpy((char *)newp, (char *)oldp, (size_t)(setsize+1) * SETelemsize);
+    sizep= SETsizeaddr_(newset);
+    sizep->i= setsize+1;
+    FOREACHset_((setT *)qh->qhmem.tempstack) {
+      if (set == oldset)
+        *(setp-1)= newset;
+    }
+    qh_setfree(qh, oldsetp);
+  }else
+    newset= qh_setnew(qh, 3);
+  *oldsetp= newset;
+} /* setlarger */
+
+
+/*---------------------------------
+
+  qh_setlarger_quick(qh, setsize, newsize )
+    determine newsize for setsize
+    returns True if newsize fits in quick memory
+
+  design:
+    if 2x fits into quick memory
+      return True, 2x
+    if x+4 does not fit into quick memory
+      return False, 2x
+    if x+x/3 fits into quick memory
+      return True, the last quick set
+    otherwise
+      return False, 2x
+*/
+int qh_setlarger_quick(qhT *qh, int setsize, int *newsize) {
+    int lastquickset;
+
+    *newsize= 2 * setsize;
+    lastquickset= (qh->qhmem.LASTsize - SETbasesize) / SETelemsize; /* matches size computation in qh_setnew */
+    if (*newsize <= lastquickset)
+      return 1;
+    if (setsize + 4 > lastquickset)
+      return 0;
+    if (setsize + setsize/3 <= lastquickset) {
+      *newsize= lastquickset;
+      return 1;
+    }
+    return 0;
+} /* setlarger_quick */
+
+/*---------------------------------
+
+  qh_setlast( set )
+    return last element of set or NULL (use type conversion)
+
+  notes:
+    set may be NULL
+
+  design:
+    return last element
+*/
+void *qh_setlast(setT *set) {
+  int size;
+
+  if (set) {
+    size= SETsizeaddr_(set)->i;
+    if (!size)
+      return SETelem_(set, set->maxsize - 1);
+    else if (size > 1)
+      return SETelem_(set, size - 2);
+  }
+  return NULL;
+} /* setlast */
+
+
+/*---------------------------------
+
+  qh_setnew(qh, setsize )
+    creates and allocates space for a set
+
+  notes:
+    setsize means the number of elements (!including the NULL terminator)
+    use qh_settemp/qh_setfreetemp if set is temporary
+
+  design:
+    allocate memory for set
+    roundup memory if small set
+    initialize as empty set
+*/
+setT *qh_setnew(qhT *qh, int setsize) {
+  setT *set;
+  int sizereceived; /* used if !qh_NOmem */
+  int size;
+  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
+
+  if (!setsize)
+    setsize++;
+  size= SETbasesize + setsize * SETelemsize; /* setT includes NULL terminator, see qh.LASTquickset */
+  if (size>0 && size <= qh->qhmem.LASTsize) {
+    qh_memalloc_(qh, size, freelistp, set, setT);
+#ifndef qh_NOmem
+    sizereceived= qh->qhmem.sizetable[ qh->qhmem.indextable[size]];
+    if (sizereceived > size)
+      setsize += (sizereceived - size)/SETelemsize;
+#endif
+  }else
+    set= (setT *)qh_memalloc(qh, size);
+  set->maxsize= setsize;
+  set->e[setsize].i= 1;
+  set->e[0].p= NULL;
+  return(set);
+} /* setnew */
+
+
+/*---------------------------------
+
+  qh_setnew_delnthsorted(qh, set, size, nth, prepend )
+    creates a sorted set not containing nth element
+    if prepend, the first prepend elements are undefined
+
+  notes:
+    set must be defined
+    checks nth
+    see also: setdelnthsorted
+
+  design:
+    create new set
+    setup pointers and allocate room for prepend'ed entries
+    append head of old set to new set
+    append tail of old set to new set
+*/
+setT *qh_setnew_delnthsorted(qhT *qh, setT *set, int size, int nth, int prepend) {
+  setT *newset;
+  void **oldp, **newp;
+  int tailsize= size - nth -1, newsize;
+
+  if (tailsize < 0) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6176, "qhull internal error (qh_setnew_delnthsorted): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qh, qh->qhmem.ferr, "", set);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  newsize= size-1 + prepend;
+  newset= qh_setnew(qh, newsize);
+  newset->e[newset->maxsize].i= newsize+1;  /* may be overwritten */
+  oldp= SETaddr_(set, void);
+  newp= SETaddr_(newset, void) + prepend;
+  switch (nth) {
+  case 0:
+    break;
+  case 1:
+    *(newp++)= *oldp++;
+    break;
+  case 2:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 3:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 4:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  default:
+    memcpy((char *)newp, (char *)oldp, (size_t)nth * SETelemsize);
+    newp += nth;
+    oldp += nth;
+    break;
+  }
+  oldp++;
+  switch (tailsize) {
+  case 0:
+    break;
+  case 1:
+    *(newp++)= *oldp++;
+    break;
+  case 2:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 3:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 4:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  default:
+    memcpy((char *)newp, (char *)oldp, (size_t)tailsize * SETelemsize);
+    newp += tailsize;
+  }
+  *newp= NULL;
+  return(newset);
+} /* setnew_delnthsorted */
+
+
+/*---------------------------------
+
+  qh_setprint(qh, fp, string, set )
+    print set elements to fp with identifying string
+
+  notes:
+    never errors
+*/
+void qh_setprint(qhT *qh, FILE *fp, const char* string, setT *set) {
+  int size, k;
+
+  if (!set)
+    qh_fprintf(qh, fp, 9346, "%s set is null\n", string);
+  else {
+    SETreturnsize_(set, size);
+    qh_fprintf(qh, fp, 9347, "%s set=%p maxsize=%d size=%d elems=",
+             string, (void *) set, set->maxsize, size);
+    if (size > set->maxsize)
+      size= set->maxsize+1;
+    for (k=0; k < size; k++)
+      qh_fprintf(qh, fp, 9348, " %p", (void *) set->e[k].p);
+    qh_fprintf(qh, fp, 9349, "\n");
+  }
+} /* setprint */
+
+/*---------------------------------
+
+  qh_setreplace(qh, set, oldelem, newelem )
+    replaces oldelem in set with newelem
+
+  notes:
+    errors if oldelem not in the set
+    newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
+
+  design:
+    find oldelem
+    replace with newelem
+*/
+void qh_setreplace(qhT *qh, setT *set, void *oldelem, void *newelem) {
+  void **elemp;
+
+  elemp= SETaddr_(set, void);
+  while (*elemp != oldelem && *elemp)
+    elemp++;
+  if (*elemp)
+    *elemp= newelem;
+  else {
+    qh_fprintf(qh, qh->qhmem.ferr, 6177, "qhull internal error (qh_setreplace): elem %p not found in set\n",
+       oldelem);
+    qh_setprint(qh, qh->qhmem.ferr, "", set);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+} /* setreplace */
+
+
+/*---------------------------------
+
+  qh_setsize(qh, set )
+    returns the size of a set
+
+  notes:
+    errors if set's maxsize is incorrect
+    same as SETreturnsize_(set)
+    same code for qh_setsize [qset_r.c] and QhullSetBase::count
+    if first element is NULL, SETempty_() is True but qh_setsize may be greater than 0
+
+  design:
+    determine actual size of set from maxsize
+*/
+int qh_setsize(qhT *qh, setT *set) {
+  int size;
+  setelemT *sizep;
+
+  if (!set)
+    return(0);
+  sizep= SETsizeaddr_(set);
+  if ((size= sizep->i)) {
+    size--;
+    if (size > set->maxsize) {
+      qh_fprintf(qh, qh->qhmem.ferr, 6178, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
+               size, set->maxsize);
+      qh_setprint(qh, qh->qhmem.ferr, "set: ", set);
+      qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+    }
+  }else
+    size= set->maxsize;
+  return size;
+} /* setsize */
+
+/*---------------------------------
+
+  qh_settemp(qh, setsize )
+    return a stacked, temporary set of up to setsize elements
+
+  notes:
+    use settempfree or settempfree_all to release from qh->qhmem.tempstack
+    see also qh_setnew
+
+  design:
+    allocate set
+    append to qh->qhmem.tempstack
+
+*/
+setT *qh_settemp(qhT *qh, int setsize) {
+  setT *newset;
+
+  newset= qh_setnew(qh, setsize);
+  qh_setappend(qh, &qh->qhmem.tempstack, newset);
+  if (qh->qhmem.IStracing >= 5)
+    qh_fprintf(qh, qh->qhmem.ferr, 8123, "qh_settemp: temp set %p of %d elements, depth %d\n",
+       (void *) newset, newset->maxsize, qh_setsize(qh, qh->qhmem.tempstack));
+  return newset;
+} /* settemp */
+
+/*---------------------------------
+
+  qh_settempfree(qh, set )
+    free temporary set at top of qh->qhmem.tempstack
+
+  notes:
+    nop if set is NULL
+    errors if set not from previous   qh_settemp
+
+  to locate errors:
+    use 'T2' to find source and then find mis-matching qh_settemp
+
+  design:
+    check top of qh->qhmem.tempstack
+    free it
+*/
+void qh_settempfree(qhT *qh, setT **set) {
+  setT *stackedset;
+
+  if (!*set)
+    return;
+  stackedset= qh_settemppop(qh);
+  if (stackedset != *set) {
+    qh_settemppush(qh, stackedset);
+    qh_fprintf(qh, qh->qhmem.ferr, 6179, "qhull internal error (qh_settempfree): set %p(size %d) was not last temporary allocated(depth %d, set %p, size %d)\n",
+             (void *) *set, qh_setsize(qh, *set), qh_setsize(qh, qh->qhmem.tempstack)+1,
+             (void *) stackedset, qh_setsize(qh, stackedset));
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  qh_setfree(qh, set);
+} /* settempfree */
+
+/*---------------------------------
+
+  qh_settempfree_all(qh)
+    free all temporary sets in qh->qhmem.tempstack
+
+  design:
+    for each set in tempstack
+      free set
+    free qh->qhmem.tempstack
+*/
+void qh_settempfree_all(qhT *qh) {
+  setT *set, **setp;
+
+  FOREACHset_(qh->qhmem.tempstack)
+    qh_setfree(qh, &set);
+  qh_setfree(qh, &qh->qhmem.tempstack);
+} /* settempfree_all */
+
+/*---------------------------------
+
+  qh_settemppop(qh)
+    pop and return temporary set from qh->qhmem.tempstack
+
+  notes:
+    the returned set is permanent
+
+  design:
+    pop and check top of qh->qhmem.tempstack
+*/
+setT *qh_settemppop(qhT *qh) {
+  setT *stackedset;
+
+  stackedset= (setT *)qh_setdellast(qh->qhmem.tempstack);
+  if (!stackedset) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6180, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  if (qh->qhmem.IStracing >= 5)
+    qh_fprintf(qh, qh->qhmem.ferr, 8124, "qh_settemppop: depth %d temp set %p of %d elements\n",
+       qh_setsize(qh, qh->qhmem.tempstack)+1, (void *) stackedset, qh_setsize(qh, stackedset));
+  return stackedset;
+} /* settemppop */
+
+/*---------------------------------
+
+  qh_settemppush(qh, set )
+    push temporary set unto qh->qhmem.tempstack (makes it temporary)
+
+  notes:
+    duplicates settemp() for tracing
+
+  design:
+    append set to tempstack
+*/
+void qh_settemppush(qhT *qh, setT *set) {
+  if (!set) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6267, "qhull error (qh_settemppush): can not push a NULL temp\n");
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  qh_setappend(qh, &qh->qhmem.tempstack, set);
+  if (qh->qhmem.IStracing >= 5)
+    qh_fprintf(qh, qh->qhmem.ferr, 8125, "qh_settemppush: depth %d temp set %p of %d elements\n",
+      qh_setsize(qh, qh->qhmem.tempstack), (void *) set, qh_setsize(qh, set));
+} /* settemppush */
+
+
+/*---------------------------------
+
+  qh_settruncate(qh, set, size )
+    truncate set to size elements
+
+  notes:
+    set must be defined
+
+  see:
+    SETtruncate_
+
+  design:
+    check size
+    update actual size of set
+*/
+void qh_settruncate(qhT *qh, setT *set, int size) {
+
+  if (size < 0 || size > set->maxsize) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6181, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
+    qh_setprint(qh, qh->qhmem.ferr, "", set);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  set->e[set->maxsize].i= size+1;   /* maybe overwritten */
+  set->e[size].p= NULL;
+} /* settruncate */
+
+/*---------------------------------
+
+  qh_setunique(qh, set, elem )
+    add elem to unsorted set unless it is already in set
+
+  notes:
+    returns 1 if it is appended
+
+  design:
+    if elem not in set
+      append elem to set
+*/
+int qh_setunique(qhT *qh, setT **set, void *elem) {
+
+  if (!qh_setin(*set, elem)) {
+    qh_setappend(qh, set, elem);
+    return 1;
+  }
+  return 0;
+} /* setunique */
+
+/*---------------------------------
+
+  qh_setzero(qh, set, index, size )
+    zero elements from index on
+    set actual size of set to size
+
+  notes:
+    set must be defined
+    the set becomes an indexed set (can not use FOREACH...)
+
+  see also:
+    qh_settruncate
+
+  design:
+    check index and size
+    update actual size
+    zero elements starting at e[index]
+*/
+void qh_setzero(qhT *qh, setT *set, int idx, int size) {
+  int count;
+
+  if (idx < 0 || idx >= size || size > set->maxsize) {
+    qh_fprintf(qh, qh->qhmem.ferr, 6182, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", idx, size);
+    qh_setprint(qh, qh->qhmem.ferr, "", set);
+    qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
+  }
+  set->e[set->maxsize].i=  size+1;  /* may be overwritten */
+  count= size - idx + 1;   /* +1 for NULL terminator */
+  memset((char *)SETelemaddr_(set, idx, void), 0, (size_t)count * SETelemsize);
+} /* setzero */
+
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.h
new file mode 100644
index 00000000000..bc0298ed086
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/qset_r.h
@@ -0,0 +1,515 @@
+/*
  ---------------------------------
+
+   qset_r.h
+     header file for qset_r.c that implements set
+
+   see qh-set_r.htm and qset_r.c
+
+   only uses mem_r.c, malloc/free
+
+   for error handling, writes message and calls
+      qh_errexit(qhT *qh, qhmem_ERRqhull, NULL, NULL);
+
+   set operations satisfy the following properties:
+    - sets have a max size, the actual size (if different) is stored at the end
+    - every set is NULL terminated
+    - sets may be sorted or unsorted, the caller must distinguish this
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/qset_r.h#4 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#ifndef qhDEFset
+#define qhDEFset 1
+
+#include 
+
+/*================= -structures- ===============*/
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;   /* a set is a sorted or unsorted array of pointers */
+#endif
+
+#ifndef DEFqhT
+#define DEFqhT 1
+typedef struct qhT qhT;          /* defined in libqhull_r.h */
+#endif
+
+/* [jan'15] Decided not to use countT.  Most sets are small.  The code uses signed tests */
+
+/*------------------------------------------
+
+setT
+  a set or list of pointers with maximum size and actual size.
+
+variations:
+  unsorted, unique   -- a list of unique pointers with NULL terminator
+                           user guarantees uniqueness
+  sorted             -- a sorted list of unique pointers with NULL terminator
+                           qset_r.c guarantees uniqueness
+  unsorted           -- a list of pointers terminated with NULL
+  indexed            -- an array of pointers with NULL elements
+
+structure for set of n elements:
+
+        --------------
+        |  maxsize
+        --------------
+        |  e[0] - a pointer, may be NULL for indexed sets
+        --------------
+        |  e[1]
+
+        --------------
+        |  ...
+        --------------
+        |  e[n-1]
+        --------------
+        |  e[n] = NULL
+        --------------
+        |  ...
+        --------------
+        |  e[maxsize] - n+1 or NULL (determines actual size of set)
+        --------------
+
+*/
+
+/*-- setelemT -- internal type to allow both pointers and indices
+*/
+typedef union setelemT setelemT;
+union setelemT {
+  void    *p;
+  int   i;         /* integer used for e[maxSize] */
+};
+
+struct setT {
+  int maxsize;          /* maximum number of elements (except NULL) */
+  setelemT e[];        /* array of pointers, tail is NULL */
+                        /* last slot (unless NULL) is actual size+1
+                           e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
+                        /* this may generate a warning since e[] contains
+                           maxsize elements */
+};
+
+/*=========== -constants- =========================*/
+
+/*-------------------------------------
+
+  SETelemsize
+    size of a set element in bytes
+*/
+#define SETelemsize ((int)sizeof(setelemT))
+
+/*
+   SETbasesize - size of setT with a single element
+   in e[]. Before C99, setT has been declared with e[1], so
+   sizeof(setT) included already space for one element, but with e[]
+   (C99), it does not. All instances of (int)sizeof(setT) have been
+   replaced with SETbasesize throughout the code -- Tomas Kalibera,
+   2025-01-09 */
+#define SETbasesize ((int)sizeof(setT) + SETelemsize)
+
+
+/*=========== -macros- =========================*/
+
+/*-------------------------------------
+
+   FOREACHsetelement_(type, set, variable)
+     define FOREACH iterator
+
+   declare:
+     assumes *variable and **variablep are declared
+     no space in "variable)" [DEC Alpha cc compiler]
+
+   each iteration:
+     variable is set element
+     variablep is one beyond variable.
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+
+   example:
+     #define FOREACHfacet_(facets) FOREACHsetelement_(facetT, facets, facet)
+
+   notes:
+     use FOREACHsetelement_i_() if need index or include NULLs
+     assumes set is not modified
+
+   WARNING:
+     nested loops can't use the same variable (define another FOREACH)
+
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##p= (type **)&((set)->e[0].p); \
+          (variable= *variable##p++);)
+
+/*------------------------------------------
+
+   FOREACHsetelement_i_(qh, type, set, variable)
+     define indexed FOREACH iterator
+
+   declare:
+     type *variable, variable_n, variable_i;
+
+   each iteration:
+     variable is set element, may be NULL
+     variable_i is index, variable_n is qh_setsize()
+
+   to repeat an element:
+     variable_i--; variable_n-- repeats for deleted element
+
+   at exit:
+     variable==NULL and variable_i==variable_n
+
+   example:
+     #define FOREACHfacet_i_(qh, facets) FOREACHsetelement_i_(qh, facetT, facets, facet)
+
+   WARNING:
+     nested loops can't use the same variable (define another FOREACH)
+
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_i_(qh, type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##_i= 0, variable= (type *)((set)->e[0].p), \
+                   variable##_n= qh_setsize(qh, set);\
+          variable##_i < variable##_n;\
+          variable= (type *)((set)->e[++variable##_i].p) )
+
+/*----------------------------------------
+
+   FOREACHsetelementreverse_(qh, type, set, variable)-
+     define FOREACH iterator in reverse order
+
+   declare:
+     assumes *variable and **variablep are declared
+     also declare 'int variabletemp'
+
+   each iteration:
+     variable is set element
+
+   to repeat an element:
+     variabletemp++; / *repeat* /
+
+   at exit:
+     variable is NULL
+
+   example:
+     #define FOREACHvertexreverse_(vertices) FOREACHsetelementreverse_(vertexT, vertices, vertex)
+
+   notes:
+     use FOREACHsetelementreverse12_() to reverse first two elements
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse_(qh, type, set, variable) \
+        if (((variable= NULL), set)) for (\
+           variable##temp= qh_setsize(qh, set)-1, variable= qh_setlast(qh, set);\
+           variable; variable= \
+           ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
+
+/*-------------------------------------
+
+   FOREACHsetelementreverse12_(type, set, variable)-
+     define FOREACH iterator with e[1] and e[0] reversed
+
+   declare:
+     assumes *variable and **variablep are declared
+
+   each iteration:
+     variable is set element
+     variablep is one after variable.
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+
+   example
+     #define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
+
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse12_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##p= (type **)&((set)->e[1].p); \
+          (variable= *variable##p); \
+          variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
+              (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
+
+/*-------------------------------------
+
+   FOREACHelem_( set )-
+     iterate elements in a set
+
+   declare:
+     void *elem, *elemp;
+
+   each iteration:
+     elem is set element
+     elemp is one beyond
+
+   to repeat an element:
+     elemp--; / *repeat* /
+
+   at exit:
+     elem == NULL at end of loop
+
+   example:
+     FOREACHelem_(set) {
+
+   notes:
+     assumes set is not modified
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
+
+/*-------------------------------------
+
+   FOREACHset_( set )-
+     iterate a set of sets
+
+   declare:
+     setT *set, **setp;
+
+   each iteration:
+     set is set element
+     setp is one beyond
+
+   to repeat an element:
+     setp--; / *repeat* /
+
+   at exit:
+     set == NULL at end of loop
+
+   example
+     FOREACHset_(sets) {
+
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
+
+/*-------------------------------------------
+
+   SETindex_( set, elem )
+     return index of elem in set
+
+   notes:
+     for use with FOREACH iteration
+     WARN64 -- Maximum set size is 2G
+
+   example:
+     i= SETindex_(ridges, ridge)
+*/
+#define SETindex_(set, elem) ((int)((void **)elem##p - (void **)&(set)->e[1].p))
+
+/*-----------------------------------------
+
+   SETref_( elem )
+     l.h.s. for modifying the current element in a FOREACH iteration
+
+   example:
+     SETref_(ridge)= anotherridge;
+*/
+#define SETref_(elem) (elem##p[-1])
+
+/*-----------------------------------------
+
+   SETelem_(set, n)
+     return the n'th element of set
+
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+      use SETelemt_() for type cast
+*/
+#define SETelem_(set, n)           ((set)->e[n].p)
+
+/*-----------------------------------------
+
+   SETelemt_(set, n, type)
+     return the n'th element of set as a type
+
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+*/
+#define SETelemt_(set, n, type)    ((type *)((set)->e[n].p))
+
+/*-----------------------------------------
+
+   SETelemaddr_(set, n, type)
+     return address of the n'th element of a set
+
+   notes:
+      assumes that n is valid [0..size] and set is defined
+*/
+#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
+
+/*-----------------------------------------
+
+   SETfirst_(set)
+     return first element of set
+
+*/
+#define SETfirst_(set)             ((set)->e[0].p)
+
+/*-----------------------------------------
+
+   SETfirstt_(set, type)
+     return first element of set as a type
+
+*/
+#define SETfirstt_(set, type)      ((type *)((set)->e[0].p))
+
+/*-----------------------------------------
+
+   SETsecond_(set)
+     return second element of set
+
+*/
+#define SETsecond_(set)            ((set)->e[1].p)
+
+/*-----------------------------------------
+
+   SETsecondt_(set, type)
+     return second element of set as a type
+*/
+#define SETsecondt_(set, type)     ((type *)((set)->e[1].p))
+
+/*-----------------------------------------
+
+   SETaddr_(set, type)
+       return address of set's elements
+*/
+#define SETaddr_(set,type)         ((type **)(&((set)->e[0].p)))
+
+/*-----------------------------------------
+
+   SETreturnsize_(set, size)
+     return size of a set
+
+   notes:
+      set must be defined
+      use qh_setsize(qhT *qh, set) unless speed is critical
+*/
+#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
+
+/*-----------------------------------------
+
+   SETempty_(set)
+     return true(1) if set is empty (i.e., FOREACHsetelement_ is empty)
+
+   notes:
+      set may be NULL
+      qh_setsize may be non-zero if first element is NULL
+*/
+#define SETempty_(set)            (!set || (SETfirst_(set) ? 0 : 1))
+
+/*---------------------------------
+
+  SETsizeaddr_(set)
+    return pointer to 'actual size+1' of set (set CANNOT be NULL!!)
+    Its type is setelemT* for strict aliasing
+    All SETelemaddr_ must be cast to setelemT
+
+
+  notes:
+    *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
+*/
+#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize]))
+
+/*-----------------------------------------
+
+   SETtruncate_(set, size)
+     truncate set to size
+
+   see:
+     qh_settruncate()
+
+*/
+#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
+      set->e[size].p= NULL;}
+
+/*======= prototypes in alphabetical order ============*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void  qh_setaddsorted(qhT *qh, setT **setp, void *elem);
+void  qh_setaddnth(qhT *qh, setT **setp, int nth, void *newelem);
+void  qh_setappend(qhT *qh, setT **setp, void *elem);
+void  qh_setappend_set(qhT *qh, setT **setp, setT *setA);
+void  qh_setappend2ndlast(qhT *qh, setT **setp, void *elem);
+void  qh_setcheck(qhT *qh, setT *set, const char *tname, unsigned int id);
+void  qh_setcompact(qhT *qh, setT *set);
+setT *qh_setcopy(qhT *qh, setT *set, int extra);
+void *qh_setdel(setT *set, void *elem);
+void *qh_setdellast(setT *set);
+void *qh_setdelnth(qhT *qh, setT *set, int nth);
+void *qh_setdelnthsorted(qhT *qh, setT *set, int nth);
+void *qh_setdelsorted(setT *set, void *newelem);
+setT *qh_setduplicate(qhT *qh, setT *set, int elemsize);
+void **qh_setendpointer(setT *set);
+int   qh_setequal(setT *setA, setT *setB);
+int   qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB);
+int   qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB);
+void  qh_setfree(qhT *qh, setT **set);
+void  qh_setfree2(qhT *qh, setT **setp, int elemsize);
+void  qh_setfreelong(qhT *qh, setT **set);
+int   qh_setin(setT *set, void *setelem);
+int   qh_setindex(setT *set, void *setelem);
+void  qh_setlarger(qhT *qh, setT **setp);
+int   qh_setlarger_quick(qhT *qh, int setsize, int *newsize);
+void *qh_setlast(setT *set);
+setT *qh_setnew(qhT *qh, int size);
+setT *qh_setnew_delnthsorted(qhT *qh, setT *set, int size, int nth, int prepend);
+void  qh_setprint(qhT *qh, FILE *fp, const char* string, setT *set);
+void  qh_setreplace(qhT *qh, setT *set, void *oldelem, void *newelem);
+int   qh_setsize(qhT *qh, setT *set);
+setT *qh_settemp(qhT *qh, int setsize);
+void  qh_settempfree(qhT *qh, setT **set);
+void  qh_settempfree_all(qhT *qh);
+setT *qh_settemppop(qhT *qh);
+void  qh_settemppush(qhT *qh, setT *set);
+void  qh_settruncate(qhT *qh, setT *set, int size);
+int   qh_setunique(qhT *qh, setT **set, void *elem);
+void  qh_setzero(qhT *qh, setT *set, int idx, int size);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFset */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.c
new file mode 100644
index 00000000000..7eecd30e094
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.c
@@ -0,0 +1,249 @@
+/*
  ---------------------------------
+
+   random_r.c and utilities
+     Park & Miller's minimimal standard random number generator
+     argc/argv conversion
+
+     Used by rbox.  Do not use 'qh' 
+*/
+
+#include "libqhull_r.h"
+#include "random_r.h"
+
+#include 
+#include 
+#include 
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
+#pragma warning( disable : 4706)  /* assignment within conditional function */
+#pragma warning( disable : 4996)  /* function was declared deprecated(strcpy, localtime, etc.) */
+#endif
+
+/*---------------------------------
+
+  qh_argv_to_command( argc, argv, command, max_size )
+
+    build command from argc/argv
+    max_size is at least
+
+  returns:
+    a space-delimited string of options (just as typed)
+    returns false if max_size is too short
+
+  notes:
+    silently removes
+    makes option string easy to input and output
+    matches qh_argv_to_command_size
+    argc may be 0
+*/
+int qh_argv_to_command(int argc, char *argv[], char* command, int max_size) {
+  int i, remaining;
+  char *s;
+  *command= '\0';  /* max_size > 0 */
+
+  if (argc) {
+    if ((s= strrchr( argv[0], '\\')) /* get filename w/o .exe extension */
+    || (s= strrchr( argv[0], '/')))
+        s++;
+    else
+        s= argv[0];
+    if ((int)strlen(s) < max_size)   /* WARN64 */
+        strcpy(command, s);
+    else
+        goto error_argv;
+    if ((s= strstr(command, ".EXE"))
+    ||  (s= strstr(command, ".exe")))
+        *s= '\0';
+  }
+  for (i=1; i < argc; i++) {
+    s= argv[i];
+    remaining= max_size - (int)strlen(command) - (int)strlen(s) - 2;   /* WARN64 */
+    if (!*s || strchr(s, ' ')) {
+      char *t= command + strlen(command);
+      remaining -= 2;
+      if (remaining < 0) {
+        goto error_argv;
+      }
+      *t++= ' ';
+      *t++= '"';
+      while (*s) {
+        if (*s == '"') {
+          if (--remaining < 0)
+            goto error_argv;
+          *t++= '\\';
+        }
+        *t++= *s++;
+      }
+      *t++= '"';
+      *t= '\0';
+    }else if (remaining < 0) {
+      goto error_argv;
+    }else {
+      strcat(command, " ");
+      strcat(command, s);
+    }
+  }
+  return 1;
+
+error_argv:
+  return 0;
+} /* argv_to_command */
+
+/*---------------------------------
+
+  qh_argv_to_command_size( argc, argv )
+
+    return size to allocate for qh_argv_to_command()
+
+  notes:
+    only called from rbox with qh_errexit not enabled
+    caller should report error if returned size is less than 1
+    argc may be 0
+    actual size is usually shorter
+*/
+int qh_argv_to_command_size(int argc, char *argv[]) {
+    int count= 1; /* null-terminator if argc==0 */
+    int i;
+    char *s;
+
+    for (i=0; i0 && strchr(argv[i], ' ')) {
+        count += 2;  /* quote delimiters */
+        for (s=argv[i]; *s; s++) {
+          if (*s == '"') {
+            count++;
+          }
+        }
+      }
+    }
+    return count;
+} /* argv_to_command_size */
+
+/*---------------------------------
+
+  qh_rand()
+  qh_srand(qh, seed )
+    generate pseudo-random number between 1 and 2^31 -2
+
+  notes:
+    For qhull and rbox, called from qh_RANDOMint(),etc. [user_r.h]
+
+    From Park & Miller's minimal standard random number generator
+      Communications of the ACM, 31:1192-1201, 1988.
+    Does not use 0 or 2^31 -1
+      this is silently enforced by qh_srand()
+    Can make 'Rn' much faster by moving qh_rand to qh_distplane
+*/
+
+/* Global variables and constants */
+
+#define qh_rand_a 16807
+#define qh_rand_m 2147483647
+#define qh_rand_q 127773  /* m div a */
+#define qh_rand_r 2836    /* m mod a */
+
+int qh_rand(qhT *qh) {
+    int lo, hi, test;
+    int seed= qh->last_random;
+
+    hi= seed / qh_rand_q;  /* seed div q */
+    lo= seed % qh_rand_q;  /* seed mod q */
+    test= qh_rand_a * lo - qh_rand_r * hi;
+    if (test > 0)
+        seed= test;
+    else
+        seed= test + qh_rand_m;
+    qh->last_random= seed;
+    /* seed= seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax;  for testing */
+    /* seed= qh_RANDOMmax;  for testing */
+    return seed;
+} /* rand */
+
+void qh_srand(qhT *qh, int seed) {
+    if (seed < 1)
+        qh->last_random= 1;
+    else if (seed >= qh_rand_m)
+        qh->last_random= qh_rand_m - 1;
+    else
+        qh->last_random= seed;
+} /* qh_srand */
+
+/*---------------------------------
+
+qh_randomfactor(qh, scale, offset )
+  return a random factor r * scale + offset
+
+notes:
+  qh.RANDOMa/b are defined in global_r.c
+  qh_RANDOMint requires 'qh'
+*/
+realT qh_randomfactor(qhT *qh, realT scale, realT offset) {
+    realT randr;
+
+    randr= qh_RANDOMint;
+    return randr * scale + offset;
+} /* randomfactor */
+
+/*---------------------------------
+
+  qh_randommatrix(qh, buffer, dim, rows )
+    generate a random dim X dim matrix in range [-1,1]
+    assumes buffer is [dim+1, dim]
+
+  returns:
+    sets buffer to random numbers
+    sets rows to rows of buffer
+    sets row[dim] as scratch row
+
+  notes:
+    qh_RANDOMint requires 'qh'
+*/
+void qh_randommatrix(qhT *qh, realT *buffer, int dim, realT **rows) {
+    int i, k;
+    realT **rowi, *coord, realr;
+
+    coord= buffer;
+    rowi= rows;
+    for (i=0; i < dim; i++) {
+        *(rowi++)= coord;
+        for (k=0; k < dim; k++) {
+            realr= qh_RANDOMint;
+            *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+        }
+    }
+    *rowi= coord;
+} /* randommatrix */
+
+/*---------------------------------
+
+  qh_strtol( s, endp) qh_strtod( s, endp)
+    internal versions of strtol() and strtod()
+    does not skip trailing spaces
+  notes:
+    some implementations of strtol()/strtod() skip trailing spaces
+*/
+double qh_strtod(const char *s, char **endp) {
+  double result;
+
+  result= strtod(s, endp);
+  if (s < (*endp) && (*endp)[-1] == ' ')
+    (*endp)--;
+  return result;
+} /* strtod */
+
+int qh_strtol(const char *s, char **endp) {
+  int result;
+
+  result= (int) strtol(s, endp, 10);     /* WARN64 */
+  if (s< (*endp) && (*endp)[-1] == ' ')
+    (*endp)--;
+  return result;
+} /* strtol */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.h
new file mode 100644
index 00000000000..a17549d3b93
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/random_r.h
@@ -0,0 +1,41 @@
+/*
  ---------------------------------
+
+  random_r.h
+    header file for random and utility routines
+
+   see qh-geom_r.htm and random_r.c
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/random_r.h#3 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+*/
+
+#ifndef qhDEFrandom
+#define qhDEFrandom 1
+
+#include "libqhull_r.h"
+
+/*============= prototypes in alphabetical order ======= */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int     qh_argv_to_command(int argc, char *argv[], char* command, int max_size);
+int     qh_argv_to_command_size(int argc, char *argv[]);
+int     qh_rand(qhT *qh);
+void    qh_srand(qhT *qh, int seed);
+realT   qh_randomfactor(qhT *qh, realT scale, realT offset);
+void    qh_randommatrix(qhT *qh, realT *buffer, int dim, realT **row);
+int     qh_strtol(const char *s, char **endp);
+double  qh_strtod(const char *s, char **endp);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* qhDEFrandom */
+
+
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/rboxlib_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/rboxlib_r.c
new file mode 100644
index 00000000000..67e39984115
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/rboxlib_r.c
@@ -0,0 +1,854 @@
+/*
  ---------------------------------
+
+   rboxlib_r.c
+     Generate input points
+
+   notes:
+     For documentation, see prompt[] of rbox_r.c
+     50 points generated for 'rbox D4'
+
+   WARNING:
+     incorrect range if qh_RANDOMmax is defined wrong (user_r.h)
+*/
+
+#include "libqhull_r.h"  /* First for user_r.h */
+#include "random_r.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ */
+#pragma warning( disable : 4706)  /* assignment within conditional expression. */
+#pragma warning( disable : 4996)  /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
+#endif
+
+#define MAXdim 200
+#define PI 3.1415926535897932384
+
+/* ------------------------------ prototypes ----------------*/
+int qh_roundi(qhT *qh, double a);
+void qh_out1(qhT *qh, double a);
+void qh_out2n(qhT *qh, double a, double b);
+void qh_out3n(qhT *qh, double a, double b, double c);
+void qh_outcoord(qhT *qh, int iscdd, double *coord, int dim);
+void qh_outcoincident(qhT *qh, int coincidentpoints, double radius, int iscdd, double *coord, int dim);
+void qh_rboxpoints2(qhT *qh, char* rbox_command, double **simplex);
+
+void    qh_fprintf_rbox(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... );
+void    qh_free(void *mem);
+void   *qh_malloc(size_t size);
+int     qh_rand(qhT *qh);
+void    qh_srand(qhT *qh, int seed);
+
+/*---------------------------------
+
+  qh_rboxpoints(qh, rbox_command )
+    Generate points to qh.fout according to rbox options
+    Report errors on qh.ferr
+
+  returns:
+    0 (qh_ERRnone) on success
+    1 (qh_ERRinput) on input error
+    4 (qh_ERRmem) on memory error
+    5 (qh_ERRqhull) on internal error
+
+  notes:
+    To avoid using stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user_r.c)
+    Split out qh_rboxpoints2() to avoid -Wclobbered
+
+  design:
+    Straight line code (consider defining a struct and functions):
+
+    Parse arguments into variables
+    Determine the number of points
+    Generate the points
+*/
+int qh_rboxpoints(qhT *qh, char* rbox_command) {
+  int exitcode;
+  double *simplex;
+
+  simplex= NULL;
+  exitcode= setjmp(qh->rbox_errexit);
+  if (exitcode) {
+    /* same code for error exit and normal return.  qh.NOerrexit is set */
+    if (simplex)
+      qh_free(simplex);
+    return exitcode;
+  }
+  qh_rboxpoints2(qh, rbox_command, &simplex);
+  /* same code for error exit and normal return */
+  if (simplex)
+    qh_free(simplex);
+  return qh_ERRnone;
+} /* rboxpoints */
+
+void qh_rboxpoints2(qhT *qh, char* rbox_command, double **simplex) {
+  int i,j,k;
+  int gendim;
+  int coincidentcount=0, coincidenttotal=0, coincidentpoints=0;
+  int cubesize, diamondsize, seed=0, count, apex;
+  int dim=3, numpoints=0, totpoints, addpoints=0;
+  int issphere=0, isaxis=0,  iscdd=0, islens=0, isregular=0, iswidth=0, addcube=0;
+  int isgap=0, isspiral=0, NOcommand=0, adddiamond=0;
+  int israndom=0, istime=0;
+  int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
+  double width=0.0, gap=0.0, radius=0.0, coincidentradius=0.0;
+  double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
+  double *coordp, *simplexp;
+  int nthroot, mult[MAXdim];
+  double norm, factor, randr, rangap, tempr, lensangle=0, lensbase=1;
+  double anglediff, angle, x, y, cube=0.0, diamond=0.0;
+  double box= qh_DEFAULTbox; /* scale all numbers before output */
+  double randmax= qh_RANDOMmax;
+  char command[250], seedbuf[50];
+  char *s=command, *t, *first_point=NULL;
+  time_t timedata;
+
+  *command= '\0';
+  strncat(command, rbox_command, sizeof(command)-sizeof(seedbuf)-strlen(command)-1);
+
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    if (isdigit(*s)) {
+      numpoints= qh_strtol(s, &s);
+      continue;
+    }
+    /* ============= read flags =============== */
+    switch (*s++) {
+    case 'c':
+      addcube= 1;
+      t= s;
+      while (isspace(*t))
+        t++;
+      if (*t == 'G')
+        cube= qh_strtod(++t, &s);
+      break;
+    case 'd':
+      adddiamond= 1;
+      t= s;
+      while (isspace(*t))
+        t++;
+      if (*t == 'G')
+        diamond= qh_strtod(++t, &s);
+      break;
+    case 'h':
+      iscdd= 1;
+      break;
+    case 'l':
+      isspiral= 1;
+      break;
+    case 'n':
+      NOcommand= 1;
+      break;
+    case 'r':
+      isregular= 1;
+      break;
+    case 's':
+      issphere= 1;
+      break;
+    case 't':
+      istime= 1;
+      if (isdigit(*s)) {
+        seed= qh_strtol(s, &s);
+        israndom= 0;
+      }else
+        israndom= 1;
+      break;
+    case 'x':
+      issimplex= 1;
+      break;
+    case 'y':
+      issimplex2= 1;
+      break;
+    case 'z':
+      qh->rbox_isinteger= 1;
+      break;
+    case 'B':
+      box= qh_strtod(s, &s);
+      isbox= 1;
+      break;
+    case 'C':
+      if (*s)
+        coincidentpoints=  qh_strtol(s, &s);
+      if (*s == ',') {
+        ++s;
+        coincidentradius=  qh_strtod(s, &s);
+      }
+      if (*s == ',') {
+        ++s;
+        coincidenttotal=  qh_strtol(s, &s);
+      }
+      if (*s && !isspace(*s)) {
+        qh_fprintf_rbox(qh, qh->ferr, 7080, "rbox error: arguments for 'Cn,r,m' are not 'int', 'float', and 'int'.  Remaining string is '%s'\n", s);
+        qh_errexit_rbox(qh, qh_ERRinput);
+      }
+      if (coincidentpoints==0){
+        qh_fprintf_rbox(qh, qh->ferr, 6268, "rbox error: missing arguments for 'Cn,r,m' where n is the number of coincident points, r is the radius (default 0.0), and m is the number of points\n");
+        qh_errexit_rbox(qh, qh_ERRinput);
+      }
+      if (coincidentpoints<0 || coincidenttotal<0 || coincidentradius<0.0){
+        qh_fprintf_rbox(qh, qh->ferr, 6269, "rbox error: negative arguments for 'Cn,m,r' where n (%d) is the number of coincident points, m (%d) is the number of points, and r (%.2g) is the radius (default 0.0)\n", coincidentpoints, coincidenttotal, coincidentradius);
+        qh_errexit_rbox(qh, qh_ERRinput);
+      }
+      break;
+    case 'D':
+      dim= qh_strtol(s, &s);
+      if (dim < 1
+      || dim > MAXdim) {
+        qh_fprintf_rbox(qh, qh->ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)\n", dim, MAXdim);
+        qh_errexit_rbox(qh, qh_ERRinput);
+      }
+      break;
+    case 'G':
+      if (isdigit(*s))
+        gap= qh_strtod(s, &s);
+      else
+        gap= 0.5;
+      isgap= 1;
+      break;
+    case 'L':
+      if (isdigit(*s))
+        radius= qh_strtod(s, &s);
+      else
+        radius= 10;
+      islens= 1;
+      break;
+    case 'M':
+      ismesh= 1;
+      if (*s)
+        meshn= qh_strtod(s, &s);
+      if (*s == ',') {
+        ++s;
+        meshm= qh_strtod(s, &s);
+      }else
+        meshm= 0.0;
+      if (*s == ',') {
+        ++s;
+        meshr= qh_strtod(s, &s);
+      }else
+        meshr= sqrt(meshn*meshn + meshm*meshm);
+      if (*s && !isspace(*s)) {
+        qh_fprintf_rbox(qh, qh->ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
+        meshn= 3.0, meshm=4.0, meshr=5.0;
+      }
+      break;
+    case 'O':
+      qh->rbox_out_offset= qh_strtod(s, &s);
+      break;
+    case 'P':
+      if (!first_point)
+        first_point= s - 1;
+      addpoints++;
+      while (*s && !isspace(*s))   /* read points later */
+        s++;
+      break;
+    case 'W':
+      width= qh_strtod(s, &s);
+      iswidth= 1;
+      break;
+    case 'Z':
+      if (isdigit(*s))
+        radius= qh_strtod(s, &s);
+      else
+        radius= 1.0;
+      isaxis= 1;
+      break;
+    default:
+      qh_fprintf_rbox(qh, qh->ferr, 6352, "rbox error: unknown flag at '%s'.\nExecute 'rbox' without arguments for documentation.\n", s - 1);
+      qh_errexit_rbox(qh, qh_ERRinput);
+    }
+    if (*s && !isspace(*s)) {
+      qh_fprintf_rbox(qh, qh->ferr, 6353, "rbox error: missing space between flags at %s.\n", s);
+      qh_errexit_rbox(qh, qh_ERRinput);
+    }
+  }
+
+  /* ============= defaults, constants, and sizes =============== */
+  if (qh->rbox_isinteger && !isbox)
+    box= qh_DEFAULTzbox;
+  if (addcube) {
+    tempr= floor(ldexp(1.0,dim)+0.5);
+    cubesize= (int)tempr;
+    if (cube == 0.0)
+      cube= box;
+  }else
+    cubesize= 0;
+  if (adddiamond) {
+    diamondsize= 2*dim;
+    if (diamond == 0.0)
+      diamond= box;
+  }else
+    diamondsize= 0;
+  if (islens) {
+    if (isaxis) {
+        qh_fprintf_rbox(qh, qh->ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
+        qh_errexit_rbox(qh, qh_ERRinput);
+    }
+    if (radius <= 1.0) {
+        qh_fprintf_rbox(qh, qh->ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
+               radius);
+        qh_errexit_rbox(qh, qh_ERRinput);
+    }
+    lensangle= asin(1.0/radius);
+    lensbase= radius * cos(lensangle);
+  }
+
+  if (!numpoints) {
+    if (issimplex2)
+        ; /* ok */
+    else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
+        qh_fprintf_rbox(qh, qh->ferr, 6192, "rbox error: missing count\n");
+        qh_errexit_rbox(qh, qh_ERRinput);
+    }else if (adddiamond + addcube + addpoints)
+        ; /* ok */
+    else {
+        numpoints= 50;  /* ./rbox D4 is the test case */
+        issphere= 1;
+    }
+  }
+  if ((issimplex + islens + isspiral + ismesh > 1)
+  || (issimplex + issphere + isspiral + ismesh > 1)) {
+    qh_fprintf_rbox(qh, qh->ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
+    qh_errexit_rbox(qh, qh_ERRinput);
+  }
+  if (coincidentpoints>0 && (numpoints == 0 || coincidenttotal > numpoints)) {
+    qh_fprintf_rbox(qh, qh->ferr, 6270, "rbox error: 'Cn,r,m' requested n coincident points for each of m points.  Either there is no points or m (%d) is greater than the number of points (%d).\n", coincidenttotal, numpoints);
+    qh_errexit_rbox(qh, qh_ERRinput);
+  }
+  if (coincidentpoints > 0 && isregular) {
+    qh_fprintf_rbox(qh, qh->ferr, 6423, "rbox error: 'Cn,r,m' is not implemented for regular points ('r')\n");
+    qh_errexit_rbox(qh, qh_ERRinput);
+  }
+
+  if (coincidenttotal == 0)
+    coincidenttotal= numpoints;
+
+  /* ============= print header with total points =============== */
+  if (issimplex || ismesh)
+    totpoints= numpoints;
+  else if (issimplex2)
+    totpoints= numpoints+dim+1;
+  else if (isregular) {
+    totpoints= numpoints;
+    if (dim == 2) {
+        if (islens)
+          totpoints += numpoints - 2;
+    }else if (dim == 3) {
+        if (islens)
+          totpoints += 2 * numpoints;
+      else if (isgap)
+        totpoints += 1 + numpoints;
+      else
+        totpoints += 2;
+    }
+  }else
+    totpoints= numpoints + isaxis;
+  totpoints += cubesize + diamondsize + addpoints;
+  totpoints += coincidentpoints*coincidenttotal;
+
+  /* ============= seed randoms =============== */
+  if (istime == 0) {
+    for (s=command; *s; s++) {
+      if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
+        i= 'x';
+      else
+        i= *s;
+      seed= 11*seed + i;
+    }
+  }else if (israndom) {
+    seed= (int)time(&timedata);
+    snprintf(seedbuf, sizeof(seedbuf) / sizeof(seedbuf[0]), " t%d", seed);  /* appends an extra t, not worth removing */
+    strncat(command, seedbuf, sizeof(command) - strlen(command) - 1);
+    t= strstr(command, " t ");
+    if (t)
+      strcpy(t+1, t+3); /* remove " t " */
+  } /* else, seed explicitly set to n */
+  qh_RANDOMseed_(qh, seed);
+
+  /* ============= print header =============== */
+
+  if (iscdd)
+      qh_fprintf_rbox(qh, qh->fout, 9391, "%s\nbegin\n        %d %d %s\n",
+      NOcommand ? "" : command,
+      totpoints, dim+1,
+      qh->rbox_isinteger ? "integer" : "real");
+  else if (NOcommand)
+      qh_fprintf_rbox(qh, qh->fout, 9392, "%d\n%d\n", dim, totpoints);
+  else
+      /* qh_fprintf_rbox special cases 9393 to append 'command' to the RboxPoints.comment() */
+      qh_fprintf_rbox(qh, qh->fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
+
+  /* ============= explicit points =============== */
+  if ((s= first_point)) {
+    while (s && *s) { /* 'P' */
+      count= 0;
+      if (iscdd)
+        qh_out1(qh, 1.0);
+      while (*++s) {
+        qh_out1(qh, qh_strtod(s, &s));
+        count++;
+        if (isspace(*s) || !*s)
+          break;
+        if (*s != ',') {
+          qh_fprintf_rbox(qh, qh->ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
+          qh_errexit_rbox(qh, qh_ERRinput);
+        }
+      }
+      if (count < dim) {
+        for (k=dim-count; k--; )
+          qh_out1(qh, 0.0);
+      }else if (count > dim) {
+        qh_fprintf_rbox(qh, qh->ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
+                  count, dim, s);
+        qh_errexit_rbox(qh, qh_ERRinput);
+      }
+      qh_fprintf_rbox(qh, qh->fout, 9394, "\n");
+      while ((s= strchr(s, 'P'))) {
+        if (isspace(s[-1]))
+          break;
+      }
+    }
+  }
+
+  /* ============= simplex distribution =============== */
+  if (issimplex+issimplex2) {
+    if (!(*simplex= (double *)qh_malloc( (size_t)(dim * (dim+1)) * sizeof(double)))) {
+      qh_fprintf_rbox(qh, qh->ferr, 6196, "rbox error: insufficient memory for simplex\n");
+      qh_errexit_rbox(qh, qh_ERRmem); /* qh_ERRmem */
+    }
+    simplexp= *simplex;
+    if (isregular) {
+      for (i=0; ifout, 9395, "\n");
+      }
+    }
+    for (j=0; jferr, 6197, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+      qh_errexit_rbox(qh, qh_ERRinput);
+    }
+    if (!isaxis || radius == 0.0) {
+      isaxis= 1;
+      radius= 1.0;
+    }
+    if (dim == 3) {
+      if (iscdd)
+        qh_out1(qh, 1.0);
+      qh_out3n(qh, 0.0, 0.0, -box);
+      if (!isgap) {
+        if (iscdd)
+          qh_out1(qh, 1.0);
+        qh_out3n(qh, 0.0, 0.0, box);
+      }
+    }
+    angle= 0.0;
+    anglediff= 2.0 * PI/numpoints;
+    for (i=0; i < numpoints; i++) {
+      angle += anglediff;
+      x= radius * cos(angle);
+      y= radius * sin(angle);
+      if (dim == 2) {
+        if (iscdd)
+          qh_out1(qh, 1.0);
+        qh_out2n(qh, x*box, y*box);
+      }else {
+        norm= sqrt(1.0 + x*x + y*y);
+        if (iscdd)
+          qh_out1(qh, 1.0);
+        qh_out3n(qh, box*x/norm, box*y/norm, box/norm);
+        if (isgap) {
+          x *= 1-gap;
+          y *= 1-gap;
+          norm= sqrt(1.0 + x*x + y*y);
+          if (iscdd)
+            qh_out1(qh, 1.0);
+          qh_out3n(qh, box*x/norm, box*y/norm, box/norm);
+        }
+      }
+    }
+  }
+  /* ============= regular points for 'r Ln D2' =============== */
+  else if (isregular && islens && dim == 2) {
+    double cos_0;
+
+    angle= lensangle;
+    anglediff= 2 * lensangle/(numpoints - 1);
+    cos_0= cos(lensangle);
+    for (i=0; i < numpoints; i++, angle -= anglediff) {
+      x= radius * sin(angle);
+      y= radius * (cos(angle) - cos_0);
+      if (iscdd)
+        qh_out1(qh, 1.0);
+      qh_out2n(qh, x*box, y*box);
+      if (i != 0 && i != numpoints - 1) {
+        if (iscdd)
+          qh_out1(qh, 1.0);
+        qh_out2n(qh, x*box, -y*box);
+      }
+    }
+  }
+  /* ============= regular points for 'r Ln D3' =============== */
+  else if (isregular && islens && dim != 2) {
+    if (dim != 3) {
+      qh_fprintf_rbox(qh, qh->ferr, 6198, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+      qh_errexit_rbox(qh, qh_ERRinput);
+    }
+    angle= 0.0;
+    anglediff= 2* PI/numpoints;
+    if (!isgap) {
+      isgap= 1;
+      gap= 0.5;
+    }
+    offset= sqrt(radius * radius - (1-gap)*(1-gap)) - lensbase;
+    for (i=0; i < numpoints; i++, angle += anglediff) {
+      x= cos(angle);
+      y= sin(angle);
+      if (iscdd)
+        qh_out1(qh, 1.0);
+      qh_out3n(qh, box*x, box*y, 0.0);
+      x *= 1-gap;
+      y *= 1-gap;
+      if (iscdd)
+        qh_out1(qh, 1.0);
+      qh_out3n(qh, box*x, box*y, box * offset);
+      if (iscdd)
+        qh_out1(qh, 1.0);
+      qh_out3n(qh, box*x, box*y, -box * offset);
+    }
+  }
+  /* ============= apex of 'Zn' distribution + gendim =============== */
+  else {
+    if (isaxis) {
+      gendim= dim-1;
+      if (iscdd)
+        qh_out1(qh, 1.0);
+      for (j=0; j < gendim; j++)
+        qh_out1(qh, 0.0);
+      qh_out1(qh, -box);
+      qh_fprintf_rbox(qh, qh->fout, 9398, "\n");
+    }else if (islens)
+      gendim= dim-1;
+    else
+      gendim= dim;
+    /* ============= generate random point in unit cube =============== */
+    for (i=0; i < numpoints; i++) {
+      norm= 0.0;
+      for (j=0; j < gendim; j++) {
+        randr= qh_RANDOMint;
+        coord[j]= 2.0 * randr/randmax - 1.0;
+        norm += coord[j] * coord[j];
+      }
+      norm= sqrt(norm);
+      /* ============= dim-1 point of 'Zn' distribution ========== */
+      if (isaxis) {
+        if (!isgap) {
+          isgap= 1;
+          gap= 1.0;
+        }
+        randr= qh_RANDOMint;
+        rangap= 1.0 - gap * randr/randmax;
+        factor= radius * rangap / norm;
+        for (j=0; jferr, 6199, "rbox error: spiral distribution is available only in 3d\n\n");
+          qh_errexit_rbox(qh, qh_ERRinput);
+        }
+        coord[0]= cos(2*PI*i/(numpoints - 1));
+        coord[1]= sin(2*PI*i/(numpoints - 1));
+        coord[2]= 2.0*(double)i/(double)(numpoints - 1) - 1.0;
+      /* ============= point of 's' distribution =============== */
+      }else if (issphere) {
+        factor= 1.0/norm;
+        if (iswidth) {
+          randr= qh_RANDOMint;
+          factor *= 1.0 - width * randr/randmax;
+        }
+        for (j=0; j randmax/2)
+          coord[dim-1]= -coord[dim-1];
+      /* ============= project 'Wn' point toward boundary =============== */
+      }else if (iswidth && !issphere) {
+        j= qh_RANDOMint % gendim;
+        if (coord[j] < 0)
+          coord[j]= -1.0 - coord[j] * width;
+        else
+          coord[j]= 1.0 - coord[j] * width;
+      }
+      /* ============= scale point to box =============== */
+      for (k=0; k=0; k--) {
+        if (j & ( 1 << k))
+          qh_out1(qh, cube);
+        else
+          qh_out1(qh, -cube);
+      }
+      qh_fprintf_rbox(qh, qh->fout, 9400, "\n");
+    }
+  }
+
+  /* ============= write diamond vertices =============== */
+  if (adddiamond) {
+    for (j=0; j=0; k--) {
+        if (j/2 != k)
+          qh_out1(qh, 0.0);
+        else if (j & 0x1)
+          qh_out1(qh, diamond);
+        else
+          qh_out1(qh, -diamond);
+      }
+      qh_fprintf_rbox(qh, qh->fout, 9401, "\n");
+    }
+  }
+
+  if (iscdd)
+    qh_fprintf_rbox(qh, qh->fout, 9402, "end\nhull\n");
+} /* rboxpoints2 */
+
+/*------------------------------------------------
+outxxx - output functions for qh_rboxpoints
+*/
+int qh_roundi(qhT *qh, double a) {
+  if (a < 0.0) {
+    if (a - 0.5 < INT_MIN) {
+      qh_fprintf_rbox(qh, qh->ferr, 6200, "rbox input error: negative coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      qh_errexit_rbox(qh, qh_ERRinput);
+    }
+    return (int)(a - 0.5);
+  }else {
+    if (a + 0.5 > INT_MAX) {
+      qh_fprintf_rbox(qh, qh->ferr, 6201, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      qh_errexit_rbox(qh, qh_ERRinput);
+    }
+    return (int)(a + 0.5);
+  }
+} /* qh_roundi */
+
+void qh_out1(qhT *qh, double a) {
+
+  if (qh->rbox_isinteger)
+    qh_fprintf_rbox(qh, qh->fout, 9403, "%d ", qh_roundi(qh, a+qh->rbox_out_offset));
+  else
+    qh_fprintf_rbox(qh, qh->fout, 9404, qh_REAL_1, a+qh->rbox_out_offset);
+} /* qh_out1 */
+
+void qh_out2n(qhT *qh, double a, double b) {
+
+  if (qh->rbox_isinteger)
+    qh_fprintf_rbox(qh, qh->fout, 9405, "%d %d\n", qh_roundi(qh, a+qh->rbox_out_offset), qh_roundi(qh, b+qh->rbox_out_offset));
+  else
+    qh_fprintf_rbox(qh, qh->fout, 9406, qh_REAL_2n, a+qh->rbox_out_offset, b+qh->rbox_out_offset);
+} /* qh_out2n */
+
+void qh_out3n(qhT *qh, double a, double b, double c) {
+
+  if (qh->rbox_isinteger)
+    qh_fprintf_rbox(qh, qh->fout, 9407, "%d %d %d\n", qh_roundi(qh, a+qh->rbox_out_offset), qh_roundi(qh, b+qh->rbox_out_offset), qh_roundi(qh, c+qh->rbox_out_offset));
+  else
+    qh_fprintf_rbox(qh, qh->fout, 9408, qh_REAL_3n, a+qh->rbox_out_offset, b+qh->rbox_out_offset, c+qh->rbox_out_offset);
+} /* qh_out3n */
+
+void qh_outcoord(qhT *qh, int iscdd, double *coord, int dim) {
+    double *p= coord;
+    int k;
+
+    if (iscdd)
+      qh_out1(qh, 1.0);
+    for (k=0; k < dim; k++)
+      qh_out1(qh, *(p++));
+    qh_fprintf_rbox(qh, qh->fout, 9396, "\n");
+} /* qh_outcoord */
+
+void qh_outcoincident(qhT *qh, int coincidentpoints, double radius, int iscdd, double *coord, int dim) {
+  double *p;
+  double randr, delta;
+  int i,k;
+  double randmax= qh_RANDOMmax;
+
+  for (i=0; ifout, 9410, "\n");
+  }
+} /* qh_outcoincident */
+
+/*------------------------------------------------
+   Only called from qh_rboxpoints2 or qh_fprintf_rbox
+   qh_fprintf_rbox is only called from qh_rboxpoints2
+   The largest exitcode is '255' for compatibility with exit()
+*/
+void qh_errexit_rbox(qhT *qh, int exitcode)
+{
+    longjmp(qh->rbox_errexit, exitcode);
+} /* qh_errexit_rbox */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.c
new file mode 100644
index 00000000000..edc9c2fb3a3
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.c
@@ -0,0 +1,727 @@
+/*
  ---------------------------------
+
+   stat_r.c
+   contains all statistics that are collected for qhull
+
+   see qh-stat_r.htm and stat_r.h
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/stat_r.c#9 $$Change: 3037 $
+   $DateTime: 2020/09/03 17:28:32 $$Author: bbarber $
+*/
+
+#include "qhull_ra.h"
+
+/*========== functions in alphabetic order ================*/
+
+/*---------------------------------
+
+  qh_allstatA()
+    define statistics in groups of 20
+
+  notes:
+    (otherwise, 'gcc -O2' uses too much memory)
+    uses qhstat.next
+*/
+void qh_allstatA(qhT *qh) {
+
+   /* zdef_(type,name,doc,average) */
+  zzdef_(zdoc, Zdoc2, "precision statistics", -1);
+  zdef_(zinc, Znewvertex, NULL, -1);
+  zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet", Znewvertex);
+  zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
+  zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
+  zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
+  zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
+
+  qh->qhstat.precision= qh->qhstat.next;  /* usually call qh_joggle_restart, printed if Q0 or QJn */
+  zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
+  zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
+  zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
+  zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
+  zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
+  zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
+  zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
+  zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
+  zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
+  zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
+  zzdef_(zinc, Zmultiridge, "dupridges with multiple neighbors", -1);
+  zzdef_(zinc, Zflipridge, "dupridges with flip facet into good neighbor", -1);
+  zzdef_(zinc, Zflipridge2, "dupridges with flip facet into good flip neighbor", -1);
+}
+void qh_allstatB(qhT *qh) {
+  zzdef_(zdoc, Zdoc1, "summary information", -1);
+  zdef_(zinc, Zvertices, "number of vertices in output", -1);
+  zdef_(zinc, Znumfacets, "number of facets in output", -1);
+  zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
+  zdef_(zinc, Znowsimplicial, "simplicial facets that were non-simplicial", -1);
+  zdef_(zinc, Znumridges, "number of ridges in output", -1);
+  zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
+  zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
+  zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
+  zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
+  zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
+  zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
+  zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
+  zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
+  zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
+  zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
+  zzdef_(zinc, Zsetplane, "facets created altogether", -1);
+  zdef_(zinc, Ztotridges, "ridges created altogether", -1);
+  zdef_(zinc, Zpostfacets, "facets before post merge", -1);
+  zdef_(zadd, Znummergetot, "average merges per facet (at most 511)", Znumfacets);
+  zdef_(zmax, Znummergemax, "  maximum merges for a facet (at most 511)", -1);
+  zdef_(zinc, Zangle, NULL, -1);
+  zdef_(wadd, Wangle, "average cosine (angle) of facet normals for all ridges", Zangle);
+  zdef_(wmax, Wanglemax, "  maximum cosine of facet normals (flatest) across a ridge", -1);
+  zdef_(wmin, Wanglemin, "  minimum cosine of facet normals (sharpest) across a ridge", -1);
+  zdef_(wadd, Wareatot, "total area of facets", -1);
+  zdef_(wmax, Wareamax, "  maximum facet area", -1);
+  zdef_(wmin, Wareamin, "  minimum facet area", -1);
+}
+void qh_allstatC(qhT *qh) {
+  zdef_(zdoc, Zdoc9, "build hull statistics", -1);
+  zzdef_(zinc, Zprocessed, "points processed", -1);
+  zzdef_(zinc, Zretry, "retries due to precision problems", -1);
+  zdef_(wmax, Wretrymax, "  max. random joggle", -1);
+  zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
+  zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
+  zdef_(zinc, Zinsidevisible, "  ave. visible facets without an horizon neighbor", Zprocessed);
+  zdef_(zadd, Zvisfacettot,  "  ave. facets deleted per iteration", Zprocessed);
+  zdef_(zmax, Zvisfacetmax,  "    maximum", -1);
+  zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
+  zdef_(zmax, Zvisvertexmax, "    maximum", -1);
+  zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
+  zdef_(zadd, Znewfacettot,  "ave. new or merged facets per iteration", Zprocessed);
+  zdef_(zmax, Znewfacetmax,  "    maximum (includes initial simplex)", -1);
+  zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
+  zdef_(wadd, Wnewbalance2, "  standard deviation", -1);
+  zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
+  zdef_(wadd, Wpbalance2, "  standard deviation", -1);
+  zdef_(zinc, Zpbalance,  "  count", -1);
+  zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
+  zdef_(zinc, Zdetfacetarea, "determinants for facet area", -1);
+  zdef_(zinc, Znoarea, "  determinants not computed because vertex too low", -1);
+  zdef_(zinc, Zdetsimplex, "determinants for initial hull or voronoi vertices", -1);
+  zdef_(zinc, Znotmax, "points ignored (!above max_outside)", -1);
+  zdef_(zinc, Zpinchedapex, "points ignored (pinched apex)", -1);
+  zdef_(zinc, Znotgood, "points ignored (!above a good facet)", -1);
+  zdef_(zinc, Znotgoodnew, "points ignored (didn't create a good new facet)", -1);
+  zdef_(zinc, Zgoodfacet, "good facets found", -1);
+  zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
+  zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
+  zzdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
+  zzdef_(zinc, Zcheckpart, "  ave. distance tests per check", Ztotcheck);
+}
+void qh_allstatD(qhT *qh) {
+  zdef_(zinc, Zvisit, "resets of visit_id", -1);
+  zdef_(zinc, Zvvisit, "  resets of vertex_visit", -1);
+  zdef_(zmax, Zvisit2max, "  max visit_id/2", -1);
+  zdef_(zmax, Zvvisit2max, "  max vertex_visit/2", -1);
+
+  zdef_(zdoc, Zdoc4, "partitioning statistics (see previous for outer planes)", -1);
+  zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
+  zdef_(zmax, Zdelvertexmax, "    maximum vertices deleted per iteration", -1);
+  zdef_(zinc, Zfindbest, "calls to findbest", -1);
+  zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
+  zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
+  zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
+  zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
+  zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
+  zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
+  zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
+  zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
+  zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
+  zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
+  zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
+  zdef_(zinc, Zfindjump,       " ave. clearly better", Zfindhorizon);
+  zdef_(zinc, Znewbesthorizon, " new bestfacets during qh_findbesthorizon", -1);
+  zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
+  zdef_(zinc, Zpartcorner, "  repartitioned coplanar points above a corner facet", -1);
+  zdef_(zinc, Zparthidden, "  repartitioned coplanar points above a hidden facet", -1);
+  zdef_(zinc, Zparttwisted, "  repartitioned coplanar points above a twisted facet", -1);
+}
+void qh_allstatE(qhT *qh) {
+  zdef_(zinc, Zpartinside, "inside points", -1);
+  zdef_(zinc, Zpartnear, "  near inside points kept with a facet", -1);
+  zdef_(zinc, Zcoplanarinside, "  inside points that were coplanar with a facet", -1);
+  zdef_(zinc, Zbestlower, "calls to findbestlower", -1);
+  zdef_(zinc, Zbestlowerv, "  with search of vertex neighbors", -1);
+  zdef_(zinc, Zbestlowerall, "  with rare search of all facets", -1);
+  zdef_(zmax, Zbestloweralln, "  facets per search of all facets", -1);
+  zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
+  zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
+  zdef_(zinc, Ztotpartition, "partitions of a point", -1);
+  zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
+  zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1);
+  zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1);
+  zdef_(zinc, Zdistgood, "distance tests for checking good point", -1);
+  zdef_(zinc, Zdistio, "distance tests for output", -1);
+  zdef_(zinc, Zdiststat, "distance tests for statistics", -1);
+  zzdef_(zinc, Zdistplane, "total number of distance tests", -1);
+  zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
+  zzdef_(zinc, Zpartcoplanar, "   distance tests for these partitions", -1);
+  zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
+}
+void qh_allstatE2(qhT *qh) {
+  zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
+  zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
+  zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
+  zdef_(zinc, Zhashridge, "total lookups of subridges (duplicates and boundary)", -1);
+  zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
+  zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
+  zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
+
+  zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
+  zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
+  zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
+  zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
+  zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
+  zzdef_(zinc, Zvertextests, "distance tests for vertex convexity", -1);
+  zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
+  zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
+  zdef_(zinc, Zcoplanarcentrum, "coplanar centrums or vertices in getmergeset", -1);
+  zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
+  zdef_(zinc, Zconcavecoplanarridge, "concave-coplanar ridges in getmergeset", -1);
+  zdef_(zinc, Ztwistedridge, "twisted ridges in getmergeset", -1);
+}
+void qh_allstatF(qhT *qh) {
+  zdef_(zdoc, Zdoc7, "statistics for merging", -1);
+  zdef_(zinc, Zpremergetot, "merge iterations", -1);
+  zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
+  zdef_(zadd, Zmergeinitmax, "  maximum", -1);
+  zdef_(zadd, Zmergesettot, "  ave. additional non-convex ridges per iteration", Zpremergetot);
+  zdef_(zadd, Zmergesetmax, "  maximum additional in one pass", -1);
+  zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
+  zdef_(zadd, Zmergesettot2, "  additional non-convex ridges", -1);
+  zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet (w/roundoff)", -1);
+  zdef_(wmin, Wminvertex, "max distance of vertex below facet (or roundoff)", -1);
+  zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
+  zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
+  zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
+  zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
+  zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
+  zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
+  zzdef_(zadd, Zcyclefacettot, "  ave. facets per cycle", Zcyclehorizon);
+  zdef_(zmax, Zcyclefacetmax, "  max. facets", -1);
+  zdef_(zinc, Zmergeintocoplanar, "new facets merged into coplanar horizon", -1);
+  zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
+  zdef_(zinc, Zmergenew, "new facets merged", -1);
+  zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
+  zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
+  zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
+  zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
+  zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
+  zdef_(zinc, Zredundant, "merges due to redundant neighbors", -1);
+  zdef_(zinc, Zredundantmerge, "  detected by qh_test_nonsimplicial_merge instead of qh_test_redundant_neighbors", -1);
+  zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1);
+}
+void qh_allstatG(qhT *qh) {
+  zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
+  zdef_(wadd, Wacoplanartot, "  average merge distance", Zacoplanar);
+  zdef_(wmax, Wacoplanarmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
+  zdef_(wadd, Wcoplanartot, "  average merge distance", Zcoplanar);
+  zdef_(wmax, Wcoplanarmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zconcave, "merges due to concave facets", -1);
+  zdef_(wadd, Wconcavetot, "  average merge distance", Zconcave);
+  zdef_(wmax, Wconcavemax, "  maximum merge distance", -1);
+  zdef_(zinc, Zconcavecoplanar, "merges due to concave-coplanar facets", -1);
+  zdef_(wadd, Wconcavecoplanartot, "  average merge distance", Zconcavecoplanar);
+  zdef_(wmax, Wconcavecoplanarmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
+  zdef_(wadd, Wavoidoldtot, "  average merge distance", Zavoidold);
+  zdef_(wmax, Wavoidoldmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
+  zdef_(wadd, Wdegentot, "  average merge distance", Zdegen);
+  zdef_(wmax, Wdegenmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
+  zdef_(wadd, Wflippedtot, "  average merge distance", Zflipped);
+  zdef_(wmax, Wflippedmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zduplicate, "merges due to dupridges", -1);
+  zdef_(wadd, Wduplicatetot, "  average merge distance", Zduplicate);
+  zdef_(wmax, Wduplicatemax, "  maximum merge distance", -1);
+  zdef_(zinc, Ztwisted, "merges due to twisted facets", -1);
+  zdef_(wadd, Wtwistedtot, "  average merge distance", Ztwisted);
+  zdef_(wmax, Wtwistedmax, "  maximum merge distance", -1);
+}
+void qh_allstatH(qhT *qh) {
+  zdef_(zdoc, Zdoc8, "statistics for vertex merges", -1);
+  zzdef_(zinc, Zpinchduplicate, "merge pinched vertices for a duplicate ridge", -1);
+  zzdef_(zinc, Zpinchedvertex, "merge pinched vertices for a dupridge", -1);
+  zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
+  zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
+  zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
+  zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
+  zdef_(zinc, Znewvertexridge, "  found new vertex in ridge", -1);
+  zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
+  zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
+  zdef_(zinc, Zdropdegen, "merge degenerate facets due to dropped neighbors", -1);
+  zdef_(zinc, Zdelfacetdup, "  facets deleted because of no neighbors", -1);
+  zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
+  zdef_(zinc, Zremvertexdel, "  deleted", -1);
+  zdef_(zinc, Zretryadd, "retry qh_addpoint after merge pinched vertex", -1);
+  zdef_(zadd, Zretryaddtot, "  tot. merge pinched vertex due to dupridge", -1);
+  zdef_(zmax, Zretryaddmax, "  max. merge pinched vertex for a qh_addpoint", -1);
+  zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
+  zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
+  zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
+  zdef_(zadd, Zintersecttot, "   ave. number found per vertex", Zintersect);
+  zdef_(zmax, Zintersectmax, "   max. found for a vertex", -1);
+  zdef_(zinc, Zvertexridge, NULL, -1);
+  zdef_(zadd, Zvertexridgetot, "  ave. number of ridges per tested vertex", Zvertexridge);
+  zdef_(zmax, Zvertexridgemax, "  max. number of ridges per tested vertex", -1);
+
+  zdef_(zdoc, Zdoc10, "memory usage statistics (in bytes)", -1);
+  zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
+  zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
+  zdef_(zadd, Zmempoints, "for input points, outside and coplanar sets, and qhT",-1);
+  zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
+} /* allstat */
+
+void qh_allstatI(qhT *qh) {
+  qh->qhstat.vridges= qh->qhstat.next; /* printed in qh_produce_output2 if non-zero Zridge or Zridgemid */
+  zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
+  zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
+  zzdef_(wadd, Wridge, "  ave. distance to ridge", Zridge);
+  zzdef_(wmax, Wridgemax, "  max. distance to ridge", -1);
+  zzdef_(zinc, Zridgemid, "bounded ridges", -1);
+  zzdef_(wadd, Wridgemid, "  ave. distance of midpoint to ridge", Zridgemid);
+  zzdef_(wmax, Wridgemidmax, "  max. distance of midpoint to ridge", -1);
+  zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
+  zzdef_(wadd, Wridgeok, "  ave. angle to ridge", Zridgeok);
+  zzdef_(wmax, Wridgeokmax, "  max. angle to ridge", -1);
+  zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
+  zzdef_(wadd, Wridge0, "  ave. angle to ridge", Zridge0);
+  zzdef_(wmax, Wridge0max, "  max. angle to ridge", -1);
+
+  zdef_(zdoc, Zdoc12, "Triangulation statistics ('Qt')", -1);
+  zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
+  zdef_(zadd, Ztricoplanartot, "  ave. new facets created (may be deleted)", Ztricoplanar);
+  zdef_(zmax, Ztricoplanarmax, "  max. new facets created", -1);
+  zdef_(zinc, Ztrinull, "null new facets deleted (duplicated vertex)", -1);
+  zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted (same vertices)", -1);
+  zdef_(zinc, Ztridegen, "degenerate new facets in output (same ridge)", -1);
+} /* allstat */
+
+/*---------------------------------
+
+  qh_allstatistics()
+    reset printed flag for all statistics
+*/
+void qh_allstatistics(qhT *qh) {
+  int i;
+
+  for(i=ZEND; i--; )
+    qh->qhstat.printed[i]= False;
+} /* allstatistics */
+
+#if qh_KEEPstatistics
+/*---------------------------------
+
+  qh_collectstatistics()
+    collect statistics for qh.facet_list
+
+*/
+void qh_collectstatistics(qhT *qh) {
+  facetT *facet, *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  realT dotproduct, dist;
+  int sizneighbors, sizridges, sizvertices, i;
+
+  qh->old_randomdist= qh->RANDOMdist;
+  qh->RANDOMdist= False;
+  zval_(Zmempoints)= qh->num_points * qh->normal_size + (int)sizeof(qhT);
+  zval_(Zmemfacets)= 0;
+  zval_(Zmemridges)= 0;
+  zval_(Zmemvertices)= 0;
+  zval_(Zangle)= 0;
+  wval_(Wangle)= 0.0;
+  zval_(Znumridges)= 0;
+  zval_(Znumfacets)= 0;
+  zval_(Znumneighbors)= 0;
+  zval_(Znumvertices)= 0;
+  zval_(Znumvneighbors)= 0;
+  zval_(Znummergetot)= 0;
+  zval_(Znummergemax)= 0;
+  zval_(Zvertices)= qh->num_vertices - qh_setsize(qh, qh->del_vertices);
+  if (qh->MERGING || qh->APPROXhull || qh->JOGGLEmax < REALmax/2)
+    wmax_(Wmaxoutside, qh->max_outside);
+  if (qh->MERGING)
+    wmin_(Wminvertex, qh->min_vertex);
+  if (!qh_checklists(qh, qh->facet_list)) {
+    qh_fprintf(qh, qh->ferr, 6373, "qhull internal error: qh_checklists failed on qh_collectstatistics\n");
+    if (!qh->ERREXITcalled)
+      qh_errexit(qh, qh_ERRqhull, NULL, NULL);
+  }
+  FORALLfacets
+    facet->seen= False;
+  if (qh->DELAUNAY) {
+    FORALLfacets {
+      if (facet->upperdelaunay != qh->UPPERdelaunay)
+        facet->seen= True; /* remove from angle statistics */
+    }
+  }
+  FORALLfacets {
+    if (facet->visible && qh->NEWfacets)
+      continue;
+    sizvertices= qh_setsize(qh, facet->vertices);
+    sizneighbors= qh_setsize(qh, facet->neighbors);
+    sizridges= qh_setsize(qh, facet->ridges);
+    zinc_(Znumfacets);
+    zadd_(Znumvertices, sizvertices);
+    zmax_(Zmaxvertices, sizvertices);
+    zadd_(Znumneighbors, sizneighbors);
+    zmax_(Zmaxneighbors, sizneighbors);
+    zadd_(Znummergetot, facet->nummerge);
+    i= facet->nummerge; /* avoid warnings */
+    zmax_(Znummergemax, i);
+    if (!facet->simplicial) {
+      if (sizvertices == qh->hull_dim) {
+        zinc_(Znowsimplicial);
+      }else {
+        zinc_(Znonsimplicial);
+      }
+    }
+    if (sizridges) {
+      zadd_(Znumridges, sizridges);
+      zmax_(Zmaxridges, sizridges);
+    }
+    zadd_(Zmemfacets, (int)sizeof(facetT) + qh->normal_size + 2*SETbasesize
+       + SETelemsize * (sizneighbors + sizvertices));
+    if (facet->ridges) {
+      zadd_(Zmemridges,
+        SETbasesize + SETelemsize * sizridges + sizridges *
+         ((int)sizeof(ridgeT) + SETbasesize + SETelemsize * (qh->hull_dim-1))/2);
+    }
+    if (facet->outsideset)
+      zadd_(Zmempoints, SETbasesize + SETelemsize * qh_setsize(qh, facet->outsideset));
+    if (facet->coplanarset)
+      zadd_(Zmempoints, SETbasesize + SETelemsize * qh_setsize(qh, facet->coplanarset));
+    if (facet->seen) /* Delaunay upper envelope */
+      continue;
+    facet->seen= True;
+    FOREACHneighbor_(facet) {
+      if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
+          || neighbor->seen || !facet->normal || !neighbor->normal)
+        continue;
+      dotproduct= qh_getangle(qh, facet->normal, neighbor->normal);
+      zinc_(Zangle);
+      wadd_(Wangle, dotproduct);
+      wmax_(Wanglemax, dotproduct)
+      wmin_(Wanglemin, dotproduct)
+    }
+    if (facet->normal) {
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdiststat);
+        qh_distplane(qh, vertex->point, facet, &dist);
+        wmax_(Wvertexmax, dist);
+        wmin_(Wvertexmin, dist);
+      }
+    }
+  }
+  FORALLvertices {
+    if (vertex->deleted)
+      continue;
+    zadd_(Zmemvertices, (int)sizeof(vertexT));
+    if (vertex->neighbors) {
+      sizneighbors= qh_setsize(qh, vertex->neighbors);
+      zadd_(Znumvneighbors, sizneighbors);
+      zmax_(Zmaxvneighbors, sizneighbors);
+      zadd_(Zmemvertices, (int)sizeof(vertexT) + SETelemsize * sizneighbors);
+    }
+  }
+  qh->RANDOMdist= qh->old_randomdist;
+} /* collectstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*---------------------------------
+
+  qh_initstatistics(qh)
+    initialize statistics
+
+  notes:
+    NOerrors -- qh_initstatistics can not use qh_errexit(), qh_fprintf, or qh.ferr
+    On first call, only qhmem.ferr is defined.  qh_memalloc is not setup.
+    Also invoked by QhullQh().
+*/
+void qh_initstatistics(qhT *qh) {
+  int i;
+  realT realx;
+  int intx;
+
+  qh_allstatistics(qh);
+  qh->qhstat.next= 0;
+  qh_allstatA(qh);
+  qh_allstatB(qh);
+  qh_allstatC(qh);
+  qh_allstatD(qh);
+  qh_allstatE(qh);
+  qh_allstatE2(qh);
+  qh_allstatF(qh);
+  qh_allstatG(qh);
+  qh_allstatH(qh);
+  qh_allstatI(qh);
+  if (qh->qhstat.next > (int)sizeof(qh->qhstat.id)) {
+    qh_fprintf_stderr(6184, "qhull internal error (qh_initstatistics): increase size of qhstat.id[].  qhstat.next %d should be <= sizeof(qh->qhstat.id) %d\n", 
+          qh->qhstat.next, (int)sizeof(qh->qhstat.id));
+#if 0 /* for locating error, Znumridges should be duplicated */
+    for(i=0; i < ZEND; i++) {
+      int j;
+      for(j=i+1; j < ZEND; j++) {
+        if (qh->qhstat.id[i] == qh->qhstat.id[j]) {
+          qh_fprintf_stderr(6185, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n",
+              qh->qhstat.id[i], i, j);
+        }
+      }
+    }
+#endif
+    qh_exit(qh_ERRqhull);  /* can not use qh_errexit() */
+  }
+  qh->qhstat.init[zinc].i= 0;
+  qh->qhstat.init[zadd].i= 0;
+  qh->qhstat.init[zmin].i= INT_MAX;
+  qh->qhstat.init[zmax].i= INT_MIN;
+  qh->qhstat.init[wadd].r= 0;
+  qh->qhstat.init[wmin].r= REALmax;
+  qh->qhstat.init[wmax].r= -REALmax;
+  for(i=0; i < ZEND; i++) {
+    if (qh->qhstat.type[i] > ZTYPEreal) {
+      realx= qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].r;
+      qh->qhstat.stats[i].r= realx;
+    }else if (qh->qhstat.type[i] != zdoc) {
+      intx= qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].i;
+      qh->qhstat.stats[i].i= intx;
+    }
+  }
+} /* initstatistics */
+
+/*---------------------------------
+
+  qh_newstats(qh )
+    returns True if statistics for zdoc
+
+  returns:
+    next zdoc
+*/
+boolT qh_newstats(qhT *qh, int idx, int *nextindex) {
+  boolT isnew= False;
+  int start, i;
+
+  if (qh->qhstat.type[qh->qhstat.id[idx]] == zdoc)
+    start= idx+1;
+  else
+    start= idx;
+  for(i= start; i < qh->qhstat.next && qh->qhstat.type[qh->qhstat.id[i]] != zdoc; i++) {
+    if (!qh_nostatistic(qh, qh->qhstat.id[i]) && !qh->qhstat.printed[qh->qhstat.id[i]])
+        isnew= True;
+  }
+  *nextindex= i;
+  return isnew;
+} /* newstats */
+
+/*---------------------------------
+
+  qh_nostatistic(qh, index )
+    true if no statistic to print
+*/
+boolT qh_nostatistic(qhT *qh, int i) {
+
+  if ((qh->qhstat.type[i] > ZTYPEreal
+       &&qh->qhstat.stats[i].r == qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].r)
+      || (qh->qhstat.type[i] < ZTYPEreal
+          &&qh->qhstat.stats[i].i == qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].i))
+    return True;
+  return False;
+} /* nostatistic */
+
+#if qh_KEEPstatistics
+/*---------------------------------
+
+  qh_printallstatistics(qh, fp, string )
+    print all statistics with header 'string'
+*/
+void qh_printallstatistics(qhT *qh, FILE *fp, const char *string) {
+
+  qh_allstatistics(qh);
+  qh_collectstatistics(qh);
+  qh_printstatistics(qh, fp, string);
+  qh_memstatistics(qh, fp);
+}
+
+
+/*---------------------------------
+
+  qh_printstatistics(qh, fp, string )
+    print statistics to a file with header 'string'
+    skips statistics with qhstat.printed[] (reset with qh_allstatistics)
+
+  see:
+    qh_printallstatistics()
+*/
+void qh_printstatistics(qhT *qh, FILE *fp, const char *string) {
+  int i, k;
+  realT ave; /* ignored */
+
+  if (qh->num_points != qh->num_vertices || zval_(Zpbalance) == 0) {
+    wval_(Wpbalance)= 0.0;
+    wval_(Wpbalance2)= 0.0;
+  }else
+    wval_(Wpbalance2)= qh_stddev(qh, zval_(Zpbalance), wval_(Wpbalance),
+                                 wval_(Wpbalance2), &ave);
+  if (zval_(Zprocessed) == 0)
+    wval_(Wnewbalance2)= 0.0;
+  else
+    wval_(Wnewbalance2)= qh_stddev(qh, zval_(Zprocessed), wval_(Wnewbalance),
+                                 wval_(Wnewbalance2), &ave);
+  qh_fprintf(qh, fp, 9350, "\n\
+%s\n\
+qhull invoked by: %s | %s\n  %s with options:\n%s\n", 
+    string, qh->rbox_command, qh->qhull_command, qh_version, qh->qhull_options);
+
+  qh_fprintf(qh, fp, 9351, "\nprecision constants:\n\
+ %6.2g max. abs. coordinate in the (transformed) input ('Qbd:n')\n\
+ %6.2g max. roundoff error for distance computation ('En')\n\
+ %6.2g max. roundoff error for angle computations\n\
+ %6.2g min. distance for outside points ('Wn')\n\
+ %6.2g min. distance for visible facets ('Vn')\n\
+ %6.2g max. distance for coplanar facets ('Un')\n\
+ %6.2g max. facet width for recomputing centrum and area\n\
+",
+  qh->MAXabs_coord, qh->DISTround, qh->ANGLEround, qh->MINoutside,
+        qh->MINvisible, qh->MAXcoplanar, qh->WIDEfacet);
+  if (qh->KEEPnearinside)
+    qh_fprintf(qh, fp, 9352, "\
+ %6.2g max. distance for near-inside points\n", qh->NEARinside);
+  if (qh->premerge_cos < REALmax/2) qh_fprintf(qh, fp, 9353, "\
+ %6.2g max. cosine for pre-merge angle\n", qh->premerge_cos);
+  if (qh->PREmerge) qh_fprintf(qh, fp, 9354, "\
+ %6.2g radius of pre-merge centrum\n", qh->premerge_centrum);
+  if (qh->postmerge_cos < REALmax/2) qh_fprintf(qh, fp, 9355, "\
+ %6.2g max. cosine for post-merge angle\n", qh->postmerge_cos);
+  if (qh->POSTmerge) qh_fprintf(qh, fp, 9356, "\
+ %6.2g radius of post-merge centrum\n", qh->postmerge_centrum);
+  qh_fprintf(qh, fp, 9357, "\
+ %6.2g max. distance for merging two simplicial facets\n\
+ %6.2g max. roundoff error for arithmetic operations\n\
+ %6.2g min. denominator for division\n\
+  zero diagonal for Gauss: ", qh->ONEmerge, REALepsilon, qh->MINdenom);
+  for(k=0; k < qh->hull_dim; k++)
+    qh_fprintf(qh, fp, 9358, "%6.2e ", qh->NEARzero[k]);
+  qh_fprintf(qh, fp, 9359, "\n\n");
+  for(i=0 ; i < qh->qhstat.next; )
+    qh_printstats(qh, fp, i, &i);
+} /* printstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*---------------------------------
+
+  qh_printstatlevel(qh, fp, id )
+    print level information for a statistic
+
+  notes:
+    nop if id >= ZEND, printed, or same as initial value
+*/
+void qh_printstatlevel(qhT *qh, FILE *fp, int id) {
+
+  if (id >= ZEND || qh->qhstat.printed[id])
+    return;
+  if (qh->qhstat.type[id] == zdoc) {
+    qh_fprintf(qh, fp, 9360, "%s\n", qh->qhstat.doc[id]);
+    return;
+  }
+  if (qh_nostatistic(qh, id) || !qh->qhstat.doc[id])
+    return;
+  qh->qhstat.printed[id]= True;
+  if (qh->qhstat.count[id] != -1
+      && qh->qhstat.stats[(unsigned char)(qh->qhstat.count[id])].i == 0)
+    qh_fprintf(qh, fp, 9361, " *0 cnt*");
+  else if (qh->qhstat.type[id] >= ZTYPEreal && qh->qhstat.count[id] == -1)
+    qh_fprintf(qh, fp, 9362, "%7.2g", qh->qhstat.stats[id].r);
+  else if (qh->qhstat.type[id] >= ZTYPEreal && qh->qhstat.count[id] != -1)
+    qh_fprintf(qh, fp, 9363, "%7.2g", qh->qhstat.stats[id].r/ qh->qhstat.stats[(unsigned char)(qh->qhstat.count[id])].i);
+  else if (qh->qhstat.type[id] < ZTYPEreal && qh->qhstat.count[id] == -1)
+    qh_fprintf(qh, fp, 9364, "%7d", qh->qhstat.stats[id].i);
+  else if (qh->qhstat.type[id] < ZTYPEreal && qh->qhstat.count[id] != -1)
+    qh_fprintf(qh, fp, 9365, "%7.3g", (realT) qh->qhstat.stats[id].i / qh->qhstat.stats[(unsigned char)(qh->qhstat.count[id])].i);
+  qh_fprintf(qh, fp, 9366, " %s\n", qh->qhstat.doc[id]);
+} /* printstatlevel */
+
+
+/*---------------------------------
+
+  qh_printstats(qh, fp, index, nextindex )
+    print statistics for a zdoc group
+
+  returns:
+    next zdoc if non-null
+*/
+void qh_printstats(qhT *qh, FILE *fp, int idx, int *nextindex) {
+  int j, nexti;
+
+  if (qh_newstats(qh, idx, &nexti)) {
+    qh_fprintf(qh, fp, 9367, "\n");
+    for (j=idx; jqhstat.id[j]);
+  }
+  if (nextindex)
+    *nextindex= nexti;
+} /* printstats */
+
+#if qh_KEEPstatistics
+
+/*---------------------------------
+
+  qh_stddev(qh, num, tot, tot2, ave )
+    compute the standard deviation and average from statistics
+
+    tot2 is the sum of the squares
+  notes:
+    computes r.m.s.:
+      (x-ave)^2
+      == x^2 - 2x tot/num +   (tot/num)^2
+      == tot2 - 2 tot tot/num + tot tot/num
+      == tot2 - tot ave
+*/
+realT qh_stddev(qhT *qh, int num, realT tot, realT tot2, realT *ave) {
+  realT stddev;
+
+  if (num <= 0) {
+    qh_fprintf(qh, qh->ferr, 7101, "qhull warning (qh_stddev): expecting num > 0.  Got num %d, tot %4.4g, tot2 %4.4g.  Returning 0.0\n",
+      num, tot, tot2);
+    return 0.0;
+  }
+  *ave= tot/num;
+  stddev= sqrt(fabs(tot2/num - *ave * *ave));
+  return stddev;
+} /* stddev */
+#else
+realT qh_stddev(qhT *qh, int num, realT tot, realT tot2, realT *ave) { /* for qhull_r-exports.def */
+  QHULL_UNUSED(qh)
+  QHULL_UNUSED(num)
+  QHULL_UNUSED(tot)
+  QHULL_UNUSED(tot2)
+  QHULL_UNUSED(ave)
+
+  return 0.0;
+}
+#endif /* qh_KEEPstatistics */
+
+#if !qh_KEEPstatistics
+void    qh_collectstatistics(qhT *qh) {}
+void    qh_printallstatistics(qhT *qh, FILE *fp, const char *string) {}
+void    qh_printstatistics(qhT *qh, FILE *fp, const char *string) {}
+#endif
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.h
new file mode 100644
index 00000000000..41b6e5171dd
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/stat_r.h
@@ -0,0 +1,563 @@
+/*
  ---------------------------------
+
+   stat_r.h
+     contains all statistics that are collected for qhull
+
+   see qh-stat_r.htm and stat_r.c
+
+   Copyright (c) 1993-2020 The Geometry Center.
+   $Id: //main/2019/qhull/src/libqhull_r/stat_r.h#4 $$Change: 2953 $
+   $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
+
+   recompile qhull if you change this file
+
+   Integer statistics are Z* while real statistics are W*.
+
+   define MAYdebugx to call a routine at every statistic event
+
+*/
+
+#ifndef qhDEFstat
+#define qhDEFstat 1
+
+/* Depends on realT.  Do not include "libqhull_r" to avoid circular dependency */
+
+#ifndef DEFqhT
+#define DEFqhT 1
+typedef struct qhT qhT;         /* Defined by libqhull_r.h */
+#endif
+
+#ifndef DEFqhstatT
+#define DEFqhstatT 1
+typedef struct qhstatT qhstatT; /* Defined here */
+#endif
+
+/*---------------------------------
+
+  qh_KEEPstatistics
+    0 turns off statistic reporting and gathering (except zzdef/zzinc/zzadd/zzval/wwval)
+
+  set qh_KEEPstatistics in user_r.h to 0 to turn off statistics
+*/
+#ifndef qh_KEEPstatistics
+#define qh_KEEPstatistics 1
+#endif
+
+/*---------------------------------
+
+  Zxxx for integers, Wxxx for reals
+
+  notes:
+    be sure that all statistics are defined in stat_r.c
+      otherwise initialization may core dump
+    can pick up all statistics by:
+      grep '[zw].*_[(][ZW]' *.c >z.x
+    remove trailers with query">-
+    remove leaders with  query-replace-regexp [ ^I]+  (
+*/
+#if qh_KEEPstatistics
+enum qh_statistics {     /* alphabetical after Z/W */
+    Zacoplanar,
+    Wacoplanarmax,
+    Wacoplanartot,
+    Zangle,
+    Wangle,
+    Wanglemax,
+    Wanglemin,
+    Zangletests,
+    Wareatot,
+    Wareamax,
+    Wareamin,
+    Zavoidold,
+    Wavoidoldmax,
+    Wavoidoldtot,
+    Zback0,
+    Zbestcentrum,
+    Zbestdist,
+    Zbestlower,
+    Zbestlowerall,
+    Zbestloweralln,
+    Zbestlowerv,
+    Zcentrumtests,
+    Zcheckpart,
+    Zcomputefurthest,
+    Zconcave,
+    Wconcavemax,
+    Wconcavetot,
+    Zconcavecoplanar,
+    Wconcavecoplanarmax,
+    Wconcavecoplanartot,
+    Zconcavecoplanarridge,
+    Zconcaveridge,
+    Zconcaveridges,
+    Zcoplanar,
+    Wcoplanarmax,
+    Wcoplanartot,
+    Zcoplanarangle,
+    Zcoplanarcentrum,
+    Zcoplanarhorizon,
+    Zcoplanarinside,
+    Zcoplanarpart,
+    Zcoplanarridges,
+    Wcpu,
+    Zcyclefacetmax,
+    Zcyclefacettot,
+    Zcyclehorizon,
+    Zcyclevertex,
+    Zdegen,
+    Wdegenmax,
+    Wdegentot,
+    Zdegenvertex,
+    Zdelfacetdup,
+    Zdelridge,
+    Zdelvertextot,
+    Zdelvertexmax,
+    Zdetfacetarea,
+    Zdetsimplex,
+    Zdistcheck,
+    Zdistconvex,
+    Zdistgood,
+    Zdistio,
+    Zdistplane,
+    Zdiststat,
+    Zdistvertex,
+    Zdistzero,
+    Zdoc1,
+    Zdoc2,
+    Zdoc3,
+    Zdoc4,
+    Zdoc5,
+    Zdoc6,
+    Zdoc7,
+    Zdoc8,
+    Zdoc9,
+    Zdoc10,
+    Zdoc11,
+    Zdoc12,
+    Zdropdegen,
+    Zdropneighbor,
+    Zdupflip,
+    Zduplicate,
+    Wduplicatemax,
+    Wduplicatetot,
+    Zdupsame,
+    Zflipped,
+    Wflippedmax,
+    Wflippedtot,
+    Zflippedfacets,
+    Zflipridge,
+    Zflipridge2,
+    Zfindbest,
+    Zfindbestmax,
+    Zfindbesttot,
+    Zfindcoplanar,
+    Zfindfail,
+    Zfindhorizon,
+    Zfindhorizonmax,
+    Zfindhorizontot,
+    Zfindjump,
+    Zfindnew,
+    Zfindnewmax,
+    Zfindnewtot,
+    Zfindnewjump,
+    Zfindnewsharp,
+    Zgauss0,
+    Zgoodfacet,
+    Zhashlookup,
+    Zhashridge,
+    Zhashridgetest,
+    Zhashtests,
+    Zinsidevisible,
+    Zintersect,
+    Zintersectfail,
+    Zintersectmax,
+    Zintersectnum,
+    Zintersecttot,
+    Zmaxneighbors,
+    Wmaxout,
+    Wmaxoutside,
+    Zmaxridges,
+    Zmaxvertex,
+    Zmaxvertices,
+    Zmaxvneighbors,
+    Zmemfacets,
+    Zmempoints,
+    Zmemridges,
+    Zmemvertices,
+    Zmergeflipdup,
+    Zmergehorizon,
+    Zmergeinittot,
+    Zmergeinitmax,
+    Zmergeinittot2,
+    Zmergeintocoplanar,
+    Zmergeintohorizon,
+    Zmergenew,
+    Zmergesettot,
+    Zmergesetmax,
+    Zmergesettot2,
+    Zmergesimplex,
+    Zmergevertex,
+    Wmindenom,
+    Wminvertex,
+    Zminnorm,
+    Zmultiridge,
+    Znearlysingular,
+    Zredundant,
+    Wnewbalance,
+    Wnewbalance2,
+    Znewbesthorizon,
+    Znewfacettot,
+    Znewfacetmax,
+    Znewvertex,
+    Wnewvertex,
+    Wnewvertexmax,
+    Znewvertexridge,
+    Znoarea,
+    Znonsimplicial,
+    Znowsimplicial,
+    Znotgood,
+    Znotgoodnew,
+    Znotmax,
+    Znumfacets,
+    Znummergemax,
+    Znummergetot,
+    Znumneighbors,
+    Znumridges,
+    Znumvertices,
+    Znumvisibility,
+    Znumvneighbors,
+    Zonehorizon,
+    Zpartangle,
+    Zpartcoplanar,
+    Zpartcorner,
+    Zparthidden,
+    Zpartinside,
+    Zpartition,
+    Zpartitionall,
+    Zpartnear,
+    Zparttwisted,
+    Zpbalance,
+    Wpbalance,
+    Wpbalance2,
+    Zpinchduplicate,
+    Zpinchedapex,
+    Zpinchedvertex,
+    Zpostfacets,
+    Zpremergetot,
+    Zprocessed,
+    Zremvertex,
+    Zremvertexdel,
+    Zredundantmerge,
+    Zrenameall,
+    Zrenamepinch,
+    Zrenameshare,
+    Zretry,
+    Wretrymax,
+    Zretryadd,
+    Zretryaddmax,
+    Zretryaddtot,
+    Zridge,
+    Wridge,
+    Wridgemax,
+    Zridge0,
+    Wridge0,
+    Wridge0max,
+    Zridgemid,
+    Wridgemid,
+    Wridgemidmax,
+    Zridgeok,
+    Wridgeok,
+    Wridgeokmax,
+    Zsearchpoints,
+    Zsetplane,
+    Ztestvneighbor,
+    Ztotcheck,
+    Ztothorizon,
+    Ztotmerge,
+    Ztotpartcoplanar,
+    Ztotpartition,
+    Ztotridges,
+    Ztotvertices,
+    Ztotvisible,
+    Ztricoplanar,
+    Ztricoplanarmax,
+    Ztricoplanartot,
+    Ztridegen,
+    Ztrimirror,
+    Ztrinull,
+    Ztwisted,
+    Wtwistedtot,
+    Wtwistedmax,
+    Ztwistedridge,
+    Zvertextests,
+    Wvertexmax,
+    Wvertexmin,
+    Zvertexridge,
+    Zvertexridgetot,
+    Zvertexridgemax,
+    Zvertices,
+    Zvisfacettot,
+    Zvisfacetmax,
+    Zvisit,
+    Zvisit2max,
+    Zvisvertextot,
+    Zvisvertexmax,
+    Zvvisit,
+    Zvvisit2max,
+    Zwidefacet,
+    Zwidevertices,
+    ZEND};
+
+/*---------------------------------
+
+  Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
+
+  notes:
+    be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
+*/
+#else
+enum qh_statistics {     /* for zzdef etc. macros */
+  Zback0,
+  Zbestdist,
+  Zcentrumtests,
+  Zcheckpart,
+  Zconcaveridges,
+  Zcoplanarhorizon,
+  Zcoplanarpart,
+  Zcoplanarridges,
+  Zcyclefacettot,
+  Zcyclehorizon,
+  Zdelvertextot,
+  Zdistcheck,
+  Zdistconvex,
+  Zdistplane,
+  Zdistzero,
+  Zdoc1,
+  Zdoc2,
+  Zdoc3,
+  Zdoc11,
+  Zflippedfacets,
+  Zflipridge,
+  Zflipridge2,
+  Zgauss0,
+  Zminnorm,
+  Zmultiridge,
+  Znearlysingular,
+  Wnewvertexmax,
+  Znumvisibility,
+  Zpartcoplanar,
+  Zpartition,
+  Zpartitionall,
+  Zpinchduplicate,
+  Zpinchedvertex,
+  Zprocessed,
+  Zretry,
+  Zridge,
+  Wridge,
+  Wridgemax,
+  Zridge0,
+  Wridge0,
+  Wridge0max,
+  Zridgemid,
+  Wridgemid,
+  Wridgemidmax,
+  Zridgeok,
+  Wridgeok,
+  Wridgeokmax,
+  Zsetplane,
+  Ztotcheck,
+  Ztotmerge,
+  Zvertextests,
+  ZEND};
+#endif
+
+/*---------------------------------
+
+  ztype
+    the type of a statistic sets its initial value.
+
+  notes:
+    The type should be the same as the macro for collecting the statistic
+*/
+enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
+
+/*========== macros and constants =============*/
+
+/*----------------------------------
+
+  MAYdebugx
+    define as maydebug() to be called frequently for error trapping
+*/
+#define MAYdebugx
+
+/*----------------------------------
+
+  zzdef_, zdef_( type, name, doc, -1)
+    define a statistic (assumes 'qhstat.next= 0;')
+
+  zdef_( type, name, doc, count)
+    define an averaged statistic
+    printed as name/count
+*/
+#define zzdef_(stype,name,string,cnt) qh->qhstat.id[qh->qhstat.next++]=name; \
+   qh->qhstat.doc[name]= string; qh->qhstat.count[name]= cnt; qh->qhstat.type[name]= stype
+#if qh_KEEPstatistics
+#define zdef_(stype,name,string,cnt) qh->qhstat.id[qh->qhstat.next++]=name; \
+   qh->qhstat.doc[name]= string; qh->qhstat.count[name]= cnt; qh->qhstat.type[name]= stype
+#else
+#define zdef_(type,name,doc,count)
+#endif
+
+/*----------------------------------
+
+  zzinc_( name ), zinc_( name)
+    increment an integer statistic
+*/
+#define zzinc_(id) {MAYdebugx; qh->qhstat.stats[id].i++;}
+#if qh_KEEPstatistics
+#define zinc_(id) {MAYdebugx; qh->qhstat.stats[id].i++;}
+#else
+#define zinc_(id) {}
+#endif
+
+/*----------------------------------
+
+  zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
+    add value to an integer or real statistic
+*/
+#define zzadd_(id, val) {MAYdebugx; qh->qhstat.stats[id].i += (val);}
+#define wwadd_(id, val) {MAYdebugx; qh->qhstat.stats[id].r += (val);}
+#if qh_KEEPstatistics
+#define zadd_(id, val) {MAYdebugx; qh->qhstat.stats[id].i += (val);}
+#define wadd_(id, val) {MAYdebugx; qh->qhstat.stats[id].r += (val);}
+#else
+#define zadd_(id, val) {}
+#define wadd_(id, val) {}
+#endif
+
+/*----------------------------------
+
+  zzval_( name ), zval_( name ), wwval_( name )
+    set or return value of a statistic
+*/
+#define zzval_(id) ((qh->qhstat.stats[id]).i)
+#define wwval_(id) ((qh->qhstat.stats[id]).r)
+#if qh_KEEPstatistics
+#define zval_(id) ((qh->qhstat.stats[id]).i)
+#define wval_(id) ((qh->qhstat.stats[id]).r)
+#else
+#define zval_(id) qh->qhstat.tempi
+#define wval_(id) qh->qhstat.tempr
+#endif
+
+/*----------------------------------
+
+  zmax_( id, val ), wmax_( id, value )
+    maximize id with val
+*/
+#define wwmax_(id, val) {MAYdebugx; maximize_(qh->qhstat.stats[id].r,(val));}
+#if qh_KEEPstatistics
+#define zmax_(id, val) {MAYdebugx; maximize_(qh->qhstat.stats[id].i,(val));}
+#define wmax_(id, val) {MAYdebugx; maximize_(qh->qhstat.stats[id].r,(val));}
+#else
+#define zmax_(id, val) {}
+#define wmax_(id, val) {}
+#endif
+
+/*----------------------------------
+
+  zmin_( id, val ), wmin_( id, value )
+    minimize id with val
+*/
+#if qh_KEEPstatistics
+#define zmin_(id, val) {MAYdebugx; minimize_(qh->qhstat.stats[id].i,(val));}
+#define wmin_(id, val) {MAYdebugx; minimize_(qh->qhstat.stats[id].r,(val));}
+#else
+#define zmin_(id, val) {}
+#define wmin_(id, val) {}
+#endif
+
+/*================== stat_r.h types ==============*/
+
+
+/*----------------------------------
+
+  intrealT
+    union of integer and real, used for statistics
+*/
+typedef union intrealT intrealT;    /* union of int and realT */
+union intrealT {
+    int i;
+    realT r;
+};
+
+/*----------------------------------
+
+  qhstat
+    Data structure for statistics, similar to qh and qhrbox
+
+    Allocated as part of qhT (libqhull_r.h)
+*/
+
+struct qhstatT {
+  intrealT   stats[ZEND];     /* integer and real statistics */
+  unsigned char id[ZEND+10];  /* id's in print order */
+  const char *doc[ZEND];      /* array of documentation strings */
+  short int  count[ZEND];     /* -1 if none, else index of count to use */
+  char       type[ZEND];      /* type, see ztypes above */
+  char       printed[ZEND];   /* true, if statistic has been printed */
+  intrealT   init[ZTYPEend];  /* initial values by types, set initstatistics */
+
+  int        next;            /* next index for zdef_ */
+  int        precision;       /* index for precision problems, printed on qh_errexit and qh_produce_output2/Q0/QJn */
+  int        vridges;         /* index for Voronoi ridges, printed on qh_produce_output2 */
+  int        tempi;
+  realT      tempr;
+};
+
+/*========== function prototypes ===========*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    qh_allstatA(qhT *qh);
+void    qh_allstatB(qhT *qh);
+void    qh_allstatC(qhT *qh);
+void    qh_allstatD(qhT *qh);
+void    qh_allstatE(qhT *qh);
+void    qh_allstatE2(qhT *qh);
+void    qh_allstatF(qhT *qh);
+void    qh_allstatG(qhT *qh);
+void    qh_allstatH(qhT *qh);
+void    qh_allstatI(qhT *qh);
+void    qh_allstatistics(qhT *qh);
+void    qh_collectstatistics(qhT *qh);
+void    qh_initstatistics(qhT *qh);
+boolT   qh_newstats(qhT *qh, int idx, int *nextindex);
+boolT   qh_nostatistic(qhT *qh, int i);
+void    qh_printallstatistics(qhT *qh, FILE *fp, const char *string);
+void    qh_printstatistics(qhT *qh, FILE *fp, const char *string);
+void    qh_printstatlevel(qhT *qh, FILE *fp, int id);
+void    qh_printstats(qhT *qh, FILE *fp, int idx, int *nextindex);
+realT   qh_stddev(qhT *qh, int num, realT tot, realT tot2, realT *ave);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif   /* qhDEFstat */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.c
new file mode 100644
index 00000000000..70eab8b156e
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.c
@@ -0,0 +1,617 @@
+/*
  ---------------------------------
+
+   user_r.c
+   user redefinable functions
+
+   see user2_r.c for qh_fprintf, qh_malloc, qh_free
+
+   see README.txt  see COPYING.txt for copyright information.
+
+   see libqhull_r.h for data structures, macros, and user-callable functions.
+
+   see user_eg_r.c, user_eg2_r.c, and unix_r.c for examples.
+
+   see user_r.h for user-definable constants
+
+      use qh_NOmem in mem_r.h to turn off memory management
+      use qh_NOmerge in user_r.h to turn off facet merging
+      set qh_KEEPstatistics in user_r.h to 0 to turn off statistics
+
+   This is unsupported software.  You're welcome to make changes,
+   but you're on your own if something goes wrong.  Use 'Tc' to
+   check frequently.  Usually qhull will report an error if
+   a data structure becomes inconsistent.  If so, it also reports
+   the last point added to the hull, e.g., 102.  You can then trace
+   the execution of qhull with "T4P102".
+
+   Please report any errors that you fix to qhull@qhull.org
+
+   Qhull-template is a template for calling qhull from within your application
+
+   if you recompile and load this module, then user.o will not be loaded
+   from qhull.a
+
+   you can add additional quick allocation sizes in qh_user_memsizes
+
+   if the other functions here are redefined to not use qh_print...,
+   then io.o will not be loaded from qhull.a.  See user_eg_r.c for an
+   example.  We recommend keeping io.o for the extra debugging
+   information it supplies.
+*/
+
+#include "qhull_ra.h"
+
+#include 
+
+/*---------------------------------
+
+  Qhull-template
+    Template for calling qhull from inside your program
+
+  returns:
+    exit code(see qh_ERR... in libqhull_r.h)
+    all memory freed
+
+  notes:
+    This can be called any number of times.
+*/
+#if 0
+{
+  int dim;                  /* dimension of points */
+  int numpoints;            /* number of points */
+  coordT *points;           /* array of coordinates for each point */
+  boolT ismalloc;           /* True if qhull should free points in qh_freeqhull() or reallocation */
+  char flags[]= "qhull Tv"; /* option flags for qhull, see html/qh-quick.htm */
+  FILE *outfile= stdout;    /* output from qh_produce_output
+                               use NULL to skip qh_produce_output */
+  FILE *errfile= stderr;    /* error messages from qhull code */
+  int exitcode;             /* 0 if no error from qhull */
+  facetT *facet;            /* set by FORALLfacets */
+  int curlong, totlong;     /* memory remaining after qh_memfreeshort */
+
+  qhT qh_qh;                /* Qhull's data structure.  First argument of most calls */
+  qhT *qh= &qh_qh;          /* Alternatively -- qhT *qh= (qhT *)malloc(sizeof(qhT)) */
+
+  QHULL_LIB_CHECK /* Check for compatible library */
+
+  qh_zero(qh, errfile);
+
+  /* initialize dim, numpoints, points[], ismalloc here */
+  exitcode= qh_new_qhull(qh, dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile);
+  if (!exitcode) {                  /* if no error */
+    /* 'qh->facet_list' contains the convex hull */
+    FORALLfacets {
+       /* ... your code ... */
+    }
+  }
+  qh_freeqhull(qh, !qh_ALL);
+  qh_memfreeshort(qh, &curlong, &totlong);
+  if (curlong || totlong)
+    qh_fprintf(qh, errfile, 7079, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong);
+}
+#endif
+
+/*---------------------------------
+
+  qh_new_qhull(qh, dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
+    Run qhull
+    Before first call, either call qh_zero(qh, errfile), or set qh to all zero.
+
+  returns:
+    results in qh
+    exitcode (0 if no errors).
+
+  notes:
+    do not modify points until finished with results.
+      The qhull data structure contains pointers into the points array.
+    do not call qhull functions before qh_new_qhull().
+      The qhull data structure is not initialized until qh_new_qhull().
+    do not call qh_init_A (global_r.c)
+
+    Default errfile is stderr, outfile may be null
+    qhull_cmd must start with "qhull "
+    projects points to a new point array for Delaunay triangulations ('d' and 'v')
+    transforms points into a new point array for halfspace intersection ('H')
+
+  see:
+    Qhull-template at the beginning of this file.
+    An example of using qh_new_qhull is user_eg_r.c
+*/
+int qh_new_qhull(qhT *qh, int dim, int numpoints, coordT *points, boolT ismalloc,
+                char *qhull_cmd, FILE *outfile, FILE *errfile) {
+  /* gcc may issue a "might be clobbered" warning for dim, points, and ismalloc [-Wclobbered].
+     These parameters are not referenced after a longjmp() and hence not clobbered.
+     See http://stackoverflow.com/questions/7721854/what-sense-do-these-clobbered-variable-warnings-make */
+  int exitcode, hulldim;
+  boolT new_ismalloc;
+  coordT *new_points;
+
+  if(!errfile){
+    errfile= stderr;
+  }
+  if (!qh->qhmem.ferr) {
+    qh_meminit(qh, errfile);
+  } else {
+    qh_memcheck(qh);
+  }
+  if (strncmp(qhull_cmd, "qhull ", (size_t)6) && strcmp(qhull_cmd, "qhull") != 0) {
+    qh_fprintf(qh, errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \" or set to \"qhull\"\n");
+    return qh_ERRinput;
+  }
+  qh_initqhull_start(qh, NULL, outfile, errfile);
+  if(numpoints==0 && points==NULL){
+      trace1((qh, qh->ferr, 1047, "qh_new_qhull: initialize Qhull\n"));
+      return 0;
+  }
+  trace1((qh, qh->ferr, 1044, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
+  exitcode= setjmp(qh->errexit);
+  if (!exitcode) {
+    qh->NOerrexit= False;
+    qh_initflags(qh, qhull_cmd);
+    if (qh->DELAUNAY)
+      qh->PROJECTdelaunay= True;
+    if (qh->HALFspace) {
+      /* points is an array of halfspaces,
+         the last coordinate of each halfspace is its offset */
+      hulldim= dim-1;
+      qh_setfeasible(qh, hulldim);
+      new_points= qh_sethalfspace_all(qh, dim, numpoints, points, qh->feasible_point);
+      new_ismalloc= True;
+      if (ismalloc)
+        qh_free(points);
+    }else {
+      hulldim= dim;
+      new_points= points;
+      new_ismalloc= ismalloc;
+    }
+    qh_init_B(qh, new_points, numpoints, hulldim, new_ismalloc);
+    qh_qhull(qh);
+    qh_check_output(qh);
+    if (outfile) {
+      qh_produce_output(qh);
+    }else {
+      qh_prepare_output(qh);
+    }
+    if (qh->VERIFYoutput && !qh->FORCEoutput && !qh->STOPadd && !qh->STOPcone && !qh->STOPpoint)
+      qh_check_points(qh);
+  }
+  qh->NOerrexit= True;
+  return exitcode;
+} /* new_qhull */
+
+/*---------------------------------
+
+  qh_errexit(qh, exitcode, facet, ridge )
+    report and exit from an error
+    report facet and ridge if non-NULL
+    reports useful information such as last point processed
+    set qh.FORCEoutput to print neighborhood of facet
+
+  see:
+    qh_errexit2() in libqhull_r.c for printing 2 facets
+
+  design:
+    check for error within error processing
+    compute qh.hulltime
+    print facet and ridge (if any)
+    report commandString, options, qh.furthest_id
+    print summary and statistics (including precision statistics)
+    if qh_ERRsingular
+      print help text for singular data set
+    exit program via long jump (if defined) or exit()
+*/
+void qh_errexit(qhT *qh, int exitcode, facetT *facet, ridgeT *ridge) {
+
+  qh->tracefacet= NULL;  /* avoid infinite recursion through qh_fprintf */
+  qh->traceridge= NULL;
+  qh->tracevertex= NULL;
+  if (qh->ERREXITcalled) {
+    qh_fprintf(qh, qh->ferr, 8126, "\nqhull error while handling previous error in qh_errexit.  Exit program\n");
+    qh_exit(qh_ERRother);
+  }
+  qh->ERREXITcalled= True;
+  if (!qh->QHULLfinished)
+    qh->hulltime= qh_CPUclock - qh->hulltime;
+  qh_errprint(qh, "ERRONEOUS", facet, NULL, ridge, NULL);
+  qh_option(qh, "_maxoutside", NULL, &qh->MAXoutside);
+  qh_fprintf(qh, qh->ferr, 8127, "\nWhile executing: %s | %s\n", qh->rbox_command, qh->qhull_command);
+  qh_fprintf(qh, qh->ferr, 8128, "Options selected for Qhull %s:\n%s\n", qh_version, qh->qhull_options);
+  if (qh->furthest_id >= 0) {
+    qh_fprintf(qh, qh->ferr, 8129, "Last point added to hull was p%d.", qh->furthest_id);
+    if (zzval_(Ztotmerge))
+      qh_fprintf(qh, qh->ferr, 8130, "  Last merge was #%d.", zzval_(Ztotmerge));
+    if (qh->QHULLfinished)
+      qh_fprintf(qh, qh->ferr, 8131, "\nQhull has finished constructing the hull.");
+    else if (qh->POSTmerging)
+      qh_fprintf(qh, qh->ferr, 8132, "\nQhull has started post-merging.");
+    qh_fprintf(qh, qh->ferr, 8133, "\n");
+  }
+  if (qh->FORCEoutput && (qh->QHULLfinished || (!facet && !ridge)))
+    qh_produce_output(qh);
+  else if (exitcode != qh_ERRinput) {
+    if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh->hull_dim+1) {
+      qh_fprintf(qh, qh->ferr, 8134, "\nAt error exit:\n");
+      qh_printsummary(qh, qh->ferr);
+      if (qh->PRINTstatistics) {
+        qh_collectstatistics(qh);
+        qh_allstatistics(qh);
+        qh_printstatistics(qh, qh->ferr, "at error exit");
+        qh_memstatistics(qh, qh->ferr);
+      }
+    }
+    if (qh->PRINTprecision)
+      qh_printstats(qh, qh->ferr, qh->qhstat.precision, NULL);
+  }
+  if (!exitcode)
+    exitcode= qh_ERRother;
+  else if (exitcode == qh_ERRprec && !qh->PREmerge)
+    qh_printhelp_degenerate(qh, qh->ferr);
+  else if (exitcode == qh_ERRqhull)
+    qh_printhelp_internal(qh, qh->ferr);
+  else if (exitcode == qh_ERRsingular)
+    qh_printhelp_singular(qh, qh->ferr);
+  else if (exitcode == qh_ERRdebug)
+    qh_fprintf(qh, qh->ferr, 8016, "qhull exit due to qh_ERRdebug\n");
+  else if (exitcode == qh_ERRtopology || exitcode == qh_ERRwide || exitcode == qh_ERRprec) {
+    if (qh->NOpremerge && !qh->MERGING)
+      qh_printhelp_degenerate(qh, qh->ferr);
+    else if (exitcode == qh_ERRtopology)
+      qh_printhelp_topology(qh, qh->ferr);
+    else if (exitcode == qh_ERRwide)
+      qh_printhelp_wide(qh, qh->ferr);
+  }else if (exitcode > 255) {
+    qh_fprintf(qh, qh->ferr, 6426, "qhull internal error (qh_errexit): exit code %d is greater than 255.  Invalid argument for exit().  Replaced with 255\n", exitcode);
+    exitcode= 255;
+  }
+  if (qh->NOerrexit) {
+    qh_fprintf(qh, qh->ferr, 6187, "qhull internal error (qh_errexit): either error while reporting error QH%d, or qh.NOerrexit not cleared after setjmp(). Exit program with error status %d\n",
+         qh->last_errcode, exitcode);
+    qh_exit(exitcode);
+  }
+  qh->ERREXITcalled= False;
+  qh->NOerrexit= True;
+  qh->ALLOWrestart= False;  /* longjmp will undo qh_build_withrestart */
+  longjmp(qh->errexit, exitcode);
+} /* errexit */
+
+/*---------------------------------
+
+  qh_errprint(qh, fp, string, atfacet, otherfacet, atridge, atvertex )
+    prints out the information of facets and ridges to fp
+    also prints neighbors and geomview output
+
+  notes:
+    except for string, any parameter may be NULL
+*/
+void qh_errprint(qhT *qh, const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
+  int i;
+
+  if (atvertex) {
+    qh_fprintf(qh, qh->ferr, 8138, "%s VERTEX:\n", string);
+    qh_printvertex(qh, qh->ferr, atvertex);
+  }
+  if (atridge) {
+    qh_fprintf(qh, qh->ferr, 8137, "%s RIDGE:\n", string);
+    qh_printridge(qh, qh->ferr, atridge);
+    if (!atfacet)
+      atfacet= atridge->top;
+    if (!otherfacet)
+      otherfacet= otherfacet_(atridge, atfacet);
+    if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
+      qh_printfacet(qh, qh->ferr, atridge->top);
+    if (atridge->bottom && atridge->bottom != atfacet && atridge->bottom != otherfacet)
+      qh_printfacet(qh, qh->ferr, atridge->bottom);
+  }
+  if (atfacet) {
+    qh_fprintf(qh, qh->ferr, 8135, "%s FACET:\n", string);
+    qh_printfacet(qh, qh->ferr, atfacet);
+  }
+  if (otherfacet) {
+    qh_fprintf(qh, qh->ferr, 8136, "%s OTHER FACET:\n", string);
+    qh_printfacet(qh, qh->ferr, otherfacet);
+  }
+  if (qh->fout && qh->FORCEoutput && atfacet && !qh->QHULLfinished && !qh->IStracing) {
+    qh_fprintf(qh, qh->ferr, 8139, "ERRONEOUS and NEIGHBORING FACETS to output\n");
+    for (i=0; i < qh_PRINTEND; i++)  /* use fout for geomview output */
+      qh_printneighborhood(qh, qh->fout, qh->PRINTout[i], atfacet, otherfacet,
+                            !qh_ALL);
+  }
+} /* errprint */
+
+
+/*---------------------------------
+
+  qh_printfacetlist(qh, fp, facetlist, facets, printall )
+    print all fields for a facet list and/or set of facets to fp
+    if !printall,
+      only prints good facets
+
+  notes:
+    also prints all vertices
+*/
+void qh_printfacetlist(qhT *qh, facetT *facetlist, setT *facets, boolT printall) {
+  facetT *facet, **facetp;
+
+  if (facetlist)
+    qh_checklists(qh, facetlist);
+  qh_fprintf(qh, qh->ferr, 9424, "printfacetlist: vertices\n");
+  qh_printbegin(qh, qh->ferr, qh_PRINTfacets, facetlist, facets, printall);
+  if (facetlist) {
+    qh_fprintf(qh, qh->ferr, 9413, "printfacetlist: facetlist\n");
+    FORALLfacet_(facetlist)
+      qh_printafacet(qh, qh->ferr, qh_PRINTfacets, facet, printall);
+  }
+  if (facets) {
+    qh_fprintf(qh, qh->ferr, 9414, "printfacetlist: %d facets\n", qh_setsize(qh, facets));
+    FOREACHfacet_(facets)
+      qh_printafacet(qh, qh->ferr, qh_PRINTfacets, facet, printall);
+  }
+  qh_fprintf(qh, qh->ferr, 9412, "printfacetlist: end\n");
+  qh_printend(qh, qh->ferr, qh_PRINTfacets, facetlist, facets, printall);
+} /* printfacetlist */
+
+
+/*---------------------------------
+
+  qh_printhelp_degenerate(qh, fp )
+    prints descriptive message for precision error with qh_ERRprec
+
+  notes:
+    no message if qh_QUICKhelp
+*/
+void qh_printhelp_degenerate(qhT *qh, FILE *fp) {
+
+  if (qh->MERGEexact || qh->PREmerge || qh->JOGGLEmax < REALmax/2)
+    qh_fprintf(qh, fp, 9368, "\n\
+A Qhull error has occurred.  Qhull should have corrected the above\n\
+precision error.  Please send the input and all of the output to\n\
+qhull_bug@qhull.org\n");
+  else if (!qh_QUICKhelp) {
+    qh_fprintf(qh, fp, 9369, "\n\
+Precision problems were detected during construction of the convex hull.\n\
+This occurs because convex hull algorithms assume that calculations are\n\
+exact, but floating-point arithmetic has roundoff errors.\n\
+\n\
+To correct for precision problems, do not use 'Q0'.  By default, Qhull\n\
+selects 'C-0' or 'Qx' and merges non-convex facets.  With option 'QJ',\n\
+Qhull joggles the input to prevent precision problems.  See \"Imprecision\n\
+in Qhull\" (qh-impre.htm).\n\
+\n\
+If you use 'Q0', the output may include\n\
+coplanar ridges, concave ridges, and flipped facets.  In 4-d and higher,\n\
+Qhull may produce a ridge with four neighbors or two facets with the same \n\
+vertices.  Qhull reports these events when they occur.  It stops when a\n\
+concave ridge, flipped facet, or duplicate facet occurs.\n");
+#if REALfloat
+    qh_fprintf(qh, fp, 9370, "\
+\n\
+Qhull is currently using single precision arithmetic.  The following\n\
+will probably remove the precision problems:\n\
+  - recompile qhull for realT precision(#define REALfloat 0 in user_r.h).\n");
+#endif
+    if (qh->DELAUNAY && !qh->SCALElast && qh->MAXabs_coord > 1e4)
+      qh_fprintf(qh, fp, 9371, "\
+\n\
+When computing the Delaunay triangulation of coordinates > 1.0,\n\
+  - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
+    if (qh->DELAUNAY && !qh->ATinfinity)
+      qh_fprintf(qh, fp, 9372, "\
+When computing the Delaunay triangulation:\n\
+  - use 'Qz' to add a point at-infinity.  This reduces precision problems.\n");
+
+    qh_fprintf(qh, fp, 9373, "\
+\n\
+If you need triangular output:\n\
+  - use option 'Qt' to triangulate the output\n\
+  - use option 'QJ' to joggle the input points and remove precision errors\n\
+  - use option 'Ft'.  It triangulates non-simplicial facets with added points.\n\
+\n\
+If you must use 'Q0',\n\
+try one or more of the following options.  They can not guarantee an output.\n\
+  - use 'QbB' to scale the input to a cube.\n\
+  - use 'Po' to produce output and prevent partitioning for flipped facets\n\
+  - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
+  - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
+  - options 'Qf', 'Qbb', and 'QR0' may also help\n",
+               qh->DISTround);
+    qh_fprintf(qh, fp, 9374, "\
+\n\
+To guarantee simplicial output:\n\
+  - use option 'Qt' to triangulate the output\n\
+  - use option 'QJ' to joggle the input points and remove precision errors\n\
+  - use option 'Ft' to triangulate the output by adding points\n\
+  - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
+");
+  }
+} /* printhelp_degenerate */
+
+/*---------------------------------
+
+  qh_printhelp_internal(qh, fp )
+    prints descriptive message for qhull internal error with qh_ERRqhull
+
+  notes:
+    no message if qh_QUICKhelp
+*/
+void qh_printhelp_internal(qhT *qh, FILE *fp) {
+
+  if (!qh_QUICKhelp) {
+    qh_fprintf(qh, fp, 9426, "\n\
+A Qhull internal error has occurred.  Please send the input and output to\n\
+qhull_bug@qhull.org. If you can duplicate the error with logging ('T4z'), please\n\
+include the log file.\n");
+  }
+} /* printhelp_internal */
+
+/*---------------------------------
+
+  qh_printhelp_narrowhull(qh, minangle )
+    Warn about a narrow hull
+
+  notes:
+    Alternatively, reduce qh_WARNnarrow in user_r.h
+
+*/
+void qh_printhelp_narrowhull(qhT *qh, FILE *fp, realT minangle) {
+
+    qh_fprintf(qh, fp, 7089, "qhull precision warning: The initial hull is narrow.  Is the input lower\n\
+dimensional (e.g., a square in 3-d instead of a cube)?  Cosine of the minimum\n\
+angle is %.16f.  If so, Qhull may produce a wide facet.\n\
+Options 'Qs' (search all points), 'Qbb' (scale last coordinate), or\n\
+'QbB' (scale to unit box) may remove this warning.\n\
+See 'Limitations' in qh-impre.htm.  Use 'Pp' to skip this warning.\n",
+          -minangle);   /* convert from angle between normals to angle between facets */
+} /* printhelp_narrowhull */
+
+/*---------------------------------
+
+  qh_printhelp_singular(qh, fp )
+    prints descriptive message for singular input
+*/
+void qh_printhelp_singular(qhT *qh, FILE *fp) {
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+  realT min, max, *coord, dist;
+  int i,k;
+
+  qh_fprintf(qh, fp, 9376, "\n\
+The input to qhull appears to be less than %d dimensional, or a\n\
+computation has overflowed.\n\n\
+Qhull could not construct a clearly convex simplex from points:\n",
+           qh->hull_dim);
+  qh_printvertexlist(qh, fp, "", qh->facet_list, NULL, qh_ALL);
+  if (!qh_QUICKhelp)
+    qh_fprintf(qh, fp, 9377, "\n\
+The center point is coplanar with a facet, or a vertex is coplanar\n\
+with a neighboring facet.  The maximum round off error for\n\
+computing distances is %2.2g.  The center point, facets and distances\n\
+to the center point are as follows:\n\n", qh->DISTround);
+  qh_printpointid(qh, fp, "center point", qh->hull_dim, qh->interior_point, qh_IDunknown);
+  qh_fprintf(qh, fp, 9378, "\n");
+  FORALLfacets {
+    qh_fprintf(qh, fp, 9379, "facet");
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(qh, fp, 9380, " p%d", qh_pointid(qh, vertex->point));
+    zinc_(Zdistio);
+    qh_distplane(qh, qh->interior_point, facet, &dist);
+    qh_fprintf(qh, fp, 9381, " distance= %4.2g\n", dist);
+  }
+  if (!qh_QUICKhelp) {
+    if (qh->HALFspace)
+      qh_fprintf(qh, fp, 9382, "\n\
+These points are the dual of the given halfspaces.  They indicate that\n\
+the intersection is degenerate.\n");
+    qh_fprintf(qh, fp, 9383,"\n\
+These points either have a maximum or minimum x-coordinate, or\n\
+they maximize the determinant for k coordinates.  Trial points\n\
+are first selected from points that maximize a coordinate.\n");
+    if (qh->hull_dim >= qh_INITIALmax)
+      qh_fprintf(qh, fp, 9384, "\n\
+Because of the high dimension, the min x-coordinate and max-coordinate\n\
+points are used if the determinant is non-zero.  Option 'Qs' will\n\
+do a better, though much slower, job.  Instead of 'Qs', you can change\n\
+the points by randomly rotating the input with 'QR0'.\n");
+  }
+  qh_fprintf(qh, fp, 9385, "\nThe min and max coordinates for each dimension are:\n");
+  for (k=0; k < qh->hull_dim; k++) {
+    min= REALmax;
+    max= -REALmax;
+    for (i=qh->num_points, coord= qh->first_point+k; i--; coord += qh->hull_dim) {
+      maximize_(max, *coord);
+      minimize_(min, *coord);
+    }
+    qh_fprintf(qh, fp, 9386, "  %d:  %8.4g  %8.4g  difference= %4.4g\n", k, min, max, max-min);
+  }
+  if (!qh_QUICKhelp) {
+    qh_fprintf(qh, fp, 9387, "\n\
+If the input should be full dimensional, you have several options that\n\
+may determine an initial simplex:\n\
+  - use 'QJ'  to joggle the input and make it full dimensional\n\
+  - use 'QbB' to scale the points to the unit cube\n\
+  - use 'QR0' to randomly rotate the input for different maximum points\n\
+  - use 'Qs'  to search all points for the initial simplex\n\
+  - use 'En'  to specify a maximum roundoff error less than %2.2g.\n\
+  - trace execution with 'T3' to see the determinant for each point.\n",
+                     qh->DISTround);
+#if REALfloat
+    qh_fprintf(qh, fp, 9388, "\
+  - recompile qhull for realT precision(#define REALfloat 0 in libqhull_r.h).\n");
+#endif
+    qh_fprintf(qh, fp, 9389, "\n\
+If the input is lower dimensional:\n\
+  - use 'QJ' to joggle the input and make it full dimensional\n\
+  - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should\n\
+    pick the coordinate with the least range.  The hull will have the\n\
+    correct topology.\n\
+  - determine the flat containing the points, rotate the points\n\
+    into a coordinate plane, and delete the other coordinates.\n\
+  - add one or more points to make the input full dimensional.\n\
+");
+  }
+} /* printhelp_singular */
+
+/*---------------------------------
+
+  qh_printhelp_topology(qh, fp )
+    prints descriptive message for qhull topology error with qh_ERRtopology
+
+  notes:
+    no message if qh_QUICKhelp
+*/
+void qh_printhelp_topology(qhT *qh, FILE *fp) {
+
+  if (!qh_QUICKhelp) {
+    qh_fprintf(qh, fp, 9427, "\n\
+A Qhull topology error has occurred.  Qhull did not recover from facet merges and vertex merges.\n\
+This usually occurs when the input is nearly degenerate and substantial merging has occurred.\n\
+See http://www.qhull.org/html/qh-impre.htm#limit\n");
+  }
+} /* printhelp_topology */
+
+/*---------------------------------
+
+  qh_printhelp_wide(qh, fp )
+    prints descriptive message for qhull wide facet with qh_ERRwide
+
+  notes:
+    no message if qh_QUICKhelp
+*/
+void qh_printhelp_wide(qhT *qh, FILE *fp) {
+
+  if (!qh_QUICKhelp) {
+    qh_fprintf(qh, fp, 9428, "\n\
+A wide merge error has occurred.  Qhull has produced a wide facet due to facet merges and vertex merges.\n\
+This usually occurs when the input is nearly degenerate and substantial merging has occurred.\n\
+See http://www.qhull.org/html/qh-impre.htm#limit\n");
+  }
+} /* printhelp_wide */
+
+/*---------------------------------
+
+  qh_user_memsizes(qh)
+    allocate up to 10 additional, quick allocation sizes
+
+  notes:
+    increase maximum number of allocations in qh_initqhull_mem()
+*/
+void qh_user_memsizes(qhT *qh) {
+
+  QHULL_UNUSED(qh)
+  /* qh_memsize(qh, size); */
+} /* user_memsizes */
+
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.h b/src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.h
new file mode 100644
index 00000000000..523c179dc03
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/user_r.h
@@ -0,0 +1,1061 @@
+/*
  ---------------------------------
+
+   user_r.h
+   user redefinable constants
+
+   for each source file, user_r.h is included first
+
+   see qh-user_r.htm.  see COPYING for copyright information.
+
+   See user_r.c for sample code.
+
+   before reading any code, review libqhull_r.h for data structure definitions
+
+Sections:
+   ============= qhull library constants ======================
+   ============= data types and configuration macros ==========
+   ============= performance related constants ================
+   ============= memory constants =============================
+   ============= joggle constants =============================
+   ============= conditional compilation ======================
+   ============= merge constants ==============================
+   ============= Microsoft DevStudio ==========================
+
+Code flags --
+  NOerrors -- the code does not call qh_errexit()
+  WARN64 -- the code may be incompatible with 64-bit pointers
+
+*/
+
+#include 
+#include 
+#include 
+
+#ifndef qhDEFuser
+#define qhDEFuser 1
+
+/* Derived from Qt's corelib/global/qglobal.h */
+#if !defined(SAG_COM) && !defined(__CYGWIN__) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
+#   define QHULL_OS_WIN
+#elif defined(__MWERKS__) && defined(__INTEL__) /* Metrowerks discontinued before the release of Intel Macs */
+#   define QHULL_OS_WIN
+#endif
+
+/*============================================================*/
+/*============= qhull library constants ======================*/
+/*============================================================*/
+
+/*----------------------------------
+
+  FILENAMElen -- max length for TI and TO filenames
+
+*/
+
+#define qh_FILENAMElen 500
+
+/*----------------------------------
+
+  msgcode -- Unique message codes for qh_fprintf
+
+  If add new messages, assign these values and increment in user.h and user_r.h
+  See QhullError.h for 10000 error codes.
+  Cannot use '0031' since it would be octal
+
+  def counters =  [31/32/33/38, 1067, 2113, 3079, 4097, 5006,
+     6429, 7027/7028/7035/7068/7070/7102, 8163, 9428, 10000, 11034]
+
+  See: qh_ERR* [libqhull_r.h]
+*/
+
+#define MSG_TRACE0     0   /* always include if logging ('Tn') */
+#define MSG_TRACE1  1000
+#define MSG_TRACE2  2000
+#define MSG_TRACE3  3000
+#define MSG_TRACE4  4000
+#define MSG_TRACE5  5000
+#define MSG_ERROR   6000   /* errors written to qh.ferr */
+#define MSG_WARNING 7000
+#define MSG_STDERR  8000   /* log messages Written to qh.ferr */
+#define MSG_OUTPUT  9000
+#define MSG_QHULL_ERROR 10000 /* errors thrown by QhullError.cpp (QHULLlastError is in QhullError.h) */
+#define MSG_FIX    11000   /* Document as 'QH11... FIX: ...' */
+#define MSG_MAXLEN  3000   /* qh_printhelp_degenerate() in user_r.c */
+
+
+/*----------------------------------
+
+  qh_OPTIONline -- max length of an option line 'FO'
+*/
+#define qh_OPTIONline 80
+
+/*============================================================*/
+/*============= data types and configuration macros ==========*/
+/*============================================================*/
+
+/*----------------------------------
+
+  realT
+    set the size of floating point numbers
+
+  qh_REALdigits
+    maximum number of significant digits
+
+  qh_REAL_1, qh_REAL_2n, qh_REAL_3n
+    format strings for printf
+
+  REALmax, REALmin
+    maximum and minimum (near zero) values
+
+  REALepsilon
+    machine roundoff.  Maximum roundoff error for addition and multiplication.
+
+  notes:
+   Select whether to store floating point numbers in single precision (float)
+   or double precision (double).
+
+   Use 'float' to save about 8% in time and 25% in space.  This is particularly
+   helpful if high-d where convex hulls are space limited.  Using 'float' also
+   reduces the printed size of Qhull's output since numbers have 8 digits of
+   precision.
+
+   Use 'double' when greater arithmetic precision is needed.  This is needed
+   for Delaunay triangulations and Voronoi diagrams when you are not merging
+   facets.
+
+   If 'double' gives insufficient precision, your data probably includes
+   degeneracies.  If so you should use facet merging (done by default)
+   or exact arithmetic (see imprecision section of manual, qh-impre.htm).
+   You may also use option 'Po' to force output despite precision errors.
+
+   You may use 'long double', but many format statements need to be changed
+   and you may need a 'long double' square root routine.  S. Grundmann
+   (sg@eeiwzb.et.tu-dresden.de) has done this.  He reports that the code runs
+   much slower with little gain in precision.
+
+   WARNING: on some machines,    int f(){realT a= REALmax;return (a == REALmax);}
+      returns False.  Use (a > REALmax/2) instead of (a == REALmax).
+
+   REALfloat =   1      all numbers are 'float' type
+             =   0      all numbers are 'double' type
+*/
+#define REALfloat 0
+
+#if (REALfloat == 1)
+#define realT float
+#define REALmax FLT_MAX
+#define REALmin FLT_MIN
+#define REALepsilon FLT_EPSILON
+#define qh_REALdigits 8   /* maximum number of significant digits */
+#define qh_REAL_1 "%6.8g "
+#define qh_REAL_2n "%6.8g %6.8g\n"
+#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
+
+#elif (REALfloat == 0)
+#define realT double
+#define REALmax DBL_MAX
+#define REALmin DBL_MIN
+#define REALepsilon DBL_EPSILON
+#define qh_REALdigits 16    /* maximum number of significant digits */
+#define qh_REAL_1 "%6.16g "
+#define qh_REAL_2n "%6.16g %6.16g\n"
+#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
+
+#else
+#error unknown float option
+#endif
+
+/*----------------------------------
+
+  countT
+    The type for counts and identifiers (e.g., the number of points, vertex identifiers)
+    Currently used by C++ code-only.  Decided against using it for setT because most sets are small.
+
+    Defined as 'int' for C-code compatibility and QH11026
+
+    QH11026 FIX: countT may be defined as a 'unsigned int', but several code issues need to be solved first.  See countT in Changes.txt
+*/
+
+#ifndef DEFcountT
+#define DEFcountT 1
+typedef int countT;
+#endif
+#define COUNTmax INT_MAX
+
+/*----------------------------------
+
+  qh_POINTSmax
+    Maximum number of points for qh.num_points and point allocation in qh_readpoints
+*/
+#define qh_POINTSmax (INT_MAX-16)
+
+/*----------------------------------
+
+  qh_CPUclock
+    define the clock() function for reporting the total time spent by Qhull
+    returns CPU ticks as a 'long int'
+    qh_CPUclock is only used for reporting the total time spent by Qhull
+
+  qh_SECticks
+    the number of clock ticks per second
+
+  notes:
+    looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
+    to define a custom clock, set qh_CLOCKtype to 0
+
+    if your system does not use clock() to return CPU ticks, replace
+    qh_CPUclock with the corresponding function.  It is converted
+    to 'unsigned long' to prevent wrap-around during long runs.  By default,
+     defines clock_t as 'long'
+
+   Set qh_CLOCKtype to
+
+     1          for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
+                Note:  may fail if more than 1 hour elapsed time
+
+     2          use qh_clock() with POSIX times() (see global_r.c)
+*/
+#define qh_CLOCKtype 1  /* change to the desired number */
+
+#if (qh_CLOCKtype == 1)
+
+#if defined(CLOCKS_PER_SECOND)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock, may be converted to approximate double */
+#define qh_SECticks CLOCKS_PER_SECOND
+
+#elif defined(CLOCKS_PER_SEC)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock, may be converted to approximate double */
+#define qh_SECticks CLOCKS_PER_SEC
+
+#elif defined(CLK_TCK)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock, may be converted to approximate double */
+#define qh_SECticks CLK_TCK
+
+#else
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock, may be converted to approximate double */
+#define qh_SECticks 1E6
+#endif
+
+#elif (qh_CLOCKtype == 2)
+#define qh_CPUclock    qh_clock()  /* return CPU clock, may be converted to approximate double */
+#define qh_SECticks 100
+
+#else /* qh_CLOCKtype == ? */
+#error unknown clock option
+#endif
+
+/*----------------------------------
+
+  qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
+    define random number generator
+
+    qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.
+    qh_RANDOMseed sets the random number seed for qh_RANDOMint
+
+  Set qh_RANDOMtype (default 5) to:
+    1       for random() with 31 bits (UCB)
+    2       for rand() with RAND_MAX or 15 bits (system 5)
+    3       for rand() with 31 bits (Sun)
+    4       for lrand48() with 31 bits (Solaris)
+    5       for qh_rand(qh) with 31 bits (included with Qhull, requires 'qh')
+
+  notes:
+    Random numbers are used by rbox to generate point sets.  Random
+    numbers are used by Qhull to rotate the input ('QRn' option),
+    simulate a randomized algorithm ('Qr' option), and to simulate
+    roundoff errors ('Rn' option).
+
+    Random number generators differ between systems.  Most systems provide
+    rand() but the period varies.  The period of rand() is not critical
+    since qhull does not normally use random numbers.
+
+    The default generator is Park & Miller's minimal standard random
+    number generator [CACM 31:1195 '88].  It is included with Qhull.
+
+    If qh_RANDOMmax is wrong, qhull will report a warning and Geomview
+    output will likely be invisible.
+*/
+#define qh_RANDOMtype 5   /* *** change to the desired number *** */
+
+#if (qh_RANDOMtype == 1)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, random()/MAX */
+#define qh_RANDOMint random()
+#define qh_RANDOMseed_(qh, seed) srandom(seed);
+
+#elif (qh_RANDOMtype == 2)
+#ifdef RAND_MAX
+#define qh_RANDOMmax ((realT)RAND_MAX)
+#else
+#define qh_RANDOMmax ((realT)32767)   /* 15 bits (System 5) */
+#endif
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(qh, seed) srand((unsigned int)seed);
+
+#elif (qh_RANDOMtype == 3)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, Sun */
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(qh, seed) srand((unsigned int)seed);
+
+#elif (qh_RANDOMtype == 4)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, lrand38()/MAX */
+#define qh_RANDOMint lrand48()
+#define qh_RANDOMseed_(qh, seed) srand48(seed);
+
+#elif (qh_RANDOMtype == 5)  /* 'qh' is an implicit parameter */
+#define qh_RANDOMmax ((realT)2147483646UL)  /* 31 bits, qh_rand/MAX */
+#define qh_RANDOMint qh_rand(qh)
+#define qh_RANDOMseed_(qh, seed) qh_srand(qh, seed);
+/* unlike rand(), never returns 0 */
+
+#else
+#error: unknown random option
+#endif
+
+/*----------------------------------
+
+  qh_ORIENTclock
+    0 for inward pointing normals by Geomview convention
+*/
+#define qh_ORIENTclock 0
+
+/*----------------------------------
+
+  qh_RANDOMdist
+    define for random perturbation of qh_distplane and qh_setfacetplane (qh.RANDOMdist, 'QRn')
+
+  For testing qh.DISTround.  Qhull should not depend on computations always producing the same roundoff error
+
+  #define qh_RANDOMdist 1e-13
+*/
+
+/*============================================================*/
+/*============= joggle constants =============================*/
+/*============================================================*/
+
+/*----------------------------------
+
+  qh_JOGGLEdefault
+    default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
+
+  notes:
+    rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
+    rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
+    rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
+    rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
+    rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
+    rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
+    rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
+    rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
+    rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
+    the later have about 20 points per facet, each of which may interfere
+
+    pick a value large enough to avoid retries on most inputs
+*/
+#define qh_JOGGLEdefault 30000.0
+
+/*----------------------------------
+
+  qh_JOGGLEincrease
+    factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
+*/
+#define qh_JOGGLEincrease 10.0
+
+/*----------------------------------
+
+  qh_JOGGLEretry
+    if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
+
+notes:
+try twice at the original value in case of bad luck the first time
+*/
+#define qh_JOGGLEretry 2
+
+/*----------------------------------
+
+  qh_JOGGLEagain
+    every following qh_JOGGLEagain, increase qh.JOGGLEmax
+
+  notes:
+    1 is OK since it's already failed qh_JOGGLEretry times
+*/
+#define qh_JOGGLEagain 1
+
+/*----------------------------------
+
+  qh_JOGGLEmaxincrease
+    maximum qh.JOGGLEmax due to qh_JOGGLEincrease
+    relative to qh.MAXwidth
+
+  notes:
+    qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
+*/
+#define qh_JOGGLEmaxincrease 1e-2
+
+/*----------------------------------
+
+  qh_JOGGLEmaxretry
+    stop after qh_JOGGLEmaxretry attempts
+*/
+#define qh_JOGGLEmaxretry 50
+
+/*============================================================*/
+/*============= performance related constants ================*/
+/*============================================================*/
+
+/*----------------------------------
+
+  qh_HASHfactor
+    total hash slots / used hash slots.  Must be at least 1.1.
+
+  notes:
+    =2 for at worst 50% occupancy for qh.hash_table and normally 25% occupancy
+*/
+#define qh_HASHfactor 2
+
+/*----------------------------------
+
+  qh_VERIFYdirect
+    with 'Tv' verify all points against all facets if op count is smaller
+
+  notes:
+    if greater, calls qh_check_bestdist() instead
+*/
+#define qh_VERIFYdirect 1000000
+
+/*----------------------------------
+
+  qh_INITIALsearch
+     if qh_INITIALmax, search points up to this dimension
+*/
+#define qh_INITIALsearch 6
+
+/*----------------------------------
+
+  qh_INITIALmax
+    if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
+
+  notes:
+    from points with non-zero determinants
+    use option 'Qs' to override (much slower)
+*/
+#define qh_INITIALmax 8
+
+/*============================================================*/
+/*============= memory constants =============================*/
+/*============================================================*/
+
+/*----------------------------------
+
+  qh_MEMalign
+    memory alignment for qh_meminitbuffers() in global_r.c
+
+  notes:
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem_r.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers.
+
+    If using gcc, best alignment is [fmax_() is defined in geom_r.h]
+              #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
+*/
+#define qh_MEMalign ((int)(fmax_(sizeof(realT), sizeof(void *))))
+
+/*----------------------------------
+
+  qh_MEMbufsize
+    size of additional memory buffers
+
+  notes:
+    used for qh_meminitbuffers() in global_r.c
+*/
+#define qh_MEMbufsize 0x10000       /* allocate 64K memory buffers */
+
+/*----------------------------------
+
+  qh_MEMinitbuf
+    size of initial memory buffer
+
+  notes:
+    use for qh_meminitbuffers() in global_r.c
+*/
+#define qh_MEMinitbuf 0x20000      /* initially allocate 128K buffer */
+
+/*----------------------------------
+
+  qh_INFINITE
+    on output, indicates Voronoi center at infinity
+*/
+#define qh_INFINITE  -10.101
+
+/*----------------------------------
+
+  qh_DEFAULTbox
+    default box size (Geomview expects 0.5)
+
+  qh_DEFAULTbox
+    default box size for integer coorindate (rbox only)
+*/
+#define qh_DEFAULTbox 0.5
+#define qh_DEFAULTzbox 1e6
+
+/*============================================================*/
+/*============= conditional compilation ======================*/
+/*============================================================*/
+
+/*----------------------------------
+
+  __cplusplus
+    defined by C++ compilers
+
+  __MSC_VER
+    defined by Microsoft Visual C++
+
+  __MWERKS__ && __INTEL__
+    defined by Metrowerks when compiling for Windows (not Intel-based Macintosh)
+
+  __MWERKS__ && __POWERPC__
+    defined by Metrowerks when compiling for PowerPC-based Macintosh
+
+  __STDC__
+    defined for strict ANSI C
+*/
+
+/*----------------------------------
+
+  qh_COMPUTEfurthest
+    compute furthest distance to an outside point instead of storing it with the facet
+    =1 to compute furthest
+
+  notes:
+    computing furthest saves memory but costs time
+      about 40% more distance tests for partitioning
+      removes facet->furthestdist
+*/
+#define qh_COMPUTEfurthest 0
+
+/*----------------------------------
+
+  qh_KEEPstatistics
+    =0 removes most of statistic gathering and reporting
+
+  notes:
+    if 0, code size is reduced by about 4%.
+*/
+#define qh_KEEPstatistics 0
+
+/*----------------------------------
+
+  qh_MAXoutside
+    record outer plane for each facet
+    =1 to record facet->maxoutside
+
+  notes:
+    this takes a realT per facet and slightly slows down qhull
+    it produces better outer planes for geomview output
+*/
+#define qh_MAXoutside 1
+
+/*----------------------------------
+
+  qh_NOmerge
+    disables facet merging if defined
+    For MSVC compiles, use qhull_r-exports-nomerge.def instead of qhull_r-exports.def
+
+  notes:
+    This saves about 25% space, 30% space in combination with qh_NOtrace,
+    and 36% with qh_NOtrace and qh_KEEPstatistics 0
+
+    Unless option 'Q0' is used
+      qh_NOmerge sets 'QJ' to avoid precision errors
+
+  see:
+    qh_NOmem in mem_r.h
+
+    see user_r.c/user_eg.c for removing io_r.o
+
+  #define qh_NOmerge
+*/
+
+/*----------------------------------
+
+  qh_NOtrace
+    no tracing if defined
+    disables 'Tn', 'TMn', 'TPn' and 'TWn'
+    override with 'Qw' for qh_addpoint tracing and various other items
+
+  notes:
+    This saves about 15% space.
+    Removes all traceN((...)) code and substantial sections of qh.IStracing code
+
+  #define qh_NOtrace
+*/
+#define qh_NOtrace
+
+#if 0  /* sample code */
+    exitcode= qh_new_qhull(qhT *qh, dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile);
+    qh_freeqhull(qhT *qh, !qh_ALL); /* frees long memory used by second call */
+    qh_memfreeshort(qhT *qh, &curlong, &totlong);  /* frees short memory and memory allocator */
+#endif
+
+/*----------------------------------
+
+  qh_QUICKhelp
+    =1 to use abbreviated help messages, e.g., for degenerate inputs
+*/
+#define qh_QUICKhelp    0
+
+/*============================================================*/
+/*============= merge constants ==============================*/
+/*============================================================*/
+/*
+   These constants effect facet merging.  You probably will not need
+   to modify them.  They effect the performance of facet merging.
+*/
+
+/*----------------------------------
+
+  qh_BESTcentrum
+     if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
+     else, qh_findbestneighbor() tests all vertices (much better merges)
+
+  qh_BESTcentrum2
+     if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
+*/
+#define qh_BESTcentrum 20
+#define qh_BESTcentrum2 2
+
+/*----------------------------------
+
+  qh_BESTnonconvex
+    if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
+
+  notes:
+    It is needed because qh_findbestneighbor is slow for large facets
+*/
+#define qh_BESTnonconvex 15
+
+/*----------------------------------
+
+  qh_COPLANARratio
+    for 3-d+ merging, qh.MINvisible is n*premerge_centrum
+
+  notes:
+    for non-merging, it's DISTround
+*/
+#define qh_COPLANARratio 3
+
+/*----------------------------------
+
+  qh_DIMmergeVertex
+    max dimension for vertex merging (it is not effective in high-d)
+*/
+#define qh_DIMmergeVertex 6
+
+/*----------------------------------
+
+  qh_DIMreduceBuild
+     max dimension for vertex reduction during build (slow in high-d)
+*/
+#define qh_DIMreduceBuild 5
+
+/*----------------------------------
+
+  qh_DISToutside
+    When is a point clearly outside of a facet?
+    Stops search in qh_findbestnew or qh_partitionall
+    qh_findbest uses qh.MINoutside since since it is only called if no merges.
+
+  notes:
+    'Qf' always searches for best facet
+    if !qh.MERGING, same as qh.MINoutside.
+    if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
+      [Note: Zdelvertextot occurs normally with interior points]
+            RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
+    When there is a sharp edge, need to move points to a
+    clearly good facet; otherwise may be lost in another partitioning.
+    if too big then O(n^2) behavior for partitioning in cone
+    if very small then important points not processed
+    Needed in qh_partitionall for
+      RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
+    Needed in qh_findbestnew for many instances of
+      RBOX 1000 s Z1 G1e-13 t | QHULL Tv
+
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
+     fmax_((qh->MERGING ? 2 : 1)*qh->MINoutside, qh->max_outside))
+
+/*----------------------------------
+
+  qh_MAXcheckpoint
+    Report up to qh_MAXcheckpoint errors per facet in qh_check_point ('Tv')
+*/
+#define qh_MAXcheckpoint 10
+
+/*----------------------------------
+
+  qh_MAXcoplanarcentrum
+    if pre-merging with qh.MERGEexact ('Qx') and f.nummerge > qh_MAXcoplanarcentrum
+      use f.maxoutside instead of qh.centrum_radius for coplanarity testing
+
+  notes:
+    see qh_test_nonsimplicial_merges
+    with qh.MERGEexact, a coplanar ridge is ignored until post-merging
+    otherwise a large facet with many merges may take all the facets
+*/
+#define qh_MAXcoplanarcentrum 10
+
+/*----------------------------------
+
+  qh_MAXnewcentrum
+    if <= dim+n vertices (n approximates the number of merges),
+      reset the centrum in qh_updatetested() and qh_mergecycle_facets()
+
+  notes:
+    needed to reduce cost and because centrums may move too much if
+    many vertices in high-d
+*/
+#define qh_MAXnewcentrum 5
+
+/*----------------------------------
+
+  qh_MAXnewmerges
+    if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
+
+  notes:
+    It is needed because postmerge can merge many facets at once
+*/
+#define qh_MAXnewmerges 2
+
+/*----------------------------------
+
+  qh_RATIOconcavehorizon
+    ratio of horizon vertex distance to max_outside for concave, twisted new facets in qh_test_nonsimplicial_merge
+    if too small, end up with vertices far below merged facets
+*/
+#define qh_RATIOconcavehorizon 20.0
+
+/*----------------------------------
+
+  qh_RATIOconvexmerge
+    ratio of vertex distance to qh.min_vertex for clearly convex new facets in qh_test_nonsimplicial_merge
+
+  notes:
+    must be convex for MRGtwisted
+*/
+#define qh_RATIOconvexmerge 10.0
+
+/*----------------------------------
+
+  qh_RATIOcoplanarapex
+    ratio of best distance for coplanar apex vs. vertex merge in qh_getpinchedmerges
+
+  notes:
+    A coplanar apex always works, while a vertex merge may fail
+*/
+#define qh_RATIOcoplanarapex 3.0
+
+/*----------------------------------
+
+  qh_RATIOcoplanaroutside
+    qh.MAXoutside ratio to repartition a coplanar point in qh_partitioncoplanar and qh_check_maxout
+
+  notes:
+    combines several tests, see qh_partitioncoplanar
+
+*/
+#define qh_RATIOcoplanaroutside 30.0
+
+/*----------------------------------
+
+  qh_RATIOmaxsimplex
+    ratio of max determinate to estimated determinate for searching all points in qh_maxsimplex
+
+  notes:
+    As each point is added to the simplex, the max determinate is should approximate the previous determinate * qh.MAXwidth
+    If maxdet is significantly less, the simplex may not be full-dimensional.
+    If so, all points are searched, stopping at 10 times qh_RATIOmaxsimplex
+*/
+#define qh_RATIOmaxsimplex 1.0e-3
+
+/*----------------------------------
+
+  qh_RATIOnearinside
+    ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
+    qh_check_maxout().
+
+  notes:
+    This is overkill since do not know the correct value.
+    It effects whether 'Qc' reports all coplanar points
+    Not used for 'd' since non-extreme points are coplanar, nearly incident points
+*/
+#define qh_RATIOnearinside 5
+
+/*----------------------------------
+
+  qh_RATIOpinchedsubridge
+    ratio to qh.ONEmerge to accept vertices in qh_findbest_pinchedvertex
+    skips search of neighboring vertices
+    facet width may increase by this ratio
+*/
+#define qh_RATIOpinchedsubridge 10.0
+
+/*----------------------------------
+
+  qh_RATIOtrypinched
+    ratio to qh.ONEmerge to try qh_getpinchedmerges in qh_buildcone_mergepinched
+    otherwise a duplicate ridge will increase facet width by this amount
+*/
+#define qh_RATIOtrypinched 4.0
+
+/*----------------------------------
+
+  qh_RATIOtwisted
+    maximum ratio to qh.ONEmerge to merge twisted facets in qh_merge_twisted
+*/
+#define qh_RATIOtwisted 20.0
+
+/*----------------------------------
+
+  qh_SEARCHdist
+    When is a facet coplanar with the best facet?
+    qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
+        increases minsearch if ischeckmax and more than 100 neighbors (is_5x_minsearch)
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
+      (qh->max_outside + 2 * qh->DISTround + fmax_( qh->MINvisible, qh->MAXcoplanar)));
+
+/*----------------------------------
+
+  qh_USEfindbestnew
+     Always use qh_findbestnew for qh_partitionpoint, otherwise use
+     qh_findbestnew if merged new facet or sharpnewfacets.
+
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
+
+/*----------------------------------
+
+  qh_MAXnarrow
+    max. cosine in initial hull that sets qh.NARROWhull
+
+  notes:
+    If qh.NARROWhull, the initial partition does not make
+    coplanar points.  If narrow, a coplanar point can be
+    coplanar to two facets of opposite orientations and
+    distant from the exact convex hull.
+
+    Conservative estimate.  Don't actually see problems until it is -1.0
+*/
+#define qh_MAXnarrow -0.99999999
+
+/*----------------------------------
+
+  qh_WARNnarrow
+    max. cosine in initial hull to warn about qh.NARROWhull
+
+  notes:
+    this is a conservative estimate.
+    Don't actually see problems until it is -1.0.  See qh-impre.htm
+*/
+#define qh_WARNnarrow -0.999999999999999
+
+/*----------------------------------
+
+  qh_WIDEcoplanar
+    n*MAXcoplanar or n*MINvisible for a WIDEfacet
+
+    if vertex is further than qh.WIDEfacet from the hyperplane
+    then its ridges are not counted in computing the area, and
+    the facet's centrum is frozen.
+
+  notes:
+    qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
+    qh_WIDEcoplanar * qh.MINvisible);
+*/
+#define qh_WIDEcoplanar 6
+
+/*----------------------------------
+
+  qh_WIDEduplicate
+    merge ratio for errexit from qh_forcedmerges due to duplicate ridge
+    Override with option Q12-allow-wide
+
+  Notes:
+    Merging a duplicate ridge can lead to very wide facets.
+*/
+#define qh_WIDEduplicate 100
+
+/*----------------------------------
+
+  qh_WIDEdupridge
+    Merge ratio for selecting a forced dupridge merge
+
+  Notes:
+    Merging a dupridge can lead to very wide facets.
+*/
+#define qh_WIDEdupridge 50
+
+/*----------------------------------
+
+  qh_WIDEmaxoutside
+    Precision ratio for maximum increase for qh.max_outside in qh_check_maxout
+    Precision errors while constructing the hull, may lead to very wide facets when checked in qh_check_maxout
+    Nearly incident points in 4-d and higher is the most likely culprit
+    Skip qh_check_maxout with 'Q5' (no-check-outer)
+    Do not error with option 'Q12' (allow-wide)
+    Do not warn with options 'Q12 Pp'
+*/
+#define qh_WIDEmaxoutside 100
+
+/*----------------------------------
+
+  qh_WIDEmaxoutside2
+    Precision ratio for maximum qh.max_outside in qh_check_maxout
+    Skip qh_check_maxout with 'Q5' no-check-outer
+    Do not error with option 'Q12' allow-wide
+*/
+#define qh_WIDEmaxoutside2 (10*qh_WIDEmaxoutside)
+
+
+/*----------------------------------
+
+  qh_WIDEpinched
+    Merge ratio for distance between pinched vertices compared to current facet width for qh_getpinchedmerges and qh_next_vertexmerge
+    Reports warning and merges duplicate ridges instead
+    Enable these attempts with option Q14 merge-pinched-vertices
+
+  notes:
+    Merging pinched vertices should prevent duplicate ridges (see qh_WIDEduplicate)
+    Merging the duplicate ridges may be better than merging the pinched vertices
+    Found up to 45x ratio for qh_pointdist -- for ((i=1; i<20; i++)); do rbox 175 C1,6e-13 t | qhull d T4 2>&1 | tee x.1 | grep  -E 'QH|non-simplicial|Statis|pinched'; done
+    Actual distance to facets is a third to a tenth of the qh_pointdist (T1)
+*/
+#define qh_WIDEpinched 100
+
+/*----------------------------------
+
+  qh_ZEROdelaunay
+    a zero Delaunay facet occurs for input sites coplanar with their convex hull
+    the last normal coefficient of a zero Delaunay facet is within
+        qh_ZEROdelaunay * qh.ANGLEround of 0
+
+  notes:
+    qh_ZEROdelaunay does not allow for joggled input ('QJ').
+
+    You can avoid zero Delaunay facets by surrounding the input with a box.
+
+    Use option 'PDk:-n' to explicitly define zero Delaunay facets
+      k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
+      n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
+*/
+#define qh_ZEROdelaunay 2
+
+/*============================================================*/
+/*============= Microsoft DevStudio ==========================*/
+/*============================================================*/
+
+/*
+   Finding Memory Leaks Using the CRT Library
+   https://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.100).aspx
+
+   Reports enabled in qh_lib_check for Debug window and stderr
+
+   From 2005=>msvcr80d, 2010=>msvcr100d, 2012=>msvcr110d
+
+   Watch: {,,msvcr80d.dll}_crtBreakAlloc  Value from {n} in the leak report
+   _CrtSetBreakAlloc(689); // qh_lib_check() [global_r.c]
+
+   Examples
+     http://free-cad.sourceforge.net/SrcDocu/d2/d7f/MemDebug_8cpp_source.html
+     https://github.com/illlust/Game/blob/master/library/MemoryLeak.cpp
+*/
+#if 0   /* off (0) by default for QHULL_CRTDBG */
+#define QHULL_CRTDBG
+#endif
+
+#if defined(_MSC_VER) && defined(_DEBUG) && defined(QHULL_CRTDBG)
+#define _CRTDBG_MAP_ALLOC
+#include 
+#include 
+#endif
+
+#endif /* qh_DEFuser */
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/usermem_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/usermem_r.c
new file mode 100644
index 00000000000..27563cff4a7
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/usermem_r.c
@@ -0,0 +1,102 @@
+/*
  ---------------------------------
+
+   usermem_r.c
+   user redefinable functions -- qh_exit, qh_free, and qh_malloc
+
+   See README.txt.
+
+   If you redefine one of these functions you must redefine all of them.
+   If you recompile and load this file, then usermem.o will not be loaded
+   from qhull.a or qhull.lib
+
+   See libqhull_r.h for data structures, macros, and user-callable functions.
+   See user_r.c for qhull-related, redefinable functions
+   see user_r.h for user-definable constants
+   See userprintf_r.c for qh_fprintf and userprintf_rbox_r.c for qh_fprintf_rbox
+
+   Please report any errors that you fix to qhull@qhull.org
+*/
+
+#include "libqhull_r.h"
+
+#include "igraph_error.h"
+
+#include 
+#include 
+
+/*---------------------------------
+
+  qh_exit( exitcode )
+    exit program
+    the exitcode must be 255 or less.  Zero indicates success.
+    Note: Exit status ('$?') in bash reports 256 as 0
+
+  notes:
+    qh_exit() is called when qh_errexit() and longjmp() are not available.
+
+    This is the only use of exit() in Qhull
+    To replace qh_exit with 'throw', see libqhullcpp/usermem_r-cpp.cpp
+*/
+void qh_exit(int exitcode) {
+    /* exit(exitcode); */
+    /* This code is not reachable. We comment out exit() to ensure
+     * that the igraph shared library does not reference it. */
+    IGRAPH_FATALF("Qhull called exit() with exit code %d.", exitcode);
+} /* exit */
+
+/*---------------------------------
+
+  qh_fprintf_stderr( msgcode, format, list of args )
+    fprintf to stderr with msgcode (non-zero)
+
+  notes:
+    qh_fprintf_stderr() is called when qh.ferr is not defined, usually due to an initialization error
+    if msgcode is a MSG_ERROR (6000), caller should set qh.last_errcode (like qh_fprintf) or variable 'last_errcode'
+    
+    It is typically followed by qh_errexit().
+
+    Redefine this function to avoid using stderr
+
+    Use qh_fprintf [userprintf_r.c] for normal printing
+*/
+void qh_fprintf_stderr(int msgcode, const char *fmt, ... ) {
+    va_list args;
+
+    va_start(args, fmt);
+    if(msgcode)
+      fprintf(stderr, "QH%.4d ", msgcode);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+} /* fprintf_stderr */
+
+/*---------------------------------
+
+  qh_free(qh, mem )
+    free memory
+
+  notes:
+    same as free()
+    No calls to qh_errexit() 
+*/
+void qh_free(void *mem) {
+    free(mem);
+} /* free */
+
+/*---------------------------------
+
+    qh_malloc( mem )
+      allocate memory
+
+    notes:
+      same as malloc()
+*/
+void *qh_malloc(size_t size) {
+    return malloc(size);
+} /* malloc */
+
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_r.c
new file mode 100644
index 00000000000..7eb3600b34f
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_r.c
@@ -0,0 +1,68 @@
+/*
  ---------------------------------
+
+  userprintf_r.c
+  user redefinable function -- qh_fprintf
+
+  see README.txt  see COPYING.txt for copyright information.
+
+  If you recompile and load this file, then userprintf_r.o will not be loaded
+  from qhull_r.a or qhull_r.lib
+
+  See libqhull_r.h for data structures, macros, and user-callable functions.
+  See user_r.c for qhull-related, redefinable functions
+  see user_r.h for user-definable constants
+  See usermem_r.c for qh_exit(), qh_free(), and qh_malloc()
+  see Qhull.cpp and RboxPoints.cpp for examples.
+
+  qh_printf is a good location for debugging traps, checked on each log line
+
+  Please report any errors that you fix to qhull@qhull.org
+*/
+
+#include "libqhull_r.h"
+#include "poly_r.h" /* for qh.tracefacet */
+
+#include 
+#include 
+#include 
+
+/*---------------------------------
+
+  qh_fprintf(qh, fp, msgcode, format, list of args )
+    print arguments to *fp according to format
+    Use qh_fprintf_rbox() for rboxlib_r.c
+
+  notes:
+    sets qh.last_errcode if msgcode is error 6000..6999
+    same as fprintf()
+    fgets() is not trapped like fprintf()
+    exit qh_fprintf via qh_errexit()
+    may be called for errors in qh_initstatistics and qh_meminit
+*/
+
+void qh_fprintf(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... ) {
+    va_list args;
+    if (qh) {
+        if (msgcode >= MSG_ERROR && msgcode < MSG_WARNING) {
+            qh->last_errcode = msgcode;
+        }
+        if (qh->FLUSHprint) {
+            fflush(fp);
+        }
+    }
+    if (!fp) {
+        return;
+    }
+    if ((qh && qh->ANNOTATEoutput) || msgcode < MSG_TRACE4) {
+        fprintf(fp, "[QH%.4d]", msgcode);
+    } else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) {
+        fprintf(fp, "QH%.4d ", msgcode);
+    }
+    va_start(args, fmt);
+    vfprintf(fp, fmt, args);
+    va_end(args);
+
+} /* qh_fprintf */
+
diff --git a/src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_rbox_r.c b/src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_rbox_r.c
new file mode 100644
index 00000000000..64c16cb57b8
--- /dev/null
+++ b/src/vendor/cigraph/vendor/qhull/libqhull_r/userprintf_rbox_r.c
@@ -0,0 +1,53 @@
+/*
  ---------------------------------
+
+   userprintf_rbox_r.c
+   user redefinable function -- qh_fprintf_rbox
+
+   see README.txt  see COPYING.txt for copyright information.
+
+   If you recompile and load this file, then userprintf_rbox_r.o will not be loaded
+   from qhull.a or qhull.lib
+
+   See libqhull_r.h for data structures, macros, and user-callable functions.
+   See user_r.c for qhull-related, redefinable functions
+   see user_r.h for user-definable constants
+   See usermem_r.c for qh_exit(), qh_free(), and qh_malloc()
+   see Qhull.cpp and RboxPoints.cpp for examples.
+
+   Please report any errors that you fix to qhull@qhull.org
+*/
+
+#include "libqhull_r.h"
+
+#include 
+#include 
+#include 
+
+/*---------------------------------
+
+   qh_fprintf_rbox(qh, fp, msgcode, format, list of args )
+     print arguments to *fp according to format
+     Use qh_fprintf_rbox() for rboxlib_r.c
+
+   notes:
+     same as fprintf()
+     fgets() is not trapped like fprintf()
+     exit qh_fprintf_rbox via qh_errexit_rbox()
+*/
+
+void qh_fprintf_rbox(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... ) {
+    va_list args;
+
+    if (!fp) {
+      qh_fprintf_stderr(6231, "qhull internal error (userprintf_rbox_r.c): fp is 0.  Wrong qh_fprintf_rbox called.\n");
+      qh_errexit_rbox(qh, qh_ERRqhull);
+    }
+    if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR)
+      fprintf(fp, "QH%.4d ", msgcode);
+    va_start(args, fmt);
+    vfprintf(fp, fmt, args);
+    va_end(args);
+} /* qh_fprintf_rbox */
+
diff --git a/src/vendor/igraph_threading.h b/src/vendor/igraph_threading.h
index 3a8faa10e7a..415d8cf01ab 100644
--- a/src/vendor/igraph_threading.h
+++ b/src/vendor/igraph_threading.h
@@ -1,5 +1,5 @@
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2011-2025  The igraph development team 
 
    This program is free software; you can redistribute it and/or modify
diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h
index 5e79535b53d..fc5feb5a9d6 100644
--- a/src/vendor/igraph_version.h
+++ b/src/vendor/igraph_version.h
@@ -1,5 +1,5 @@
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2010-2025  The igraph development team 
 
    This program is free software; you can redistribute it and/or modify
@@ -23,16 +23,16 @@
 
 IGRAPH_BEGIN_C_DECLS
 
-#define IGRAPH_VERSION "0.10.16-913-g1db733b23"
-#define IGRAPH_VERSION_MAJOR 0
-#define IGRAPH_VERSION_MINOR 10
-#define IGRAPH_VERSION_PATCH 16
-#define IGRAPH_VERSION_PRERELEASE "913-g1db733b23"
+#define IGRAPH_VERSION "1.0.0-30-g2d1bce327"
+#define IGRAPH_VERSION_MAJOR 1
+#define IGRAPH_VERSION_MINOR 0
+#define IGRAPH_VERSION_PATCH 0
+#define IGRAPH_VERSION_PRERELEASE "30-g2d1bce327"
 
 IGRAPH_EXPORT void igraph_version(const char **version_string,
                                   int *major,
                                   int *minor,
-                                  int *subminor);
+                                  int *patch);
 
 IGRAPH_END_C_DECLS
 
diff --git a/src/vendor/io/dl-lexer.c b/src/vendor/io/dl-lexer.c
index 4844b12f2e1..6814eaf0a33 100644
--- a/src/vendor/io/dl-lexer.c
+++ b/src/vendor/io/dl-lexer.c
@@ -837,7 +837,7 @@ static const flex_int32_t yy_rule_can_match_eol[25] =
 #define YY_RESTORE_YY_MORE_OFFSET
 #line 1 "src/vendor/cigraph/src/io/dl-lexer.l"
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2007-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -860,7 +860,7 @@ static const flex_int32_t yy_rule_can_match_eol[25] =
 #line 24 "src/vendor/cigraph/src/io/dl-lexer.l"
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2007-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
diff --git a/src/vendor/io/dl-parser.c b/src/vendor/io/dl-parser.c
index b3cb901766e..4b810f27290 100644
--- a/src/vendor/io/dl-parser.c
+++ b/src/vendor/io/dl-parser.c
@@ -76,7 +76,7 @@
 
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2009-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -107,12 +107,12 @@ int igraph_dl_yyerror(YYLTYPE* locp, igraph_i_dl_parsedata_t* context,
                       const char *s);
 static igraph_error_t igraph_i_dl_add_str(char *newstr, yy_size_t length,
                         igraph_i_dl_parsedata_t *context);
-static igraph_error_t igraph_i_dl_add_edge(igraph_integer_t from, igraph_integer_t to,
+static igraph_error_t igraph_i_dl_add_edge(igraph_int_t from, igraph_int_t to,
                          igraph_i_dl_parsedata_t *context);
-static igraph_error_t igraph_i_dl_add_edge_w(igraph_integer_t from, igraph_integer_t to,
+static igraph_error_t igraph_i_dl_add_edge_w(igraph_int_t from, igraph_int_t to,
                            igraph_real_t weight,
                            igraph_i_dl_parsedata_t *context);
-static igraph_error_t igraph_i_dl_check_vid(igraph_integer_t dl_vid);
+static igraph_error_t igraph_i_dl_check_vid(igraph_int_t dl_vid);
 
 #define scanner context->scanner
 
@@ -1848,7 +1848,7 @@ YYLTYPE yylloc = yyloc_default;
   case 40: /* edgelist1dataline: integer integer weight "end of line"  */
 #line 197 "src/vendor/cigraph/src/io/dl-parser.y"
                                                   {
-                    igraph_integer_t from = (yyvsp[-3].integer), to = (yyvsp[-2].integer);
+                    igraph_int_t from = (yyvsp[-3].integer), to = (yyvsp[-2].integer);
                     IGRAPH_YY_CHECK(igraph_i_dl_check_vid(from));
                     IGRAPH_YY_CHECK(igraph_i_dl_check_vid(to));
                     IGRAPH_YY_CHECK(igraph_i_dl_add_edge_w(from-1, to-1, (yyvsp[-1].real), context)); }
@@ -1858,7 +1858,7 @@ YYLTYPE yylloc = yyloc_default;
   case 41: /* edgelist1dataline: integer integer "end of line"  */
 #line 202 "src/vendor/cigraph/src/io/dl-parser.y"
                                            {
-                    igraph_integer_t from = (yyvsp[-2].integer), to = (yyvsp[-1].integer);
+                    igraph_int_t from = (yyvsp[-2].integer), to = (yyvsp[-1].integer);
                     IGRAPH_YY_CHECK(igraph_i_dl_check_vid(from));
                     IGRAPH_YY_CHECK(igraph_i_dl_check_vid(to));
                     IGRAPH_YY_CHECK(igraph_i_dl_add_edge(from-1, to-1, context));
@@ -1869,7 +1869,7 @@ YYLTYPE yylloc = yyloc_default;
   case 42: /* integer: "number"  */
 #line 209 "src/vendor/cigraph/src/io/dl-parser.y"
              {
-    igraph_integer_t val;
+    igraph_int_t val;
     IGRAPH_YY_CHECK(igraph_i_parse_integer(igraph_dl_yyget_text(scanner),
                                            igraph_dl_yyget_leng(scanner),
                                            &val));
@@ -1920,11 +1920,11 @@ YYLTYPE yylloc = yyloc_default;
   case 48: /* elabel: "label"  */
 #line 235 "src/vendor/cigraph/src/io/dl-parser.y"
               {
-  igraph_integer_t trie_id;
+  igraph_int_t trie_id;
 
   /* Copy label list to trie, if needed */
   if (igraph_strvector_size(&context->labels) != 0) {
-    igraph_integer_t i, id, n=igraph_strvector_size(&context->labels);
+    igraph_int_t i, id, n=igraph_strvector_size(&context->labels);
     for (i=0; itrie, igraph_strvector_get(&context->labels, i), &id));
     }
@@ -2012,7 +2012,7 @@ YYLTYPE yylloc = yyloc_default;
   case 60: /* tolist: tolist integer  */
 #line 276 "src/vendor/cigraph/src/io/dl-parser.y"
                             {
-  igraph_integer_t to = (yyvsp[0].integer);
+  igraph_int_t to = (yyvsp[0].integer);
   IGRAPH_YY_CHECK(igraph_i_dl_check_vid(to));
   IGRAPH_YY_CHECK(igraph_vector_int_push_back(&context->edges,
                                               context->from-1));
@@ -2305,7 +2305,7 @@ static igraph_error_t igraph_i_dl_add_str(char *newstr, yy_size_t length,
   return IGRAPH_SUCCESS;
 }
 
-static igraph_error_t igraph_i_dl_add_edge(igraph_integer_t from, igraph_integer_t to,
+static igraph_error_t igraph_i_dl_add_edge(igraph_int_t from, igraph_int_t to,
                          igraph_i_dl_parsedata_t *context) {
   //IGRAPH_CHECK(igraph_i_dl_check_vid(from+1));
   //IGRAPH_CHECK(igraph_i_dl_check_vid(to+1));
@@ -2314,11 +2314,11 @@ static igraph_error_t igraph_i_dl_add_edge(igraph_integer_t from, igraph_integer
   return IGRAPH_SUCCESS;
 }
 
-static igraph_error_t igraph_i_dl_add_edge_w(igraph_integer_t from, igraph_integer_t to,
+static igraph_error_t igraph_i_dl_add_edge_w(igraph_int_t from, igraph_int_t to,
                            igraph_real_t weight,
                            igraph_i_dl_parsedata_t *context) {
-  igraph_integer_t n=igraph_vector_size(&context->weights);
-  igraph_integer_t n2=igraph_vector_int_size(&context->edges)/2;
+  igraph_int_t n=igraph_vector_size(&context->weights);
+  igraph_int_t n2=igraph_vector_int_size(&context->edges)/2;
   if (n != n2) {
     IGRAPH_CHECK(igraph_vector_resize(&context->weights, n2));
     for (; n
    334 Harvard st, Cambridge, MA, 02138 USA
 
diff --git a/src/vendor/io/gml-parser.c b/src/vendor/io/gml-parser.c
index 66a809a3b61..c9fe95bd9c6 100644
--- a/src/vendor/io/gml-parser.c
+++ b/src/vendor/io/gml-parser.c
@@ -76,7 +76,7 @@
 
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2009-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -1893,7 +1893,7 @@ static igraph_error_t igraph_i_gml_make_numeric(const char *name,
   IGRAPH_FINALLY(igraph_free, t);
 
   /* The GML spec only requires support for 32-bit signed integers,
-   * but igraph tries to support the same range as igraph_integer_t,
+   * but igraph tries to support the same range as igraph_int_t,
    * so that it can read/write all graphs it can represent.
    * We treat anything out of that range as real. These values end
    * up as igraph_real_t anyway, as igraph does not currently support
diff --git a/src/vendor/io/lgl-lexer.c b/src/vendor/io/lgl-lexer.c
index d202b600b82..547946952d4 100644
--- a/src/vendor/io/lgl-lexer.c
+++ b/src/vendor/io/lgl-lexer.c
@@ -682,7 +682,7 @@ static const flex_int32_t yy_rule_can_match_eol[7] =
 #define YY_RESTORE_YY_MORE_OFFSET
 #line 1 "src/vendor/cigraph/src/io/lgl-lexer.l"
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2007-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -705,7 +705,7 @@ static const flex_int32_t yy_rule_can_match_eol[7] =
 #line 24 "src/vendor/cigraph/src/io/lgl-lexer.l"
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2007-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
diff --git a/src/vendor/io/lgl-parser.c b/src/vendor/io/lgl-parser.c
index ff1fb8cd812..76904374aa3 100644
--- a/src/vendor/io/lgl-parser.c
+++ b/src/vendor/io/lgl-parser.c
@@ -76,7 +76,7 @@
 
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2006-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -1536,7 +1536,7 @@ YYLTYPE yylloc = yyloc_default;
   case 11: /* edgeid: "alphanumeric"  */
 #line 117 "src/vendor/cigraph/src/io/lgl-parser.y"
                 {
-  igraph_integer_t trie_id;
+  igraph_int_t trie_id;
   IGRAPH_YY_CHECK(igraph_trie_get_len(context->trie,
     igraph_lgl_yyget_text(scanner),
     igraph_lgl_yyget_leng(scanner),
diff --git a/src/vendor/io/ncol-lexer.c b/src/vendor/io/ncol-lexer.c
index 393423e5f4d..2d83aca793a 100644
--- a/src/vendor/io/ncol-lexer.c
+++ b/src/vendor/io/ncol-lexer.c
@@ -682,7 +682,7 @@ static const flex_int32_t yy_rule_can_match_eol[6] =
 #define YY_RESTORE_YY_MORE_OFFSET
 #line 1 "src/vendor/cigraph/src/io/ncol-lexer.l"
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2006-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -705,7 +705,7 @@ static const flex_int32_t yy_rule_can_match_eol[6] =
 #line 24 "src/vendor/cigraph/src/io/ncol-lexer.l"
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2006-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
diff --git a/src/vendor/io/ncol-parser.c b/src/vendor/io/ncol-parser.c
index 2c64493ac68..d60a9f24737 100644
--- a/src/vendor/io/ncol-parser.c
+++ b/src/vendor/io/ncol-parser.c
@@ -76,7 +76,7 @@
 
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2006-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -1528,7 +1528,7 @@ YYLTYPE yylloc = yyloc_default;
   case 8: /* edgeid: "alphanumeric"  */
 #line 111 "src/vendor/cigraph/src/io/ncol-parser.y"
                 {
-  igraph_integer_t trie_id;
+  igraph_int_t trie_id;
   IGRAPH_YY_CHECK(igraph_trie_get_len(context->trie,
     igraph_ncol_yyget_text(scanner),
     igraph_ncol_yyget_leng(scanner),
diff --git a/src/vendor/io/pajek-lexer.c b/src/vendor/io/pajek-lexer.c
index 781f2e869e1..dd12ab7ae5d 100644
--- a/src/vendor/io/pajek-lexer.c
+++ b/src/vendor/io/pajek-lexer.c
@@ -835,7 +835,7 @@ static const flex_int32_t yy_rule_can_match_eol[58] =
 #define YY_RESTORE_YY_MORE_OFFSET
 #line 1 "src/vendor/cigraph/src/io/pajek-lexer.l"
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2006-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -858,7 +858,7 @@ static const flex_int32_t yy_rule_can_match_eol[58] =
 #line 24 "src/vendor/cigraph/src/io/pajek-lexer.l"
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2006-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
diff --git a/src/vendor/io/pajek-parser.c b/src/vendor/io/pajek-parser.c
index 466796d5633..ce2bdf8b804 100644
--- a/src/vendor/io/pajek-parser.c
+++ b/src/vendor/io/pajek-parser.c
@@ -76,7 +76,7 @@
 
 
 /*
-   IGraph library.
+   igraph library.
    Copyright (C) 2006-2012  Gabor Csardi 
    334 Harvard st, Cambridge, MA, 02138 USA
 
@@ -132,19 +132,19 @@ static igraph_error_t add_numeric_edge_attribute(const char *name,
                                               igraph_i_pajek_parsedata_t *context);
 static igraph_error_t add_numeric_attribute(igraph_trie_t *names,
                                          igraph_attribute_record_list_t *attrs,
-                                         igraph_integer_t count,
+                                         igraph_int_t count,
                                          const char *attrname,
                                          igraph_real_t default_value,
-                                         igraph_integer_t vid,
+                                         igraph_int_t vid,
                                          igraph_real_t number);
 static igraph_error_t add_string_attribute(igraph_trie_t *names,
                                         igraph_attribute_record_list_t *attrs,
-                                        igraph_integer_t count,
+                                        igraph_int_t count,
                                         const char *attrname,
                                         const char *default_value,
-                                        igraph_integer_t vid,
+                                        igraph_int_t vid,
                                         const char *str,
-                                        igraph_integer_t str_len);
+                                        igraph_int_t str_len);
 
 static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context);
 static igraph_error_t check_bipartite(igraph_i_pajek_parsedata_t *context);
@@ -1860,7 +1860,7 @@ YYLTYPE yylloc = yyloc_default;
   case 14: /* vertexline: vertex $@1 vertexid vertexcoords shape vertparams "end of line"  */
 #line 244 "src/vendor/cigraph/src/io/pajek-parser.y"
                                                                                              {
-              igraph_integer_t v = (yyvsp[-6].intnum)-1; /* zero-based vertex ID */
+              igraph_int_t v = (yyvsp[-6].intnum)-1; /* zero-based vertex ID */
               if (IGRAPH_BIT_TEST(*context->seen, v)) {
                 IGRAPH_WARNINGF("Vertex ID %" IGRAPH_PRId " appears twice in Pajek file. Duplicate attributes will be overwritten.", v+1);
               } else {
@@ -1873,7 +1873,7 @@ YYLTYPE yylloc = yyloc_default;
   case 15: /* vertex: integer  */
 #line 254 "src/vendor/cigraph/src/io/pajek-parser.y"
                 {
-  igraph_integer_t v = (yyvsp[0].intnum);
+  igraph_int_t v = (yyvsp[0].intnum);
   /* Per feedback from Pajek's authors, negative signs should be ignored for vertex IDs.
    * See https://nascol.discourse.group/t/pajek-arcslist-edgelist-format/44/2
    * This applies to all of *Edges, *Arcs, *Edgeslist, *Arcslist and *Vertices section.
@@ -2386,7 +2386,7 @@ YYLTYPE yylloc = yyloc_default;
   case 109: /* integer: "number"  */
 #line 530 "src/vendor/cigraph/src/io/pajek-parser.y"
              {
-  igraph_integer_t val;
+  igraph_int_t val;
   IGRAPH_YY_CHECK(igraph_i_parse_integer(igraph_pajek_yyget_text(scanner),
                                          igraph_pajek_yyget_leng(scanner),
                                          &val));
@@ -2688,13 +2688,13 @@ int igraph_pajek_yyerror(YYLTYPE* locp,
 
 static igraph_error_t add_numeric_attribute(igraph_trie_t *names,
                                             igraph_attribute_record_list_t *attrs,
-                                            igraph_integer_t count,
+                                            igraph_int_t count,
                                             const char *attrname,
                                             igraph_real_t default_value,
-                                            igraph_integer_t elem_id,
+                                            igraph_int_t elem_id,
                                             igraph_real_t number) {
-  igraph_integer_t attrsize = igraph_trie_size(names);
-  igraph_integer_t id;
+  igraph_int_t attrsize = igraph_trie_size(names);
+  igraph_int_t id;
   igraph_vector_t *na;
   igraph_attribute_record_t *prec;
 
@@ -2735,14 +2735,14 @@ static igraph_error_t make_dynstr(const char *src, size_t len, char **res) {
 
 static igraph_error_t add_string_attribute(igraph_trie_t *names,
                                            igraph_attribute_record_list_t *attrs,
-                                           igraph_integer_t count,
+                                           igraph_int_t count,
                                            const char *attrname,
                                            const char *default_value,
-                                           igraph_integer_t elem_id,
+                                           igraph_int_t elem_id,
                                            const char *str,
-                                           igraph_integer_t str_len) {
-  igraph_integer_t attrsize=igraph_trie_size(names);
-  igraph_integer_t id;
+                                           igraph_int_t str_len) {
+  igraph_int_t attrsize=igraph_trie_size(names);
+  igraph_int_t id;
   igraph_strvector_t *na;
   igraph_attribute_record_t *prec;
 
@@ -2843,8 +2843,8 @@ 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_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_int_t n=context->vcount, n1=context->vcount2;
+  igraph_int_t attrid, attrsize = igraph_trie_size(names);
   igraph_attribute_record_t* rec;
   igraph_vector_bool_t *na;
 
@@ -2866,7 +2866,7 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) {
   IGRAPH_CHECK(igraph_attribute_record_resize(rec, n));
 
   na = rec->value.as_vector_bool;
-  for (igraph_integer_t i = n1; i < n; i++) {
+  for (igraph_int_t i = n1; i < n; i++) {
     VECTOR(*na)[i] = true;
   }
 
@@ -2875,12 +2875,12 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) {
 
 static igraph_error_t check_bipartite(igraph_i_pajek_parsedata_t *context) {
   const igraph_vector_int_t *edges=context->vector;
-  igraph_integer_t n1=context->vcount2;
-  igraph_integer_t ne=igraph_vector_int_size(edges);
+  igraph_int_t n1=context->vcount2;
+  igraph_int_t ne=igraph_vector_int_size(edges);
 
-  for (igraph_integer_t i=0; i n1 && v2 > n1) ) {
       IGRAPH_WARNING("Invalid edge in bipartite graph.");
     }
diff --git a/src/vendor/io/parsers/dl-parser.h b/src/vendor/io/parsers/dl-parser.h
index 46dac54e14b..95b943f5eac 100644
--- a/src/vendor/io/parsers/dl-parser.h
+++ b/src/vendor/io/parsers/dl-parser.h
@@ -78,7 +78,7 @@ union YYSTYPE
 {
 #line 78 "src/vendor/cigraph/src/io/dl-parser.y"
 
-  igraph_integer_t integer;
+  igraph_int_t integer;
   igraph_real_t real;
 
 #line 85 "src/vendor/io/dl-parser.h"
diff --git a/src/vendor/io/parsers/lgl-parser.h b/src/vendor/io/parsers/lgl-parser.h
index b391c8fac2b..e7929b4047f 100644
--- a/src/vendor/io/parsers/lgl-parser.h
+++ b/src/vendor/io/parsers/lgl-parser.h
@@ -68,7 +68,7 @@ union YYSTYPE
 {
 #line 76 "src/vendor/cigraph/src/io/lgl-parser.y"
 
-  igraph_integer_t edgenum;
+  igraph_int_t edgenum;
   igraph_real_t weightnum;
 
 #line 75 "src/vendor/io/lgl-parser.h"
diff --git a/src/vendor/io/parsers/ncol-parser.h b/src/vendor/io/parsers/ncol-parser.h
index 361262035fe..c00fbf67c61 100644
--- a/src/vendor/io/parsers/ncol-parser.h
+++ b/src/vendor/io/parsers/ncol-parser.h
@@ -67,7 +67,7 @@ union YYSTYPE
 {
 #line 77 "src/vendor/cigraph/src/io/ncol-parser.y"
 
-  igraph_integer_t edgenum;
+  igraph_int_t edgenum;
   igraph_real_t weightnum;
 
 #line 74 "src/vendor/io/ncol-parser.h"
diff --git a/src/vendor/io/parsers/pajek-parser.h b/src/vendor/io/parsers/pajek-parser.h
index 64ada07751d..1f9b313a94c 100644
--- a/src/vendor/io/parsers/pajek-parser.h
+++ b/src/vendor/io/parsers/pajek-parser.h
@@ -111,7 +111,7 @@ union YYSTYPE
 {
 #line 122 "src/vendor/cigraph/src/io/pajek-parser.y"
 
-  igraph_integer_t intnum;
+  igraph_int_t intnum;
   igraph_real_t    realnum;
   struct {
     char *str;

From a2ed929992ab1eaa4c27da2353d37b7e3e94a64f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 10:45:57 +0200
Subject: [PATCH 088/154] Document

---
 man/assortativity.Rd       |  8 +++++-
 man/cliques.Rd             |  2 +-
 man/edge_density.Rd        |  2 +-
 man/harmonic_centrality.Rd |  2 +-
 man/page_rank.Rd           | 50 +++++++++++++++++++-------------------
 man/sample_fitness.Rd      |  3 +--
 man/sample_fitness_pl.Rd   |  9 +++----
 man/sample_sbm.Rd          | 15 ++++++++----
 man/weighted_cliques.Rd    | 13 +++++-----
 9 files changed, 57 insertions(+), 47 deletions(-)

diff --git a/man/assortativity.Rd b/man/assortativity.Rd
index 038771a866a..97a9fd54754 100644
--- a/man/assortativity.Rd
+++ b/man/assortativity.Rd
@@ -17,7 +17,13 @@ assortativity(
   types2 = NULL
 )
 
-assortativity_nominal(graph, types, directed = TRUE, normalized = TRUE)
+assortativity_nominal(
+  graph,
+  weights = NULL,
+  types,
+  directed = TRUE,
+  normalized = TRUE
+)
 
 assortativity_degree(graph, directed = TRUE)
 }
diff --git a/man/cliques.Rd b/man/cliques.Rd
index fcf314fd78a..4204c2c3ecf 100644
--- a/man/cliques.Rd
+++ b/man/cliques.Rd
@@ -12,7 +12,7 @@
 \alias{is_clique}
 \title{Functions to find cliques, i.e. complete subgraphs in a graph}
 \usage{
-cliques(graph, min = 0, max = 0)
+cliques(graph, min = UNLIMITED, max = UNLIMITED, max.results = UNLIMITED)
 
 largest_cliques(graph)
 
diff --git a/man/edge_density.Rd b/man/edge_density.Rd
index 99b4db0eb71..6c9b330f3bb 100644
--- a/man/edge_density.Rd
+++ b/man/edge_density.Rd
@@ -4,7 +4,7 @@
 \alias{edge_density}
 \title{Graph density}
 \usage{
-edge_density(graph, loops = FALSE)
+edge_density(graph, weights = NULL, loops = FALSE)
 }
 \arguments{
 \item{graph}{The input graph.}
diff --git a/man/harmonic_centrality.Rd b/man/harmonic_centrality.Rd
index c70629c847d..ae8184aec5b 100644
--- a/man/harmonic_centrality.Rd
+++ b/man/harmonic_centrality.Rd
@@ -10,7 +10,7 @@ harmonic_centrality(
   mode = c("out", "in", "all", "total"),
   weights = NULL,
   normalized = FALSE,
-  cutoff = -1
+  cutoff = UNLIMITED
 )
 }
 \arguments{
diff --git a/man/page_rank.Rd b/man/page_rank.Rd
index 182032cf711..7cec30c3880 100644
--- a/man/page_rank.Rd
+++ b/man/page_rank.Rd
@@ -6,18 +6,35 @@
 \usage{
 page_rank(
   graph,
-  algo = c("prpack", "arpack"),
-  vids = V(graph),
-  directed = TRUE,
-  damping = 0.85,
-  personalized = NULL,
   weights = NULL,
+  reset = NULL,
+  damping = 0.85,
+  directed = TRUE,
+  vids = V(graph),
+  algo = c("prpack", "arpack"),
   options = NULL
 )
 }
 \arguments{
 \item{graph}{The graph object.}
 
+\item{weights}{A numerical vector or \code{NULL}. This argument can be used
+to give edge weights for calculating the weighted PageRank of vertices. If
+this is \code{NULL} and the graph has a \code{weight} edge attribute then
+that is used. If \code{weights} is a numerical vector then it used, even if
+the graph has a \code{weights} edge attribute. If this is \code{NA}, then no
+edge weights are used (even if the graph has a \code{weight} edge attribute.
+This function interprets edge weights as connection strengths. In the
+random surfer model, an edge with a larger weight is more likely to be
+selected by the surfer.}
+
+\item{damping}{The damping factor (\sQuote{d} in the original paper).}
+
+\item{directed}{Logical, if true directed paths will be considered for
+directed graphs. It is ignored for undirected graphs.}
+
+\item{vids}{The vertices of interest.}
+
 \item{algo}{Character scalar, which implementation to use to carry out the
 calculation. The default is \code{"prpack"}, which uses the PRPACK library
 (\url{https://github.com/dgleich/prpack}) to calculate PageRank scores
@@ -27,32 +44,15 @@ for all but small graphs.  \code{"arpack"} uses the ARPACK library, the
 default implementation from igraph version 0.5 until version 0.7. It computes
 PageRank scores by solving an eingevalue problem.}
 
-\item{vids}{The vertices of interest.}
-
-\item{directed}{Logical, if true directed paths will be considered for
-directed graphs. It is ignored for undirected graphs.}
-
-\item{damping}{The damping factor (\sQuote{d} in the original paper).}
+\item{options}{A named list, to override some ARPACK options. See
+\code{\link[=arpack]{arpack()}} for details. This argument is ignored if the PRPACK
+implementation is used.}
 
 \item{personalized}{Optional vector giving a probability distribution to
 calculate personalized PageRank. For personalized PageRank, the probability
 of jumping to a node when abandoning the random walk is not uniform, but it
 is given by this vector. The vector should contains an entry for each vertex
 and it will be rescaled to sum up to one.}
-
-\item{weights}{A numerical vector or \code{NULL}. This argument can be used
-to give edge weights for calculating the weighted PageRank of vertices. If
-this is \code{NULL} and the graph has a \code{weight} edge attribute then
-that is used. If \code{weights} is a numerical vector then it used, even if
-the graph has a \code{weights} edge attribute. If this is \code{NA}, then no
-edge weights are used (even if the graph has a \code{weight} edge attribute.
-This function interprets edge weights as connection strengths. In the
-random surfer model, an edge with a larger weight is more likely to be
-selected by the surfer.}
-
-\item{options}{A named list, to override some ARPACK options. See
-\code{\link[=arpack]{arpack()}} for details. This argument is ignored if the PRPACK
-implementation is used.}
 }
 \value{
 A named list with entries:
diff --git a/man/sample_fitness.Rd b/man/sample_fitness.Rd
index 28d1ec28925..9e299a9a53e 100644
--- a/man/sample_fitness.Rd
+++ b/man/sample_fitness.Rd
@@ -8,8 +8,7 @@ sample_fitness(
   no.of.edges,
   fitness.out,
   fitness.in = NULL,
-  loops = FALSE,
-  multiple = FALSE
+  allowed.edge.types = c("simple", "loops", "multi", "all")
 )
 }
 \arguments{
diff --git a/man/sample_fitness_pl.Rd b/man/sample_fitness_pl.Rd
index 003c9ae2411..7981f0f1cfb 100644
--- a/man/sample_fitness_pl.Rd
+++ b/man/sample_fitness_pl.Rd
@@ -9,8 +9,7 @@ sample_fitness_pl(
   no.of.edges,
   exponent.out,
   exponent.in = -1,
-  loops = FALSE,
-  multiple = FALSE,
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
   finite.size.correction = TRUE
 )
 }
@@ -29,14 +28,14 @@ undirected. If greater than or equal to 2, this argument specifies the
 exponent of the in-degree distribution. If non-negative but less than 2, an
 error will be generated.}
 
+\item{finite.size.correction}{Logical scalar, whether to use the proposed
+finite size correction of Cho et al., see references below.}
+
 \item{loops}{Logical scalar, whether to allow loop edges in the generated
 graph.}
 
 \item{multiple}{Logical scalar, whether to allow multiple edges in the
 generated graph.}
-
-\item{finite.size.correction}{Logical scalar, whether to use the proposed
-finite size correction of Cho et al., see references below.}
 }
 \value{
 An igraph graph, directed or undirected.
diff --git a/man/sample_sbm.Rd b/man/sample_sbm.Rd
index 1fe65860ee8..f9897450a61 100644
--- a/man/sample_sbm.Rd
+++ b/man/sample_sbm.Rd
@@ -5,13 +5,16 @@
 \alias{sbm}
 \title{Sample stochastic block model}
 \usage{
-sample_sbm(n, pref.matrix, block.sizes, directed = FALSE, loops = FALSE)
+sample_sbm(
+  pref.matrix,
+  block.sizes,
+  directed = FALSE,
+  allowed.edge.types = c("simple", "loops", "multi", "all")
+)
 
 sbm(...)
 }
 \arguments{
-\item{n}{Number of vertices in the graph.}
-
 \item{pref.matrix}{The matrix giving the Bernoulli rates.  This is a
 \eqn{K\times K}{KxK} matrix, where \eqn{K} is the number of groups. The
 probability of creating an edge between vertices from groups \eqn{i} and
@@ -23,9 +26,11 @@ group. The sum of the vector must match the number of vertices.}
 
 \item{directed}{Logical scalar, whether to generate a directed graph.}
 
-\item{loops}{Logical scalar, whether self-loops are allowed in the graph.}
-
 \item{...}{Passed to \code{sample_sbm()}.}
+
+\item{n}{Number of vertices in the graph.}
+
+\item{loops}{Logical scalar, whether self-loops are allowed in the graph.}
 }
 \value{
 An igraph graph.
diff --git a/man/weighted_cliques.Rd b/man/weighted_cliques.Rd
index d3af9be3171..a2bc0797ed3 100644
--- a/man/weighted_cliques.Rd
+++ b/man/weighted_cliques.Rd
@@ -7,9 +7,10 @@
 weighted_cliques(
   graph,
   vertex.weights = NULL,
-  min.weight = 0,
-  max.weight = 0,
-  maximal = FALSE
+  maximal = FALSE,
+  min.weight = UNLIMITED,
+  max.weight = UNLIMITED,
+  max.results = UNLIMITED
 )
 }
 \arguments{
@@ -22,14 +23,14 @@ vertex attribute, then this is used by default. If the graph does not have a
 vertex is assumed to have a weight of 1. Note that the current implementation
 of the weighted clique finder supports positive integer weights only.}
 
+\item{maximal}{Specifies whether to look for all weighted cliques (\code{FALSE})
+or only the maximal ones (\code{TRUE}).}
+
 \item{min.weight}{Numeric constant, lower limit on the weight of the cliques to find.
 \code{NULL} means no limit, i.e. it is the same as 0.}
 
 \item{max.weight}{Numeric constant, upper limit on the weight of the cliques to find.
 \code{NULL} means no limit.}
-
-\item{maximal}{Specifies whether to look for all weighted cliques (\code{FALSE})
-or only the maximal ones (\code{TRUE}).}
 }
 \value{
 \code{weighted_cliques()} and \code{largest_weighted_cliques()} return a

From 5f90a0e93f07a1fb30848ef32e009e7dcbc14425 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Fri, 24 Oct 2025 14:58:12 +0200
Subject: [PATCH 089/154] Snapshot updates

---
 tests/testthat/_snaps/aaa-auto.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/testthat/_snaps/aaa-auto.md b/tests/testthat/_snaps/aaa-auto.md
index a755d144f68..27225b3a2d1 100644
--- a/tests/testthat/_snaps/aaa-auto.md
+++ b/tests/testthat/_snaps/aaa-auto.md
@@ -1174,7 +1174,7 @@
       dot_product_game_impl(matrix(0.5, 5, 2))
     Condition
       Warning in `dot_product_game_impl()`:
-      At vendor/cigraph/src/games/dotproduct.c:87 : Greater than 1 connection probability in dot-product graph.
+      At vendor/cigraph/src/games/dotproduct.c:86 : Greater than 1 connection probability in dot-product graph.
     Output
       IGRAPH U--- 2 1 -- 
       + edge:
@@ -1186,7 +1186,7 @@
       dot_product_game_impl(matrix(0.5, 5, 2), directed = TRUE)
     Condition
       Warning in `dot_product_game_impl()`:
-      At vendor/cigraph/src/games/dotproduct.c:87 : Greater than 1 connection probability in dot-product graph.
+      At vendor/cigraph/src/games/dotproduct.c:86 : Greater than 1 connection probability in dot-product graph.
     Output
       IGRAPH D--- 2 2 -- 
       + edges:
@@ -5736,7 +5736,7 @@
       triad_census_impl(g)
     Condition
       Warning in `triad_census_impl()`:
-      At vendor/cigraph/src/misc/motifs.c:1167 : Triad census called on an undirected graph. All connections will be treated as mutual.
+      At vendor/cigraph/src/misc/motifs.c:1170 : Triad census called on an undirected graph. All connections will be treated as mutual.
     Output
        [1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
 
@@ -9600,7 +9600,7 @@
     Code
       version_impl_clean()
     Output
-      [1] "0.10.16"
+      [1] "1.0.0"
 
 # version_impl errors
 

From 5556a920728e5a410a1bbed2f509cde51c12a808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 21:29:33 +0200
Subject: [PATCH 090/154] Remove storage arg

---
 R/aaa-auto.R                 | 4 ++--
 src/cpp11.cpp                | 4 ++--
 tools/stimulus/types-RR.yaml | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index 4987848c663..b6adff86b94 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -5225,7 +5225,7 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c("
   res
 }
 
-eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack"), which=list(), options=arpack_defaults(), storage) {
+eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack"), which=list(), options=arpack_defaults()) {
   # Argument checks
   ensure_igraph(graph)
   algorithm <- switch_igraph_arg(algorithm, "auto" = 0L, "lapack" = 1L,
@@ -5237,7 +5237,7 @@ eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack",
 
   on.exit( .Call(R_igraph_finalizer) )
   # Function call
-  res <- .Call(R_igraph_eigen_adjacency, graph, algorithm, which, options, storage)
+  res <- .Call(R_igraph_eigen_adjacency, graph, algorithm, which, options)
 
   res
 }
diff --git a/src/cpp11.cpp b/src/cpp11.cpp
index ad77d25fc5d..9046075ad19 100644
--- a/src/cpp11.cpp
+++ b/src/cpp11.cpp
@@ -160,7 +160,7 @@ extern SEXP R_igraph_edge_connectivity(SEXP, SEXP);
 extern SEXP R_igraph_edge_disjoint_paths(SEXP, SEXP, SEXP);
 extern SEXP R_igraph_edgelist_percolation(SEXP);
 extern SEXP R_igraph_edges(SEXP, SEXP);
-extern SEXP R_igraph_eigen_adjacency(SEXP, SEXP, SEXP, SEXP, SEXP);
+extern SEXP R_igraph_eigen_adjacency(SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_eigenvector_centrality(SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_empty(SEXP, SEXP);
 extern SEXP R_igraph_erdos_renyi_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP);
@@ -643,7 +643,7 @@ static const R_CallMethodDef CallEntries[] = {
     {"R_igraph_edge_disjoint_paths",                        (DL_FUNC) &R_igraph_edge_disjoint_paths,                         3},
     {"R_igraph_edgelist_percolation",                       (DL_FUNC) &R_igraph_edgelist_percolation,                        1},
     {"R_igraph_edges",                                      (DL_FUNC) &R_igraph_edges,                                       2},
-    {"R_igraph_eigen_adjacency",                            (DL_FUNC) &R_igraph_eigen_adjacency,                             5},
+    {"R_igraph_eigen_adjacency",                            (DL_FUNC) &R_igraph_eigen_adjacency,                             4},
     {"R_igraph_eigenvector_centrality",                     (DL_FUNC) &R_igraph_eigenvector_centrality,                      4},
     {"R_igraph_empty",                                      (DL_FUNC) &R_igraph_empty,                                       2},
     {"R_igraph_erdos_renyi_game_gnm",                       (DL_FUNC) &R_igraph_erdos_renyi_game_gnm,                        5},
diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml
index 812dc9f4320..9311dce03a5 100644
--- a/tools/stimulus/types-RR.yaml
+++ b/tools/stimulus/types-RR.yaml
@@ -275,7 +275,7 @@ EDGESET_LIST:
               %I% <- lapply(%I%, unsafe_create_es, graph = %I1%, es = E(%I1%))
             }
 
-'ARPACKSTORAGE':
+ARPACK_STORAGE:
     CALL: {}
     HEADER: ~
 

From cc4e6d744289c2f0fe7387ea9848bed1a22c2095 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 19:09:48 +0000
Subject: [PATCH 091/154] Replace `_impl` aliases with explicit wrapper
 functions in `R/games.R`

Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/games.R | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 143 insertions(+), 11 deletions(-)

diff --git a/R/games.R b/R/games.R
index 7c9a1d8f996..27666c5e3fc 100644
--- a/R/games.R
+++ b/R/games.R
@@ -1462,7 +1462,15 @@ degseq <- function(..., deterministic = FALSE) {
 #' g2 <- sample_growing(500, citation = TRUE)
 #'
 #' @cdocs igraph_growing_random_game
-sample_growing <- growing_random_game_impl
+sample_growing <- function(n, m = 1, ..., directed = TRUE, citation = FALSE) {
+  growing_random_game_impl(
+    n = n,
+    m = m,
+    ...,
+    directed = directed,
+    citation = citation
+  )
+}
 
 #' @rdname sample_growing
 #' @param ... Passed to `sample_growing()`.
@@ -2492,7 +2500,21 @@ sample_bipartite_gnp <- function(
 #' @family games
 #' @export
 #' @cdocs igraph_sbm_game
-sample_sbm <- sbm_game_impl
+sample_sbm <- function(
+  n,
+  pref.matrix,
+  block.sizes,
+  directed = FALSE,
+  loops = FALSE
+) {
+  sbm_game_impl(
+    n = n,
+    pref.matrix = pref.matrix,
+    block.sizes = block.sizes,
+    directed = directed,
+    loops = loops
+  )
+}
 
 #' @rdname sample_sbm
 #' @param ... Passed to `sample_sbm()`.
@@ -2621,7 +2643,12 @@ hierarchical_sbm <- function(...) {
 #' @family games
 #' @export
 #' @cdocs igraph_dot_product_game
-sample_dot_product <- dot_product_game_impl
+sample_dot_product <- function(vecs, directed = FALSE) {
+  dot_product_game_impl(
+    vecs = vecs,
+    directed = directed
+  )
+}
 
 #' @rdname sample_dot_product
 #' @param ... Passed to `sample_dot_product()`.
@@ -2653,7 +2680,14 @@ dot_product <- function(...) constructor_spec(sample_dot_product, ...)
 #' @family games
 #' @export
 #' @cdocs igraph_simple_interconnected_islands_game
-sample_islands <- simple_interconnected_islands_game_impl
+sample_islands <- function(islands.n, islands.size, islands.pin, n.inter) {
+  simple_interconnected_islands_game_impl(
+    islands.n = islands.n,
+    islands.size = islands.size,
+    islands.pin = islands.pin,
+    n.inter = n.inter
+  )
+}
 
 
 #' Create a random regular graph
@@ -2692,7 +2726,19 @@ sample_islands <- simple_interconnected_islands_game_impl
 #' @family games
 #' @export
 #' @cdocs igraph_k_regular_game
-sample_k_regular <- k_regular_game_impl
+sample_k_regular <- function(
+  no.of.nodes,
+  k,
+  directed = FALSE,
+  multiple = FALSE
+) {
+  k_regular_game_impl(
+    no.of.nodes = no.of.nodes,
+    k = k,
+    directed = directed,
+    multiple = multiple
+  )
+}
 
 
 #' Random graph with given expected degrees
@@ -2841,7 +2887,21 @@ sample_k_regular <- k_regular_game_impl
 #' ))
 #' @export
 #' @cdocs igraph_chung_lu_game
-sample_chung_lu <- chung_lu_game_impl
+sample_chung_lu <- function(
+  out.weights,
+  in.weights = NULL,
+  ...,
+  loops = TRUE,
+  variant = c("original", "maxent", "nr")
+) {
+  chung_lu_game_impl(
+    out.weights = out.weights,
+    in.weights = in.weights,
+    ...,
+    loops = loops,
+    variant = variant
+  )
+}
 
 #' @rdname sample_chung_lu
 #' @export
@@ -2923,7 +2983,21 @@ chung_lu <- function(
 #' degree_distribution(g)
 #' plot(degree_distribution(g, cumulative = TRUE), log = "xy")
 #' @cdocs igraph_static_fitness_game
-sample_fitness <- static_fitness_game_impl
+sample_fitness <- function(
+  no.of.edges,
+  fitness.out,
+  fitness.in = NULL,
+  loops = FALSE,
+  multiple = FALSE
+) {
+  static_fitness_game_impl(
+    no.of.edges = no.of.edges,
+    fitness.out = fitness.out,
+    fitness.in = fitness.in,
+    loops = loops,
+    multiple = multiple
+  )
+}
 
 
 #' Scale-free random graphs, from vertex fitness scores
@@ -2990,7 +3064,25 @@ sample_fitness <- static_fitness_game_impl
 #' g <- sample_fitness_pl(10000, 30000, 2.2, 2.3)
 #' plot(degree_distribution(g, cumulative = TRUE, mode = "out"), log = "xy")
 #' @cdocs igraph_static_power_law_game
-sample_fitness_pl <- static_power_law_game_impl
+sample_fitness_pl <- function(
+  no.of.nodes,
+  no.of.edges,
+  exponent.out,
+  exponent.in = -1,
+  loops = FALSE,
+  multiple = FALSE,
+  finite.size.correction = TRUE
+) {
+  static_power_law_game_impl(
+    no.of.nodes = no.of.nodes,
+    no.of.edges = no.of.edges,
+    exponent.out = exponent.out,
+    exponent.in = exponent.in,
+    loops = loops,
+    multiple = multiple,
+    finite.size.correction = finite.size.correction
+  )
+}
 
 
 #' Forest Fire Network Model
@@ -3053,7 +3145,21 @@ sample_fitness_pl <- static_power_law_game_impl
 #' plot(seq(along.with = dd1) - 1, dd1, log = "xy")
 #' points(seq(along.with = dd2) - 1, dd2, col = 2, pch = 2)
 #' @cdocs igraph_forest_fire_game
-sample_forestfire <- forest_fire_game_impl
+sample_forestfire <- function(
+  nodes,
+  fw.prob,
+  bw.factor = 1,
+  ambs = 1,
+  directed = TRUE
+) {
+  forest_fire_game_impl(
+    nodes = nodes,
+    fw.prob = fw.prob,
+    bw.factor = bw.factor,
+    ambs = ambs,
+    directed = directed
+  )
+}
 
 
 #' Generate a new random graph from a given graph by randomly
@@ -3093,7 +3199,19 @@ sample_forestfire <- forest_fire_game_impl
 #' g
 #' g2
 #' @cdocs igraph_correlated_game
-sample_correlated_gnp <- correlated_game_impl
+sample_correlated_gnp <- function(
+  old.graph,
+  corr,
+  p = edge_density(old.graph),
+  permutation = NULL
+) {
+  correlated_game_impl(
+    old.graph = old.graph,
+    corr = corr,
+    p = p,
+    permutation = permutation
+  )
+}
 
 
 #' Sample a pair of correlated \eqn{G(n,p)} random graphs
@@ -3131,4 +3249,18 @@ sample_correlated_gnp <- correlated_game_impl
 #' gg
 #' cor(as.vector(gg[[1]][]), as.vector(gg[[2]][]))
 #' @cdocs igraph_correlated_pair_game
-sample_correlated_gnp_pair <- correlated_pair_game_impl
+sample_correlated_gnp_pair <- function(
+  n,
+  corr,
+  p,
+  directed = FALSE,
+  permutation = NULL
+) {
+  correlated_pair_game_impl(
+    n = n,
+    corr = corr,
+    p = p,
+    directed = directed,
+    permutation = permutation
+  )
+}

From 126852bc5ec916dbabec5e9423a199862e9daf18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 21:33:57 +0200
Subject: [PATCH 092/154] chore: Fix isomorphism callback function

---
 R/aaa-auto.R                 | 4 ++--
 src/cpp11.cpp                | 4 ++--
 tools/stimulus/types-RR.yaml | 4 ++++
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index b6adff86b94..f796c3080fb 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -4646,7 +4646,7 @@ isomorphic_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color
   res
 }
 
-get_isomorphisms_vf2_callback_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL, ishohandler.fn) {
+get_isomorphisms_vf2_callback_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4693,7 +4693,7 @@ get_isomorphisms_vf2_callback_impl <- function(graph1, graph2, vertex.color1=NUL
 
   on.exit( .Call(R_igraph_finalizer) )
   # Function call
-  res <- .Call(R_igraph_get_isomorphisms_vf2_callback, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2, ishohandler.fn)
+  res <- .Call(R_igraph_get_isomorphisms_vf2_callback, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
 
   res
 }
diff --git a/src/cpp11.cpp b/src/cpp11.cpp
index 9046075ad19..fafa5d92d36 100644
--- a/src/cpp11.cpp
+++ b/src/cpp11.cpp
@@ -205,7 +205,7 @@ extern SEXP R_igraph_get_edgelist(SEXP, SEXP);
 extern SEXP R_igraph_get_eids(SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_get_graph_id(SEXP);
 extern SEXP R_igraph_get_isomorphisms_vf2(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
-extern SEXP R_igraph_get_isomorphisms_vf2_callback(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
+extern SEXP R_igraph_get_isomorphisms_vf2_callback(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_get_k_shortest_paths(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_get_laplacian(SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_get_laplacian_sparse(SEXP, SEXP, SEXP, SEXP);
@@ -688,7 +688,7 @@ static const R_CallMethodDef CallEntries[] = {
     {"R_igraph_get_eids",                                   (DL_FUNC) &R_igraph_get_eids,                                    4},
     {"R_igraph_get_graph_id",                               (DL_FUNC) &R_igraph_get_graph_id,                                1},
     {"R_igraph_get_isomorphisms_vf2",                       (DL_FUNC) &R_igraph_get_isomorphisms_vf2,                        6},
-    {"R_igraph_get_isomorphisms_vf2_callback",              (DL_FUNC) &R_igraph_get_isomorphisms_vf2_callback,               7},
+    {"R_igraph_get_isomorphisms_vf2_callback",              (DL_FUNC) &R_igraph_get_isomorphisms_vf2_callback,               6},
     {"R_igraph_get_k_shortest_paths",                       (DL_FUNC) &R_igraph_get_k_shortest_paths,                        6},
     {"R_igraph_get_laplacian",                              (DL_FUNC) &R_igraph_get_laplacian,                               4},
     {"R_igraph_get_laplacian_sparse",                       (DL_FUNC) &R_igraph_get_laplacian_sparse,                        4},
diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml
index 9311dce03a5..ae59baa0bc9 100644
--- a/tools/stimulus/types-RR.yaml
+++ b/tools/stimulus/types-RR.yaml
@@ -259,6 +259,10 @@ ISOCOMPAT_FUNC:
     CALL: {}
     HEADER: ~
 
+ISOMORPHISM_FUNC:
+    CALL: {}
+    HEADER: ~
+
 VERTEXSET_LIST:
     CALL: lapply(%I%, function(.x) .x-1)
     OUTCONV:

From 4cb3ad75e6001421f4cfa535a2e9431ceea08723 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 21:38:47 +0200
Subject: [PATCH 093/154] Fix attributes for static_power_law_game_impl

---
 R/aaa-auto.R                    | 2 --
 R/games.R                       | 9 ++++++++-
 tools/stimulus/functions-R.yaml | 2 +-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index f796c3080fb..058588041a6 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -701,8 +701,6 @@ static_power_law_game_impl <- function(no.of.nodes, no.of.edges, exponent.out, e
     res$name <- 'Static power law model'
     res$exponent.out <- exponent.out
     res$exponent.in <- exponent.in
-    res$loops <- loops
-    res$multiple <- multiple
     res$finite.size.correction <- finite.size.correction
   }
 
diff --git a/R/games.R b/R/games.R
index 27666c5e3fc..862d416bcbc 100644
--- a/R/games.R
+++ b/R/games.R
@@ -3073,7 +3073,7 @@ sample_fitness_pl <- function(
   multiple = FALSE,
   finite.size.correction = TRUE
 ) {
-  static_power_law_game_impl(
+  res <- static_power_law_game_impl(
     no.of.nodes = no.of.nodes,
     no.of.edges = no.of.edges,
     exponent.out = exponent.out,
@@ -3082,6 +3082,13 @@ sample_fitness_pl <- function(
     multiple = multiple,
     finite.size.correction = finite.size.correction
   )
+
+  if (igraph_opt("add.params")) {
+    res$loops <- loops
+    res$multiple <- multiple
+  }
+
+  res
 }
 
 
diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml
index 591e1f70df4..c745f0ab52a 100644
--- a/tools/stimulus/functions-R.yaml
+++ b/tools/stimulus/functions-R.yaml
@@ -190,7 +190,7 @@ igraph_static_power_law_game:
     R:
         GATTR:
           name: Static power law model
-        GATTR-PARAM: exponent_out, exponent_in, loops, multiple, finite_size_correction
+        GATTR-PARAM: exponent_out, exponent_in, finite_size_correction
 
 igraph_k_regular_game:
     R:

From 3c6b977f0ae2a84d7d7d78ca16c05ab2a72cf851 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 19:01:58 +0200
Subject: [PATCH 094/154] git subrepo clone --branch=0.21.5
 git@github.com:igraph/stimulus tools/py-stimulus

subrepo:
  subdir:   "tools/py-stimulus"
  merged:   "f62f215a6d"
upstream:
  origin:   "git@github.com:igraph/stimulus"
  branch:   "0.21.5"
  commit:   "f62f215a6d"
git-subrepo:
  version:  "0.4.9"
  origin:   "https://github.com/Homebrew/brew"
  commit:   "00001bedf8"
---
 tools/py-stimulus/.gitignore                  | 132 ++++
 tools/py-stimulus/.gitrepo                    |  12 +
 tools/py-stimulus/.pre-commit-config.yaml     |  20 +
 tools/py-stimulus/LICENSE                     | 339 +++++++++
 tools/py-stimulus/README.md                   |  10 +
 tools/py-stimulus/docs/index.mdx              |  72 ++
 tools/py-stimulus/poetry.lock                 | 142 ++++
 tools/py-stimulus/poetry.toml                 |   2 +
 tools/py-stimulus/pyproject.toml              |  30 +
 tools/py-stimulus/src/stimulus/__init__.py    |   0
 tools/py-stimulus/src/stimulus/__main__.py    | 154 ++++
 tools/py-stimulus/src/stimulus/errors.py      |  61 ++
 .../src/stimulus/generators/__init__.py       |   3 +
 .../src/stimulus/generators/base.py           | 416 +++++++++++
 .../src/stimulus/generators/debug.py          | 170 +++++
 .../src/stimulus/generators/java.py           | 410 +++++++++++
 .../src/stimulus/generators/python.py         | 623 ++++++++++++++++
 .../py-stimulus/src/stimulus/generators/r.py  | 663 ++++++++++++++++++
 .../src/stimulus/generators/registry.py       |  76 ++
 .../src/stimulus/generators/shell.py          | 295 ++++++++
 .../src/stimulus/generators/utils.py          |  34 +
 .../src/stimulus/model/__init__.py            |  12 +
 tools/py-stimulus/src/stimulus/model/base.py  |  40 ++
 .../src/stimulus/model/docstrings.py          |  10 +
 .../src/stimulus/model/functions.py           | 398 +++++++++++
 .../src/stimulus/model/parameters.py          | 214 ++++++
 tools/py-stimulus/src/stimulus/model/types.py | 267 +++++++
 .../src/stimulus/providers/__init__.py        |   0
 .../src/stimulus/providers/docstrings.py      |  52 ++
 tools/py-stimulus/src/stimulus/utils.py       |  28 +
 tools/py-stimulus/src/stimulus/version.py     |   2 +
 tools/py-stimulus/tbump.toml                  |  26 +
 32 files changed, 4713 insertions(+)
 create mode 100644 tools/py-stimulus/.gitignore
 create mode 100644 tools/py-stimulus/.gitrepo
 create mode 100644 tools/py-stimulus/.pre-commit-config.yaml
 create mode 100644 tools/py-stimulus/LICENSE
 create mode 100644 tools/py-stimulus/README.md
 create mode 100644 tools/py-stimulus/docs/index.mdx
 create mode 100644 tools/py-stimulus/poetry.lock
 create mode 100644 tools/py-stimulus/poetry.toml
 create mode 100644 tools/py-stimulus/pyproject.toml
 create mode 100644 tools/py-stimulus/src/stimulus/__init__.py
 create mode 100755 tools/py-stimulus/src/stimulus/__main__.py
 create mode 100644 tools/py-stimulus/src/stimulus/errors.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/__init__.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/base.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/debug.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/java.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/python.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/r.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/registry.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/shell.py
 create mode 100644 tools/py-stimulus/src/stimulus/generators/utils.py
 create mode 100644 tools/py-stimulus/src/stimulus/model/__init__.py
 create mode 100644 tools/py-stimulus/src/stimulus/model/base.py
 create mode 100644 tools/py-stimulus/src/stimulus/model/docstrings.py
 create mode 100644 tools/py-stimulus/src/stimulus/model/functions.py
 create mode 100644 tools/py-stimulus/src/stimulus/model/parameters.py
 create mode 100644 tools/py-stimulus/src/stimulus/model/types.py
 create mode 100644 tools/py-stimulus/src/stimulus/providers/__init__.py
 create mode 100644 tools/py-stimulus/src/stimulus/providers/docstrings.py
 create mode 100644 tools/py-stimulus/src/stimulus/utils.py
 create mode 100644 tools/py-stimulus/src/stimulus/version.py
 create mode 100644 tools/py-stimulus/tbump.toml

diff --git a/tools/py-stimulus/.gitignore b/tools/py-stimulus/.gitignore
new file mode 100644
index 00000000000..2dbe033b6c9
--- /dev/null
+++ b/tools/py-stimulus/.gitignore
@@ -0,0 +1,132 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# VS Code
+.vscode/
diff --git a/tools/py-stimulus/.gitrepo b/tools/py-stimulus/.gitrepo
new file mode 100644
index 00000000000..05d5fc4eeff
--- /dev/null
+++ b/tools/py-stimulus/.gitrepo
@@ -0,0 +1,12 @@
+; DO NOT EDIT (unless you know what you are doing)
+;
+; This subdirectory is a git "subrepo", and this file is maintained by the
+; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
+;
+[subrepo]
+	remote = git@github.com:igraph/stimulus
+	branch = 0.21.5
+	commit = f62f215a6d325545b44b59e114c963cf04abb4ce
+	parent = 63943053a43a247f1bf7628bbf481d400ce3e315
+	method = merge
+	cmdver = 0.4.9
diff --git a/tools/py-stimulus/.pre-commit-config.yaml b/tools/py-stimulus/.pre-commit-config.yaml
new file mode 100644
index 00000000000..04afe0c00e0
--- /dev/null
+++ b/tools/py-stimulus/.pre-commit-config.yaml
@@ -0,0 +1,20 @@
+fail_fast: true
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v4.0.1
+    hooks:
+      - id: check-ast
+      - id: end-of-file-fixer
+      - id: trailing-whitespace
+
+  - repo: https://github.com/charliermarsh/ruff-pre-commit
+    rev: v0.0.275
+    hooks:
+      - id: ruff
+        args: [--fix, --exit-non-zero-on-fix]
+
+  - repo: https://github.com/psf/black
+    rev: 22.3.0
+    hooks:
+      - id: black
+        language_version: python3
diff --git a/tools/py-stimulus/LICENSE b/tools/py-stimulus/LICENSE
new file mode 100644
index 00000000000..d159169d105
--- /dev/null
+++ b/tools/py-stimulus/LICENSE
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    
+    Copyright (C)   
+
+    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, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  , 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/tools/py-stimulus/README.md b/tools/py-stimulus/README.md
new file mode 100644
index 00000000000..3ae92f0046d
--- /dev/null
+++ b/tools/py-stimulus/README.md
@@ -0,0 +1,10 @@
+# `stimulus`
+
+This repository hosts an experimental code generator for high-level interfaces
+of igraph.
+
+`stimulus` has already been used to generate a significant part of the codebase
+of the R interface of igraph. The aim of this repository is to refactor it in a
+way that makes it easier to potentially use `stimulus` for other high-level
+interfaces (e.g., the Python interface, which still relies on hand-written code
+for the Python bindings).
diff --git a/tools/py-stimulus/docs/index.mdx b/tools/py-stimulus/docs/index.mdx
new file mode 100644
index 00000000000..b98aaf96e06
--- /dev/null
+++ b/tools/py-stimulus/docs/index.mdx
@@ -0,0 +1,72 @@
+# Introduction
+
+The `igraph` C library supports several interfaces, currently R, Python and Mathematica. Often, much of the glue code between the C library and the interfaces is rather repetitive. In order to automate the code generation of the glue code between the C library and an interface, there is an automated tool available, called Stimulus, available from [Github](https://github.com/igraph/stimulus). Stimulus accepts two types of definition files, one for functions, and one for types, which it both parses, and turns into generated code. In principle, the generated code can be any language, but currently, it is mostly used for the R interface. For that interface, it generates both the C glue code and a large part of the R interface itself, with additional R functionality being supplied in separate R source files.
+
+`stimulus` can be called as follows:
+
+```
+stimulus -f 
+         -t 
+         -l language
+         -i 
+         -o 
+         -h --help -v
+```
+
+The `` and `` are the definition files for the functions and the types respectively. Function files may be provided multiple times; files provided later mostly override or extend files provided earlier in the command line. We will explain them in greater detail below. The `language` is an identifier of a code generator specific to a language; currently only `RR`, `RC`, and `RInit`) are used in practice. The `` is in principle simply read and output to the ``, to which any generated code will also be written.
+
+# Language
+
+In `stimulus`, each language is represented separately by its own `CodeGenerator` class. The language specific `CodeGenerator` *must* derive from the base `CodeGenerator` class provided in `stimulus`, and *must* be prepended with the language identifier. For example, the code generator of the C code for the R interface is named `RCCodeGenerator`. The identifier `language` that is provided as an option to `stimulus` corresponds to its code generator class. For example, specifiying `-l RC` in `stimulus` will use the `RCCodeGenerator` class to generate the code. The key ingredient of a code generator is the `generate_function` method, which is an abstract method in the `CodeGenerator` base class, and which should be implemented for any language specific class.
+
+# Definition files
+
+The definition files contain a list of items (either functions or types) that are the basis for generating code. The basic idea is that each function will be translated in some way, using the specified types. Hence, the function definitions are common to all interfaces, and simply describe the actual C API. The type definition are language specific, and may also contain language specific descriptions.
+
+The format of the definition files is the same for both functions and types, and it is currently based on YAML.
+
+## Function definitions
+
+Each item in the function definition file describes a function, and is included in the `igraph` repository in [`interfaces/functions.yaml`](https://github.com/igraph/igraph/blob/master/interfaces/functions.yaml). The identifier of each item corresponds to an implemented function of the `igraph` C library. As the file format is just general, in principle, it is possible to add all types of custom properties. There are however a number of common properties, which are describe in more detail below. The most important one is the `PARAMS` property, which contains a comma-separated description of the parameters of the C igraph function. This property needs to be specified for any function (assuming a function has parameters, obviously). Secondly, some parameters may depend on other pieces of code (it will become clear what this entails below), which can be specified by the `DEPS` property. A return type can be provided by the `RETURN` property, although for most `igraph` functions this is actually an error code. Since this is the most common type, if no `RETURN` property is specified, it is assumed to return an `ERROR` type. Finally, the `IGNORE` property allows to specify languages for which this function should be ignored, and no code should be hence generated for it using `generate_function`. Typically, the `IGNORE` key is not used in the base function definition file; it is added in the repository of higher-level interfaces from another `functions.yaml` file that is _overlaid_ on top of the base `functions.yaml` file.
+
+As stated, in principle any property can be listed here, and so language specific necessities could also be included here. The most prominent example at the moment is the `NAME` property, which overrides the name `stimulus` will use to represent this function in a higher-level language. Name overrides are also defined in `functions.yaml` files in the repositories of the higher-level interfaces. Additionally, the R code generator also uses the `GATTR` and `GATTR-PARAM` properties, which add graph attributes based on a specified value or an R parameter respectively.
+
+Finally, for some functions the `FLAGS` property is specified. This is parsed and the flags are set for each function, and can be queried from code generators. Currently we use `PROGRESS` for functions that support reporting progress and `DEPRECATED` for deprecated functions. It is up to the code generator class to make use of these flags as appropriate.
+
+### PARAMS
+
+The parameters of each function should be specified using a comma separated list, where each parameter is specified by a parameter type and a parameter identifier. In addition, it can be specified whether a parameter is considered to be an argument to the function, or a result of the function. This is the case for many `igraph` functions, since the actual return type is usually an error code, and hence the actual results of the function are returned through pointer arguments. Finally, a default value can be specified by setting it equal to (`=`) some value. In short, the specification is
+
+```
+PARAMS: [PRIMARY] [IN/OUT]  identifier=DEFAULT, [PRIMARY] [IN/OUT]  identifier=DEFAULT
+```
+
+The `TYPE` identifiers are in uppercase, and correspond to the types that will be specified in the type definition file. In principle, all type identifiers are allowed here. Under the explanation of the type definition section, the most common types will be described in more detail.
+
+By default, a parameter is considered an input argument (i.e. `IN`), so this will typically not be specified explicitly. If a parameter should be considered a result, it is specified as `OUT`. Finally, if a parameter is considered both as an input argument to the function, and a result, it is specified as `INOUT`. For example, adding a vertex or an edge to a graph, will mean that the `graph` argument will contain the initial graph, but it also contains the modified graph, and hence should be considered as both an incoming argument and an outgoing result.
+
+The default specified by `DEFAULT` can refer to a list of possible defaults specified for the specific `TYPE`. For example, `CONNECTEDNESS mode=WEAK` refers to the default of `WEAK` connectedness, where `WEAK` actually refers to the default specified for the `TYPE` `CONNECTEDNESS`, which for the R code generator generates the code `c("weak", "strong")`.
+
+The `PRIMARY` keyword can be used to designate one or more _output_ arguments of a function as "primary" outputs. Code generators may use this keyword to generate two versions of a function: one that returns only the primary outputs and one that returns all of them. Alternatively, code generators may also generate a _single_ function with an additional `details` argument letting the user decide whether the result should include only the primary results or all of them. Again, it is up to the code generator to support the `PRIMARY` keyword.
+
+## DEPS
+
+Some parameters may require some other code to obtain some results. The different parameters are separated by commas, and the different codes are simply separated by whitespace. In short, the arguments for this dependency are specified as
+```
+DEPS: parameterx ON code1 code2, parametery ON code1 code2
+```
+
+For example, when specifying vertices, `R` ensures that these are correct vertex sequences for the graph (for example, translating vertex names to vertex indices). Many functions contain this dependency, specified as `DEPS: vids ON graph`, where `vids` has the type `VERTEXSET`. The dependencies can be used in the templates for the type definitions as `%I[dependency number]%` (see more detail in the type definitions). For example, `DEPS: res ON graph vids` contains two dependencies, and hence `%I1%` refers to `graph`, and `%I2%` refers to `vids`.
+
+## Type definitions
+
+### Types
+
+The most common types are:
+
+- `GRAPH`
+- `BOOLEAN`
+- `INTEGER`
+- `VECTOR`
+- `REAL`
+- ...
diff --git a/tools/py-stimulus/poetry.lock b/tools/py-stimulus/poetry.lock
new file mode 100644
index 00000000000..0fee24619fc
--- /dev/null
+++ b/tools/py-stimulus/poetry.lock
@@ -0,0 +1,142 @@
+# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
+
+[[package]]
+name = "deepmerge"
+version = "0.3.0"
+description = "a toolset to deeply merge python dictionaries."
+optional = false
+python-versions = ">=3"
+files = [
+    {file = "deepmerge-0.3.0-py2.py3-none-any.whl", hash = "sha256:87166dbe9ba1a3348a45c9d4ada6778f518d41afc0b85aa017ea3041facc3f9c"},
+    {file = "deepmerge-0.3.0.tar.gz", hash = "sha256:f6fd7f1293c535fb599e197e750dbe8674503c5d2a89759b3c72a3c46746d4fd"},
+]
+
+[[package]]
+name = "jinja2"
+version = "3.1.2"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+    {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.3"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+    {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
+]
+
+[[package]]
+name = "pyyaml"
+version = "6.0"
+description = "YAML parser and emitter for Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
+    {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
+    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
+    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
+    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
+    {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
+    {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
+    {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
+    {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
+    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
+    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
+    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
+    {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
+    {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
+    {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
+    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
+    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
+    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
+    {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
+    {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
+    {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
+    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
+    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
+    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
+    {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
+    {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
+    {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
+    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
+    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
+    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
+    {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
+    {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
+    {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
+    {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
+    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
+    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
+    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
+    {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
+    {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
+    {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.7"
+content-hash = "02ee53fad3ba232428867b1b13e8f26aef041e09da72069f2f0fba2682e4a398"
diff --git a/tools/py-stimulus/poetry.toml b/tools/py-stimulus/poetry.toml
new file mode 100644
index 00000000000..d697ca4701e
--- /dev/null
+++ b/tools/py-stimulus/poetry.toml
@@ -0,0 +1,2 @@
+[virtualenvs]
+in-project=true
diff --git a/tools/py-stimulus/pyproject.toml b/tools/py-stimulus/pyproject.toml
new file mode 100644
index 00000000000..e2f1acafc95
--- /dev/null
+++ b/tools/py-stimulus/pyproject.toml
@@ -0,0 +1,30 @@
+[tool.poetry]
+name = "stimulus"
+version = "0.21.5"
+description = "Experimental code generator for high-level interfaces of igraph"
+authors = [
+    "Gabor Csardi ",
+    "Tamas Nepusz ",
+]
+packages = [{ include = "stimulus", from = "src" }]
+license = "GPL-2.0-or-later"
+
+[tool.poetry.dependencies]
+python = "^3.8"
+PyYAML = "^6.0"
+deepmerge = "^0.3.0"
+jinja2 = "^3.1.2"
+
+[tool.poetry.dev-dependencies]
+
+[tool.poetry.scripts]
+stimulus = 'stimulus.__main__:main'
+
+[tool.ruff]
+ignore = ["B905", "C901", "E402", "E501"]
+line-length = 80
+select = ["B", "C", "E", "F", "W"]
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/tools/py-stimulus/src/stimulus/__init__.py b/tools/py-stimulus/src/stimulus/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tools/py-stimulus/src/stimulus/__main__.py b/tools/py-stimulus/src/stimulus/__main__.py
new file mode 100755
index 00000000000..185d7e839e7
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/__main__.py
@@ -0,0 +1,154 @@
+import logging
+import os
+import sys
+
+from argparse import ArgumentParser
+
+from .generators import (
+    get_code_generator_factory_for_language,
+    is_valid_language,
+)
+from .providers.docstrings import FolderBasedDocstringProvider
+from .version import __version__
+
+
+def create_argument_parser() -> ArgumentParser:
+    parser = ArgumentParser()
+
+    parser.add_argument(
+        "--version", action="http://github.com/version", version=f"%(prog)s {__version__}"
+    )
+
+    parser.add_argument(
+        "-t",
+        "--types",
+        action="http://github.com/append",
+        metavar="FILE",
+        help="use the given type definition FILE",
+        default=[],
+    )
+
+    parser.add_argument(
+        "-f",
+        "--functions",
+        action="http://github.com/append",
+        metavar="FILE",
+        help="use the given function definition FILE",
+        default=[],
+    )
+
+    parser.add_argument(
+        "-l",
+        "--language",
+        action="http://github.com/append",
+        metavar="LANGUAGE",
+        help="generate code in the given LANGUAGE",
+        default=[],
+    )
+
+    parser.add_argument(
+        "-i",
+        "--input",
+        action="http://github.com/append",
+        metavar="FILE",
+        help="read input from the given FILE",
+        default=[],
+    )
+
+    parser.add_argument(
+        "-o",
+        "--output",
+        action="http://github.com/append",
+        metavar="FILE",
+        help="write output to the given FILE. Use '-' for standard output.",
+        default=[],
+    )
+
+    parser.add_argument(
+        "-D",
+        "--docstring-dir",
+        metavar="DIR",
+        help="use docstrings from files stored in DIR",
+        default=None,
+    )
+
+    return parser
+
+
+def main():
+    logging.basicConfig(
+        format="%(levelname)-10s| %(message)s", level=logging.INFO, stream=sys.stderr
+    )
+
+    parser = create_argument_parser()
+    options = parser.parse_args()
+
+    type_files = options.types or ()
+    function_files = options.functions
+    inputs = options.input
+    languages = options.language
+    outputs = options.output
+    docstring_dir = options.docstring_dir
+
+    # Parameter checks
+    # Note: the lists might be empty, but languages and outputs must
+    # have the same length.
+    if len(languages) != len(outputs):
+        if len(languages) == 1 and not len(outputs):
+            # Special case: just write to stdout
+            outputs.append("-")
+        else:
+            parser.error("Number of languages and output files must match")
+
+    for language in languages:
+        if not is_valid_language(language):
+            parser.error(f"Unknown language: {language}")
+
+    for path in type_files:
+        if not os.access(path, os.R_OK):
+            parser.error(f"Cannot open type file: {path}")
+
+    for path in function_files:
+        if not os.access(path, os.R_OK):
+            parser.error(f"Error: cannot open function file: {path}")
+
+    for path in inputs:
+        if not os.access(path, os.R_OK):
+            parser.error(f"Error: cannot open input file: {path}")
+
+    # Construct a log that the generators can write their messages to
+    log = logging.getLogger()
+
+    # OK, do the trick:
+    for language, output in zip(languages, outputs):
+        factory = get_code_generator_factory_for_language(language)
+
+        generator = factory()
+        generator.use_logger(log)
+        for path in function_files:
+            generator.load_function_descriptors_from_file(path)
+        for path in type_files:
+            generator.load_type_descriptors_from_file(path)
+        if docstring_dir:
+            generator.use_docstring_provider(
+                FolderBasedDocstringProvider(docstring_dir)
+            )
+
+        if output == "-":
+            generator.generate(inputs, sys.stdout)
+        else:
+            try:
+                with open(output, "w") as fp:
+                    generator.generate(inputs, fp)
+            except Exception:
+                # An error happened; delete the file and re-raise the exception
+                try:
+                    os.unlink(output)
+                except Exception:
+                    # Well, meh.
+                    pass
+                raise
+
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/py-stimulus/src/stimulus/errors.py b/tools/py-stimulus/src/stimulus/errors.py
new file mode 100644
index 00000000000..4892aeb5819
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/errors.py
@@ -0,0 +1,61 @@
+from typing import Optional
+
+__all__ = (
+    "StimulusError",
+    "ParseError",
+    "CodeGenerationError",
+    "InvalidDependencyError",
+    "NoSuchTypeError",
+)
+
+
+class StimulusError(RuntimeError):
+    """Base class for all errors specific to the `stimulus` package."""
+
+    msg: str
+
+    def __init__(self, message: str):
+        super().__init__(message)
+        self.msg = message
+
+    def __str__(self):
+        return str(self.msg)
+
+
+class ParseError(StimulusError):
+    """Base class for errors thrown while parsing input files."""
+
+    lineno: Optional[int]
+
+    def __init__(self, message: str, lineno: Optional[int] = None):
+        super().__init__(
+            f"{message} in line {lineno}" if lineno is not None else message
+        )
+        self.lineno = lineno
+
+
+class CodeGenerationError(StimulusError):
+    """Base class for errors thrown while generating code."""
+
+    pass
+
+
+class InvalidDependencyError(CodeGenerationError):
+    """Error thrown when a parameter specification refers to a non-existing
+    parameter in a dependency.
+    """
+
+    pass
+
+
+class NoSuchTypeError(CodeGenerationError):
+    """Error thrown when the code generator attempts to look up a type by
+    name and there is no such type in the registry.
+    """
+
+    type: str
+    #: Name of the type for which the lookup failed
+
+    def __init__(self, type: str, *, message: Optional[str] = None):
+        super().__init__(message or f"No such type: {type!r}")
+        self.type = type
diff --git a/tools/py-stimulus/src/stimulus/generators/__init__.py b/tools/py-stimulus/src/stimulus/generators/__init__.py
new file mode 100644
index 00000000000..e63ed65cd4e
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/__init__.py
@@ -0,0 +1,3 @@
+from .registry import get_code_generator_factory_for_language, is_valid_language
+
+__all__ = ("get_code_generator_factory_for_language", "is_valid_language")
diff --git a/tools/py-stimulus/src/stimulus/generators/base.py b/tools/py-stimulus/src/stimulus/generators/base.py
new file mode 100644
index 00000000000..f5cd5a790ec
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/base.py
@@ -0,0 +1,416 @@
+import re
+
+from abc import abstractmethod, ABCMeta
+from collections import Counter, OrderedDict
+from enum import Enum
+from io import StringIO
+from logging import Logger
+from pathlib import Path
+from shutil import copyfileobj
+from typing import (
+    Any,
+    Dict,
+    IO,
+    Iterable,
+    List,
+    Sequence,
+    Tuple,
+)
+
+from stimulus.errors import CodeGenerationError, NoSuchTypeError
+from stimulus.model import DocstringProvider, FunctionDescriptor, TypeDescriptor
+from stimulus.utils import constant
+
+__all__ = (
+    "BlockBasedCodeGenerator",
+    "CodeGenerator",
+    "CodeGeneratorBase",
+    "InputPlacement",
+    "SingleBlockCodeGenerator",
+)
+
+
+class CodeGenerator(metaclass=ABCMeta):
+    """Interface specification for code generators."""
+
+    name: str
+
+    @abstractmethod
+    def generate(self, inputs: List[str], output: IO[str]) -> None:
+        """Generates code from the given input files into the given output
+        stream, according to the function and type rules loaded into the
+        generator.
+
+        Parameters:
+            inputs: the list of input files to process
+            output: the output stream to write the generated code into
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def load_function_descriptors_from_file(self, filename: str) -> None:
+        """Loads function descriptors from the input file with the given name.
+
+        Parameters:
+            filename: the name of the input file
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def load_function_descriptors_from_object(self, obj: Dict[str, Any]) -> None:
+        """Loads function descriptors from the given object. The object is
+        typically parsed from a specification file, although it can also come
+        from other sources.
+
+        Parameters:
+            obj: the object to load the descriptors from
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def load_type_descriptors_from_file(self, filename: str) -> None:
+        """Loads type descriptors from the input file with the given name.
+
+        Parameters:
+            filename: the name of the input file
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def load_type_descriptors_from_object(self, obj: Dict[str, Any]) -> None:
+        """Loads type descriptors from the given object. The object is
+        typically parsed from a specification file, although it can also come
+        from other sources.
+
+        Parameters:
+            obj: the object to load the descriptors from
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def use_docstring_provider(self, provider: DocstringProvider) -> None:
+        """Instructs the code generator to use the given object to retrieve
+        docstrings for the functions for which it generates code.
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def use_logger(self, log: Logger) -> None:
+        """Instructs the code generator to log any issues that it finds during
+        code generation to the given logger.
+        """
+        raise NotImplementedError
+
+
+def _nop(*args, **kwds) -> None:
+    pass
+
+
+class _DummyLogger:
+    def __getattr__(self, name: str):
+        return _nop
+
+
+class CodeGeneratorBase(CodeGenerator):
+    """Base class for code generator implementations."""
+
+    log: Logger
+    name: str
+
+    _docstring_provider: DocstringProvider
+    _function_descriptors: Dict[str, FunctionDescriptor]
+    _type_descriptors: Dict[str, TypeDescriptor]
+
+    _deps_cache: Dict[str, Dict[str, Tuple[str, ...]]]
+    _ignore_cache: Dict[str, bool]
+
+    def __init__(self):
+        """Constructor."""
+        # Set name, note this only works correctly if derived classes always
+        # extend it as by prepending the language to the CodeGenerator class
+        # name
+        self.name = type(self).__name__
+        if self.name.endswith("CodeGenerator"):
+            self.name = self.name[0 : len(self.name) - len("CodeGenerator")]
+
+        self.log = _DummyLogger()  # type: ignore
+
+        self._docstring_provider = constant(None)
+        self._function_descriptors = OrderedDict()
+        self._type_descriptors = {}
+
+        self._deps_cache = {}
+        self._ignore_cache = {}
+
+    def check_types_of_function(self, function: str, errors: str = "raise") -> bool:
+        """Checks whether the types of all the input arguments of the given
+        function are known to the code generator.
+
+        Parameters:
+            function: the name of the function to check
+            errors: specifies what to do when an unknown type is found;
+                ``"ignore"`` does nothing; ``"warn"`` prints a warning;
+                ``"error"`` logs an error message; any other value raises an
+                exception
+
+        Returns:
+            whether the types of all the input arguments of the given function
+            are known to the code generator
+        """
+        spec = self.get_function_descriptor(function)
+        ok = True
+
+        for param in spec.iter_parameters():
+            if param.is_deprecated:
+                continue
+
+            type_name = param.type
+            if type_name not in self._type_descriptors:
+                message = (
+                    f"Parameter {param.name!r} of {function}() is of type "
+                    f"{type_name!r}, but it is not known to the type system"
+                )
+                ok = False
+                if errors == "ignore":
+                    pass
+                elif errors == "warn":
+                    self.log.warning(message)
+                elif errors == "error":
+                    self.log.error(message)
+                else:
+                    raise NoSuchTypeError(type_name, message=message)
+
+        return ok
+
+    def load_function_descriptors_from_file(self, filename: str) -> None:
+        specs = self._parse_file(filename)
+        self.load_function_descriptors_from_object(specs)
+
+    def load_function_descriptors_from_object(self, obj: Dict[str, Any]) -> None:
+        for name, spec in obj.items():
+            descriptor = self.get_or_create_function_descriptor(name)
+            if spec is not None:
+                descriptor.update_from(spec)
+
+    def load_type_descriptors_from_file(self, filename: str) -> None:
+        specs = self._parse_file(filename)
+        self.load_type_descriptors_from_object(specs)
+
+    def load_type_descriptors_from_object(self, obj: Dict[str, Any]) -> None:
+        for name, spec in obj.items():
+            descriptor = self.get_or_create_type_descriptor(name)
+            if spec is not None:
+                descriptor.update_from(spec)
+
+    def use_docstring_provider(self, provider: DocstringProvider) -> None:
+        self.docstring_provider = provider
+
+    def use_logger(self, log: Logger) -> None:
+        self.log = log
+
+    def get_function_descriptor(self, name: str) -> FunctionDescriptor:
+        return self._function_descriptors[name]
+
+    def get_or_create_function_descriptor(self, name: str) -> FunctionDescriptor:
+        try:
+            descriptor = self.get_function_descriptor(name)
+        except KeyError:
+            descriptor = self._function_descriptors[name] = FunctionDescriptor(name)
+        return descriptor
+
+    def get_type_descriptor(self, name: str) -> TypeDescriptor:
+        try:
+            return self._type_descriptors[name]
+        except KeyError:
+            raise NoSuchTypeError(name) from None
+
+    def get_or_create_type_descriptor(self, name: str) -> TypeDescriptor:
+        try:
+            descriptor = self.get_type_descriptor(name)
+        except NoSuchTypeError:
+            descriptor = self._type_descriptors[name] = TypeDescriptor(name)
+        return descriptor
+
+    @abstractmethod
+    def generate_function(self, name: str, output: IO[str]) -> None:
+        """Processes the function with the given name and generates the
+        corresponding output on the output stream.
+
+        This function is _not_ called for functions that are deemed to be
+        ignored by `should_ignore_function()`.
+        """
+        raise NotImplementedError
+
+    def generate_functions_block(self, output: IO[str]) -> None:
+        """Generates the part of the output file that contains the generated code
+        for functions.
+        """
+        for name in self.iter_functions():
+            self.generate_function(name, output)
+
+    def iter_functions(self, include_ignored: bool = False) -> Iterable[str]:
+        """Iterator that yields the names of the functions in the function
+        specification that are _not_ to be ignored by this generator.
+        """
+        if include_ignored:
+            yield from self._function_descriptors.keys()
+        else:
+            for name in self._function_descriptors:
+                if not self.should_ignore_function(name):
+                    yield name
+
+    def should_ignore_function(self, name: str) -> bool:
+        """Returns whether the function with the given name should be ignored
+        by this code generator.
+
+        This function is memoized. Do not override this function; override
+        `_should_ignore_function()` instead.
+
+        Parameters:
+            name: the name of the function
+
+        Returns:
+            whether the function should be ignored by this code generator
+        """
+        result = self._ignore_cache.get(name)
+        if result is None:
+            self._ignore_cache[name] = result = self._should_ignore_function(name)
+        return result
+
+    def _append_inputs(self, inputs: Sequence[str], output: IO[str]) -> None:
+        for input in inputs:
+            with Path(input).open() as fp:
+                copyfileobj(fp, output)
+
+    def _parse_file(self, name: str) -> Dict[str, Any]:
+        """Parses a generic input file from YAML format."""
+        from yaml import safe_load
+
+        # Check for top-level duplicate keys
+        with open(name) as fp:
+            keys = Counter(
+                line.strip().rstrip(":") for line in fp if line and line[0].isalpha()
+            )
+        duplicates = sorted(k for k, v in keys.items() if v > 1)
+        if duplicates:
+            raise ValueError(f"duplicate keys found: {', '.join(duplicates)}")
+
+        # No top-level duplicate keys, load the YAML file
+        with open(name) as fp:
+            return safe_load(fp)
+
+    def _should_ignore_function(self, name: str) -> bool:
+        """Returns whether the function with the given name should be ignored
+        by this code generator.
+
+        Parameters:
+            name: the name of the function
+
+        Returns:
+            whether the function should be ignored by this code generator
+        """
+        desc = self.get_function_descriptor(name)
+        return self.name in desc.ignored_by
+
+
+class BlockBasedCodeGenerator(CodeGeneratorBase):
+    """Code generator that looks for block markers in input files and replaces
+    each block with the corresponding content.
+
+    Block markers are lines that look like this:
+
+        % STIMULUS: block_name %
+
+    where the colon and the whitespace after and before the percent signs are
+    optional. Block names may contain alphanumeric characters, underscore and
+    dash only.
+    """
+
+    _BLOCK_REGEXP = re.compile(r"^\s*%\s*STIMULUS:?\s*(?P[-A-Za-z0-9_]*)\s*%")
+
+    _block_cache: Dict[str, str]
+
+    def __init__(self):
+        super().__init__()
+        self._block_cache = {}
+
+    def generate(self, inputs: Sequence[str], out: IO[str]) -> None:
+        for input in inputs:
+            with open(input) as fp:
+                for line in fp:
+                    if not self._process_marker_line(line, out):
+                        out.write(line)
+
+    def _generate_block(self, name: str) -> str:
+        """Generates the contents of the block with the given name.
+
+        This function is called once per block; further occurrences of the same
+        block are retrieved from the cache.
+        """
+        handler = getattr(self, f"generate_{name}_block", None)
+        if handler is None:
+            raise CodeGenerationError(f"Unhandled block in input file: {name}")
+
+        buf = StringIO()
+        handler(buf)
+        return buf.getvalue()
+
+    def _process_marker_line(self, line: str, out: IO[str]) -> bool:
+        """Attempts to process a potential marker line in one of the input files.
+
+        Marker lines are the ones that start with ``% STIMULUS``.
+
+        Returns:
+            whether the line was handled. Unhandled files should be forwarded to
+            the output as is by the caller.
+        """
+        match = self._BLOCK_REGEXP.match(line)
+        if match:
+            block_name = match.group("name") or "functions"
+            block = self._block_cache.get(block_name)
+            if block is None:
+                self._block_cache[block_name] = block = self._generate_block(block_name)
+            out.write(block)
+            return True
+        else:
+            return False
+
+
+class InputPlacement(Enum):
+    """Enum describing the possible placements of input files in a
+    single-block code generator.
+    """
+
+    PREAMBLE = "preamble"
+    EPILOGUE = "epilogue"
+
+
+class SingleBlockCodeGenerator(CodeGeneratorBase):
+    """Code generator that generates all functions in a single block and then
+    puts the content of all input files before or after them.
+    """
+
+    def __init__(self, input_placement: InputPlacement = InputPlacement.PREAMBLE):
+        super().__init__()
+        self._input_placement = input_placement
+
+    def generate(self, inputs: Sequence[str], output: IO[str]) -> None:
+        self.generate_preamble(inputs, output)
+        self.generate_functions_block(output)
+        self.generate_epilogue(inputs, output)
+
+    def generate_epilogue(self, inputs: Sequence[str], output: IO[str]) -> None:
+        """Processes the input files with the given names and generates the
+        epilogue of the output, i.e. the part that gets printed _after_ the
+        processed functions.
+        """
+        if self._input_placement is InputPlacement.EPILOGUE:
+            self._append_inputs(inputs, output)
+
+    def generate_preamble(self, inputs: Sequence[str], output: IO[str]) -> None:
+        """Processes the input files with the given names and generates the
+        preamble of the output, i.e. the part that gets printed _before_ the
+        processed functions.
+        """
+        if self._input_placement is InputPlacement.PREAMBLE:
+            self._append_inputs(inputs, output)
diff --git a/tools/py-stimulus/src/stimulus/generators/debug.py b/tools/py-stimulus/src/stimulus/generators/debug.py
new file mode 100644
index 00000000000..bae75fef9e2
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/debug.py
@@ -0,0 +1,170 @@
+"""Code generator classes that are meant for debugging purposes only.
+
+The classes in this module are not really "code generators" in the traditional
+sense; they consume the loaded functions and type definitions and print various
+pieces of information based on them, but they do not produce any runnable code.
+Typically, they are used from the command line as follows::
+
+    $ stimulus -f functions.yaml -t types.yaml -l DebugListTypes
+"""
+
+from collections import Counter
+from functools import partial
+from textwrap import dedent
+from typing import IO, List, Sequence
+
+from stimulus.errors import InvalidDependencyError, NoSuchTypeError
+
+from .base import SingleBlockCodeGenerator
+from .utils import create_indentation_function
+
+__all__ = ("ListTypesCodeGenerator",)
+
+indent = create_indentation_function("    ")
+
+
+class ListTypesCodeGenerator(SingleBlockCodeGenerator):
+    """Debugging aid that lists all the types that appear in the function
+    definitions.
+    """
+
+    def __init__(self, *args, **kwds):
+        super().__init__(*args, **kwds)
+        self.collected_types = Counter()
+
+    def generate_function(self, name: str, output: IO[str]) -> None:
+        spec = self.get_function_descriptor(name)
+        self.collected_types.update(param.type for param in spec.iter_parameters())
+        self.collected_types.update((spec.return_type,))
+
+    def generate_functions_block(self, output: IO[str]) -> None:
+        super().generate_functions_block(output)
+        write = partial(print, file=output)
+        for type, count in sorted(self.collected_types.items()):
+            write(type, count)
+
+
+class FunctionSpecificationValidator(SingleBlockCodeGenerator):
+    """Dummy code generator that simply prints C functions that call the
+    original C functions from igraph. This file can then be compiled with a
+    C++ compiler to validate whether the function specifications are correct
+    when linked with igraph.
+    """
+
+    functions: List[str]
+    """List to collect the names of all the functions that were matched by
+    the generator.
+    """
+
+    unknown_types: Counter
+    """Dictionary that counts how many times we have seen an unknown type
+    so we can figure out which ones need to be prioritized.
+    """
+
+    def __init__(self, *args, **kwds):
+        super().__init__(*args, **kwds)
+        self.functions = []
+        self.unknown_types = Counter()
+
+    def generate_preamble(self, inputs: Sequence[str], output: IO[str]) -> None:
+        write = partial(print, file=output)
+
+        write("#include \n")
+        write("#include ")
+        write("#include \n")
+
+    def generate_function(self, name: str, output: IO[str]) -> None:
+        write = partial(print, file=output)
+
+        args: List[str] = []
+
+        # Determine parameter declarations in C
+        func_desc = self.get_function_descriptor(name)
+        param_names = {param.name for param in func_desc.iter_parameters()}
+        for param in func_desc.iter_parameters():
+            if param.is_deprecated:
+                # Ignore deprecated parameters; they are only used in the R
+                # interface to show deprecation warnings
+                continue
+
+            try:
+                param_type_desc = self.get_type_descriptor(param.type)
+                arg = param_type_desc.declare_c_function_argument(
+                    param.name, mode=param.mode
+                )
+            except NoSuchTypeError:
+                arg = "void*"
+                self.unknown_types[param.type] += 1
+
+            if arg:
+                args.append(arg)
+
+            # Check whether the other parameters named in the dependencies are
+            # all valid
+            for dependency in param.dependencies:
+                if dependency not in param_names:
+                    raise InvalidDependencyError(
+                        f"{func_desc.name} parameter {param.name!r} refers to "
+                        f"an unknown dependency: {dependency!r}"
+                    )
+
+        # Determine return type in C
+        return_type_desc = self.get_type_descriptor(func_desc.return_type)
+        return_type = return_type_desc.get_c_type()
+        if return_type is None:
+            raise NoSuchTypeError(
+                func_desc.return_type,
+                message=f"{func_desc.name} declares a return value that has no corresponding C type",
+            )
+
+        # Write the function declaration to the output
+        args_str = ", ".join(args) or "void"
+        write(f"{return_type} generated_{name}({args_str});")
+
+        self.functions.append(name)
+
+    def generate_epilogue(self, inputs: Sequence[str], output: IO[str]) -> None:
+        write = partial(print, file=output)
+
+        checks = "\n".join(
+            dedent(
+                f"""\
+                static_assert(
+                    std::is_same<
+                        decltype({name}),
+                        decltype(generated_{name})
+                    >::value,
+                    "{name} prototype mismatch"
+                );"""
+            )
+            for name in self.functions
+        )
+        checks = indent(checks)
+        write()
+        write("int main() {")
+
+        # Turn off the GCC warning about deprecated declarations because we
+        # also want to check those
+        write()
+        write("#if defined(__GNUC__)")
+        write("#  pragma GCC diagnostic push")
+        write('#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"')
+        write("#endif")
+        write()
+
+        write(checks)
+
+        write()
+        write("#if defined(__GNUC__)")
+        write("#  pragma GCC diagnostic pop")
+        write("#endif")
+
+        write()
+        write('    printf("Everything OK!\n");')
+        write("    return 0;")
+        write("}")
+
+        if self.unknown_types:
+            self.log.info("Most common types that were not known to the type system:")
+            for type, count in self.unknown_types.most_common(10):
+                self.log.info(f"  {type} ({count})")
diff --git a/tools/py-stimulus/src/stimulus/generators/java.py b/tools/py-stimulus/src/stimulus/generators/java.py
new file mode 100644
index 00000000000..3c2ff30da51
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/java.py
@@ -0,0 +1,410 @@
+"""Java interface, experimental version using JNI (Java Native Interface)
+
+TODO: - everything :) This is just a PoC implementation.
+"""
+
+from typing import Any, Dict, IO
+
+from stimulus.errors import StimulusError
+from stimulus.model import ParamMode, ParamSpec
+
+from .base import BlockBasedCodeGenerator
+from .utils import create_indentation_function
+
+
+indent = create_indentation_function("  ")
+
+
+class JavaCodeGenerator(BlockBasedCodeGenerator):
+    """Class containing the common parts of JavaJavaCodeGenerator and
+    JavaCCodeGenerator"""
+
+    package = "net.sf.igraph"
+
+    def get_function_metadata(
+        self, name: str, type_param: str = "JAVATYPE"
+    ) -> Dict[str, Any]:
+        """Returns metadata for the given function based on the parameters.
+        f is the name of the function. The result is a dict with the following
+        keys:
+
+        - java_modifiers: Java modifiers to be used in the .java file
+        - return_type: return type of the function
+        - name: name of the function
+        - argument_types: list of argument types
+        - self_name: name of the "self" argument
+        - is_static: whether the function is static
+        - is_constructor: whether the function is a constructor
+        """
+        spec = self.get_function_descriptor(name)
+        is_constructor = False
+
+        # We will collect data related to the current function in a dict
+        data = {}
+        data["name"] = spec.get_name_in_generated_code("Java")
+        data["java_modifiers"] = ["public"]
+
+        # Check parameter types to determine Java calling semantics
+        types = {"IN": [], "OUT": [], "INOUT": []}
+        for param in spec.iter_parameters():
+            types[param.mode_str].append(param)
+
+        if len(types["OUT"]) + len(types["INOUT"]) == 1:
+            # If a single one is OUT or INOUT and all others are
+            # INs, then this is our lucky day - the method fits the Java
+            # semantics
+            if len(types["OUT"]) > 0:
+                return_type_name = types["OUT"][0].type
+            else:
+                return_type_name = types["INOUT"][0].type
+        elif len(types["OUT"]) + len(types["INOUT"]) == 0 and spec.return_type:
+            # There are only input parameters and the return type is specified,
+            # this also fits the Java semantics
+            return_type_name = spec.return_type
+        else:
+            raise StimulusError(
+                "{}: calling convention unsupported yet".format(data["name"])
+            )
+
+        # Loop through the input parameters
+        method_arguments = []
+        found_self = False
+        for param in spec.iter_parameters():
+            if param.mode is ParamMode.IN:
+                continue
+
+            type_name = param.type
+            if not found_self and type_name == "GRAPH":
+                # this will be the 'self' argument
+                found_self = True
+                data["self_name"] = param.name
+                continue
+            tdesc = self.get_or_create_type_descriptor(type_name)
+            if type_param not in tdesc:
+                raise StimulusError(
+                    "{}: unknown input type {} (needs {}), skipping".format(
+                        data["name"], type_name, type_param
+                    )
+                )
+            method_arguments.append(" ".join([tdesc[type_param], param.name]))
+        data["argument_types"] = method_arguments
+
+        if not found_self:
+            # Loop through INOUT arguments if we found no "self" yet
+            for param in spec.iter_parameters():
+                if param.mode is ParamMode.OUT and param.type == "GRAPH":
+                    found_self = True
+                    data["self_name"] = param.name
+                    break
+
+        tdesc = self.get_or_create_type_descriptor(return_type_name)
+        if type_param not in tdesc:
+            raise StimulusError(
+                "{}: unknown return type {}, skipping".format(
+                    data["name"], return_type_name
+                )
+            )
+        data["return_type"] = tdesc[type_param]
+
+        if not found_self:
+            data["java_modifiers"].append("static")
+            data["name"] = data["name"][0].upper() + data["name"][1:]
+
+        data["java_modifiers"] = " ".join(data["java_modifiers"])
+        data["is_static"] = not found_self
+        data["is_constructor"] = is_constructor
+
+        return data
+
+
+class JavaJavaCodeGenerator(JavaCodeGenerator):
+    def generate_function(self, name: str, out: IO[str]) -> None:
+        try:
+            func_metadata = self.get_function_metadata(name)
+            func_metadata["arguments"] = ", ".join(func_metadata["argument_types"])
+            out.write(
+                "    %(java_modifiers)s native %(return_type)s %(name)s(%(arguments)s);\n"
+                % func_metadata
+            )
+        except StimulusError as e:
+            out.write("    // %s\n" % str(e))
+
+
+class JavaCCodeGenerator(JavaCodeGenerator):
+    def generate_function(self, function: str, out: IO[str]) -> None:
+        try:
+            self.metadata = self.get_function_metadata(function, "CTYPE")
+        except StimulusError as e:
+            out.write("\n/* %s */\n" % str(e))
+            return
+
+        # Check types
+        if not self.check_types_of_function(function, "error"):
+            return
+
+        desc = self.get_function_descriptor(function)
+
+        ## Compile the output
+        ## This code generator is quite difficult, so we use different
+        ## functions to generate the approprite chunks and then
+        ## compile them together using a simple template.
+        ## See the documentation of each chunk below.
+        params = desc.parameters
+        try:
+            res = {}
+            res["func"] = function
+            res["header"] = self.chunk_header(function, params)
+            res["decl"] = self.chunk_declaration(function, params)
+            res["before"] = self.chunk_before(function, params)
+            res["inconv"] = self.chunk_inconv(function)
+            res["call"] = self.chunk_call(function, params)
+            res["outconv"] = self.chunk_outconv(function, params)
+            res["after"] = self.chunk_after(function, params)
+        except StimulusError as e:
+            out.write("/* %s */\n" % str(e))
+            return
+
+        # Replace into the template
+        text = (
+            """
+/*-------------------------------------------/
+/ %(func)-42s /
+/-------------------------------------------*/
+%(header)s {
+                                        /* Declarations */
+%(decl)s
+
+%(before)s
+                                        /* Convert input */
+%(inconv)s
+                                        /* Call igraph */
+%(call)s
+                                        /* Convert output */
+%(outconv)s
+
+%(after)s
+
+  return result;
+}\n"""
+            % res
+        )
+
+        out.write(text)
+
+    def chunk_header(self, function: str, params: Dict[str, ParamSpec]) -> str:
+        """The header.
+
+        The name of the function is the igraph function name minus the
+        igraph_ prefix, camelcased and prefixed with the underscored
+        Java classname: net_sf_igraph_Graph_. The arguments
+        are mapped from the JAVATYPE key of the type dict. Static
+        methods also need a 'jclass cls' argument, ordinary methods
+        need 'jobject jobj'. Besides that, the Java environment pointer
+        is also passed.
+        """
+        data = self.get_function_metadata(function, "JAVATYPE")
+
+        data["funcname"] = "Java_%s_Graph_%s" % (
+            self.package.replace(".", "_"),
+            data["name"],
+        )
+
+        if data["is_static"]:
+            data["argument_types"].insert(0, "jclass cls")
+        else:
+            data["argument_types"].insert(0, "jobject " + data["self_name"])
+        data["argument_types"].insert(0, "JNIEnv *env")
+
+        data["types"] = ", ".join(data["argument_types"])
+
+        res = "JNIEXPORT %(return_type)s JNICALL %(funcname)s(%(types)s)" % data
+        return res
+
+    def chunk_declaration(self, function: str, params: Dict[str, ParamSpec]) -> str:
+        """The declaration part of the function body
+
+        There are a couple of things to declare. First a C type is
+        needed for every argument, these will be supplied in the C
+        igraph call. Then, all 'OUT' arguments need an appropriate variable as
+        well, the result will be stored here. The return type
+        of the C function also needs to be declared, that comes
+        next. The result variable will contain the final result. Finally,
+        if the method is not static but we are returning a new Graph object
+        (e.g. in the case of igraph_linegraph), we need a jclass variable
+        to store the Java class object."""
+
+        desc = self.get_function_descriptor(function)
+
+        def do_cpar(spec: ParamSpec) -> str:
+            type_desc = self.get_type_descriptor(spec.type)
+            return type_desc.declare_c_variable(f"c_{spec.name}", mode=spec.mode)
+
+        def do_jpar(spec: ParamSpec) -> str:
+            type_desc = self.get_type_descriptor(spec.type)
+            return type_desc.declare_c_variable(
+                f"j_{spec.name}", mode=spec.mode, name_token="%J%"
+            )
+
+        inout = [do_cpar(param) for param in desc.iter_parameters()]
+        out = [
+            do_jpar(param)
+            for param in desc.iter_parameters()
+            if param.mode is ParamMode.OUT
+        ]
+
+        return_type_desc = self.get_type_descriptor(desc.return_type)
+        retdecl = return_type_desc.declare_c_variable("c__result")
+
+        rnames = [n for n, p in params.items() if p.is_output]
+        jretdecl = ""
+        if len(rnames) > 0:
+            n = rnames[0]
+            rtname = params[n].type
+        else:
+            rtname = desc.return_type
+
+        rt = self.get_type_descriptor(rtname)
+        if "JAVADECL" in rt:
+            jretdecl = rt["JAVADECL"]
+        elif "JAVATYPE" in rt:
+            jretdecl = rt["JAVATYPE"] + " result;"
+
+        decls = inout + out + [retdecl, jretdecl]
+        if not self.metadata["is_static"] and rtname == "GRAPH":
+            self.metadata["need_class_decl"] = True
+            decls.append(
+                "jclass cls = (*env)->GetObjectClass(env, %s);"
+                % self.metadata["self_name"]
+            )
+        else:
+            self.metadata["need_class_decl"] = False
+        return indent("\n".join(i for i in decls if i != ""))
+
+    def chunk_before(self, function: str, params: Dict[str, ParamSpec]) -> str:
+        """We simply call Java_igraph_before"""
+        return "  Java_igraph_before();"
+
+    def chunk_inconv(self, function: str) -> str:
+        """Input conversions. Not only for types with mode 'IN' and
+        'INOUT', eg. for 'OUT' vector types we need to allocate the
+        required memory here, do all the initializations, etc. Types
+        without INCONV fields are ignored. The usual %C%, %I% is
+        performed at the end.
+        """
+
+        desc = self.get_function_descriptor(function)
+
+        def do_par(param: ParamSpec):
+            cname = "c_" + param.name
+            t = self.get_type_descriptor(param.type)
+            inconv = t.get_input_conversion_template_for(param.mode)
+            if inconv:
+                inconv = indent(inconv)
+            for i, dep in enumerate(param.dependencies):
+                inconv = inconv.replace("%C" + str(i + 1) + "%", "c_" + dep)
+
+            return inconv.replace("%C%", cname).replace("%I%", param.name)
+
+        inconv = [do_par(param) for param in desc.iter_parameters()]
+        inconv = [i for i in inconv if i != ""]
+
+        return "\n".join(inconv)
+
+    def chunk_call(self, function, params):
+        """Every single argument is included, independently of their
+        mode. If a type has a 'CALL' field then that is used after the
+        usual %C% and %I% substitutions, otherwise the standard 'c_'
+        prefixed C argument name is used.
+        """
+        types = [self.get_type_descriptor(params[n].type) for n in params]
+        call = list(
+            map(lambda t, n: t.get("CALL", "c_" + n), types, list(params.keys()))
+        )
+        call = list(
+            map(
+                lambda c, n: c.replace("%C%", "c_" + n).replace("%I%", n),
+                call,
+                list(params.keys()),
+            )
+        )
+        lines = [
+            "  if ((*env)->ExceptionCheck(env)) {",
+            "    c__result = IGRAPH_EINVAL;",
+            "  } else {",
+            "    c__result = " + function + "(" + ", ".join(call) + ");",
+            "  }",
+        ]
+        return "\n".join(lines)
+
+    def chunk_outconv(self, function: str, params: Dict[str, ParamSpec]) -> str:
+        """The output conversions, this is quite difficult. A function
+        may report its results in two ways: by returning it directly
+        or by setting a variable to which a pointer was passed. igraph
+        usually uses the latter and returns error codes, except for
+        some simple functions like 'igraph_vcount()' which cannot
+        fail.
+
+        First we add the output conversion for all types. This is
+        easy. Note that even 'IN' arguments may have output
+        conversion, eg. this is the place to free memory allocated to
+        them in the 'INCONV' part.
+
+        Then we check how many 'OUT' or 'INOUT' arguments we
+        have. There are three cases. If there is a single such
+        argument then that is already converted and we need to return
+        that. If there is no such argument then the output of the
+        function was returned, so we perform the output conversion for
+        the returned type and this will be the result. The case of
+        more than one 'OUT' and 'INOUT' arguments is not yet supported by
+        the Java interface.
+        """
+
+        spec = self.get_function_descriptor(function)
+
+        def do_par(pname):
+            cname = "c_" + pname
+            jname = "j_" + pname
+            t = self.get_type_descriptor(params[pname].type)
+            outconv = t.get_output_conversion_template_for(params[pname].mode)
+            if outconv:
+                outconv = indent(outconv)
+            return outconv.replace("%C%", cname).replace("%I%", jname)
+
+        outconv = [do_par(n) for n in params]
+        outconv = [o for o in outconv if o != ""]
+
+        retpars = [(n, p) for n, p in params.items() if p.is_output]
+        if len(retpars) == 0:
+            # return the return value of the function
+            rt = self.get_type_descriptor(spec.return_type)
+            retconv = rt.get_output_conversion_template_for(ParamMode.OUT)
+            if retconv:
+                retconv = indent(retconv)
+            retconv = retconv.replace("%C%", "c__result").replace("%I%", "result")
+            if len(retconv) > 0:
+                outconv.append(retconv)
+            ret = "\n".join(outconv)
+        elif len(retpars) == 1:
+            # return the single output value
+            if retpars[0][1].mode is ParamMode.OUT:
+                # OUT parameter
+                retconv = "  result = j_" + retpars[0][0] + ";"
+            else:
+                # INOUT parameter
+                retconv = "  result = " + retpars[0][0] + ";"
+            outconv.append(retconv)
+
+            outconv.insert(0, "if (c__result == 0) {")
+            outconv.extend(["} else {", "  result = 0;", "}"])
+            outconv = [indent(line) for line in outconv]
+            ret = "\n".join(outconv)
+        else:
+            raise StimulusError(
+                "{}: the case of multiple outputs not supported yet".format(function)
+            )
+
+        return ret
+
+    def chunk_after(self, function, params):
+        """We simply call Java_igraph_after"""
+        return "  Java_igraph_after();"
diff --git a/tools/py-stimulus/src/stimulus/generators/python.py b/tools/py-stimulus/src/stimulus/generators/python.py
new file mode 100644
index 00000000000..772a2624e55
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/python.py
@@ -0,0 +1,623 @@
+"""Code generators for an experimental generated Python interface of igraph."""
+
+from contextlib import contextmanager, ExitStack
+from dataclasses import dataclass
+from functools import lru_cache
+from typing import Callable, Dict, IO, Iterator, List, Optional, Sequence, Set, Tuple
+
+from stimulus.errors import CodeGenerationError, NoSuchTypeError
+from stimulus.model.functions import FunctionDescriptor
+from stimulus.model.parameters import DefaultValueType, ParamMode, ParamSpec
+from stimulus.model.types import TypeDescriptor
+
+from .base import SingleBlockCodeGenerator
+from .utils import create_indentation_function, remove_prefix
+
+
+indent = create_indentation_function("    ")
+
+
+@lru_cache(maxsize=128)
+def _get_ctypes_arg_type_from_c_arg_type(c_type: str):
+    # Strip "const" from the front
+    c_type = c_type.strip()
+    while c_type.startswith("const "):
+        c_type = c_type[6:].strip()
+
+    # Replace pointer asterisks
+    wrap_counter = 0
+    while c_type.endswith("*"):
+        c_type = c_type[:-1].strip()
+        wrap_counter += 1
+
+    # Add c_ prefix if needed
+    if c_type in (
+        "char",
+        "int",
+        "float",
+        "double",
+        "size_t",
+        "ssize_t",
+        "bool",
+        "void",
+    ):
+        c_type = f"c_{c_type}"
+
+    # Some ctypes types have specific aliases for the single-pointer case
+    if wrap_counter > 0 and c_type in ("c_void", "c_char", "c_wchar"):
+        wrap_counter -= 1
+        c_type = f"{c_type}_p"
+
+    # Wrap the type in POINTER() as many times as needed
+    while wrap_counter > 0:
+        c_type = f"POINTER({c_type})"
+        wrap_counter -= 1
+
+    # c_void should be substituted with None
+    if c_type == "c_void":
+        c_type = "None"
+
+    return c_type
+
+
+def _get_python_type_from_type_spec(
+    type_spec: TypeDescriptor, out: bool = False
+) -> Optional[str]:
+    if out and "PY_RETURN_TYPE" in type_spec:
+        return type_spec.get("PY_RETURN_TYPE")
+    elif "PY_TYPE" in type_spec:
+        return type_spec.get("PY_TYPE")
+    else:
+        raise CodeGenerationError(f"no Python type known for type: {type_spec.name}")
+
+
+def _format_docstring(value: str) -> str:
+    """Formats a Python docstring."""
+    value = indent(value.strip()).strip()
+    if "\n" not in value:
+        return f'    """{value}"""'
+    else:
+        return f'    """{value}\n    """'
+
+
+class IndentedWriter:
+    """Helper class to dynamically manage indentation levels while creating the
+    body of a function.
+    """
+
+    _indentation: str = "    "
+    """The indentation prefix for each line for a single indentation level."""
+
+    _level: int = 0
+    """The current indentation level."""
+
+    _writer: Callable[[str], None]
+    """The writer function to wrap."""
+
+    def __init__(self, writer: Callable[[str], None], *, level: int = 0):
+        """Constructor."""
+        self._writer = writer
+        self._level = level
+
+    @contextmanager
+    def indent(self) -> Iterator[None]:
+        """Context manager that increases the current indentation level
+        while the execution is in the context.
+        """
+        self._level += 1
+        try:
+            yield
+        finally:
+            self._level -= 1
+
+    def write(self, line: str) -> None:
+        if line:
+            line = (self._indentation * self._level) + line
+        self._writer(line)
+
+    __call__ = write
+
+
+class PythonCTypesCodeGenerator(SingleBlockCodeGenerator):
+    """Code generator that generates argument and return value specifications
+    of each igraph function using the Python ctypes module.
+
+    This generator generates a Python code snippet that can be inserted into
+    a Python source file, assuming that the following assumptions hold:
+
+    * the Python source file contains a variable named ``_lib`` that refers to
+      igraph's C shared library as loaded by ``ctypes``
+
+    * it also has a callable named ``handle_igraph_error_t`` that takes an
+      igraph error code and raises an approprate exception if the error code
+      is nonzero (and returns ``None`` otherwise)
+
+    * all the C data types used in the functions are present in the Python
+      namespace, aliased to the appropriate ctypes types
+    """
+
+    bitfield_types: Set[str]
+    enum_types: Set[str]
+    lines: List[str]
+
+    def generate_preamble(self, inputs: Sequence[str], output: IO[str]) -> None:
+        self.bitfield_types = set()
+        self.enum_types = set()
+        self.lines = []
+        return super().generate_preamble(inputs, output)
+
+    def generate_function(self, name: str, output: IO[str]) -> None:
+        self.lines.append("")
+        try:
+            self._generate_function(name, self.lines.append)
+        except CodeGenerationError as ex:
+            self.lines.append(f"# {name}: {ex}")
+
+    def _generate_function(self, name: str, write: Callable[[str], None]) -> None:
+        # Check types
+        self.check_types_of_function(name)
+
+        # Get function specification
+        spec = self.get_function_descriptor(name)
+
+        # Construct Python return type
+        return_type = self.get_type_descriptor(spec.return_type)
+        py_return_type: Optional[str] = return_type.get("CTYPES_RETURN_TYPE")
+        if not py_return_type:
+            # Try deriving the ctypes type
+            py_return_type = _get_ctypes_arg_type_from_c_arg_type(
+                return_type.get_c_type()
+            )
+
+        if not py_return_type:
+            raise NoSuchTypeError(
+                spec.return_type,
+                message=f"No ctypes return type known for abstract type {spec.return_type}",
+            )
+
+        # Remember the type if it is an enum type or a bitfield type
+        if return_type.is_enum:
+            self.enum_types.add(py_return_type)
+        if return_type.is_bitfield:
+            self.bitfield_types.add(py_return_type)
+
+        # Construct Python argument types in the ctypes layer
+        py_arg_types: List[str] = []
+        for parameter in spec.iter_parameters():
+            if parameter.is_deprecated:
+                continue
+
+            param_type = self.get_type_descriptor(parameter.type)
+            c_arg_type = param_type.declare_c_function_argument(mode=parameter.mode)
+            if not c_arg_type:
+                # This argument is not present in the C function calls
+                continue
+
+            py_arg_type = _get_ctypes_arg_type_from_c_arg_type(c_arg_type)
+            py_arg_types.append(py_arg_type)
+
+            # Remember the type if it is an enum type or a bitfield type
+            if param_type.is_enum:
+                self.enum_types.add(py_arg_type)
+            if param_type.is_bitfield:
+                self.bitfield_types.add(py_arg_type)
+
+        py_arg_types_joined = ", ".join(py_arg_types)
+
+        write(f"{name} = _lib.{name}")
+        write(f"{name}.restype = {py_return_type}")
+        write(f"{name}.argtypes = [{py_arg_types_joined}]")
+
+    def generate_epilogue(self, inputs: Sequence[str], output: IO[str]) -> None:
+        write = output.write
+
+        if self.enum_types:
+            write("# Set up aliases for all enum types\n")
+            write("\n")
+            for enum_type in sorted(self.enum_types):
+                write(f"{enum_type} = c_int\n")
+            write("\n")
+
+        if self.bitfield_types:
+            write("# Set up aliases for all bitfield types\n")
+            write("\n")
+            for bitfield_type in sorted(self.bitfield_types):
+                write(f"{bitfield_type} = c_int\n")
+            write("\n")
+
+        write("# Add argument and return types for functions imported from igraph\n")
+        write("\n".join(self.lines))
+        write("\n")
+
+        return super().generate_epilogue(inputs, output)
+
+
+@dataclass
+class ArgInfo:
+    param_spec: ParamSpec
+    type_spec: TypeDescriptor
+
+    c_name: str
+    py_name: str
+    py_type: str
+
+    appears_in_argument_list: bool = False
+    default_value: Optional[str] = None
+
+    @classmethod
+    def from_param_spec(
+        cls, spec: ParamSpec, type_descriptor_getter: Callable[[str], TypeDescriptor]
+    ):
+        type = type_descriptor_getter(spec.type)
+
+        py_name = spec.name
+
+        # Translate Python reserved keywords
+        if py_name in ("from", "in", "lambda"):
+            py_name += "_"
+
+        c_name = f"c_{spec.name}"
+
+        py_type = _get_python_type_from_type_spec(type)
+        if spec.is_optional and py_type and not py_type.startswith("Optional["):
+            py_type = f"Optional[{py_type}]"
+
+        result = cls(
+            param_spec=spec,
+            type_spec=type,
+            c_name=c_name,
+            py_name=py_name,
+            py_type=py_type or "None",
+        )
+
+        if py_type is None:
+            # Python type of argument is explicitly declared to be "null", so
+            # we need to exclude it from the argument list no matter what
+            result.appears_in_argument_list = False
+        elif spec.is_deprecated:
+            # Deprecated args do not appear in the argument list either
+            result.appears_in_argument_list = False
+        else:
+            # IN and INOUT arguments will appear in the Python call signature;
+            # pure OUT arguments will not
+            result.appears_in_argument_list = spec.is_input
+
+        # Map default value to Python
+        if spec.has_default_value:
+            result.default_value = spec.get_default_value(type) or "None"
+
+            # Map "NULL" to "None"
+            if result.default_value == "NULL":
+                result.default_value = "None"
+
+            # For enums, prefix the name of the default value with the name
+            # of the enum
+            if (
+                type.is_enum
+                and spec.default is not None
+                and spec.default[0] == DefaultValueType.ABSTRACT
+                and result.default_value == spec.default[1]
+                and py_type is not None
+            ):
+                result.default_value = py_type + "." + result.default_value
+        else:
+            result.default_value = None
+
+        return result
+
+    @property
+    def name(self) -> str:
+        return self.param_spec.name
+
+    def get_argument_for_function_call(self, args: Dict[str, "ArgInfo"]) -> str:
+        template = self.type_spec.get("CALL")
+        if template:
+            return self._apply_replacements(template, args)
+        else:
+            return self.c_name
+
+    def get_input_conversion(self, args: Dict[str, "ArgInfo"]) -> Optional[str]:
+        if not self.appears_in_argument_list:
+            default = "%C% = None"
+        elif self.param_spec.is_input:
+            default = "%C% = %I%"
+        else:
+            default = ""
+        template = self.type_spec.get_input_conversion_template_for(
+            self.param_spec.mode, default=default
+        )
+        if not template:
+            if not self.param_spec.is_input:
+                raise CodeGenerationError(
+                    f"Cannot construct an instance of abstract type {self.type_spec.name}"
+                )
+            else:
+                return None
+        else:
+            if (
+                self.param_spec.is_input
+                and self.param_spec.is_optional
+                and self.default_value in (None, "None")
+            ):
+                template = f"{template} if %I% is not None else None"
+            return self._apply_replacements(template, args)
+
+    def get_output_conversion(self, args: Dict[str, "ArgInfo"]) -> Optional[str]:
+        if self.param_spec.mode == ParamMode.OUT:
+            default = "%I% = %C%.value"
+        else:
+            default = ""
+        template = self.type_spec.get_output_conversion_template_for(
+            self.param_spec.mode, default=default
+        )
+        if not template:
+            return None
+        else:
+            return self._apply_replacements(template, args)
+
+    def get_python_declaration(self) -> str:
+        """Returns the declaration of this argument for the Python function header."""
+        if self.default_value is None and not self.param_spec.is_optional:
+            return f"{self.py_name}: {self.py_type}"
+        elif self.default_value == "None" and not self.py_type.startswith("Optional["):
+            return f"{self.py_name}: Optional[{self.py_type}] = None"
+        else:
+            return f"{self.py_name}: {self.py_type} = {self.default_value}"
+
+    @property
+    def needs_exit_stack(self) -> bool:
+        """Returns whether this argument needs an exit stack for properly
+        handling its input and/or output conversions.
+        """
+        return self.type_spec.has_flag("stack")
+
+    def _apply_replacements(self, value: str, args: Dict[str, "ArgInfo"]) -> str:
+        value = value.replace("%I%", self.py_name)
+        value = value.replace("%C%", self.c_name)
+        if self.needs_exit_stack:
+            value = value.replace("%S%", "py__stack")
+
+        for index, dep in enumerate(self.param_spec.dependencies, 1):
+            arg = args.get(dep)
+            if arg is None:
+                raise CodeGenerationError(
+                    f"Unknown dependency for parameter {self.py_name!r}: {dep!r}"
+                )
+            value = value.replace(f"%I{index}%", arg.py_name)
+            value = value.replace(f"%C{index}%", arg.c_name)
+
+        return value
+
+
+class PythonCTypesTypedWrapperCodeGenerator(SingleBlockCodeGenerator):
+    def generate_function(self, name: str, output: IO[str]) -> None:
+        write = output.write
+
+        lines = [""]
+        try:
+            self._generate_function(name, lines.append)
+            lines.append("")
+            write("\n".join(lines))
+        except CodeGenerationError as ex:
+            write(f"\n# {name}: {ex}\n")
+
+    def _generate_function(self, name: str, write: Callable[[str], None]) -> None:
+        writer = IndentedWriter(write)
+        write = writer.write
+
+        # Check types
+        self.check_types_of_function(name)
+
+        # Get function specification
+        spec = self.get_function_descriptor(name)
+
+        # Derive Python name of the function from its C name
+        py_name = self._get_python_name(spec)
+
+        # Construct Python arguments
+        args = self._process_argument_list(spec)
+
+        # Decide in which order the arguments should appear on the Python side.
+        # Arguments with no default values must appear earlier even if they are
+        # declared later on the C side. Python's sort is stable so the code
+        # below will keep the order when possible.
+        arg_specs = [
+            arg_spec
+            for arg_spec in spec.iter_reordered_parameters()
+            if args[arg_spec.name].appears_in_argument_list
+        ]
+        arg_specs = sorted(
+            arg_specs,
+            key=lambda arg_spec: 1
+            if arg_spec.default is None and not arg_spec.is_optional
+            else 2,
+        )
+
+        # Determine return type and argument ordering
+        py_return_type, return_arg_names, return_types = self._get_return_type_and_args(
+            spec
+        )
+        py_args = [
+            args[arg_spec.name].get_python_declaration() for arg_spec in arg_specs
+        ]
+
+        # Find the longest suffix of the argument list that consists solely of
+        # keyword-only arguments, and insert * in py_args as needed
+        idx = len(arg_specs)
+        while idx > 0 and arg_specs[idx - 1].is_keyword_only:
+            idx -= 1
+        if idx < len(arg_specs):
+            py_args.insert(idx, "*")
+
+        # Print function header
+        write("")
+        write(f"def {py_name}({', '.join(py_args)}) -> {py_return_type}:")
+
+        # Print documentation string (if any)
+        docstring = self.docstring_provider(spec.name) or (
+            f"Type-annotated wrapper for ``{spec.name}``."
+        )
+        write(_format_docstring(docstring))
+
+        # Check whether we will need an exit stack in the generated code
+        needs_exit_stack = any(
+            args[param_spec.name].needs_exit_stack
+            for param_spec in spec.iter_parameters()
+        )
+
+        with ExitStack() as stack:
+            stack.enter_context(writer.indent())
+
+            # Add exit stack context if needed
+            if needs_exit_stack:
+                write("# Create exit stack for graceful cleanup")
+                write("with ExitStack() as py__stack:")
+                write("")
+                stack.enter_context(writer.indent())
+
+            # Add input conversion calls
+            convs = [
+                args[param_spec.name].get_input_conversion(args)
+                for param_spec in spec.iter_parameters()
+            ]
+            convs = [conv for conv in convs if conv]
+            if convs:
+                write("# Prepare input arguments")
+                for conv in convs:
+                    write(conv)
+                write("")
+
+            write("# Call wrapped function")
+            needs_return_value_from_c_call = "" in return_arg_names
+            c_args = ", ".join(
+                args[arg_spec.name].get_argument_for_function_call(args)
+                for arg_spec in spec.iter_parameters()
+            )
+            c_call = f"{name}({c_args})"
+            if needs_return_value_from_c_call:
+                c_call = f"c__result = {c_call}"
+            write(c_call)
+
+            # Add output conversion calls
+            convs = [
+                args[param_spec.name].get_output_conversion(args)
+                for param_spec in spec.iter_parameters()
+            ]
+            convs = [conv for conv in convs if conv]
+            if convs:
+                write("")
+                write("# Prepare output arguments")
+                for conv in convs:
+                    write(conv)
+
+            if return_arg_names:
+                return_var = "c__result"
+
+                try:
+                    idx = return_arg_names.index("")
+                except ValueError:
+                    tmpl = ""
+                    idx = -1
+                else:
+                    tmpl = return_types[idx].get_output_conversion_template_for(
+                        ParamMode.OUT
+                    )
+
+                if tmpl:
+                    conv = tmpl.replace("%I%", "py__result").replace("%C%", "c__result")
+                    return_var = "py__result"
+                    write("")
+                    write("# Prepare return value")
+                    write(conv)
+
+                write("")
+                write("# Construct return value")
+                if len(return_arg_names) == 1:
+                    if needs_return_value_from_c_call:
+                        var_name = return_var
+                    else:
+                        var_name = args[return_arg_names[0]].py_name
+                    write(f"return {var_name}")
+                else:
+                    joint_parts = ", ".join(
+                        args[name].py_name if name else return_var
+                        for name in return_arg_names
+                    )
+                    write(f"return {joint_parts}")
+
+        # If an exit stack was needed, let the type checker know that it is
+        # impossible to get outside the stack
+        if needs_exit_stack and return_arg_names:
+            with writer.indent():
+                write("")
+                write("# Help the type checker to figure out that we never get here")
+                write('assert False, "unreachable"  # noqa: B011')
+
+    def _get_python_name(self, spec: FunctionDescriptor) -> str:
+        return spec.get("NAME") or remove_prefix(spec.name, "igraph_")
+
+    def _get_return_type_and_args(
+        self, spec: FunctionDescriptor
+    ) -> Tuple[str, List[str], List[TypeDescriptor]]:
+        """Returns the return type of the given function, the names of the
+        C arguments from which the output arguments are created and the
+        corresponding type descriptors.
+
+        An empty string in the returned argument list means that the return
+        value of the C function should be converted into the return value of
+        the Python function.
+
+        The rules are as follows:
+
+        - The index of each argument marked as OUT appears in the returned list
+          of arguments.
+
+        - INOUT parameters are _not_ returned, but it is assumed that the
+          function will mutate these arguments in-place.
+
+        - If the function is declared to return with an `ERROR` abstract type,
+          it is assumed that the underlying ctypes wrapper handles the error and
+          raises appropriate exceptions.
+
+        - If the function is declared to return any other abstract type than
+          `ERROR` or `VOID`, the return value itself is _also_ considered and
+          -1 is prepended to the list of argument indices.
+        """
+        arg_names: List[str] = []
+        arg_types: List[TypeDescriptor] = []
+        arg_type_strs: List[str]
+
+        return_type = self.get_type_descriptor(spec.return_type)
+        if return_type.name != "ERROR" and return_type.name != "VOID":
+            arg_names.append("")
+            arg_types.append(return_type)
+
+        for parameter in spec.iter_parameters():
+            if not parameter.is_deprecated and not parameter.is_input:
+                arg_names.append(parameter.name)
+                arg_types.append(self.get_type_descriptor(parameter.type))
+
+        arg_type_strs = []
+        for arg_spec in arg_types:
+            py_type = _get_python_type_from_type_spec(arg_spec, out=True)
+            if py_type is None:
+                raise CodeGenerationError(
+                    f"no Python type known for type {arg_spec.name!r} and "
+                    f"it needs to be used as a return value"
+                )
+            arg_type_strs.append(py_type)
+
+        if not arg_type_strs:
+            output_type = "None"
+        elif len(arg_type_strs) == 1:
+            output_type = arg_type_strs[0]
+        else:
+            output_type = "tuple[" + ", ".join(arg_type_strs) + "]"
+
+        return output_type, arg_names, arg_types
+
+    def _process_argument_list(self, spec: FunctionDescriptor) -> Dict[str, ArgInfo]:
+        return {
+            param.name: ArgInfo.from_param_spec(param, self.get_type_descriptor)
+            for param in spec.iter_parameters()
+        }
diff --git a/tools/py-stimulus/src/stimulus/generators/r.py b/tools/py-stimulus/src/stimulus/generators/r.py
new file mode 100644
index 00000000000..d80b5dc70f9
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/r.py
@@ -0,0 +1,663 @@
+"""GNU R interface, see http://www.r-project.org
+
+TODO: free memory when CTRL+C pressed, even on Windows
+"""
+
+import re
+
+from shlex import quote
+from typing import Iterable, IO, Optional, Tuple
+
+from stimulus.errors import NoSuchTypeError
+from stimulus.model import ParamMode, ParamSpec
+from stimulus.model.functions import FunctionDescriptor
+
+from .base import (
+    BlockBasedCodeGenerator,
+    SingleBlockCodeGenerator,
+)
+from .utils import create_indentation_function
+
+
+indent = create_indentation_function("  ")
+
+init_functions = {
+    "igraph_vector_int_t": "IGRAPH_R_CHECK(igraph_vector_int_init(&%C%, 0));\nIGRAPH_FINALLY(igraph_vector_int_destroy, &%C%);"
+}
+
+
+def get_r_parameter_name(param: ParamSpec) -> str:
+    result = param.name_in_higher_level_interface
+    if result == param.name:
+        result = result.replace("_", ".")
+    return result
+
+
+def optional_wrapper_c(conv: str, c_type: str) -> str:
+    # Workaround for legacy types in R which have Rf_isNull
+    # TODO: refactoring types in R
+    if "Rf_isNull" in conv:
+        return conv
+    result = ""
+    optional_template = ["if (!Rf_isNull(%I%)) {\n", indent(conv), "\n}"]
+
+    if c_type in init_functions:
+        optional_template += [" else {\n", indent(init_functions[c_type]), "\n}"]
+
+    return result.join(optional_template)
+
+
+def optional_wrapper_r(conv: str) -> str:
+    if "is.null" in conv:
+        return conv
+
+    return f"if (!is.null(%I%)) {conv}"
+
+
+class RRCodeGenerator(SingleBlockCodeGenerator):
+    def generate_function(self, function: str, out: IO[str]) -> None:
+        # Check types
+        self.check_types_of_function(function)
+
+        # Get function specification
+        spec = self.get_function_descriptor(function)
+
+        # Derive name of R function
+        name = spec.get_name_in_generated_code("R")
+
+        ## Header
+        ## do_par handles the translation of a single argument in the
+        ## header. Pretty simple, the only difficulty is that we
+        ## might need to add default values. Default values are taken
+        ## from a language specific dictionary, this is compiled from
+        ## the type file(s).
+
+        ## So we take all arguments with mode 'IN' or 'INOUT' and
+        ## check whether they have a default value. If yes then we
+        ## check if the default value is given in the type file. If
+        ## yes then we use the value given there, otherwise the
+        ## default value is used as is.
+
+        ## Finally, if the function designates one or more of its output
+        ## parameters as primary parameters, and there is at least one
+        ## non-primary output parameter, the function needs a "details"
+        ## parameter as well that lets the user specify whether the
+        ## non-primary parameters are needed.
+
+        ## TODO(ntamas): if the function designates one or more of its
+        ## arguments as "primary" and the user is not interested in the
+        ## details, do not generate conversion code for the non-primary
+        ## arguments if they are optional
+
+        needs_details_arg = (
+            spec.has_primary_output_parameter and spec.has_non_primary_output_parameter
+        )
+
+        out.write(name)
+        out.write("_impl <- function(")
+
+        def handle_input_argument(param: ParamSpec) -> str:
+            tname = param.type
+            type_desc = self.get_type_descriptor(tname)
+            header = name_in_r_interface = get_r_parameter_name(param)
+            if "HEADER" in type_desc:
+                header = type_desc["HEADER"] or ""
+            if header:
+                header = header.replace("%I%", name_in_r_interface)
+            else:
+                header = ""
+
+            default = param.get_default_value(type_desc) or (
+                "NULL" if param.is_optional and header else ""
+            )
+            if default:
+                header = f"{header}={default}"
+
+            for i, dep in enumerate(param.dependencies):
+                header = header.replace("%I" + str(i + 1) + "%", dep)
+
+            if re.search("%I[0-9]*%", header):
+                self.log.error(
+                    f"Missing HEADER dependency for {tname} {param.name} in function {function}"
+                )
+
+            return header
+
+        head = [
+            handle_input_argument(param)
+            for param in spec.iter_input_parameters(reorder=True)
+            if not param.is_keyword_only
+        ]
+        head = [h for h in head if h != ""]
+
+        head2 = [
+            handle_input_argument(param)
+            for param in spec.iter_input_parameters(reorder=True)
+            if param.is_keyword_only
+        ]
+        head2 = [h for h in head2 if h != ""]
+
+        if head2:
+            head.append("...")
+            head.extend(head2)
+            has_dots_arg = True
+        else:
+            has_dots_arg = False
+
+        if needs_details_arg:
+            if "details" in head:
+                # We already have another parameter named "details" so we
+                # pretend that we don't have primary output parameters
+                self.log.warn(
+                    f"Primary parameters declared for function {function}, which already "
+                    f"has an argument named 'details'; not adding another one."
+                )
+                needs_details_arg = False
+        if needs_details_arg:
+            head.append("details=FALSE")
+
+        out.write(", ".join(head))
+        out.write(") {\n")
+
+        ## Argument checks, INCONV
+        ##
+        ## We take 'IN' and 'INOUT' mode arguments and if they have an
+        ## INCONV field then we use that. This is typically for
+        ## argument checks, like we check here that the argument
+        ## supplied for a graph is indeed an igraph graph object. We
+        ## also convert numeric vectors to 'double' here.
+
+        ## The INCONV fields are simply concatenated by newline
+        ## characters.
+        out.write("  # Argument checks\n")
+
+        if has_dots_arg:
+            out.write("  check_dots_empty()\n")
+
+        def handle_argument_check(param: ParamSpec) -> str:
+            tname = param.type
+            t = self.get_type_descriptor(tname)
+            res = t.get_input_conversion_template_for(param.mode)
+
+            if param.is_optional and param.is_input and res:
+                res = optional_wrapper_r(res)
+
+            # Replace template placeholders
+            res = indent(res).replace("%I%", get_r_parameter_name(param))
+            for i, dep in enumerate(param.dependencies):
+                res = res.replace("%I" + str(i + 1) + "%", dep)
+
+            if re.search("%I[0-9]*%", res):
+                self.log.error(
+                    f"Missing IN dependency for {tname} {param.name} in function {function}"
+                )
+
+            return res
+
+        inconv = [handle_argument_check(param) for param in spec.iter_parameters()]
+        inconv = [i for i in inconv if i != ""]
+        out.write("\n".join(inconv) + "\n\n")
+
+        ## Function call
+        ## This is a bit more difficult than INCONV. Here we supply
+        ## each argument to the .Call function, if the argument has a
+        ## 'CALL' field then it is used, otherwise we simply use its
+        ## name.
+        ##
+        ## Note that arguments with empty CALL fields are
+        ## completely ignored, so giving an empty CALL field is
+        ## different than not giving it at all.
+
+        out.write("  on.exit( .Call(R_igraph_finalizer) )\n")
+        out.write("  # Function call\n")
+        out.write("  res <- .Call(R_" + function)
+
+        parts = []
+        for param in spec.iter_input_parameters():
+            type = self.get_type_descriptor(param.type)
+            name = get_r_parameter_name(param)
+            call = type.get("CALL", name)
+            if call:
+                parts.append(call.replace("%I%", name))
+
+        if len(parts):
+            out.write(", " + ", ".join(parts))
+        out.write(")\n")
+
+        ## Output conversions
+        def handle_output_argument(
+            param: ParamSpec,
+            realname: Optional[str] = None,
+            *,
+            iprefix: str = "",
+        ):
+            if realname is None:
+                realname = get_r_parameter_name(param)
+
+            tname = param.type
+            t = self.get_type_descriptor(tname)
+            outconv = indent(t.get_output_conversion_template_for(param.mode))
+            outconv = outconv.replace("%I%", iprefix + realname)
+            for i, dep in enumerate(param.dependencies):
+                outconv = outconv.replace("%I" + str(i + 1) + "%", dep)
+
+            if re.search("%I[0-9]*%", outconv):
+                self.log.error(
+                    f"Missing OUT dependency for {tname} {param.name} in function {function}"
+                )
+
+            return re.sub("%I[0-9]+%", "", outconv)
+
+        retpars = [param.name for param in spec.iter_output_parameters()]
+
+        if len(retpars) <= 1:
+            outconv = [
+                handle_output_argument(param, "res") for param in spec.iter_parameters()
+            ]
+        else:
+            outconv = [
+                handle_output_argument(param, iprefix="res$")
+                for param in spec.iter_parameters()
+            ]
+
+        outconv = [o for o in outconv if o != ""]
+
+        if len(retpars) == 0:
+            # returning the return value of the function
+            rt = self.get_type_descriptor(spec.return_type)
+            retconv = indent(rt.get_output_conversion_template_for(ParamMode.OUT))
+            retconv = retconv.replace("%I%", "res")
+            # TODO: %I1% etc, is not handled here!
+            outconv.append("")
+            outconv.append(retconv)
+        elif len(retpars) == 1:
+            # returning a single output value
+            pass
+        else:
+            # returning a list of output values
+            if needs_details_arg:
+                # user had the option to switch between the primary or all the
+                # output arguments. If we only have a single primary argument,
+                # simply return that; otherwise pick the relevant ones from the
+                # result list
+                pick_details = ["if (!details) {"]
+                primary_params = list(spec.iter_primary_output_parameters())
+                if len(primary_params) == 1:
+                    primary_param = primary_params[0]
+                    pick_details.append(f"  res <- res${primary_param.name}")
+                else:
+                    names = ", ".join(quote(param.name) for param in primary_params)
+                    pick_details.append(f"  res <- res[c({names})]")
+                pick_details.append("}")
+                outconv.extend(indent(line) for line in pick_details)
+            else:
+                # just use the output arguments as they are
+                pass
+        out.write("\n".join(outconv) + "\n")
+
+        ## Some graph attributes to add
+        if "R" not in spec:
+            # Convert legacy "GATTR-R", "GATTR-PARAM-R", "CLASS-R" and "PP-R"
+            r_namespace = {}
+            for key in ("GATTR", "GATTR-PARAM", "CLASS", "PP"):
+                r_key = f"{key}-R"
+                if r_key in spec:
+                    r_namespace[key] = spec[r_key]
+            if r_namespace:
+                spec._obj["R"] = r_namespace
+
+        r_spec = spec._obj.get("R", {})
+
+        ## Add graph attributes
+        if "GATTR" in r_spec or "GATTR-PARAM" in r_spec:
+            gattrs_dict = {}
+            lines = []
+
+            gattrs = r_spec.get("GATTR")
+            pars = r_spec.get("GATTR-PARAM")
+
+            if isinstance(gattrs, dict):
+                gattrs_dict.update(gattrs)
+            elif gattrs is not None:
+                for item in gattrs.split(","):
+                    name, value = item.split(" IS ", 1)
+                    name = name.strip()
+                    value = value.strip()
+                    gattrs_dict[name] = value
+
+            if gattrs_dict:
+                lines.extend(
+                    f"res${name} <- {val!r}" for name, val in gattrs_dict.items()
+                )
+
+            if pars is not None:
+                if isinstance(pars, str):
+                    pars = pars.split(",")
+                for par in pars:
+                    par = par.strip().replace("_", ".")
+                    lines.append(f"res${par} <- {par}")
+
+            if lines:
+                out.write('  if (igraph_opt("add.params")) {\n')
+                for line in lines:
+                    out.write(indent(indent(line)) + "\n")
+                out.write("  }\n\n")
+
+        ## Set the class if requested
+        if "CLASS" in r_spec:
+            out.write(f'  class(res) <- "{r_spec["CLASS"]}"\n')
+
+        ## See if there is a postprocessor
+        if "PP" in r_spec:
+            out.write(f'  res <- {r_spec["PP"]}(res)\n')
+
+        out.write("  res\n}\n\n")
+
+
+class RCCodeGenerator(SingleBlockCodeGenerator):
+    def generate_function(self, function: str, out: IO[str]) -> None:
+        # Check types
+        self.check_types_of_function(function, errors="error")
+
+        desc = self.get_function_descriptor(function)
+
+        ## Compile the output
+        ## This code generator is quite difficult, so we use different
+        ## functions to generate the approprite chunks and then
+        ## compile them together using a simple template.
+        ## See the documentation of each chunk below.
+        res = {}
+        res["func"] = function
+        res["header"] = self.chunk_header(desc)
+        res["decl"] = self.chunk_declaration(desc)
+        res["inconv"] = self.chunk_inconv(desc)
+        res["call"] = self.chunk_call(desc)
+        res["outconv"] = self.chunk_outconv(desc)
+
+        # Replace into the template
+        text = (
+            """
+/*-------------------------------------------/
+/ %(func)-42s /
+/-------------------------------------------*/
+%(header)s {
+                                        /* Declarations */
+%(decl)s
+                                        /* Convert input */
+%(inconv)s
+                                        /* Call igraph */
+%(call)s
+                                        /* Convert output */
+%(outconv)s
+
+  UNPROTECT(1);
+  return(r_result);
+}\n"""
+            % res
+        )
+
+        out.write(text)
+
+    def chunk_header(self, desc: FunctionDescriptor) -> str:
+        """The header. All functions return with a 'SEXP', so this is
+        easy. We just take the 'IN' and 'INOUT' arguments, all will
+        have type SEXP, and concatenate them by commas. The function name
+        is created by prefixing the original name with 'R_'.
+        """
+
+        def do_par(spec: ParamSpec) -> str:
+            t = self.get_type_descriptor(spec.type)
+            if "HEADER" in t:
+                if t["HEADER"]:
+                    return t["HEADER"].replace("%I%", spec.name)
+                else:
+                    return ""
+            else:
+                return spec.name
+
+        inout = [do_par(spec) for spec in desc.iter_input_parameters()]
+        inout = ["SEXP " + n for n in inout if n != ""]
+        return "SEXP R_" + desc.name + "(" + (", ".join(inout) or "void") + ")"
+
+    def chunk_declaration(self, desc: FunctionDescriptor) -> str:
+        """There are a couple of things to declare. First a C type is
+        needed for every argument, these will be supplied in the C
+        igraph call. Then, all 'OUT' arguments need a SEXP variable as
+        well, the result will be stored here. The return type
+        of the C function also needs to be declared, that comes
+        next. The result and names SEXP variables will contain the
+        final result, these are last. ('names' is not always used, but
+        it is easier to always declare it.)
+        """
+
+        def do_par(spec: ParamSpec) -> str:
+            type_desc = self.get_type_descriptor(spec.type)
+            try:
+                return type_desc.declare_c_variable(f"c_{spec.name}", mode=spec.mode)
+            except NoSuchTypeError:
+                return f"/* {spec.name} has no corresponding C type */"
+
+        inout = [do_par(spec) for spec in desc.iter_parameters()]
+        out = [
+            f"SEXP {spec.name};"
+            for spec in desc.iter_parameters()
+            if spec.mode is ParamMode.OUT
+        ]
+
+        retpars = [spec.name for spec in desc.iter_output_parameters()]
+
+        return_type_desc = self.get_type_descriptor(desc.return_type)
+        retdecl = return_type_desc.declare_c_variable("c_result") if not retpars else ""
+
+        if len(retpars) <= 1:
+            res = "\n".join(inout + out + [retdecl] + ["SEXP r_result;"])
+        else:
+            res = "\n".join(inout + out + [retdecl] + ["SEXP r_result, r_names;"])
+        return indent(res)
+
+    def chunk_inconv(self, desc: FunctionDescriptor) -> str:
+        """Input conversions. Not only for types with mode 'IN' and
+        'INOUT', eg. for 'OUT' vector types we need to allocate the
+        required memory here, do all the initializations, etc. Types
+        without INCONV fields are ignored. The usual %C%, %I% is
+        performed at the end.
+        """
+
+        def do_par(param: ParamSpec) -> str:
+            cname = "c_" + param.name
+            t = self.get_type_descriptor(param.type)
+
+            # Get the template from the type specification
+            inconv = t.get_input_conversion_template_for(param.mode)
+            c_type = t.get_c_type(mode=param.mode)
+
+            if not inconv and param.is_input and (t.is_enum or t.is_bitfield):
+                # If the parameter is an input argument and its type is an
+                # enum, we can provide a default conversion: we just cast its
+                # numeric value to the right type
+                if c_type is not None:
+                    inconv = f"%C% = ({c_type}) Rf_asInteger(%I%);"
+
+            if param.is_optional and param.is_input and inconv:
+                inconv = optional_wrapper_c(inconv, c_type)
+
+            # Replace the tokens in the type specification
+            for i, dep in enumerate(param.dependencies):
+                inconv = inconv.replace("%C" + str(i + 1) + "%", "c_" + dep)
+
+            return indent(inconv).replace("%C%", cname).replace("%I%", param.name)
+
+        inconv = [do_par(param) for param in desc.iter_parameters()]
+        inconv = [i for i in inconv if i != ""]
+
+        return "\n".join(inconv)
+
+    def chunk_call(self, desc: FunctionDescriptor) -> str:
+        """Every single argument is included, independently of their
+        mode. If a type has a 'CALL' field then that is used after the
+        usual %C% and %I% substitutions, otherwise the standard 'c_'
+        prefixed C argument name is used.
+        """
+
+        calls = []
+        for param in desc.iter_parameters():
+            t = self.get_type_descriptor(param.type)
+            type = t.get("CALL", f"c_{param.name}")
+
+            if isinstance(type, dict):
+                call = type.get(param.mode_str, "")
+            else:
+                call = type
+
+            if call:
+                if (
+                    param.is_optional
+                    and param.is_input
+                    and not param.is_output
+                    and call != "0"
+                ):
+                    call = f"(Rf_isNull(%I%) ? 0 : {call})"
+                call = call.replace("%C%", f"c_{param.name}").replace("%I%", param.name)
+                calls.append(call)
+
+        calls = ", ".join(calls)
+        res = ""
+        # No return type means - return type is igraph_error_t
+        if not desc.return_type:
+            res = f"  IGRAPH_R_CHECK({desc.name}({calls}));\n"
+        else:
+            return_type = self.get_type_descriptor(desc.return_type)
+            if return_type.name == "ERROR":
+                res = f"  IGRAPH_R_CHECK({desc.name}({calls}));\n"
+            elif return_type.name == "VOID":
+                res = f"  {desc.name}({calls});\n"
+            else:
+                res = f"  c_result={desc.name}({calls});\n"
+
+        return res
+
+    def chunk_outconv(self, spec: FunctionDescriptor) -> str:
+        """The output conversions, this is quite difficult. A function
+        may report its results in two ways: by returning it directly
+        or by setting a variable to which a pointer was passed. igraph
+        usually uses the latter and returns error codes, except for
+        some simple functions like 'igraph_vcount()' which cannot
+        fail.
+
+        First we add the output conversion for all types. This is
+        easy. Note that even 'IN' arguments may have output
+        conversion, eg. this is the place to free memory allocated to
+        them in the 'INCONV' part.
+
+        Then we check how many 'OUT' or 'INOUT' arguments we
+        have. There are three cases. If there is a single such
+        argument then that is already converted and we need to return
+        that. If there is no such argument then the output of the
+        function was returned, so we perform the output conversion for
+        the returned type and this will be the result. If there are
+        more than one 'OUT' and 'INOUT' arguments then they are
+        collected in a named list. The names come from the argument
+        names.
+        """
+
+        def do_par(param: ParamSpec) -> str:
+            cname = f"c_{param.name}"
+            t = self.get_type_descriptor(param.type)
+            outconv = t.get_output_conversion_template_for(param.mode)
+
+            outconv = indent(outconv)
+            for i, dep in enumerate(param.dependencies):
+                outconv = outconv.replace("%C" + str(i + 1) + "%", "c_" + dep)
+
+            return outconv.replace("%C%", cname).replace("%I%", param.name)
+
+        outconv = [do_par(param) for param in spec.iter_parameters()]
+        outconv = [o for o in outconv if o != ""]
+
+        # Consider only those parameters that have a corresponding declaration
+        # in C.
+        retpars = []
+        for param in spec.iter_output_parameters():
+            type_desc = self.get_type_descriptor(param.type)
+            if type_desc.get_c_type(param.mode) is not None:
+                retpars.append(param)
+
+        if not retpars:
+            # return the return value of the function
+            rt = self.get_type_descriptor(spec.return_type)
+            retconv = indent(rt.get_output_conversion_template_for(ParamMode.OUT))
+            retconv = retconv.replace("%C%", "c_result").replace("%I%", "r_result")
+            ret = "\n".join(outconv) + "\n" + retconv
+        elif len(retpars) == 1:
+            # return the single output value
+            retconv = "  r_result = " + retpars[0].name + ";"
+            ret = "\n".join(outconv) + "\n" + retconv
+        else:
+            # create a list of output values
+            sets = [
+                f"  SET_VECTOR_ELT(r_result, {index}, {param.name});"
+                for index, param in enumerate(retpars)
+            ]
+            names = [
+                f'  SET_STRING_ELT(r_names, {index}, Rf_mkChar("{param.name_in_higher_level_interface}"));'
+                for index, param in enumerate(retpars)
+            ]
+            ret = "\n".join(
+                [
+                    f"  PROTECT(r_result=NEW_LIST({len(retpars)}));",
+                    f"  PROTECT(r_names=NEW_CHARACTER({len(retpars)}));",
+                ]
+                + outconv
+                + sets
+                + names
+                + ["  SET_NAMES(r_result, r_names);", f"  UNPROTECT({len(sets) + 1});"]
+            )
+
+        return ret
+
+
+class RInitCodeGenerator(BlockBasedCodeGenerator):
+    def _count_arguments(self, name: str) -> Tuple[int, int]:
+        desc = self.get_function_descriptor(name)
+        in_args, out_args = 0, 0
+        for param in desc.iter_parameters():
+            try:
+                type_spec = self.get_type_descriptor(param.type)
+            except NoSuchTypeError:
+                # param should probably be included in the function header
+                type_spec = None
+            if (
+                type_spec is None
+                or "HEADER" not in type_spec
+                or type_spec.get("HEADER") is not None
+            ):
+                if param.is_input:
+                    in_args += 1
+                if param.is_output:
+                    out_args += 1
+        return in_args, out_args
+
+    def generate_declarations_block(self, out: IO[str]) -> None:
+        for name in self.iter_functions():
+            self.generate_declaration(name, out)
+
+    def generate_declaration(self, name: str, out: IO[str]) -> None:
+        num_input_args, num_output_args = self._count_arguments(name)
+
+        # One output argument is used for the return value. The default generated
+        # R wrapper only uses the first output argument.
+        num_r_args = num_input_args
+
+        args = ", ".join(["SEXP"] * num_r_args) or "void"
+        out.write(f"extern SEXP R_{name}({args});\n")
+
+    def generate_function(self, name: str, out: IO[str]) -> None:
+        num_input_args, num_output_args = self._count_arguments(name)
+        num_r_args = "{:>2}".format(num_input_args)
+        padding = " " * (50 - len(name))
+        out.write(
+            f'    {{"R_{name}",{padding}(DL_FUNC) &R_{name},{padding}{num_r_args}}},\n'
+        )
+
+    def iter_functions(self, include_ignored: bool = False) -> Iterable[str]:
+        return sorted(super().iter_functions(include_ignored=include_ignored))
diff --git a/tools/py-stimulus/src/stimulus/generators/registry.py b/tools/py-stimulus/src/stimulus/generators/registry.py
new file mode 100644
index 00000000000..b3c770fc5c6
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/registry.py
@@ -0,0 +1,76 @@
+"""Registry object that maps language identifiers to the corresponding code
+generators.
+"""
+
+from typing import Callable, Dict
+
+from .base import CodeGenerator
+
+__all__ = ("get_code_generator_factory_for_language", "is_valid_language")
+
+
+#: Dictionary mapping language codes to code generators
+_registry: Dict[str, Callable[[], CodeGenerator]] = {}
+
+#: Flag storing whether the registry has already been initialized with the
+#: code generators
+_registry_initialized: bool = False
+
+
+def get_code_generator_factory_for_language(
+    lang: str,
+) -> Callable[[], CodeGenerator]:
+    """Returns the class or factory function that is responsible for generating
+    code in the given language.
+    """
+    global _registry_initialized, _registry
+
+    if not _registry_initialized:
+        _register_code_generators()
+        _registry_initialized = True
+
+    return _registry[lang]
+
+
+def is_valid_language(lang: str) -> bool:
+    """Returns whether there is a class or factory function that is responsible
+    for generating code in the given language.
+    """
+    try:
+        get_code_generator_factory_for_language(lang)
+        return True
+    except KeyError:
+        return False
+
+
+def _register_code_generators() -> None:
+    """Register all code generators in the project into the registry."""
+    from .debug import FunctionSpecificationValidator, ListTypesCodeGenerator
+    from .java import JavaCCodeGenerator, JavaJavaCodeGenerator
+    from .python import PythonCTypesCodeGenerator, PythonCTypesTypedWrapperCodeGenerator
+    from .r import (
+        RCCodeGenerator,
+        RInitCodeGenerator,
+        RRCodeGenerator,
+    )
+    from .shell import ShellCodeGenerator
+
+    updates = {
+        "ci:validate": FunctionSpecificationValidator,
+        "debug:list-types": ListTypesCodeGenerator,
+        "java:c": JavaCCodeGenerator,
+        "java:java": JavaJavaCodeGenerator,
+        "python:ctypes": PythonCTypesCodeGenerator,
+        "python:ctypes-typed-wrapper": PythonCTypesTypedWrapperCodeGenerator,
+        "r:c": RCCodeGenerator,
+        "r:init": RInitCodeGenerator,
+        "r:r": RRCodeGenerator,
+        "shell": ShellCodeGenerator,
+        # legacy names
+        "RC": RCCodeGenerator,
+        "RInit": RInitCodeGenerator,
+        "RR": RRCodeGenerator,
+        "Shell": ShellCodeGenerator,
+    }
+
+    _registry.update(updates)
diff --git a/tools/py-stimulus/src/stimulus/generators/shell.py b/tools/py-stimulus/src/stimulus/generators/shell.py
new file mode 100644
index 00000000000..1373f34900f
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/shell.py
@@ -0,0 +1,295 @@
+"""Shell interface generator, allowing one to invoke igraph functions directly
+from the command line.
+"""
+
+from collections import OrderedDict
+from typing import Any, Dict, IO
+
+from stimulus.model import ParamMode, ParamSpec
+
+from .base import SingleBlockCodeGenerator
+from .utils import create_indentation_function
+
+__all__ = ("ShellCodeGenerator",)
+
+################################################################################
+# Shell interface, igraph functions directly from the command line
+# TODO: - read/write default input/output from/to stdin/stdout
+#       - short options
+#       - prefixed output (?)
+#       - default values depending on other parameters
+#       - other input/output graph formats, to be controlled by
+#         environment variables (?): IGRAPH_INGRAPH, IGRAPH_OUTGRAPH
+################################################################################
+
+
+indent = create_indentation_function("  ")
+
+FUNCTION_TEMPLATE = """\
+/*-------------------------------------------/
+/ %(func)-42s /
+/-------------------------------------------*/
+void shell_%(func)s_usage(char **argv) {
+%(usage)s
+  exit(1);
+}
+
+int shell_%(func)s(int argc, char **argv) {
+
+%(decl)s
+
+  int shell_seen[%(nargs)s];
+  int shell_index=-1;
+  struct option shell_options[]= { %(args)s
+                                   { "help", no_argument, 0, %(nargs)s },
+                                   { 0, 0, 0, 0 }
+                                 };
+
+  /* 0 - not seen, 1 - seen as argument, 2 - seen as default */
+  memset(shell_seen, 0, %(nargs)s*sizeof(int));
+%(default)s
+
+  /* Parse arguments and read input */
+  while (getopt_long(argc, argv, "", shell_options, &shell_index) != -1) {
+
+    if (shell_index==-1) {
+      exit(1);
+    }
+
+    if (shell_seen[shell_index]==1) {
+      fprintf(stderr, "Error, `--%%s' argument given twice.\\n",
+              shell_options[shell_index].name);
+      exit(1);
+    }
+    shell_seen[shell_index]=1;
+%(inconv)s
+    shell_index=-1;
+  }
+
+  /* Check that we have all arguments */
+  for (shell_index=0; shell_index<%(nargs)s; shell_index++) {
+    if (!shell_seen[shell_index]) {
+      fprintf(stderr, "Error, argument missing: `--%%s'.\\n",
+              shell_options[shell_index].name);
+      exit(1);
+    }
+  }
+
+  /* Do the operation */
+%(call)s
+
+  /* Write the result */
+%(outconv)s
+
+  return 0;
+}
+"""
+
+
+class ShellCodeGenerator(SingleBlockCodeGenerator):
+    def generate_functions_block(self, out: IO[str]) -> None:
+        out.write("\n/* Function prototypes first */\n\n")
+
+        for name in self.iter_functions():
+            self.generate_prototype(name, out)
+
+        out.write("\n/* The main function */\n\n")
+        out.write("int main(int argc, char **argv) {\n\n")
+        out.write("  const char *base=basename(argv[0]);\n\n  ")
+
+        for name in self.iter_functions():
+            out.write(
+                f'if (!strcasecmp(base, "{name}")) {{\n'
+                f"    return shell_{name}(argc, argv);\n"
+                f"  }} else "
+            )
+
+        out.write('{\n    printf("Unknown function, exiting\\n");\n')
+        out.write("  }\n\n  shell_igraph_usage(argc, argv);\n\n  return 0;\n}\n")
+
+        out.write("\n/* The functions themselves at last */\n")
+
+        for name in self.iter_functions():
+            self.generate_function(name, out)
+
+    def generate_prototype(self, name: str, out: IO[str]):
+        """Generates the prototype of the C function that will handle the
+        function with the given name.
+        """
+        out.write(f"int shell_{name}(int argc, char **argv);\n")
+
+    def generate_function(self, name: str, out: IO[str]) -> None:
+        # Check types
+        self.check_types_of_function(name, errors="warn")
+
+        # Enumerate parameters
+        desc = self.get_function_descriptor(name)
+        args = OrderedDict()
+        for param in desc.iter_parameters():
+            tname = param.type
+            t = self.get_type_descriptor(tname)
+            mode = param.mode
+            if "INCONV" in t or "OUTCONV" in t:
+                p = param.name
+                args[p] = param.as_dict()
+                args[p]["shell_no"] = len(args) - 1
+                if mode is ParamMode.INOUT:
+                    args[p]["mode"] = "IN"
+                    args[p + "-out"] = param.as_dict()
+                    args[p + "-out"]["mode"] = "OUT"
+                    args[p + "-out"]["shell_no"] = len(args) - 1
+                    if "INCONV" not in t or "IN" not in t["INCONV"]:
+                        self.log.warning(f"No INCONV for type {tname!r}, mode IN")
+                    if "OUTCONV" not in t or "OUT" not in t["OUTCONV"]:
+                        self.log.warning(f"No OUTCONV for type {tname!r}, mode OUT")
+            if mode is ParamMode.IN and ("INCONV" not in t or mode not in t["INCONV"]):
+                self.log.warning(f"No INCONV for type {tname!r}, mode {mode}")
+            if mode is ParamMode.OUT and (
+                "OUTCONV" not in t or mode not in t["OUTCONV"]
+            ):
+                self.log.warning(f"No OUTCONV for type {tname!r}, mode {mode}")
+
+        res: Dict[str, Any] = {"nargs": len(args)}
+        params = desc.parameters
+        res["func"] = name
+        res["args"] = self.chunk_args(name, args)
+        res["decl"] = self.chunk_decl(name, params)
+        res["inconv"] = self.chunk_inconv(name, params, args)
+        res["call"] = self.chunk_call(name, params)
+        res["outconv"] = self.chunk_outconv(name, params)
+        res["default"] = self.chunk_default(name, params, args)
+        res["usage"] = self.chunk_usage(name, args)
+        out.write(FUNCTION_TEMPLATE % res)
+
+    def chunk_args(self, func_name: str, params: Dict[str, Dict[str, str]]) -> str:
+        res = [
+            [f'"{name}"', "required_argument", "0", str(p["shell_no"])]
+            for name, p in params.items()
+        ]
+        res = ["{ " + ", ".join(e) + " }," for e in res]
+        return "\n                                   ".join(res)
+
+    def chunk_decl(self, name: str, params: Dict[str, ParamSpec]) -> str:
+        spec = self.get_function_descriptor(name)
+
+        def do_par(pname):
+            param = params[name]
+            type_desc = self.get_type_descriptor(params[pname].type)
+            decl = type_desc.declare_c_variable(pname, mode=ParamMode.IN)
+
+            default = param.get_default_value(type_desc) or ""
+
+            if decl:
+                if default:
+                    return f"{decl}={default};"
+                else:
+                    return f"{decl};"
+            else:
+                return ""
+
+        decl = [do_par(n) for n in params]
+        inout = [
+            "char* shell_arg_" + n + "=0;" for n, p in params.items() if p.is_output
+        ]
+
+        return_type_desc = self.get_type_descriptor(spec.return_type)
+        retdecl = return_type_desc.declare_c_variable("shell_result")
+
+        if spec.return_type != "ERROR":
+            retchar = 'char *shell_arg_shell_result="-";'
+        else:
+            retchar = ""
+        return indent("\n".join(decl + inout + [retdecl, retchar]))
+
+    def chunk_default(
+        self, name: str, params: Dict[str, ParamSpec], args: Dict[str, Dict[str, str]]
+    ) -> str:
+        def do_par(pname: str) -> str:
+            if params[pname].has_default_value is not None:
+                shell_no = args[pname]["shell_no"]
+                res = f"  shell_seen[{shell_no}] = 2;"
+            else:
+                res = ""
+            return res
+
+        res = [do_par(n) for n in params]
+        res = [n for n in res if n != ""]
+        return "\n".join(res)
+
+    def chunk_inconv(
+        self,
+        func_name: str,
+        params: Dict[str, ParamSpec],
+        args: Dict[str, Dict[str, str]],
+    ) -> str:
+        def do_par(pname):
+            t = self.get_type_descriptor(params[pname].type)
+            mode = params[pname].mode_str
+            if "INCONV" in t and mode in t["INCONV"]:
+                inconv = "" + t["INCONV"][mode]
+            else:
+                inconv = ""
+            if pname.endswith("-out"):
+                pname = pname[0:-4]
+            return inconv.replace("%C%", pname)
+
+        inconv = [
+            "    case "
+            + str(arg["shell_no"])
+            + ": /* "
+            + name
+            + " */\n      "
+            + do_par(name)
+            for name, arg in args.items()
+        ]
+        inconv = [n + "\n      break;" for n in inconv]
+        inconv = ["".join(n) for n in inconv]
+        text = (
+            "\n    switch (shell_index) {\n"
+            + "\n".join(inconv)
+            + "\n    case "
+            + str(len(inconv))
+            + ":\n      shell_"
+            + func_name
+            + "_usage(argv);\n      break;"
+            + "\n    default:\n      break;\n    }\n"
+        )
+        return text
+
+    def chunk_call(self, func_name: str, params: Dict[str, ParamSpec]) -> str:
+        parts = []
+        for name, spec in params.items():
+            type = self.get_type_descriptor(spec.type)
+            call = type.get("CALL", name).replace("%C%", name)
+            parts.append(call)
+
+        call = ", ".join(parts)
+        return f"  shell_result = {func_name}({call});"
+
+    def chunk_outconv(self, name: str, params: Dict[str, ParamSpec]) -> str:
+        spec = self.get_function_descriptor(name)
+
+        def do_par(pname):
+            t = self.get_type_descriptor(params[pname].type)
+            mode = params[pname].mode_str
+            if "OUTCONV" in t and mode in t["OUTCONV"]:
+                outconv = indent(t["OUTCONV"][mode])
+            else:
+                outconv = ""
+            if pname.endswith("-out"):
+                pname = pname[0:-4]
+            return outconv.replace("%C%", pname)
+
+        outconv = [do_par(n) for n in params]
+        rt = self.get_type_descriptor(spec.return_type)
+        if "OUTCONV" in rt and "OUT" in rt["OUTCONV"]:
+            rtout = indent(rt["OUTCONV"]["OUT"])
+        else:
+            rtout = ""
+        outconv.append(rtout.replace("%C%", "shell_result"))
+        outconv = [o for o in outconv if o != ""]
+        return "\n".join(outconv)
+
+    def chunk_usage(self, func_name: str, params: Dict[str, ParamSpec]) -> str:
+        res = " ".join(f"--{name}=<{name}>" for name in params)
+        return f'  printf("%s {res}\\n", basename(argv[0]));'
diff --git a/tools/py-stimulus/src/stimulus/generators/utils.py b/tools/py-stimulus/src/stimulus/generators/utils.py
new file mode 100644
index 00000000000..e6001634641
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/generators/utils.py
@@ -0,0 +1,34 @@
+"""Helper utility functions for code generators."""
+
+from functools import lru_cache
+from textwrap import indent
+from typing import Callable
+
+
+__all__ = ("create_indentation_function", "remove_prefix")
+
+
+@lru_cache(maxsize=32)
+def create_indentation_function(indentation: str) -> Callable[[str], str]:
+    """Creates a function that indents the given input string with the
+    given indentation, except when the input string is empty.
+    """
+
+    def func(input: str) -> str:
+        return indent(input, indentation) if input else input
+
+    return func
+
+
+def remove_prefix(input: str, prefix: str) -> str:
+    """Removes th given prefix from the input string if it is present.
+
+    Parameters:
+        input: the input string
+        prefix: the prefix to remove
+
+    Returns:
+        the input string without the given prefix if it started with the prefix,
+        or the input string intact otherwise
+    """
+    return input[len(prefix) :] if input.startswith(prefix) else input
diff --git a/tools/py-stimulus/src/stimulus/model/__init__.py b/tools/py-stimulus/src/stimulus/model/__init__.py
new file mode 100644
index 00000000000..0a9638c8777
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/model/__init__.py
@@ -0,0 +1,12 @@
+from .docstrings import DocstringProvider
+from .functions import FunctionDescriptor
+from .parameters import ParamMode, ParamSpec
+from .types import TypeDescriptor
+
+__all__ = (
+    "DocstringProvider",
+    "FunctionDescriptor",
+    "ParamMode",
+    "ParamSpec",
+    "TypeDescriptor",
+)
diff --git a/tools/py-stimulus/src/stimulus/model/base.py b/tools/py-stimulus/src/stimulus/model/base.py
new file mode 100644
index 00000000000..d1ecd5895b0
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/model/base.py
@@ -0,0 +1,40 @@
+"""Base classes for model objects."""
+
+from typing import Any, Dict, Iterable, Optional
+
+__all__ = ("DescriptorMixin",)
+
+
+class DescriptorMixin:
+    """Mixin class for function and type descriptors."""
+
+    _obj: Dict[str, Any]
+
+    def _parse_as_boolean(self, key: str) -> Optional[bool]:
+        value = self._obj.pop(key, None)
+        if value is None:
+            return None
+        elif isinstance(value, (int, float)):
+            return bool(value)
+        elif isinstance(value, str):
+            return value.lower() in ("true", "yes", "y")
+        else:
+            return bool(value)
+
+    def _parse_as_comma_separated_list(self, key: str) -> Iterable[str]:
+        value = self._obj.pop(key, None)
+        if value is None:
+            return ()
+        if isinstance(value, str):
+            return (
+                stripped_part
+                for part in value.split(",")
+                if (stripped_part := part.strip())
+            )
+        elif hasattr(value, "__iter__"):
+            return (part.strip() for part in value)  # type: ignore
+        else:
+            if key:
+                raise RuntimeError(f"{key!r} key must map to a string or a list")
+            else:
+                raise RuntimeError("key must map to a string or a list")
diff --git a/tools/py-stimulus/src/stimulus/model/docstrings.py b/tools/py-stimulus/src/stimulus/model/docstrings.py
new file mode 100644
index 00000000000..b6050243f8c
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/model/docstrings.py
@@ -0,0 +1,10 @@
+from typing import Callable, Optional
+
+__all__ = ("DocstringProvider",)
+
+
+DocstringProvider = Callable[[str], Optional[str]]
+"""Interface specification for functions that can be called with a function name
+and return the docstring corresponding to the given function or ``None`` if
+no docstring is available.
+"""
diff --git a/tools/py-stimulus/src/stimulus/model/functions.py b/tools/py-stimulus/src/stimulus/model/functions.py
new file mode 100644
index 00000000000..ff72bbcfc73
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/model/functions.py
@@ -0,0 +1,398 @@
+from dataclasses import dataclass, field
+from deepmerge import always_merger
+from typing import (
+    Any,
+    Dict,
+    Iterable,
+    List,
+    Mapping,
+    Optional,
+    OrderedDict,
+    Set,
+    Tuple,
+)
+
+from stimulus.utils import camelcase
+
+from .base import DescriptorMixin
+from .parameters import ParamSpec
+
+__all__ = ("FunctionDescriptor",)
+
+
+@dataclass
+class FunctionDescriptor(Mapping[str, Any], DescriptorMixin):
+    """Dataclass that describes a single function for which we can generate
+    related code in a code generator.
+    """
+
+    name: str
+    """The name of the function that the descriptor describes."""
+
+    _obj: Dict[str, Any] = field(default_factory=dict)
+    """The specification from which the function descriptor was created."""
+
+    _parameters: Optional[OrderedDict[str, ParamSpec]] = None
+    """Ordered mapping from parameter names to the corresponding specifications,
+    or ``None`` if the parameters have not been parsed yet.
+    """
+
+    _param_order: List[str] = field(default_factory=list)
+    """Order of the parameters. Empty if the parameters have not been parsed yet."""
+
+    flags: Set[str] = field(default_factory=set)
+    """Flags corresponding to the function specification."""
+
+    ignored_by: Set[str] = field(default_factory=set)
+    """Set of generators that should ignore this function."""
+
+    return_type: str = "ERROR"
+    """The name of the return type of this function."""
+
+    def __getitem__(self, key: str) -> Any:
+        return self._obj[key]
+
+    def __iter__(self):
+        return iter(self._obj)
+
+    def __len__(self):
+        return len(self._obj)
+
+    @property
+    def is_deprecated(self) -> bool:
+        """Returns whether the function is deprecated."""
+        return self.has_flag("deprecated")
+
+    @property
+    def is_internal(self) -> bool:
+        """Returns whether the function is internal (i.e. should not be exported
+        in the public namespace of the generated higher-level interface.
+        """
+        return self.has_flag("internal")
+
+    @property
+    def parameters(self) -> OrderedDict[str, ParamSpec]:
+        if self._parameters is None:
+            self._parameters = self._parse_parameter_specifications()
+            self._update_parameter_order()
+        return self._parameters
+
+    def get_name_in_generated_code(self, language: str) -> str:
+        """Returns the proposed name of the function in code generated for the
+        given language.
+        """
+        lang_key = f"NAME-{language}"
+        result = self._obj.get(lang_key) or self._obj.get("NAME")
+        if result is None:
+            if language == "R":
+                return self.name[7:]
+            elif language == "Java":
+                return camelcase(self.name[7:])
+            else:
+                return self.name
+        else:
+            return result
+
+    def has_flag(self, flag: str) -> bool:
+        """Checks whether the function descriptor has the given flag, in a
+        case-insensitive manner.
+        """
+        return flag.lower() in self.flags
+
+    @property
+    def has_output_parameter(self) -> bool:
+        """Returns whether the function has at least one parameter that is
+        designated as an output or in-out parameter.
+        """
+        return any(param.is_output for param in self.parameters.values())
+
+    @property
+    def has_primary_output_parameter(self) -> bool:
+        """Returns whether the function has at least one parameter that is
+        explicitly marked as being a primary output or in-out parameter.
+        """
+        return any(param.is_primary for param in self.iter_output_parameters())
+
+    @property
+    def has_non_primary_output_parameter(self) -> bool:
+        """Returns whether the function has at least one parameter that is
+        explicitly marked as being a primary output or in-out parameter.
+        """
+        return any(not param.is_primary for param in self.iter_output_parameters())
+
+    def iter_input_parameters(self, *, reorder: bool = False) -> Iterable[ParamSpec]:
+        """Iterates over the input and in-out parameters of this function.
+
+        Parameters:
+            reorder: when `False`, iterates over the parameters of this function
+                in the order they were _defined_, which should match the ordering
+                in C. When `True`, iterates over the parameters in the preferred
+                order as specified by `PARAM_ORDER`; this matches the order they
+                should appear in the higher level interface. The two are typically
+                identical but sometimes they are not.
+        """
+        if reorder:
+            for name in self._param_order:
+                param = self.parameters[name]
+                if param.is_input:
+                    yield param
+        else:
+            yield from (param for param in self.parameters.values() if param.is_input)
+
+    def iter_parameters(self, *, reorder: bool = False) -> Iterable[ParamSpec]:
+        """Iterates over the parameters of this function.
+
+        Parameters:
+            reorder: when `False`, iterates over the parameters of this function
+                in the order they were _defined_, which should match the ordering
+                in C. When `True`, iterates over the parameters in the preferred
+                order as specified by `PARAM_ORDER`; this matches the order they
+                should appear in the higher level interface. The two are typically
+                identical but sometimes they are not.
+        """
+        if reorder:
+            return (self.parameters[name] for name in self._param_order)
+        else:
+            return self.parameters.values()
+
+    def iter_output_parameters(self) -> Iterable[ParamSpec]:
+        """Iterates over the output and in-out parameters of this function in the
+        order they were _defined_.
+        """
+        return (param for param in self.parameters.values() if param.is_output)
+
+    def iter_primary_output_parameters(self) -> Iterable[ParamSpec]:
+        """Iterates over the primary output and in-out parameters of this function in the
+        order they were _defined_.
+        """
+        return (param for param in self.iter_output_parameters() if param.is_primary)
+
+    def iter_reordered_parameters(self) -> Iterable[ParamSpec]:
+        """Iterates over the parameters of this function in the order they
+        should appear in the argument list of the function for the higher
+        level interface. This is different from `iter_parameters()` if the
+        `PARAM_ORDER` key is present in the input YAML file.
+        """
+        return (self.parameters[name] for name in self._param_order)
+
+    def update_from(self, obj: Dict[str, str]) -> None:
+        """Updates the function descriptor from an object typically parsed from
+        a specification file.
+
+        The rules are as follows:
+
+          - The ``PARAMS`` key from `obj` overwrites the previous parameter
+            description.
+
+          - The ``DEPS`` key from `obj` overwrites the previous dependencies.
+
+          - The ``RETURN`` key from `obj` overwrites the previous return type.
+
+          - The ``PARAM_ORDER`` key from `obj` overwrites the previous parameter
+            order.
+
+          - The values from the ``IGNORE`` list are added to the existing list
+            of generators that will ignore this function. ``IGNORE`` may also
+            be a string, in which case it will be split along commas.
+
+          - The values from the ``FLAGS`` list are merged with the existing
+            flags. ``FLAGS`` may also be a string, in which case it will be
+            split along commas.
+
+          - The mapping in the ``PARAM_NAMES`` key is merged with the
+            existing parameter name mapping.
+
+          - The mapping in the ``DEFAULT`` key is merged with the
+            existing parameter-to-default-value mapping.
+
+          - Any other key in `obj` is merged with the existing key-value store.
+        """
+        if "PARAMS" in obj:
+            self._obj["PARAMS"] = ""
+            self._parameters = None
+
+        if "DEPS" in obj:
+            self._obj["DEPS"] = ""
+            self._parameters = None
+
+        if "PARAM_NAMES" in obj:
+            self._parameters = None
+
+        if "DEFAULT" in obj:
+            self._parameters = None
+
+        if "PARAM_ORDER" in obj:
+            self._param_order.clear()
+            self._parameters = None
+
+        always_merger.merge(self._obj, obj)
+
+        it = self._parse_as_comma_separated_list("IGNORE")
+        self.ignored_by |= set(it)
+
+        it = self._parse_as_comma_separated_list("FLAGS")
+        self.flags |= {flag.lower() for flag in it}
+
+        is_internal = self._parse_as_boolean("INTERNAL")
+        if is_internal is not None:
+            if is_internal is True:
+                self.flags.add("internal")
+            else:
+                self.flags.discard("internal")
+
+        return_type: str = self._obj.pop("RETURN", "")
+        if return_type:
+            self.return_type = str(return_type)
+
+    def _parse_dependencies(self) -> Dict[str, Tuple[str, ...]]:
+        dep_spec_str = self._obj.get("DEPS")
+        deps = dep_spec_str.split(",") if dep_spec_str else []
+
+        deps = [item.strip().split("ON", 1) for item in deps]
+        deps = [[dd.strip() for dd in item] for item in deps]
+        deps = [[item[0]] + item[1].split(" ", 1) for item in deps]
+        deps = [[dd.strip() for dd in item] for item in deps]
+
+        return {str(name): tuple(values) for name, *values in deps}
+
+    def _parse_parameter_specifications(self) -> OrderedDict[str, ParamSpec]:
+        params: List[str]
+
+        param_spec_str = self._obj.get("PARAMS")
+        param_name_mapping = self._obj.get("PARAM_NAMES")
+        default_value_overrides = self._obj.get("DEFAULT")
+
+        # First, get the parameter specifications
+        if not param_spec_str:
+            params = []
+        elif isinstance(param_spec_str, str):
+            params = param_spec_str.split(",")
+        elif hasattr(param_spec_str, "__iter__"):
+            params = list(param_spec_str)
+        else:
+            raise TypeError(
+                f"PARAMS must be a string or a list, got {type(param_spec_str)!r}"
+            )
+        params = [item.strip() for item in params]
+
+        # Figure out which of the parameters are keyword-only. There are three
+        # ways to achieve this, in order of precedence:
+        #
+        # - For each parameter, you can add "KW" in front of the parameter name
+        #   and type to mark it explicitly as a keywork argument. This is not
+        #   compatible with Stimulus <0.21, though.
+        # - You can add '*' in the parameter list before the first keyword-only
+        #   parameter. This is not compatible with Stimulus <0.21 either.
+        # - You can add a key named "FIRST_KW_PARAM" whose value must
+        #   be the name of the first keyword argument. This is compatible with
+        #   Stimulus <0.21 as earlier versions will simply ignore this key.
+
+        try:
+            kwarg_marker_index = params.index("*")
+            del params[kwarg_marker_index : (kwarg_marker_index + 1)]
+        except ValueError:
+            kwarg_marker_index = len(params)
+
+        specs = [ParamSpec.from_string(item) for item in params]
+        for spec in specs[kwarg_marker_index:]:
+            spec.is_keyword_only = True
+
+        first_kwarg_name = self._obj.get("FIRST_KW_PARAM")
+        if first_kwarg_name and not any(spec.is_keyword_only for spec in specs):
+            is_kwarg = False
+            for spec in specs:
+                if spec.name == first_kwarg_name:
+                    is_kwarg = True
+                spec.is_keyword_only = is_kwarg
+
+        # Now that we have the specifications, create an ordered dict
+        result = OrderedDict((spec.name, spec) for spec in specs)
+
+        # Parse dependencies between parameters
+        for name, deps in self._parse_dependencies().items():
+            for dep in deps:
+                param = result.get(name)
+                if param:
+                    param.add_dependency(dep)
+                else:
+                    raise RuntimeError(
+                        f"dependency declared on unknown argument {name!r} of "
+                        f"function {self.name!r}"
+                    )
+
+        # Remap parameter names if needed
+        if param_name_mapping:
+            for name, new_name in param_name_mapping.items():
+                param = result.get(name)
+                if param:
+                    param.name_override = new_name or None
+                else:
+                    raise RuntimeError(
+                        f"parameter name was overridden for unknown "
+                        f"parameter {name!r} of function {self.name!r}"
+                    )
+
+        # Override default values if needed
+        if default_value_overrides:
+            for name, default_value in default_value_overrides.items():
+                param = result.get(name)
+                if param:
+                    param.use_explicit_default_value(default_value)
+                else:
+                    raise RuntimeError(
+                        f"parameter default value was overridden for unknown "
+                        f"parameter {name!r} of function {self.name!r}"
+                    )
+
+        return result
+
+    def _update_parameter_order(self) -> None:
+        assert self._parameters is not None
+
+        param_order_str = self._obj.get("PARAM_ORDER")
+
+        if not param_order_str:
+            param_order = []
+        elif isinstance(param_order_str, str):
+            param_order = param_order_str.split(",")
+        elif hasattr(param_order_str, "__iter__"):
+            param_order = list(param_order_str)
+        else:
+            raise TypeError(
+                f"PARAM_ORDER must be a string or a list, got {type(param_order_str)!r}"
+            )
+
+        self._param_order.clear()
+        rest_index = -1
+        kwarg_index = -1
+
+        not_seen_params = list(self._parameters.keys())
+        valid_params = not_seen_params[:]
+        for name in param_order:
+            name = name.strip()
+            if name in not_seen_params:
+                self._param_order.append(name)
+                not_seen_params.remove(name)
+            elif name == "...":
+                rest_index = len(self._param_order)
+            elif name == "*":
+                kwarg_index = len(self._param_order)
+            elif name not in valid_params:
+                raise RuntimeError(
+                    f"{name!r} in PARAM_ORDER refers to an unknown parameter in "
+                    f"function {self.name!r}"
+                )
+            else:
+                raise RuntimeError(
+                    f"parameter {name!r} appears twice in PARAM_ORDER for "
+                    f"function {self.name!r}"
+                )
+
+        if not_seen_params:
+            if rest_index < 0:
+                rest_index = len(self._param_order)
+            self._param_order[rest_index:rest_index] = not_seen_params
+
+        if kwarg_index >= 0:
+            for index, name in enumerate(self._param_order):
+                self._parameters[name].is_keyword_only = index >= kwarg_index
diff --git a/tools/py-stimulus/src/stimulus/model/parameters.py b/tools/py-stimulus/src/stimulus/model/parameters.py
new file mode 100644
index 00000000000..91d35eb9520
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/model/parameters.py
@@ -0,0 +1,214 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from enum import Enum
+from typing import Dict, List, Optional, Tuple, TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from .types import TypeDescriptor
+
+__all__ = ("ParamMode", "ParamSpec")
+
+
+class ParamMode(Enum):
+    """Enum representing the modes of function parameters."""
+
+    IN = "in"
+    OUT = "out"
+    INOUT = "inout"
+
+    @property
+    def is_input(self) -> bool:
+        return self is self.__class__.IN or self is self.__class__.INOUT
+
+    @property
+    def is_output(self) -> bool:
+        return self is self.__class__.OUT or self is self.__class__.INOUT
+
+
+class DefaultValueType(Enum):
+    """Enum representing the different types of default values for function
+    parameters.
+
+    Default values may be abstract or explicit. Abstract default values are
+    mapped to a language-specific literal using the type descriptor corresponding
+    to the type of the parameter. Explicit default values are used verbatim
+    in the generated code.
+    """
+
+    ABSTRACT = "abstract"
+    EXPLICIT = "explicit"
+
+
+@dataclass
+class ParamSpec:
+    """Specification of a single function parameter."""
+
+    name: str
+    """Name of the parameter in the function signature."""
+
+    type: str
+    """Type of the parameter in the function signature.
+
+    This is the "abstract type" of the parameter, which is then mapped to a real
+    type both in C and in the host language by the type definition files.
+    """
+
+    mode: ParamMode = ParamMode.IN
+    """Mode of the parameter (input, output or both)."""
+
+    default: Optional[Tuple[DefaultValueType, str]] = None
+    """Default value of the parameter and its type."""
+
+    is_optional: bool = False
+    """Whether the parameter is an optional parameter.
+
+    igraph's core is implemented in C, which does not really have optional
+    parameters. However, a typical pattern is that certain values are used to
+    denote that the caller of the function is not providing a value for the
+    parameter (for input parameters) or is not interested in the value of the
+    parameter after calling the function (for output parameters). This
+    property can be used to mark such a parameter.
+    """
+
+    is_primary: bool = False
+    """Whether the parameter is a primary parameter.
+
+    This property has no semantic meaning for strictly input parameters. For
+    in-out and output parameters, one or more parameters may be designated as
+    the primary output(s) of the function. Higher level interfaces may use this
+    to generate a "simplified" and a "complex" wrapper for the function, or
+    may add an additional switch to the generated function that specifies
+    whether the user wants the primary return value(s) only or all of them.
+    """
+
+    is_keyword_only: bool = False
+    """Whether the parameter is keyword-only.
+
+    Code generators for languages that distinguish between positional and
+    keyword arguments may use this flag to determine whether an argument is to
+    be used as a keyword argument only.
+    """
+
+    dependencies: List[str] = field(default_factory=list)
+    """List of other parameters that the code generators will need to generate
+    code for the in- and out-conversions of this parameter.
+    """
+
+    name_override: Optional[str] = None
+    """Name of the parameter in the generated higher-level interface. This can
+    be used in two cases: 1) when the parameter is used as an output and the
+    code generator needs to return multiple output parameters to the caller,
+    2) when the parameter is used as an input and the higher-level interface
+    needs a different name due to compatibility issues or keyword restrictions.
+    `None` means that the name is the same as the "real" name of the parameter.
+    """
+
+    @classmethod
+    def from_string(cls, value: str):
+        """Constructs a ParamSpec object from its string representation in a
+        ``.yaml`` file.
+        """
+        value = value.strip()
+
+        flags = ("PRIMARY", "OPTIONAL", "KW")
+        flags_present = set()
+        while True:
+            for flag in flags:
+                if value.startswith(flag):
+                    flags_present.add(flag)
+                    value = value[len(flag) :].strip()
+                    break
+            else:
+                # No flag was stripped in this iteration, break out of the loop
+                break
+
+        parts = value.split(" ", 1)
+        if parts[0] not in ("OUT", "IN", "INOUT"):
+            parts = ["IN", parts[0]] + parts[1].split(" ", 1)
+        else:
+            parts = [parts[0]] + parts[1].split(" ", 1)
+        if "=" in parts[2]:
+            parts = parts[:2] + parts[2].split("=", 1)
+
+        mode, type, name, *rest = [part.strip() for part in parts]
+
+        return ParamSpec(
+            name=str(name),
+            mode=ParamMode(mode.lower()),
+            type=str(type),
+            default=(DefaultValueType.ABSTRACT, rest[0]) if rest else None,
+            is_primary="PRIMARY" in flags_present,
+            is_optional="OPTIONAL" in flags_present,
+            is_keyword_only="KW" in flags_present,
+        )
+
+    def add_dependency(self, name: str) -> None:
+        """Adds a new dependency to this parameter specification."""
+        self.dependencies.append(name)
+
+    def as_dict(self) -> Dict[str, str]:
+        """Returns a dict representation of the parameter specification."""
+        result = {"name": self.name, "mode": self.mode_str, "type": self.type}
+        if self.default is not None:
+            type, value = self.default
+            if type is DefaultValueType.ABSTRACT:
+                result["default"] = value
+            else:
+                raise RuntimeError(
+                    "serializing explicit default values into a dict is not "
+                    "supported yet"
+                )
+        return result
+
+    def get_default_value(self, type_desc: TypeDescriptor) -> Optional[str]:
+        """Returns the default value of this parameter, replacing any abstract
+        default values from the corresponding type specification if needed.
+        """
+        if self.default is None:
+            return None
+        else:
+            type, value = self.default
+            if type is DefaultValueType.EXPLICIT:
+                return value
+            else:
+                return type_desc.translate_default_value(value)
+
+    def use_explicit_default_value(self, value: str) -> None:
+        """Sets an explicit default value for this parameter, replacing any
+        previous abstract default value.
+        """
+        self.default = (DefaultValueType.EXPLICIT, value)
+
+    @property
+    def has_default_value(self) -> bool:
+        """Returns whether the parameter has an explicit or an abstract
+        default value.
+        """
+        return self.default is not None
+
+    @property
+    def is_deprecated(self) -> bool:
+        """Returns whether the function parameter is marked as deprecated."""
+        return self.type == "DEPRECATED"
+
+    @property
+    def is_input(self) -> bool:
+        """Returns whether the function parameter is an input argument."""
+        return self.mode in (ParamMode.IN, ParamMode.INOUT)
+
+    @property
+    def is_output(self) -> bool:
+        """Returns whether the function parameter is an output argument."""
+        return self.mode in (ParamMode.OUT, ParamMode.INOUT)
+
+    @property
+    def mode_str(self) -> str:
+        return str(self.mode.value).upper()
+
+    @property
+    def name_in_higher_level_interface(self) -> str:
+        """Returns the name of the parameter when it is used in the higher-level
+        interface.
+        """
+        return self.name_override or self.name
diff --git a/tools/py-stimulus/src/stimulus/model/types.py b/tools/py-stimulus/src/stimulus/model/types.py
new file mode 100644
index 00000000000..6d9071f9feb
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/model/types.py
@@ -0,0 +1,267 @@
+from dataclasses import dataclass, field
+from deepmerge import always_merger
+from typing import Any, Dict, Mapping, Optional, Set
+
+from stimulus.errors import NoSuchTypeError
+
+from .base import DescriptorMixin
+from .parameters import ParamMode
+
+__all__ = ("TypeDescriptor",)
+
+
+_MISSING = object()
+
+
+@dataclass
+class TypeDescriptor(Mapping[str, Any], DescriptorMixin):
+    """Dataclass that describes a single type that is used in a code generator."""
+
+    name: str
+    """Name of the type"""
+
+    flags: Set[str] = field(default_factory=set)
+    """The flags associated to the type"""
+
+    _obj: Dict[str, str] = field(default_factory=dict)
+
+    def __getitem__(self, key: str) -> Any:
+        return self._obj[key]
+
+    def __iter__(self):
+        return iter(self._obj)
+
+    def __len__(self):
+        return len(self._obj)
+
+    def declare_c_function_argument(
+        self, name: Optional[str] = None, *, mode: ParamMode = ParamMode.OUT
+    ) -> str:
+        """Returns a string that declares a function argument in C using this
+        type.
+
+        Parameters:
+            name: the name of the C argument to declare. May be left as an
+                empty string or `None` if we only need the type declaration in
+                the function header
+
+        Returns:
+            a C function argument declaration, without indentation or trailing
+            newline, ready to be used in a function header, or an empty string
+            if the argument with this abstract type should not be used in C
+            function headers
+
+        Raises:
+            NoSuchTypeError: if the type specification does not specify
+                explicitly the corresponding C type in the given mode (and does
+                not state explicitly that the abstract type does _not_ have
+                a corresponding C type either)
+        """
+        param_type = self.get_c_type(mode)
+        by_ref = self.is_passed_by_reference
+
+        if param_type is None:
+            return ""  # no argument declaration needed
+
+        if by_ref:
+            # Argument is always passed by reference, but it gains a
+            # "const" modifier if it is used as a purely input argument --
+            # except when it is "void*" because everyone does all sorts of
+            # nasty things with void pointers
+            param_type += "*"
+            if mode.is_input and not mode.is_output and param_type != "void*":
+                param_type = f"const {param_type}"
+        else:
+            # Argument is passed by value by default, but it needs to
+            # become a pointer if it is to be used in output or in-out mode
+            if mode.is_output:
+                param_type += "*"
+
+        return f"{param_type} {name}" if name else param_type
+
+    def declare_c_variable(
+        self,
+        name: str,
+        *,
+        mode: ParamMode = ParamMode.OUT,
+        name_token: str = "%C%",
+        type_token: str = "%T%",
+    ) -> str:
+        """Returns a string that declares a new variable in C using this type.
+
+        Parameters:
+            name: the name of the C variable to declare
+
+        Returns:
+            a C variable declaration, without indentation or trailing newline
+        """
+        mode_str = str(mode.value).upper()
+        c_decl = self._obj.get("CDECL")
+        if isinstance(c_decl, dict):
+            c_decl = c_decl.get(mode_str)
+
+        c_type = self.get_c_type(mode)
+
+        if c_decl is None:
+            c_decl = f"{type_token} {name_token};"
+
+        if c_type is None and type_token in c_decl:
+            c_decl = ""
+
+        return c_decl.replace(type_token, c_type or "").replace(name_token, name)
+
+    def get_c_type(self, mode: ParamMode = ParamMode.OUT) -> Optional[str]:
+        """Returns a string that contains the C type corresponding to this
+        abstract type, or `None` if the abstract type has no corresponding
+        C type in the given mode.
+
+        Returns:
+            a non-empty string or `None` if the abstract type has no corresponding
+            C type in the given mode
+
+        Raises:
+            NoSuchTypeError: if the type specification does not specify
+                explicitly the corresponding C type in the given mode (and does
+                not state explicitly that the abstract type does _not_ have
+                a corresponding C type either)
+        """
+        mode_str = str(mode.value).upper()
+        c_type = self._obj.get("CTYPE", _MISSING)
+        if c_type is _MISSING:
+            raise NoSuchTypeError(
+                f"{self.name} does not specify its corresponding C type"
+            )
+
+        if isinstance(c_type, dict):
+            try:
+                value = c_type[mode_str]
+            except KeyError:
+                raise NoSuchTypeError(
+                    f"{self.name} does not specify its corresponding C type in mode {mode_str}"
+                ) from None
+            if isinstance(value, str) or value is None:
+                return value or None
+            else:
+                raise ValueError(
+                    f"CTYPE declaration must be a string or a mapping, got {type(value)}"
+                )
+        elif isinstance(c_type, str) or c_type is None:
+            return c_type or None
+        else:
+            raise ValueError(
+                f"CTYPE declaration must be a string or a mapping, got {type(c_type)}"
+            )
+
+    def get_input_conversion_template_for(
+        self, mode: ParamMode, *, default: str = ""
+    ) -> str:
+        """Returns a template string that specifies how parameters of this type
+        should be converted when it is used as an input parameter.
+
+        When the type definition contains several conversion code snippets
+        depending on the mode of the parameter and there is no snippet for the
+        `INOUT` mode, it is assumed to be identical to the code snippet for
+        the `IN` mode.
+        """
+        if "INCONV" in self:
+            inconv = self["INCONV"]
+            if isinstance(inconv, str):
+                return inconv if mode.is_input else default
+            elif isinstance(inconv, dict):
+                try:
+                    return inconv[mode.value.upper()] or default
+                except KeyError:
+                    if mode is ParamMode.INOUT:
+                        return self.get_input_conversion_template_for(
+                            ParamMode.IN, default=default
+                        )
+                    else:
+                        return default
+            else:
+                raise TypeError(
+                    f"INCONV should be a string or a dict for type {self.name}"
+                )
+        else:
+            return default
+
+    def get_output_conversion_template_for(
+        self, mode: ParamMode, *, default: str = ""
+    ) -> str:
+        """Returns a template string that specifies how parameters of this type
+        should be converted when it is used as an output parameter.
+
+        When the type definition contains several conversion code snippets
+        depending on the mode of the parameter and there is no snippet for the
+        `INOUT` mode, it is assumed to be identical to the code snippet for
+        the `OUT` mode.
+        """
+        if "OUTCONV" in self:
+            outconv = self["OUTCONV"]
+            if isinstance(outconv, str):
+                return outconv if mode.is_output else default
+            elif isinstance(outconv, dict):
+                try:
+                    return outconv[mode.value.upper()] or default
+                except KeyError:
+                    if mode is ParamMode.INOUT:
+                        return self.get_output_conversion_template_for(
+                            ParamMode.OUT, default=default
+                        )
+                    else:
+                        return default
+            else:
+                raise TypeError(
+                    f"OUTCONV should be a string or a dict for type {self.name}"
+                )
+        else:
+            return default
+
+    def has_flag(self, flag: str) -> bool:
+        """Checks whether the type descriptor has the given flag, in a
+        case-insensitive manner.
+        """
+        return flag.lower() in self.flags
+
+    @property
+    def is_bitfield(self) -> bool:
+        """Returns whether the type is a bitfield type in the C layer."""
+        return self.has_flag("bits")
+
+    @property
+    def is_enum(self) -> bool:
+        """Returns whether the type is an enumeration type in the C layer."""
+        return self.has_flag("enum")
+
+    @property
+    def is_passed_by_reference(self) -> bool:
+        """Returns whether the type is typically passed by reference in function
+        calls in the C layer.
+        """
+        return self.has_flag("by_ref")
+
+    def translate_default_value(self, value: Any) -> str:
+        """Translates the default value of a parameter having this type to
+        a string in the format that should be used in the output file.
+        """
+        mapping = self._obj.get("DEFAULT")
+        if mapping is not None and value in mapping:
+            return mapping[value]
+        else:
+            return str(value)
+
+    def update_from(self, obj: Dict[str, str]) -> None:
+        """Updates the type descriptor from an object typically parsed from
+        a specification file.
+
+        The rules are as follows:
+
+          - The values from the ``FLAGS`` list are merged with the existing
+            flags. ``FLAGS`` may also be a string, in which case it will be
+            split along commas.
+
+          - Any other key in `obj` is merged with the existing key-value store.
+        """
+        always_merger.merge(self._obj, obj)
+
+        it = self._parse_as_comma_separated_list("FLAGS")
+        self.flags |= {flag.lower() for flag in it}
diff --git a/tools/py-stimulus/src/stimulus/providers/__init__.py b/tools/py-stimulus/src/stimulus/providers/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tools/py-stimulus/src/stimulus/providers/docstrings.py b/tools/py-stimulus/src/stimulus/providers/docstrings.py
new file mode 100644
index 00000000000..eed956777f4
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/providers/docstrings.py
@@ -0,0 +1,52 @@
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Dict, Optional, Union, TYPE_CHECKING
+
+from stimulus.model import DocstringProvider
+
+if TYPE_CHECKING:
+    from jinja2 import Environment
+
+__all__ = ("DocstringProvider", "FolderBasedDocstringProvider")
+
+
+class FolderBasedDocstringProvider:
+    """Docstring provider that returns docstrings from files in a given folder
+    on the filesystem.
+
+    The files are interpreted as Jinja2 templates so you can use all the markup
+    that is valid in Jinja2.
+    """
+
+    _root: Path
+    """Root folder that contains the files with the docstrongs."""
+
+    _jinja_env: Environment
+    """Jinja2 environment that resolves template names from the filesystem."""
+
+    _cache: Dict[str, Optional[str]]
+
+    def __init__(self, root: Union[str, Path]):
+        from jinja2 import Environment, FileSystemLoader
+
+        self._cache = {}
+        self._root = Path(root)
+        self._jinja_env = Environment(
+            loader=FileSystemLoader(self._root),
+            autoescape=False,
+        )
+
+    def __call__(self, name: str) -> Optional[str]:
+        from jinja2 import TemplateNotFound
+
+        if name not in self._cache:
+            try:
+                template = self._jinja_env.get_template(f"{name}.txt")
+            except TemplateNotFound:
+                result = None
+            else:
+                result = template.render(name=name)
+            self._cache[name] = result
+
+        return self._cache.get(name)
diff --git a/tools/py-stimulus/src/stimulus/utils.py b/tools/py-stimulus/src/stimulus/utils.py
new file mode 100644
index 00000000000..b13100e57a7
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/utils.py
@@ -0,0 +1,28 @@
+from typing import Callable, TypeVar
+
+__all__ = ("camelcase", "constant")
+
+
+def camelcase(s: str) -> str:
+    """Returns a camelCase version of the given string (as used in Java
+    libraries.
+    """
+    parts = s.split("_")
+    result = [parts.pop(0)]
+    for part in parts:
+        result.append(part.capitalize())
+    return "".join(result)
+
+
+T = TypeVar("T")
+
+
+def constant(value: T) -> Callable[..., T]:
+    """Function factory that creates functions that return the same value
+    irrespectively of the arguments passed to it.
+    """
+
+    def func(*args, **kwds) -> T:
+        return value
+
+    return func
diff --git a/tools/py-stimulus/src/stimulus/version.py b/tools/py-stimulus/src/stimulus/version.py
new file mode 100644
index 00000000000..ac83366729e
--- /dev/null
+++ b/tools/py-stimulus/src/stimulus/version.py
@@ -0,0 +1,2 @@
+__version_info__ = (0, 21, 5)
+__version__ = ".".join("{0}".format(x) for x in __version_info__)
diff --git a/tools/py-stimulus/tbump.toml b/tools/py-stimulus/tbump.toml
new file mode 100644
index 00000000000..e6602e24f82
--- /dev/null
+++ b/tools/py-stimulus/tbump.toml
@@ -0,0 +1,26 @@
+[version]
+current = "0.21.5"
+regex = '''
+  (?P\d+)
+  \.
+  (?P\d+)
+  \.
+  (?P\d+)
+  '''
+
+[git]
+message_template = "chore: bumped version to {new_version}"
+tag_template = "{new_version}"
+
+[[file]]
+src = "pyproject.toml"
+search = 'version = "{current_version}"'
+
+[[file]]
+src = "src/stimulus/version.py"
+version_template = "({major}, {minor}, {patch})"
+search = "__version_info__ = {current_version}"
+
+[[before_commit]]
+name = "Run pre-commit hooks"
+cmd = "pre-commit run --all-files"

From 177285de4f3926532ed7ba1f5a8e25d64f549aeb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 23:00:55 +0200
Subject: [PATCH 095/154] git subrepo pull (merge) --branch=main
 tools/py-stimulus

subrepo:
  subdir:   "tools/py-stimulus"
  merged:   "4715438bc5"
upstream:
  origin:   "git@github.com:igraph/stimulus"
  branch:   "main"
  commit:   "9652bc7b30"
git-subrepo:
  version:  "0.4.9"
  origin:   "https://github.com/Homebrew/brew"
  commit:   "00001bedf8"
---
 tools/py-stimulus/.gitrepo                    |   6 +-
 tools/py-stimulus/.pre-commit-config.yaml     |  12 +-
 tools/py-stimulus/README.md                   |  10 +
 tools/py-stimulus/poetry.lock                 | 142 ----------
 tools/py-stimulus/poetry.toml                 |   2 -
 tools/py-stimulus/pyproject.toml              |  30 +--
 .../src/stimulus/generators/debug.py          |   2 +-
 .../py-stimulus/src/stimulus/generators/r.py  |   7 +-
 .../src/stimulus/model/functions.py           |   5 +
 tools/py-stimulus/src/stimulus/version.py     |   2 +-
 tools/py-stimulus/tbump.toml                  |   2 +-
 tools/py-stimulus/uv.lock                     | 250 ++++++++++++++++++
 12 files changed, 290 insertions(+), 180 deletions(-)
 delete mode 100644 tools/py-stimulus/poetry.lock
 delete mode 100644 tools/py-stimulus/poetry.toml
 create mode 100644 tools/py-stimulus/uv.lock

diff --git a/tools/py-stimulus/.gitrepo b/tools/py-stimulus/.gitrepo
index 05d5fc4eeff..f99282820ff 100644
--- a/tools/py-stimulus/.gitrepo
+++ b/tools/py-stimulus/.gitrepo
@@ -5,8 +5,8 @@
 ;
 [subrepo]
 	remote = git@github.com:igraph/stimulus
-	branch = 0.21.5
-	commit = f62f215a6d325545b44b59e114c963cf04abb4ce
-	parent = 63943053a43a247f1bf7628bbf481d400ce3e315
+	branch = main
+	commit = 9652bc7b3037b235f5e88b3f6e325ec9f5fda7b9
+	parent = 9fbd9772fd942be5a2516c496c59a4166438f6d2
 	method = merge
 	cmdver = 0.4.9
diff --git a/tools/py-stimulus/.pre-commit-config.yaml b/tools/py-stimulus/.pre-commit-config.yaml
index 04afe0c00e0..2b88275d5e3 100644
--- a/tools/py-stimulus/.pre-commit-config.yaml
+++ b/tools/py-stimulus/.pre-commit-config.yaml
@@ -1,20 +1,14 @@
 fail_fast: true
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.0.1
+    rev: v4.6.0
     hooks:
-      - id: check-ast
       - id: end-of-file-fixer
       - id: trailing-whitespace
 
   - repo: https://github.com/charliermarsh/ruff-pre-commit
-    rev: v0.0.275
+    rev: v0.3.5
     hooks:
       - id: ruff
         args: [--fix, --exit-non-zero-on-fix]
-
-  - repo: https://github.com/psf/black
-    rev: 22.3.0
-    hooks:
-      - id: black
-        language_version: python3
+      - id: ruff-format
diff --git a/tools/py-stimulus/README.md b/tools/py-stimulus/README.md
index 3ae92f0046d..705a2da46e6 100644
--- a/tools/py-stimulus/README.md
+++ b/tools/py-stimulus/README.md
@@ -8,3 +8,13 @@ of the R interface of igraph. The aim of this repository is to refactor it in a
 way that makes it easier to potentially use `stimulus` for other high-level
 interfaces (e.g., the Python interface, which still relies on hand-written code
 for the Python bindings).
+
+## Installation
+
+Install [`uv`](https://astral.sh/uv) and then run `uv sync` to create a virtual
+environment with all required dependencies. Then run `uv run stimulus --help` to
+get help about the command line options.
+
+## Documentation
+
+See `docs/index.mdx` for generic usage instructions.
diff --git a/tools/py-stimulus/poetry.lock b/tools/py-stimulus/poetry.lock
deleted file mode 100644
index 0fee24619fc..00000000000
--- a/tools/py-stimulus/poetry.lock
+++ /dev/null
@@ -1,142 +0,0 @@
-# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
-
-[[package]]
-name = "deepmerge"
-version = "0.3.0"
-description = "a toolset to deeply merge python dictionaries."
-optional = false
-python-versions = ">=3"
-files = [
-    {file = "deepmerge-0.3.0-py2.py3-none-any.whl", hash = "sha256:87166dbe9ba1a3348a45c9d4ada6778f518d41afc0b85aa017ea3041facc3f9c"},
-    {file = "deepmerge-0.3.0.tar.gz", hash = "sha256:f6fd7f1293c535fb599e197e750dbe8674503c5d2a89759b3c72a3c46746d4fd"},
-]
-
-[[package]]
-name = "jinja2"
-version = "3.1.2"
-description = "A very fast and expressive template engine."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
-    {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
-]
-
-[package.dependencies]
-MarkupSafe = ">=2.0"
-
-[package.extras]
-i18n = ["Babel (>=2.7)"]
-
-[[package]]
-name = "markupsafe"
-version = "2.1.3"
-description = "Safely add untrusted strings to HTML/XML markup."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
-    {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
-]
-
-[[package]]
-name = "pyyaml"
-version = "6.0"
-description = "YAML parser and emitter for Python"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
-    {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
-    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
-    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
-    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
-    {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
-    {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
-    {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
-    {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
-    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
-    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
-    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
-    {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
-    {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
-    {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
-    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
-    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
-    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
-    {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
-    {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
-    {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
-    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
-    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
-    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
-    {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
-    {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
-    {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
-    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
-    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
-    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
-    {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
-    {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
-    {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
-    {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
-    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
-    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
-    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
-    {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
-    {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
-    {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
-]
-
-[metadata]
-lock-version = "2.0"
-python-versions = "^3.7"
-content-hash = "02ee53fad3ba232428867b1b13e8f26aef041e09da72069f2f0fba2682e4a398"
diff --git a/tools/py-stimulus/poetry.toml b/tools/py-stimulus/poetry.toml
deleted file mode 100644
index d697ca4701e..00000000000
--- a/tools/py-stimulus/poetry.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[virtualenvs]
-in-project=true
diff --git a/tools/py-stimulus/pyproject.toml b/tools/py-stimulus/pyproject.toml
index e2f1acafc95..c05bd3eba27 100644
--- a/tools/py-stimulus/pyproject.toml
+++ b/tools/py-stimulus/pyproject.toml
@@ -1,30 +1,22 @@
-[tool.poetry]
+[project]
 name = "stimulus"
-version = "0.21.5"
+version = "0.23.0"
 description = "Experimental code generator for high-level interfaces of igraph"
 authors = [
-    "Gabor Csardi ",
-    "Tamas Nepusz ",
+  { name = "Gabor Csardi", email = "csardi.gabor@gmail.com" },
+  { name = "Tamas Nepusz", email = "ntamas@gmail.com" },
 ]
-packages = [{ include = "stimulus", from = "src" }]
 license = "GPL-2.0-or-later"
+requires-python = ">=3.8"
+dependencies = ["PyYAML>=6.0", "deepmerge>=0.3.0", "jinja2>=3.1.2"]
 
-[tool.poetry.dependencies]
-python = "^3.8"
-PyYAML = "^6.0"
-deepmerge = "^0.3.0"
-jinja2 = "^3.1.2"
-
-[tool.poetry.dev-dependencies]
-
-[tool.poetry.scripts]
+[project.scripts]
 stimulus = 'stimulus.__main__:main'
 
 [tool.ruff]
-ignore = ["B905", "C901", "E402", "E501"]
-line-length = 80
-select = ["B", "C", "E", "F", "W"]
+lint.ignore = ["B905", "C901", "E402", "E501"]
+lint.select = ["B", "C", "E", "F", "W"]
 
 [build-system]
-requires = ["poetry-core>=1.0.0"]
-build-backend = "poetry.core.masonry.api"
+requires = ["uv_build>=0.7.18"]
+build-backend = "uv_build"
diff --git a/tools/py-stimulus/src/stimulus/generators/debug.py b/tools/py-stimulus/src/stimulus/generators/debug.py
index bae75fef9e2..198e69cff80 100644
--- a/tools/py-stimulus/src/stimulus/generators/debug.py
+++ b/tools/py-stimulus/src/stimulus/generators/debug.py
@@ -160,7 +160,7 @@ def generate_epilogue(self, inputs: Sequence[str], output: IO[str]) -> None:
         write("#endif")
 
         write()
-        write('    printf("Everything OK!\n");')
+        write('    printf("Everything OK!\\n");')
         write("    return 0;")
         write("}")
 
diff --git a/tools/py-stimulus/src/stimulus/generators/r.py b/tools/py-stimulus/src/stimulus/generators/r.py
index d80b5dc70f9..9dd73e29ad3 100644
--- a/tools/py-stimulus/src/stimulus/generators/r.py
+++ b/tools/py-stimulus/src/stimulus/generators/r.py
@@ -349,7 +349,7 @@ def handle_output_argument(
 
         ## See if there is a postprocessor
         if "PP" in r_spec:
-            out.write(f'  res <- {r_spec["PP"]}(res)\n')
+            out.write(f"  res <- {r_spec['PP']}(res)\n")
 
         out.write("  res\n}\n\n")
 
@@ -516,7 +516,7 @@ def chunk_call(self, desc: FunctionDescriptor) -> str:
                     and not param.is_output
                     and call != "0"
                 ):
-                    call = f"(Rf_isNull(%I%) ? 0 : {call})"
+                    call = f"(Rf_isNull(%I%) ? {param.get_default_value(t) or "NULL"} : {call})"
                 call = call.replace("%C%", f"c_{param.name}").replace("%I%", param.name)
                 calls.append(call)
 
@@ -534,6 +534,9 @@ def chunk_call(self, desc: FunctionDescriptor) -> str:
             else:
                 res = f"  c_result={desc.name}({calls});\n"
 
+        if desc.uses_rng:
+            res = "".join(["  GetRNGstate();\n", res, "  PutRNGstate();\n"])
+
         return res
 
     def chunk_outconv(self, spec: FunctionDescriptor) -> str:
diff --git a/tools/py-stimulus/src/stimulus/model/functions.py b/tools/py-stimulus/src/stimulus/model/functions.py
index ff72bbcfc73..1bd7956572f 100644
--- a/tools/py-stimulus/src/stimulus/model/functions.py
+++ b/tools/py-stimulus/src/stimulus/model/functions.py
@@ -70,6 +70,11 @@ def is_internal(self) -> bool:
         """
         return self.has_flag("internal")
 
+    @property
+    def uses_rng(self) -> bool:
+        """Returns whether the function uses a random number generator."""
+        return not self.has_flag("no_rng")
+
     @property
     def parameters(self) -> OrderedDict[str, ParamSpec]:
         if self._parameters is None:
diff --git a/tools/py-stimulus/src/stimulus/version.py b/tools/py-stimulus/src/stimulus/version.py
index ac83366729e..827137eafc6 100644
--- a/tools/py-stimulus/src/stimulus/version.py
+++ b/tools/py-stimulus/src/stimulus/version.py
@@ -1,2 +1,2 @@
-__version_info__ = (0, 21, 5)
+__version_info__ = (0, 23, 0)
 __version__ = ".".join("{0}".format(x) for x in __version_info__)
diff --git a/tools/py-stimulus/tbump.toml b/tools/py-stimulus/tbump.toml
index e6602e24f82..294e1661def 100644
--- a/tools/py-stimulus/tbump.toml
+++ b/tools/py-stimulus/tbump.toml
@@ -1,5 +1,5 @@
 [version]
-current = "0.21.5"
+current = "0.23.0"
 regex = '''
   (?P\d+)
   \.
diff --git a/tools/py-stimulus/uv.lock b/tools/py-stimulus/uv.lock
new file mode 100644
index 00000000000..08cde9e06b6
--- /dev/null
+++ b/tools/py-stimulus/uv.lock
@@ -0,0 +1,250 @@
+version = 1
+revision = 3
+requires-python = ">=3.8"
+resolution-markers = [
+    "python_full_version >= '3.9'",
+    "python_full_version < '3.9'",
+]
+
+[[package]]
+name = "deepmerge"
+version = "2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+    { name = "typing-extensions", marker = "python_full_version < '3.10'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a8/3a/b0ba594708f1ad0bc735884b3ad854d3ca3bdc1d741e56e40bbda6263499/deepmerge-2.0.tar.gz", hash = "sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20", size = 19890, upload-time = "2024-08-30T05:31:50.308Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/2d/82/e5d2c1c67d19841e9edc74954c827444ae826978499bde3dfc1d007c8c11/deepmerge-2.0-py3-none-any.whl", hash = "sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00", size = 13475, upload-time = "2024-08-30T05:31:48.659Z" },
+]
+
+[[package]]
+name = "jinja2"
+version = "3.1.6"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+    { name = "markupsafe", version = "2.1.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
+    { name = "markupsafe", version = "3.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
+]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.5"
+source = { registry = "https://pypi.org/simple" }
+resolution-markers = [
+    "python_full_version < '3.9'",
+]
+sdist = { url = "https://files.pythonhosted.org/packages/87/5b/aae44c6655f3801e81aa3eef09dbbf012431987ba564d7231722f68df02d/MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", size = 19384, upload-time = "2024-02-02T16:31:22.863Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/e4/54/ad5eb37bf9d51800010a74e4665425831a9db4e7c4e0fde4352e391e808e/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", size = 18206, upload-time = "2024-02-02T16:30:04.105Z" },
+    { url = "https://files.pythonhosted.org/packages/6a/4a/a4d49415e600bacae038c67f9fecc1d5433b9d3c71a4de6f33537b89654c/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", size = 14079, upload-time = "2024-02-02T16:30:06.5Z" },
+    { url = "https://files.pythonhosted.org/packages/0a/7b/85681ae3c33c385b10ac0f8dd025c30af83c78cec1c37a6aa3b55e67f5ec/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", size = 26620, upload-time = "2024-02-02T16:30:08.31Z" },
+    { url = "https://files.pythonhosted.org/packages/7c/52/2b1b570f6b8b803cef5ac28fdf78c0da318916c7d2fe9402a84d591b394c/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", size = 25818, upload-time = "2024-02-02T16:30:09.577Z" },
+    { url = "https://files.pythonhosted.org/packages/29/fe/a36ba8c7ca55621620b2d7c585313efd10729e63ef81e4e61f52330da781/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", size = 25493, upload-time = "2024-02-02T16:30:11.488Z" },
+    { url = "https://files.pythonhosted.org/packages/60/ae/9c60231cdfda003434e8bd27282b1f4e197ad5a710c14bee8bea8a9ca4f0/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", size = 30630, upload-time = "2024-02-02T16:30:13.144Z" },
+    { url = "https://files.pythonhosted.org/packages/65/dc/1510be4d179869f5dafe071aecb3f1f41b45d37c02329dfba01ff59e5ac5/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", size = 29745, upload-time = "2024-02-02T16:30:14.222Z" },
+    { url = "https://files.pythonhosted.org/packages/30/39/8d845dd7d0b0613d86e0ef89549bfb5f61ed781f59af45fc96496e897f3a/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", size = 30021, upload-time = "2024-02-02T16:30:16.032Z" },
+    { url = "https://files.pythonhosted.org/packages/c7/5c/356a6f62e4f3c5fbf2602b4771376af22a3b16efa74eb8716fb4e328e01e/MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", size = 16659, upload-time = "2024-02-02T16:30:17.079Z" },
+    { url = "https://files.pythonhosted.org/packages/69/48/acbf292615c65f0604a0c6fc402ce6d8c991276e16c80c46a8f758fbd30c/MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", size = 17213, upload-time = "2024-02-02T16:30:18.251Z" },
+    { url = "https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", size = 18219, upload-time = "2024-02-02T16:30:19.988Z" },
+    { url = "https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", size = 14098, upload-time = "2024-02-02T16:30:21.063Z" },
+    { url = "https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", size = 29014, upload-time = "2024-02-02T16:30:22.926Z" },
+    { url = "https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", size = 28220, upload-time = "2024-02-02T16:30:24.76Z" },
+    { url = "https://files.pythonhosted.org/packages/0c/40/2e73e7d532d030b1e41180807a80d564eda53babaf04d65e15c1cf897e40/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", size = 27756, upload-time = "2024-02-02T16:30:25.877Z" },
+    { url = "https://files.pythonhosted.org/packages/18/46/5dca760547e8c59c5311b332f70605d24c99d1303dd9a6e1fc3ed0d73561/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", size = 33988, upload-time = "2024-02-02T16:30:26.935Z" },
+    { url = "https://files.pythonhosted.org/packages/6d/c5/27febe918ac36397919cd4a67d5579cbbfa8da027fa1238af6285bb368ea/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", size = 32718, upload-time = "2024-02-02T16:30:28.111Z" },
+    { url = "https://files.pythonhosted.org/packages/f8/81/56e567126a2c2bc2684d6391332e357589a96a76cb9f8e5052d85cb0ead8/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", size = 33317, upload-time = "2024-02-02T16:30:29.214Z" },
+    { url = "https://files.pythonhosted.org/packages/00/0b/23f4b2470accb53285c613a3ab9ec19dc944eaf53592cb6d9e2af8aa24cc/MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", size = 16670, upload-time = "2024-02-02T16:30:30.915Z" },
+    { url = "https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", size = 17224, upload-time = "2024-02-02T16:30:32.09Z" },
+    { url = "https://files.pythonhosted.org/packages/53/bd/583bf3e4c8d6a321938c13f49d44024dbe5ed63e0a7ba127e454a66da974/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", size = 18215, upload-time = "2024-02-02T16:30:33.081Z" },
+    { url = "https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", size = 14069, upload-time = "2024-02-02T16:30:34.148Z" },
+    { url = "https://files.pythonhosted.org/packages/51/b5/5d8ec796e2a08fc814a2c7d2584b55f889a55cf17dd1a90f2beb70744e5c/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", size = 29452, upload-time = "2024-02-02T16:30:35.149Z" },
+    { url = "https://files.pythonhosted.org/packages/0a/0d/2454f072fae3b5a137c119abf15465d1771319dfe9e4acbb31722a0fff91/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", size = 28462, upload-time = "2024-02-02T16:30:36.166Z" },
+    { url = "https://files.pythonhosted.org/packages/2d/75/fd6cb2e68780f72d47e6671840ca517bda5ef663d30ada7616b0462ad1e3/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", size = 27869, upload-time = "2024-02-02T16:30:37.834Z" },
+    { url = "https://files.pythonhosted.org/packages/b0/81/147c477391c2750e8fc7705829f7351cf1cd3be64406edcf900dc633feb2/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", size = 33906, upload-time = "2024-02-02T16:30:39.366Z" },
+    { url = "https://files.pythonhosted.org/packages/8b/ff/9a52b71839d7a256b563e85d11050e307121000dcebc97df120176b3ad93/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", size = 32296, upload-time = "2024-02-02T16:30:40.413Z" },
+    { url = "https://files.pythonhosted.org/packages/88/07/2dc76aa51b481eb96a4c3198894f38b480490e834479611a4053fbf08623/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", size = 33038, upload-time = "2024-02-02T16:30:42.243Z" },
+    { url = "https://files.pythonhosted.org/packages/96/0c/620c1fb3661858c0e37eb3cbffd8c6f732a67cd97296f725789679801b31/MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", size = 16572, upload-time = "2024-02-02T16:30:43.326Z" },
+    { url = "https://files.pythonhosted.org/packages/3f/14/c3554d512d5f9100a95e737502f4a2323a1959f6d0d01e0d0997b35f7b10/MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", size = 17127, upload-time = "2024-02-02T16:30:44.418Z" },
+    { url = "https://files.pythonhosted.org/packages/f8/ff/2c942a82c35a49df5de3a630ce0a8456ac2969691b230e530ac12314364c/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", size = 18192, upload-time = "2024-02-02T16:30:57.715Z" },
+    { url = "https://files.pythonhosted.org/packages/4f/14/6f294b9c4f969d0c801a4615e221c1e084722ea6114ab2114189c5b8cbe0/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", size = 14072, upload-time = "2024-02-02T16:30:58.844Z" },
+    { url = "https://files.pythonhosted.org/packages/81/d4/fd74714ed30a1dedd0b82427c02fa4deec64f173831ec716da11c51a50aa/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", size = 26928, upload-time = "2024-02-02T16:30:59.922Z" },
+    { url = "https://files.pythonhosted.org/packages/c7/bd/50319665ce81bb10e90d1cf76f9e1aa269ea6f7fa30ab4521f14d122a3df/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", size = 26106, upload-time = "2024-02-02T16:31:01.582Z" },
+    { url = "https://files.pythonhosted.org/packages/4c/6f/f2b0f675635b05f6afd5ea03c094557bdb8622fa8e673387444fe8d8e787/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68", size = 25781, upload-time = "2024-02-02T16:31:02.71Z" },
+    { url = "https://files.pythonhosted.org/packages/51/e0/393467cf899b34a9d3678e78961c2c8cdf49fb902a959ba54ece01273fb1/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", size = 30518, upload-time = "2024-02-02T16:31:04.392Z" },
+    { url = "https://files.pythonhosted.org/packages/f6/02/5437e2ad33047290dafced9df741d9efc3e716b75583bbd73a9984f1b6f7/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", size = 29669, upload-time = "2024-02-02T16:31:05.53Z" },
+    { url = "https://files.pythonhosted.org/packages/0e/7d/968284145ffd9d726183ed6237c77938c021abacde4e073020f920e060b2/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", size = 29933, upload-time = "2024-02-02T16:31:06.636Z" },
+    { url = "https://files.pythonhosted.org/packages/bf/f3/ecb00fc8ab02b7beae8699f34db9357ae49d9f21d4d3de6f305f34fa949e/MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", size = 16656, upload-time = "2024-02-02T16:31:07.767Z" },
+    { url = "https://files.pythonhosted.org/packages/92/21/357205f03514a49b293e214ac39de01fadd0970a6e05e4bf1ddd0ffd0881/MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", size = 17206, upload-time = "2024-02-02T16:31:08.843Z" },
+    { url = "https://files.pythonhosted.org/packages/0f/31/780bb297db036ba7b7bbede5e1d7f1e14d704ad4beb3ce53fb495d22bc62/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", size = 18193, upload-time = "2024-02-02T16:31:10.155Z" },
+    { url = "https://files.pythonhosted.org/packages/6c/77/d77701bbef72892affe060cdacb7a2ed7fd68dae3b477a8642f15ad3b132/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", size = 14073, upload-time = "2024-02-02T16:31:11.442Z" },
+    { url = "https://files.pythonhosted.org/packages/d9/a7/1e558b4f78454c8a3a0199292d96159eb4d091f983bc35ef258314fe7269/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", size = 26486, upload-time = "2024-02-02T16:31:12.488Z" },
+    { url = "https://files.pythonhosted.org/packages/5f/5a/360da85076688755ea0cceb92472923086993e86b5613bbae9fbc14136b0/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", size = 25685, upload-time = "2024-02-02T16:31:13.726Z" },
+    { url = "https://files.pythonhosted.org/packages/6a/18/ae5a258e3401f9b8312f92b028c54d7026a97ec3ab20bfaddbdfa7d8cce8/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", size = 25338, upload-time = "2024-02-02T16:31:14.812Z" },
+    { url = "https://files.pythonhosted.org/packages/0b/cc/48206bd61c5b9d0129f4d75243b156929b04c94c09041321456fd06a876d/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", size = 30439, upload-time = "2024-02-02T16:31:15.946Z" },
+    { url = "https://files.pythonhosted.org/packages/d1/06/a41c112ab9ffdeeb5f77bc3e331fdadf97fa65e52e44ba31880f4e7f983c/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", size = 29531, upload-time = "2024-02-02T16:31:17.13Z" },
+    { url = "https://files.pythonhosted.org/packages/02/8c/ab9a463301a50dab04d5472e998acbd4080597abc048166ded5c7aa768c8/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", size = 29823, upload-time = "2024-02-02T16:31:18.247Z" },
+    { url = "https://files.pythonhosted.org/packages/bc/29/9bc18da763496b055d8e98ce476c8e718dcfd78157e17f555ce6dd7d0895/MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", size = 16658, upload-time = "2024-02-02T16:31:19.583Z" },
+    { url = "https://files.pythonhosted.org/packages/f6/f8/4da07de16f10551ca1f640c92b5f316f9394088b183c6a57183df6de5ae4/MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", size = 17211, upload-time = "2024-02-02T16:31:20.96Z" },
+]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.2"
+source = { registry = "https://pypi.org/simple" }
+resolution-markers = [
+    "python_full_version >= '3.9'",
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" },
+    { url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393, upload-time = "2024-10-18T15:20:52.426Z" },
+    { url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732, upload-time = "2024-10-18T15:20:53.578Z" },
+    { url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866, upload-time = "2024-10-18T15:20:55.06Z" },
+    { url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964, upload-time = "2024-10-18T15:20:55.906Z" },
+    { url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977, upload-time = "2024-10-18T15:20:57.189Z" },
+    { url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366, upload-time = "2024-10-18T15:20:58.235Z" },
+    { url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091, upload-time = "2024-10-18T15:20:59.235Z" },
+    { url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065, upload-time = "2024-10-18T15:21:00.307Z" },
+    { url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514, upload-time = "2024-10-18T15:21:01.122Z" },
+    { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" },
+    { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" },
+    { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" },
+    { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" },
+    { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" },
+    { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" },
+    { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" },
+    { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" },
+    { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" },
+    { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" },
+    { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" },
+    { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" },
+    { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" },
+    { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" },
+    { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" },
+    { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" },
+    { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" },
+    { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" },
+    { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" },
+    { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" },
+    { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" },
+    { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" },
+    { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" },
+    { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" },
+    { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" },
+    { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" },
+    { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" },
+    { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" },
+    { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" },
+    { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" },
+    { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" },
+    { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" },
+    { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" },
+    { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" },
+    { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" },
+    { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" },
+    { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" },
+    { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" },
+    { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" },
+    { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
+    { url = "https://files.pythonhosted.org/packages/a7/ea/9b1530c3fdeeca613faeb0fb5cbcf2389d816072fab72a71b45749ef6062/MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", size = 14344, upload-time = "2024-10-18T15:21:43.721Z" },
+    { url = "https://files.pythonhosted.org/packages/4b/c2/fbdbfe48848e7112ab05e627e718e854d20192b674952d9042ebd8c9e5de/MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", size = 12389, upload-time = "2024-10-18T15:21:44.666Z" },
+    { url = "https://files.pythonhosted.org/packages/f0/25/7a7c6e4dbd4f867d95d94ca15449e91e52856f6ed1905d58ef1de5e211d0/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", size = 21607, upload-time = "2024-10-18T15:21:45.452Z" },
+    { url = "https://files.pythonhosted.org/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", size = 20728, upload-time = "2024-10-18T15:21:46.295Z" },
+    { url = "https://files.pythonhosted.org/packages/1a/03/8496a1a78308456dbd50b23a385c69b41f2e9661c67ea1329849a598a8f9/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", size = 20826, upload-time = "2024-10-18T15:21:47.134Z" },
+    { url = "https://files.pythonhosted.org/packages/e6/cf/0a490a4bd363048c3022f2f475c8c05582179bb179defcee4766fb3dcc18/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", size = 21843, upload-time = "2024-10-18T15:21:48.334Z" },
+    { url = "https://files.pythonhosted.org/packages/19/a3/34187a78613920dfd3cdf68ef6ce5e99c4f3417f035694074beb8848cd77/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", size = 21219, upload-time = "2024-10-18T15:21:49.587Z" },
+    { url = "https://files.pythonhosted.org/packages/17/d8/5811082f85bb88410ad7e452263af048d685669bbbfb7b595e8689152498/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", size = 20946, upload-time = "2024-10-18T15:21:50.441Z" },
+    { url = "https://files.pythonhosted.org/packages/7c/31/bd635fb5989440d9365c5e3c47556cfea121c7803f5034ac843e8f37c2f2/MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", size = 15063, upload-time = "2024-10-18T15:21:51.385Z" },
+    { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506, upload-time = "2024-10-18T15:21:52.974Z" },
+]
+
+[[package]]
+name = "pyyaml"
+version = "6.0.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" },
+    { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" },
+    { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" },
+    { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" },
+    { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" },
+    { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" },
+    { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" },
+    { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" },
+    { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" },
+    { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" },
+    { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" },
+    { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" },
+    { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" },
+    { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" },
+    { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" },
+    { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" },
+    { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" },
+    { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" },
+    { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" },
+    { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" },
+    { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" },
+    { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" },
+    { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" },
+    { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" },
+    { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" },
+    { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" },
+    { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" },
+    { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" },
+    { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" },
+    { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" },
+    { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" },
+    { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" },
+    { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" },
+    { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" },
+    { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" },
+    { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" },
+    { url = "https://files.pythonhosted.org/packages/74/d9/323a59d506f12f498c2097488d80d16f4cf965cee1791eab58b56b19f47a/PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", size = 183218, upload-time = "2024-08-06T20:33:06.411Z" },
+    { url = "https://files.pythonhosted.org/packages/74/cc/20c34d00f04d785f2028737e2e2a8254e1425102e730fee1d6396f832577/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", size = 728067, upload-time = "2024-08-06T20:33:07.879Z" },
+    { url = "https://files.pythonhosted.org/packages/20/52/551c69ca1501d21c0de51ddafa8c23a0191ef296ff098e98358f69080577/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", size = 757812, upload-time = "2024-08-06T20:33:12.542Z" },
+    { url = "https://files.pythonhosted.org/packages/fd/7f/2c3697bba5d4aa5cc2afe81826d73dfae5f049458e44732c7a0938baa673/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", size = 746531, upload-time = "2024-08-06T20:33:14.391Z" },
+    { url = "https://files.pythonhosted.org/packages/8c/ab/6226d3df99900e580091bb44258fde77a8433511a86883bd4681ea19a858/PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", size = 800820, upload-time = "2024-08-06T20:33:16.586Z" },
+    { url = "https://files.pythonhosted.org/packages/a0/99/a9eb0f3e710c06c5d922026f6736e920d431812ace24aae38228d0d64b04/PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", size = 145514, upload-time = "2024-08-06T20:33:22.414Z" },
+    { url = "https://files.pythonhosted.org/packages/75/8a/ee831ad5fafa4431099aa4e078d4c8efd43cd5e48fbc774641d233b683a9/PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", size = 162702, upload-time = "2024-08-06T20:33:23.813Z" },
+    { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777, upload-time = "2024-08-06T20:33:25.896Z" },
+    { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318, upload-time = "2024-08-06T20:33:27.212Z" },
+    { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891, upload-time = "2024-08-06T20:33:28.974Z" },
+    { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614, upload-time = "2024-08-06T20:33:34.157Z" },
+    { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360, upload-time = "2024-08-06T20:33:35.84Z" },
+    { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006, upload-time = "2024-08-06T20:33:37.501Z" },
+    { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577, upload-time = "2024-08-06T20:33:39.389Z" },
+    { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593, upload-time = "2024-08-06T20:33:46.63Z" },
+    { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312, upload-time = "2024-08-06T20:33:49.073Z" },
+]
+
+[[package]]
+name = "stimulus"
+version = "0.22.0"
+source = { editable = "." }
+dependencies = [
+    { name = "deepmerge" },
+    { name = "jinja2" },
+    { name = "pyyaml" },
+]
+
+[package.metadata]
+requires-dist = [
+    { name = "deepmerge", specifier = ">=0.3.0" },
+    { name = "jinja2", specifier = ">=3.1.2" },
+    { name = "pyyaml", specifier = ">=6.0" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.13.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" },
+]

From 154fcf8469b7e91bc201ac9be2abe3401e6808eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 23:18:06 +0200
Subject: [PATCH 096/154] Sync .github

---
 .github/workflows/R-CMD-check.yaml         | 10 +----
 .github/workflows/claude.yaml              | 38 -----------------
 .github/workflows/commit/action.yml        |  2 +-
 .github/workflows/copilot-setup-steps.yaml | 48 ++++++++++++++++++++++
 .github/workflows/vendor.yaml              |  4 +-
 5 files changed, 51 insertions(+), 51 deletions(-)
 delete mode 100644 .github/workflows/claude.yaml
 create mode 100644 .github/workflows/copilot-setup-steps.yaml

diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index a68f3c859e4..301322c8d1f 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -16,7 +16,6 @@ on:
     branches:
       - main
       - master
-      - next
   workflow_dispatch:
     inputs:
       ref:
@@ -70,16 +69,12 @@ jobs:
 
       - name: Update status for rcc
         # FIXME: Wrap into action
-        if: github.event_name == 'workflow_dispatch'
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         run: |
           # Check status of this workflow
           state="pending"
           sha=${{ inputs.ref }}
-          if [ -z "${sha}" ]; then
-            sha=${{ github.head_ref }}
-          fi
           if [ -z "${sha}" ]; then
             sha=${{ github.sha }}
           fi
@@ -176,7 +171,7 @@ jobs:
 
       - name: Update status for rcc
         # FIXME: Wrap into action
-        if: always() && github.event_name == 'workflow_dispatch'
+        if: always()
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         run: |
@@ -191,9 +186,6 @@ jobs:
           if [ -z "${sha}" ]; then
             sha=${{ inputs.ref }}
           fi
-          if [ -z "${sha}" ]; then
-            sha=${{ github.head_ref }}
-          fi
           if [ -z "${sha}" ]; then
             sha=${{ github.sha }}
           fi
diff --git a/.github/workflows/claude.yaml b/.github/workflows/claude.yaml
deleted file mode 100644
index 913a1870f79..00000000000
--- a/.github/workflows/claude.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Claude Assistant
-on:
-  issue_comment:
-    types: [created]
-  pull_request_review_comment:
-    types: [created]
-  issues:
-    types: [opened, assigned]
-  pull_request_review:
-    types: [submitted]
-
-jobs:
-  claude-response:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-        with:
-          fetch-depth: 1
-
-      - uses: anthropics/claude-code-action@beta
-        id: claude
-        with:
-          allowed_tools: |
-            Bash
-            R
-          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
-          github_token: ${{ secrets.GITHUB_TOKEN }}
-          # Optional: add custom trigger phrase (default: @claude)
-          # trigger_phrase: "/claude"
-          # Optional: add assignee trigger for issues
-          # assignee_trigger: "claude"
-          # Optional: add custom environment variables (YAML format)
-          # claude_env: |
-          #   NODE_ENV: test
-          #   DEBUG: true
-          #   API_URL: https://api.example.com
-          # Optional: limit the number of conversation turns
-          max_turns: "20"
diff --git a/.github/workflows/commit/action.yml b/.github/workflows/commit/action.yml
index 8dd0c9e225b..e385cd88832 100644
--- a/.github/workflows/commit/action.yml
+++ b/.github/workflows/commit/action.yml
@@ -32,7 +32,7 @@ runs:
         protected=${{ github.ref_protected }}
         foreign=${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
         is_pr=${{ github.event_name == 'pull_request' }}
-        if [ "${is_pr}" = "true" ]; then
+        if [ "${is_pr}" = "true" ] && [ "${foreign}" = "true" ]; then
           # Running on a PR - will use reviewdog in next step
           echo "Code changes detected on PR, will suggest changes via reviewdog"
           echo "use_reviewdog=true" | tee -a $GITHUB_OUTPUT
diff --git a/.github/workflows/copilot-setup-steps.yaml b/.github/workflows/copilot-setup-steps.yaml
new file mode 100644
index 00000000000..a604762abbd
--- /dev/null
+++ b/.github/workflows/copilot-setup-steps.yaml
@@ -0,0 +1,48 @@
+name: "Copilot Setup Steps"
+
+# Automatically run the setup steps when they are changed to allow for easy validation, and
+# allow manual testing through the repository's "Actions" tab
+on:
+  workflow_dispatch:
+  push:
+    paths:
+      - .github/workflows/copilot-setup-steps.yml
+  pull_request:
+    paths:
+      - .github/workflows/copilot-setup-steps.yml
+
+jobs:
+  # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
+  copilot-setup-steps:
+    runs-on: ubuntu-latest
+
+    # Set the permissions to the lowest permissions possible needed for your steps.
+    # Copilot will be given its own token for its operations.
+    permissions:
+      # If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
+      contents: read
+
+    # You can define any steps you want, and they will run before the agent starts.
+    # If you do not check out your code, Copilot will do this for you.
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v5
+      - uses: ./.github/workflows/custom/before-install
+        if: hashFiles('.github/workflows/custom/before-install/action.yml') != ''
+
+      - uses: ./.github/workflows/install
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          cache-version: copilot
+          needs: build, check, website
+          # Beware of using dev pkgdown here, has brought in dev dependencies in the past
+          extra-packages: any::rcmdcheck r-lib/roxygen2 any::decor r-lib/styler r-lib/pkgdown deps::.
+
+      - uses: ./.github/workflows/custom/after-install
+        if: hashFiles('.github/workflows/custom/after-install/action.yml') != ''
+
+      # Must come after the custom after-install workflow
+      - name: Install package
+        run: |
+          UserNM=true R CMD INSTALL . || true
+        shell: bash
diff --git a/.github/workflows/vendor.yaml b/.github/workflows/vendor.yaml
index 5a7041de198..7f578d3ccec 100644
--- a/.github/workflows/vendor.yaml
+++ b/.github/workflows/vendor.yaml
@@ -20,10 +20,8 @@ jobs:
     strategy:
       matrix:
         include:
-          - branch: main
-            upstream: master
           - branch: next
-            upstream: develop
+            upstream: main
     outputs:
       sha: ${{ steps.commit.outputs.sha }}
 

From ddf74dce2cda5a8145655c356e528a9352c64189 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 23:20:33 +0200
Subject: [PATCH 097/154] Sync agents

---
 CLAUDE.md => AGENTS.md | 46 ++++++++++++++----------------------------
 1 file changed, 15 insertions(+), 31 deletions(-)
 rename CLAUDE.md => AGENTS.md (52%)

diff --git a/CLAUDE.md b/AGENTS.md
similarity index 52%
rename from CLAUDE.md
rename to AGENTS.md
index 2e85c72d0c5..5c4ecdb87cf 100644
--- a/CLAUDE.md
+++ b/AGENTS.md
@@ -1,11 +1,22 @@
-# Claude Development Guidelines for igraph
+# AI Agent Development Guidelines for igraph
 
 ## Project Overview
 
 igraph is an R package with routines for simple graphs and network analysis. It can handle large graphs very well and provides functions for generating random and regular graphs, graph visualization, centrality methods and much more.
 
+## Install and run R
+
+- When run on GitHub Actions, assume that R, the package in its current state and all dependencies are installed.
+- Only install new packages when needed for implementing new features or tests.
+- Run `R -q -e 'testthat::test_local(reporter = "check")` to execute tests as a final step.
+
 ## Code Style and Documentation
 
+### PR and Commit Style
+
+- PRs and commits use the conventional commit style with backticks for code references such as `function_call()` .
+- PRs are generally squashed, a clean history within a PR is not necessary.
+
 ### Comment Style
 
 - Add comprehensive comments to utility functions that aren't immediately obvious
@@ -16,35 +27,8 @@ igraph is an R package with routines for simple graphs and network analysis. It
 ### R Code Conventions
 
 - Follow existing naming conventions (snake_case for functions, camelCase for some legacy functions)
-- Use explicit package prefixes (e.g., `withr::local_db_connection`) for clarity
+- Use explicit package prefixes (e.g., `withr::local_db_connection()`) for clarity
 - Maintain consistent indentation and spacing patterns
 - Use meaningful variable names that reflect the testing context
-
-## Install and run R
-
-Never check if rig or R are installed on GitHub Actions, they are not.
-Use rig to install R.
-Install rig with:
-
-```bash
-curl -Ls https://github.com/r-lib/rig/releases/download/latest/rig-linux-$(arch)-latest.tar.gz |
-  sudo tar xz -C /usr/local
-```
-
-Then install the current release version of R:
-
-```bash
-rig add release
-```
-
-Run R code with:
-
-```bash
-Rscript -e ''
-```
-
-Use pak to install packages, it will be installed by rig:
-
-```R
-pak::pak("")
-```
+- Run `air format .` before committing changes to ensure consistent formatting
+- Keep documentation in sync with code changes. When updating roxygen2 documentation, ensure that each sentence is on its own line for better readability. Run `R -q -e 'devtools::document()'` to update the documentation.

From 4167c65f336d1030af573241cdbe265df58c9c28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 23:22:08 +0200
Subject: [PATCH 098/154] Use local Stimulus

---
 tools/README.md              | 134 ++++++++++++++++++++++++++++++-----
 tools/build-requirements.txt |   2 +-
 2 files changed, 118 insertions(+), 18 deletions(-)

diff --git a/tools/README.md b/tools/README.md
index cb3173d1191..83af213ae6a 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -5,9 +5,11 @@
 In the shell:
 
 ```sh
-vendor.sh 
+./vendor.sh 
 ```
 
+By default, `cigraph` is assumed to be in `../../../igraph`.
+
 There is a CI/CD workflow that runs this very frequently.
 
 ## Running Stimulus
@@ -15,20 +17,118 @@ There is a CI/CD workflow that runs this very frequently.
 Currently, there are only two files generated by Stimulus.
 They are version-controlled and depend on various input files.
 The logic is governed by the `Makefile-cigraph` file.
+To update them, do the following steps:
+
+```sh
+make -f Makefile-cigraph src/rinterface.c R/aaa-auto.R
+```
+
+## Managing Stimulus with git subrepo
+
+### What is git subrepo?
+
+The Stimulus code generator is vendored into this repository using [`git subrepo`](https://github.com/ingydotnet/git-subrepo), a tool that allows you to include an external git repository as a subdirectory within your main repository.
+Unlike git submodules, subrepos are easier to work with because they don't require special checkout commands; the code is directly present in the repository.
+This approach gives us the flexibility to test local modifications to Stimulus while still being able to pull upstream updates cleanly.
+
+### Installing git subrepo
+
+If you don't have `git subrepo` installed yet:
+
+```sh
+# On macOS with Homebrew
+brew install git-subrepo
+
+# Or install from source
+git clone https://github.com/ingydotnet/git-subrepo /path/to/git-subrepo
+echo 'source /path/to/git-subrepo/.rc' >> ~/.zshrc
+```
+
+### Updating Stimulus from upstream
+
+To pull the latest changes from the upstream Stimulus repository:
+
+```sh
+# Pull the latest from the main branch
+git subrepo pull tools/py-stimulus
+
+# Or pull a specific branch
+git subrepo pull tools/py-stimulus -b branch-name
+
+# Or pull a specific commit or tag
+git subrepo pull tools/py-stimulus -b v0.21.5
+```
+
+This command will:
+
+1. Fetch changes from the upstream Stimulus repository
+2. Merge them into the `tools/py-stimulus/` directory
+3. Create a merge commit with metadata in `.gitrepo`
+4. Update the commit hash in `tools/py-stimulus/.gitrepo`
+
+After pulling, test the changes:
+
+```sh
+# Clean the virtualenv to ensure fresh installation
+rm -rf .venv
+
+# Regenerate the interface files
+make -f Makefile-cigraph src/rinterface.c R/aaa-auto.R
+```
+
+### Working with a modified version of Stimulus
+
+If you need to test local changes to Stimulus:
+
+1. **Make your changes** directly in `tools/py-stimulus/`:
+
+   ```sh
+   cd tools/py-stimulus
+   # Edit files as needed
+   vim src/stimulus/some_file.py
+   cd ../..
+   ```
+
+2. **Test your changes**:
+
+   ```sh
+   # Remove the virtualenv to force reinstallation
+   rm -rf .venv
+
+   # Regenerate with your modified Stimulus
+   make -f Makefile-cigraph src/rinterface.c R/aaa-auto.R
+   ```
+
+3. **Commit everything together**:
+
+   ```sh
+   git add tools/py-stimulus/ src/rinterface.c R/aaa-auto.R
+   git commit -m "feat: update Stimulus and regenerated interface files"
+   ```
+
+The modified Stimulus code and generated files will be committed together, making it easy to see what Stimulus changes caused which interface changes.
+
+### Pushing Stimulus changes upstream
+
+If your Stimulus modifications should be contributed back to the upstream repository:
+
+```sh
+# Push your changes to the upstream Stimulus repository
+git subrepo push tools/py-stimulus
+
+# Or push to a specific branch (useful for PRs)
+git subrepo push tools/py-stimulus -b feature-branch-name
+```
+
+This will create commits in the upstream Stimulus repository based on the commits you made in `tools/py-stimulus/`.
+
+### Checking subrepo status
+
+To see information about the subrepo:
+
+```sh
+git subrepo status tools/py-stimulus
+```
+
+This shows the remote URL, branch, and commit hashes.
 
-1. For igraph/C < 0.10, this requires the `cigraph` submodule.
-    After the update, the code will be taken from `src/vendor/cigraph` (search for a FIXME in the `Makefile-cigraph` file).
-    ```sh
-    git submodule init
-    git submodule update
-    ```
-
-2. Update the generated code.
-    ```sh
-    make -f Makefile-cigraph src/rinterface.c R/aaa-auto.R
-    ```
-
-3. Optional: Clean submodule
-    ```sh
-    git submodule deinit --all
-    ```
diff --git a/tools/build-requirements.txt b/tools/build-requirements.txt
index 53cf255b4b3..351930a23ed 100644
--- a/tools/build-requirements.txt
+++ b/tools/build-requirements.txt
@@ -3,4 +3,4 @@
 # environment to detect when to re-create the virtualenv so the hash
 # needs to change whenever a package is updated.
 
-git+https://github.com/krlmlr/stimulus@r#egg=stimulus
+./tools/py-stimulus/

From 2986763a9058d7f58689c6326c59c9055b372dce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 18:05:46 +0200
Subject: [PATCH 099/154] ci: Deterministic setup for Copilot

---
 .Rbuildignore | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.Rbuildignore b/.Rbuildignore
index b1879373672..468a6790eb3 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -58,7 +58,7 @@
 ^src/deps\.mk$
 ^[\.]?air\.toml$
 ^\.vscode$
-^CLAUDE\.md$
+^AGENTS\.md$
 ^covr$
 ^src/*\.gcda$
 ^src/*\.gcno$

From 7e84e62ddfc983b05de051df50f4f521fd2a2201 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 18:23:39 +0200
Subject: [PATCH 100/154] chore: Replace `_impl` aliases with explicit wrappers
 in R/assortativity.R (#2333)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/assortativity.R | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/R/assortativity.R b/R/assortativity.R
index cec0dd3aa83..e6f9c98ca93 100644
--- a/R/assortativity.R
+++ b/R/assortativity.R
@@ -230,9 +230,26 @@ assortativity_legacy <- function(
 #' @rdname assortativity
 #' @export
 #' @cdocs igraph_assortativity_nominal
-assortativity_nominal <- assortativity_nominal_impl
+assortativity_nominal <- function(
+  graph,
+  types,
+  directed = TRUE,
+  normalized = TRUE
+) {
+  assortativity_nominal_impl(
+    graph = graph,
+    types = types,
+    directed = directed,
+    normalized = normalized
+  )
+}
 
 #' @rdname assortativity
 #' @export
 #' @cdocs igraph_assortativity_degree
-assortativity_degree <- assortativity_degree_impl
+assortativity_degree <- function(graph, directed = TRUE) {
+  assortativity_degree_impl(
+    graph = graph,
+    directed = directed
+  )
+}

From 99e60ca4e05a4f69d67d1254a63998d7e937e8ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 19:00:02 +0200
Subject: [PATCH 101/154] chore: Embed Stimulus sources, add docs

---
 src/README.md | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/README.md b/src/README.md
index 483f15774cd..171928561e5 100644
--- a/src/README.md
+++ b/src/README.md
@@ -2,29 +2,25 @@
 
 ## Updating the C sources
 
-1. Check out and update the `cigraph` submodule to the desired version.
-    ```sh
-    git submodule init
-    git submodule update
-    # other git submodule commands to update the submodule to the desired version
-    ```
-2. Clean the `src/` directory:
+1. Clean the `src/` directory:
+
     ```sh
     make -f Makefile-cigraph clean
     ```
-3. Update the `src/` directory:
+
+2. Update the `src/` directory:
+
     ```sh
     make -f Makefile-cigraph
     ```
 
     Note that this may change files generated by `flex` and `bison`, and configure scripts, depending on the version of those tools.
-    For stability, you can use a Docker image that uses pinned versions of these tools:
+    For stability, the `Makefile` uses Docker with pinned versions of those tools.
+
+3. Review the changes, especially in `src/` and `configure`:
+
     ```sh
-    docker run --rm -ti --platform linux/amd64 -v $(pwd):/root/workspace ghcr.io/cynkra/docker-images/rig-ubuntu-igraph make -f Makefile-cigraph
+    git diff src/ configure
     ```
 
 4. Commit and push
-5. Optional: Clean submodule
-    ```sh
-    git submodule deinit --all
-    ```

From 1bd16e7c4f9536ba454beb107c401eb617f2a0ac Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 19:33:16 +0200
Subject: [PATCH 102/154] chore: Replace `_impl` alias with explicit wrapper in
 `R/coloring.R` (#2364)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/coloring.R | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/R/coloring.R b/R/coloring.R
index b04c1392012..888380298be 100644
--- a/R/coloring.R
+++ b/R/coloring.R
@@ -31,4 +31,12 @@
 #' plot(g, vertex.color = col)
 #'
 #' @cdocs igraph_vertex_coloring_greedy
-greedy_vertex_coloring <- vertex_coloring_greedy_impl
+greedy_vertex_coloring <- function(
+  graph,
+  heuristic = c("colored_neighbors", "dsatur")
+) {
+  vertex_coloring_greedy_impl(
+    graph = graph,
+    heuristic = heuristic
+  )
+}

From eadb4cb816a938efbb2480489c4cb2a347383ac7 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 19:33:25 +0200
Subject: [PATCH 103/154] chore: Replace `_impl` function aliases with explicit
 wrappers in `R/centrality.R` (#2362)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/centrality.R | 64 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 60 insertions(+), 4 deletions(-)

diff --git a/R/centrality.R b/R/centrality.R
index 23ca01f4610..58112f7bdcb 100644
--- a/R/centrality.R
+++ b/R/centrality.R
@@ -1473,7 +1473,21 @@ eigen_centrality <- function(
 #' @family centrality
 #' @export
 #' @cdocs igraph_strength
-strength <- strength_impl
+strength <- function(
+  graph,
+  vids = V(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = TRUE,
+  weights = NULL
+) {
+  strength_impl(
+    graph = graph,
+    vids = vids,
+    mode = mode,
+    loops = loops,
+    weights = weights
+  )
+}
 
 
 #' Graph diversity
@@ -1517,7 +1531,13 @@ strength <- strength_impl
 #' @family centrality
 #' @export
 #' @cdocs igraph_diversity
-diversity <- diversity_impl
+diversity <- function(graph, weights = NULL, vids = V(graph)) {
+  diversity_impl(
+    graph = graph,
+    weights = weights,
+    vids = vids
+  )
+}
 
 
 #' Kleinberg's hub and authority centrality scores.
@@ -1769,7 +1789,27 @@ hub_score <- function(
 #' @family centrality
 #' @export
 #' @cdocs igraph_personalized_pagerank
-page_rank <- personalized_pagerank_impl
+page_rank <- function(
+  graph,
+  algo = c("prpack", "arpack"),
+  vids = V(graph),
+  directed = TRUE,
+  damping = 0.85,
+  personalized = NULL,
+  weights = NULL,
+  options = NULL
+) {
+  personalized_pagerank_impl(
+    graph = graph,
+    algo = algo,
+    vids = vids,
+    directed = directed,
+    damping = damping,
+    personalized = personalized,
+    weights = weights,
+    options = options
+  )
+}
 
 #' Harmonic centrality of vertices
 #'
@@ -1817,7 +1857,23 @@ page_rank <- personalized_pagerank_impl
 #' harmonic_centrality(g %du% make_full_graph(5), mode = "all")
 #'
 #' @cdocs igraph_harmonic_centrality_cutoff
-harmonic_centrality <- harmonic_centrality_cutoff_impl
+harmonic_centrality <- function(
+  graph,
+  vids = V(graph),
+  mode = c("out", "in", "all", "total"),
+  weights = NULL,
+  normalized = FALSE,
+  cutoff = -1
+) {
+  harmonic_centrality_cutoff_impl(
+    graph = graph,
+    vids = vids,
+    mode = mode,
+    weights = weights,
+    normalized = normalized,
+    cutoff = cutoff
+  )
+}
 
 
 bonpow.dense <- function(

From 7781f93de3f2c9e11550b5a323a308e4ce5b3563 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 19:33:33 +0200
Subject: [PATCH 104/154] chore: Replace `_impl` aliases with explicit wrapper
 functions in `R/cliques.R` (#2363)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/cliques.R | 71 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 62 insertions(+), 9 deletions(-)

diff --git a/R/cliques.R b/R/cliques.R
index 44565406c19..ec3ee54fdd8 100644
--- a/R/cliques.R
+++ b/R/cliques.R
@@ -239,12 +239,22 @@ clique.number <- function(graph) {
 #' # Check that all returned vertex sets are indeed cliques
 #' all(sapply(max_cliques(g), function (c) is_clique(g, c)))
 #' @cdocs igraph_cliques
-cliques <- cliques_impl
+cliques <- function(graph, min = 0, max = 0) {
+  cliques_impl(
+    graph = graph,
+    min = min,
+    max = max
+  )
+}
 
 #' @rdname cliques
 #' @export
 #' @cdocs igraph_largest_cliques
-largest_cliques <- largest_cliques_impl
+largest_cliques <- function(graph) {
+  largest_cliques_impl(
+    graph = graph
+  )
+}
 
 #' @rdname cliques
 #' @param subset If not `NULL`, then it must be a vector of vertex ids,
@@ -352,7 +362,11 @@ count_max_cliques <- function(graph, min = NULL, max = NULL, subset = NULL) {
 #' @rdname cliques
 #' @export
 #' @cdocs igraph_clique_number
-clique_num <- clique_number_impl
+clique_num <- function(graph) {
+  clique_number_impl(
+    graph = graph
+  )
+}
 
 
 #' Functions to find weighted cliques, i.e. vertex-weighted complete subgraphs in a graph
@@ -405,15 +419,39 @@ clique_num <- clique_number_impl
 #' largest_weighted_cliques(g)
 #' weighted_clique_num(g)
 #' @cdocs igraph_weighted_cliques
-weighted_cliques <- weighted_cliques_impl
+weighted_cliques <- function(
+  graph,
+  vertex.weights = NULL,
+  min.weight = 0,
+  max.weight = 0,
+  maximal = FALSE
+) {
+  weighted_cliques_impl(
+    graph = graph,
+    vertex.weights = vertex.weights,
+    min.weight = min.weight,
+    max.weight = max.weight,
+    maximal = maximal
+  )
+}
 #' @export
 #' @rdname cliques
 #' @cdocs igraph_largest_weighted_cliques
-largest_weighted_cliques <- largest_weighted_cliques_impl
+largest_weighted_cliques <- function(graph, vertex.weights = NULL) {
+  largest_weighted_cliques_impl(
+    graph = graph,
+    vertex.weights = vertex.weights
+  )
+}
 #' @export
 #' @rdname cliques
 #' @cdocs igraph_weighted_clique_number
-weighted_clique_num <- weighted_clique_number_impl
+weighted_clique_num <- function(graph, vertex.weights = NULL) {
+  weighted_clique_number_impl(
+    graph = graph,
+    vertex.weights = vertex.weights
+  )
+}
 
 #' Independent vertex sets
 #'
@@ -600,7 +638,11 @@ clique_size_counts <- function(graph, min = 0, max = 0, maximal = FALSE) {
 #' is_complete(g)
 #' g <- as_undirected(g)
 #' is_complete(g)
-is_complete <- is_complete_impl
+is_complete <- function(graph) {
+  is_complete_impl(
+    graph = graph
+  )
+}
 
 #' @rdname cliques
 #'
@@ -616,7 +658,13 @@ is_complete <- is_complete_impl
 #' @keywords graphs
 #' @export
 #' @cdocs igraph_is_clique
-is_clique <- is_clique_impl
+is_clique <- function(graph, candidate, directed = FALSE) {
+  is_clique_impl(
+    graph = graph,
+    candidate = candidate,
+    directed = directed
+  )
+}
 
 #' @rdname ivs
 #'
@@ -627,4 +675,9 @@ is_clique <- is_clique_impl
 #' @keywords graphs
 #' @export
 #' @cdocs igraph_is_independent_vertex_set
-is_ivs <- is_independent_vertex_set_impl
+is_ivs <- function(graph, candidate) {
+  is_independent_vertex_set_impl(
+    graph = graph,
+    candidate = candidate
+  )
+}

From 3d960e86d4983f0e835cb477250636d4133332c1 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 19:44:29 +0200
Subject: [PATCH 105/154] chore: Replace _impl aliases with explicit wrapper
 functions in R/centralization.R (#2360)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/centralization.R | 54 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 5 deletions(-)

diff --git a/R/centralization.R b/R/centralization.R
index acbc39fb769..e5e9d44aff2 100644
--- a/R/centralization.R
+++ b/R/centralization.R
@@ -317,7 +317,13 @@ NULL
 #' centr_eigen(g0)$centralization
 #' centr_eigen(g1)$centralization
 #' @cdocs igraph_centralization
-centralize <- centralization_impl
+centralize <- function(scores, theoretical.max = 0, normalized = TRUE) {
+  centralization_impl(
+    scores = scores,
+    theoretical.max = theoretical.max,
+    normalized = normalized
+  )
+}
 
 #' Centralize a graph according to the degrees of vertices
 #'
@@ -359,7 +365,19 @@ centralize <- centralization_impl
 #' centr_betw(g, directed = FALSE)$centralization
 #' centr_eigen(g, directed = FALSE)$centralization
 #' @cdocs igraph_centralization_degree
-centr_degree <- centralization_degree_impl
+centr_degree <- function(
+  graph,
+  mode = c("all", "out", "in", "total"),
+  loops = TRUE,
+  normalized = TRUE
+) {
+  centralization_degree_impl(
+    graph = graph,
+    mode = mode,
+    loops = loops,
+    normalized = normalized
+  )
+}
 
 #' Theoretical maximum for degree centralization
 #'
@@ -496,7 +514,13 @@ centr_betw <- function(graph, directed = TRUE, normalized = TRUE) {
 #'   `/`(centr_betw_tmax(g))
 #' centr_betw(g, normalized = TRUE)$centralization
 #' @cdocs igraph_centralization_betweenness_tmax
-centr_betw_tmax <- centralization_betweenness_tmax_impl
+centr_betw_tmax <- function(graph = NULL, nodes = 0, directed = TRUE) {
+  centralization_betweenness_tmax_impl(
+    graph = graph,
+    nodes = nodes,
+    directed = directed
+  )
+}
 
 #' Centralize a graph according to the closeness of vertices
 #'
@@ -536,7 +560,17 @@ centr_betw_tmax <- centralization_betweenness_tmax_impl
 #' centr_betw(g, directed = FALSE)$centralization
 #' centr_eigen(g, directed = FALSE)$centralization
 #' @cdocs igraph_centralization_closeness
-centr_clo <- centralization_closeness_impl
+centr_clo <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  normalized = TRUE
+) {
+  centralization_closeness_impl(
+    graph = graph,
+    mode = mode,
+    normalized = normalized
+  )
+}
 
 #' Theoretical maximum for closeness centralization
 #'
@@ -563,7 +597,17 @@ centr_clo <- centralization_closeness_impl
 #'   `/`(centr_clo_tmax(g))
 #' centr_clo(g, normalized = TRUE)$centralization
 #' @cdocs igraph_centralization_closeness_tmax
-centr_clo_tmax <- centralization_closeness_tmax_impl
+centr_clo_tmax <- function(
+  graph = NULL,
+  nodes = 0,
+  mode = c("out", "in", "all", "total")
+) {
+  centralization_closeness_tmax_impl(
+    graph = graph,
+    nodes = nodes,
+    mode = mode
+  )
+}
 
 #' Centralize a graph according to the eigenvector centrality of vertices
 #'

From 2b043ed8f8fe0a9634703d2974ec95e1b1793132 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 19:44:39 +0200
Subject: [PATCH 106/154] chore: Replace `_impl` aliases with explicit wrapper
 functions in `R/bipartite.R` (#2361)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/bipartite.R | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/R/bipartite.R b/R/bipartite.R
index 4c2cc669615..bf1dfb4673b 100644
--- a/R/bipartite.R
+++ b/R/bipartite.R
@@ -227,7 +227,12 @@ bipartite_projection <- function(
 #' @rdname bipartite_projection
 #' @export
 #' @cdocs igraph_bipartite_projection_size
-bipartite_projection_size <- bipartite_projection_size_impl
+bipartite_projection_size <- function(graph, types = NULL) {
+  bipartite_projection_size_impl(
+    graph = graph,
+    types = types
+  )
+}
 
 #' Decide whether a graph is bipartite
 #'
@@ -279,4 +284,8 @@ bipartite_projection_size <- bipartite_projection_size_impl
 #' @family bipartite
 #' @export
 #' @cdocs igraph_is_bipartite
-bipartite_mapping <- is_bipartite_impl
+bipartite_mapping <- function(graph) {
+  is_bipartite_impl(
+    graph = graph
+  )
+}

From c8aa209d727671d3b08fa96e0a27acae997a0d30 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 18:07:03 +0000
Subject: [PATCH 107/154] refactor: Replace `_impl` aliases with explicit
 wrappers in `R/trees.R` (#2373)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/trees.R | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/R/trees.R b/R/trees.R
index 810770826be..3852dac3e8c 100644
--- a/R/trees.R
+++ b/R/trees.R
@@ -96,7 +96,17 @@ is_tree <- function(
 #' @family trees
 #' @export
 #' @cdocs igraph_is_forest
-is_forest <- is_forest_impl
+is_forest <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  details = FALSE
+) {
+  is_forest_impl(
+    graph = graph,
+    mode = mode,
+    details = details
+  )
+}
 
 #' Convert a tree graph to its Prüfer sequence
 #'
@@ -123,7 +133,9 @@ is_forest <- is_forest_impl
 #' @family trees
 #' @export
 #' @cdocs igraph_to_prufer
-to_prufer <- to_prufer_impl
+to_prufer <- function(graph) {
+  to_prufer_impl(graph = graph)
+}
 
 #' Samples from the spanning trees of a graph randomly and uniformly
 #'

From a370af5c001b2ffe87339da4c11b600c5f78b1da Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 18:22:20 +0000
Subject: [PATCH 108/154] refactor: replace `are_adjacent` alias with explicit
 wrapper in `R/structure.info.R` (#2374)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/structure.info.R | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/R/structure.info.R b/R/structure.info.R
index f358d441165..fd09d1c47f8 100644
--- a/R/structure.info.R
+++ b/R/structure.info.R
@@ -59,4 +59,10 @@ are.connected <- function(graph, v1, v2) {
 #' are_adjacent(ug, 1, 2)
 #' are_adjacent(ug, 2, 1)
 #' @cdocs igraph_are_adjacent
-are_adjacent <- are_adjacent_impl
+are_adjacent <- function(graph, v1, v2) {
+  are_adjacent_impl(
+    graph = graph,
+    v1 = v1,
+    v2 = v2
+  )
+}

From d4069d06a164c2bb938c04c38053790a26d01ad0 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 20:31:59 +0200
Subject: [PATCH 109/154] refactor: Replace `_impl` aliases with explicit
 wrappers in `R/embedding.R` (#2380)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/embedding.R | 44 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/R/embedding.R b/R/embedding.R
index d88cd7b09b2..da8c4ad1557 100644
--- a/R/embedding.R
+++ b/R/embedding.R
@@ -102,7 +102,25 @@
 #' @family embedding
 #' @export
 #' @cdocs igraph_adjacency_spectral_embedding
-embed_adjacency_matrix <- adjacency_spectral_embedding_impl
+embed_adjacency_matrix <- function(
+  graph,
+  no,
+  weights = NULL,
+  which = c("lm", "la", "sa"),
+  scaled = TRUE,
+  cvec = strength(graph, weights = weights) / (vcount(graph) - 1),
+  options = arpack_defaults()
+) {
+  adjacency_spectral_embedding_impl(
+    graph = graph,
+    no = no,
+    weights = weights,
+    which = which,
+    scaled = scaled,
+    cvec = cvec,
+    options = options
+  )
+}
 
 
 #' Dimensionality selection for singular values using profile likelihood.
@@ -164,7 +182,9 @@ embed_adjacency_matrix <- adjacency_spectral_embedding_impl
 #' @family embedding
 #' @export
 #' @cdocs igraph_dim_select
-dim_select <- dim_select_impl
+dim_select <- function(sv) {
+  dim_select_impl(sv = sv)
+}
 
 
 #' Spectral Embedding of the Laplacian of a Graph
@@ -256,7 +276,25 @@ dim_select <- dim_select_impl
 #' embed <- embed_laplacian_matrix(RDP, 5)
 #' @family embedding
 #' @cdocs igraph_laplacian_spectral_embedding
-embed_laplacian_matrix <- laplacian_spectral_embedding_impl
+embed_laplacian_matrix <- function(
+  graph,
+  no,
+  weights = NULL,
+  which = c("lm", "la", "sa"),
+  type = c("default", "D-A", "DAD", "I-DAD", "OAP"),
+  scaled = TRUE,
+  options = arpack_defaults()
+) {
+  laplacian_spectral_embedding_impl(
+    graph = graph,
+    no = no,
+    weights = weights,
+    which = which,
+    type = type,
+    scaled = scaled,
+    options = options
+  )
+}
 
 
 #' Sample vectors uniformly from the surface of a sphere

From e1f1a9d1f8fb7a30c87b5a61857a159420aa0e3e Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 19:42:04 +0000
Subject: [PATCH 110/154] refactor: Replace `_impl` aliases with explicit
 wrapper functions in `R/simple.R` (#2386)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/simple.R | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/R/simple.R b/R/simple.R
index c8b41a589a1..f05142ff5a5 100644
--- a/R/simple.R
+++ b/R/simple.R
@@ -99,12 +99,28 @@ is.simple <- function(graph) {
 #' @family isomorphism
 #' @export
 #' @cdocs igraph_simplify
-simplify <- simplify_impl
+simplify <- function(
+  graph,
+  remove.multiple = TRUE,
+  remove.loops = TRUE,
+  edge.attr.comb = igraph_opt("edge.attr.comb")
+) {
+  simplify_impl(
+    graph = graph,
+    remove.multiple = remove.multiple,
+    remove.loops = remove.loops,
+    edge.attr.comb = edge.attr.comb
+  )
+}
 
 #' @export
 #' @rdname simplify
 #' @cdocs igraph_is_simple
-is_simple <- is_simple_impl
+is_simple <- function(graph) {
+  is_simple_impl(
+    graph = graph
+  )
+}
 
 #' @export
 #' @rdname simplify

From cdf45296dbf3c4ecbc295c96b246d22d388ddcb2 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:39:27 +0200
Subject: [PATCH 111/154] refactor: replace `sir <- sir_impl` alias with
 explicit wrapper (#2370)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/sir.R | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/R/sir.R b/R/sir.R
index 78ccdfa2ff2..7e5197719e9 100644
--- a/R/sir.R
+++ b/R/sir.R
@@ -109,4 +109,11 @@
 #' @family processes
 #' @export
 #' @cdocs igraph_sir
-sir <- sir_impl
+sir <- function(graph, beta, gamma, no.sim = 100) {
+  sir_impl(
+    graph = graph,
+    beta = beta,
+    gamma = gamma,
+    no.sim = no.sim
+  )
+}

From 8db9a054ab5e528cdcac728983aa6cbbcf23ff11 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:39:43 +0200
Subject: [PATCH 112/154] refactor: Replace `_impl` aliases with explicit
 wrapper functions in `R/structural-properties.R` (#2372)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/structural-properties.R | 123 ++++++++++++++++++++++++++++++++++----
 man/k_shortest_paths.Rd   |   6 +-
 2 files changed, 113 insertions(+), 16 deletions(-)

diff --git a/R/structural-properties.R b/R/structural-properties.R
index 8339299a3a0..21f26dd2e48 100644
--- a/R/structural-properties.R
+++ b/R/structural-properties.R
@@ -1489,7 +1489,25 @@ all_shortest_paths <- function(
 #' @seealso [shortest_paths()], [all_shortest_paths()]
 #' @keywords graphs
 #' @cdocs igraph_get_k_shortest_paths
-k_shortest_paths <- get_k_shortest_paths_impl
+k_shortest_paths <- function(
+  graph,
+  from,
+  to,
+  k,
+  ...,
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
+  get_k_shortest_paths_impl(
+    graph = graph,
+    from = from,
+    to = to,
+    k = k,
+    ...,
+    weights = weights,
+    mode = mode
+  )
+}
 
 #' In- or out- component of a vertex
 #'
@@ -1959,7 +1977,17 @@ constraint <- function(graph, nodes = V(graph), weights = NULL) {
 #' reciprocity(g)
 #'
 #' @cdocs igraph_reciprocity
-reciprocity <- reciprocity_impl
+reciprocity <- function(
+  graph,
+  ignore.loops = TRUE,
+  mode = c("default", "ratio")
+) {
+  reciprocity_impl(
+    graph = graph,
+    ignore.loops = ignore.loops,
+    mode = mode
+  )
+}
 
 
 #' Graph density
@@ -2000,7 +2028,12 @@ reciprocity <- reciprocity_impl
 #' edge_density(simplify(g), loops = FALSE) # this is also right, but different
 #'
 #' @cdocs igraph_density
-edge_density <- density_impl
+edge_density <- function(graph, loops = FALSE) {
+  density_impl(
+    graph = graph,
+    loops = loops
+  )
+}
 
 #' @rdname ego
 #' @export
@@ -2313,7 +2346,17 @@ topo_sort <- function(graph, mode = c("out", "all", "in")) {
 #' feedback_arc_set(g)
 #' feedback_arc_set(g, algo = "approx_eades")
 #' @cdocs igraph_feedback_arc_set
-feedback_arc_set <- feedback_arc_set_impl
+feedback_arc_set <- function(
+  graph,
+  weights = NULL,
+  algo = c("approx_eades", "exact_ip")
+) {
+  feedback_arc_set_impl(
+    graph = graph,
+    weights = weights,
+    algo = algo
+  )
+}
 
 #' Finding a feedback vertex set in a graph
 #'
@@ -2344,7 +2387,13 @@ feedback_arc_set <- feedback_arc_set_impl
 #' g <- make_lattice(c(3,3))
 #' feedback_vertex_set(g)
 #' @cdocs igraph_feedback_vertex_set
-feedback_vertex_set <- feedback_vertex_set_impl
+feedback_vertex_set <- function(graph, weights = NULL, algo = c("exact_ip")) {
+  feedback_vertex_set_impl(
+    graph = graph,
+    weights = weights,
+    algo = algo
+  )
+}
 
 #' Girth of a graph
 #'
@@ -2471,23 +2520,46 @@ girth <- function(graph, circle = TRUE) {
 #' E(g)$weight
 #'
 #' @cdocs igraph_is_multiple
-which_multiple <- is_multiple_impl
+which_multiple <- function(graph, eids = E(graph)) {
+  is_multiple_impl(
+    graph = graph,
+    eids = eids
+  )
+}
 #' @rdname which_multiple
 #' @export
 #' @cdocs igraph_has_multiple
-any_multiple <- has_multiple_impl
+any_multiple <- function(graph) {
+  has_multiple_impl(
+    graph = graph
+  )
+}
 #' @rdname which_multiple
 #' @export
 #' @cdocs igraph_count_multiple
-count_multiple <- count_multiple_impl
+count_multiple <- function(graph, eids = E(graph)) {
+  count_multiple_impl(
+    graph = graph,
+    eids = eids
+  )
+}
 #' @rdname which_multiple
 #' @export
 #' @cdocs igraph_is_loop
-which_loop <- is_loop_impl
+which_loop <- function(graph, eids = E(graph)) {
+  is_loop_impl(
+    graph = graph,
+    eids = eids
+  )
+}
 #' @rdname which_multiple
 #' @export
 #' @cdocs igraph_has_loop
-any_loop <- has_loop_impl
+any_loop <- function(graph) {
+  has_loop_impl(
+    graph = graph
+  )
+}
 
 
 #' Breadth-first search
@@ -3074,7 +3146,12 @@ components <- function(graph, mode = c("weak", "strong")) {
 #' @rdname components
 #' @export
 #' @cdocs igraph_is_connected
-is_connected <- is_connected_impl
+is_connected <- function(graph, mode = c("weak", "strong")) {
+  is_connected_impl(
+    graph = graph,
+    mode = mode
+  )
+}
 
 #' @rdname components
 #' @export
@@ -3449,7 +3526,13 @@ max_bipartite_match <- function(
 #' @family structural.properties
 #' @export
 #' @cdocs igraph_is_mutual
-which_mutual <- is_mutual_impl
+which_mutual <- function(graph, eids = E(graph), loops = TRUE) {
+  is_mutual_impl(
+    graph = graph,
+    eids = eids,
+    loops = loops
+  )
+}
 
 
 #' Average nearest neighbor degree
@@ -3527,4 +3610,18 @@ which_mutual <- is_mutual_impl
 #' @family structural.properties
 #' @export
 #' @cdocs igraph_avg_nearest_neighbor_degree
-knn <- avg_nearest_neighbor_degree_impl
+knn <- function(
+  graph,
+  vids = V(graph),
+  mode = c("all", "out", "in", "total"),
+  neighbor.degree.mode = c("all", "out", "in", "total"),
+  weights = NULL
+) {
+  avg_nearest_neighbor_degree_impl(
+    graph = graph,
+    vids = vids,
+    mode = mode,
+    neighbor.degree.mode = neighbor.degree.mode,
+    weights = weights
+  )
+}
diff --git a/man/k_shortest_paths.Rd b/man/k_shortest_paths.Rd
index 177d4270c35..c136dc00977 100644
--- a/man/k_shortest_paths.Rd
+++ b/man/k_shortest_paths.Rd
@@ -8,8 +8,8 @@ k_shortest_paths(
   graph,
   from,
   to,
-  ...,
   k,
+  ...,
   weights = NULL,
   mode = c("out", "in", "all", "total")
 )
@@ -21,11 +21,11 @@ k_shortest_paths(
 
 \item{to}{The target vertex of the shortest paths.}
 
-\item{...}{These dots are for future extensions and must be empty.}
-
 \item{k}{The number of paths to find. They will be returned in order of
 increasing length.}
 
+\item{...}{These dots are for future extensions and must be empty.}
+
 \item{weights}{Possibly a numeric vector giving edge weights. If this is
 \code{NULL} and the graph has a \code{weight} edge attribute, then the
 attribute is used. If this is \code{NA} then no weights are used (even if

From c9bf72a00cb587f9e08521fa1472406d9f0b5ab5 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:40:01 +0200
Subject: [PATCH 113/154] refactor: Replace `_impl` alias with explicit wrapper
 in `R/layout.R` (#2382)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/layout.R | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/R/layout.R b/R/layout.R
index 81f184843cc..53aa268cee4 100644
--- a/R/layout.R
+++ b/R/layout.R
@@ -3014,4 +3014,9 @@ drl_defaults <- list(
 #' l2 <- align_layout(g,l1)
 #' plot(g, layout = l1)
 #' plot(g, layout = l2)
-align_layout <- layout_align_impl
+align_layout <- function(graph, layout) {
+  layout_align_impl(
+    graph = graph,
+    layout = layout
+  )
+}

From 9a99bbbe3eb12d832d14d75a3fb6e4798121f54a Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:40:23 +0200
Subject: [PATCH 114/154] refactor: Replace `_impl` aliases with explicit
 wrapper functions in `R/make.R` (#2384)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/make.R | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/R/make.R b/R/make.R
index 0fb6b6d2b89..3d607cee373 100644
--- a/R/make.R
+++ b/R/make.R
@@ -2111,7 +2111,13 @@ make_tree <- function(n, children = 2, mode = c("out", "in", "undirected")) {
 #'
 #' @export
 #' @cdocs igraph_tree_game
-sample_tree <- tree_game_impl
+sample_tree <- function(n, directed = FALSE, method = c("lerw", "prufer")) {
+  tree_game_impl(
+    n = n,
+    directed = directed,
+    method = method
+  )
+}
 
 #' @rdname make_tree
 #' @param ... Passed to `make_tree()` or `sample_tree()`.
@@ -2146,7 +2152,11 @@ tree <- function(...) {
 #' @family trees
 #' @export
 #' @cdocs igraph_from_prufer
-make_from_prufer <- from_prufer_impl
+make_from_prufer <- function(prufer) {
+  from_prufer_impl(
+    prufer = prufer
+  )
+}
 
 #' @rdname make_from_prufer
 #' @param ... Passed to `make_from_prufer()`
@@ -2721,7 +2731,19 @@ graph_from_lcf <- function(
 #' g5 <- realize_degseq(degs, allowed.edge.types = "multi")
 #' all(degree(g5) == degs)
 #' @cdocs igraph_realize_degree_sequence
-realize_degseq <- realize_degree_sequence_impl
+realize_degseq <- function(
+  out.deg,
+  in.deg = NULL,
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  method = c("smallest", "largest", "index")
+) {
+  realize_degree_sequence_impl(
+    out.deg = out.deg,
+    in.deg = in.deg,
+    allowed.edge.types = allowed.edge.types,
+    method = method
+  )
+}
 
 
 #' Creating a bipartite graph from two degree sequences, deterministically

From f64ac17b5cfcf25a6e39cfdf0041f53e5cd7c6d0 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:40:36 +0200
Subject: [PATCH 115/154] refactor: Replace `_impl` aliases with explicit
 wrapper functions in `R/triangles.R` (#2369)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/triangles.R | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/R/triangles.R b/R/triangles.R
index 00bf6fc7207..1745ab62254 100644
--- a/R/triangles.R
+++ b/R/triangles.R
@@ -89,9 +89,18 @@ adjacent.triangles <- function(graph, vids = V(graph)) {
 #' @export
 #' @rdname count_triangles
 #' @cdocs igraph_list_triangles
-triangles <- list_triangles_impl
+triangles <- function(graph) {
+  list_triangles_impl(
+    graph = graph
+  )
+}
 
 #' @export
 #' @rdname count_triangles
 #' @cdocs igraph_count_adjacent_triangles
-count_triangles <- count_adjacent_triangles_impl
+count_triangles <- function(graph, vids = V(graph)) {
+  count_adjacent_triangles_impl(
+    graph = graph,
+    vids = vids
+  )
+}

From a0cc8e5c3a3fe13b68aa9a2569259d7b6bfcdfcf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 25 Oct 2025 23:28:43 +0200
Subject: [PATCH 116/154] Sync meta

---
 CITATION.cff | 8 ++++----
 DESCRIPTION  | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/CITATION.cff b/CITATION.cff
index f6e2ebcf333..02f2e59d6ec 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -2,13 +2,13 @@
 # CITATION file created with {cffr} R package
 # See also: https://docs.ropensci.org/cffr/
 # --------------------------------------------
-
+ 
 cff-version: 1.2.0
 message: 'To cite package "igraph" in publications use:'
 type: software
 license: GPL-2.0-or-later
 title: 'igraph: Network Analysis and Visualization'
-version: 2.1.99
+version: 2.2.1
 identifiers:
 - type: doi
   value: 10.32614/CRAN.package.igraph
@@ -135,7 +135,7 @@ references:
   - family-names: Salmon
     given-names: Maëlle
   year: '2025'
-  notes: R package version 2.1.99
+  notes: R package version 2.2.1
   doi: 10.5281/zenodo.7682609
   url: https://CRAN.R-project.org/package=igraph
 - type: software
@@ -219,7 +219,7 @@ references:
     email: stefan@stefanbache.dk
   - family-names: Wickham
     given-names: Hadley
-    email: hadley@rstudio.com
+    email: hadley@posit.co
   year: '2025'
   doi: 10.32614/CRAN.package.magrittr
 - type: software
diff --git a/DESCRIPTION b/DESCRIPTION
index 26e1e2235d3..191bdd4d860 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
 Package: igraph
 Title: Network Analysis and Visualization
-Version: 2.1.4.9079
+Version: 2.2.1
 Authors@R: c(
     person("Gábor", "Csárdi", , "csardi.gabor@gmail.com", role = "aut",
            comment = c(ORCID = "0000-0001-7098-9676")),

From 33664b28fe18e102ef3d3194318730c4142cb364 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 21:27:04 +0000
Subject: [PATCH 117/154] Replace _impl aliases in R/hrg.R (#2381)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/hrg.R | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/R/hrg.R b/R/hrg.R
index b699ab6412f..7532b814e1b 100644
--- a/R/hrg.R
+++ b/R/hrg.R
@@ -301,7 +301,19 @@ fit_hrg <- function(graph, hrg = NULL, start = FALSE, steps = 0) {
 #' @family hierarchical random graph functions
 #' @export
 #' @cdocs igraph_hrg_consensus
-consensus_tree <- hrg_consensus_impl
+consensus_tree <- function(
+  graph,
+  hrg = NULL,
+  start = FALSE,
+  num.samples = 10000
+) {
+  hrg_consensus_impl(
+    graph = graph,
+    hrg = hrg,
+    start = start,
+    num.samples = num.samples
+  )
+}
 
 
 #' Create a hierarchical random graph from an igraph graph
@@ -319,7 +331,12 @@ consensus_tree <- hrg_consensus_impl
 #' @family hierarchical random graph functions
 #' @export
 #' @cdocs igraph_hrg_create
-hrg <- hrg_create_impl
+hrg <- function(graph, prob) {
+  hrg_create_impl(
+    graph = graph,
+    prob = prob
+  )
+}
 
 
 #' Create an igraph graph from a hierarchical random graph model

From a709d4e33a01299db50197ffde68eb1ec6bd1f05 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 21:31:04 +0000
Subject: [PATCH 118/154] Replace `_impl` aliases with explicit wrapper
 functions in `community.R` (#2391)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/community.R | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/R/community.R b/R/community.R
index c4f9eff03a7..ba92e3afe7a 100644
--- a/R/community.R
+++ b/R/community.R
@@ -3246,7 +3246,17 @@ communities <- groups.communities
 #' @export
 #' @family functions for manipulating graph structure
 #' @cdocs igraph_contract_vertices
-contract <- contract_vertices_impl
+contract <- function(
+  graph,
+  mapping,
+  vertex.attr.comb = igraph_opt("vertex.attr.comb")
+) {
+  contract_vertices_impl(
+    graph = graph,
+    mapping = mapping,
+    vertex.attr.comb = vertex.attr.comb
+  )
+}
 
 
 #' Voronoi partitioning of a graph
@@ -3292,4 +3302,20 @@ contract <- contract_vertices_impl
 #' @export
 #' @family community
 #' @cdocs igraph_voronoi
-voronoi_cells <- voronoi_impl
+voronoi_cells <- function(
+  graph,
+  generators,
+  ...,
+  weights = NULL,
+  mode = c("out", "in", "all", "total"),
+  tiebreaker = c("random", "first", "last")
+) {
+  voronoi_impl(
+    graph = graph,
+    generators = generators,
+    ...,
+    weights = weights,
+    mode = mode,
+    tiebreaker = tiebreaker
+  )
+}

From 621825461c19f67ab0156d03525fb96ecf36f16f Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 21:57:50 +0000
Subject: [PATCH 119/154] Replace `_impl` aliases in `R/conversion.R` (#2392)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/conversion.R | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/R/conversion.R b/R/conversion.R
index 29384d45619..534d772770b 100644
--- a/R/conversion.R
+++ b/R/conversion.R
@@ -600,7 +600,15 @@ as_edgelist <- function(graph, names = TRUE) {
 #' print(ug4, e = TRUE)
 #'
 #' @cdocs igraph_to_directed
-as_directed <- to_directed_impl
+as_directed <- function(
+  graph,
+  mode = c("mutual", "arbitrary", "random", "acyclic")
+) {
+  to_directed_impl(
+    graph = graph,
+    mode = mode
+  )
+}
 
 #' @rdname as_directed
 #' @param edge.attr.comb Specifies what to do with edge attributes, if
@@ -1267,7 +1275,17 @@ as_data_frame <- function(x, what = c("edges", "vertices", "both")) {
 #' @family conversion
 #' @export
 #' @cdocs igraph_adjlist
-graph_from_adj_list <- adjlist_impl
+graph_from_adj_list <- function(
+  adjlist,
+  mode = c("out", "in", "all", "total"),
+  duplicate = TRUE
+) {
+  adjlist_impl(
+    adjlist = adjlist,
+    mode = mode,
+    duplicate = duplicate
+  )
+}
 
 
 #' Convert a graph to a long data frame

From 97be47e09dc3d392c82a40b6c266ff0f95a86ebe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 00:00:01 +0200
Subject: [PATCH 120/154] ci: Update status directly for Copilot

---
 .github/workflows/R-CMD-check.yaml | 34 +++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index 301322c8d1f..00c76772683 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -68,10 +68,13 @@ jobs:
           ref: ${{ inputs.ref }}
 
       - name: Update status for rcc
+        if: github.actor != 'github-copilot[bot]'
         # FIXME: Wrap into action
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         run: |
+          echo "Actor: ${{ github.actor }}"
+
           # Check status of this workflow
           state="pending"
           sha=${{ inputs.ref }}
@@ -171,7 +174,7 @@ jobs:
 
       - name: Update status for rcc
         # FIXME: Wrap into action
-        if: always()
+        if: always() && (github.actor != 'github-copilot[bot]')
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         run: |
@@ -206,6 +209,35 @@ jobs:
             -f "state=${state}" -f "target_url=${html_url}" -f "description=${description}" -f "context=rcc"
         shell: bash
 
+      - name: Update status for rcc (Copilot)
+        # Update status directly when triggered by Copilot or bots, since they can't dispatch workflows
+        if: always() && (github.actor == 'github-copilot[bot]')
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          # Check status of this workflow
+          state="pending"
+          sha=${{ inputs.ref }}
+          if [ -z "${sha}" ]; then
+            sha=${{ github.sha }}
+          fi
+          sha=$(git rev-parse ${sha})
+
+          html_url=$(gh api \
+            -H "Accept: application/vnd.github+json" \
+            -H "X-GitHub-Api-Version: 2022-11-28" \
+            repos/${{ github.repository }}/actions/runs/${{ github.run_id }} | jq -r .html_url)
+
+          description="${{ github.workflow }} / ${{ github.job }}"
+
+          gh api \
+            --method POST \
+            -H "Accept: application/vnd.github+json" \
+            -H "X-GitHub-Api-Version: 2022-11-28" \
+            repos/${{ github.repository }}/statuses/${sha} \
+            -f "state=${state}" -f "target_url=${html_url}" -f "description=${description}" -f "context=rcc"
+        shell: bash
+
   rcc-smoke-check-matrix:
     runs-on: ubuntu-24.04
 

From daecf33df710ffccb6b3c0da9d991ad776c6e7c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 00:05:51 +0200
Subject: [PATCH 121/154] ci: Install air for Copilot

---
 .github/workflows/copilot-setup-steps.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.github/workflows/copilot-setup-steps.yaml b/.github/workflows/copilot-setup-steps.yaml
index a604762abbd..766b03a6a30 100644
--- a/.github/workflows/copilot-setup-steps.yaml
+++ b/.github/workflows/copilot-setup-steps.yaml
@@ -46,3 +46,6 @@ jobs:
         run: |
           UserNM=true R CMD INSTALL . || true
         shell: bash
+
+      - name: Install air
+        uses: posit-dev/setup-air@v1

From 3af7806743673c7424c99f00d57111f0fabb010f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 21:53:18 +0000
Subject: [PATCH 122/154] Replace first 3 _impl aliases with explicit wrappers

Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/topology.R | 52 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/R/topology.R b/R/topology.R
index a8d50883863..7eb38ba0b66 100644
--- a/R/topology.R
+++ b/R/topology.R
@@ -472,13 +472,59 @@ isomorphic <- function(
 
 #' @export
 #' @cdocs igraph_isomorphic_bliss
-graph.isomorphic.bliss <- isomorphic_bliss_impl
+graph.isomorphic.bliss <- function(
+  graph1,
+  graph2,
+  colors1 = NULL,
+  colors2 = NULL,
+  sh = c("fm", "f", "fs", "fl", "flm", "fsm")
+) {
+  isomorphic_bliss_impl(
+    graph1 = graph1,
+    graph2 = graph2,
+    colors1 = colors1,
+    colors2 = colors2,
+    sh = sh
+  )
+}
 #' @export
 #' @cdocs igraph_isomorphic_vf2
-graph.isomorphic.vf2 <- isomorphic_vf2_impl
+graph.isomorphic.vf2 <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
+  isomorphic_vf2_impl(
+    graph1 = graph1,
+    graph2 = graph2,
+    vertex.color1 = vertex.color1,
+    vertex.color2 = vertex.color2,
+    edge.color1 = edge.color1,
+    edge.color2 = edge.color2
+  )
+}
 #' @export
 #' @cdocs igraph_subisomorphic_vf2
-graph.subisomorphic.vf2 <- subisomorphic_vf2_impl
+graph.subisomorphic.vf2 <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
+  subisomorphic_vf2_impl(
+    graph1 = graph1,
+    graph2 = graph2,
+    vertex.color1 = vertex.color1,
+    vertex.color2 = vertex.color2,
+    edge.color1 = edge.color1,
+    edge.color2 = edge.color2
+  )
+}
 
 #' @export
 #' @rdname isomorphic

From 9694f9febab2c2a66a5fd7f8beb331e2e1a1a18e Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:31:23 +0000
Subject: [PATCH 123/154] Replace `_impl` aliases in `R/degseq.R` (#2389)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/degseq.R | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/R/degseq.R b/R/degseq.R
index 114d5e66576..69e646e79f0 100644
--- a/R/degseq.R
+++ b/R/degseq.R
@@ -140,4 +140,14 @@ is_degseq <- function(out.deg, in.deg = NULL) {
 #' is_graphical(degree(g))
 #' @export
 #' @cdocs igraph_is_graphical
-is_graphical <- is_graphical_impl
+is_graphical <- function(
+  out.deg,
+  in.deg = NULL,
+  allowed.edge.types = c("simple", "loops", "multi", "all")
+) {
+  is_graphical_impl(
+    out.deg = out.deg,
+    in.deg = in.deg,
+    allowed.edge.types = allowed.edge.types
+  )
+}

From 2cf76f05f49c08c07124f846f88a2ebddfbb714b Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:32:48 +0000
Subject: [PATCH 124/154] Replace `_impl` aliases in `R/paths.R` (#2387)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/paths.R | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/R/paths.R b/R/paths.R
index 4a5aff74546..c7ccd32f42c 100644
--- a/R/paths.R
+++ b/R/paths.R
@@ -159,7 +159,9 @@ all_simple_paths <- function(
 #' @family structural.properties
 #' @export
 #' @cdocs igraph_is_dag
-is_dag <- is_dag_impl
+is_dag <- function(graph) {
+  is_dag_impl(graph = graph)
+}
 
 #' Acyclic graphs
 #'
@@ -182,7 +184,9 @@ is_dag <- is_dag_impl
 #' @family structural.properties
 #' @export
 #' @cdocs igraph_is_acyclic
-is_acyclic <- is_acyclic_impl
+is_acyclic <- function(graph) {
+  is_acyclic_impl(graph = graph)
+}
 
 #' Maximum cardinality search
 #'
@@ -239,7 +243,9 @@ is_acyclic <- is_acyclic_impl
 #' is_chordal(g2, fillin = TRUE)
 #' @family chordal
 #' @cdocs igraph_maximum_cardinality_search
-max_cardinality <- maximum_cardinality_search_impl
+max_cardinality <- function(graph) {
+  maximum_cardinality_search_impl(graph = graph)
+}
 
 
 #' Eccentricity of the vertices in a graph
@@ -377,11 +383,25 @@ radius <- function(
 #'
 #' @export
 #' @cdocs igraph_graph_center
-graph_center <- graph_center_impl
+graph_center <- function(
+  graph,
+  ...,
+  weights = NULL,
+  mode = c("all", "out", "in", "total")
+) {
+  graph_center_impl(
+    graph = graph,
+    ...,
+    weights = weights,
+    mode = mode
+  )
+}
 
 #' @rdname distances
 #' @param directed Whether to consider directed paths in directed graphs,
 #'   this argument is ignored for undirected graphs.
 #' @export
 #' @cdocs igraph_path_length_hist
-distance_table <- path_length_hist_impl
+distance_table <- function(graph, directed = TRUE) {
+  path_length_hist_impl(graph = graph, directed = directed)
+}

From b9483672a009c65ec08bbb39e0a99e2091a55d3e Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 22:39:37 +0000
Subject: [PATCH 125/154] [WIP] Replace _impl aliases with explicit wrapper
 functions (#2393)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/efficiency.R | 38 +++++++++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/R/efficiency.R b/R/efficiency.R
index c650c7183ed..bb7e7a0df23 100644
--- a/R/efficiency.R
+++ b/R/efficiency.R
@@ -67,14 +67,46 @@
 #' global_efficiency(g)
 #' average_local_efficiency(g)
 #' @cdocs igraph_global_efficiency
-global_efficiency <- global_efficiency_impl
+global_efficiency <- function(graph, weights = NULL, directed = TRUE) {
+  global_efficiency_impl(
+    graph = graph,
+    weights = weights,
+    directed = directed
+  )
+}
 
 #' @rdname global_efficiency
 #' @export
 #' @cdocs igraph_local_efficiency
-local_efficiency <- local_efficiency_impl
+local_efficiency <- function(
+  graph,
+  vids = V(graph),
+  weights = NULL,
+  directed = TRUE,
+  mode = c("all", "out", "in", "total")
+) {
+  local_efficiency_impl(
+    graph = graph,
+    vids = vids,
+    weights = weights,
+    directed = directed,
+    mode = mode
+  )
+}
 
 #' @rdname global_efficiency
 #' @export
 #' @cdocs igraph_average_local_efficiency
-average_local_efficiency <- average_local_efficiency_impl
+average_local_efficiency <- function(
+  graph,
+  weights = NULL,
+  directed = TRUE,
+  mode = c("all", "out", "in", "total")
+) {
+  average_local_efficiency_impl(
+    graph = graph,
+    weights = weights,
+    directed = directed,
+    mode = mode
+  )
+}

From 5d34d1892df5a66919f12c56cf643279bceb6b4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 01:11:02 +0200
Subject: [PATCH 126/154] Deps

---
 R/aaa-auto.R                    | 27 ++++++++++++++++-----------
 src/cpp11.cpp                   |  4 ++--
 src/rinterface.c                |  9 +++++++--
 tools/stimulus/functions-R.yaml | 20 +++++++++++++++-----
 4 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index 058588041a6..d8e3dfa2d15 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -369,7 +369,7 @@ full_bipartite_impl <- function(n1, n2, directed=FALSE, mode=c("all", "out", "in
   # Function call
   res <- .Call(R_igraph_full_bipartite, n1, n2, directed, mode)
   if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
-    names(res$types) <- vertex_attr(res$graph, "name", )
+    names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
@@ -2593,7 +2593,7 @@ bipartite_projection_size_impl <- function(graph, types=NULL) {
 
 create_bipartite_impl <- function(types, edges, directed=FALSE) {
   # Argument checks
-  types <- handle_vertex_type_arg(types, %I1%)
+  types <- handle_vertex_type_arg(types, graph)
   edges <- as.numeric(edges)
   directed <- as.logical(directed)
 
@@ -2629,8 +2629,8 @@ weighted_biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all",
   on.exit( .Call(R_igraph_finalizer) )
   # Function call
   res <- .Call(R_igraph_weighted_biadjacency, biadjmatrix, directed, mode)
-  if (igraph_opt("add.vertex.names") && is_named(graph)) {
-    names(res$types) <- vertex_attr(graph, "name", )
+  if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
+    names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
@@ -2668,18 +2668,23 @@ is_bipartite_impl <- function(graph) {
   res
 }
 
-bipartite_game_gnp_impl <- function(n1, n2, p, directed=FALSE, mode=c("all", "out", "in", "total")) {
+bipartite_game_gnp_impl <- function(n1, n2, p, directed=FALSE, mode=c("all", "out", "in", "total"), allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) {
   # Argument checks
   n1 <- as.numeric(n1)
   n2 <- as.numeric(n2)
   p <- as.numeric(p)
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
+  allowed.edge.types <- switch_igraph_arg(allowed.edge.types,
+    "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
+  edge.labeled <- as.logical(edge.labeled)
 
   on.exit( .Call(R_igraph_finalizer) )
   # Function call
-  res <- .Call(R_igraph_bipartite_game_gnp, n1, n2, p, directed, mode)
-
+  res <- .Call(R_igraph_bipartite_game_gnp, n1, n2, p, directed, mode, allowed.edge.types, edge.labeled)
+  if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
+    names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
+  }
   res
 }
 
@@ -2697,8 +2702,8 @@ bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou
   on.exit( .Call(R_igraph_finalizer) )
   # Function call
   res <- .Call(R_igraph_bipartite_game_gnm, n1, n2, m, directed, mode, allowed.edge.types, edge.labeled)
-  if (igraph_opt("add.vertex.names") && is_named()) {
-    names(res$types) <- vertex_attr(, "name", )
+  if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
+    names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
@@ -2714,8 +2719,8 @@ bipartite_iea_game_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou
   on.exit( .Call(R_igraph_finalizer) )
   # Function call
   res <- .Call(R_igraph_bipartite_iea_game, n1, n2, m, directed, mode)
-  if (igraph_opt("add.vertex.names") && is_named(graph)) {
-    names(res$types) <- vertex_attr(graph, "name", )
+  if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
+    names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
diff --git a/src/cpp11.cpp b/src/cpp11.cpp
index fafa5d92d36..187a7c19c1b 100644
--- a/src/cpp11.cpp
+++ b/src/cpp11.cpp
@@ -62,7 +62,7 @@ extern SEXP R_igraph_biadjacency(SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_bibcoupling(SEXP, SEXP);
 extern SEXP R_igraph_biconnected_components(SEXP);
 extern SEXP R_igraph_bipartite_game_gnm(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
-extern SEXP R_igraph_bipartite_game_gnp(SEXP, SEXP, SEXP, SEXP, SEXP);
+extern SEXP R_igraph_bipartite_game_gnp(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_bipartite_iea_game(SEXP, SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_bipartite_projection(SEXP, SEXP, SEXP, SEXP);
 extern SEXP R_igraph_bipartite_projection_size(SEXP, SEXP);
@@ -545,7 +545,7 @@ 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_gnm",                         (DL_FUNC) &R_igraph_bipartite_game_gnm,                          7},
-    {"R_igraph_bipartite_game_gnp",                         (DL_FUNC) &R_igraph_bipartite_game_gnp,                          5},
+    {"R_igraph_bipartite_game_gnp",                         (DL_FUNC) &R_igraph_bipartite_game_gnp,                          7},
     {"R_igraph_bipartite_iea_game",                         (DL_FUNC) &R_igraph_bipartite_iea_game,                          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},
diff --git a/src/rinterface.c b/src/rinterface.c
index c1863699877..40edca651a7 100644
--- a/src/rinterface.c
+++ b/src/rinterface.c
@@ -6374,7 +6374,7 @@ SEXP R_igraph_is_bipartite(SEXP graph) {
 /*-------------------------------------------/
 / igraph_bipartite_game_gnp                  /
 /-------------------------------------------*/
-SEXP R_igraph_bipartite_game_gnp(SEXP n1, SEXP n2, SEXP p, SEXP directed, SEXP mode) {
+SEXP R_igraph_bipartite_game_gnp(SEXP n1, SEXP n2, SEXP p, SEXP directed, SEXP mode, SEXP allowed_edge_types, SEXP edge_labeled) {
                                         /* Declarations */
   igraph_t c_graph;
   igraph_vector_bool_t c_types;
@@ -6383,6 +6383,8 @@ SEXP R_igraph_bipartite_game_gnp(SEXP n1, SEXP n2, SEXP p, SEXP directed, SEXP m
   igraph_real_t c_p;
   igraph_bool_t c_directed;
   igraph_neimode_t c_mode;
+  igraph_edge_type_sw_t c_allowed_edge_types;
+  igraph_bool_t c_edge_labeled;
   SEXP graph;
   SEXP types;
 
@@ -6399,9 +6401,12 @@ SEXP R_igraph_bipartite_game_gnp(SEXP n1, SEXP n2, SEXP p, SEXP directed, SEXP m
   IGRAPH_R_CHECK_BOOL(directed);
   c_directed = LOGICAL(directed)[0];
   c_mode = (igraph_neimode_t) Rf_asInteger(mode);
+  c_allowed_edge_types = (igraph_edge_type_sw_t) Rf_asInteger(allowed_edge_types);
+  IGRAPH_R_CHECK_BOOL(edge_labeled);
+  c_edge_labeled = LOGICAL(edge_labeled)[0];
                                         /* Call igraph */
   GetRNGstate();
-  IGRAPH_R_CHECK(igraph_bipartite_game_gnp(&c_graph, &c_types, c_n1, c_n2, c_p, c_directed, c_mode));
+  IGRAPH_R_CHECK(igraph_bipartite_game_gnp(&c_graph, &c_types, c_n1, c_n2, c_p, c_directed, c_mode, c_allowed_edge_types, c_edge_labeled));
   PutRNGstate();
 
                                         /* Convert output */
diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml
index c745f0ab52a..90d41f6233e 100644
--- a/tools/stimulus/functions-R.yaml
+++ b/tools/stimulus/functions-R.yaml
@@ -519,16 +519,26 @@ igraph_is_bipartite:
     DEPS: type ON graph V(graph)
 
 igraph_bipartite_game_gnp:
-    PARAMS: |-
-        OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES_UNNAMED types,
-        INTEGER n1, INTEGER n2, REAL p, BOOLEAN directed=False,
-        NEIMODE mode=ALL
+    DEPS: types ON res$graph V(res$graph)
 
 igraph_bipartite_game:
     IGNORE: RR, RC
 
+igraph_bipartite_game_gnm:
+    DEPS: types ON res$graph V(res$graph)
+
+igraph_bipartite_iea_game:
+    DEPS: types ON res$graph V(res$graph)
+
+igraph_create_bipartite:
+    DEPS: types ON graph
+
+igraph_weighted_biadjacency:
+    DEPS: |-
+        weights ON res$graph E(res$graph), types ON res$graph V(res$graph)
+
 igraph_full_bipartite:
-    DEPS: types ON res$graph
+    DEPS: types ON res$graph V(res$graph)
 
 
 #######################################

From cd19f6b5cdec6686e28795966b41727410ebf6f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 01:27:47 +0200
Subject: [PATCH 127/154] Adapt implementation

---
 src/rinterface_extra.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c
index c64becf90cc..1f6d7763ffb 100644
--- a/src/rinterface_extra.c
+++ b/src/rinterface_extra.c
@@ -2672,7 +2672,7 @@ SEXP R_igraph_matrix_to_SEXP(const igraph_matrix_t *m) {
   }
 
   PROTECT(result=NEW_NUMERIC(igraph_matrix_size(m)));
-  igraph_matrix_copy_to(m, REAL(result));
+  igraph_matrix_copy_to(m, REAL(result), IGRAPH_COLUMN_MAJOR);
   PROTECT(dim=NEW_INTEGER(2));
   INTEGER(dim)[0] = (int) nrow;
   INTEGER(dim)[1] = (int) ncol;
@@ -2739,7 +2739,7 @@ SEXP R_igraph_matrix_complex_to_SEXP(const igraph_matrix_complex_t *m) {
   }
 
   PROTECT(result=NEW_COMPLEX(igraph_matrix_complex_size(m)));
-  igraph_matrix_complex_copy_to(m, (igraph_complex_t*) COMPLEX(result));
+  igraph_matrix_complex_copy_to(m, (igraph_complex_t*) COMPLEX(result), IGRAPH_COLUMN_MAJOR);
   PROTECT(dim=NEW_INTEGER(2));
   INTEGER(dim)[0] = (int) nrow;
   INTEGER(dim)[1] = (int) ncol;
@@ -3269,7 +3269,7 @@ SEXP R_igraph_sparsemat_to_SEXP_cc(const igraph_sparsemat_t *sp) {
     igraph_vector_t x;
     R_SEXP_to_vector_int_copy(VECTOR_ELT(res, 2), &p);
     R_SEXP_to_vector_int_copy(VECTOR_ELT(res, 3), &i);
-    igraph_vector_view(&x, REAL(VECTOR_ELT(res, 4)), nz);
+    x = igraph_vector_view(REAL(VECTOR_ELT(res, 4)), nz);
     igraph_sparsemat_getelements_sorted(sp, &i, &p, &x);
   }
 
@@ -3335,7 +3335,7 @@ void R_igraph_SEXP_to_vector_list(SEXP vectorlist, igraph_vector_list_t *list) {
   for (igraph_integer_t i=0; i
Date: Sun, 26 Oct 2025 01:29:09 +0200
Subject: [PATCH 128/154] Type

---
 src/rinterface.c             |  9 +++++++--
 tools/stimulus/types-RC.yaml | 15 +++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/rinterface.c b/src/rinterface.c
index 40edca651a7..cfdc44f1eee 100644
--- a/src/rinterface.c
+++ b/src/rinterface.c
@@ -13217,15 +13217,20 @@ SEXP R_igraph_spatial_edge_lengths(SEXP graph, SEXP points, SEXP METRIC) {
   SEXP r_result;
                                         /* Convert input */
   R_SEXP_to_igraph(graph, &c_graph);
+  IGRAPH_R_CHECK(igraph_vector_init(&c_lengths, 0));
+  IGRAPH_FINALLY(igraph_vector_destroy, &c_lengths);
+  lengths=R_GlobalEnv; /* hack to have a non-NULL value */
   R_SEXP_to_matrix(points, &c_points);
   c_METRIC = (igraph_metric_t) Rf_asInteger(METRIC);
                                         /* Call igraph */
   GetRNGstate();
-  IGRAPH_R_CHECK(igraph_spatial_edge_lengths(&c_graph, c_lengths, &c_points, c_METRIC));
+  IGRAPH_R_CHECK(igraph_spatial_edge_lengths(&c_graph, &c_lengths, &c_points, c_METRIC));
   PutRNGstate();
 
                                         /* Convert output */
-
+  PROTECT(lengths=R_igraph_0orvector_to_SEXP(&c_lengths));
+  igraph_vector_destroy(&c_lengths);
+  IGRAPH_FINALLY_CLEAN(1);
   r_result = lengths;
 
   UNPROTECT(1);
diff --git a/tools/stimulus/types-RC.yaml b/tools/stimulus/types-RC.yaml
index e61a5c3424f..899582855a8 100644
--- a/tools/stimulus/types-RC.yaml
+++ b/tools/stimulus/types-RC.yaml
@@ -294,6 +294,21 @@ EDGE_WEIGHTS:
             igraph_vector_destroy(&%C%);
             IGRAPH_FINALLY_CLEAN(1);
 
+EDGE_LENGTHS:
+    CALL: '&%C%'
+    CTYPE: igraph_vector_t
+    INCONV:
+        IN: R_SEXP_to_vector(%I%, &%C%);
+        OUT: |-
+            IGRAPH_R_CHECK(igraph_vector_init(&%C%, 0));
+            IGRAPH_FINALLY(igraph_vector_destroy, &%C%);
+            %I%=R_GlobalEnv; /* hack to have a non-NULL value */
+    OUTCONV:
+        OUT: |-
+            PROTECT(%I%=R_igraph_0orvector_to_SEXP(&%C%));
+            igraph_vector_destroy(&%C%);
+            IGRAPH_FINALLY_CLEAN(1);
+
 VERTEX_WEIGHTS:
     CALL: '&%C%'
     CTYPE: igraph_vector_t

From 5a28a47ba12a42345153bc405fbcb7219a9b8758 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 01:35:37 +0200
Subject: [PATCH 129/154] Tweak function definitions

---
 R/aaa-auto.R                                 |  4 +--
 patch/0008-Tweak-function-definitions.patch  | 34 ++++++++++++++++++++
 src/rinterface.c                             |  4 +--
 src/vendor/cigraph/interfaces/functions.yaml |  4 +--
 4 files changed, 40 insertions(+), 6 deletions(-)
 create mode 100644 patch/0008-Tweak-function-definitions.patch

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index d8e3dfa2d15..82fad52367a 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -5382,7 +5382,7 @@ eulerian_cycle_impl <- function(graph) {
   res
 }
 
-fundamental_cycles_impl <- function(graph, weights=NULL, start=NULL, bfs.cutoff=UNLIMITED) {
+fundamental_cycles_impl <- function(graph, weights=NULL, start=-1, bfs.cutoff=UNLIMITED) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -5534,7 +5534,7 @@ minimum_spanning_tree_impl <- function(graph, weights=NULL, method=c("automatic"
   res
 }
 
-random_spanning_tree_impl <- function(graph, vid=NULL) {
+random_spanning_tree_impl <- function(graph, vid=-1) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(vid)) vid <- as_igraph_vs(graph, vid)
diff --git a/patch/0008-Tweak-function-definitions.patch b/patch/0008-Tweak-function-definitions.patch
new file mode 100644
index 00000000000..389a658b908
--- /dev/null
+++ b/patch/0008-Tweak-function-definitions.patch
@@ -0,0 +1,34 @@
+From 7545c34b50bf4e0d6b0c45a1f9af92e709a11034 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
+Date: Sun, 26 Oct 2025 01:35:37 +0200
+Subject: [PATCH] Tweak function definitions
+
+---
+ src/vendor/cigraph/interfaces/functions.yaml | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml
+index 17d0ba25fe..a1ba2d947a 100644
+--- a/src/vendor/cigraph/interfaces/functions.yaml
++++ b/src/vendor/cigraph/interfaces/functions.yaml
+@@ -2669,7 +2669,7 @@ igraph_fundamental_cycles:
+     PARAMS: |-
+         GRAPH graph, OPTIONAL EDGE_WEIGHTS weights,
+         OUT EDGE_INDICES_LIST basis,
+-        OPTIONAL VERTEX start,
++        OPTIONAL VERTEX start=-1,
+         REAL bfs_cutoff=UNLIMITED
+     DEPS: weights ON graph, basis ON graph, start ON graph
+ 
+@@ -2710,7 +2710,7 @@ igraph_minimum_spanning_tree:
+     DEPS: res ON graph, weights ON graph
+ 
+ igraph_random_spanning_tree:
+-    PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid
++    PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid=-1
+     DEPS: res ON graph, vid ON graph
+ 
+ igraph_tree_game:
+-- 
+2.50.1
+
diff --git a/src/rinterface.c b/src/rinterface.c
index cfdc44f1eee..15a52815f5a 100644
--- a/src/rinterface.c
+++ b/src/rinterface.c
@@ -12612,7 +12612,7 @@ SEXP R_igraph_fundamental_cycles(SEXP graph, SEXP weights, SEXP start, SEXP bfs_
   c_bfs_cutoff = REAL(bfs_cutoff)[0];
                                         /* Call igraph */
   GetRNGstate();
-  IGRAPH_R_CHECK(igraph_fundamental_cycles(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_basis, (Rf_isNull(start) ? NULL : c_start), c_bfs_cutoff));
+  IGRAPH_R_CHECK(igraph_fundamental_cycles(&c_graph, (Rf_isNull(weights) ? NULL : &c_weights), &c_basis, (Rf_isNull(start) ? -1 : c_start), c_bfs_cutoff));
   PutRNGstate();
 
                                         /* Convert output */
@@ -12925,7 +12925,7 @@ SEXP R_igraph_random_spanning_tree(SEXP graph, SEXP vid) {
   }
                                         /* Call igraph */
   GetRNGstate();
-  IGRAPH_R_CHECK(igraph_random_spanning_tree(&c_graph, &c_res, (Rf_isNull(vid) ? NULL : c_vid)));
+  IGRAPH_R_CHECK(igraph_random_spanning_tree(&c_graph, &c_res, (Rf_isNull(vid) ? -1 : c_vid)));
   PutRNGstate();
 
                                         /* Convert output */
diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml
index 17d0ba25fe2..a1ba2d947ac 100644
--- a/src/vendor/cigraph/interfaces/functions.yaml
+++ b/src/vendor/cigraph/interfaces/functions.yaml
@@ -2669,7 +2669,7 @@ igraph_fundamental_cycles:
     PARAMS: |-
         GRAPH graph, OPTIONAL EDGE_WEIGHTS weights,
         OUT EDGE_INDICES_LIST basis,
-        OPTIONAL VERTEX start,
+        OPTIONAL VERTEX start=-1,
         REAL bfs_cutoff=UNLIMITED
     DEPS: weights ON graph, basis ON graph, start ON graph
 
@@ -2710,7 +2710,7 @@ igraph_minimum_spanning_tree:
     DEPS: res ON graph, weights ON graph
 
 igraph_random_spanning_tree:
-    PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid
+    PARAMS: GRAPH graph, OUT EDGE_INDICES res, OPTIONAL VERTEX vid=-1
     DEPS: res ON graph, vid ON graph
 
 igraph_tree_game:

From 35b19fe84607e8e87dbd3b6c5ef91c2f38ffb0bc Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 23:40:49 +0000
Subject: [PATCH 130/154] Replace `_impl` aliases with explicit wrapper
 functions in `R/glet.R` (#2376)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/glet.R | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/R/glet.R b/R/glet.R
index d685420ae43..77b6087a04f 100644
--- a/R/glet.R
+++ b/R/glet.R
@@ -240,4 +240,10 @@ function() {
 #' @rdname graphlet_basis
 #' @export
 #' @cdocs igraph_graphlets
-graphlets <- graphlets_impl
+graphlets <- function(graph, weights = NULL, niter = 1000) {
+  graphlets_impl(
+    graph = graph,
+    weights = weights,
+    niter = niter
+  )
+}

From 16b3e130dc38cabe672aa7ac2f90f68b9170d19c Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 23:42:25 +0000
Subject: [PATCH 131/154] Replace _impl aliases in R/operators.R (#2385)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/operators.R | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/R/operators.R b/R/operators.R
index 4276666b977..20cea8fc969 100644
--- a/R/operators.R
+++ b/R/operators.R
@@ -1334,7 +1334,12 @@ rep.igraph <- function(x, n, mark = TRUE, ...) {
 #' @family functions for manipulating graph structure
 #' @export
 #' @cdocs igraph_reverse_edges
-reverse_edges <- reverse_edges_impl
+reverse_edges <- function(graph, eids = E(graph)) {
+  reverse_edges_impl(
+    graph = graph,
+    eids = eids
+  )
+}
 
 #' @rdname reverse_edges
 #' @param x The input graph.

From fe80c79eec5774331ea12d516f46b8ab9533794e Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 25 Oct 2025 23:52:38 +0000
Subject: [PATCH 132/154] Replace `_impl` aliases with explicit wrapper
 functions in `R/components.R` (#2390)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/components.R | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/R/components.R b/R/components.R
index 67e8a4fcbb5..8e3ccb8fed9 100644
--- a/R/components.R
+++ b/R/components.R
@@ -257,12 +257,16 @@ decompose <- function(
 #' @family components
 #' @export
 #' @cdocs igraph_articulation_points
-articulation_points <- articulation_points_impl
+articulation_points <- function(graph) {
+  articulation_points_impl(graph = graph)
+}
 
 #' @rdname articulation_points
 #' @export
 #' @cdocs igraph_bridges
-bridges <- bridges_impl
+bridges <- function(graph) {
+  bridges_impl(graph = graph)
+}
 
 
 #' Biconnected components
@@ -383,7 +387,9 @@ biconnected_components <- function(graph) {
 #' @family components
 #' @export
 #' @cdocs igraph_is_biconnected
-is_biconnected <- is_biconnected_impl
+is_biconnected <- function(graph) {
+  is_biconnected_impl(graph = graph)
+}
 
 
 #' @rdname components

From 1623dd1917bd31465418447fff590954fbfacb0e Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 26 Oct 2025 00:40:18 +0000
Subject: [PATCH 133/154] Replace `_impl` aliases in `R/motifs.R` with explicit
 wrappers (#2377)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/motifs.R | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/R/motifs.R b/R/motifs.R
index c6f2910224f..cca68c34749 100644
--- a/R/motifs.R
+++ b/R/motifs.R
@@ -394,4 +394,6 @@ dyad_census <- function(graph) {
 #' @family motifs
 #' @export
 #' @cdocs igraph_triad_census
-triad_census <- triad_census_impl
+triad_census <- function(graph) {
+  triad_census_impl(graph = graph)
+}

From dddc44afe7632ca3e8925169b9bc644c779a3420 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 26 Oct 2025 00:40:51 +0000
Subject: [PATCH 134/154] Replace `_impl` function aliases in R/cycles.R
 (#2394)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
---
 R/cycles.R | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/R/cycles.R b/R/cycles.R
index 636c993c505..e74e3fd9465 100644
--- a/R/cycles.R
+++ b/R/cycles.R
@@ -50,7 +50,12 @@
 #' @cdocs igraph_find_cycle
 #' @export
 
-find_cycle <- find_cycle_impl
+find_cycle <- function(graph, mode = c("out", "in", "all", "total")) {
+  find_cycle_impl(
+    graph = graph,
+    mode = mode
+  )
+}
 
 
 #' Finds all simple cycles in a graph.

From 25a90c55ecee103c6242ec3c87ed211c1514ebaf Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 26 Oct 2025 00:41:40 +0000
Subject: [PATCH 135/154] Replace `_impl` aliases in `R/eulerian.R` (#2378)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/eulerian.R | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/R/eulerian.R b/R/eulerian.R
index 5f46aa082d2..baf9ea992fa 100644
--- a/R/eulerian.R
+++ b/R/eulerian.R
@@ -81,9 +81,17 @@ has_eulerian_cycle <- function(graph) {
 #' @rdname has_eulerian_path
 #' @export
 #' @cdocs igraph_eulerian_path
-eulerian_path <- eulerian_path_impl
+eulerian_path <- function(graph) {
+  eulerian_path_impl(
+    graph = graph
+  )
+}
 
 #' @rdname has_eulerian_path
 #' @export
 #' @cdocs igraph_eulerian_cycle
-eulerian_cycle <- eulerian_cycle_impl
+eulerian_cycle <- function(graph) {
+  eulerian_cycle_impl(
+    graph = graph
+  )
+}

From e86fa0f8f1eee8f5824861dff5df3e7fbc26ea88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 08:42:10 +0100
Subject: [PATCH 136/154] ci: Run running sanitizer only on cran branches to
 avoid pipeline contention

---
 .github/workflows/build-and-check.yml | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/build-and-check.yml b/.github/workflows/build-and-check.yml
index 79243ca5cbd..e543c7e3a79 100644
--- a/.github/workflows/build-and-check.yml
+++ b/.github/workflows/build-and-check.yml
@@ -3,14 +3,10 @@
 on:
   push:
     branches:
-      - main
-      - fix/*
-  pull_request:
-    branches:
-      - main
-      - fix/*
+      - cran-*
   schedule:
     - cron: '0 2 * * *'
+  workflow_dispatch:
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || github.sha }}-${{ github.base_ref || '' }}

From 40788f036191258392677c7cd5598f7d39e2cbad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 08:45:17 +0100
Subject: [PATCH 137/154] chore: Autogenerated file looks more like as if it
 was formatted with `air` (#2395)

---
 AGENTS.md                                     |    4 +
 R/aaa-auto.R                                  | 5175 +++++++++++++----
 R/utils-assert-args.R                         |   23 +-
 .../py-stimulus/src/stimulus/generators/r.py  |  108 +-
 4 files changed, 4297 insertions(+), 1013 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md
index 5c4ecdb87cf..90c89218c30 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -32,3 +32,7 @@ igraph is an R package with routines for simple graphs and network analysis. It
 - Use meaningful variable names that reflect the testing context
 - Run `air format .` before committing changes to ensure consistent formatting
 - Keep documentation in sync with code changes. When updating roxygen2 documentation, ensure that each sentence is on its own line for better readability. Run `R -q -e 'devtools::document()'` to update the documentation.
+
+## Code Generation
+
+See `tools/README.md` for guidelines on code generation using the Stimulus framework.
diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index 82fad52367a..39de47f286e 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -1,65 +1,101 @@
 # Generated by make -f Makefile-cigraph, do not edit by hand
 # styler: off
 
-empty_impl <- function(n=0, directed=TRUE) {
+empty_impl <- function(
+  n = 0,
+  directed = TRUE
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_empty, n, directed)
+  res <- .Call(
+    R_igraph_empty,
+    n,
+    directed
+  )
 
   res
 }
 
-add_edges_impl <- function(graph, edges) {
+add_edges_impl <- function(
+  graph,
+  edges
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_add_edges, graph, edges)
+  res <- .Call(
+    R_igraph_add_edges,
+    graph,
+    edges
+  )
 
   res
 }
 
-copy_impl <- function(from) {
+copy_impl <- function(
+  from
+) {
   # Argument checks
   ensure_igraph(from)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_copy, from)
+  res <- .Call(
+    R_igraph_copy,
+    from
+  )
 
   res
 }
 
-delete_vertices_map_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) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_delete_vertices_map, graph, vertices-1)
+  res <- .Call(
+    R_igraph_delete_vertices_map,
+    graph,
+    vertices - 1
+  )
 
   res
 }
 
-vcount_impl <- function(graph) {
+vcount_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_vcount, graph)
-
+  res <- .Call(
+    R_igraph_vcount,
+    graph
+  )
 
   res
 }
 
-neighbors_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once"), multiple=TRUE) {
+neighbors_impl <- function(
+  graph,
+  vid,
+  mode = c("all", "out", "in", "total"),
+  loops = c("twice", "none", "once"),
+  multiple = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   vid <- as_igraph_vs(graph, vid)
@@ -70,30 +106,53 @@ neighbors_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loop
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
   multiple <- as.logical(multiple)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_neighbors, graph, vid-1, mode, loops, multiple)
+  res <- .Call(
+    R_igraph_neighbors,
+    graph,
+    vid - 1,
+    mode,
+    loops,
+    multiple
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_vs(graph, res)
   }
   res
 }
 
-degree_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once")) {
+degree_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = c("twice", "none", "once")
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_degree, graph, vids-1, mode, loops)
+  res <- .Call(
+    R_igraph_degree,
+    graph,
+    vids - 1,
+    mode,
+    loops
+  )
 
   res
 }
 
-get_all_eids_between_impl <- function(graph, from, to, directed=TRUE) {
+get_all_eids_between_impl <- function(
+  graph,
+  from,
+  to,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -106,16 +165,27 @@ get_all_eids_between_impl <- function(graph, from, to, directed=TRUE) {
   }
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_all_eids_between, graph, from-1, to-1, directed)
+  res <- .Call(
+    R_igraph_get_all_eids_between,
+    graph,
+    from - 1,
+    to - 1,
+    directed
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_es(graph, res)
   }
   res
 }
 
-incident_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once")) {
+incident_impl <- function(
+  graph,
+  vid,
+  mode = c("all", "out", "in", "total"),
+  loops = c("twice", "none", "once")
+) {
   # Argument checks
   ensure_igraph(graph)
   vid <- as_igraph_vs(graph, vid)
@@ -125,41 +195,69 @@ incident_impl <- function(graph, vid, mode=c("all", "out", "in", "total"), loops
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_incident, graph, vid-1, mode, loops)
+  res <- .Call(
+    R_igraph_incident,
+    graph,
+    vid - 1,
+    mode,
+    loops
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_es(graph, res)
   }
   res
 }
 
-wheel_impl <- function(n, mode=c("out", "in", "undirected", "mutual"), center=0) {
+wheel_impl <- function(
+  n,
+  mode = c("out", "in", "undirected", "mutual"),
+  center = 0
+) {
   # Argument checks
   n <- as.numeric(n)
   mode <- switch_igraph_arg(mode, "out" = 0L, "in" = 1L, "undirected" = 2L, "mutual" = 3L)
   center <- as.numeric(center)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_wheel, n, mode, center)
+  res <- .Call(
+    R_igraph_wheel,
+    n,
+    mode,
+    center
+  )
 
   res
 }
 
-hypercube_impl <- function(n, directed=FALSE) {
+hypercube_impl <- function(
+  n,
+  directed = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hypercube, n, directed)
+  res <- .Call(
+    R_igraph_hypercube,
+    n,
+    directed
+  )
 
   res
 }
 
-square_lattice_impl <- function(dimvector, nei=1, directed=FALSE, mutual=FALSE, periodic=NULL) {
+square_lattice_impl <- function(
+  dimvector,
+  nei = 1,
+  directed = FALSE,
+  mutual = FALSE,
+  periodic = NULL
+) {
   # Argument checks
   dimvector <- as.numeric(dimvector)
   nei <- as.numeric(nei)
@@ -167,227 +265,374 @@ square_lattice_impl <- function(dimvector, nei=1, directed=FALSE, mutual=FALSE,
   mutual <- as.logical(mutual)
   if (!is.null(periodic)) periodic <- as.logical(periodic)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_square_lattice, dimvector, nei, directed, mutual, periodic)
+  res <- .Call(
+    R_igraph_square_lattice,
+    dimvector,
+    nei,
+    directed,
+    mutual,
+    periodic
+  )
 
   res
 }
 
-triangular_lattice_impl <- function(dimvector, directed=FALSE, mutual=FALSE) {
+triangular_lattice_impl <- function(
+  dimvector,
+  directed = FALSE,
+  mutual = FALSE
+) {
   # Argument checks
   dimvector <- as.numeric(dimvector)
   directed <- as.logical(directed)
   mutual <- as.logical(mutual)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_triangular_lattice, dimvector, directed, mutual)
+  res <- .Call(
+    R_igraph_triangular_lattice,
+    dimvector,
+    directed,
+    mutual
+  )
 
   res
 }
 
-path_graph_impl <- function(n, directed=FALSE, mutual=FALSE) {
+path_graph_impl <- function(
+  n,
+  directed = FALSE,
+  mutual = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
   mutual <- as.logical(mutual)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_path_graph, n, directed, mutual)
+  res <- .Call(
+    R_igraph_path_graph,
+    n,
+    directed,
+    mutual
+  )
 
   res
 }
 
-cycle_graph_impl <- function(n, directed=FALSE, mutual=FALSE) {
+cycle_graph_impl <- function(
+  n,
+  directed = FALSE,
+  mutual = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
   mutual <- as.logical(mutual)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_cycle_graph, n, directed, mutual)
+  res <- .Call(
+    R_igraph_cycle_graph,
+    n,
+    directed,
+    mutual
+  )
 
   res
 }
 
-symmetric_tree_impl <- function(branches, type=c("out", "in", "undirected")) {
+symmetric_tree_impl <- function(
+  branches,
+  type = c("out", "in", "undirected")
+) {
   # Argument checks
   branches <- as.numeric(branches)
   type <- switch_igraph_arg(type, "out" = 0L, "in" = 1L, "undirected" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_symmetric_tree, branches, type)
+  res <- .Call(
+    R_igraph_symmetric_tree,
+    branches,
+    type
+  )
 
   res
 }
 
-regular_tree_impl <- function(h, k=3, type=c("undirected", "out", "in")) {
+regular_tree_impl <- function(
+  h,
+  k = 3,
+  type = c("undirected", "out", "in")
+) {
   # Argument checks
   h <- as.numeric(h)
   k <- as.numeric(k)
   type <- switch_igraph_arg(type, "out" = 0L, "in" = 1L, "undirected" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_regular_tree, h, k, type)
+  res <- .Call(
+    R_igraph_regular_tree,
+    h,
+    k,
+    type
+  )
 
   res
 }
 
-full_citation_impl <- function(n, directed=TRUE) {
+full_citation_impl <- function(
+  n,
+  directed = TRUE
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_full_citation, n, directed)
+  res <- .Call(
+    R_igraph_full_citation,
+    n,
+    directed
+  )
 
   res
 }
 
-atlas_impl <- function(number=0) {
+atlas_impl <- function(
+  number = 0
+) {
   # Argument checks
   number <- as.numeric(number)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_atlas, number)
+  res <- .Call(
+    R_igraph_atlas,
+    number
+  )
 
   res
 }
 
-extended_chordal_ring_impl <- function(nodes, W, directed=FALSE) {
+extended_chordal_ring_impl <- function(
+  nodes,
+  W,
+  directed = FALSE
+) {
   # Argument checks
   nodes <- as.numeric(nodes)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_extended_chordal_ring, nodes, W, directed)
+  res <- .Call(
+    R_igraph_extended_chordal_ring,
+    nodes,
+    W,
+    directed
+  )
 
   res
 }
 
-graph_power_impl <- function(graph, order, directed=FALSE) {
+graph_power_impl <- function(
+  graph,
+  order,
+  directed = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   order <- as.numeric(order)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_graph_power, graph, order, directed)
+  res <- .Call(
+    R_igraph_graph_power,
+    graph,
+    order,
+    directed
+  )
 
   res
 }
 
-linegraph_impl <- function(graph) {
+linegraph_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_linegraph, graph)
+  res <- .Call(
+    R_igraph_linegraph,
+    graph
+  )
 
   res
 }
 
-de_bruijn_impl <- function(m, n) {
+de_bruijn_impl <- function(
+  m,
+  n
+) {
   # Argument checks
   m <- as.numeric(m)
   n <- as.numeric(n)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_de_bruijn, m, n)
+  res <- .Call(
+    R_igraph_de_bruijn,
+    m,
+    n
+  )
 
   res
 }
 
-kautz_impl <- function(m, n) {
+kautz_impl <- function(
+  m,
+  n
+) {
   # Argument checks
   m <- as.numeric(m)
   n <- as.numeric(n)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_kautz, m, n)
+  res <- .Call(
+    R_igraph_kautz,
+    m,
+    n
+  )
 
   res
 }
 
-lcf_impl <- function(n, shifts, repeats=1) {
+lcf_impl <- function(
+  n,
+  shifts,
+  repeats = 1
+) {
   # Argument checks
   n <- as.numeric(n)
   shifts <- as.numeric(shifts)
   repeats <- as.numeric(repeats)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_lcf, n, shifts, repeats)
+  res <- .Call(
+    R_igraph_lcf,
+    n,
+    shifts,
+    repeats
+  )
 
   res
 }
 
-mycielski_graph_impl <- function(k) {
+mycielski_graph_impl <- function(
+  k
+) {
   # Argument checks
   k <- as.numeric(k)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_mycielski_graph, k)
+  res <- .Call(
+    R_igraph_mycielski_graph,
+    k
+  )
 
   res
 }
 
-adjlist_impl <- function(adjlist, mode=c("out", "in", "all", "total"), duplicate=TRUE) {
+adjlist_impl <- function(
+  adjlist,
+  mode = c("out", "in", "all", "total"),
+  duplicate = TRUE
+) {
   # Argument checks
   adjlist <- lapply(adjlist, function(x) as.numeric(x)-1)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   duplicate <- as.logical(duplicate)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_adjlist, adjlist, mode, duplicate)
+  res <- .Call(
+    R_igraph_adjlist,
+    adjlist,
+    mode,
+    duplicate
+  )
 
   res
 }
 
-full_bipartite_impl <- function(n1, n2, directed=FALSE, mode=c("all", "out", "in", "total")) {
+full_bipartite_impl <- function(
+  n1,
+  n2,
+  directed = FALSE,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   n1 <- as.numeric(n1)
   n2 <- as.numeric(n2)
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_full_bipartite, n1, n2, directed, mode)
+  res <- .Call(
+    R_igraph_full_bipartite,
+    n1,
+    n2,
+    directed,
+    mode
+  )
   if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
     names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
 
-full_multipartite_impl <- function(n, directed=FALSE, mode=c("all", "out", "in", "total")) {
+full_multipartite_impl <- function(
+  n,
+  directed = FALSE,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_full_multipartite, n, directed, mode)
+  res <- .Call(
+    R_igraph_full_multipartite,
+    n,
+    directed,
+    mode
+  )
 
   res
 }
 
-realize_degree_sequence_impl <- function(out.deg, in.deg=NULL, allowed.edge.types=c("simple", "loops", "multi", "all"), method=c("smallest", "largest", "index")) {
+realize_degree_sequence_impl <- function(
+  out.deg,
+  in.deg = NULL,
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  method = c("smallest", "largest", "index")
+) {
   # Argument checks
   out.deg <- as.numeric(out.deg)
   if (!is.null(in.deg)) in.deg <- as.numeric(in.deg)
@@ -395,9 +640,15 @@ realize_degree_sequence_impl <- function(out.deg, in.deg=NULL, allowed.edge.type
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
   method <- switch_igraph_arg(method, "smallest" = 0L, "largest" = 1L, "index" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_realize_degree_sequence, out.deg, in.deg, allowed.edge.types, method)
+  res <- .Call(
+    R_igraph_realize_degree_sequence,
+    out.deg,
+    in.deg,
+    allowed.edge.types,
+    method
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Graph from degree sequence'
@@ -410,7 +661,12 @@ realize_degree_sequence_impl <- function(out.deg, in.deg=NULL, allowed.edge.type
   res
 }
 
-realize_bipartite_degree_sequence_impl <- function(degrees1, degrees2, allowed.edge.types=c("simple", "loops", "multi", "all"), method=c("smallest", "largest", "index")) {
+realize_bipartite_degree_sequence_impl <- function(
+  degrees1,
+  degrees2,
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  method = c("smallest", "largest", "index")
+) {
   # Argument checks
   degrees1 <- as.numeric(degrees1)
   degrees2 <- as.numeric(degrees2)
@@ -418,9 +674,15 @@ realize_bipartite_degree_sequence_impl <- function(degrees1, degrees2, allowed.e
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
   method <- switch_igraph_arg(method, "smallest" = 0L, "largest" = 1L, "index" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_realize_bipartite_degree_sequence, degrees1, degrees2, allowed.edge.types, method)
+  res <- .Call(
+    R_igraph_realize_bipartite_degree_sequence,
+    degrees1,
+    degrees2,
+    allowed.edge.types,
+    method
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Bipartite graph from degree sequence'
@@ -433,44 +695,73 @@ realize_bipartite_degree_sequence_impl <- function(degrees1, degrees2, allowed.e
   res
 }
 
-circulant_impl <- function(n, shifts, directed=FALSE) {
+circulant_impl <- function(
+  n,
+  shifts,
+  directed = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   shifts <- as.numeric(shifts)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_circulant, n, shifts, directed)
+  res <- .Call(
+    R_igraph_circulant,
+    n,
+    shifts,
+    directed
+  )
 
   res
 }
 
-generalized_petersen_impl <- function(n, k) {
+generalized_petersen_impl <- function(
+  n,
+  k
+) {
   # Argument checks
   n <- as.numeric(n)
   k <- as.numeric(k)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_generalized_petersen, n, k)
+  res <- .Call(
+    R_igraph_generalized_petersen,
+    n,
+    k
+  )
 
   res
 }
 
-turan_impl <- function(n, r) {
+turan_impl <- function(
+  n,
+  r
+) {
   # Argument checks
   n <- as.numeric(n)
   r <- as.numeric(r)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_turan, n, r)
+  res <- .Call(
+    R_igraph_turan,
+    n,
+    r
+  )
 
   res
 }
 
-erdos_renyi_game_gnp_impl <- function(n, p, directed=FALSE, allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) {
+erdos_renyi_game_gnp_impl <- function(
+  n,
+  p,
+  directed = FALSE,
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  edge.labeled = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   p <- as.numeric(p)
@@ -479,14 +770,27 @@ erdos_renyi_game_gnp_impl <- function(n, p, directed=FALSE, allowed.edge.types=c
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
   edge.labeled <- as.logical(edge.labeled)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_erdos_renyi_game_gnp, n, p, directed, allowed.edge.types, edge.labeled)
+  res <- .Call(
+    R_igraph_erdos_renyi_game_gnp,
+    n,
+    p,
+    directed,
+    allowed.edge.types,
+    edge.labeled
+  )
 
   res
 }
 
-erdos_renyi_game_gnm_impl <- function(n, m, directed=FALSE, allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) {
+erdos_renyi_game_gnm_impl <- function(
+  n,
+  m,
+  directed = FALSE,
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  edge.labeled = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   m <- as.numeric(m)
@@ -495,28 +799,52 @@ erdos_renyi_game_gnm_impl <- function(n, m, directed=FALSE, allowed.edge.types=c
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
   edge.labeled <- as.logical(edge.labeled)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_erdos_renyi_game_gnm, n, m, directed, allowed.edge.types, edge.labeled)
+  res <- .Call(
+    R_igraph_erdos_renyi_game_gnm,
+    n,
+    m,
+    directed,
+    allowed.edge.types,
+    edge.labeled
+  )
 
   res
 }
 
-iea_game_impl <- function(n, m, directed=FALSE, loops=FALSE) {
+iea_game_impl <- function(
+  n,
+  m,
+  directed = FALSE,
+  loops = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   m <- as.numeric(m)
   directed <- as.logical(directed)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_iea_game, n, m, directed, loops)
+  res <- .Call(
+    R_igraph_iea_game,
+    n,
+    m,
+    directed,
+    loops
+  )
 
   res
 }
 
-growing_random_game_impl <- function(n, m=1, ..., directed=TRUE, citation=FALSE) {
+growing_random_game_impl <- function(
+  n,
+  m = 1,
+  ...,
+  directed = TRUE,
+  citation = FALSE
+) {
   # Argument checks
   check_dots_empty()
   n <- as.numeric(n)
@@ -524,9 +852,15 @@ growing_random_game_impl <- function(n, m=1, ..., directed=TRUE, citation=FALSE)
   directed <- as.logical(directed)
   citation <- as.logical(citation)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_growing_random_game, n, m, directed, citation)
+  res <- .Call(
+    R_igraph_growing_random_game,
+    n,
+    m,
+    directed,
+    citation
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Growing random graph'
@@ -537,7 +871,15 @@ growing_random_game_impl <- function(n, m=1, ..., directed=TRUE, citation=FALSE)
   res
 }
 
-preference_game_impl <- function(nodes, types, type.dist, fixed.sizes=FALSE, pref.matrix, directed=FALSE, loops=FALSE) {
+preference_game_impl <- function(
+  nodes,
+  types,
+  type.dist,
+  fixed.sizes = FALSE,
+  pref.matrix,
+  directed = FALSE,
+  loops = FALSE
+) {
   # Argument checks
   nodes <- as.numeric(nodes)
   types <- as.numeric(types)
@@ -547,14 +889,30 @@ preference_game_impl <- function(nodes, types, type.dist, fixed.sizes=FALSE, pre
   directed <- as.logical(directed)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_preference_game, nodes, types, type.dist, fixed.sizes, pref.matrix, directed, loops)
+  res <- .Call(
+    R_igraph_preference_game,
+    nodes,
+    types,
+    type.dist,
+    fixed.sizes,
+    pref.matrix,
+    directed,
+    loops
+  )
 
   res
 }
 
-asymmetric_preference_game_impl <- function(nodes, out.types, in.types, type.dist.matrix, pref.matrix, loops=FALSE) {
+asymmetric_preference_game_impl <- function(
+  nodes,
+  out.types,
+  in.types,
+  type.dist.matrix,
+  pref.matrix,
+  loops = FALSE
+) {
   # Argument checks
   nodes <- as.numeric(nodes)
   out.types <- as.numeric(out.types)
@@ -563,42 +921,76 @@ asymmetric_preference_game_impl <- function(nodes, out.types, in.types, type.dis
   pref.matrix[] <- as.numeric(pref.matrix)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_asymmetric_preference_game, nodes, out.types, in.types, type.dist.matrix, pref.matrix, loops)
+  res <- .Call(
+    R_igraph_asymmetric_preference_game,
+    nodes,
+    out.types,
+    in.types,
+    type.dist.matrix,
+    pref.matrix,
+    loops
+  )
 
   res
 }
 
-rewire_edges_impl <- function(graph, prob, allowed.edge.types=c("simple", "loops", "multi", "all")) {
+rewire_edges_impl <- function(
+  graph,
+  prob,
+  allowed.edge.types = c("simple", "loops", "multi", "all")
+) {
   # Argument checks
   ensure_igraph(graph)
   prob <- as.numeric(prob)
   allowed.edge.types <- switch_igraph_arg(allowed.edge.types,
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_rewire_edges, graph, prob, allowed.edge.types)
+  res <- .Call(
+    R_igraph_rewire_edges,
+    graph,
+    prob,
+    allowed.edge.types
+  )
 
   res
 }
 
-rewire_directed_edges_impl <- function(graph, prob, loops=FALSE, mode=c("out", "in", "all", "total")) {
+rewire_directed_edges_impl <- function(
+  graph,
+  prob,
+  loops = FALSE,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   prob <- as.numeric(prob)
   loops <- as.logical(loops)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_rewire_directed_edges, graph, prob, loops, mode)
+  res <- .Call(
+    R_igraph_rewire_directed_edges,
+    graph,
+    prob,
+    loops,
+    mode
+  )
 
   res
 }
 
-forest_fire_game_impl <- function(nodes, fw.prob, bw.factor=1, ambs=1, directed=TRUE) {
+forest_fire_game_impl <- function(
+  nodes,
+  fw.prob,
+  bw.factor = 1,
+  ambs = 1,
+  directed = TRUE
+) {
   # Argument checks
   nodes <- as.numeric(nodes)
   fw.prob <- as.numeric(fw.prob)
@@ -606,9 +998,16 @@ forest_fire_game_impl <- function(nodes, fw.prob, bw.factor=1, ambs=1, directed=
   ambs <- as.numeric(ambs)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_forest_fire_game, nodes, fw.prob, bw.factor, ambs, directed)
+  res <- .Call(
+    R_igraph_forest_fire_game,
+    nodes,
+    fw.prob,
+    bw.factor,
+    ambs,
+    directed
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Forest fire model'
@@ -620,16 +1019,27 @@ forest_fire_game_impl <- function(nodes, fw.prob, bw.factor=1, ambs=1, directed=
   res
 }
 
-simple_interconnected_islands_game_impl <- function(islands.n, islands.size, islands.pin, n.inter) {
+simple_interconnected_islands_game_impl <- function(
+  islands.n,
+  islands.size,
+  islands.pin,
+  n.inter
+) {
   # Argument checks
   islands.n <- as.numeric(islands.n)
   islands.size <- as.numeric(islands.size)
   islands.pin <- as.numeric(islands.pin)
   n.inter <- as.numeric(n.inter)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_simple_interconnected_islands_game, islands.n, islands.size, islands.pin, n.inter)
+  res <- .Call(
+    R_igraph_simple_interconnected_islands_game,
+    islands.n,
+    islands.size,
+    islands.pin,
+    n.inter
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Interconnected islands model'
@@ -642,7 +1052,13 @@ simple_interconnected_islands_game_impl <- function(islands.n, islands.size, isl
   res
 }
 
-chung_lu_game_impl <- function(out.weights, in.weights=NULL, ..., loops=TRUE, variant=c("original", "maxent", "nr")) {
+chung_lu_game_impl <- function(
+  out.weights,
+  in.weights = NULL,
+  ...,
+  loops = TRUE,
+  variant = c("original", "maxent", "nr")
+) {
   # Argument checks
   check_dots_empty()
   out.weights <- as.numeric(out.weights)
@@ -650,9 +1066,15 @@ chung_lu_game_impl <- function(out.weights, in.weights=NULL, ..., loops=TRUE, va
   loops <- as.logical(loops)
   variant <- switch_igraph_arg(variant, "original" = 0L, "maxent" = 1L, "nr" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_chung_lu_game, out.weights, in.weights, loops, variant)
+  res <- .Call(
+    R_igraph_chung_lu_game,
+    out.weights,
+    in.weights,
+    loops,
+    variant
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Chung-Lu model'
@@ -662,7 +1084,12 @@ chung_lu_game_impl <- function(out.weights, in.weights=NULL, ..., loops=TRUE, va
   res
 }
 
-static_fitness_game_impl <- function(no.of.edges, fitness.out, fitness.in=NULL, allowed.edge.types=c("simple", "loops", "multi", "all")) {
+static_fitness_game_impl <- function(
+  no.of.edges,
+  fitness.out,
+  fitness.in = NULL,
+  allowed.edge.types = c("simple", "loops", "multi", "all")
+) {
   # Argument checks
   no.of.edges <- as.numeric(no.of.edges)
   fitness.out <- as.numeric(fitness.out)
@@ -670,9 +1097,15 @@ static_fitness_game_impl <- function(no.of.edges, fitness.out, fitness.in=NULL,
   allowed.edge.types <- switch_igraph_arg(allowed.edge.types,
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_static_fitness_game, no.of.edges, fitness.out, fitness.in, allowed.edge.types)
+  res <- .Call(
+    R_igraph_static_fitness_game,
+    no.of.edges,
+    fitness.out,
+    fitness.in,
+    allowed.edge.types
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Static fitness model'
@@ -683,7 +1116,14 @@ static_fitness_game_impl <- function(no.of.edges, fitness.out, fitness.in=NULL,
   res
 }
 
-static_power_law_game_impl <- function(no.of.nodes, no.of.edges, exponent.out, exponent.in=-1, allowed.edge.types=c("simple", "loops", "multi", "all"), finite.size.correction=TRUE) {
+static_power_law_game_impl <- function(
+  no.of.nodes,
+  no.of.edges,
+  exponent.out,
+  exponent.in = -1,
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  finite.size.correction = TRUE
+) {
   # Argument checks
   no.of.nodes <- as.numeric(no.of.nodes)
   no.of.edges <- as.numeric(no.of.edges)
@@ -693,9 +1133,17 @@ static_power_law_game_impl <- function(no.of.nodes, no.of.edges, exponent.out, e
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
   finite.size.correction <- as.logical(finite.size.correction)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_static_power_law_game, no.of.nodes, no.of.edges, exponent.out, exponent.in, allowed.edge.types, finite.size.correction)
+  res <- .Call(
+    R_igraph_static_power_law_game,
+    no.of.nodes,
+    no.of.edges,
+    exponent.out,
+    exponent.in,
+    allowed.edge.types,
+    finite.size.correction
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Static power law model'
@@ -707,16 +1155,27 @@ static_power_law_game_impl <- function(no.of.nodes, no.of.edges, exponent.out, e
   res
 }
 
-k_regular_game_impl <- function(no.of.nodes, k, directed=FALSE, multiple=FALSE) {
+k_regular_game_impl <- function(
+  no.of.nodes,
+  k,
+  directed = FALSE,
+  multiple = FALSE
+) {
   # Argument checks
   no.of.nodes <- as.numeric(no.of.nodes)
   k <- as.numeric(k)
   directed <- as.logical(directed)
   multiple <- as.logical(multiple)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_k_regular_game, no.of.nodes, k, directed, multiple)
+  res <- .Call(
+    R_igraph_k_regular_game,
+    no.of.nodes,
+    k,
+    directed,
+    multiple
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'k-regular graph'
@@ -726,7 +1185,12 @@ k_regular_game_impl <- function(no.of.nodes, k, directed=FALSE, multiple=FALSE)
   res
 }
 
-sbm_game_impl <- function(pref.matrix, block.sizes, directed=FALSE, allowed.edge.types=c("simple", "loops", "multi", "all")) {
+sbm_game_impl <- function(
+  pref.matrix,
+  block.sizes,
+  directed = FALSE,
+  allowed.edge.types = c("simple", "loops", "multi", "all")
+) {
   # Argument checks
   pref.matrix[] <- as.numeric(pref.matrix)
   block.sizes <- as.numeric(block.sizes)
@@ -734,9 +1198,15 @@ sbm_game_impl <- function(pref.matrix, block.sizes, directed=FALSE, allowed.edge
   allowed.edge.types <- switch_igraph_arg(allowed.edge.types,
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_sbm_game, pref.matrix, block.sizes, directed, allowed.edge.types)
+  res <- .Call(
+    R_igraph_sbm_game,
+    pref.matrix,
+    block.sizes,
+    directed,
+    allowed.edge.types
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Stochastic block model'
@@ -746,7 +1216,13 @@ sbm_game_impl <- function(pref.matrix, block.sizes, directed=FALSE, allowed.edge
   res
 }
 
-hsbm_game_impl <- function(n, m, rho, C, p) {
+hsbm_game_impl <- function(
+  n,
+  m,
+  rho,
+  C,
+  p
+) {
   # Argument checks
   n <- as.numeric(n)
   m <- as.numeric(m)
@@ -754,9 +1230,16 @@ hsbm_game_impl <- function(n, m, rho, C, p) {
   C[] <- as.numeric(C)
   p <- as.numeric(p)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hsbm_game, n, m, rho, C, p)
+  res <- .Call(
+    R_igraph_hsbm_game,
+    n,
+    m,
+    rho,
+    C,
+    p
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Hierarchical stochastic block model'
@@ -769,15 +1252,28 @@ hsbm_game_impl <- function(n, m, rho, C, p) {
   res
 }
 
-hsbm_list_game_impl <- function(n, mlist, rholist, Clist, p) {
+hsbm_list_game_impl <- function(
+  n,
+  mlist,
+  rholist,
+  Clist,
+  p
+) {
   # Argument checks
   n <- as.numeric(n)
   mlist <- as.numeric(mlist)
   p <- as.numeric(p)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hsbm_list_game, n, mlist, rholist, Clist, p)
+  res <- .Call(
+    R_igraph_hsbm_list_game,
+    n,
+    mlist,
+    rholist,
+    Clist,
+    p
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Hierarchical stochastic block model'
@@ -787,16 +1283,27 @@ hsbm_list_game_impl <- function(n, mlist, rholist, Clist, p) {
   res
 }
 
-correlated_game_impl <- function(old.graph, corr, p=edge_density(old.graph), permutation=NULL) {
+correlated_game_impl <- function(
+  old.graph,
+  corr,
+  p = edge_density(old.graph),
+  permutation = NULL
+) {
   # Argument checks
   ensure_igraph(old.graph)
   corr <- as.numeric(corr)
   p <- as.numeric(p)
   if (!is.null(permutation)) permutation <- as.numeric(permutation)-1
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_correlated_game, old.graph, corr, p, permutation)
+  res <- .Call(
+    R_igraph_correlated_game,
+    old.graph,
+    corr,
+    p,
+    permutation
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Correlated random graph'
@@ -807,7 +1314,13 @@ correlated_game_impl <- function(old.graph, corr, p=edge_density(old.graph), per
   res
 }
 
-correlated_pair_game_impl <- function(n, corr, p, directed=FALSE, permutation=NULL) {
+correlated_pair_game_impl <- function(
+  n,
+  corr,
+  p,
+  directed = FALSE,
+  permutation = NULL
+) {
   # Argument checks
   n <- as.numeric(n)
   corr <- as.numeric(corr)
@@ -815,26 +1328,44 @@ correlated_pair_game_impl <- function(n, corr, p, directed=FALSE, permutation=NU
   directed <- as.logical(directed)
   if (!is.null(permutation)) permutation <- as.numeric(permutation)-1
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_correlated_pair_game, n, corr, p, directed, permutation)
+  res <- .Call(
+    R_igraph_correlated_pair_game,
+    n,
+    corr,
+    p,
+    directed,
+    permutation
+  )
 
   res
 }
 
-dot_product_game_impl <- function(vecs, directed=FALSE) {
+dot_product_game_impl <- function(
+  vecs,
+  directed = FALSE
+) {
   # Argument checks
   vecs[] <- as.numeric(vecs)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_dot_product_game, vecs, directed)
+  res <- .Call(
+    R_igraph_dot_product_game,
+    vecs,
+    directed
+  )
 
   res
 }
 
-are_adjacent_impl <- function(graph, v1, v2) {
+are_adjacent_impl <- function(
+  graph,
+  v1,
+  v2
+) {
   # Argument checks
   ensure_igraph(graph)
   v1 <- as_igraph_vs(graph, v1)
@@ -846,14 +1377,24 @@ are_adjacent_impl <- function(graph, v1, v2) {
     stop("No vertex was specified")
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_are_adjacent, graph, v1-1, v2-1)
+  res <- .Call(
+    R_igraph_are_adjacent,
+    graph,
+    v1 - 1,
+    v2 - 1
+  )
 
   res
 }
 
-diameter_impl <- function(graph, weights=NULL, directed=TRUE, unconnected=TRUE) {
+diameter_impl <- function(
+  graph,
+  weights = NULL,
+  directed = TRUE,
+  unconnected = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -867,14 +1408,26 @@ diameter_impl <- function(graph, weights=NULL, directed=TRUE, unconnected=TRUE)
   directed <- as.logical(directed)
   unconnected <- as.logical(unconnected)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_diameter, graph, weights, directed, unconnected)
+  res <- .Call(
+    R_igraph_diameter,
+    graph,
+    weights,
+    directed,
+    unconnected
+  )
 
   res
 }
 
-closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE) {
+closeness_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("out", "in", "all", "total"),
+  weights = NULL,
+  normalized = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
@@ -889,16 +1442,30 @@ closeness_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "tot
   }
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_closeness, graph, vids-1, mode, weights, normalized)
+  res <- .Call(
+    R_igraph_closeness,
+    graph,
+    vids - 1,
+    mode,
+    weights,
+    normalized
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE, cutoff=UNLIMITED) {
+closeness_cutoff_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("out", "in", "all", "total"),
+  weights = NULL,
+  normalized = FALSE,
+  cutoff = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
@@ -914,16 +1481,30 @@ closeness_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all
   normalized <- as.logical(normalized)
   cutoff <- as.numeric(cutoff)
 
-  on.exit( .Call(R_igraph_finalizer) )
-  # Function call
-  res <- .Call(R_igraph_closeness_cutoff, graph, vids-1, mode, weights, normalized, cutoff)
+  on.exit(.Call(R_igraph_finalizer))
+  # Function call
+  res <- .Call(
+    R_igraph_closeness_cutoff,
+    graph,
+    vids - 1,
+    mode,
+    weights,
+    normalized,
+    cutoff
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-get_shortest_path_impl <- function(graph, weights=NULL, from, to, mode=c("out", "in", "all", "total")) {
+get_shortest_path_impl <- function(
+  graph,
+  weights = NULL,
+  from,
+  to,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -944,9 +1525,16 @@ get_shortest_path_impl <- function(graph, weights=NULL, from, to, mode=c("out",
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_shortest_path, graph, weights, from-1, to-1, mode)
+  res <- .Call(
+    R_igraph_get_shortest_path,
+    graph,
+    weights,
+    from - 1,
+    to - 1,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$vertices <- create_vs(graph, res$vertices)
   }
@@ -956,7 +1544,13 @@ get_shortest_path_impl <- function(graph, weights=NULL, from, to, mode=c("out",
   res
 }
 
-get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, mode=c("out", "in", "all", "total")) {
+get_shortest_path_bellman_ford_impl <- function(
+  graph,
+  from,
+  to,
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -977,9 +1571,16 @@ get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, m
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_shortest_path_bellman_ford, graph, from-1, to-1, weights, mode)
+  res <- .Call(
+    R_igraph_get_shortest_path_bellman_ford,
+    graph,
+    from - 1,
+    to - 1,
+    weights,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$vertices <- create_vs(graph, res$vertices)
   }
@@ -989,7 +1590,13 @@ get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, m
   res
 }
 
-get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode=c("out", "in", "all", "total")) {
+get_shortest_path_dijkstra_impl <- function(
+  graph,
+  from,
+  to,
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -1010,9 +1617,16 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode=
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_shortest_path_dijkstra, graph, from-1, to-1, weights, mode)
+  res <- .Call(
+    R_igraph_get_shortest_path_dijkstra,
+    graph,
+    from - 1,
+    to - 1,
+    weights,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$vertices <- create_vs(graph, res$vertices)
   }
@@ -1022,7 +1636,13 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode=
   res
 }
 
-get_all_shortest_paths_impl <- function(graph, weights=NULL, from, to, mode=c("out", "in", "all", "total")) {
+get_all_shortest_paths_impl <- function(
+  graph,
+  weights = NULL,
+  from,
+  to,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1040,14 +1660,27 @@ get_all_shortest_paths_impl <- function(graph, weights=NULL, from, to, mode=c("o
   to <- as_igraph_vs(graph, to)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_all_shortest_paths, graph, weights, from-1, to-1, mode)
+  res <- .Call(
+    R_igraph_get_all_shortest_paths,
+    graph,
+    weights,
+    from - 1,
+    to - 1,
+    mode
+  )
 
   res
 }
 
-get_all_shortest_paths_dijkstra_impl <- function(graph, from, to=V(graph), weights=NULL, mode=c("out", "in", "all", "total")) {
+get_all_shortest_paths_dijkstra_impl <- function(
+  graph,
+  from,
+  to = V(graph),
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -1065,14 +1698,28 @@ get_all_shortest_paths_dijkstra_impl <- function(graph, from, to=V(graph), weigh
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_all_shortest_paths_dijkstra, graph, from-1, to-1, weights, mode)
+  res <- .Call(
+    R_igraph_get_all_shortest_paths_dijkstra,
+    graph,
+    from - 1,
+    to - 1,
+    weights,
+    mode
+  )
 
   res
 }
 
-voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in", "all", "total"), tiebreaker=c("random", "first", "last")) {
+voronoi_impl <- function(
+  graph,
+  generators,
+  ...,
+  weights = NULL,
+  mode = c("out", "in", "all", "total"),
+  tiebreaker = c("random", "first", "last")
+) {
   # Argument checks
   check_dots_empty()
   ensure_igraph(graph)
@@ -1088,14 +1735,29 @@ voronoi_impl <- function(graph, generators, ..., weights=NULL, mode=c("out", "in
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   tiebreaker <- switch_igraph_arg(tiebreaker, "first" = 0L, "last" = 1L, "random" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_voronoi, graph, generators-1, weights, mode, tiebreaker)
+  res <- .Call(
+    R_igraph_voronoi,
+    graph,
+    generators - 1,
+    weights,
+    mode,
+    tiebreaker
+  )
 
   res
 }
 
-get_all_simple_paths_impl <- function(graph, from, to=V(graph), mode=c("out", "in", "all", "total"), minlen=UNLIMITED, maxlen=UNLIMITED, max.results=UNLIMITED) {
+get_all_simple_paths_impl <- function(
+  graph,
+  from,
+  to = V(graph),
+  mode = c("out", "in", "all", "total"),
+  minlen = UNLIMITED,
+  maxlen = UNLIMITED,
+  max.results = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -1108,14 +1770,31 @@ get_all_simple_paths_impl <- function(graph, from, to=V(graph), mode=c("out", "i
   maxlen <- as.numeric(maxlen)
   max.results <- as.numeric(max.results)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_all_simple_paths, graph, from-1, to-1, mode, minlen, maxlen, max.results)
+  res <- .Call(
+    R_igraph_get_all_simple_paths,
+    graph,
+    from - 1,
+    to - 1,
+    mode,
+    minlen,
+    maxlen,
+    max.results
+  )
 
   res
 }
 
-get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mode=c("out", "in", "all", "total")) {
+get_k_shortest_paths_impl <- function(
+  graph,
+  from,
+  to,
+  ...,
+  k,
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   check_dots_empty()
   ensure_igraph(graph)
@@ -1138,14 +1817,28 @@ get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mod
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_k_shortest_paths, graph, weights, k, from-1, to-1, mode)
+  res <- .Call(
+    R_igraph_get_k_shortest_paths,
+    graph,
+    weights,
+    k,
+    from - 1,
+    to - 1,
+    mode
+  )
 
   res
 }
 
-get_widest_path_impl <- function(graph, from, to, weights, mode=c("out", "in", "all", "total")) {
+get_widest_path_impl <- function(
+  graph,
+  from,
+  to,
+  weights,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -1166,9 +1859,16 @@ get_widest_path_impl <- function(graph, from, to, weights, mode=c("out", "in", "
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_widest_path, graph, from-1, to-1, weights, mode)
+  res <- .Call(
+    R_igraph_get_widest_path,
+    graph,
+    from - 1,
+    to - 1,
+    weights,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$vertices <- create_vs(graph, res$vertices)
   }
@@ -1178,7 +1878,13 @@ get_widest_path_impl <- function(graph, from, to, weights, mode=c("out", "in", "
   res
 }
 
-get_widest_paths_impl <- function(graph, from, to=V(graph), weights, mode=c("out", "in", "all", "total")) {
+get_widest_paths_impl <- function(
+  graph,
+  from,
+  to = V(graph),
+  weights,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -1196,14 +1902,27 @@ get_widest_paths_impl <- function(graph, from, to=V(graph), weights, mode=c("out
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_widest_paths, graph, from-1, to-1, weights, mode)
+  res <- .Call(
+    R_igraph_get_widest_paths,
+    graph,
+    from - 1,
+    to - 1,
+    weights,
+    mode
+  )
 
   res
 }
 
-widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph), weights, mode=c("out", "in", "all", "total")) {
+widest_path_widths_dijkstra_impl <- function(
+  graph,
+  from = V(graph),
+  to = V(graph),
+  weights,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -1218,14 +1937,27 @@ widest_path_widths_dijkstra_impl <- function(graph, from=V(graph), to=V(graph),
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_widest_path_widths_dijkstra, graph, from-1, to-1, weights, mode)
+  res <- .Call(
+    R_igraph_widest_path_widths_dijkstra,
+    graph,
+    from - 1,
+    to - 1,
+    weights,
+    mode
+  )
 
   res
 }
 
-widest_path_widths_floyd_warshall_impl <- function(graph, from=V(graph), to=V(graph), weights, mode=c("out", "in", "all", "total")) {
+widest_path_widths_floyd_warshall_impl <- function(
+  graph,
+  from = V(graph),
+  to = V(graph),
+  weights,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -1240,14 +1972,25 @@ widest_path_widths_floyd_warshall_impl <- function(graph, from=V(graph), to=V(gr
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_widest_path_widths_floyd_warshall, graph, from-1, to-1, weights, mode)
+  res <- .Call(
+    R_igraph_widest_path_widths_floyd_warshall,
+    graph,
+    from - 1,
+    to - 1,
+    weights,
+    mode
+  )
 
   res
 }
 
-spanner_impl <- function(graph, stretch, weights=NULL) {
+spanner_impl <- function(
+  graph,
+  stretch,
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   stretch <- as.numeric(stretch)
@@ -1260,16 +2003,28 @@ spanner_impl <- function(graph, stretch, weights=NULL) {
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_spanner, graph, stretch, weights)
+  res <- .Call(
+    R_igraph_spanner,
+    graph,
+    stretch,
+    weights
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_es(graph, res)
   }
   res
 }
 
-betweenness_cutoff_impl <- function(graph, weights=NULL, vids=V(graph), directed=TRUE, normalized=FALSE, cutoff=UNLIMITED) {
+betweenness_cutoff_impl <- function(
+  graph,
+  weights = NULL,
+  vids = V(graph),
+  directed = TRUE,
+  normalized = FALSE,
+  cutoff = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1285,16 +2040,32 @@ betweenness_cutoff_impl <- function(graph, weights=NULL, vids=V(graph), directed
   normalized <- as.logical(normalized)
   cutoff <- as.numeric(cutoff)
 
-  on.exit( .Call(R_igraph_finalizer) )
-  # Function call
-  res <- .Call(R_igraph_betweenness_cutoff, graph, weights, vids-1, directed, normalized, cutoff)
+  on.exit(.Call(R_igraph_finalizer))
+  # Function call
+  res <- .Call(
+    R_igraph_betweenness_cutoff,
+    graph,
+    weights,
+    vids - 1,
+    directed,
+    normalized,
+    cutoff
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-betweenness_subset_impl <- function(graph, weights=NULL, vids=V(graph), sources=V(graph), targets=V(graph), directed=TRUE, normalized=FALSE) {
+betweenness_subset_impl <- function(
+  graph,
+  weights = NULL,
+  vids = V(graph),
+  sources = V(graph),
+  targets = V(graph),
+  directed = TRUE,
+  normalized = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1311,16 +2082,31 @@ betweenness_subset_impl <- function(graph, weights=NULL, vids=V(graph), sources=
   directed <- as.logical(directed)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
-  # Function call
-  res <- .Call(R_igraph_betweenness_subset, graph, weights, vids-1, sources-1, targets-1, directed, normalized)
+  on.exit(.Call(R_igraph_finalizer))
+  # Function call
+  res <- .Call(
+    R_igraph_betweenness_subset,
+    graph,
+    weights,
+    vids - 1,
+    sources - 1,
+    targets - 1,
+    directed,
+    normalized
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-edge_betweenness_impl <- function(graph, weights=NULL, eids=E(graph), directed=TRUE, normalized=FALSE) {
+edge_betweenness_impl <- function(
+  graph,
+  weights = NULL,
+  eids = E(graph),
+  directed = TRUE,
+  normalized = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1335,14 +2121,28 @@ edge_betweenness_impl <- function(graph, weights=NULL, eids=E(graph), directed=T
   directed <- as.logical(directed)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_edge_betweenness, graph, weights, eids-1, directed, normalized)
+  res <- .Call(
+    R_igraph_edge_betweenness,
+    graph,
+    weights,
+    eids - 1,
+    directed,
+    normalized
+  )
 
   res
 }
 
-edge_betweenness_cutoff_impl <- function(graph, weights=NULL, eids=E(graph), directed=TRUE, normalized=FALSE, cutoff=UNLIMITED) {
+edge_betweenness_cutoff_impl <- function(
+  graph,
+  weights = NULL,
+  eids = E(graph),
+  directed = TRUE,
+  normalized = FALSE,
+  cutoff = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1358,14 +2158,30 @@ edge_betweenness_cutoff_impl <- function(graph, weights=NULL, eids=E(graph), dir
   normalized <- as.logical(normalized)
   cutoff <- as.numeric(cutoff)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_edge_betweenness_cutoff, graph, weights, eids-1, directed, normalized, cutoff)
+  res <- .Call(
+    R_igraph_edge_betweenness_cutoff,
+    graph,
+    weights,
+    eids - 1,
+    directed,
+    normalized,
+    cutoff
+  )
 
   res
 }
 
-edge_betweenness_subset_impl <- function(graph, weights=NULL, sources=V(graph), targets=V(graph), eids=E(graph), directed=TRUE, normalized=FALSE) {
+edge_betweenness_subset_impl <- function(
+  graph,
+  weights = NULL,
+  sources = V(graph),
+  targets = V(graph),
+  eids = E(graph),
+  directed = TRUE,
+  normalized = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1382,14 +2198,30 @@ edge_betweenness_subset_impl <- function(graph, weights=NULL, sources=V(graph),
   directed <- as.logical(directed)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_edge_betweenness_subset, graph, weights, sources-1, targets-1, eids-1, directed, normalized)
+  res <- .Call(
+    R_igraph_edge_betweenness_subset,
+    graph,
+    weights,
+    sources - 1,
+    targets - 1,
+    eids - 1,
+    directed,
+    normalized
+  )
 
   res
 }
 
-harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE, cutoff=UNLIMITED) {
+harmonic_centrality_cutoff_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("out", "in", "all", "total"),
+  weights = NULL,
+  normalized = FALSE,
+  cutoff = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
@@ -1405,16 +2237,33 @@ harmonic_centrality_cutoff_impl <- function(graph, vids=V(graph), mode=c("out",
   normalized <- as.logical(normalized)
   cutoff <- as.numeric(cutoff)
 
-  on.exit( .Call(R_igraph_finalizer) )
-  # Function call
-  res <- .Call(R_igraph_harmonic_centrality_cutoff, graph, vids-1, mode, weights, normalized, cutoff)
+  on.exit(.Call(R_igraph_finalizer))
+  # Function call
+  res <- .Call(
+    R_igraph_harmonic_centrality_cutoff,
+    graph,
+    vids - 1,
+    mode,
+    weights,
+    normalized,
+    cutoff
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-personalized_pagerank_impl <- function(graph, weights=NULL, reset=NULL, damping=0.85, directed=TRUE, vids=V(graph), algo=c("prpack", "arpack"), options=NULL) {
+personalized_pagerank_impl <- function(
+  graph,
+  weights = NULL,
+  reset = NULL,
+  damping = 0.85,
+  directed = TRUE,
+  vids = V(graph),
+  algo = c("prpack", "arpack"),
+  options = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1440,16 +2289,36 @@ personalized_pagerank_impl <- function(graph, weights=NULL, reset=NULL, damping=
     }
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_personalized_pagerank, graph, weights, reset, damping, directed, vids-1, algo, options)
+  res <- .Call(
+    R_igraph_personalized_pagerank,
+    graph,
+    weights,
+    reset,
+    damping,
+    directed,
+    vids - 1,
+    algo,
+    options
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$vector) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-personalized_pagerank_vs_impl <- function(graph, weights=NULL, reset.vids, damping=0.85, directed=TRUE, vids=V(graph), algo=c("prpack", "arpack"), options=NULL, details=FALSE) {
+personalized_pagerank_vs_impl <- function(
+  graph,
+  weights = NULL,
+  reset.vids,
+  damping = 0.85,
+  directed = TRUE,
+  vids = V(graph),
+  algo = c("prpack", "arpack"),
+  options = NULL,
+  details = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1475,9 +2344,19 @@ personalized_pagerank_vs_impl <- function(graph, weights=NULL, reset.vids, dampi
     }
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_personalized_pagerank_vs, graph, weights, reset.vids-1, damping, directed, vids-1, algo, options)
+  res <- .Call(
+    R_igraph_personalized_pagerank_vs,
+    graph,
+    weights,
+    reset.vids - 1,
+    damping,
+    directed,
+    vids - 1,
+    algo,
+    options
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$vector) <- vertex_attr(graph, "name", vids)
   }
@@ -1487,45 +2366,76 @@ personalized_pagerank_vs_impl <- function(graph, weights=NULL, reset.vids, dampi
   res
 }
 
-induced_subgraph_impl <- function(graph, vids, impl=c("auto", "copy_and_delete", "create_from_scratch")) {
+induced_subgraph_impl <- function(
+  graph,
+  vids,
+  impl = c("auto", "copy_and_delete", "create_from_scratch")
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
   impl <- switch_igraph_arg(impl, "auto" = 0L, "copy_and_delete" = 1L, "create_from_scratch" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_induced_subgraph, graph, vids-1, impl)
+  res <- .Call(
+    R_igraph_induced_subgraph,
+    graph,
+    vids - 1,
+    impl
+  )
 
   res
 }
 
-subgraph_from_edges_impl <- function(graph, eids, delete.vertices=TRUE) {
+subgraph_from_edges_impl <- function(
+  graph,
+  eids,
+  delete.vertices = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   eids <- as_igraph_es(graph, eids)
   delete.vertices <- as.logical(delete.vertices)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_subgraph_from_edges, graph, eids-1, delete.vertices)
+  res <- .Call(
+    R_igraph_subgraph_from_edges,
+    graph,
+    eids - 1,
+    delete.vertices
+  )
 
   res
 }
 
-reverse_edges_impl <- function(graph, eids=E(graph)) {
+reverse_edges_impl <- function(
+  graph,
+  eids = E(graph)
+) {
   # Argument checks
   ensure_igraph(graph)
   eids <- as_igraph_es(graph, eids)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_reverse_edges, graph, eids-1)
+  res <- .Call(
+    R_igraph_reverse_edges,
+    graph,
+    eids - 1
+  )
 
   res
 }
 
-average_path_length_impl <- function(graph, weights=NULL, directed=TRUE, unconn=TRUE, details=FALSE) {
+average_path_length_impl <- function(
+  graph,
+  weights = NULL,
+  directed = TRUE,
+  unconn = TRUE,
+  details = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1539,79 +2449,131 @@ average_path_length_impl <- function(graph, weights=NULL, directed=TRUE, unconn=
   directed <- as.logical(directed)
   unconn <- as.logical(unconn)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_average_path_length, graph, weights, directed, unconn)
+  res <- .Call(
+    R_igraph_average_path_length,
+    graph,
+    weights,
+    directed,
+    unconn
+  )
   if (!details) {
     res <- res$res
   }
   res
 }
 
-path_length_hist_impl <- function(graph, directed=TRUE) {
+path_length_hist_impl <- function(
+  graph,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_path_length_hist, graph, directed)
+  res <- .Call(
+    R_igraph_path_length_hist,
+    graph,
+    directed
+  )
 
   res
 }
 
-simplify_impl <- function(graph, remove.multiple=TRUE, remove.loops=TRUE, edge.attr.comb=igraph_opt("edge.attr.comb")) {
+simplify_impl <- function(
+  graph,
+  remove.multiple = TRUE,
+  remove.loops = TRUE,
+  edge.attr.comb = igraph_opt("edge.attr.comb")
+) {
   # Argument checks
   ensure_igraph(graph)
   remove.multiple <- as.logical(remove.multiple)
   remove.loops <- as.logical(remove.loops)
   edge.attr.comb <- igraph.i.attribute.combination(edge.attr.comb)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_simplify, graph, remove.multiple, remove.loops, edge.attr.comb)
+  res <- .Call(
+    R_igraph_simplify,
+    graph,
+    remove.multiple,
+    remove.loops,
+    edge.attr.comb
+  )
 
   res
 }
 
-transitivity_undirected_impl <- function(graph, mode=c("nan", "zero")) {
+transitivity_undirected_impl <- function(
+  graph,
+  mode = c("nan", "zero")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_transitivity_undirected, graph, mode)
+  res <- .Call(
+    R_igraph_transitivity_undirected,
+    graph,
+    mode
+  )
 
   res
 }
 
-transitivity_local_undirected_impl <- function(graph, vids=V(graph), mode=c("nan", "zero")) {
+transitivity_local_undirected_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("nan", "zero")
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
   mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_transitivity_local_undirected, graph, vids-1, mode)
+  res <- .Call(
+    R_igraph_transitivity_local_undirected,
+    graph,
+    vids - 1,
+    mode
+  )
 
   res
 }
 
-transitivity_avglocal_undirected_impl <- function(graph, mode=c("nan", "zero")) {
+transitivity_avglocal_undirected_impl <- function(
+  graph,
+  mode = c("nan", "zero")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_transitivity_avglocal_undirected, graph, mode)
+  res <- .Call(
+    R_igraph_transitivity_avglocal_undirected,
+    graph,
+    mode
+  )
 
   res
 }
 
-transitivity_barrat_impl <- function(graph, vids=V(graph), weights=NULL, mode=c("nan", "zero")) {
+transitivity_barrat_impl <- function(
+  graph,
+  vids = V(graph),
+  weights = NULL,
+  mode = c("nan", "zero")
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
@@ -1625,14 +2587,26 @@ transitivity_barrat_impl <- function(graph, vids=V(graph), weights=NULL, mode=c(
   }
   mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_transitivity_barrat, graph, vids-1, weights, mode)
+  res <- .Call(
+    R_igraph_transitivity_barrat,
+    graph,
+    vids - 1,
+    weights,
+    mode
+  )
 
   res
 }
 
-ecc_impl <- function(graph, eids=E(graph), k=3, offset=FALSE, normalize=TRUE) {
+ecc_impl <- function(
+  graph,
+  eids = E(graph),
+  k = 3,
+  offset = FALSE,
+  normalize = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   eids <- as_igraph_es(graph, eids)
@@ -1640,27 +2614,49 @@ ecc_impl <- function(graph, eids=E(graph), k=3, offset=FALSE, normalize=TRUE) {
   offset <- as.logical(offset)
   normalize <- as.logical(normalize)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_ecc, graph, eids-1, k, offset, normalize)
+  res <- .Call(
+    R_igraph_ecc,
+    graph,
+    eids - 1,
+    k,
+    offset,
+    normalize
+  )
 
   res
 }
 
-reciprocity_impl <- function(graph, ignore.loops=TRUE, mode=c("default", "ratio")) {
+reciprocity_impl <- function(
+  graph,
+  ignore.loops = TRUE,
+  mode = c("default", "ratio")
+) {
   # Argument checks
   ensure_igraph(graph)
   ignore.loops <- as.logical(ignore.loops)
   mode <- switch_igraph_arg(mode, "default" = 0L, "ratio" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_reciprocity, graph, ignore.loops, mode)
+  res <- .Call(
+    R_igraph_reciprocity,
+    graph,
+    ignore.loops,
+    mode
+  )
 
   res
 }
 
-maxdegree_impl <- function(graph, ..., v=V(graph), mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once")) {
+maxdegree_impl <- function(
+  graph,
+  ...,
+  v = V(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = c("twice", "none", "once")
+) {
   # Argument checks
   check_dots_empty()
   ensure_igraph(graph)
@@ -1668,14 +2664,24 @@ maxdegree_impl <- function(graph, ..., v=V(graph), mode=c("all", "out", "in", "t
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_maxdegree, graph, v-1, mode, loops)
+  res <- .Call(
+    R_igraph_maxdegree,
+    graph,
+    v - 1,
+    mode,
+    loops
+  )
 
   res
 }
 
-density_impl <- function(graph, weights=NULL, loops=FALSE) {
+density_impl <- function(
+  graph,
+  weights = NULL,
+  loops = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1688,26 +2694,42 @@ density_impl <- function(graph, weights=NULL, loops=FALSE) {
   }
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_density, graph, weights, loops)
+  res <- .Call(
+    R_igraph_density,
+    graph,
+    weights,
+    loops
+  )
 
   res
 }
 
-mean_degree_impl <- function(graph, loops=TRUE) {
+mean_degree_impl <- function(
+  graph,
+  loops = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_mean_degree, graph, loops)
+  res <- .Call(
+    R_igraph_mean_degree,
+    graph,
+    loops
+  )
 
   res
 }
 
-feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "exact_ip")) {
+feedback_arc_set_impl <- function(
+  graph,
+  weights = NULL,
+  algo = c("approx_eades", "exact_ip")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1720,16 +2742,25 @@ feedback_arc_set_impl <- function(graph, weights=NULL, algo=c("approx_eades", "e
   }
   algo <- switch_igraph_arg(algo, "exact_ip" = 0L, "approx_eades" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_feedback_arc_set, graph, weights, algo)
+  res <- .Call(
+    R_igraph_feedback_arc_set,
+    graph,
+    weights,
+    algo
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_es(graph, res)
   }
   res
 }
 
-feedback_vertex_set_impl <- function(graph, weights=NULL, algo=c("exact_ip")) {
+feedback_vertex_set_impl <- function(
+  graph,
+  weights = NULL,
+  algo = c("exact_ip")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% vertex_attr_names(graph)) {
@@ -1742,130 +2773,198 @@ feedback_vertex_set_impl <- function(graph, weights=NULL, algo=c("exact_ip")) {
   }
   algo <- switch_igraph_arg(algo, "exact_ip" = 0L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_feedback_vertex_set, graph, weights, algo)
+  res <- .Call(
+    R_igraph_feedback_vertex_set,
+    graph,
+    weights,
+    algo
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_vs(graph, res)
   }
   res
 }
 
-is_loop_impl <- function(graph, eids=E(graph)) {
+is_loop_impl <- function(
+  graph,
+  eids = E(graph)
+) {
   # Argument checks
   ensure_igraph(graph)
   eids <- as_igraph_es(graph, eids)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_loop, graph, eids-1)
+  res <- .Call(
+    R_igraph_is_loop,
+    graph,
+    eids - 1
+  )
 
   res
 }
 
-is_dag_impl <- function(graph) {
+is_dag_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_dag, graph)
+  res <- .Call(
+    R_igraph_is_dag,
+    graph
+  )
 
   res
 }
 
-is_acyclic_impl <- function(graph) {
+is_acyclic_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_acyclic, graph)
+  res <- .Call(
+    R_igraph_is_acyclic,
+    graph
+  )
 
   res
 }
 
-is_simple_impl <- function(graph, directed=TRUE) {
+is_simple_impl <- function(
+  graph,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_simple, graph, directed)
+  res <- .Call(
+    R_igraph_is_simple,
+    graph,
+    directed
+  )
 
   res
 }
 
-is_multiple_impl <- function(graph, eids=E(graph)) {
+is_multiple_impl <- function(
+  graph,
+  eids = E(graph)
+) {
   # Argument checks
   ensure_igraph(graph)
   eids <- as_igraph_es(graph, eids)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_multiple, graph, eids-1)
+  res <- .Call(
+    R_igraph_is_multiple,
+    graph,
+    eids - 1
+  )
 
   res
 }
 
-has_loop_impl <- function(graph) {
+has_loop_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_has_loop, graph)
+  res <- .Call(
+    R_igraph_has_loop,
+    graph
+  )
 
   res
 }
 
-has_multiple_impl <- function(graph) {
+has_multiple_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_has_multiple, graph)
+  res <- .Call(
+    R_igraph_has_multiple,
+    graph
+  )
 
   res
 }
 
-count_loops_impl <- function(graph) {
+count_loops_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_loops, graph)
+  res <- .Call(
+    R_igraph_count_loops,
+    graph
+  )
 
   res
 }
 
-count_multiple_impl <- function(graph, eids=E(graph)) {
+count_multiple_impl <- function(
+  graph,
+  eids = E(graph)
+) {
   # Argument checks
   ensure_igraph(graph)
   eids <- as_igraph_es(graph, eids)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_multiple, graph, eids-1)
+  res <- .Call(
+    R_igraph_count_multiple,
+    graph,
+    eids - 1
+  )
 
   res
 }
 
-is_perfect_impl <- function(graph) {
+is_perfect_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_perfect, graph)
+  res <- .Call(
+    R_igraph_is_perfect,
+    graph
+  )
 
   res
 }
 
-eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total"), weights=NULL, options=arpack_defaults()) {
+eigenvector_centrality_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  weights = NULL,
+  options = arpack_defaults()
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
@@ -1879,16 +2978,26 @@ eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total
   }
   options <- modify_list(arpack_defaults(), options)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_eigenvector_centrality, graph, mode, weights, options)
+  res <- .Call(
+    R_igraph_eigenvector_centrality,
+    graph,
+    mode,
+    weights,
+    options
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$vector) <- vertex_attr(graph, "name")
   }
   res
 }
 
-hub_and_authority_scores_impl <- function(graph, weights=NULL, options=arpack_defaults()) {
+hub_and_authority_scores_impl <- function(
+  graph,
+  weights = NULL,
+  options = arpack_defaults()
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1901,9 +3010,14 @@ hub_and_authority_scores_impl <- function(graph, weights=NULL, options=arpack_de
   }
   options <- modify_list(arpack_defaults(), options)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hub_and_authority_scores, graph, weights, options)
+  res <- .Call(
+    R_igraph_hub_and_authority_scores,
+    graph,
+    weights,
+    options
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$hub.vector) <- vertex_attr(graph, "name")
   }
@@ -1913,58 +3027,94 @@ hub_and_authority_scores_impl <- function(graph, weights=NULL, options=arpack_de
   res
 }
 
-unfold_tree_impl <- function(graph, mode=c("all", "out", "in", "total"), roots) {
+unfold_tree_impl <- function(
+  graph,
+  mode = c("all", "out", "in", "total"),
+  roots
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   roots <- as.numeric(roots)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_unfold_tree, graph, mode, roots)
+  res <- .Call(
+    R_igraph_unfold_tree,
+    graph,
+    mode,
+    roots
+  )
 
   res
 }
 
-is_mutual_impl <- function(graph, eids=E(graph), loops=TRUE) {
+is_mutual_impl <- function(
+  graph,
+  eids = E(graph),
+  loops = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   eids <- as_igraph_es(graph, eids)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_mutual, graph, eids-1, loops)
+  res <- .Call(
+    R_igraph_is_mutual,
+    graph,
+    eids - 1,
+    loops
+  )
 
   res
 }
 
-has_mutual_impl <- function(graph, loops=TRUE) {
+has_mutual_impl <- function(
+  graph,
+  loops = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_has_mutual, graph, loops)
+  res <- .Call(
+    R_igraph_has_mutual,
+    graph,
+    loops
+  )
 
   res
 }
 
-maximum_cardinality_search_impl <- function(graph) {
+maximum_cardinality_search_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_maximum_cardinality_search, graph)
+  res <- .Call(
+    R_igraph_maximum_cardinality_search,
+    graph
+  )
   if (igraph_opt("return.vs.es")) {
     res$alpham1 <- create_vs(graph, res$alpham1)
   }
   res
 }
 
-avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), neighbor.degree.mode=c("all", "out", "in", "total"), weights=NULL) {
+avg_nearest_neighbor_degree_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("all", "out", "in", "total"),
+  neighbor.degree.mode = c("all", "out", "in", "total"),
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
@@ -1979,16 +3129,29 @@ avg_nearest_neighbor_degree_impl <- function(graph, vids=V(graph), mode=c("all",
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_avg_nearest_neighbor_degree, graph, vids-1, mode, neighbor.degree.mode, weights)
+  res <- .Call(
+    R_igraph_avg_nearest_neighbor_degree,
+    graph,
+    vids - 1,
+    mode,
+    neighbor.degree.mode,
+    weights
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$knn) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE) {
+degree_correlation_vector_impl <- function(
+  graph,
+  weights = NULL,
+  from.mode = c("out", "in", "all", "total"),
+  to.mode = c("in", "out", "all", "total"),
+  directed.neighbors = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2003,14 +3166,28 @@ degree_correlation_vector_impl <- function(graph, weights=NULL, from.mode=c("out
   to.mode <- switch_igraph_arg(to.mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   directed.neighbors <- as.logical(directed.neighbors)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_degree_correlation_vector, graph, weights, from.mode, to.mode, directed.neighbors)
+  res <- .Call(
+    R_igraph_degree_correlation_vector,
+    graph,
+    weights,
+    from.mode,
+    to.mode,
+    directed.neighbors
+  )
 
   res
 }
 
-rich_club_sequence_impl <- function(graph, weights=NULL, vertex.order, normalized=TRUE, loops=FALSE, directed=TRUE) {
+rich_club_sequence_impl <- function(
+  graph,
+  weights = NULL,
+  vertex.order,
+  normalized = TRUE,
+  loops = FALSE,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2026,14 +3203,28 @@ rich_club_sequence_impl <- function(graph, weights=NULL, vertex.order, normalize
   loops <- as.logical(loops)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_rich_club_sequence, graph, weights, vertex.order, normalized, loops, directed)
+  res <- .Call(
+    R_igraph_rich_club_sequence,
+    graph,
+    weights,
+    vertex.order,
+    normalized,
+    loops,
+    directed
+  )
 
   res
 }
 
-strength_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once"), weights=NULL) {
+strength_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = c("twice", "none", "once"),
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
@@ -2048,137 +3239,236 @@ strength_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "tota
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_strength, graph, vids-1, mode, loops, weights)
+  res <- .Call(
+    R_igraph_strength,
+    graph,
+    vids - 1,
+    mode,
+    loops,
+    weights
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-centralization_impl <- function(scores, theoretical.max=0, normalized=TRUE) {
+centralization_impl <- function(
+  scores,
+  theoretical.max = 0,
+  normalized = TRUE
+) {
   # Argument checks
   scores <- as.numeric(scores)
   theoretical.max <- as.numeric(theoretical.max)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization, scores, theoretical.max, normalized)
-
+  res <- .Call(
+    R_igraph_centralization,
+    scores,
+    theoretical.max,
+    normalized
+  )
 
   res
 }
 
-centralization_degree_impl <- function(graph, mode=c("all", "out", "in", "total"), loops=c("twice", "none", "once"), normalized=TRUE) {
+centralization_degree_impl <- function(
+  graph,
+  mode = c("all", "out", "in", "total"),
+  loops = c("twice", "none", "once"),
+  normalized = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_degree, graph, mode, loops, normalized)
+  res <- .Call(
+    R_igraph_centralization_degree,
+    graph,
+    mode,
+    loops,
+    normalized
+  )
 
   res
 }
 
-centralization_degree_tmax_impl <- function(graph=NULL, nodes=0, mode=c("all", "out", "in", "total"), loops) {
+centralization_degree_tmax_impl <- function(
+  graph = NULL,
+  nodes = 0,
+  mode = c("all", "out", "in", "total"),
+  loops
+) {
   # Argument checks
   if (!is.null(graph)) ensure_igraph(graph)
   nodes <- as.numeric(nodes)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_degree_tmax, graph, nodes, mode, loops)
+  res <- .Call(
+    R_igraph_centralization_degree_tmax,
+    graph,
+    nodes,
+    mode,
+    loops
+  )
 
   res
 }
 
-centralization_betweenness_impl <- function(graph, directed=TRUE, normalized=TRUE) {
+centralization_betweenness_impl <- function(
+  graph,
+  directed = TRUE,
+  normalized = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   directed <- as.logical(directed)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_betweenness, graph, directed, normalized)
+  res <- .Call(
+    R_igraph_centralization_betweenness,
+    graph,
+    directed,
+    normalized
+  )
 
   res
 }
 
-centralization_betweenness_tmax_impl <- function(graph=NULL, nodes=0, directed=TRUE) {
+centralization_betweenness_tmax_impl <- function(
+  graph = NULL,
+  nodes = 0,
+  directed = TRUE
+) {
   # Argument checks
   if (!is.null(graph)) ensure_igraph(graph)
   nodes <- as.numeric(nodes)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_betweenness_tmax, graph, nodes, directed)
+  res <- .Call(
+    R_igraph_centralization_betweenness_tmax,
+    graph,
+    nodes,
+    directed
+  )
 
   res
 }
 
-centralization_closeness_impl <- function(graph, mode=c("out", "in", "all", "total"), normalized=TRUE) {
+centralization_closeness_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  normalized = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_closeness, graph, mode, normalized)
+  res <- .Call(
+    R_igraph_centralization_closeness,
+    graph,
+    mode,
+    normalized
+  )
 
   res
 }
 
-centralization_closeness_tmax_impl <- function(graph=NULL, nodes=0, mode=c("out", "in", "all", "total")) {
+centralization_closeness_tmax_impl <- function(
+  graph = NULL,
+  nodes = 0,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   if (!is.null(graph)) ensure_igraph(graph)
   nodes <- as.numeric(nodes)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_closeness_tmax, graph, nodes, mode)
+  res <- .Call(
+    R_igraph_centralization_closeness_tmax,
+    graph,
+    nodes,
+    mode
+  )
 
   res
 }
 
-centralization_eigenvector_centrality_impl <- function(graph, mode=c("out", "in", "all", "total"), options=arpack_defaults(), normalized=TRUE) {
+centralization_eigenvector_centrality_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  options = arpack_defaults(),
+  normalized = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   options <- modify_list(arpack_defaults(), options)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_eigenvector_centrality, graph, mode, options, normalized)
+  res <- .Call(
+    R_igraph_centralization_eigenvector_centrality,
+    graph,
+    mode,
+    options,
+    normalized
+  )
 
   res
 }
 
-centralization_eigenvector_centrality_tmax_impl <- function(graph=NULL, nodes=0, mode=c("out", "in", "all", "total")) {
+centralization_eigenvector_centrality_tmax_impl <- function(
+  graph = NULL,
+  nodes = 0,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   if (!is.null(graph)) ensure_igraph(graph)
   nodes <- as.numeric(nodes)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_centralization_eigenvector_centrality_tmax, graph, nodes, mode)
+  res <- .Call(
+    R_igraph_centralization_eigenvector_centrality_tmax,
+    graph,
+    nodes,
+    mode
+  )
 
   res
 }
 
-assortativity_nominal_impl <- function(graph, weights=NULL, types, directed=TRUE, normalized=TRUE) {
+assortativity_nominal_impl <- function(
+  graph,
+  weights = NULL,
+  types,
+  directed = TRUE,
+  normalized = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2193,14 +3483,28 @@ assortativity_nominal_impl <- function(graph, weights=NULL, types, directed=TRUE
   directed <- as.logical(directed)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_assortativity_nominal, graph, weights, types, directed, normalized)
+  res <- .Call(
+    R_igraph_assortativity_nominal,
+    graph,
+    weights,
+    types,
+    directed,
+    normalized
+  )
 
   res
 }
 
-assortativity_impl <- function(graph, weights=NULL, values, values.in=NULL, directed=TRUE, normalized=TRUE) {
+assortativity_impl <- function(
+  graph,
+  weights = NULL,
+  values,
+  values.in = NULL,
+  directed = TRUE,
+  normalized = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2216,26 +3520,46 @@ assortativity_impl <- function(graph, weights=NULL, values, values.in=NULL, dire
   directed <- as.logical(directed)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_assortativity, graph, weights, values, values.in, directed, normalized)
+  res <- .Call(
+    R_igraph_assortativity,
+    graph,
+    weights,
+    values,
+    values.in,
+    directed,
+    normalized
+  )
 
   res
 }
 
-assortativity_degree_impl <- function(graph, directed=TRUE) {
+assortativity_degree_impl <- function(
+  graph,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_assortativity_degree, graph, directed)
+  res <- .Call(
+    R_igraph_assortativity_degree,
+    graph,
+    directed
+  )
 
   res
 }
 
-joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=UNLIMITED, max.in.degree=UNLIMITED) {
+joint_degree_matrix_impl <- function(
+  graph,
+  weights = NULL,
+  max.out.degree = UNLIMITED,
+  max.in.degree = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2249,14 +3573,29 @@ joint_degree_matrix_impl <- function(graph, weights=NULL, max.out.degree=UNLIMIT
   max.out.degree <- as.numeric(max.out.degree)
   max.in.degree <- as.numeric(max.in.degree)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_joint_degree_matrix, graph, weights, max.out.degree, max.in.degree)
+  res <- .Call(
+    R_igraph_joint_degree_matrix,
+    graph,
+    weights,
+    max.out.degree,
+    max.in.degree
+  )
 
   res
 }
 
-joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out", "in", "all", "total"), to.mode=c("in", "out", "all", "total"), directed.neighbors=TRUE, normalized=TRUE, max.from.degree=UNLIMITED, max.to.degree=UNLIMITED) {
+joint_degree_distribution_impl <- function(
+  graph,
+  weights = NULL,
+  from.mode = c("out", "in", "all", "total"),
+  to.mode = c("in", "out", "all", "total"),
+  directed.neighbors = TRUE,
+  normalized = TRUE,
+  max.from.degree = UNLIMITED,
+  max.to.degree = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2274,14 +3613,31 @@ joint_degree_distribution_impl <- function(graph, weights=NULL, from.mode=c("out
   max.from.degree <- as.numeric(max.from.degree)
   max.to.degree <- as.numeric(max.to.degree)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_joint_degree_distribution, graph, weights, from.mode, to.mode, directed.neighbors, normalized, max.from.degree, max.to.degree)
+  res <- .Call(
+    R_igraph_joint_degree_distribution,
+    graph,
+    weights,
+    from.mode,
+    to.mode,
+    directed.neighbors,
+    normalized,
+    max.from.degree,
+    max.to.degree
+  )
 
   res
 }
 
-joint_type_distribution_impl <- function(graph, weights=NULL, from.types, to.types=NULL, directed=TRUE, normalized=TRUE) {
+joint_type_distribution_impl <- function(
+  graph,
+  weights = NULL,
+  from.types,
+  to.types = NULL,
+  directed = TRUE,
+  normalized = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2297,27 +3653,49 @@ joint_type_distribution_impl <- function(graph, weights=NULL, from.types, to.typ
   directed <- as.logical(directed)
   normalized <- as.logical(normalized)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_joint_type_distribution, graph, weights, from.types, to.types, directed, normalized)
+  res <- .Call(
+    R_igraph_joint_type_distribution,
+    graph,
+    weights,
+    from.types,
+    to.types,
+    directed,
+    normalized
+  )
 
   res
 }
 
-contract_vertices_impl <- function(graph, mapping, vertex.attr.comb=igraph_opt("vertex.attr.comb")) {
+contract_vertices_impl <- function(
+  graph,
+  mapping,
+  vertex.attr.comb = igraph_opt("vertex.attr.comb")
+) {
   # Argument checks
   ensure_igraph(graph)
   mapping <- as.numeric(mapping)-1
   vertex.attr.comb <- igraph.i.attribute.combination(vertex.attr.comb)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_contract_vertices, graph, mapping, vertex.attr.comb)
+  res <- .Call(
+    R_igraph_contract_vertices,
+    graph,
+    mapping,
+    vertex.attr.comb
+  )
 
   res
 }
 
-eccentricity_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all", "out", "in", "total")) {
+eccentricity_impl <- function(
+  graph,
+  weights = NULL,
+  vids = V(graph),
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2331,16 +3709,26 @@ eccentricity_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all",
   vids <- as_igraph_vs(graph, vids)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_eccentricity, graph, weights, vids-1, mode)
+  res <- .Call(
+    R_igraph_eccentricity,
+    graph,
+    weights,
+    vids - 1,
+    mode
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")) {
+graph_center_impl <- function(
+  graph,
+  weights = NULL,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2353,16 +3741,25 @@ graph_center_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "t
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_graph_center, graph, weights, mode)
+  res <- .Call(
+    R_igraph_graph_center,
+    graph,
+    weights,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_vs(graph, res)
   }
   res
 }
 
-radius_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")) {
+radius_impl <- function(
+  graph,
+  weights = NULL,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2375,14 +3772,25 @@ radius_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_radius, graph, weights, mode)
+  res <- .Call(
+    R_igraph_radius,
+    graph,
+    weights,
+    mode
+  )
 
   res
 }
 
-pseudo_diameter_impl <- function(graph, weights=NULL, start.vid, directed=TRUE, unconnected=TRUE) {
+pseudo_diameter_impl <- function(
+  graph,
+  weights = NULL,
+  start.vid,
+  directed = TRUE,
+  unconnected = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2400,14 +3808,25 @@ pseudo_diameter_impl <- function(graph, weights=NULL, start.vid, directed=TRUE,
   directed <- as.logical(directed)
   unconnected <- as.logical(unconnected)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_pseudo_diameter, graph, weights, start.vid-1, directed, unconnected)
+  res <- .Call(
+    R_igraph_pseudo_diameter,
+    graph,
+    weights,
+    start.vid - 1,
+    directed,
+    unconnected
+  )
 
   res
 }
 
-diversity_impl <- function(graph, weights=NULL, vids=V(graph)) {
+diversity_impl <- function(
+  graph,
+  weights = NULL,
+  vids = V(graph)
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2420,16 +3839,28 @@ diversity_impl <- function(graph, weights=NULL, vids=V(graph)) {
   }
   vids <- as_igraph_vs(graph, vids)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_diversity, graph, weights, vids-1)
+  res <- .Call(
+    R_igraph_diversity,
+    graph,
+    weights,
+    vids - 1
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "in", "all", "total"), stuck=c("return", "error")) {
+random_walk_impl <- function(
+  graph,
+  start,
+  steps,
+  weights = NULL,
+  mode = c("out", "in", "all", "total"),
+  stuck = c("return", "error")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2448,9 +3879,17 @@ random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "i
   steps <- as.numeric(steps)
   stuck <- switch_igraph_arg(stuck, "error" = 0L, "return" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
-  # Function call
-  res <- .Call(R_igraph_random_walk, graph, weights, start-1, mode, steps, stuck)
+  on.exit(.Call(R_igraph_finalizer))
+  # Function call
+  res <- .Call(
+    R_igraph_random_walk,
+    graph,
+    weights,
+    start - 1,
+    mode,
+    steps,
+    stuck
+  )
   if (igraph_opt("return.vs.es")) {
     res$vertices <- create_vs(graph, res$vertices)
   }
@@ -2460,7 +3899,11 @@ random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "i
   res
 }
 
-global_efficiency_impl <- function(graph, weights=NULL, directed=TRUE) {
+global_efficiency_impl <- function(
+  graph,
+  weights = NULL,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2473,14 +3916,25 @@ global_efficiency_impl <- function(graph, weights=NULL, directed=TRUE) {
   }
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_global_efficiency, graph, weights, directed)
+  res <- .Call(
+    R_igraph_global_efficiency,
+    graph,
+    weights,
+    directed
+  )
 
   res
 }
 
-local_efficiency_impl <- function(graph, weights=NULL, vids=V(graph), directed=TRUE, mode=c("all", "out", "in", "total")) {
+local_efficiency_impl <- function(
+  graph,
+  weights = NULL,
+  vids = V(graph),
+  directed = TRUE,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2495,16 +3949,28 @@ local_efficiency_impl <- function(graph, weights=NULL, vids=V(graph), directed=T
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_efficiency, graph, weights, vids-1, directed, mode)
+  res <- .Call(
+    R_igraph_local_efficiency,
+    graph,
+    weights,
+    vids - 1,
+    directed,
+    mode
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name", vids)
   }
   res
 }
 
-average_local_efficiency_impl <- function(graph, weights=NULL, directed=TRUE, mode=c("all", "out", "in", "total")) {
+average_local_efficiency_impl <- function(
+  graph,
+  weights = NULL,
+  directed = TRUE,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -2518,50 +3984,79 @@ average_local_efficiency_impl <- function(graph, weights=NULL, directed=TRUE, mo
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_average_local_efficiency, graph, weights, directed, mode)
+  res <- .Call(
+    R_igraph_average_local_efficiency,
+    graph,
+    weights,
+    directed,
+    mode
+  )
 
   res
 }
 
-transitive_closure_impl <- function(graph) {
+transitive_closure_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_transitive_closure, graph)
+  res <- .Call(
+    R_igraph_transitive_closure,
+    graph
+  )
 
   res
 }
 
-trussness_impl <- function(graph) {
+trussness_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_trussness, graph)
+  res <- .Call(
+    R_igraph_trussness,
+    graph
+  )
 
   res
 }
 
-is_graphical_impl <- function(out.deg, in.deg=NULL, allowed.edge.types=c("simple", "loops", "multi", "all")) {
+is_graphical_impl <- function(
+  out.deg,
+  in.deg = NULL,
+  allowed.edge.types = c("simple", "loops", "multi", "all")
+) {
   # Argument checks
   out.deg <- as.numeric(out.deg)
   if (!is.null(in.deg)) in.deg <- as.numeric(in.deg)
   allowed.edge.types <- switch_igraph_arg(allowed.edge.types,
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_graphical, out.deg, in.deg, allowed.edge.types)
+  res <- .Call(
+    R_igraph_is_graphical,
+    out.deg,
+    in.deg,
+    allowed.edge.types
+  )
 
   res
 }
 
-bfs_simple_impl <- function(graph, root, mode=c("out", "in", "all", "total")) {
+bfs_simple_impl <- function(
+  graph,
+  root,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   root <- as_igraph_vs(graph, root)
@@ -2570,72 +4065,117 @@ bfs_simple_impl <- function(graph, root, mode=c("out", "in", "all", "total")) {
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_bfs_simple, graph, root-1, mode)
+  res <- .Call(
+    R_igraph_bfs_simple,
+    graph,
+    root - 1,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$order <- create_vs(graph, res$order)
   }
   res
 }
 
-bipartite_projection_size_impl <- function(graph, types=NULL) {
+bipartite_projection_size_impl <- function(
+  graph,
+  types = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   types <- handle_vertex_type_arg(types, graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_bipartite_projection_size, graph, types)
+  res <- .Call(
+    R_igraph_bipartite_projection_size,
+    graph,
+    types
+  )
 
   res
 }
 
-create_bipartite_impl <- function(types, edges, directed=FALSE) {
+create_bipartite_impl <- function(
+  types,
+  edges,
+  directed = FALSE
+) {
   # Argument checks
   types <- handle_vertex_type_arg(types, graph)
   edges <- as.numeric(edges)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_create_bipartite, types, edges, directed)
+  res <- .Call(
+    R_igraph_create_bipartite,
+    types,
+    edges,
+    directed
+  )
 
   res
 }
 
-biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", "out", "in", "total"), multiple=FALSE) {
+biadjacency_impl <- function(
+  biadjmatrix,
+  directed = FALSE,
+  mode = c("all", "out", "in", "total"),
+  multiple = FALSE
+) {
   # Argument checks
   biadjmatrix[] <- as.numeric(biadjmatrix)
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   multiple <- as.logical(multiple)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_biadjacency, biadjmatrix, directed, mode, multiple)
+  res <- .Call(
+    R_igraph_biadjacency,
+    biadjmatrix,
+    directed,
+    mode,
+    multiple
+  )
   if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
     names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
 
-weighted_biadjacency_impl <- function(biadjmatrix, directed=FALSE, mode=c("all", "out", "in", "total")) {
+weighted_biadjacency_impl <- function(
+  biadjmatrix,
+  directed = FALSE,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   biadjmatrix[] <- as.numeric(biadjmatrix)
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_weighted_biadjacency, biadjmatrix, directed, mode)
+  res <- .Call(
+    R_igraph_weighted_biadjacency,
+    biadjmatrix,
+    directed,
+    mode
+  )
   if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
     names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
 
-get_biadjacency_impl <- function(graph, types, weights=NULL) {
+get_biadjacency_impl <- function(
+  graph,
+  types,
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   types <- handle_vertex_type_arg(types, graph)
@@ -2648,27 +4188,45 @@ get_biadjacency_impl <- function(graph, types, weights=NULL) {
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_biadjacency, graph, types, weights)
+  res <- .Call(
+    R_igraph_get_biadjacency,
+    graph,
+    types,
+    weights
+  )
 
   res
 }
 
-is_bipartite_impl <- function(graph) {
+is_bipartite_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_bipartite, graph)
+  res <- .Call(
+    R_igraph_is_bipartite,
+    graph
+  )
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res$type) <- vertex_attr(graph, "name", V(graph))
   }
   res
 }
 
-bipartite_game_gnp_impl <- function(n1, n2, p, directed=FALSE, mode=c("all", "out", "in", "total"), allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) {
+bipartite_game_gnp_impl <- function(
+  n1,
+  n2,
+  p,
+  directed = FALSE,
+  mode = c("all", "out", "in", "total"),
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  edge.labeled = FALSE
+) {
   # Argument checks
   n1 <- as.numeric(n1)
   n2 <- as.numeric(n2)
@@ -2679,16 +4237,33 @@ bipartite_game_gnp_impl <- function(n1, n2, p, directed=FALSE, mode=c("all", "ou
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
   edge.labeled <- as.logical(edge.labeled)
 
-  on.exit( .Call(R_igraph_finalizer) )
-  # Function call
-  res <- .Call(R_igraph_bipartite_game_gnp, n1, n2, p, directed, mode, allowed.edge.types, edge.labeled)
+  on.exit(.Call(R_igraph_finalizer))
+  # Function call
+  res <- .Call(
+    R_igraph_bipartite_game_gnp,
+    n1,
+    n2,
+    p,
+    directed,
+    mode,
+    allowed.edge.types,
+    edge.labeled
+  )
   if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
     names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
 
-bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "out", "in", "total"), allowed.edge.types=c("simple", "loops", "multi", "all"), edge.labeled=FALSE) {
+bipartite_game_gnm_impl <- function(
+  n1,
+  n2,
+  m,
+  directed = FALSE,
+  mode = c("all", "out", "in", "total"),
+  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  edge.labeled = FALSE
+) {
   # Argument checks
   n1 <- as.numeric(n1)
   n2 <- as.numeric(n2)
@@ -2699,16 +4274,31 @@ bipartite_game_gnm_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou
     "simple" = 0L, "loop" = 1L, "loops" = 1L, "multi" = 6L, "multiple" = 6L, "all" = 7L)
   edge.labeled <- as.logical(edge.labeled)
 
-  on.exit( .Call(R_igraph_finalizer) )
-  # Function call
-  res <- .Call(R_igraph_bipartite_game_gnm, n1, n2, m, directed, mode, allowed.edge.types, edge.labeled)
+  on.exit(.Call(R_igraph_finalizer))
+  # Function call
+  res <- .Call(
+    R_igraph_bipartite_game_gnm,
+    n1,
+    n2,
+    m,
+    directed,
+    mode,
+    allowed.edge.types,
+    edge.labeled
+  )
   if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
     names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
 
-bipartite_iea_game_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "out", "in", "total")) {
+bipartite_iea_game_impl <- function(
+  n1,
+  n2,
+  m,
+  directed = FALSE,
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   n1 <- as.numeric(n1)
   n2 <- as.numeric(n2)
@@ -2716,16 +4306,28 @@ bipartite_iea_game_impl <- function(n1, n2, m, directed=FALSE, mode=c("all", "ou
   directed <- as.logical(directed)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_bipartite_iea_game, n1, n2, m, directed, mode)
+  res <- .Call(
+    R_igraph_bipartite_iea_game,
+    n1,
+    n2,
+    m,
+    directed,
+    mode
+  )
   if (igraph_opt("add.vertex.names") && is_named(res$graph)) {
     names(res$types) <- vertex_attr(res$graph, "name", V(res$graph))
   }
   res
 }
 
-get_laplacian_impl <- function(graph, mode=c("out", "in", "all", "total"), normalization=c("unnormalized", "symmetric", "left", "right"), weights=NULL) {
+get_laplacian_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  normalization = c("unnormalized", "symmetric", "left", "right"),
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
@@ -2739,14 +4341,25 @@ get_laplacian_impl <- function(graph, mode=c("out", "in", "all", "total"), norma
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_laplacian, graph, mode, normalization, weights)
+  res <- .Call(
+    R_igraph_get_laplacian,
+    graph,
+    mode,
+    normalization,
+    weights
+  )
 
   res
 }
 
-get_laplacian_sparse_impl <- function(graph, mode=c("out", "in", "all", "total"), normalization=c("unnormalized", "symmetric", "left", "right"), weights=NULL) {
+get_laplacian_sparse_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  normalization = c("unnormalized", "symmetric", "left", "right"),
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
@@ -2760,212 +4373,334 @@ get_laplacian_sparse_impl <- function(graph, mode=c("out", "in", "all", "total")
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_laplacian_sparse, graph, mode, normalization, weights)
+  res <- .Call(
+    R_igraph_get_laplacian_sparse,
+    graph,
+    mode,
+    normalization,
+    weights
+  )
 
   res
 }
 
-connected_components_impl <- function(graph, mode=c("weak", "strong"), details=FALSE) {
+connected_components_impl <- function(
+  graph,
+  mode = c("weak", "strong"),
+  details = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "weak" = 1L, "strong" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_connected_components, graph, mode)
+  res <- .Call(
+    R_igraph_connected_components,
+    graph,
+    mode
+  )
   if (!details) {
     res <- res$membership
   }
   res
 }
 
-is_connected_impl <- function(graph, mode=c("weak", "strong")) {
+is_connected_impl <- function(
+  graph,
+  mode = c("weak", "strong")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "weak" = 1L, "strong" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_connected, graph, mode)
+  res <- .Call(
+    R_igraph_is_connected,
+    graph,
+    mode
+  )
 
   res
 }
 
-articulation_points_impl <- function(graph) {
+articulation_points_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_articulation_points, graph)
+  res <- .Call(
+    R_igraph_articulation_points,
+    graph
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_vs(graph, res)
   }
   res
 }
 
-biconnected_components_impl <- function(graph) {
+biconnected_components_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_biconnected_components, graph)
+  res <- .Call(
+    R_igraph_biconnected_components,
+    graph
+  )
   if (igraph_opt("return.vs.es")) {
     res$articulation.points <- create_vs(graph, res$articulation.points)
   }
   res
 }
 
-bridges_impl <- function(graph) {
+bridges_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_bridges, graph)
+  res <- .Call(
+    R_igraph_bridges,
+    graph
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_es(graph, res)
   }
   res
 }
 
-is_biconnected_impl <- function(graph) {
+is_biconnected_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_biconnected, graph)
+  res <- .Call(
+    R_igraph_is_biconnected,
+    graph
+  )
 
   res
 }
 
-count_reachable_impl <- function(graph, mode=c("out", "in", "all", "total")) {
+count_reachable_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_reachable, graph, mode)
+  res <- .Call(
+    R_igraph_count_reachable,
+    graph,
+    mode
+  )
 
   res
 }
 
-bond_percolation_impl <- function(graph, edge.order=NULL) {
+bond_percolation_impl <- function(
+  graph,
+  edge.order = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(edge.order)) edge.order <- as_igraph_es(graph, edge.order)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_bond_percolation, graph, edge.order-1)
+  res <- .Call(
+    R_igraph_bond_percolation,
+    graph,
+    edge.order - 1
+  )
 
   res
 }
 
-site_percolation_impl <- function(graph, vertex.order=NULL) {
+site_percolation_impl <- function(
+  graph,
+  vertex.order = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(vertex.order)) vertex.order <- as_igraph_vs(graph, vertex.order)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_site_percolation, graph, vertex.order-1)
+  res <- .Call(
+    R_igraph_site_percolation,
+    graph,
+    vertex.order - 1
+  )
 
   res
 }
 
-edgelist_percolation_impl <- function(edges) {
+edgelist_percolation_impl <- function(
+  edges
+) {
   # Argument checks
 
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_edgelist_percolation, edges)
+  res <- .Call(
+    R_igraph_edgelist_percolation,
+    edges
+  )
 
   res
 }
 
-is_clique_impl <- function(graph, candidate, directed=FALSE) {
+is_clique_impl <- function(
+  graph,
+  candidate,
+  directed = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   candidate <- as_igraph_vs(graph, candidate)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_clique, graph, candidate-1, directed)
+  res <- .Call(
+    R_igraph_is_clique,
+    graph,
+    candidate - 1,
+    directed
+  )
 
   res
 }
 
-cliques_impl <- function(graph, min=UNLIMITED, max=UNLIMITED, max.results=UNLIMITED) {
+cliques_impl <- function(
+  graph,
+  min = UNLIMITED,
+  max = UNLIMITED,
+  max.results = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   min <- as.numeric(min)
   max <- as.numeric(max)
   max.results <- as.numeric(max.results)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_cliques, graph, min, max, max.results)
+  res <- .Call(
+    R_igraph_cliques,
+    graph,
+    min,
+    max,
+    max.results
+  )
 
   res
 }
 
-clique_size_hist_impl <- function(graph, min.size=0, max.size=0) {
+clique_size_hist_impl <- function(
+  graph,
+  min.size = 0,
+  max.size = 0
+) {
   # Argument checks
   ensure_igraph(graph)
   min.size <- as.numeric(min.size)
   max.size <- as.numeric(max.size)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_clique_size_hist, graph, min.size, max.size)
+  res <- .Call(
+    R_igraph_clique_size_hist,
+    graph,
+    min.size,
+    max.size
+  )
 
   res
 }
 
-largest_cliques_impl <- function(graph) {
+largest_cliques_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_largest_cliques, graph)
+  res <- .Call(
+    R_igraph_largest_cliques,
+    graph
+  )
 
   res
 }
 
-maximal_cliques_hist_impl <- function(graph, min.size=0, max.size=0) {
+maximal_cliques_hist_impl <- function(
+  graph,
+  min.size = 0,
+  max.size = 0
+) {
   # Argument checks
   ensure_igraph(graph)
   min.size <- as.numeric(min.size)
   max.size <- as.numeric(max.size)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_maximal_cliques_hist, graph, min.size, max.size)
+  res <- .Call(
+    R_igraph_maximal_cliques_hist,
+    graph,
+    min.size,
+    max.size
+  )
 
   res
 }
 
-clique_number_impl <- function(graph) {
+clique_number_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_clique_number, graph)
+  res <- .Call(
+    R_igraph_clique_number,
+    graph
+  )
 
   res
 }
 
-weighted_cliques_impl <- function(graph, vertex.weights=NULL, maximal=FALSE, min.weight=UNLIMITED, max.weight=UNLIMITED, max.results=UNLIMITED) {
+weighted_cliques_impl <- function(
+  graph,
+  vertex.weights = NULL,
+  maximal = FALSE,
+  min.weight = UNLIMITED,
+  max.weight = UNLIMITED,
+  max.results = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) {
@@ -2981,14 +4716,25 @@ weighted_cliques_impl <- function(graph, vertex.weights=NULL, maximal=FALSE, min
   max.weight <- as.numeric(max.weight)
   max.results <- as.numeric(max.results)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_weighted_cliques, graph, vertex.weights, maximal, min.weight, max.weight, max.results)
+  res <- .Call(
+    R_igraph_weighted_cliques,
+    graph,
+    vertex.weights,
+    maximal,
+    min.weight,
+    max.weight,
+    max.results
+  )
 
   res
 }
 
-largest_weighted_cliques_impl <- function(graph, vertex.weights=NULL) {
+largest_weighted_cliques_impl <- function(
+  graph,
+  vertex.weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) {
@@ -3000,14 +4746,21 @@ largest_weighted_cliques_impl <- function(graph, vertex.weights=NULL) {
     vertex.weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_largest_weighted_cliques, graph, vertex.weights)
+  res <- .Call(
+    R_igraph_largest_weighted_cliques,
+    graph,
+    vertex.weights
+  )
 
   res
 }
 
-weighted_clique_number_impl <- function(graph, vertex.weights=NULL) {
+weighted_clique_number_impl <- function(
+  graph,
+  vertex.weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(vertex.weights) && "weight" %in% vertex_attr_names(graph)) {
@@ -3019,49 +4772,76 @@ weighted_clique_number_impl <- function(graph, vertex.weights=NULL) {
     vertex.weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_weighted_clique_number, graph, vertex.weights)
+  res <- .Call(
+    R_igraph_weighted_clique_number,
+    graph,
+    vertex.weights
+  )
 
   res
 }
 
-is_independent_vertex_set_impl <- function(graph, candidate) {
+is_independent_vertex_set_impl <- function(
+  graph,
+  candidate
+) {
   # Argument checks
   ensure_igraph(graph)
   candidate <- as_igraph_vs(graph, candidate)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_independent_vertex_set, graph, candidate-1)
+  res <- .Call(
+    R_igraph_is_independent_vertex_set,
+    graph,
+    candidate - 1
+  )
 
   res
 }
 
-layout_random_impl <- function(graph) {
+layout_random_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_random, graph)
+  res <- .Call(
+    R_igraph_layout_random,
+    graph
+  )
 
   res
 }
 
-layout_circle_impl <- function(graph, order=V(graph)) {
+layout_circle_impl <- function(
+  graph,
+  order = V(graph)
+) {
   # Argument checks
   ensure_igraph(graph)
   order <- as_igraph_vs(graph, order)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_circle, graph, order-1)
+  res <- .Call(
+    R_igraph_layout_circle,
+    graph,
+    order - 1
+  )
 
   res
 }
 
-layout_star_impl <- function(graph, center=V(graph)[1], order=NULL) {
+layout_star_impl <- function(
+  graph,
+  center = V(graph)[1],
+  order = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   center <- as_igraph_vs(graph, center)
@@ -3070,75 +4850,121 @@ layout_star_impl <- function(graph, center=V(graph)[1], order=NULL) {
   }
   if (!is.null(order)) order <- as.numeric(order)-1
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_star, graph, center-1, order)
+  res <- .Call(
+    R_igraph_layout_star,
+    graph,
+    center - 1,
+    order
+  )
 
   res
 }
 
-layout_grid_impl <- function(graph, width=0) {
+layout_grid_impl <- function(
+  graph,
+  width = 0
+) {
   # Argument checks
   ensure_igraph(graph)
   width <- as.numeric(width)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_grid, graph, width)
+  res <- .Call(
+    R_igraph_layout_grid,
+    graph,
+    width
+  )
 
   res
 }
 
-layout_grid_3d_impl <- function(graph, width=0, height=0) {
+layout_grid_3d_impl <- function(
+  graph,
+  width = 0,
+  height = 0
+) {
   # Argument checks
   ensure_igraph(graph)
   width <- as.numeric(width)
   height <- as.numeric(height)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_grid_3d, graph, width, height)
+  res <- .Call(
+    R_igraph_layout_grid_3d,
+    graph,
+    width,
+    height
+  )
 
   res
 }
 
-roots_for_tree_layout_impl <- function(graph, mode=c("out", "in", "all", "total"), heuristic) {
+roots_for_tree_layout_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  heuristic
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_roots_for_tree_layout, graph, mode, heuristic)
+  res <- .Call(
+    R_igraph_roots_for_tree_layout,
+    graph,
+    mode,
+    heuristic
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_vs(graph, res)
   }
   res
 }
 
-layout_random_3d_impl <- function(graph) {
+layout_random_3d_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_random_3d, graph)
+  res <- .Call(
+    R_igraph_layout_random_3d,
+    graph
+  )
 
   res
 }
 
-layout_sphere_impl <- function(graph) {
+layout_sphere_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_sphere, graph)
+  res <- .Call(
+    R_igraph_layout_sphere,
+    graph
+  )
 
   res
 }
 
-layout_drl_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$default, weights=NULL) {
+layout_drl_impl <- function(
+  graph,
+  res,
+  use.seed = FALSE,
+  options = drl_defaults$default,
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   res[] <- as.numeric(res)
@@ -3153,14 +4979,27 @@ layout_drl_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$def
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_drl, graph, res, use.seed, options, weights)
+  res <- .Call(
+    R_igraph_layout_drl,
+    graph,
+    res,
+    use.seed,
+    options,
+    weights
+  )
 
   res
 }
 
-layout_drl_3d_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$default, weights=NULL) {
+layout_drl_3d_impl <- function(
+  graph,
+  res,
+  use.seed = FALSE,
+  options = drl_defaults$default,
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   res[] <- as.numeric(res)
@@ -3175,14 +5014,28 @@ layout_drl_3d_impl <- function(graph, res, use.seed=FALSE, options=drl_defaults$
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_drl_3d, graph, res, use.seed, options, weights)
+  res <- .Call(
+    R_igraph_layout_drl_3d,
+    graph,
+    res,
+    use.seed,
+    options,
+    weights
+  )
 
   res
 }
 
-layout_sugiyama_impl <- function(graph, layers=NULL, hgap=1, vgap=1, maxiter=100, weights=NULL) {
+layout_sugiyama_impl <- function(
+  graph,
+  layers = NULL,
+  hgap = 1,
+  vgap = 1,
+  maxiter = 100,
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(layers)) layers <- as.numeric(layers)-1
@@ -3198,27 +5051,50 @@ layout_sugiyama_impl <- function(graph, layers=NULL, hgap=1, vgap=1, maxiter=100
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_sugiyama, graph, layers, hgap, vgap, maxiter, weights)
+  res <- .Call(
+    R_igraph_layout_sugiyama,
+    graph,
+    layers,
+    hgap,
+    vgap,
+    maxiter,
+    weights
+  )
 
   res
 }
 
-layout_mds_impl <- function(graph, dist=NULL, dim=2) {
+layout_mds_impl <- function(
+  graph,
+  dist = NULL,
+  dim = 2
+) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(dist)) dist[] <- as.numeric(dist)
   dim <- as.numeric(dim)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_mds, graph, dist, dim)
+  res <- .Call(
+    R_igraph_layout_mds,
+    graph,
+    dist,
+    dim
+  )
 
   res
 }
 
-layout_bipartite_impl <- function(graph, types, hgap=1, vgap=1, maxiter=100) {
+layout_bipartite_impl <- function(
+  graph,
+  types,
+  hgap = 1,
+  vgap = 1,
+  maxiter = 100
+) {
   # Argument checks
   ensure_igraph(graph)
   types <- handle_vertex_type_arg(types, graph)
@@ -3226,14 +5102,29 @@ layout_bipartite_impl <- function(graph, types, hgap=1, vgap=1, maxiter=100) {
   vgap <- as.numeric(vgap)
   maxiter <- as.numeric(maxiter)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_bipartite, graph, types, hgap, vgap, maxiter)
+  res <- .Call(
+    R_igraph_layout_bipartite,
+    graph,
+    types,
+    hgap,
+    vgap,
+    maxiter
+  )
 
   res
 }
 
-layout_gem_impl <- function(graph, res=matrix(), use.seed=FALSE, maxiter=40*vcount(graph)^2, temp.max=vcount(graph), temp.min=1/10, temp.init=sqrt(vcount(graph))) {
+layout_gem_impl <- function(
+  graph,
+  res = matrix(),
+  use.seed = FALSE,
+  maxiter = 40*vcount(graph)^2,
+  temp.max = vcount(graph),
+  temp.min = 1/10,
+  temp.init = sqrt(vcount(graph))
+) {
   # Argument checks
   ensure_igraph(graph)
   res[] <- as.numeric(res)
@@ -3243,14 +5134,35 @@ layout_gem_impl <- function(graph, res=matrix(), use.seed=FALSE, maxiter=40*vcou
   temp.min <- as.numeric(temp.min)
   temp.init <- as.numeric(temp.init)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_gem, graph, res, use.seed, maxiter, temp.max, temp.min, temp.init)
+  res <- .Call(
+    R_igraph_layout_gem,
+    graph,
+    res,
+    use.seed,
+    maxiter,
+    temp.max,
+    temp.min,
+    temp.init
+  )
 
   res
 }
 
-layout_davidson_harel_impl <- function(graph, res=matrix(), use.seed=FALSE, maxiter=10, fineiter=max(10, log2(vcount(graph))), cool.fact=0.75, weight.node.dist=1.0, weight.border=0.0, weight.edge.lengths=edge_density(graph) / 10, weight.edge.crossings=1.0 - sqrt(edge_density(graph)), weight.node.edge.dist=0.2 * (1-edge_density(graph))) {
+layout_davidson_harel_impl <- function(
+  graph,
+  res = matrix(),
+  use.seed = FALSE,
+  maxiter = 10,
+  fineiter = max(10, log2(vcount(graph))),
+  cool.fact = 0.75,
+  weight.node.dist = 1.0,
+  weight.border = 0.0,
+  weight.edge.lengths = edge_density(graph) / 10,
+  weight.edge.crossings = 1.0 - sqrt(edge_density(graph)),
+  weight.node.edge.dist = 0.2 * (1-edge_density(graph))
+) {
   # Argument checks
   ensure_igraph(graph)
   res[] <- as.numeric(res)
@@ -3264,14 +5176,35 @@ layout_davidson_harel_impl <- function(graph, res=matrix(), use.seed=FALSE, maxi
   weight.edge.crossings <- as.numeric(weight.edge.crossings)
   weight.node.edge.dist <- as.numeric(weight.node.edge.dist)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_davidson_harel, graph, res, use.seed, maxiter, fineiter, cool.fact, weight.node.dist, weight.border, weight.edge.lengths, weight.edge.crossings, weight.node.edge.dist)
+  res <- .Call(
+    R_igraph_layout_davidson_harel,
+    graph,
+    res,
+    use.seed,
+    maxiter,
+    fineiter,
+    cool.fact,
+    weight.node.dist,
+    weight.border,
+    weight.edge.lengths,
+    weight.edge.crossings,
+    weight.node.edge.dist
+  )
 
   res
 }
 
-layout_umap_impl <- function(graph, res, use.seed=FALSE, distances=NULL, min.dist=0.0, epochs=200, distances.are.weights=FALSE) {
+layout_umap_impl <- function(
+  graph,
+  res,
+  use.seed = FALSE,
+  distances = NULL,
+  min.dist = 0.0,
+  epochs = 200,
+  distances.are.weights = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   res[] <- as.numeric(res)
@@ -3281,14 +5214,31 @@ layout_umap_impl <- function(graph, res, use.seed=FALSE, distances=NULL, min.dis
   epochs <- as.numeric(epochs)
   distances.are.weights <- as.logical(distances.are.weights)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_umap, graph, res, use.seed, distances, min.dist, epochs, distances.are.weights)
+  res <- .Call(
+    R_igraph_layout_umap,
+    graph,
+    res,
+    use.seed,
+    distances,
+    min.dist,
+    epochs,
+    distances.are.weights
+  )
 
   res
 }
 
-layout_umap_3d_impl <- function(graph, res, use.seed=FALSE, distances=NULL, min.dist=0.0, epochs=200, distances.are.weights=FALSE) {
+layout_umap_3d_impl <- function(
+  graph,
+  res,
+  use.seed = FALSE,
+  distances = NULL,
+  min.dist = 0.0,
+  epochs = 200,
+  distances.are.weights = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   res[] <- as.numeric(res)
@@ -3298,39 +5248,70 @@ layout_umap_3d_impl <- function(graph, res, use.seed=FALSE, distances=NULL, min.
   epochs <- as.numeric(epochs)
   distances.are.weights <- as.logical(distances.are.weights)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_umap_3d, graph, res, use.seed, distances, min.dist, epochs, distances.are.weights)
+  res <- .Call(
+    R_igraph_layout_umap_3d,
+    graph,
+    res,
+    use.seed,
+    distances,
+    min.dist,
+    epochs,
+    distances.are.weights
+  )
 
   res
 }
 
-layout_umap_compute_weights_impl <- function(graph, distances, weights) {
+layout_umap_compute_weights_impl <- function(
+  graph,
+  distances,
+  weights
+) {
   # Argument checks
   ensure_igraph(graph)
   distances <- as.numeric(distances)
   weights <- as.numeric(weights)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_umap_compute_weights, graph, distances, weights)
+  res <- .Call(
+    R_igraph_layout_umap_compute_weights,
+    graph,
+    distances,
+    weights
+  )
 
   res
 }
 
-layout_align_impl <- function(graph, layout) {
+layout_align_impl <- function(
+  graph,
+  layout
+) {
   # Argument checks
   ensure_igraph(graph)
   layout[] <- as.numeric(layout)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_layout_align, graph, layout)
+  res <- .Call(
+    R_igraph_layout_align,
+    graph,
+    layout
+  )
 
   res
 }
 
-similarity_dice_impl <- function(graph, from=V(graph), to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) {
+similarity_dice_impl <- function(
+  graph,
+  from = V(graph),
+  to = V(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -3338,54 +5319,98 @@ similarity_dice_impl <- function(graph, from=V(graph), to=V(graph), mode=c("all"
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_similarity_dice, graph, from-1, to-1, mode, loops)
+  res <- .Call(
+    R_igraph_similarity_dice,
+    graph,
+    from - 1,
+    to - 1,
+    mode,
+    loops
+  )
 
   res
 }
 
-similarity_dice_es_impl <- function(graph, es=E(graph), mode=c("all", "out", "in", "total"), loops=FALSE) {
+similarity_dice_es_impl <- function(
+  graph,
+  es = E(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   es <- as_igraph_es(graph, es)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_similarity_dice_es, graph, es-1, mode, loops)
+  res <- .Call(
+    R_igraph_similarity_dice_es,
+    graph,
+    es - 1,
+    mode,
+    loops
+  )
 
   res
 }
 
-similarity_dice_pairs_impl <- function(graph, pairs, mode=c("all", "out", "in", "total"), loops=FALSE) {
+similarity_dice_pairs_impl <- function(
+  graph,
+  pairs,
+  mode = c("all", "out", "in", "total"),
+  loops = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_similarity_dice_pairs, graph, pairs, mode, loops)
+  res <- .Call(
+    R_igraph_similarity_dice_pairs,
+    graph,
+    pairs,
+    mode,
+    loops
+  )
 
   res
 }
 
-similarity_inverse_log_weighted_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total")) {
+similarity_inverse_log_weighted_impl <- function(
+  graph,
+  vids = V(graph),
+  mode = c("all", "out", "in", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_similarity_inverse_log_weighted, graph, vids-1, mode)
+  res <- .Call(
+    R_igraph_similarity_inverse_log_weighted,
+    graph,
+    vids - 1,
+    mode
+  )
 
   res
 }
 
-similarity_jaccard_impl <- function(graph, from=V(graph), to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) {
+similarity_jaccard_impl <- function(
+  graph,
+  from = V(graph),
+  to = V(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
@@ -3393,54 +5418,98 @@ similarity_jaccard_impl <- function(graph, from=V(graph), to=V(graph), mode=c("a
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_similarity_jaccard, graph, from-1, to-1, mode, loops)
+  res <- .Call(
+    R_igraph_similarity_jaccard,
+    graph,
+    from - 1,
+    to - 1,
+    mode,
+    loops
+  )
 
   res
 }
 
-similarity_jaccard_es_impl <- function(graph, es=E(graph), mode=c("all", "out", "in", "total"), loops=FALSE) {
+similarity_jaccard_es_impl <- function(
+  graph,
+  es = E(graph),
+  mode = c("all", "out", "in", "total"),
+  loops = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   es <- as_igraph_es(graph, es)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_similarity_jaccard_es, graph, es-1, mode, loops)
+  res <- .Call(
+    R_igraph_similarity_jaccard_es,
+    graph,
+    es - 1,
+    mode,
+    loops
+  )
 
   res
 }
 
-similarity_jaccard_pairs_impl <- function(graph, pairs, mode=c("all", "out", "in", "total"), loops=FALSE) {
+similarity_jaccard_pairs_impl <- function(
+  graph,
+  pairs,
+  mode = c("all", "out", "in", "total"),
+  loops = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- as.logical(loops)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_similarity_jaccard_pairs, graph, pairs, mode, loops)
+  res <- .Call(
+    R_igraph_similarity_jaccard_pairs,
+    graph,
+    pairs,
+    mode,
+    loops
+  )
 
   res
 }
 
-compare_communities_impl <- function(comm1, comm2, method=c("vi", "nmi", "split.join", "rand", "adjusted.rand")) {
+compare_communities_impl <- function(
+  comm1,
+  comm2,
+  method = c("vi", "nmi", "split.join", "rand", "adjusted.rand")
+) {
   # Argument checks
   comm1 <- as.numeric(comm1)
   comm2 <- as.numeric(comm2)
   method <- switch_igraph_arg(method, "vi" = 0L, "nmi" = 1L, "split.join" = 2L, "rand" = 3L, "adjusted.rand" = 4L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_compare_communities, comm1, comm2, method)
+  res <- .Call(
+    R_igraph_compare_communities,
+    comm1,
+    comm2,
+    method
+  )
 
   res
 }
 
-modularity_impl <- function(graph, membership, weights=NULL, resolution=1.0, directed=TRUE) {
+modularity_impl <- function(
+  graph,
+  membership,
+  weights = NULL,
+  resolution = 1.0,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   membership <- as.numeric(membership)
@@ -3455,14 +5524,26 @@ modularity_impl <- function(graph, membership, weights=NULL, resolution=1.0, dir
   resolution <- as.numeric(resolution)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_modularity, graph, membership, weights, resolution, directed)
+  res <- .Call(
+    R_igraph_modularity,
+    graph,
+    membership,
+    weights,
+    resolution,
+    directed
+  )
 
   res
 }
 
-modularity_matrix_impl <- function(graph, weights=NULL, resolution=1.0, directed=TRUE) {
+modularity_matrix_impl <- function(
+  graph,
+  weights = NULL,
+  resolution = 1.0,
+  directed = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3476,26 +5557,46 @@ modularity_matrix_impl <- function(graph, weights=NULL, resolution=1.0, directed
   resolution <- as.numeric(resolution)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_modularity_matrix, graph, weights, resolution, directed)
+  res <- .Call(
+    R_igraph_modularity_matrix,
+    graph,
+    weights,
+    resolution,
+    directed
+  )
 
   res
 }
 
-community_fluid_communities_impl <- function(graph, no.of.communities) {
+community_fluid_communities_impl <- function(
+  graph,
+  no.of.communities
+) {
   # Argument checks
   ensure_igraph(graph)
   no.of.communities <- as.numeric(no.of.communities)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_community_fluid_communities, graph, no.of.communities)
+  res <- .Call(
+    R_igraph_community_fluid_communities,
+    graph,
+    no.of.communities
+  )
 
   res
 }
 
-community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", "total"), weights=NULL, initial=NULL, fixed=NULL, lpa.variant=c("dominance", "retention", "fast")) {
+community_label_propagation_impl <- function(
+  graph,
+  mode = c("all", "out", "in", "total"),
+  weights = NULL,
+  initial = NULL,
+  fixed = NULL,
+  lpa.variant = c("dominance", "retention", "fast")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
@@ -3512,14 +5613,26 @@ community_label_propagation_impl <- function(graph, mode=c("all", "out", "in", "
   lpa.variant <- switch_igraph_arg(lpa.variant,
     "dominance" = 0L, "retention" = 1L, "fast" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_community_label_propagation, graph, mode, weights, initial, fixed, lpa.variant)
+  res <- .Call(
+    R_igraph_community_label_propagation,
+    graph,
+    mode,
+    weights,
+    initial,
+    fixed,
+    lpa.variant
+  )
 
   res
 }
 
-community_multilevel_impl <- function(graph, weights=NULL, resolution=1.0) {
+community_multilevel_impl <- function(
+  graph,
+  weights = NULL,
+  resolution = 1.0
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3532,14 +5645,23 @@ community_multilevel_impl <- function(graph, weights=NULL, resolution=1.0) {
   }
   resolution <- as.numeric(resolution)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_community_multilevel, graph, weights, resolution)
+  res <- .Call(
+    R_igraph_community_multilevel,
+    graph,
+    weights,
+    resolution
+  )
 
   res
 }
 
-community_optimal_modularity_impl <- function(graph, weights=NULL, resolution=1.0) {
+community_optimal_modularity_impl <- function(
+  graph,
+  weights = NULL,
+  resolution = 1.0
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3552,14 +5674,29 @@ community_optimal_modularity_impl <- function(graph, weights=NULL, resolution=1.
   }
   resolution <- as.numeric(resolution)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_community_optimal_modularity, graph, weights, resolution)
+  res <- .Call(
+    R_igraph_community_optimal_modularity,
+    graph,
+    weights,
+    resolution
+  )
 
   res
 }
 
-community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL, vertex.in.weights=NULL, resolution, beta=0.01, start=FALSE, n.iterations=2, membership=NULL) {
+community_leiden_impl <- function(
+  graph,
+  weights = NULL,
+  vertex.out.weights = NULL,
+  vertex.in.weights = NULL,
+  resolution,
+  beta = 0.01,
+  start = FALSE,
+  n.iterations = 2,
+  membership = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3592,14 +5729,34 @@ community_leiden_impl <- function(graph, weights=NULL, vertex.out.weights=NULL,
   n.iterations <- as.numeric(n.iterations)
   if (!is.null(membership)) membership <- as.numeric(membership)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_community_leiden, graph, weights, vertex.out.weights, vertex.in.weights, resolution, beta, start, n.iterations, membership)
+  res <- .Call(
+    R_igraph_community_leiden,
+    graph,
+    weights,
+    vertex.out.weights,
+    vertex.in.weights,
+    resolution,
+    beta,
+    start,
+    n.iterations,
+    membership
+  )
 
   res
 }
 
-community_leiden_simple_impl <- function(graph, weights=NULL, objective, resolution, beta=0.01, start=FALSE, n.iterations=2, membership=NULL) {
+community_leiden_simple_impl <- function(
+  graph,
+  weights = NULL,
+  objective,
+  resolution,
+  beta = 0.01,
+  start = FALSE,
+  n.iterations = 2,
+  membership = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3616,26 +5773,50 @@ community_leiden_simple_impl <- function(graph, weights=NULL, objective, resolut
   n.iterations <- as.numeric(n.iterations)
   if (!is.null(membership)) membership <- as.numeric(membership)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_community_leiden_simple, graph, weights, objective, resolution, beta, start, n.iterations, membership)
+  res <- .Call(
+    R_igraph_community_leiden_simple,
+    graph,
+    weights,
+    objective,
+    resolution,
+    beta,
+    start,
+    n.iterations,
+    membership
+  )
 
   res
 }
 
-split_join_distance_impl <- function(comm1, comm2) {
+split_join_distance_impl <- function(
+  comm1,
+  comm2
+) {
   # Argument checks
   comm1 <- as.numeric(comm1)
   comm2 <- as.numeric(comm2)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_split_join_distance, comm1, comm2)
+  res <- .Call(
+    R_igraph_split_join_distance,
+    comm1,
+    comm2
+  )
 
   res
 }
 
-community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL, nb.trials=10, is.regularized=FALSE, regularization.strength=1) {
+community_infomap_impl <- function(
+  graph,
+  edge.weights = NULL,
+  vertex.weights = NULL,
+  nb.trials = 10,
+  is.regularized = FALSE,
+  regularization.strength = 1
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(edge.weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3658,14 +5839,26 @@ community_infomap_impl <- function(graph, edge.weights=NULL, vertex.weights=NULL
   is.regularized <- as.logical(is.regularized)
   regularization.strength <- as.numeric(regularization.strength)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_community_infomap, graph, edge.weights, vertex.weights, nb.trials, is.regularized, regularization.strength)
+  res <- .Call(
+    R_igraph_community_infomap,
+    graph,
+    edge.weights,
+    vertex.weights,
+    nb.trials,
+    is.regularized,
+    regularization.strength
+  )
 
   res
 }
 
-graphlets_impl <- function(graph, weights=NULL, niter=1000) {
+graphlets_impl <- function(
+  graph,
+  weights = NULL,
+  niter = 1000
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3678,14 +5871,24 @@ graphlets_impl <- function(graph, weights=NULL, niter=1000) {
   }
   niter <- as.numeric(niter)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_graphlets, graph, weights, niter)
+  res <- .Call(
+    R_igraph_graphlets,
+    graph,
+    weights,
+    niter
+  )
 
   res
 }
 
-hrg_fit_impl <- function(graph, hrg=NULL, start=FALSE, steps=0) {
+hrg_fit_impl <- function(
+  graph,
+  hrg = NULL,
+  start = FALSE,
+  steps = 0
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(hrg)) {
@@ -3695,28 +5898,42 @@ hrg_fit_impl <- function(graph, hrg=NULL, start=FALSE, steps=0) {
   start <- as.logical(start)
   steps <- as.numeric(steps)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_fit, graph, hrg, start, steps)
+  res <- .Call(
+    R_igraph_hrg_fit,
+    graph,
+    hrg,
+    start,
+    steps
+  )
 
   res
 }
 
-hrg_sample_impl <- function(hrg) {
+hrg_sample_impl <- function(
+  hrg
+) {
   # Argument checks
   if (is.null(hrg)) {
     hrg <- list(left=c(), right=c(), prob=c(), edges=c(), vertices=c())
   }
   hrg <- lapply(hrg[c("left","right","prob","edges","vertices")], as.numeric)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_sample, hrg)
+  res <- .Call(
+    R_igraph_hrg_sample,
+    hrg
+  )
 
   res
 }
 
-hrg_sample_many_impl <- function(hrg, num.samples) {
+hrg_sample_many_impl <- function(
+  hrg,
+  num.samples
+) {
   # Argument checks
   if (is.null(hrg)) {
     hrg <- list(left=c(), right=c(), prob=c(), edges=c(), vertices=c())
@@ -3724,23 +5941,32 @@ hrg_sample_many_impl <- function(hrg, num.samples) {
   hrg <- lapply(hrg[c("left","right","prob","edges","vertices")], as.numeric)
   num.samples <- as.numeric(num.samples)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_sample_many, hrg, num.samples)
+  res <- .Call(
+    R_igraph_hrg_sample_many,
+    hrg,
+    num.samples
+  )
 
   res
 }
 
-hrg_game_impl <- function(hrg) {
+hrg_game_impl <- function(
+  hrg
+) {
   # Argument checks
   if (is.null(hrg)) {
     hrg <- list(left=c(), right=c(), prob=c(), edges=c(), vertices=c())
   }
   hrg <- lapply(hrg[c("left","right","prob","edges","vertices")], as.numeric)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_game, hrg)
+  res <- .Call(
+    R_igraph_hrg_game,
+    hrg
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Hierarchical random graph model'
@@ -3749,7 +5975,12 @@ hrg_game_impl <- function(hrg) {
   res
 }
 
-hrg_consensus_impl <- function(graph, hrg=NULL, start=FALSE, num.samples=10000) {
+hrg_consensus_impl <- function(
+  graph,
+  hrg = NULL,
+  start = FALSE,
+  num.samples = 10000
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(hrg)) {
@@ -3759,14 +5990,26 @@ hrg_consensus_impl <- function(graph, hrg=NULL, start=FALSE, num.samples=10000)
   start <- as.logical(start)
   num.samples <- as.numeric(num.samples)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_consensus, graph, hrg, start, num.samples)
+  res <- .Call(
+    R_igraph_hrg_consensus,
+    graph,
+    hrg,
+    start,
+    num.samples
+  )
 
   res
 }
 
-hrg_predict_impl <- function(graph, hrg=NULL, start=FALSE, num.samples=10000, num.bins=25) {
+hrg_predict_impl <- function(
+  graph,
+  hrg = NULL,
+  start = FALSE,
+  num.samples = 10000,
+  num.bins = 25
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(hrg)) {
@@ -3777,29 +6020,46 @@ hrg_predict_impl <- function(graph, hrg=NULL, start=FALSE, num.samples=10000, nu
   num.samples <- as.numeric(num.samples)
   num.bins <- as.numeric(num.bins)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_predict, graph, hrg, start, num.samples, num.bins)
+  res <- .Call(
+    R_igraph_hrg_predict,
+    graph,
+    hrg,
+    start,
+    num.samples,
+    num.bins
+  )
   if (igraph_opt("return.vs.es")) {
     res$edges <- create_vs(graph, res$edges)
   }
   res
 }
 
-hrg_create_impl <- function(graph, prob) {
+hrg_create_impl <- function(
+  graph,
+  prob
+) {
   # Argument checks
   ensure_igraph(graph)
   prob <- as.numeric(prob)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_create, graph, prob)
+  res <- .Call(
+    R_igraph_hrg_create,
+    graph,
+    prob
+  )
 
   class(res) <- "igraphHRG"
   res
 }
 
-hrg_resize_impl <- function(hrg, newsize) {
+hrg_resize_impl <- function(
+  hrg,
+  newsize
+) {
   # Argument checks
   if (is.null(hrg)) {
     hrg <- list(left=c(), right=c(), prob=c(), edges=c(), vertices=c())
@@ -3807,43 +6067,61 @@ hrg_resize_impl <- function(hrg, newsize) {
   hrg <- lapply(hrg[c("left","right","prob","edges","vertices")], as.numeric)
   newsize <- as.numeric(newsize)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_resize, hrg, newsize)
+  res <- .Call(
+    R_igraph_hrg_resize,
+    hrg,
+    newsize
+  )
 
   res
 }
 
-hrg_size_impl <- function(hrg) {
+hrg_size_impl <- function(
+  hrg
+) {
   # Argument checks
   if (is.null(hrg)) {
     hrg <- list(left=c(), right=c(), prob=c(), edges=c(), vertices=c())
   }
   hrg <- lapply(hrg[c("left","right","prob","edges","vertices")], as.numeric)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_hrg_size, hrg)
-
+  res <- .Call(
+    R_igraph_hrg_size,
+    hrg
+  )
 
   res
 }
 
-from_hrg_dendrogram_impl <- function(hrg) {
+from_hrg_dendrogram_impl <- function(
+  hrg
+) {
   # Argument checks
   if (is.null(hrg)) {
     hrg <- list(left=c(), right=c(), prob=c(), edges=c(), vertices=c())
   }
   hrg <- lapply(hrg[c("left","right","prob","edges","vertices")], as.numeric)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_from_hrg_dendrogram, hrg)
+  res <- .Call(
+    R_igraph_from_hrg_dendrogram,
+    hrg
+  )
 
   res
 }
 
-get_adjacency_sparse_impl <- function(graph, type=c("both", "upper", "lower"), weights=NULL, loops=c("once", "none", "twice")) {
+get_adjacency_sparse_impl <- function(
+  graph,
+  type = c("both", "upper", "lower"),
+  weights = NULL,
+  loops = c("once", "none", "twice")
+) {
   # Argument checks
   ensure_igraph(graph)
   type <- switch_igraph_arg(type, "upper" = 0L, "lower" = 1L, "both" = 2L)
@@ -3857,14 +6135,24 @@ get_adjacency_sparse_impl <- function(graph, type=c("both", "upper", "lower"), w
   }
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_adjacency_sparse, graph, type, weights, loops)
+  res <- .Call(
+    R_igraph_get_adjacency_sparse,
+    graph,
+    type,
+    weights,
+    loops
+  )
 
   res
 }
 
-get_stochastic_impl <- function(graph, column.wise=FALSE, weights=NULL) {
+get_stochastic_impl <- function(
+  graph,
+  column.wise = FALSE,
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   column.wise <- as.logical(column.wise)
@@ -3877,14 +6165,23 @@ get_stochastic_impl <- function(graph, column.wise=FALSE, weights=NULL) {
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_stochastic, graph, column.wise, weights)
+  res <- .Call(
+    R_igraph_get_stochastic,
+    graph,
+    column.wise,
+    weights
+  )
 
   res
 }
 
-get_stochastic_sparse_impl <- function(graph, column.wise=FALSE, weights=NULL) {
+get_stochastic_sparse_impl <- function(
+  graph,
+  column.wise = FALSE,
+  weights = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   column.wise <- as.logical(column.wise)
@@ -3897,52 +6194,88 @@ get_stochastic_sparse_impl <- function(graph, column.wise=FALSE, weights=NULL) {
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_stochastic_sparse, graph, column.wise, weights)
+  res <- .Call(
+    R_igraph_get_stochastic_sparse,
+    graph,
+    column.wise,
+    weights
+  )
 
   res
 }
 
-to_directed_impl <- function(graph, mode=c("mutual", "arbitrary", "random", "acyclic")) {
+to_directed_impl <- function(
+  graph,
+  mode = c("mutual", "arbitrary", "random", "acyclic")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "arbitrary" = 0L, "mutual" = 1L, "random" = 2L, "acyclic" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_to_directed, graph, mode)
+  res <- .Call(
+    R_igraph_to_directed,
+    graph,
+    mode
+  )
 
   res
 }
 
-to_undirected_impl <- function(graph, mode=c("collapse", "each", "mutual"), edge.attr.comb=igraph_opt("edge.attr.comb")) {
+to_undirected_impl <- function(
+  graph,
+  mode = c("collapse", "each", "mutual"),
+  edge.attr.comb = igraph_opt("edge.attr.comb")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "collapse" = 1L, "each" = 0L, "mutual" = 2L)
   edge.attr.comb <- igraph.i.attribute.combination(edge.attr.comb)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_to_undirected, graph, mode, edge.attr.comb)
+  res <- .Call(
+    R_igraph_to_undirected,
+    graph,
+    mode,
+    edge.attr.comb
+  )
 
   res
 }
 
-motifs_randesu_impl <- function(graph, size=3, cut.prob=NULL) {
+motifs_randesu_impl <- function(
+  graph,
+  size = 3,
+  cut.prob = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   size <- as.numeric(size)
   if (!is.null(cut.prob)) cut.prob <- as.numeric(cut.prob)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_motifs_randesu, graph, size, cut.prob)
+  res <- .Call(
+    R_igraph_motifs_randesu,
+    graph,
+    size,
+    cut.prob
+  )
 
   res
 }
 
-motifs_randesu_estimate_impl <- function(graph, size=3, cut.prob=NULL, sample.size, sample=NULL) {
+motifs_randesu_estimate_impl <- function(
+  graph,
+  size = 3,
+  cut.prob = NULL,
+  sample.size,
+  sample = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   size <- as.numeric(size)
@@ -3950,72 +6283,114 @@ motifs_randesu_estimate_impl <- function(graph, size=3, cut.prob=NULL, sample.si
   sample.size <- as.numeric(sample.size)
   if (!is.null(sample)) sample <- as.numeric(sample)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_motifs_randesu_estimate, graph, size, cut.prob, sample.size, sample)
+  res <- .Call(
+    R_igraph_motifs_randesu_estimate,
+    graph,
+    size,
+    cut.prob,
+    sample.size,
+    sample
+  )
 
   res
 }
 
-motifs_randesu_no_impl <- function(graph, size=3, cut.prob=NULL) {
+motifs_randesu_no_impl <- function(
+  graph,
+  size = 3,
+  cut.prob = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   size <- as.numeric(size)
   if (!is.null(cut.prob)) cut.prob <- as.numeric(cut.prob)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_motifs_randesu_no, graph, size, cut.prob)
+  res <- .Call(
+    R_igraph_motifs_randesu_no,
+    graph,
+    size,
+    cut.prob
+  )
 
   res
 }
 
-dyad_census_impl <- function(graph) {
+dyad_census_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_dyad_census, graph)
+  res <- .Call(
+    R_igraph_dyad_census,
+    graph
+  )
 
   res
 }
 
-triad_census_impl <- function(graph) {
+triad_census_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_triad_census, graph)
+  res <- .Call(
+    R_igraph_triad_census,
+    graph
+  )
 
   res
 }
 
-count_adjacent_triangles_impl <- function(graph, vids=V(graph)) {
+count_adjacent_triangles_impl <- function(
+  graph,
+  vids = V(graph)
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_adjacent_triangles, graph, vids-1)
+  res <- .Call(
+    R_igraph_count_adjacent_triangles,
+    graph,
+    vids - 1
+  )
 
   res
 }
 
-count_triangles_impl <- function(graph) {
+count_triangles_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_triangles, graph)
+  res <- .Call(
+    R_igraph_count_triangles,
+    graph
+  )
 
   res
 }
 
-local_scan_0_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "total")) {
+local_scan_0_impl <- function(
+  graph,
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -4028,14 +6403,24 @@ local_scan_0_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "t
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_0, graph, weights, mode)
+  res <- .Call(
+    R_igraph_local_scan_0,
+    graph,
+    weights,
+    mode
+  )
 
   res
 }
 
-local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "in", "all", "total")) {
+local_scan_0_them_impl <- function(
+  us,
+  them,
+  weights.them = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(us)
   ensure_igraph(them)
@@ -4049,14 +6434,24 @@ local_scan_0_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "i
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_0_them, us, them, weights.them, mode)
+  res <- .Call(
+    R_igraph_local_scan_0_them,
+    us,
+    them,
+    weights.them,
+    mode
+  )
 
   res
 }
 
-local_scan_1_ecount_impl <- function(graph, weights=NULL, mode=c("out", "in", "all", "total")) {
+local_scan_1_ecount_impl <- function(
+  graph,
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -4069,14 +6464,24 @@ local_scan_1_ecount_impl <- function(graph, weights=NULL, mode=c("out", "in", "a
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_1_ecount, graph, weights, mode)
+  res <- .Call(
+    R_igraph_local_scan_1_ecount,
+    graph,
+    weights,
+    mode
+  )
 
   res
 }
 
-local_scan_1_ecount_them_impl <- function(us, them, weights.them=NULL, mode=c("out", "in", "all", "total")) {
+local_scan_1_ecount_them_impl <- function(
+  us,
+  them,
+  weights.them = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(us)
   ensure_igraph(them)
@@ -4090,14 +6495,25 @@ local_scan_1_ecount_them_impl <- function(us, them, weights.them=NULL, mode=c("o
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_1_ecount_them, us, them, weights.them, mode)
+  res <- .Call(
+    R_igraph_local_scan_1_ecount_them,
+    us,
+    them,
+    weights.them,
+    mode
+  )
 
   res
 }
 
-local_scan_k_ecount_impl <- function(graph, k, weights=NULL, mode=c("out", "in", "all", "total")) {
+local_scan_k_ecount_impl <- function(
+  graph,
+  k,
+  weights = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   k <- as.numeric(k)
@@ -4111,14 +6527,26 @@ local_scan_k_ecount_impl <- function(graph, k, weights=NULL, mode=c("out", "in",
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_k_ecount, graph, k, weights, mode)
+  res <- .Call(
+    R_igraph_local_scan_k_ecount,
+    graph,
+    k,
+    weights,
+    mode
+  )
 
   res
 }
 
-local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c("out", "in", "all", "total")) {
+local_scan_k_ecount_them_impl <- function(
+  us,
+  them,
+  k,
+  weights.them = NULL,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(us)
   ensure_igraph(them)
@@ -4133,14 +6561,25 @@ local_scan_k_ecount_them_impl <- function(us, them, k, weights.them=NULL, mode=c
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_k_ecount_them, us, them, k, weights.them, mode)
+  res <- .Call(
+    R_igraph_local_scan_k_ecount_them,
+    us,
+    them,
+    k,
+    weights.them,
+    mode
+  )
 
   res
 }
 
-local_scan_neighborhood_ecount_impl <- function(graph, weights=NULL, neighborhoods) {
+local_scan_neighborhood_ecount_impl <- function(
+  graph,
+  weights = NULL,
+  neighborhoods
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -4152,14 +6591,23 @@ local_scan_neighborhood_ecount_impl <- function(graph, weights=NULL, neighborhoo
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_neighborhood_ecount, graph, weights, neighborhoods)
+  res <- .Call(
+    R_igraph_local_scan_neighborhood_ecount,
+    graph,
+    weights,
+    neighborhoods
+  )
 
   res
 }
 
-local_scan_subset_ecount_impl <- function(graph, weights=NULL, subsets) {
+local_scan_subset_ecount_impl <- function(
+  graph,
+  weights = NULL,
+  subsets
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -4171,77 +6619,123 @@ local_scan_subset_ecount_impl <- function(graph, weights=NULL, subsets) {
     weights <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_local_scan_subset_ecount, graph, weights, subsets)
+  res <- .Call(
+    R_igraph_local_scan_subset_ecount,
+    graph,
+    weights,
+    subsets
+  )
 
   res
 }
 
-list_triangles_impl <- function(graph) {
+list_triangles_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_list_triangles, graph)
+  res <- .Call(
+    R_igraph_list_triangles,
+    graph
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_vs(graph, res)
   }
   res
 }
 
-join_impl <- function(left, right) {
+join_impl <- function(
+  left,
+  right
+) {
   # Argument checks
   ensure_igraph(left)
   ensure_igraph(right)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_join, left, right)
+  res <- .Call(
+    R_igraph_join,
+    left,
+    right
+  )
 
   res
 }
 
-induced_subgraph_map_impl <- function(graph, vids, impl=c("auto", "copy_and_delete", "create_from_scratch")) {
+induced_subgraph_map_impl <- function(
+  graph,
+  vids,
+  impl = c("auto", "copy_and_delete", "create_from_scratch")
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
   impl <- switch_igraph_arg(impl, "auto" = 0L, "copy_and_delete" = 1L, "create_from_scratch" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_induced_subgraph_map, graph, vids-1, impl)
+  res <- .Call(
+    R_igraph_induced_subgraph_map,
+    graph,
+    vids - 1,
+    impl
+  )
 
   res
 }
 
-mycielskian_impl <- function(graph, k=1) {
+mycielskian_impl <- function(
+  graph,
+  k = 1
+) {
   # Argument checks
   ensure_igraph(graph)
   k <- as.numeric(k)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_mycielskian, graph, k)
+  res <- .Call(
+    R_igraph_mycielskian,
+    graph,
+    k
+  )
 
   res
 }
 
-product_impl <- function(g1, g2, type=c("cartesian", "lexicographic", "strong", "tensor", "modular")) {
+product_impl <- function(
+  g1,
+  g2,
+  type = c("cartesian", "lexicographic", "strong", "tensor", "modular")
+) {
   # Argument checks
   ensure_igraph(g1)
   ensure_igraph(g2)
   type <- switch_igraph_arg(type, "cartesian" = 0L, "lexicographic" = 1L, "strong" = 2L, "tensor" = 3L, "modular" = 4L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_product, g1, g2, type)
+  res <- .Call(
+    R_igraph_product,
+    g1,
+    g2,
+    type
+  )
 
   res
 }
 
-rooted_product_impl <- function(g1, g2, root) {
+rooted_product_impl <- function(
+  g1,
+  g2,
+  root
+) {
   # Argument checks
   ensure_igraph(g1)
   ensure_igraph(g2)
@@ -4250,14 +6744,22 @@ rooted_product_impl <- function(g1, g2, root) {
     stop("No vertex was specified")
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_rooted_product, g1, g2, root-1)
+  res <- .Call(
+    R_igraph_rooted_product,
+    g1,
+    g2,
+    root - 1
+  )
 
   res
 }
 
-gomory_hu_tree_impl <- function(graph, capacity=NULL) {
+gomory_hu_tree_impl <- function(
+  graph,
+  capacity = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
@@ -4269,14 +6771,23 @@ gomory_hu_tree_impl <- function(graph, capacity=NULL) {
     capacity <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_gomory_hu_tree, graph, capacity)
+  res <- .Call(
+    R_igraph_gomory_hu_tree,
+    graph,
+    capacity
+  )
 
   res
 }
 
-maxflow_impl <- function(graph, source, target, capacity=NULL) {
+maxflow_impl <- function(
+  graph,
+  source,
+  target,
+  capacity = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
@@ -4296,9 +6807,15 @@ maxflow_impl <- function(graph, source, target, capacity=NULL) {
     capacity <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_maxflow, graph, source-1, target-1, capacity)
+  res <- .Call(
+    R_igraph_maxflow,
+    graph,
+    source - 1,
+    target - 1,
+    capacity
+  )
   if (igraph_opt("return.vs.es")) {
     res$cut <- create_es(graph, res$cut)
   }
@@ -4311,7 +6828,11 @@ maxflow_impl <- function(graph, source, target, capacity=NULL) {
   res
 }
 
-residual_graph_impl <- function(graph, capacity, flow) {
+residual_graph_impl <- function(
+  graph,
+  capacity,
+  flow
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
@@ -4324,14 +6845,23 @@ residual_graph_impl <- function(graph, capacity, flow) {
   }
   flow <- as.numeric(flow)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_residual_graph, graph, capacity, flow)
+  res <- .Call(
+    R_igraph_residual_graph,
+    graph,
+    capacity,
+    flow
+  )
 
   res
 }
 
-reverse_residual_graph_impl <- function(graph, capacity, flow) {
+reverse_residual_graph_impl <- function(
+  graph,
+  capacity,
+  flow
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
@@ -4344,14 +6874,24 @@ reverse_residual_graph_impl <- function(graph, capacity, flow) {
   }
   flow <- as.numeric(flow)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_reverse_residual_graph, graph, capacity, flow)
+  res <- .Call(
+    R_igraph_reverse_residual_graph,
+    graph,
+    capacity,
+    flow
+  )
 
   res
 }
 
-st_mincut_impl <- function(graph, source, target, capacity=NULL) {
+st_mincut_impl <- function(
+  graph,
+  source,
+  target,
+  capacity = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
@@ -4371,9 +6911,15 @@ st_mincut_impl <- function(graph, source, target, capacity=NULL) {
     capacity <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_st_mincut, graph, source-1, target-1, capacity)
+  res <- .Call(
+    R_igraph_st_mincut,
+    graph,
+    source - 1,
+    target - 1,
+    capacity
+  )
   if (igraph_opt("return.vs.es")) {
     res$cut <- create_es(graph, res$cut)
   }
@@ -4386,7 +6932,11 @@ st_mincut_impl <- function(graph, source, target, capacity=NULL) {
   res
 }
 
-dominator_tree_impl <- function(graph, root, mode=c("out", "in", "all", "total")) {
+dominator_tree_impl <- function(
+  graph,
+  root,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   root <- as_igraph_vs(graph, root)
@@ -4395,16 +6945,25 @@ dominator_tree_impl <- function(graph, root, mode=c("out", "in", "all", "total")
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_dominator_tree, graph, root-1, mode)
+  res <- .Call(
+    R_igraph_dominator_tree,
+    graph,
+    root - 1,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$leftout <- create_vs(graph, res$leftout)
   }
   res
 }
 
-all_st_cuts_impl <- function(graph, source, target) {
+all_st_cuts_impl <- function(
+  graph,
+  source,
+  target
+) {
   # Argument checks
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
@@ -4416,14 +6975,24 @@ all_st_cuts_impl <- function(graph, source, target) {
     stop("No vertex was specified")
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_all_st_cuts, graph, source-1, target-1)
+  res <- .Call(
+    R_igraph_all_st_cuts,
+    graph,
+    source - 1,
+    target - 1
+  )
 
   res
 }
 
-all_st_mincuts_impl <- function(graph, source, target, capacity=NULL) {
+all_st_mincuts_impl <- function(
+  graph,
+  source,
+  target,
+  capacity = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
@@ -4443,94 +7012,144 @@ all_st_mincuts_impl <- function(graph, source, target, capacity=NULL) {
     capacity <- NULL
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_all_st_mincuts, graph, source-1, target-1, capacity)
+  res <- .Call(
+    R_igraph_all_st_mincuts,
+    graph,
+    source - 1,
+    target - 1,
+    capacity
+  )
 
   res
 }
 
-even_tarjan_reduction_impl <- function(graph) {
+even_tarjan_reduction_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_even_tarjan_reduction, graph)
+  res <- .Call(
+    R_igraph_even_tarjan_reduction,
+    graph
+  )
 
   res
 }
 
-is_separator_impl <- function(graph, candidate) {
+is_separator_impl <- function(
+  graph,
+  candidate
+) {
   # Argument checks
   ensure_igraph(graph)
   candidate <- as_igraph_vs(graph, candidate)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_separator, graph, candidate-1)
+  res <- .Call(
+    R_igraph_is_separator,
+    graph,
+    candidate - 1
+  )
 
   res
 }
 
-is_minimal_separator_impl <- function(graph, candidate) {
+is_minimal_separator_impl <- function(
+  graph,
+  candidate
+) {
   # Argument checks
   ensure_igraph(graph)
   candidate <- as_igraph_vs(graph, candidate)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_minimal_separator, graph, candidate-1)
+  res <- .Call(
+    R_igraph_is_minimal_separator,
+    graph,
+    candidate - 1
+  )
 
   res
 }
 
-all_minimal_st_separators_impl <- function(graph) {
+all_minimal_st_separators_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_all_minimal_st_separators, graph)
+  res <- .Call(
+    R_igraph_all_minimal_st_separators,
+    graph
+  )
 
   res
 }
 
-minimum_size_separators_impl <- function(graph) {
+minimum_size_separators_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_minimum_size_separators, graph)
+  res <- .Call(
+    R_igraph_minimum_size_separators,
+    graph
+  )
 
   res
 }
 
-isoclass_impl <- function(graph) {
+isoclass_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_isoclass, graph)
+  res <- .Call(
+    R_igraph_isoclass,
+    graph
+  )
 
   res
 }
 
-isomorphic_impl <- function(graph1, graph2) {
+isomorphic_impl <- function(
+  graph1,
+  graph2
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_isomorphic, graph1, graph2)
+  res <- .Call(
+    R_igraph_isomorphic,
+    graph1,
+    graph2
+  )
 
   res
 }
 
-automorphism_group_impl <- function(graph, colors=NULL) {
+automorphism_group_impl <- function(
+  graph,
+  colors = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (missing(colors)) {
@@ -4544,14 +7163,21 @@ automorphism_group_impl <- function(graph, colors=NULL) {
     colors <- as.numeric(colors)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_automorphism_group, graph, colors)
+  res <- .Call(
+    R_igraph_automorphism_group,
+    graph,
+    colors
+  )
 
   res
 }
 
-count_automorphisms_impl <- function(graph, colors=NULL) {
+count_automorphisms_impl <- function(
+  graph,
+  colors = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (missing(colors)) {
@@ -4565,39 +7191,66 @@ count_automorphisms_impl <- function(graph, colors=NULL) {
     colors <- as.numeric(colors)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_automorphisms, graph, colors)
+  res <- .Call(
+    R_igraph_count_automorphisms,
+    graph,
+    colors
+  )
 
   res
 }
 
-isoclass_subgraph_impl <- function(graph, vids) {
+isoclass_subgraph_impl <- function(
+  graph,
+  vids
+) {
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_isoclass_subgraph, graph, vids-1)
+  res <- .Call(
+    R_igraph_isoclass_subgraph,
+    graph,
+    vids - 1
+  )
 
   res
 }
 
-isoclass_create_impl <- function(size, number, directed=TRUE) {
+isoclass_create_impl <- function(
+  size,
+  number,
+  directed = TRUE
+) {
   # Argument checks
   size <- as.numeric(size)
   number <- as.numeric(number)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_isoclass_create, size, number, directed)
+  res <- .Call(
+    R_igraph_isoclass_create,
+    size,
+    number,
+    directed
+  )
 
   res
 }
 
-isomorphic_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
+isomorphic_vf2_impl <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4642,14 +7295,29 @@ isomorphic_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color
     edge.color2 <- as.numeric(edge.color2)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_isomorphic_vf2, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
+  res <- .Call(
+    R_igraph_isomorphic_vf2,
+    graph1,
+    graph2,
+    vertex.color1,
+    vertex.color2,
+    edge.color1,
+    edge.color2
+  )
 
   res
 }
 
-get_isomorphisms_vf2_callback_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
+get_isomorphisms_vf2_callback_impl <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4694,14 +7362,29 @@ get_isomorphisms_vf2_callback_impl <- function(graph1, graph2, vertex.color1=NUL
     edge.color2 <- as.numeric(edge.color2)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_isomorphisms_vf2_callback, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
+  res <- .Call(
+    R_igraph_get_isomorphisms_vf2_callback,
+    graph1,
+    graph2,
+    vertex.color1,
+    vertex.color2,
+    edge.color1,
+    edge.color2
+  )
 
   res
 }
 
-count_isomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
+count_isomorphisms_vf2_impl <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4746,14 +7429,29 @@ count_isomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vert
     edge.color2 <- as.numeric(edge.color2)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_isomorphisms_vf2, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
+  res <- .Call(
+    R_igraph_count_isomorphisms_vf2,
+    graph1,
+    graph2,
+    vertex.color1,
+    vertex.color2,
+    edge.color1,
+    edge.color2
+  )
 
   res
 }
 
-get_isomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
+get_isomorphisms_vf2_impl <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4798,26 +7496,48 @@ get_isomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex
     edge.color2 <- as.numeric(edge.color2)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_isomorphisms_vf2, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
+  res <- .Call(
+    R_igraph_get_isomorphisms_vf2,
+    graph1,
+    graph2,
+    vertex.color1,
+    vertex.color2,
+    edge.color1,
+    edge.color2
+  )
 
   res
 }
 
-subisomorphic_impl <- function(graph1, graph2) {
+subisomorphic_impl <- function(
+  graph1,
+  graph2
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_subisomorphic, graph1, graph2)
+  res <- .Call(
+    R_igraph_subisomorphic,
+    graph1,
+    graph2
+  )
 
   res
 }
 
-subisomorphic_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
+subisomorphic_vf2_impl <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4862,14 +7582,29 @@ subisomorphic_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.co
     edge.color2 <- as.numeric(edge.color2)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_subisomorphic_vf2, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
+  res <- .Call(
+    R_igraph_subisomorphic_vf2,
+    graph1,
+    graph2,
+    vertex.color1,
+    vertex.color2,
+    edge.color1,
+    edge.color2
+  )
 
   res
 }
 
-count_subisomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
+count_subisomorphisms_vf2_impl <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4914,14 +7649,29 @@ count_subisomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, v
     edge.color2 <- as.numeric(edge.color2)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_subisomorphisms_vf2, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
+  res <- .Call(
+    R_igraph_count_subisomorphisms_vf2,
+    graph1,
+    graph2,
+    vertex.color1,
+    vertex.color2,
+    edge.color1,
+    edge.color2
+  )
 
   res
 }
 
-get_subisomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, vertex.color2=NULL, edge.color1=NULL, edge.color2=NULL) {
+get_subisomorphisms_vf2_impl <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -4966,14 +7716,25 @@ get_subisomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1=NULL, ver
     edge.color2 <- as.numeric(edge.color2)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_get_subisomorphisms_vf2, graph1, graph2, vertex.color1, vertex.color2, edge.color1, edge.color2)
+  res <- .Call(
+    R_igraph_get_subisomorphisms_vf2,
+    graph1,
+    graph2,
+    vertex.color1,
+    vertex.color2,
+    edge.color1,
+    edge.color2
+  )
 
   res
 }
 
-canonical_permutation_impl <- function(graph, colors=NULL) {
+canonical_permutation_impl <- function(
+  graph,
+  colors = NULL
+) {
   # Argument checks
   ensure_igraph(graph)
   if (missing(colors)) {
@@ -4987,14 +7748,22 @@ canonical_permutation_impl <- function(graph, colors=NULL) {
     colors <- as.numeric(colors)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_canonical_permutation, graph, colors)
+  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")) {
+canonical_permutation_bliss_impl <- function(
+  graph,
+  colors = NULL,
+  sh = c("fm", "f", "fs", "fl", "flm", "fsm")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (missing(colors)) {
@@ -5009,26 +7778,44 @@ canonical_permutation_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f",
   }
   sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_canonical_permutation_bliss, graph, colors, sh)
+  res <- .Call(
+    R_igraph_canonical_permutation_bliss,
+    graph,
+    colors,
+    sh
+  )
 
   res
 }
 
-permute_vertices_impl <- function(graph, permutation) {
+permute_vertices_impl <- function(
+  graph,
+  permutation
+) {
   # Argument checks
   ensure_igraph(graph)
   permutation <- as.numeric(permutation)-1
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_permute_vertices, graph, permutation)
+  res <- .Call(
+    R_igraph_permute_vertices,
+    graph,
+    permutation
+  )
 
   res
 }
 
-isomorphic_bliss_impl <- function(graph1, graph2, colors1=NULL, colors2=NULL, sh=c("fm", "f", "fs", "fl", "flm", "fsm")) {
+isomorphic_bliss_impl <- function(
+  graph1,
+  graph2,
+  colors1 = NULL,
+  colors2 = NULL,
+  sh = c("fm", "f", "fs", "fl", "flm", "fsm")
+) {
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
@@ -5054,14 +7841,25 @@ isomorphic_bliss_impl <- function(graph1, graph2, colors1=NULL, colors2=NULL, sh
   }
   sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_isomorphic_bliss, graph1, graph2, colors1, colors2, sh)
+  res <- .Call(
+    R_igraph_isomorphic_bliss,
+    graph1,
+    graph2,
+    colors1,
+    colors2,
+    sh
+  )
 
   res
 }
 
-count_automorphisms_bliss_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)) {
@@ -5076,14 +7874,24 @@ count_automorphisms_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", "
   }
   sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_count_automorphisms_bliss, graph, colors, sh)
+  res <- .Call(
+    R_igraph_count_automorphisms_bliss,
+    graph,
+    colors,
+    sh
+  )
 
   res
 }
 
-automorphism_group_bliss_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)) {
@@ -5098,65 +7906,105 @@ automorphism_group_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", "f
   }
   sh <- switch_igraph_arg(sh, "f" = 0L, "fl" = 1L, "fs" = 2L, "fm" = 3L, "flm" = 4L, "fsm" = 5L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_automorphism_group_bliss, graph, colors, sh)
+  res <- .Call(
+    R_igraph_automorphism_group_bliss,
+    graph,
+    colors,
+    sh
+  )
   if (!details) {
     res <- res$generators
   }
   res
 }
 
-simplify_and_colorize_impl <- function(graph) {
+simplify_and_colorize_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_simplify_and_colorize, graph)
+  res <- .Call(
+    R_igraph_simplify_and_colorize,
+    graph
+  )
 
   res
 }
 
-graph_count_impl <- function(n, directed=FALSE) {
+graph_count_impl <- function(
+  n,
+  directed = FALSE
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_graph_count, n, directed)
+  res <- .Call(
+    R_igraph_graph_count,
+    n,
+    directed
+  )
 
   res
 }
 
-is_matching_impl <- function(graph, types=NULL, matching) {
+is_matching_impl <- function(
+  graph,
+  types = NULL,
+  matching
+) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(types)) types <- handle_vertex_type_arg(types, graph)
   matching <- as.numeric(matching)-1
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_matching, graph, types, matching)
+  res <- .Call(
+    R_igraph_is_matching,
+    graph,
+    types,
+    matching
+  )
 
   res
 }
 
-is_maximal_matching_impl <- function(graph, types=NULL, matching) {
+is_maximal_matching_impl <- function(
+  graph,
+  types = NULL,
+  matching
+) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(types)) types <- handle_vertex_type_arg(types, graph)
   matching <- as.numeric(matching)-1
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_maximal_matching, graph, types, matching)
+  res <- .Call(
+    R_igraph_is_maximal_matching,
+    graph,
+    types,
+    matching
+  )
 
   res
 }
 
-maximum_bipartite_matching_impl <- function(graph, types, weights=NULL, eps=.Machine$double.eps) {
+maximum_bipartite_matching_impl <- function(
+  graph,
+  types,
+  weights = NULL,
+  eps = .Machine$double.eps
+) {
   # Argument checks
   ensure_igraph(graph)
   types <- handle_vertex_type_arg(types, graph)
@@ -5170,14 +8018,28 @@ maximum_bipartite_matching_impl <- function(graph, types, weights=NULL, eps=.Mac
   }
   eps <- as.numeric(eps)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_maximum_bipartite_matching, graph, types, weights, eps)
+  res <- .Call(
+    R_igraph_maximum_bipartite_matching,
+    graph,
+    types,
+    weights,
+    eps
+  )
 
   res
 }
 
-adjacency_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c("lm", "la", "sa"), scaled=TRUE, cvec=strength(graph, weights=weights)/(vcount(graph)-1), options=arpack_defaults()) {
+adjacency_spectral_embedding_impl <- function(
+  graph,
+  no,
+  weights = NULL,
+  which = c("lm", "la", "sa"),
+  scaled = TRUE,
+  cvec = strength(graph, weights=weights)/(vcount(graph)-1),
+  options = arpack_defaults()
+) {
   # Argument checks
   ensure_igraph(graph)
   no <- as.numeric(no)
@@ -5194,14 +8056,31 @@ adjacency_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c("
   cvec <- as.numeric(cvec)
   options <- modify_list(arpack_defaults(), options)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_adjacency_spectral_embedding, graph, no, weights, which, scaled, cvec, options)
+  res <- .Call(
+    R_igraph_adjacency_spectral_embedding,
+    graph,
+    no,
+    weights,
+    which,
+    scaled,
+    cvec,
+    options
+  )
 
   res
 }
 
-laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c("lm", "la", "sa"), type=c("default", "D-A", "DAD", "I-DAD", "OAP"), scaled=TRUE, options=arpack_defaults()) {
+laplacian_spectral_embedding_impl <- function(
+  graph,
+  no,
+  weights = NULL,
+  which = c("lm", "la", "sa"),
+  type = c("default", "D-A", "DAD", "I-DAD", "OAP"),
+  scaled = TRUE,
+  options = arpack_defaults()
+) {
   # Argument checks
   ensure_igraph(graph)
   no <- as.numeric(no)
@@ -5221,14 +8100,28 @@ laplacian_spectral_embedding_impl <- function(graph, no, weights=NULL, which=c("
   scaled <- as.logical(scaled)
   options <- modify_list(arpack_defaults(), options)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_laplacian_spectral_embedding, graph, no, weights, which, type, scaled, options)
+  res <- .Call(
+    R_igraph_laplacian_spectral_embedding,
+    graph,
+    no,
+    weights,
+    which,
+    type,
+    scaled,
+    options
+  )
 
   res
 }
 
-eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack"), which=list(), options=arpack_defaults()) {
+eigen_adjacency_impl <- function(
+  graph,
+  algorithm = c("arpack", "auto", "lapack", "comp_auto", "comp_lapack", "comp_arpack"),
+  which = list(),
+  options = arpack_defaults()
+) {
   # Argument checks
   ensure_igraph(graph)
   algorithm <- switch_igraph_arg(algorithm, "auto" = 0L, "lapack" = 1L,
@@ -5238,83 +8131,133 @@ eigen_adjacency_impl <- function(graph, algorithm=c("arpack", "auto", "lapack",
   which.tmp[ names(which) ] <- which ; which <- which.tmp
   options <- modify_list(arpack_defaults(), options)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_eigen_adjacency, graph, algorithm, which, options)
+  res <- .Call(
+    R_igraph_eigen_adjacency,
+    graph,
+    algorithm,
+    which,
+    options
+  )
 
   res
 }
 
-power_law_fit_impl <- function(data, xmin=-1, force.continuous=FALSE) {
+power_law_fit_impl <- function(
+  data,
+  xmin = -1,
+  force.continuous = FALSE
+) {
   # Argument checks
   data <- as.numeric(data)
   xmin <- as.numeric(xmin)
   force.continuous <- as.logical(force.continuous)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_power_law_fit, data, xmin, force.continuous)
+  res <- .Call(
+    R_igraph_power_law_fit,
+    data,
+    xmin,
+    force.continuous
+  )
 
   res
 }
 
-sir_impl <- function(graph, beta, gamma, no.sim=100) {
+sir_impl <- function(
+  graph,
+  beta,
+  gamma,
+  no.sim = 100
+) {
   # Argument checks
   ensure_igraph(graph)
   beta <- as.numeric(beta)
   gamma <- as.numeric(gamma)
   no.sim <- as.numeric(no.sim)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_sir, graph, beta, gamma, no.sim)
+  res <- .Call(
+    R_igraph_sir,
+    graph,
+    beta,
+    gamma,
+    no.sim
+  )
 
   class(res) <- "sir"
   res
 }
 
-convex_hull_2d_impl <- function(data) {
+convex_hull_2d_impl <- function(
+  data
+) {
   # Argument checks
   data[] <- as.numeric(data)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_convex_hull_2d, data)
+  res <- .Call(
+    R_igraph_convex_hull_2d,
+    data
+  )
 
   res
 }
 
-dim_select_impl <- function(sv) {
+dim_select_impl <- function(
+  sv
+) {
   # Argument checks
   sv <- as.numeric(sv)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_dim_select, sv)
+  res <- .Call(
+    R_igraph_dim_select,
+    sv
+  )
 
   res
 }
 
-solve_lsap_impl <- function(c, n) {
+solve_lsap_impl <- function(
+  c,
+  n
+) {
   # Argument checks
   c[] <- as.numeric(c)
   n <- as.numeric(n)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_solve_lsap, c, n)
+  res <- .Call(
+    R_igraph_solve_lsap,
+    c,
+    n
+  )
 
   res
 }
 
-find_cycle_impl <- function(graph, mode=c("out", "in", "all", "total")) {
+find_cycle_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total")
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_find_cycle, graph, mode)
+  res <- .Call(
+    R_igraph_find_cycle,
+    graph,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$vertices <- create_vs(graph, res$vertices)
   }
@@ -5324,7 +8267,13 @@ find_cycle_impl <- function(graph, mode=c("out", "in", "all", "total")) {
   res
 }
 
-simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), min.cycle.length=UNLIMITED, max.cycle.length=UNLIMITED, max.results=UNLIMITED) {
+simple_cycles_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  min.cycle.length = UNLIMITED,
+  max.cycle.length = UNLIMITED,
+  max.results = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
@@ -5332,31 +8281,48 @@ simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), min.c
   max.cycle.length <- as.numeric(max.cycle.length)
   max.results <- as.numeric(max.results)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_simple_cycles, graph, mode, min.cycle.length, max.cycle.length, max.results)
+  res <- .Call(
+    R_igraph_simple_cycles,
+    graph,
+    mode,
+    min.cycle.length,
+    max.cycle.length,
+    max.results
+  )
 
   res
 }
 
-is_eulerian_impl <- function(graph) {
+is_eulerian_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_eulerian, graph)
+  res <- .Call(
+    R_igraph_is_eulerian,
+    graph
+  )
 
   res
 }
 
-eulerian_path_impl <- function(graph) {
+eulerian_path_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_eulerian_path, graph)
+  res <- .Call(
+    R_igraph_eulerian_path,
+    graph
+  )
   if (igraph_opt("return.vs.es")) {
     res$epath <- create_es(graph, res$epath)
   }
@@ -5366,13 +8332,18 @@ eulerian_path_impl <- function(graph) {
   res
 }
 
-eulerian_cycle_impl <- function(graph) {
+eulerian_cycle_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_eulerian_cycle, graph)
+  res <- .Call(
+    R_igraph_eulerian_cycle,
+    graph
+  )
   if (igraph_opt("return.vs.es")) {
     res$epath <- create_es(graph, res$epath)
   }
@@ -5382,7 +8353,12 @@ eulerian_cycle_impl <- function(graph) {
   res
 }
 
-fundamental_cycles_impl <- function(graph, weights=NULL, start=-1, bfs.cutoff=UNLIMITED) {
+fundamental_cycles_impl <- function(
+  graph,
+  weights = NULL,
+  start = -1,
+  bfs.cutoff = UNLIMITED
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -5399,14 +8375,26 @@ fundamental_cycles_impl <- function(graph, weights=NULL, start=-1, bfs.cutoff=UN
   }
   bfs.cutoff <- as.numeric(bfs.cutoff)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_fundamental_cycles, graph, weights, start-1, bfs.cutoff)
+  res <- .Call(
+    R_igraph_fundamental_cycles,
+    graph,
+    weights,
+    start - 1,
+    bfs.cutoff
+  )
 
   res
 }
 
-minimum_cycle_basis_impl <- function(graph, weights=NULL, bfs.cutoff=UNLIMITED, complete=TRUE, use.cycle.order=TRUE) {
+minimum_cycle_basis_impl <- function(
+  graph,
+  weights = NULL,
+  bfs.cutoff = UNLIMITED,
+  complete = TRUE,
+  use.cycle.order = TRUE
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -5421,21 +8409,36 @@ minimum_cycle_basis_impl <- function(graph, weights=NULL, bfs.cutoff=UNLIMITED,
   complete <- as.logical(complete)
   use.cycle.order <- as.logical(use.cycle.order)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_minimum_cycle_basis, graph, weights, bfs.cutoff, complete, use.cycle.order)
+  res <- .Call(
+    R_igraph_minimum_cycle_basis,
+    graph,
+    weights,
+    bfs.cutoff,
+    complete,
+    use.cycle.order
+  )
 
   res
 }
 
-is_tree_impl <- function(graph, mode=c("out", "in", "all", "total"), details=FALSE) {
+is_tree_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  details = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_tree, graph, mode)
+  res <- .Call(
+    R_igraph_is_tree,
+    graph,
+    mode
+  )
   if (igraph_opt("return.vs.es") && vcount(graph) != 0) {
     res$root <- create_vs(graph, res$root)
   }
@@ -5445,14 +8448,22 @@ is_tree_impl <- function(graph, mode=c("out", "in", "all", "total"), details=FAL
   res
 }
 
-is_forest_impl <- function(graph, mode=c("out", "in", "all", "total"), details=FALSE) {
+is_forest_impl <- function(
+  graph,
+  mode = c("out", "in", "all", "total"),
+  details = FALSE
+) {
   # Argument checks
   ensure_igraph(graph)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_forest, graph, mode)
+  res <- .Call(
+    R_igraph_is_forest,
+    graph,
+    mode
+  )
   if (igraph_opt("return.vs.es")) {
     res$roots <- create_vs(graph, res$roots)
   }
@@ -5462,13 +8473,18 @@ is_forest_impl <- function(graph, mode=c("out", "in", "all", "total"), details=F
   res
 }
 
-from_prufer_impl <- function(prufer) {
+from_prufer_impl <- function(
+  prufer
+) {
   # Argument checks
   prufer <- as.numeric(prufer)-1
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_from_prufer, prufer)
+  res <- .Call(
+    R_igraph_from_prufer,
+    prufer
+  )
 
   if (igraph_opt("add.params")) {
     res$name <- 'Tree from Prufer sequence'
@@ -5478,41 +8494,62 @@ from_prufer_impl <- function(prufer) {
   res
 }
 
-to_prufer_impl <- function(graph) {
+to_prufer_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_to_prufer, graph)
+  res <- .Call(
+    R_igraph_to_prufer,
+    graph
+  )
 
   res
 }
 
-tree_from_parent_vector_impl <- function(parents, type=c("out", "in", "undirected")) {
+tree_from_parent_vector_impl <- function(
+  parents,
+  type = c("out", "in", "undirected")
+) {
   # Argument checks
   parents <- as.numeric(parents)-1
   type <- switch_igraph_arg(type, "out" = 0L, "in" = 1L, "undirected" = 2L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_tree_from_parent_vector, parents, type)
+  res <- .Call(
+    R_igraph_tree_from_parent_vector,
+    parents,
+    type
+  )
 
   res
 }
 
-is_complete_impl <- function(graph) {
+is_complete_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_complete, graph)
+  res <- .Call(
+    R_igraph_is_complete,
+    graph
+  )
 
   res
 }
 
-minimum_spanning_tree_impl <- function(graph, weights=NULL, method=c("automatic", "unweighted", "prim", "kruskal")) {
+minimum_spanning_tree_impl <- function(
+  graph,
+  weights = NULL,
+  method = c("automatic", "unweighted", "prim", "kruskal")
+) {
   # Argument checks
   ensure_igraph(graph)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -5525,16 +8562,24 @@ minimum_spanning_tree_impl <- function(graph, weights=NULL, method=c("automatic"
   }
   method <- switch_igraph_arg(method, "automatic" = 0L, "unweighted" = 1L, "prim" = 2L, "kruskal" = 3L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_minimum_spanning_tree, graph, weights, method)
+  res <- .Call(
+    R_igraph_minimum_spanning_tree,
+    graph,
+    weights,
+    method
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_es(graph, res)
   }
   res
 }
 
-random_spanning_tree_impl <- function(graph, vid=-1) {
+random_spanning_tree_impl <- function(
+  graph,
+  vid = -1
+) {
   # Argument checks
   ensure_igraph(graph)
   if (!is.null(vid)) vid <- as_igraph_vs(graph, vid)
@@ -5542,131 +8587,209 @@ random_spanning_tree_impl <- function(graph, vid=-1) {
     stop("No vertex was specified")
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_random_spanning_tree, graph, vid-1)
+  res <- .Call(
+    R_igraph_random_spanning_tree,
+    graph,
+    vid - 1
+  )
   if (igraph_opt("return.vs.es")) {
     res <- create_es(graph, res)
   }
   res
 }
 
-tree_game_impl <- function(n, directed=FALSE, method=c("lerw", "prufer")) {
+tree_game_impl <- function(
+  n,
+  directed = FALSE,
+  method = c("lerw", "prufer")
+) {
   # Argument checks
   n <- as.numeric(n)
   directed <- as.logical(directed)
   method <- switch_igraph_arg(method, "prufer" = 0L, "lerw" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_tree_game, n, directed, method)
+  res <- .Call(
+    R_igraph_tree_game,
+    n,
+    directed,
+    method
+  )
 
   res
 }
 
-nearest_neighbor_graph_impl <- function(points, metric, neighbors, cutoff, directed) {
+nearest_neighbor_graph_impl <- function(
+  points,
+  metric,
+  neighbors,
+  cutoff,
+  directed
+) {
   # Argument checks
   points[] <- as.numeric(points)
   neighbors <- as.numeric(neighbors)
   cutoff <- as.numeric(cutoff)
   directed <- as.logical(directed)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_nearest_neighbor_graph, points, metric, neighbors, cutoff, directed)
+  res <- .Call(
+    R_igraph_nearest_neighbor_graph,
+    points,
+    metric,
+    neighbors,
+    cutoff,
+    directed
+  )
 
   res
 }
 
-delaunay_graph_impl <- function(points) {
+delaunay_graph_impl <- function(
+  points
+) {
   # Argument checks
   points[] <- as.numeric(points)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_delaunay_graph, points)
+  res <- .Call(
+    R_igraph_delaunay_graph,
+    points
+  )
 
   res
 }
 
-gabriel_graph_impl <- function(points) {
+gabriel_graph_impl <- function(
+  points
+) {
   # Argument checks
   points[] <- as.numeric(points)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_gabriel_graph, points)
+  res <- .Call(
+    R_igraph_gabriel_graph,
+    points
+  )
 
   res
 }
 
-relative_neighborhood_graph_impl <- function(points) {
+relative_neighborhood_graph_impl <- function(
+  points
+) {
   # Argument checks
   points[] <- as.numeric(points)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_relative_neighborhood_graph, points)
+  res <- .Call(
+    R_igraph_relative_neighborhood_graph,
+    points
+  )
 
   res
 }
 
-lune_beta_skeleton_impl <- function(points, beta=1) {
+lune_beta_skeleton_impl <- function(
+  points,
+  beta = 1
+) {
   # Argument checks
   points[] <- as.numeric(points)
   beta <- as.numeric(beta)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_lune_beta_skeleton, points, beta)
+  res <- .Call(
+    R_igraph_lune_beta_skeleton,
+    points,
+    beta
+  )
 
   res
 }
 
-circle_beta_skeleton_impl <- function(points, beta=1) {
+circle_beta_skeleton_impl <- function(
+  points,
+  beta = 1
+) {
   # Argument checks
   points[] <- as.numeric(points)
   beta <- as.numeric(beta)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_circle_beta_skeleton, points, beta)
+  res <- .Call(
+    R_igraph_circle_beta_skeleton,
+    points,
+    beta
+  )
 
   res
 }
 
-beta_weighted_gabriel_graph_impl <- function(points, max.beta=UNLIMITED) {
+beta_weighted_gabriel_graph_impl <- function(
+  points,
+  max.beta = UNLIMITED
+) {
   # Argument checks
   points[] <- as.numeric(points)
   max.beta <- as.numeric(max.beta)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_beta_weighted_gabriel_graph, points, max.beta)
+  res <- .Call(
+    R_igraph_beta_weighted_gabriel_graph,
+    points,
+    max.beta
+  )
 
   res
 }
 
-spatial_edge_lengths_impl <- function(graph, points, METRIC) {
+spatial_edge_lengths_impl <- function(
+  graph,
+  points,
+  METRIC
+) {
   # Argument checks
   ensure_igraph(graph)
   points[] <- as.numeric(points)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_spatial_edge_lengths, graph, points, METRIC)
+  res <- .Call(
+    R_igraph_spatial_edge_lengths,
+    graph,
+    points,
+    METRIC
+  )
 
   res
 }
 
-vertex_coloring_greedy_impl <- function(graph, heuristic=c("colored_neighbors", "dsatur")) {
+vertex_coloring_greedy_impl <- function(
+  graph,
+  heuristic = c("colored_neighbors", "dsatur")
+) {
   # Argument checks
   ensure_igraph(graph)
   heuristic <- switch_igraph_arg(heuristic, "colored_neighbors" = 0L, "dsatur" = 1L)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_vertex_coloring_greedy, graph, heuristic)
+  res <- .Call(
+    R_igraph_vertex_coloring_greedy,
+    graph,
+    heuristic
+  )
   res <- res+1
   if (igraph_opt("add.vertex.names") && is_named(graph)) {
     names(res) <- vertex_attr(graph, "name")
@@ -5674,7 +8797,10 @@ vertex_coloring_greedy_impl <- function(graph, heuristic=c("colored_neighbors",
   res
 }
 
-is_vertex_coloring_impl <- function(graph, types) {
+is_vertex_coloring_impl <- function(
+  graph,
+  types
+) {
   # Argument checks
   ensure_igraph(graph)
   if (missing(types)) {
@@ -5688,26 +8814,40 @@ is_vertex_coloring_impl <- function(graph, types) {
     types <- as.numeric(types)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_vertex_coloring, graph, types)
+  res <- .Call(
+    R_igraph_is_vertex_coloring,
+    graph,
+    types
+  )
 
   res
 }
 
-is_bipartite_coloring_impl <- function(graph, types) {
+is_bipartite_coloring_impl <- function(
+  graph,
+  types
+) {
   # Argument checks
   ensure_igraph(graph)
   types <- handle_vertex_type_arg(types, graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_bipartite_coloring, graph, types)
+  res <- .Call(
+    R_igraph_is_bipartite_coloring,
+    graph,
+    types
+  )
 
   res
 }
 
-is_edge_coloring_impl <- function(graph, types) {
+is_edge_coloring_impl <- function(
+  graph,
+  types
+) {
   # Argument checks
   ensure_igraph(graph)
   if (missing(types)) {
@@ -5721,71 +8861,112 @@ is_edge_coloring_impl <- function(graph, types) {
     types <- as.numeric(types)-1
   }
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_is_edge_coloring, graph, types)
+  res <- .Call(
+    R_igraph_is_edge_coloring,
+    graph,
+    types
+  )
 
   res
 }
 
-invalidate_cache_impl <- function(graph) {
+invalidate_cache_impl <- function(
+  graph
+) {
   # Argument checks
   ensure_igraph(graph)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_invalidate_cache, graph)
+  res <- .Call(
+    R_igraph_invalidate_cache,
+    graph
+  )
 
   res
 }
 
-version_impl <- function() {
+version_impl <- function(
+) {
   # Argument checks
 
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_version)
+  res <- .Call(
+    R_igraph_version
+  )
 
   res
 }
 
-sample_sphere_surface_impl <- function(dim, n=1, radius=1, positive=TRUE) {
+sample_sphere_surface_impl <- function(
+  dim,
+  n = 1,
+  radius = 1,
+  positive = TRUE
+) {
   # Argument checks
   dim <- as.numeric(dim)
   n <- as.numeric(n)
   radius <- as.numeric(radius)
   positive <- as.logical(positive)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_sample_sphere_surface, dim, n, radius, positive)
+  res <- .Call(
+    R_igraph_sample_sphere_surface,
+    dim,
+    n,
+    radius,
+    positive
+  )
 
   res
 }
 
-sample_sphere_volume_impl <- function(dim, n=1, radius=1, positive=TRUE) {
+sample_sphere_volume_impl <- function(
+  dim,
+  n = 1,
+  radius = 1,
+  positive = TRUE
+) {
   # Argument checks
   dim <- as.numeric(dim)
   n <- as.numeric(n)
   radius <- as.numeric(radius)
   positive <- as.logical(positive)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_sample_sphere_volume, dim, n, radius, positive)
+  res <- .Call(
+    R_igraph_sample_sphere_volume,
+    dim,
+    n,
+    radius,
+    positive
+  )
 
   res
 }
 
-sample_dirichlet_impl <- function(n, alpha) {
+sample_dirichlet_impl <- function(
+  n,
+  alpha
+) {
   # Argument checks
   n <- as.numeric(n)
   alpha <- as.numeric(alpha)
 
-  on.exit( .Call(R_igraph_finalizer) )
+  on.exit(.Call(R_igraph_finalizer))
   # Function call
-  res <- .Call(R_igraph_sample_dirichlet, n, alpha)
+  res <- .Call(
+    R_igraph_sample_dirichlet,
+    n,
+    alpha
+  )
 
   res
 }
diff --git a/R/utils-assert-args.R b/R/utils-assert-args.R
index 52a3f5f06f7..d6bbf43419f 100644
--- a/R/utils-assert-args.R
+++ b/R/utils-assert-args.R
@@ -19,19 +19,34 @@ ensure_igraph <- function(graph, optional = FALSE) {
 switch_igraph_arg <- function(
   arg,
   ...,
-  error_call = rlang::caller_env()
+  .error_arg = rlang::caller_arg(arg),
+  .error_call = rlang::caller_env()
 ) {
-  values <- ...names()
-  match <- igraph.match.arg(arg, values, error_call = error_call)
+  # Materialize early, before accessing arg
+  force(.error_arg)
+
+  values <- tolower(...names())
+  if (length(arg) > 1) {
+    values <- intersect(values, tolower(arg))
+  }
+  match <- igraph.match.arg(
+    arg,
+    values,
+    error_arg = .error_arg,
+    error_call = .error_call
+  )
   switch(match, ...)
 }
 
 igraph.match.arg <- function(
   arg,
   values,
+  error_arg = rlang::caller_arg(arg),
   error_call = rlang::caller_env()
 ) {
-  error_arg <- rlang::caller_arg(arg)
+  # Materialize early, before accessing arg
+  force(error_arg)
+
   if (missing(values)) {
     formal.args <- formals(sys.function(sys.parent()))
     values <- eval(formal.args[[deparse(substitute(arg))]])
diff --git a/tools/py-stimulus/src/stimulus/generators/r.py b/tools/py-stimulus/src/stimulus/generators/r.py
index 9dd73e29ad3..79b1b0f9402 100644
--- a/tools/py-stimulus/src/stimulus/generators/r.py
+++ b/tools/py-stimulus/src/stimulus/generators/r.py
@@ -54,6 +54,76 @@ def optional_wrapper_r(conv: str) -> str:
     return f"if (!is.null(%I%)) {conv}"
 
 
+def format_switch_statement(code: str) -> str:
+    """Format switch statements with proper spacing and line breaks."""
+    # Match switch(...) patterns
+    switch_pattern = r'(switch\([^,]+)(,\s*)([^)]+)(\))'
+
+    def format_switch_args(match):
+        prefix = match.group(1)  # "switch(igraph.match.arg(mode)"
+        comma = match.group(2)   # ","
+        args = match.group(3)    # the key-value pairs
+        suffix = match.group(4)  # ")"
+
+        # Split by comma, preserving quoted strings
+        parts = []
+        current = []
+        in_quotes = False
+        paren_depth = 0
+
+        for char in args:
+            if char == '"' and (not current or current[-1] != '\\'):
+                in_quotes = not in_quotes
+            elif char == '(' and not in_quotes:
+                paren_depth += 1
+            elif char == ')' and not in_quotes:
+                paren_depth -= 1
+            elif char == ',' and not in_quotes and paren_depth == 0:
+                parts.append(''.join(current).strip())
+                current = []
+                continue
+            current.append(char)
+
+        if current:
+            parts.append(''.join(current).strip())
+
+        # Check if we should format multiline (more than 3 parts or total length > 80)
+        total_len = len(prefix) + len(comma) + sum(len(p) for p in parts) + len(parts) * 2 + len(suffix)
+
+        if len(parts) > 3 or total_len > 80:
+            # Format multiline with proper spacing around =
+            formatted_parts = []
+            for part in parts:
+                # Add spaces around = in key-value pairs
+                part = re.sub(r'(["\w]+)=(\S)', r'\1 = \2', part)
+                formatted_parts.append(part)
+
+            # Create multiline format: put the first argument on its own
+            # line after the opening 'switch(' and indent the remaining
+            # key/value parts further.
+            indent_str = '    '
+            # prefix currently holds 'switch(some_expr' — we want
+            # to emit 'switch(\n    some_expr,\n' (use indent_str)
+            first_arg = prefix[prefix.find('(') + 1 :].strip()
+            result = 'switch(\n' + indent_str + first_arg + ',\n'
+            for i, part in enumerate(formatted_parts):
+                result += indent_str + part
+                if i < len(formatted_parts) - 1:
+                    result += ','
+                result += '\n'
+            result += '  ' + suffix
+            return result
+        else:
+            # Single line format with spaces around =
+            formatted_parts = []
+            for part in parts:
+                part = re.sub(r'(["\w]+)=(\S)', r'\1 = \2', part)
+                formatted_parts.append(part)
+            return prefix + ', ' + ', '.join(formatted_parts) + suffix
+
+    return re.sub(switch_pattern, format_switch_args, code)
+
+
 class RRCodeGenerator(SingleBlockCodeGenerator):
     def generate_function(self, function: str, out: IO[str]) -> None:
         # Check types
@@ -94,7 +164,7 @@ def generate_function(self, function: str, out: IO[str]) -> None:
         )
 
         out.write(name)
-        out.write("_impl <- function(")
+        out.write("_impl <- function(\n")
 
         def handle_input_argument(param: ParamSpec) -> str:
             tname = param.type
@@ -111,7 +181,7 @@ def handle_input_argument(param: ParamSpec) -> str:
                 "NULL" if param.is_optional and header else ""
             )
             if default:
-                header = f"{header}={default}"
+                header = f"{header} = {default}"
 
             for i, dep in enumerate(param.dependencies):
                 header = header.replace("%I" + str(i + 1) + "%", dep)
@@ -154,9 +224,12 @@ def handle_input_argument(param: ParamSpec) -> str:
                 )
                 needs_details_arg = False
         if needs_details_arg:
-            head.append("details=FALSE")
+            head.append("details = FALSE")
 
-        out.write(", ".join(head))
+        # Format parameters: one per line with proper indentation
+        if head:
+            formatted_params = ",\n  ".join(head)
+            out.write("  " + formatted_params + "\n")
         out.write(") {\n")
 
         ## Argument checks, INCONV
@@ -192,6 +265,9 @@ def handle_argument_check(param: ParamSpec) -> str:
                     f"Missing IN dependency for {tname} {param.name} in function {function}"
                 )
 
+            # Format switch statements
+            res = format_switch_statement(res)
+
             return res
 
         inconv = [handle_argument_check(param) for param in spec.iter_parameters()]
@@ -208,9 +284,10 @@ def handle_argument_check(param: ParamSpec) -> str:
         ## completely ignored, so giving an empty CALL field is
         ## different than not giving it at all.
 
-        out.write("  on.exit( .Call(R_igraph_finalizer) )\n")
+        out.write("  on.exit(.Call(R_igraph_finalizer))\n")
         out.write("  # Function call\n")
-        out.write("  res <- .Call(R_" + function)
+        out.write("  res <- .Call(\n")
+        out.write("    R_" + function)
 
         parts = []
         for param in spec.iter_input_parameters():
@@ -218,11 +295,17 @@ def handle_argument_check(param: ParamSpec) -> str:
             name = get_r_parameter_name(param)
             call = type.get("CALL", name)
             if call:
-                parts.append(call.replace("%I%", name))
+                call_formatted = call.replace("%I%", name)
+                # Add spaces around arithmetic operators
+                call_formatted = re.sub(r'(\w+)(\+|\-|\*|/)(\d+)', r'\1 \2 \3', call_formatted)
+                parts.append(call_formatted)
+
+        # Format .Call() as multi-line with each argument on its own line
+        for part in parts:
+            out.write(",\n")
+            out.write("    " + part)
 
-        if len(parts):
-            out.write(", " + ", ".join(parts))
-        out.write(")\n")
+        out.write("\n  )\n")
 
         ## Output conversions
         def handle_output_argument(
@@ -268,8 +351,9 @@ def handle_output_argument(
             retconv = indent(rt.get_output_conversion_template_for(ParamMode.OUT))
             retconv = retconv.replace("%I%", "res")
             # TODO: %I1% etc, is not handled here!
-            outconv.append("")
-            outconv.append(retconv)
+            if retconv.strip():
+                outconv.append("")
+                outconv.append(retconv)
         elif len(retpars) == 1:
             # returning a single output value
             pass

From ba005476bcdb5bef27b55efb264e3daf918b8a05 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sun, 26 Oct 2025 04:48:37 +0000
Subject: [PATCH 138/154] fledge: Bump version to 2.2.1.9000 (#2399)

Co-authored-by: krlmlr 
---
 DESCRIPTION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index 191bdd4d860..eb028b7ff11 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
 Package: igraph
 Title: Network Analysis and Visualization
-Version: 2.2.1
+Version: 2.2.1.9000
 Authors@R: c(
     person("Gábor", "Csárdi", , "csardi.gabor@gmail.com", role = "aut",
            comment = c(ORCID = "0000-0001-7098-9676")),

From 5d063fccb526fe560bd8a857ae40a02c06477c19 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 26 Oct 2025 08:14:59 +0000
Subject: [PATCH 139/154] refactor: Replace _impl aliases in R/other.R (#2388)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 R/other.R | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/R/other.R b/R/other.R
index a3ecbc39f30..921d11d57b8 100644
--- a/R/other.R
+++ b/R/other.R
@@ -222,5 +222,7 @@ igraph.i.spMatrix <- function(M) {
 #' convex_hull(M)
 #' @family other
 #' @export
-#' @cdocs igraph_convex_hull_2d
-convex_hull <- convex_hull_impl
+#' @cdocs igraph_convex_hull
+convex_hull <- function(data) {
+  convex_hull_impl(data = data)
+}

From 5736053d3bb0ba8ef79d1c566c52495fa2ed1d7e Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 26 Oct 2025 08:43:16 +0000
Subject: [PATCH 140/154] chore: Replace `_impl` aliases in `R/flow.R` (#2379)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
Co-authored-by: Kirill Müller 
---
 R/aaa-auto.R                  | 180 +++++++++++++++++++++++++++-------
 R/flow.R                      |  48 +++++++--
 tests/testthat/_snaps/flow.md |   8 +-
 tools/stimulus/types-RR.yaml  |  10 +-
 4 files changed, 197 insertions(+), 49 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index 39de47f286e..ef595bc0f54 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -100,7 +100,10 @@ neighbors_impl <- function(
   ensure_igraph(graph)
   vid <- as_igraph_vs(graph, vid)
   if (length(vid) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg vid} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
@@ -157,11 +160,17 @@ get_all_eids_between_impl <- function(
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (length(to) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg to} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   directed <- as.logical(directed)
 
@@ -190,7 +199,10 @@ incident_impl <- function(
   ensure_igraph(graph)
   vid <- as_igraph_vs(graph, vid)
   if (length(vid) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg vid} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)
@@ -1370,11 +1382,17 @@ are_adjacent_impl <- function(
   ensure_igraph(graph)
   v1 <- as_igraph_vs(graph, v1)
   if (length(v1) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg v1} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   v2 <- as_igraph_vs(graph, v2)
   if (length(v2) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg v2} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
 
   on.exit(.Call(R_igraph_finalizer))
@@ -1517,11 +1535,17 @@ get_shortest_path_impl <- function(
   }
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (length(to) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg to} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
@@ -1555,11 +1579,17 @@ get_shortest_path_bellman_ford_impl <- function(
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (length(to) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg to} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
     weights <- E(graph)$weight
@@ -1601,11 +1631,17 @@ get_shortest_path_dijkstra_impl <- function(
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (length(to) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg to} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
     weights <- E(graph)$weight
@@ -1655,7 +1691,10 @@ get_all_shortest_paths_impl <- function(
   }
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
@@ -1685,7 +1724,10 @@ get_all_shortest_paths_dijkstra_impl <- function(
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1762,7 +1804,10 @@ get_all_simple_paths_impl <- function(
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
@@ -1809,11 +1854,17 @@ get_k_shortest_paths_impl <- function(
   k <- as.numeric(k)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (length(to) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg to} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
@@ -1843,11 +1894,17 @@ get_widest_path_impl <- function(
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (length(to) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg to} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
     weights <- E(graph)$weight
@@ -1889,7 +1946,10 @@ get_widest_paths_impl <- function(
   ensure_igraph(graph)
   from <- as_igraph_vs(graph, from)
   if (length(from) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg from} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   to <- as_igraph_vs(graph, to)
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -3803,7 +3863,10 @@ pseudo_diameter_impl <- function(
   }
   start.vid <- as_igraph_vs(graph, start.vid)
   if (length(start.vid) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg start.vid} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   directed <- as.logical(directed)
   unconnected <- as.logical(unconnected)
@@ -3873,7 +3936,10 @@ random_walk_impl <- function(
   }
   start <- as_igraph_vs(graph, start)
   if (length(start) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg start} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
   steps <- as.numeric(steps)
@@ -4061,7 +4127,10 @@ bfs_simple_impl <- function(
   ensure_igraph(graph)
   root <- as_igraph_vs(graph, root)
   if (length(root) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg root} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
@@ -4846,7 +4915,10 @@ layout_star_impl <- function(
   ensure_igraph(graph)
   center <- as_igraph_vs(graph, center)
   if (length(center) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg center} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   if (!is.null(order)) order <- as.numeric(order)-1
 
@@ -6741,7 +6813,10 @@ rooted_product_impl <- function(
   ensure_igraph(g2)
   root <- as_igraph_vs(g2, root)
   if (length(root) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg root} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
 
   on.exit(.Call(R_igraph_finalizer))
@@ -6792,11 +6867,17 @@ maxflow_impl <- function(
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
   if (length(source) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg source} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   target <- as_igraph_vs(graph, target)
   if (length(target) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg target} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
     capacity <- E(graph)$capacity
@@ -6896,11 +6977,17 @@ st_mincut_impl <- function(
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
   if (length(source) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg source} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   target <- as_igraph_vs(graph, target)
   if (length(target) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg target} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
     capacity <- E(graph)$capacity
@@ -6941,7 +7028,10 @@ dominator_tree_impl <- function(
   ensure_igraph(graph)
   root <- as_igraph_vs(graph, root)
   if (length(root) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg root} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   mode <- switch_igraph_arg(mode, "out" = 1L, "in" = 2L, "all" = 3L, "total" = 3L)
 
@@ -6968,11 +7058,17 @@ all_st_cuts_impl <- function(
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
   if (length(source) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg source} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   target <- as_igraph_vs(graph, target)
   if (length(target) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg target} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
 
   on.exit(.Call(R_igraph_finalizer))
@@ -6997,11 +7093,17 @@ all_st_mincuts_impl <- function(
   ensure_igraph(graph)
   source <- as_igraph_vs(graph, source)
   if (length(source) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg source} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   target <- as_igraph_vs(graph, target)
   if (length(target) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg target} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
     capacity <- E(graph)$capacity
@@ -8371,7 +8473,10 @@ fundamental_cycles_impl <- function(
   }
   if (!is.null(start)) start <- as_igraph_vs(graph, start)
   if (length(start) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg start} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
   bfs.cutoff <- as.numeric(bfs.cutoff)
 
@@ -8584,7 +8689,10 @@ random_spanning_tree_impl <- function(
   ensure_igraph(graph)
   if (!is.null(vid)) vid <- as_igraph_vs(graph, vid)
   if (length(vid) == 0) {
-    stop("No vertex was specified")
+    cli::cli_abort(
+      "{.arg vid} must specify at least one vertex",
+      call = rlang::caller_env()
+    )
   }
 
   on.exit(.Call(R_igraph_finalizer))
diff --git a/R/flow.R b/R/flow.R
index bdfd9d95021..a4a221d283b 100644
--- a/R/flow.R
+++ b/R/flow.R
@@ -761,7 +761,13 @@ cohesion.igraph <- function(x, checks = TRUE, ...) {
 #' @family flow
 #' @export
 #' @cdocs igraph_all_st_cuts
-st_cuts <- all_st_cuts_impl
+st_cuts <- function(graph, source, target) {
+  all_st_cuts_impl(
+    graph = graph,
+    source = source,
+    target = target
+  )
+}
 
 
 #' List all minimum \eqn{(s,t)}-cuts of a graph
@@ -819,7 +825,14 @@ st_cuts <- all_st_cuts_impl
 #' @family flow
 #' @export
 #' @cdocs igraph_all_st_mincuts
-st_min_cuts <- all_st_mincuts_impl
+st_min_cuts <- function(graph, source, target, capacity = NULL) {
+  all_st_mincuts_impl(
+    graph = graph,
+    source = source,
+    target = target,
+    capacity = capacity
+  )
+}
 
 
 #' Dominator tree
@@ -964,7 +977,9 @@ dominator_tree <- function(graph, root, mode = c("out", "in", "all", "total")) {
 #' ```
 #' @family flow
 #' @cdocs igraph_all_minimal_st_separators
-min_st_separators <- all_minimal_st_separators_impl
+min_st_separators <- function(graph) {
+  all_minimal_st_separators_impl(graph = graph)
+}
 
 
 #' Maximum flow in a graph
@@ -1032,7 +1047,14 @@ min_st_separators <- all_minimal_st_separators_impl
 #' @family flow
 #' @export
 #' @cdocs igraph_maxflow
-max_flow <- maxflow_impl
+max_flow <- function(graph, source, target, capacity = NULL) {
+  maxflow_impl(
+    graph = graph,
+    source = source,
+    target = target,
+    capacity = capacity
+  )
+}
 
 
 #' Check whether removing this set of vertices would disconnect the graph.
@@ -1061,7 +1083,12 @@ max_flow <- maxflow_impl
 #'
 #' @export
 #' @cdocs igraph_is_separator
-is_separator <- is_separator_impl
+is_separator <- function(graph, candidate) {
+  is_separator_impl(
+    graph = graph,
+    candidate = candidate
+  )
+}
 
 
 #' Minimal vertex separators
@@ -1110,7 +1137,12 @@ is_separator <- is_separator_impl
 #' @family flow
 #' @export
 #' @cdocs igraph_is_minimal_separator
-is_min_separator <- is_minimal_separator_impl
+is_min_separator <- function(graph, candidate) {
+  is_minimal_separator_impl(
+    graph = graph,
+    candidate = candidate
+  )
+}
 
 
 #' Minimum size vertex separators
@@ -1181,4 +1213,6 @@ is_min_separator <- is_minimal_separator_impl
 #' )
 #' min_separators(camp)
 #' @cdocs igraph_minimum_size_separators
-min_separators <- minimum_size_separators_impl
+min_separators <- function(graph) {
+  minimum_size_separators_impl(graph = graph)
+}
diff --git a/tests/testthat/_snaps/flow.md b/tests/testthat/_snaps/flow.md
index 01e1e52f55a..add2f35391b 100644
--- a/tests/testthat/_snaps/flow.md
+++ b/tests/testthat/_snaps/flow.md
@@ -4,7 +4,7 @@
       st_cuts(g_path, source = "a", target = NULL)
     Condition
       Error in `st_cuts()`:
-      ! No vertex was specified
+      ! `target` must specify at least one vertex
 
 ---
 
@@ -12,7 +12,7 @@
       st_cuts(g_path, source = NULL, target = "a")
     Condition
       Error in `st_cuts()`:
-      ! No vertex was specified
+      ! `source` must specify at least one vertex
 
 ---
 
@@ -20,7 +20,7 @@
       st_min_cuts(g_path, source = "a", target = NULL)
     Condition
       Error in `st_min_cuts()`:
-      ! No vertex was specified
+      ! `target` must specify at least one vertex
 
 ---
 
@@ -28,7 +28,7 @@
       st_min_cuts(g_path, source = NULL, target = "a")
     Condition
       Error in `st_min_cuts()`:
-      ! No vertex was specified
+      ! `source` must specify at least one vertex
 
 # vertex_connectivity error works
 
diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml
index ae59baa0bc9..0192f034161 100644
--- a/tools/stimulus/types-RR.yaml
+++ b/tools/stimulus/types-RR.yaml
@@ -103,7 +103,10 @@ VERTEX:
     INCONV: |-
         %I% <- as_igraph_vs(%I1%, %I%)
         if (length(%I%) == 0) {
-          stop("No vertex was specified")
+          cli::cli_abort(
+            "{.arg %I%} must specify at least one vertex",
+            call = rlang::caller_env()
+          )
         }
     OUTCONV:
         OUT: |-
@@ -116,7 +119,10 @@ VERTEX_ROOT:
     INCONV: |-
         %I% <- as_igraph_vs(%I1%, %I%)
         if (length(%I%) == 0) {
-          stop("No vertex was specified")
+          cli::cli_abort(
+            "{.arg %I%} must specify at least one vertex",
+            call = rlang::caller_env()
+          )
         }
     OUTCONV:
         OUT: |-

From b8ab46430b0da7568dc4450bfa1f00837adcf4b5 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 26 Oct 2025 09:30:50 +0000
Subject: [PATCH 141/154] refactor: Replace `_impl` aliases with explicit
 wrapper functions in `R/topology.R` (#2398)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
Co-authored-by: Kirill Müller 
---
 R/aaa-auto.R                 |  70 ++++++++--------
 R/topology.R                 | 154 ++++++++++++++++++++++++++++++-----
 tools/stimulus/types-RR.yaml |   4 +-
 3 files changed, 172 insertions(+), 56 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index ef595bc0f54..90bc906e0f0 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -7356,7 +7356,7 @@ isomorphic_vf2_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(vertex.color1)) {
+  if (is_missing(vertex.color1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       vertex.color1 <- V(graph1)$color
     } else {
@@ -7366,7 +7366,7 @@ isomorphic_vf2_impl <- function(
   if (!is.null(vertex.color1)) {
     vertex.color1 <- as.numeric(vertex.color1)-1
   }
-  if (missing(vertex.color2)) {
+  if (is_missing(vertex.color2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       vertex.color2 <- V(graph2)$color
     } else {
@@ -7376,7 +7376,7 @@ isomorphic_vf2_impl <- function(
   if (!is.null(vertex.color2)) {
     vertex.color2 <- as.numeric(vertex.color2)-1
   }
-  if (missing(edge.color1)) {
+  if (is_missing(edge.color1)) {
     if ("color" %in% edge_attr_names(graph1)) {
       edge.color1 <- E(graph1)$color
     } else {
@@ -7386,7 +7386,7 @@ isomorphic_vf2_impl <- function(
   if (!is.null(edge.color1)) {
     edge.color1 <- as.numeric(edge.color1)-1
   }
-  if (missing(edge.color2)) {
+  if (is_missing(edge.color2)) {
     if ("color" %in% edge_attr_names(graph2)) {
       edge.color2 <- E(graph2)$color
     } else {
@@ -7423,7 +7423,7 @@ get_isomorphisms_vf2_callback_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(vertex.color1)) {
+  if (is_missing(vertex.color1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       vertex.color1 <- V(graph1)$color
     } else {
@@ -7433,7 +7433,7 @@ get_isomorphisms_vf2_callback_impl <- function(
   if (!is.null(vertex.color1)) {
     vertex.color1 <- as.numeric(vertex.color1)-1
   }
-  if (missing(vertex.color2)) {
+  if (is_missing(vertex.color2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       vertex.color2 <- V(graph2)$color
     } else {
@@ -7443,7 +7443,7 @@ get_isomorphisms_vf2_callback_impl <- function(
   if (!is.null(vertex.color2)) {
     vertex.color2 <- as.numeric(vertex.color2)-1
   }
-  if (missing(edge.color1)) {
+  if (is_missing(edge.color1)) {
     if ("color" %in% edge_attr_names(graph1)) {
       edge.color1 <- E(graph1)$color
     } else {
@@ -7453,7 +7453,7 @@ get_isomorphisms_vf2_callback_impl <- function(
   if (!is.null(edge.color1)) {
     edge.color1 <- as.numeric(edge.color1)-1
   }
-  if (missing(edge.color2)) {
+  if (is_missing(edge.color2)) {
     if ("color" %in% edge_attr_names(graph2)) {
       edge.color2 <- E(graph2)$color
     } else {
@@ -7490,7 +7490,7 @@ count_isomorphisms_vf2_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(vertex.color1)) {
+  if (is_missing(vertex.color1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       vertex.color1 <- V(graph1)$color
     } else {
@@ -7500,7 +7500,7 @@ count_isomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color1)) {
     vertex.color1 <- as.numeric(vertex.color1)-1
   }
-  if (missing(vertex.color2)) {
+  if (is_missing(vertex.color2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       vertex.color2 <- V(graph2)$color
     } else {
@@ -7510,7 +7510,7 @@ count_isomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color2)) {
     vertex.color2 <- as.numeric(vertex.color2)-1
   }
-  if (missing(edge.color1)) {
+  if (is_missing(edge.color1)) {
     if ("color" %in% edge_attr_names(graph1)) {
       edge.color1 <- E(graph1)$color
     } else {
@@ -7520,7 +7520,7 @@ count_isomorphisms_vf2_impl <- function(
   if (!is.null(edge.color1)) {
     edge.color1 <- as.numeric(edge.color1)-1
   }
-  if (missing(edge.color2)) {
+  if (is_missing(edge.color2)) {
     if ("color" %in% edge_attr_names(graph2)) {
       edge.color2 <- E(graph2)$color
     } else {
@@ -7557,7 +7557,7 @@ get_isomorphisms_vf2_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(vertex.color1)) {
+  if (is_missing(vertex.color1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       vertex.color1 <- V(graph1)$color
     } else {
@@ -7567,7 +7567,7 @@ get_isomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color1)) {
     vertex.color1 <- as.numeric(vertex.color1)-1
   }
-  if (missing(vertex.color2)) {
+  if (is_missing(vertex.color2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       vertex.color2 <- V(graph2)$color
     } else {
@@ -7577,7 +7577,7 @@ get_isomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color2)) {
     vertex.color2 <- as.numeric(vertex.color2)-1
   }
-  if (missing(edge.color1)) {
+  if (is_missing(edge.color1)) {
     if ("color" %in% edge_attr_names(graph1)) {
       edge.color1 <- E(graph1)$color
     } else {
@@ -7587,7 +7587,7 @@ get_isomorphisms_vf2_impl <- function(
   if (!is.null(edge.color1)) {
     edge.color1 <- as.numeric(edge.color1)-1
   }
-  if (missing(edge.color2)) {
+  if (is_missing(edge.color2)) {
     if ("color" %in% edge_attr_names(graph2)) {
       edge.color2 <- E(graph2)$color
     } else {
@@ -7643,7 +7643,7 @@ subisomorphic_vf2_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(vertex.color1)) {
+  if (is_missing(vertex.color1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       vertex.color1 <- V(graph1)$color
     } else {
@@ -7653,7 +7653,7 @@ subisomorphic_vf2_impl <- function(
   if (!is.null(vertex.color1)) {
     vertex.color1 <- as.numeric(vertex.color1)-1
   }
-  if (missing(vertex.color2)) {
+  if (is_missing(vertex.color2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       vertex.color2 <- V(graph2)$color
     } else {
@@ -7663,7 +7663,7 @@ subisomorphic_vf2_impl <- function(
   if (!is.null(vertex.color2)) {
     vertex.color2 <- as.numeric(vertex.color2)-1
   }
-  if (missing(edge.color1)) {
+  if (is_missing(edge.color1)) {
     if ("color" %in% edge_attr_names(graph1)) {
       edge.color1 <- E(graph1)$color
     } else {
@@ -7673,7 +7673,7 @@ subisomorphic_vf2_impl <- function(
   if (!is.null(edge.color1)) {
     edge.color1 <- as.numeric(edge.color1)-1
   }
-  if (missing(edge.color2)) {
+  if (is_missing(edge.color2)) {
     if ("color" %in% edge_attr_names(graph2)) {
       edge.color2 <- E(graph2)$color
     } else {
@@ -7710,7 +7710,7 @@ count_subisomorphisms_vf2_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(vertex.color1)) {
+  if (is_missing(vertex.color1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       vertex.color1 <- V(graph1)$color
     } else {
@@ -7720,7 +7720,7 @@ count_subisomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color1)) {
     vertex.color1 <- as.numeric(vertex.color1)-1
   }
-  if (missing(vertex.color2)) {
+  if (is_missing(vertex.color2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       vertex.color2 <- V(graph2)$color
     } else {
@@ -7730,7 +7730,7 @@ count_subisomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color2)) {
     vertex.color2 <- as.numeric(vertex.color2)-1
   }
-  if (missing(edge.color1)) {
+  if (is_missing(edge.color1)) {
     if ("color" %in% edge_attr_names(graph1)) {
       edge.color1 <- E(graph1)$color
     } else {
@@ -7740,7 +7740,7 @@ count_subisomorphisms_vf2_impl <- function(
   if (!is.null(edge.color1)) {
     edge.color1 <- as.numeric(edge.color1)-1
   }
-  if (missing(edge.color2)) {
+  if (is_missing(edge.color2)) {
     if ("color" %in% edge_attr_names(graph2)) {
       edge.color2 <- E(graph2)$color
     } else {
@@ -7777,7 +7777,7 @@ get_subisomorphisms_vf2_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(vertex.color1)) {
+  if (is_missing(vertex.color1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       vertex.color1 <- V(graph1)$color
     } else {
@@ -7787,7 +7787,7 @@ get_subisomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color1)) {
     vertex.color1 <- as.numeric(vertex.color1)-1
   }
-  if (missing(vertex.color2)) {
+  if (is_missing(vertex.color2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       vertex.color2 <- V(graph2)$color
     } else {
@@ -7797,7 +7797,7 @@ get_subisomorphisms_vf2_impl <- function(
   if (!is.null(vertex.color2)) {
     vertex.color2 <- as.numeric(vertex.color2)-1
   }
-  if (missing(edge.color1)) {
+  if (is_missing(edge.color1)) {
     if ("color" %in% edge_attr_names(graph1)) {
       edge.color1 <- E(graph1)$color
     } else {
@@ -7807,7 +7807,7 @@ get_subisomorphisms_vf2_impl <- function(
   if (!is.null(edge.color1)) {
     edge.color1 <- as.numeric(edge.color1)-1
   }
-  if (missing(edge.color2)) {
+  if (is_missing(edge.color2)) {
     if ("color" %in% edge_attr_names(graph2)) {
       edge.color2 <- E(graph2)$color
     } else {
@@ -7868,7 +7868,7 @@ canonical_permutation_bliss_impl <- function(
 ) {
   # Argument checks
   ensure_igraph(graph)
-  if (missing(colors)) {
+  if (is_missing(colors)) {
     if ("color" %in% vertex_attr_names(graph)) {
       colors <- V(graph)$color
     } else {
@@ -7921,7 +7921,7 @@ isomorphic_bliss_impl <- function(
   # Argument checks
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  if (missing(colors1)) {
+  if (is_missing(colors1)) {
     if ("color" %in% vertex_attr_names(graph1)) {
       colors1 <- V(graph1)$color
     } else {
@@ -7931,7 +7931,7 @@ isomorphic_bliss_impl <- function(
   if (!is.null(colors1)) {
     colors1 <- as.numeric(colors1)-1
   }
-  if (missing(colors2)) {
+  if (is_missing(colors2)) {
     if ("color" %in% vertex_attr_names(graph2)) {
       colors2 <- V(graph2)$color
     } else {
@@ -7964,7 +7964,7 @@ count_automorphisms_bliss_impl <- function(
 ) {
   # Argument checks
   ensure_igraph(graph)
-  if (missing(colors)) {
+  if (is_missing(colors)) {
     if ("color" %in% vertex_attr_names(graph)) {
       colors <- V(graph)$color
     } else {
@@ -7996,7 +7996,7 @@ automorphism_group_bliss_impl <- function(
 ) {
   # Argument checks
   ensure_igraph(graph)
-  if (missing(colors)) {
+  if (is_missing(colors)) {
     if ("color" %in% vertex_attr_names(graph)) {
       colors <- V(graph)$color
     } else {
@@ -8911,7 +8911,7 @@ is_vertex_coloring_impl <- function(
 ) {
   # Argument checks
   ensure_igraph(graph)
-  if (missing(types)) {
+  if (is_missing(types)) {
     if ("color" %in% vertex_attr_names(graph)) {
       types <- V(graph)$color
     } else {
@@ -8958,7 +8958,7 @@ is_edge_coloring_impl <- function(
 ) {
   # Argument checks
   ensure_igraph(graph)
-  if (missing(types)) {
+  if (is_missing(types)) {
     if ("color" %in% edge_attr_names(graph)) {
       types <- E(graph)$color
     } else {
diff --git a/R/topology.R b/R/topology.R
index 7eb38ba0b66..9012a65fa80 100644
--- a/R/topology.R
+++ b/R/topology.R
@@ -482,8 +482,8 @@ graph.isomorphic.bliss <- function(
   isomorphic_bliss_impl(
     graph1 = graph1,
     graph2 = graph2,
-    colors1 = colors1,
-    colors2 = colors2,
+    colors1 = if (missing(colors1)) missing_arg() else colors1,
+    colors2 = if (missing(colors2)) missing_arg() else colors2,
     sh = sh
   )
 }
@@ -500,10 +500,18 @@ graph.isomorphic.vf2 <- function(
   isomorphic_vf2_impl(
     graph1 = graph1,
     graph2 = graph2,
-    vertex.color1 = vertex.color1,
-    vertex.color2 = vertex.color2,
-    edge.color1 = edge.color1,
-    edge.color2 = edge.color2
+    vertex.color1 = if (missing(vertex.color1)) {
+      missing_arg()
+    } else {
+      vertex.color1
+    },
+    vertex.color2 = if (missing(vertex.color2)) {
+      missing_arg()
+    } else {
+      vertex.color2
+    },
+    edge.color1 = if (missing(edge.color1)) missing_arg() else edge.color1,
+    edge.color2 = if (missing(edge.color2)) missing_arg() else edge.color2
   )
 }
 #' @export
@@ -519,10 +527,18 @@ graph.subisomorphic.vf2 <- function(
   subisomorphic_vf2_impl(
     graph1 = graph1,
     graph2 = graph2,
-    vertex.color1 = vertex.color1,
-    vertex.color2 = vertex.color2,
-    edge.color1 = edge.color1,
-    edge.color2 = edge.color2
+    vertex.color1 = if (missing(vertex.color1)) {
+      missing_arg()
+    } else {
+      vertex.color1
+    },
+    vertex.color2 = if (missing(vertex.color2)) {
+      missing_arg()
+    } else {
+      vertex.color2
+    },
+    edge.color1 = if (missing(edge.color1)) missing_arg() else edge.color1,
+    edge.color2 = if (missing(edge.color2)) missing_arg() else edge.color2
   )
 }
 
@@ -698,7 +714,31 @@ count_isomorphisms <- function(graph1, graph2, method = "vf2", ...) {
 
 #' @export
 #' @cdocs igraph_count_isomorphisms_vf2
-graph.count.isomorphisms.vf2 <- count_isomorphisms_vf2_impl
+graph.count.isomorphisms.vf2 <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
+  count_isomorphisms_vf2_impl(
+    graph1 = graph1,
+    graph2 = graph2,
+    vertex.color1 = if (missing(vertex.color1)) {
+      missing_arg()
+    } else {
+      vertex.color1
+    },
+    vertex.color2 = if (missing(vertex.color2)) {
+      missing_arg()
+    } else {
+      vertex.color2
+    },
+    edge.color1 = if (missing(edge.color1)) missing_arg() else edge.color1,
+    edge.color2 = if (missing(edge.color2)) missing_arg() else edge.color2
+  )
+}
 
 #' Count the isomorphic mappings between a graph and the subgraphs of
 #' another graph
@@ -781,7 +821,31 @@ count_subgraph_isomorphisms <- function(
 
 #' @export
 #' @cdocs igraph_count_subisomorphisms_vf2
-graph.count.subisomorphisms.vf2 <- count_subisomorphisms_vf2_impl
+graph.count.subisomorphisms.vf2 <- function(
+  graph1,
+  graph2,
+  vertex.color1 = NULL,
+  vertex.color2 = NULL,
+  edge.color1 = NULL,
+  edge.color2 = NULL
+) {
+  count_subisomorphisms_vf2_impl(
+    graph1 = graph1,
+    graph2 = graph2,
+    vertex.color1 = if (missing(vertex.color1)) {
+      missing_arg()
+    } else {
+      vertex.color1
+    },
+    vertex.color2 = if (missing(vertex.color2)) {
+      missing_arg()
+    } else {
+      vertex.color2
+    },
+    edge.color1 = if (missing(edge.color1)) missing_arg() else edge.color1,
+    edge.color2 = if (missing(edge.color2)) missing_arg() else edge.color2
+  )
+}
 
 #' Calculate all isomorphic mappings between the vertices of two graphs
 #'
@@ -913,7 +977,11 @@ isomorphism_class <- function(graph, v) {
 
 #' @export
 #' @cdocs igraph_isoclass
-graph.isoclass <- isoclass_impl
+graph.isoclass <- function(graph) {
+  isoclass_impl(
+    graph = graph
+  )
+}
 
 #' Create a graph from an isomorphism class
 #'
@@ -932,7 +1000,13 @@ graph.isoclass <- isoclass_impl
 #' @family graph isomorphism
 #' @export
 #' @cdocs igraph_isoclass_create
-graph_from_isomorphism_class <- isoclass_create_impl
+graph_from_isomorphism_class <- function(size, number, directed = TRUE) {
+  isoclass_create_impl(
+    size = size,
+    number = number,
+    directed = directed
+  )
+}
 
 
 #' Canonical permutation of a graph
@@ -1043,7 +1117,17 @@ graph_from_isomorphism_class <- isoclass_create_impl
 #' @family graph isomorphism
 #' @export
 #' @cdocs igraph_canonical_permutation
-canonical_permutation <- canonical_permutation_bliss_impl
+canonical_permutation <- function(
+  graph,
+  colors = NULL,
+  sh = c("fm", "f", "fs", "fl", "flm", "fsm")
+) {
+  canonical_permutation_bliss_impl(
+    graph = graph,
+    colors = if (missing(colors)) missing_arg() else colors,
+    sh = sh
+  )
+}
 
 
 #' Permute the vertices of a graph
@@ -1085,11 +1169,21 @@ canonical_permutation <- canonical_permutation_bliss_impl
 #' @export
 #' @family functions for manipulating graph structure
 #' @cdocs igraph_permute_vertices
-permute <- permute_vertices_impl
+permute <- function(graph, permutation) {
+  permute_vertices_impl(
+    graph = graph,
+    permutation = permutation
+  )
+}
 
 #' @export
 #' @cdocs igraph_isomorphic
-graph.isomorphic <- isomorphic_impl
+graph.isomorphic <- function(graph1, graph2) {
+  isomorphic_impl(
+    graph1 = graph1,
+    graph2 = graph2
+  )
+}
 
 #' Number of automorphisms
 #'
@@ -1175,7 +1269,17 @@ graph.isomorphic <- isomorphic_impl
 #' @family graph automorphism
 #' @export
 #' @cdocs igraph_count_automorphisms
-count_automorphisms <- count_automorphisms_bliss_impl
+count_automorphisms <- function(
+  graph,
+  colors = NULL,
+  sh = c("fm", "f", "fs", "fl", "flm", "fsm")
+) {
+  count_automorphisms_bliss_impl(
+    graph = graph,
+    colors = if (missing(colors)) missing_arg() else colors,
+    sh = sh
+  )
+}
 
 
 #' Generating set of the automorphism group of a graph
@@ -1232,4 +1336,16 @@ count_automorphisms <- count_automorphisms_bliss_impl
 #' @family graph automorphism
 #' @export
 #' @cdocs igraph_automorphism_group
-automorphism_group <- automorphism_group_impl
+automorphism_group <- function(
+  graph,
+  colors = NULL,
+  sh = c("fm", "f", "fs", "fl", "flm", "fsm"),
+  details = FALSE
+) {
+  automorphism_group_impl(
+    graph = graph,
+    colors = if (missing(colors)) missing_arg() else colors,
+    sh = sh,
+    details = details
+  )
+}
diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml
index 0192f034161..5a920d8d0d4 100644
--- a/tools/stimulus/types-RR.yaml
+++ b/tools/stimulus/types-RR.yaml
@@ -220,7 +220,7 @@ BIPARTITE_TYPES_UNNAMED:
 
 VERTEX_COLORS:
     INCONV: |-
-        if (missing(%I%)) {
+        if (is_missing(%I%)) {
           if ("color" %in% vertex_attr_names(%I1%)) {
             %I% <- V(%I1%)$color
           } else {
@@ -239,7 +239,7 @@ VERTEX_COLORS:
 
 EDGE_COLORS:
     INCONV: |-
-        if (missing(%I%)) {
+        if (is_missing(%I%)) {
           if ("color" %in% edge_attr_names(%I1%)) {
             %I% <- E(%I1%)$color
           } else {

From 80e5f956829106c309a54e0cce0c4c1f1a2f87f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sun, 26 Oct 2025 11:00:56 +0100
Subject: [PATCH 142/154] ci: Reduce contention by running big matrices
 overnight

---
 .github/workflows/R-CMD-check.yaml | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index 00c76772683..ed3263e344a 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -30,6 +30,14 @@ on:
         description: "Create a matrix of suggested dependencies"
         type: boolean
         default: false
+      run-rcc-full:
+        description: "Run rcc-full job"
+        type: boolean
+        default: false
+      run-rcc-suggests:
+        description: "Run rcc-suggests job"
+        type: boolean
+        default: false
   merge_group:
     types:
       - checks_requested
@@ -265,7 +273,7 @@ jobs:
 
     runs-on: ${{ matrix.os }}
 
-    if: ${{ needs.rcc-smoke.outputs.versions-matrix != '' }}
+    if: ${{ needs.rcc-smoke.outputs.versions-matrix != '' && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.run-rcc-full)) }}
 
     name: 'rcc: ${{ matrix.os }} (${{ matrix.r }}) ${{ matrix.desc }}'
 
@@ -327,7 +335,7 @@ jobs:
 
     runs-on: ubuntu-22.04
 
-    if: ${{ needs.rcc-smoke.outputs.dep-suggests-matrix != '' }}
+    if: ${{ needs.rcc-smoke.outputs.dep-suggests-matrix != '' && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.run-rcc-suggests)) }}
 
     name: Without ${{ matrix.package }}
 

From 9c9a0a1d5ba770e1d7721fd364b96f1a456b9da9 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 26 Oct 2025 12:28:16 +0100
Subject: [PATCH 143/154] docs: add GitHub Copilot instructions and expand
 AGENTS.md (#2400)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller 
---
 .github/copilot-instructions.md | 12 +++++
 AGENTS.md                       | 91 ++++++++++++++++++++++++++++-----
 2 files changed, 90 insertions(+), 13 deletions(-)
 create mode 100644 .github/copilot-instructions.md

diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 00000000000..74c7976a799
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,12 @@
+# GitHub Copilot Instructions for igraph/rigraph
+
+> **Note**: For general development guidelines, code style conventions, and AI agent instructions, see [`AGENTS.md`](../AGENTS.md) in the repository root.
+
+## Common Commands for Copilot Chat
+
+- Load for development: `pkgload::load_all()`
+- Run tests: `testthat::test_local(reporter = "check")`
+- Format code: `air format .`
+- Update documentation: `devtools::document()`
+
+Refer to `AGENTS.md` for more instructions.
diff --git a/AGENTS.md b/AGENTS.md
index 90c89218c30..fd56874ab77 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,38 +1,103 @@
 # AI Agent Development Guidelines for igraph
 
+> **Note**: For GitHub Copilot-specific instructions, see [`.github/copilot-instructions.md`](.github/copilot-instructions.md).
+
 ## Project Overview
 
-igraph is an R package with routines for simple graphs and network analysis. It can handle large graphs very well and provides functions for generating random and regular graphs, graph visualization, centrality methods and much more.
+igraph is an R package for network analysis and graph theory.
+It provides routines for simple graphs and network analysis, handles large graphs efficiently, and includes functions for generating random and regular graphs, graph visualization, centrality methods, and much more.
+
+## Key Technologies
+
+- **Language**: R with C/C++ backend (uses the igraph C library)
+- **Testing**: testthat framework
+- **Documentation**: roxygen2 with Markdown syntax
+- **Code Formatting**: air (R formatting tool)
+- **Build System**: R CMD, devtools, Makefile
+- **Code Generation**: Stimulus framework (see `tools/README.md`)
+
+## Development Setup
+
+### Installation and Dependencies
+
+```r
+# Install all dependencies
+pak::pak()
+# Install build dependencies
+pak::pak(dependencies = "Config/Needs/build")
+```
 
-## Install and run R
+### Install and run R
 
 - When run on GitHub Actions, assume that R, the package in its current state and all dependencies are installed.
 - Only install new packages when needed for implementing new features or tests.
-- Run `R -q -e 'testthat::test_local(reporter = "check")` to execute tests as a final step.
+- Run `R -q -e 'testthat::test_local(reporter = "check")'` to execute tests as a final step.
+
+### Building and Testing
+
+- Load package for development: `pkgload::load_all()`
+- Run tests: `testthat::test_local(reporter = "check")`
+- Build package: `devtools::build()`
+- Check package: `devtools::check()`
+- Update documentation: `devtools::document()`
+- Format code: `air format .`
 
 ## Code Style and Documentation
 
 ### PR and Commit Style
 
-- PRs and commits use the conventional commit style with backticks for code references such as `function_call()` .
-- PRs are generally squashed, a clean history within a PR is not necessary.
+- IMPORTANT: PR titles end up in `NEWS.md` grouped by conventional commit label. PRs and commits use the conventional commit style with backticks for code references such as `function_call()`
+- PRs are generally squashed, a clean history within a PR is not necessary
 
 ### Comment Style
 
-- Add comprehensive comments to utility functions that aren't immediately obvious
-- Use line breaks after each sentence in multi-sentence comments
+- Prefer expressive code over comments where possible
+- Add comments to utility functions that cannot be made immediately obvious
 - Focus comments on explaining the "why" and "how", the "what" should be clear from the code itself
-- Include context about the function's role in the testing framework
+- Use line breaks after each sentence in multi-sentence comments
 
 ### R Code Conventions
 
-- Follow existing naming conventions (snake_case for functions, camelCase for some legacy functions)
+- Follow the [tidyverse style guide](https://style.tidyverse.org)
+- Use `snake_case` for new functions
 - Use explicit package prefixes (e.g., `withr::local_db_connection()`) for clarity
-- Maintain consistent indentation and spacing patterns
-- Use meaningful variable names that reflect the testing context
+- Maintain consistent indentation (2 spaces) and spacing patterns
+- Use meaningful variable names that reflect context
 - Run `air format .` before committing changes to ensure consistent formatting
-- Keep documentation in sync with code changes. When updating roxygen2 documentation, ensure that each sentence is on its own line for better readability. Run `R -q -e 'devtools::document()'` to update the documentation.
 
-## Code Generation
+### Documentation
+
+- Use roxygen2 with Markdown syntax for all function documentation
+- Keep each sentence on its own line in roxygen2 comments for better readability
+- Document internal functions using devtag (work in progress)
+- Link to C documentation using `@cdocs` tag: `#' @cdocs igraph_function_name`
+- Always run `devtools::document()` after updating documentation
+
+### Naming Conventions
+
+- Use `max` for maximal (graph theory term: a vertex is maximal if no other vertex dominates it) and `largest` for maximum (the biggest value in a set)
+
+## File Structure and Organization
+
+### Test Files
+
+- Test files should align with source files
+- `R/name.R` → `tests/testthat/test-name.R`
+
+### Generated Files
+
+**Do not modify these files directly:**
+
+- `src/rinterface.c` (generated by Stimulus)
+- `R/aaa-auto.R` (generated by Stimulus)
+
+Update them using: `make -f Makefile-cigraph src/rinterface.c R/aaa-auto.R`
 
 See `tools/README.md` for guidelines on code generation using the Stimulus framework.
+
+## Testing
+
+- Add test cases for all new functionality
+- For newly created autogenerated functions, always add a test to `test-aaa-auto.R`
+- Test file naming should mirror source file naming
+- Run tests frequently during development and at the end: `testthat::test_local(reporter = "check")`

From 3cbf32c68991995f4b9947c26384b5c21b91873a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Mon, 27 Oct 2025 23:19:42 +0100
Subject: [PATCH 144/154] Format

---
 tests/testthat/test-aaa-auto.R | 120 +++++++++++----------------------
 1 file changed, 38 insertions(+), 82 deletions(-)

diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R
index 514dd50cdc8..171b2106553 100644
--- a/tests/testthat/test-aaa-auto.R
+++ b/tests/testthat/test-aaa-auto.R
@@ -750,9 +750,7 @@ test_that("preference_game_impl basic", {
     types = 2,
     type.dist = c(0.5, 0.5),
     fixed.sizes = FALSE,
-    pref.matrix = matrix(c(0.5,
-        0.5, 0.5, 0.5),
-        2, 2)
+    pref.matrix = matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2)
   ))
 })
 test_that("preference_game_impl errors", {
@@ -764,9 +762,7 @@ test_that("preference_game_impl errors", {
       types = 2,
       type.dist = c(0.5, 0.5),
       fixed.sizes = FALSE,
-      pref.matrix = matrix(c(0.5,
-        0.5, 0.5, 0.5),
-        2, 2)
+      pref.matrix = matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2)
     )
   )
 })
@@ -779,12 +775,8 @@ test_that("asymmetric_preference_game_impl basic", {
     nodes = 5,
     out.types = 2,
     in.types = 2,
-    type.dist.matrix = matrix(c(0.5,
-        0.5, 0.5, 0.5),
-        2, 2),
-    pref.matrix = matrix(c(0.5,
-        0.5, 0.5, 0.5),
-        2, 2)
+    type.dist.matrix = matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2),
+    pref.matrix = matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2)
   ))
 })
 test_that("asymmetric_preference_game_impl errors", {
@@ -795,12 +787,8 @@ test_that("asymmetric_preference_game_impl errors", {
       nodes = -1,
       out.types = 2,
       in.types = 2,
-      type.dist.matrix = matrix(c(0.5,
-        0.5, 0.5, 0.5),
-        2, 2),
-      pref.matrix = matrix(c(0.5,
-        0.5, 0.5, 0.5),
-        2, 2)
+      type.dist.matrix = matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2),
+      pref.matrix = matrix(c(0.5, 0.5, 0.5, 0.5), 2, 2)
     )
   )
 })
@@ -1008,14 +996,12 @@ test_that("sbm_game_impl basic", {
   local_igraph_options(print.id = FALSE)
   expect_snapshot(sbm_game_impl(
     n = 5,
-    pref.matrix = matrix(0.5,
-        2, 2),
+    pref.matrix = matrix(0.5, 2, 2),
     block.sizes = c(2, 3)
   ))
   expect_snapshot(sbm_game_impl(
     n = 5,
-    pref.matrix = matrix(0.5,
-        2, 2),
+    pref.matrix = matrix(0.5, 2, 2),
     block.sizes = c(2, 3),
     directed = TRUE,
     loops = TRUE
@@ -1027,8 +1013,7 @@ test_that("sbm_game_impl errors", {
   local_igraph_options(print.id = FALSE)
   expect_snapshot_igraph_error(sbm_game_impl(
     n = -1,
-    pref.matrix = matrix(0.5,
-        2, 2),
+    pref.matrix = matrix(0.5, 2, 2),
     block.sizes = c(2, 3)
   ))
 })
@@ -1042,8 +1027,7 @@ test_that("hsbm_game_impl basic", {
     n = 6,
     m = 2,
     rho = c(0.5, 0.5),
-    C = matrix(1,
-        2, 2),
+    C = matrix(1, 2, 2),
     p = 0.5
   ))
 })
@@ -1056,8 +1040,7 @@ test_that("hsbm_game_impl errors", {
       n = -1,
       m = 2,
       rho = 0.5,
-      C = matrix(1, 2,
-        2),
+      C = matrix(1, 2, 2),
       p = 0.5
     )
   )
@@ -1103,10 +1086,8 @@ test_that("hsbm_list_game_impl errors", {
       mlist = c(2, 3),
       rholist = list(0.5, 0.5),
       Clist = list(
-        matrix(1,
-        2, 2),
-        matrix(1,
-        2, 2)
+        matrix(1, 2, 2),
+        matrix(1, 2, 2)
       ),
       p = 0.5
     )
@@ -1171,12 +1152,10 @@ test_that("dot_product_game_impl basic", {
   withr::local_seed(20250909)
   local_igraph_options(print.id = FALSE)
   expect_snapshot(dot_product_game_impl(
-    vecs = matrix(0.5,
-    5, 2)
+    vecs = matrix(0.5, 5, 2)
   ))
   expect_snapshot(dot_product_game_impl(
-    vecs = matrix(0.5,
-    5, 2),
+    vecs = matrix(0.5, 5, 2),
     directed = TRUE
   ))
 })
@@ -3755,8 +3734,7 @@ test_that("edgelist_percolation_impl basic", {
   withr::local_seed(20250909)
   local_igraph_options(print.id = FALSE)
   expect_snapshot(edgelist_percolation_impl(
-    edges = matrix(c(1,
-    2, 2, 3), ncol = 2)
+    edges = matrix(c(1, 2, 2, 3), ncol = 2)
   ))
 })
 
@@ -4277,8 +4255,7 @@ test_that("layout_mds_impl basic", {
   ))
   expect_snapshot(layout_mds_impl(
     graph = g,
-    dist = matrix(1:9,
-        nrow = 3),
+    dist = matrix(1:9, nrow = 3),
     dim = 3
   ))
 })
@@ -4335,13 +4312,11 @@ test_that("layout_gem_impl basic", {
 
   expect_snapshot(layout_gem_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 2)
+    res = matrix(0, nrow = 3, ncol = 2)
   ))
   expect_snapshot(layout_gem_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 2),
+    res = matrix(0, nrow = 3, ncol = 2),
     use.seed = TRUE,
     maxiter = 10,
     temp.max = 2,
@@ -4356,8 +4331,7 @@ test_that("layout_gem_impl errors", {
   expect_snapshot_igraph_error(
     layout_gem_impl(
       graph = NULL,
-      res = matrix(0, nrow = 3,
-        ncol = 2)
+      res = matrix(0, nrow = 3, ncol = 2)
     )
   )
 })
@@ -4373,13 +4347,11 @@ test_that("layout_davidson_harel_impl basic", {
 
   expect_snapshot(layout_davidson_harel_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 2)
+    res = matrix(0, nrow = 3, ncol = 2)
   ))
   expect_snapshot(layout_davidson_harel_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 2),
+    res = matrix(0, nrow = 3, ncol = 2),
     use.seed = TRUE,
     maxiter = 10,
     fineiter = 5,
@@ -4398,8 +4370,7 @@ test_that("layout_davidson_harel_impl errors", {
   expect_snapshot_igraph_error(
     layout_davidson_harel_impl(
       graph = NULL,
-      res = matrix(0, nrow = 3,
-        ncol = 2)
+      res = matrix(0, nrow = 3, ncol = 2)
     )
   )
 })
@@ -4415,14 +4386,12 @@ test_that("layout_umap_impl basic", {
 
   expect_snapshot(layout_umap_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 2),
+    res = matrix(0, nrow = 3, ncol = 2),
     use.seed = TRUE
   ))
   expect_snapshot(layout_umap_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 2),
+    res = matrix(0, nrow = 3, ncol = 2),
     use.seed = TRUE,
     distances = 1:3,
     min.dist = 0.1,
@@ -4437,8 +4406,7 @@ test_that("layout_umap_impl errors", {
   expect_snapshot_igraph_error(
     layout_umap_impl(
       graph = NULL,
-      res = matrix(0, nrow = 3,
-        ncol = 2)
+      res = matrix(0, nrow = 3, ncol = 2)
     )
   )
 })
@@ -4454,14 +4422,12 @@ test_that("layout_umap_3d_impl basic", {
 
   expect_snapshot(layout_umap_3d_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 3),
+    res = matrix(0, nrow = 3, ncol = 3),
     use.seed = TRUE
   ))
   expect_snapshot(layout_umap_3d_impl(
     graph = g,
-    res = matrix(0, nrow = 3,
-        ncol = 3),
+    res = matrix(0, nrow = 3, ncol = 3),
     use.seed = TRUE,
     distances = 1:3,
     min.dist = 0.1,
@@ -4476,8 +4442,7 @@ test_that("layout_umap_3d_impl errors", {
   expect_snapshot_igraph_error(
     layout_umap_3d_impl(
       graph = NULL,
-      res = matrix(0, nrow = 3,
-        ncol = 3)
+      res = matrix(0, nrow = 3, ncol = 3)
     )
   )
 })
@@ -4521,8 +4486,7 @@ test_that("layout_align_impl basic", {
 
   expect_snapshot(layout_align_impl(
     graph = g,
-    layout = matrix(0,
-        nrow = 3, ncol = 2)
+    layout = matrix(0, nrow = 3, ncol = 2)
   ))
 })
 
@@ -4532,8 +4496,7 @@ test_that("layout_align_impl errors", {
   expect_snapshot_igraph_error(
     layout_align_impl(
       graph = NULL,
-      layout = matrix(0,
-        nrow = 3, ncol = 2)
+      layout = matrix(0, nrow = 3, ncol = 2)
     )
   )
 })
@@ -4602,13 +4565,11 @@ test_that("similarity_dice_pairs_impl basic", {
 
   expect_snapshot(similarity_dice_pairs_impl(
     graph = g,
-    pairs = matrix(c(1,
-        2, 2, 3), ncol = 2)
+    pairs = matrix(c(1, 2, 2, 3), ncol = 2)
   ))
   expect_snapshot(similarity_dice_pairs_impl(
     graph = g,
-    pairs = matrix(c(1,
-        2, 2, 3), ncol = 2),
+    pairs = matrix(c(1, 2, 2, 3), ncol = 2),
     mode = "in",
     loops = TRUE
   ))
@@ -4620,8 +4581,7 @@ test_that("similarity_dice_pairs_impl errors", {
   expect_snapshot_igraph_error(
     similarity_dice_pairs_impl(
       graph = NULL,
-      pairs = matrix(c(1,
-        2, 2, 3), ncol = 2)
+      pairs = matrix(c(1, 2, 2, 3), ncol = 2)
     )
   )
 })
@@ -4717,13 +4677,11 @@ test_that("similarity_jaccard_pairs_impl basic", {
 
   expect_snapshot(similarity_jaccard_pairs_impl(
     graph = g,
-    pairs = matrix(c(1,
-        2, 2, 3), ncol = 2)
+    pairs = matrix(c(1, 2, 2, 3), ncol = 2)
   ))
   expect_snapshot(similarity_jaccard_pairs_impl(
     graph = g,
-    pairs = matrix(c(1,
-        2, 2, 3), ncol = 2),
+    pairs = matrix(c(1, 2, 2, 3), ncol = 2),
     mode = "in",
     loops = TRUE
   ))
@@ -4735,8 +4693,7 @@ test_that("similarity_jaccard_pairs_impl errors", {
   expect_snapshot_igraph_error(
     similarity_jaccard_pairs_impl(
       graph = NULL,
-      pairs = matrix(c(1,
-        2, 2, 3), ncol = 2)
+      pairs = matrix(c(1, 2, 2, 3), ncol = 2)
     )
   )
 })
@@ -7174,8 +7131,7 @@ test_that("solve_lsap_impl basic", {
   withr::local_seed(20250909)
   local_igraph_options(print.id = FALSE)
   expect_snapshot(solve_lsap_impl(
-    c = matrix(1:4,
-    ncol = 2),
+    c = matrix(1:4, ncol = 2),
     n = 2
   ))
 })

From 5f119152068db0b99ddc14fdf3cb7c4b8ddc03c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Mon, 27 Oct 2025 23:22:29 +0100
Subject: [PATCH 145/154] Settings

---
 air.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/air.toml b/air.toml
index e64c3ccce39..58d5e7dcd80 100644
--- a/air.toml
+++ b/air.toml
@@ -6,4 +6,4 @@ line-ending = "auto"
 persistent-line-breaks = true
 default-exclude = true
 exclude = ["R/utils-s3.R"]
-skip = ["tribble", "graph_from_literal", "matrix", "make_graph", "edges"]
+skip = ["tribble", "graph_from_literal", "matrix", "c", "make_graph", "edges"]

From 79c7b067f6c73612520867483fc6a4792051b3fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Mon, 27 Oct 2025 23:22:52 +0100
Subject: [PATCH 146/154] Simplify

---
 R/versions.R | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/R/versions.R b/R/versions.R
index b4a3b4696fe..75ecff59322 100644
--- a/R/versions.R
+++ b/R/versions.R
@@ -243,5 +243,6 @@ print.igraph_version <- function(x, ...) {
 }
 
 c_version <- function() {
-  version_impl()[["version_string"]]
+  version <- version_impl()
+  version[["version_string"]]
 }

From bd6abe5496ff9cd041ec501102e9e44124fcce79 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Mon, 27 Oct 2025 23:23:55 +0100
Subject: [PATCH 147/154] Names

---
 R/centrality.R | 6 ++++--
 R/community.R  | 2 --
 R/interface.R  | 4 +++-
 R/versions.R   | 1 +
 4 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/R/centrality.R b/R/centrality.R
index d4e23a81bc6..23012bf1f46 100644
--- a/R/centrality.R
+++ b/R/centrality.R
@@ -448,11 +448,12 @@ betweenness <- function(
 ) {
   res <- betweenness_cutoff_impl(
     graph = graph,
+    weights = weights,
     vids = v,
     directed = directed,
-    weights = weights,
     cutoff = cutoff
   )
+
   if (normalized) {
     vc <- as.numeric(vcount(graph))
     if (is_directed(graph) && directed) {
@@ -477,10 +478,11 @@ edge_betweenness <- function(
   e <- as_igraph_es(graph, e)
   res <- edge_betweenness_cutoff_impl(
     graph = graph,
-    directed = directed,
     weights = weights,
+    directed = directed,
     cutoff = cutoff
   )
+
   res[as.numeric(e)]
 }
 
diff --git a/R/community.R b/R/community.R
index 1c581207ce2..85466833556 100644
--- a/R/community.R
+++ b/R/community.R
@@ -1700,7 +1700,6 @@ cluster_leiden <- function(
     res <- community_leiden_impl(
       graph = graph,
       weights = weights,
-      # FIXME: Also check below, might not be covered by tests
       vertex.weights = vertex_weights,
       resolution = resolution,
       beta = beta,
@@ -1718,7 +1717,6 @@ cluster_leiden <- function(
       res <- community_leiden_impl(
         graph = graph,
         weights = weights,
-        # FIXME: Also check above, might not be covered by tests
         vertex.weights = vertex_weights,
         resolution = resolution,
         beta = beta,
diff --git a/R/interface.R b/R/interface.R
index 5b4b1337a50..4187a1013ea 100644
--- a/R/interface.R
+++ b/R/interface.R
@@ -744,5 +744,7 @@ incident_edges <- function(graph, v, mode = c("out", "in", "all", "total")) {
 #' # Result should be the same
 #' is_simple(g)
 invalidate_cache <- function(graph) {
-  invalidate_cache_impl(graph)
+  invalidate_cache_impl(
+    graph = graph
+  )
 }
diff --git a/R/versions.R b/R/versions.R
index 75ecff59322..dc4336fbf7d 100644
--- a/R/versions.R
+++ b/R/versions.R
@@ -244,5 +244,6 @@ print.igraph_version <- function(x, ...) {
 
 c_version <- function() {
   version <- version_impl()
+
   version[["version_string"]]
 }

From 3d8130ed40a88d49d8c8a4c15361527f8d68aebd Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sat, 1 Nov 2025 01:49:37 +0000
Subject: [PATCH 148/154] vendor: Update vendored sources to
 igraph/igraph@6e6f6876ca2f606b8c8bc80342bb9806d702479e (#2460)

Co-authored-by: krlmlr 
---
 src/vendor/cigraph/CHANGELOG.md | 2 +-
 src/vendor/igraph_version.h     | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/vendor/cigraph/CHANGELOG.md b/src/vendor/cigraph/CHANGELOG.md
index a5e564f08b9..7b087346766 100644
--- a/src/vendor/cigraph/CHANGELOG.md
+++ b/src/vendor/cigraph/CHANGELOG.md
@@ -124,7 +124,7 @@ This section lists API-breaking changes in this version, and provides guidance o
 
 - `igraph_community_edge_betweenness()` now takes both a `weights` and a `lengths` parameter. Edge weights (interpreted as connection strengths) are used to divide betweenness scores before selecting them for removal as well as for the modularity computation. Edge lengths are used for defining shortest path lengths during the betweenness computation. This fixes issues #2229 and #1040.
 - `igraph_community_infomap()` now supports regularization and gained the `is_regularized` and `regularization_strength` parameters.
-- `igraph_community_label_propagation()` changed signature to allow specification of label propagation algorithm (LPA) variants. A new fast label propagation variant was added.
+- `igraph_community_label_propagation()` gained the `igraph_lpa_variant_t lpa_variant` parameter to allow specification of label propagation algorithm (LPA) variants. A new fast label propagation variant was added. Set `lpa_variant=DOMINANCE` to select the algorithm used up to igraph 0.10.
 - `igraph_community_leiden()` now takes two `vertex_out_weights` and `vertex_in_weights` parameters in order to support directed graphs, instead of the previous single `node_weights` parameter. To obtain the old behavior for undirected graphs, pass the vertex weights as `vertex_out_weights` and set `vertex_in_weights` to `NULL`.
 - The `history` parameter of `igraph_community_leading_eigenvector()` is now a pointer to an `igraph_vector_int_t` instead of an `igraph_vector_t`.
 - `igraph_community_optimal_modularity()` now takes a `resolution` parameter and its `weight` parameter was moved to the second place.
diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h
index fc5feb5a9d6..558c41ab6b7 100644
--- a/src/vendor/igraph_version.h
+++ b/src/vendor/igraph_version.h
@@ -23,11 +23,11 @@
 
 IGRAPH_BEGIN_C_DECLS
 
-#define IGRAPH_VERSION "1.0.0-30-g2d1bce327"
+#define IGRAPH_VERSION "1.0.0-33-g6e6f6876c"
 #define IGRAPH_VERSION_MAJOR 1
 #define IGRAPH_VERSION_MINOR 0
 #define IGRAPH_VERSION_PATCH 0
-#define IGRAPH_VERSION_PRERELEASE "30-g2d1bce327"
+#define IGRAPH_VERSION_PRERELEASE "33-g6e6f6876c"
 
 IGRAPH_EXPORT void igraph_version(const char **version_string,
                                   int *major,

From 0807c302709ee8b90cc3936c43dfd242f08145e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 1 Nov 2025 17:54:07 +0100
Subject: [PATCH 149/154] Document

---
 R/other.R                  |  2 +-
 man/assortativity.Rd       |  8 +-----
 man/automorphism_group.Rd  |  7 +++++-
 man/centr_degree.Rd        |  2 +-
 man/cliques.Rd             |  2 +-
 man/edge_density.Rd        |  2 +-
 man/global_efficiency.Rd   |  2 +-
 man/graph_center.Rd        |  4 ++-
 man/harmonic_centrality.Rd |  2 +-
 man/page_rank.Rd           | 50 +++++++++++++++++++-------------------
 man/sample_fitness.Rd      |  3 ++-
 man/sample_fitness_pl.Rd   |  9 ++++---
 man/sample_sbm.Rd          | 15 ++++--------
 man/simplify.Rd            |  2 +-
 man/strength.Rd            |  2 +-
 man/weighted_cliques.Rd    | 13 +++++-----
 16 files changed, 61 insertions(+), 64 deletions(-)

diff --git a/R/other.R b/R/other.R
index 4eff3d52685..9d5b42aaf5a 100644
--- a/R/other.R
+++ b/R/other.R
@@ -222,7 +222,7 @@ igraph.i.spMatrix <- function(M) {
 #' convex_hull(M)
 #' @family other
 #' @export
-#' @cdocs igraph_convex_hull
+#' @cdocs igraph_convex_hull_2d
 convex_hull <- function(data) {
   convex_hull_2d_impl(
     data = data
diff --git a/man/assortativity.Rd b/man/assortativity.Rd
index 97a9fd54754..038771a866a 100644
--- a/man/assortativity.Rd
+++ b/man/assortativity.Rd
@@ -17,13 +17,7 @@ assortativity(
   types2 = NULL
 )
 
-assortativity_nominal(
-  graph,
-  weights = NULL,
-  types,
-  directed = TRUE,
-  normalized = TRUE
-)
+assortativity_nominal(graph, types, directed = TRUE, normalized = TRUE)
 
 assortativity_degree(graph, directed = TRUE)
 }
diff --git a/man/automorphism_group.Rd b/man/automorphism_group.Rd
index f67e6cc13e8..b4810c1e3d6 100644
--- a/man/automorphism_group.Rd
+++ b/man/automorphism_group.Rd
@@ -4,7 +4,12 @@
 \alias{automorphism_group}
 \title{Generating set of the automorphism group of a graph}
 \usage{
-automorphism_group(graph, colors = NULL)
+automorphism_group(
+  graph,
+  colors = NULL,
+  sh = c("fm", "f", "fs", "fl", "flm", "fsm"),
+  details = FALSE
+)
 }
 \arguments{
 \item{graph}{The input graph, it is treated as undirected.}
diff --git a/man/centr_degree.Rd b/man/centr_degree.Rd
index 9e60b656976..f6ddd711458 100644
--- a/man/centr_degree.Rd
+++ b/man/centr_degree.Rd
@@ -7,7 +7,7 @@
 centr_degree(
   graph,
   mode = c("all", "out", "in", "total"),
-  loops = c("twice", "none", "once"),
+  loops = TRUE,
   normalized = TRUE
 )
 }
diff --git a/man/cliques.Rd b/man/cliques.Rd
index 4204c2c3ecf..fcf314fd78a 100644
--- a/man/cliques.Rd
+++ b/man/cliques.Rd
@@ -12,7 +12,7 @@
 \alias{is_clique}
 \title{Functions to find cliques, i.e. complete subgraphs in a graph}
 \usage{
-cliques(graph, min = UNLIMITED, max = UNLIMITED, max.results = UNLIMITED)
+cliques(graph, min = 0, max = 0)
 
 largest_cliques(graph)
 
diff --git a/man/edge_density.Rd b/man/edge_density.Rd
index 6c9b330f3bb..99b4db0eb71 100644
--- a/man/edge_density.Rd
+++ b/man/edge_density.Rd
@@ -4,7 +4,7 @@
 \alias{edge_density}
 \title{Graph density}
 \usage{
-edge_density(graph, weights = NULL, loops = FALSE)
+edge_density(graph, loops = FALSE)
 }
 \arguments{
 \item{graph}{The input graph.}
diff --git a/man/global_efficiency.Rd b/man/global_efficiency.Rd
index 2f1684405d7..c2bff5b8b62 100644
--- a/man/global_efficiency.Rd
+++ b/man/global_efficiency.Rd
@@ -10,8 +10,8 @@ global_efficiency(graph, weights = NULL, directed = TRUE)
 
 local_efficiency(
   graph,
-  weights = NULL,
   vids = V(graph),
+  weights = NULL,
   directed = TRUE,
   mode = c("all", "out", "in", "total")
 )
diff --git a/man/graph_center.Rd b/man/graph_center.Rd
index c15fb1e4df6..eb505c7da0f 100644
--- a/man/graph_center.Rd
+++ b/man/graph_center.Rd
@@ -4,11 +4,13 @@
 \alias{graph_center}
 \title{Central vertices of a graph}
 \usage{
-graph_center(graph, weights = NULL, mode = c("all", "out", "in", "total"))
+graph_center(graph, ..., weights = NULL, mode = c("all", "out", "in", "total"))
 }
 \arguments{
 \item{graph}{The input graph, it can be directed or undirected.}
 
+\item{...}{These dots are for future extensions and must be empty.}
+
 \item{weights}{Possibly a numeric vector giving edge weights. If this is
 \code{NULL} and the graph has a \code{weight} edge attribute, then the
 attribute is used. If this is \code{NA} then no weights are used (even if
diff --git a/man/harmonic_centrality.Rd b/man/harmonic_centrality.Rd
index ae8184aec5b..c70629c847d 100644
--- a/man/harmonic_centrality.Rd
+++ b/man/harmonic_centrality.Rd
@@ -10,7 +10,7 @@ harmonic_centrality(
   mode = c("out", "in", "all", "total"),
   weights = NULL,
   normalized = FALSE,
-  cutoff = UNLIMITED
+  cutoff = -1
 )
 }
 \arguments{
diff --git a/man/page_rank.Rd b/man/page_rank.Rd
index 7cec30c3880..182032cf711 100644
--- a/man/page_rank.Rd
+++ b/man/page_rank.Rd
@@ -6,35 +6,18 @@
 \usage{
 page_rank(
   graph,
-  weights = NULL,
-  reset = NULL,
-  damping = 0.85,
-  directed = TRUE,
-  vids = V(graph),
   algo = c("prpack", "arpack"),
+  vids = V(graph),
+  directed = TRUE,
+  damping = 0.85,
+  personalized = NULL,
+  weights = NULL,
   options = NULL
 )
 }
 \arguments{
 \item{graph}{The graph object.}
 
-\item{weights}{A numerical vector or \code{NULL}. This argument can be used
-to give edge weights for calculating the weighted PageRank of vertices. If
-this is \code{NULL} and the graph has a \code{weight} edge attribute then
-that is used. If \code{weights} is a numerical vector then it used, even if
-the graph has a \code{weights} edge attribute. If this is \code{NA}, then no
-edge weights are used (even if the graph has a \code{weight} edge attribute.
-This function interprets edge weights as connection strengths. In the
-random surfer model, an edge with a larger weight is more likely to be
-selected by the surfer.}
-
-\item{damping}{The damping factor (\sQuote{d} in the original paper).}
-
-\item{directed}{Logical, if true directed paths will be considered for
-directed graphs. It is ignored for undirected graphs.}
-
-\item{vids}{The vertices of interest.}
-
 \item{algo}{Character scalar, which implementation to use to carry out the
 calculation. The default is \code{"prpack"}, which uses the PRPACK library
 (\url{https://github.com/dgleich/prpack}) to calculate PageRank scores
@@ -44,15 +27,32 @@ for all but small graphs.  \code{"arpack"} uses the ARPACK library, the
 default implementation from igraph version 0.5 until version 0.7. It computes
 PageRank scores by solving an eingevalue problem.}
 
-\item{options}{A named list, to override some ARPACK options. See
-\code{\link[=arpack]{arpack()}} for details. This argument is ignored if the PRPACK
-implementation is used.}
+\item{vids}{The vertices of interest.}
+
+\item{directed}{Logical, if true directed paths will be considered for
+directed graphs. It is ignored for undirected graphs.}
+
+\item{damping}{The damping factor (\sQuote{d} in the original paper).}
 
 \item{personalized}{Optional vector giving a probability distribution to
 calculate personalized PageRank. For personalized PageRank, the probability
 of jumping to a node when abandoning the random walk is not uniform, but it
 is given by this vector. The vector should contains an entry for each vertex
 and it will be rescaled to sum up to one.}
+
+\item{weights}{A numerical vector or \code{NULL}. This argument can be used
+to give edge weights for calculating the weighted PageRank of vertices. If
+this is \code{NULL} and the graph has a \code{weight} edge attribute then
+that is used. If \code{weights} is a numerical vector then it used, even if
+the graph has a \code{weights} edge attribute. If this is \code{NA}, then no
+edge weights are used (even if the graph has a \code{weight} edge attribute.
+This function interprets edge weights as connection strengths. In the
+random surfer model, an edge with a larger weight is more likely to be
+selected by the surfer.}
+
+\item{options}{A named list, to override some ARPACK options. See
+\code{\link[=arpack]{arpack()}} for details. This argument is ignored if the PRPACK
+implementation is used.}
 }
 \value{
 A named list with entries:
diff --git a/man/sample_fitness.Rd b/man/sample_fitness.Rd
index 9e299a9a53e..28d1ec28925 100644
--- a/man/sample_fitness.Rd
+++ b/man/sample_fitness.Rd
@@ -8,7 +8,8 @@ sample_fitness(
   no.of.edges,
   fitness.out,
   fitness.in = NULL,
-  allowed.edge.types = c("simple", "loops", "multi", "all")
+  loops = FALSE,
+  multiple = FALSE
 )
 }
 \arguments{
diff --git a/man/sample_fitness_pl.Rd b/man/sample_fitness_pl.Rd
index 7981f0f1cfb..003c9ae2411 100644
--- a/man/sample_fitness_pl.Rd
+++ b/man/sample_fitness_pl.Rd
@@ -9,7 +9,8 @@ sample_fitness_pl(
   no.of.edges,
   exponent.out,
   exponent.in = -1,
-  allowed.edge.types = c("simple", "loops", "multi", "all"),
+  loops = FALSE,
+  multiple = FALSE,
   finite.size.correction = TRUE
 )
 }
@@ -28,14 +29,14 @@ undirected. If greater than or equal to 2, this argument specifies the
 exponent of the in-degree distribution. If non-negative but less than 2, an
 error will be generated.}
 
-\item{finite.size.correction}{Logical scalar, whether to use the proposed
-finite size correction of Cho et al., see references below.}
-
 \item{loops}{Logical scalar, whether to allow loop edges in the generated
 graph.}
 
 \item{multiple}{Logical scalar, whether to allow multiple edges in the
 generated graph.}
+
+\item{finite.size.correction}{Logical scalar, whether to use the proposed
+finite size correction of Cho et al., see references below.}
 }
 \value{
 An igraph graph, directed or undirected.
diff --git a/man/sample_sbm.Rd b/man/sample_sbm.Rd
index f9897450a61..1fe65860ee8 100644
--- a/man/sample_sbm.Rd
+++ b/man/sample_sbm.Rd
@@ -5,16 +5,13 @@
 \alias{sbm}
 \title{Sample stochastic block model}
 \usage{
-sample_sbm(
-  pref.matrix,
-  block.sizes,
-  directed = FALSE,
-  allowed.edge.types = c("simple", "loops", "multi", "all")
-)
+sample_sbm(n, pref.matrix, block.sizes, directed = FALSE, loops = FALSE)
 
 sbm(...)
 }
 \arguments{
+\item{n}{Number of vertices in the graph.}
+
 \item{pref.matrix}{The matrix giving the Bernoulli rates.  This is a
 \eqn{K\times K}{KxK} matrix, where \eqn{K} is the number of groups. The
 probability of creating an edge between vertices from groups \eqn{i} and
@@ -26,11 +23,9 @@ group. The sum of the vector must match the number of vertices.}
 
 \item{directed}{Logical scalar, whether to generate a directed graph.}
 
-\item{...}{Passed to \code{sample_sbm()}.}
-
-\item{n}{Number of vertices in the graph.}
-
 \item{loops}{Logical scalar, whether self-loops are allowed in the graph.}
+
+\item{...}{Passed to \code{sample_sbm()}.}
 }
 \value{
 An igraph graph.
diff --git a/man/simplify.Rd b/man/simplify.Rd
index 0e4d05a87f2..eea308171a7 100644
--- a/man/simplify.Rd
+++ b/man/simplify.Rd
@@ -13,7 +13,7 @@ simplify(
   edge.attr.comb = igraph_opt("edge.attr.comb")
 )
 
-is_simple(graph, directed = TRUE)
+is_simple(graph)
 
 simplify_and_colorize(graph)
 }
diff --git a/man/strength.Rd b/man/strength.Rd
index cd7c1db3cd5..76a2e34f9b6 100644
--- a/man/strength.Rd
+++ b/man/strength.Rd
@@ -8,7 +8,7 @@ strength(
   graph,
   vids = V(graph),
   mode = c("all", "out", "in", "total"),
-  loops = c("twice", "none", "once"),
+  loops = TRUE,
   weights = NULL
 )
 }
diff --git a/man/weighted_cliques.Rd b/man/weighted_cliques.Rd
index a2bc0797ed3..d3af9be3171 100644
--- a/man/weighted_cliques.Rd
+++ b/man/weighted_cliques.Rd
@@ -7,10 +7,9 @@
 weighted_cliques(
   graph,
   vertex.weights = NULL,
-  maximal = FALSE,
-  min.weight = UNLIMITED,
-  max.weight = UNLIMITED,
-  max.results = UNLIMITED
+  min.weight = 0,
+  max.weight = 0,
+  maximal = FALSE
 )
 }
 \arguments{
@@ -23,14 +22,14 @@ vertex attribute, then this is used by default. If the graph does not have a
 vertex is assumed to have a weight of 1. Note that the current implementation
 of the weighted clique finder supports positive integer weights only.}
 
-\item{maximal}{Specifies whether to look for all weighted cliques (\code{FALSE})
-or only the maximal ones (\code{TRUE}).}
-
 \item{min.weight}{Numeric constant, lower limit on the weight of the cliques to find.
 \code{NULL} means no limit, i.e. it is the same as 0.}
 
 \item{max.weight}{Numeric constant, upper limit on the weight of the cliques to find.
 \code{NULL} means no limit.}
+
+\item{maximal}{Specifies whether to look for all weighted cliques (\code{FALSE})
+or only the maximal ones (\code{TRUE}).}
 }
 \value{
 \code{weighted_cliques()} and \code{largest_weighted_cliques()} return a

From 4b6253d880a247433f6dbacb273a8b9dc1c45feb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kirill=20M=C3=BCller?= 
Date: Sat, 1 Nov 2025 18:04:06 +0100
Subject: [PATCH 150/154] igraph_match_arg

---
 NEWS.md                                       |  4 +-
 R/adjacency.R                                 |  4 +-
 R/bipartite.R                                 |  2 +-
 R/centrality.R                                |  4 +-
 R/centralization.R                            |  4 +-
 R/community.R                                 | 14 ++---
 R/components.R                                |  2 +-
 R/conversion.R                                | 18 +++----
 R/epi.R                                       |  4 +-
 R/fit.R                                       |  2 +-
 R/flow.R                                      |  2 +-
 R/foreign.R                                   |  8 +--
 R/games.R                                     | 18 +++----
 R/hrg.R                                       |  2 +-
 R/incidence.R                                 |  2 +-
 R/interface.R                                 |  6 +--
 R/iterators.R                                 |  2 +-
 R/layout.R                                    | 14 ++---
 R/make.R                                      | 18 +++----
 R/minimum.spanning.tree.R                     |  2 +-
 R/operators.R                                 |  2 +-
 R/plot.common.R                               |  2 +-
 R/plot.shapes.R                               |  2 +-
 R/rewire.R                                    |  2 +-
 R/scan.R                                      |  4 +-
 R/similarity.R                                |  2 +-
 R/structural-properties.R                     | 52 +++++++++----------
 R/topology.R                                  | 12 ++---
 R/utils-assert-args.R                         |  4 +-
 tests/testthat/_snaps/utils-assert-args.md    |  2 +-
 tests/testthat/test-utils-assert-args.R       |  2 +-
 .../py-stimulus/src/stimulus/generators/r.py  |  2 +-
 32 files changed, 110 insertions(+), 110 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index 0d07bdca215..3ac0a89657a 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -150,7 +150,7 @@
 
 - Rm useless error message (#1998).
 
-- Improve `igraph.match.arg()` (#1996).
+- Improve `igraph_match_arg()` (#1996).
 
 
 # igraph 2.1.4.9068
@@ -1871,7 +1871,7 @@ See = 0 & quantiles <= 1)) {
     cli::cli_abort("All {.arg quantiles} should be in [0,1].")
   }
diff --git a/R/fit.R b/R/fit.R
index 32c6d33e475..b1f0292c94b 100644
--- a/R/fit.R
+++ b/R/fit.R
@@ -190,7 +190,7 @@ fit_power_law <- function(
   p.precision = NULL,
   ...
 ) {
-  implementation <- igraph.match.arg(implementation)
+  implementation <- igraph_match_arg(implementation)
 
   if (implementation == "r.mle") {
     if (isTRUE(p.value)) {
diff --git a/R/flow.R b/R/flow.R
index 9d95389549b..0dc17ed20d2 100644
--- a/R/flow.R
+++ b/R/flow.R
@@ -906,7 +906,7 @@ dominator_tree <- function(graph, root, mode = c("out", "in", "all", "total")) {
   }
   root <- as_igraph_vs(graph, root)
 
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   # Function call
   res <- dominator_tree_impl(
diff --git a/R/foreign.R b/R/foreign.R
index a670b2cd65c..ab5917cc0e7 100644
--- a/R/foreign.R
+++ b/R/foreign.R
@@ -331,7 +331,7 @@ read_graph <- function(
     write.graph.fromraw(buffer, file)
   }
 
-  format <- igraph.match.arg(format)
+  format <- igraph_match_arg(format)
   res <- switch(
     format,
     "pajek" = read.graph.pajek(file, ...),
@@ -497,7 +497,7 @@ write_graph <- function(
     tmpfile <- FALSE
   }
 
-  format <- igraph.match.arg(format)
+  format <- igraph_match_arg(format)
   res <- switch(
     format,
     "pajek" = write.graph.pajek(graph, file, ...),
@@ -550,7 +550,7 @@ read.graph.ncol <- function(
   directed = FALSE
 ) {
   weights <- switch(
-    igraph.match.arg(weights),
+    igraph_match_arg(weights),
     "no" = 0L,
     "yes" = 1L,
     "auto" = 2L
@@ -598,7 +598,7 @@ read.graph.lgl <- function(
   directed = FALSE
 ) {
   weights <- switch(
-    igraph.match.arg(weights),
+    igraph_match_arg(weights),
     "no" = 0L,
     "yes" = 1L,
     "auto" = 2L
diff --git a/R/games.R b/R/games.R
index 022f805bfc7..517effbe71e 100644
--- a/R/games.R
+++ b/R/games.R
@@ -938,7 +938,7 @@ sample_pa <- function(
     ))
   }
 
-  algorithm <- igraph.match.arg(algorithm)
+  algorithm <- igraph_match_arg(algorithm)
   algorithm1 <- switch(
     algorithm,
     "psumtree" = 1,
@@ -1137,7 +1137,7 @@ erdos.renyi.game <- function(
   directed = FALSE,
   loops = FALSE
 ) {
-  type <- igraph.match.arg(type)
+  type <- igraph_match_arg(type)
 
   if (type == "gnp") {
     lifecycle::deprecate_soft("0.8.0", "erdos.renyi.game()", "sample_gnp()")
@@ -1157,7 +1157,7 @@ random.graph.game <- function(
   directed = FALSE,
   loops = FALSE
 ) {
-  type <- igraph.match.arg(type)
+  type <- igraph_match_arg(type)
 
   if (type == "gnp") {
     lifecycle::deprecate_soft("0.8.0", "random.graph.game()", "sample_gnp()")
@@ -1355,7 +1355,7 @@ sample_degseq <- function(
   if (missing(method)) {
     method <- method[1]
   }
-  method <- igraph.match.arg(
+  method <- igraph_match_arg(
     method,
     values = c(
       "configuration",
@@ -2035,7 +2035,7 @@ asym_pref <- function(...) constructor_spec(sample_asym_pref, ...)
 #' @family functions for manipulating graph structure
 connect <- function(graph, order, mode = c("all", "out", "in", "total")) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -2307,8 +2307,8 @@ sample_bipartite <- function(
   directed = FALSE,
   mode = c("out", "in", "all")
 ) {
-  type <- igraph.match.arg(type)
-  mode <- igraph.match.arg(mode)
+  type <- igraph_match_arg(type)
+  mode <- igraph_match_arg(mode)
 
   if (type == "gnp") {
     lifecycle::deprecate_soft(
@@ -2414,7 +2414,7 @@ sample_bipartite_gnm <- function(
   mode = c("out", "in", "all")
 ) {
   check_dots_empty()
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   m <- as.numeric(m)
 
   res <- bipartite_game_gnm_impl(
@@ -2443,7 +2443,7 @@ sample_bipartite_gnp <- function(
   mode = c("out", "in", "all")
 ) {
   check_dots_empty()
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   p <- as.numeric(p)
 
   res <- bipartite_game_gnp_impl(
diff --git a/R/hrg.R b/R/hrg.R
index 3bf54daee63..b9bbe940e23 100644
--- a/R/hrg.R
+++ b/R/hrg.R
@@ -911,7 +911,7 @@ print.igraphHRG <- function(
   level = 3,
   ...
 ) {
-  type <- igraph.match.arg(type)
+  type <- igraph_match_arg(type)
   if (type == "auto") {
     is_graph_small <- (length(x$left) <= 100)
     type <- if (is_graph_small) "tree" else "plain"
diff --git a/R/incidence.R b/R/incidence.R
index aea08429578..3937ad025af 100644
--- a/R/incidence.R
+++ b/R/incidence.R
@@ -195,7 +195,7 @@ graph_from_biadjacency_matrix <- function(
   # Argument checks
   ensure_no_na(incidence, "biadjacency matrix")
   directed <- as.logical(directed)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   multiple <- as.logical(multiple)
 
diff --git a/R/interface.R b/R/interface.R
index 4187a1013ea..faf882e3ac2 100644
--- a/R/interface.R
+++ b/R/interface.R
@@ -349,7 +349,7 @@ ecount <- gsize
 #' intersection(n1, n34)
 neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   v <- as_igraph_vs(graph, v)
   if (length(v) == 0) {
@@ -395,11 +395,11 @@ incident <- function(
 ) {
   ensure_igraph(graph)
   if (is_directed(graph)) {
-    mode <- igraph.match.arg(mode)
+    mode <- igraph_match_arg(mode)
   } else {
     mode <- "out"
   }
-  loops <- igraph.match.arg(loops)
+  loops <- igraph_match_arg(loops)
   v <- as_igraph_vs(graph, v)
   if (length(v) == 0) {
     stop("No vertex was specified")
diff --git a/R/iterators.R b/R/iterators.R
index 589f3362f88..c1199014b6e 100644
--- a/R/iterators.R
+++ b/R/iterators.R
@@ -583,7 +583,7 @@ simple_vs_index <- function(x, i, na_ok = FALSE) {
   .nei <- function(v, mode = c("all", "in", "out", "total")) {
     ## TRUE iff the vertex is a neighbor (any type)
     ## of at least one vertex in v
-    mode <- igraph.match.arg(mode)
+    mode <- igraph_match_arg(mode)
     mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3)
 
     if (is.logical(v)) {
diff --git a/R/layout.R b/R/layout.R
index 67f3a086c78..af06249748c 100644
--- a/R/layout.R
+++ b/R/layout.R
@@ -749,7 +749,7 @@ layout_as_tree <- function(
   circular <- as.logical(circular)
   rootlevel <- as.double(rootlevel)
   mode <- switch(
-    igraph.match.arg(mode),
+    igraph_match_arg(mode),
     "out" = 1,
     "in" = 2,
     "all" = 3,
@@ -1129,7 +1129,7 @@ layout.sphere <- function(..., params = list()) {
 layout_randomly <- function(graph, dim = c(2, 3)) {
   ensure_igraph(graph)
 
-  dim <- igraph.match.arg(dim)
+  dim <- igraph_match_arg(dim)
 
   if (dim == 2) {
     layout_random_impl(
@@ -1434,7 +1434,7 @@ layout_with_fr <- function(
   # Argument checks
   ensure_igraph(graph)
   coords[] <- as.numeric(coords)
-  dim <- igraph.match.arg(dim)
+  dim <- igraph_match_arg(dim)
   if (!missing(niter) && !missing(maxiter)) {
     cli::cli_abort(c(
       "{.arg niter} and {.arg maxiter} must not be specified at the same time.",
@@ -1447,7 +1447,7 @@ layout_with_fr <- function(
   niter <- as.numeric(niter)
   start.temp <- as.numeric(start.temp)
 
-  grid <- igraph.match.arg(grid)
+  grid <- igraph_match_arg(grid)
   grid <- switch(grid, "grid" = 0L, "nogrid" = 1L, "auto" = 2L)
 
   if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
@@ -1811,7 +1811,7 @@ layout_with_kk <- function(
 
   ensure_igraph(graph)
   coords[] <- as.numeric(coords)
-  dim <- igraph.match.arg(dim)
+  dim <- igraph_match_arg(dim)
 
   maxiter <- as.numeric(maxiter)
   epsilon <- as.numeric(epsilon)
@@ -2320,7 +2320,7 @@ layout_with_sugiyama <- function(
   } else {
     weights <- NULL
   }
-  attributes <- igraph.match.arg(attributes)
+  attributes <- igraph_match_arg(attributes)
 
   on.exit(.Call(R_igraph_finalizer))
   # Function call
@@ -2823,7 +2823,7 @@ layout_with_drl <- function(
 ) {
   ensure_igraph(graph)
 
-  dim <- igraph.match.arg(dim)
+  dim <- igraph_match_arg(dim)
 
   use.seed <- as.logical(use.seed)
   seed <- as.matrix(seed)
diff --git a/R/make.R b/R/make.R
index 7939a05432e..01fc5dfc8c9 100644
--- a/R/make.R
+++ b/R/make.R
@@ -318,7 +318,7 @@ graph.ring <- function(n, directed = FALSE, mutual = FALSE, circular = TRUE) {
 graph.tree <- function(n, children = 2, mode = c("out", "in", "undirected")) {
   # nocov start
   lifecycle::deprecate_soft("2.1.0", "graph.tree()", "make_tree()")
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -353,7 +353,7 @@ graph.star <- function(
 ) {
   # nocov start
   lifecycle::deprecate_soft("2.1.0", "graph.star()", "make_star()")
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2, "mutual" = 3)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -539,7 +539,7 @@ graph.full.bipartite <- function(
   n2 <- as.numeric(n2)
   directed <- as.logical(directed)
   mode1 <- switch(
-    igraph.match.arg(mode),
+    igraph_match_arg(mode),
     "out" = 1,
     "in" = 2,
     "all" = 3,
@@ -1879,7 +1879,7 @@ make_star <- function(
   mode = c("in", "out", "mutual", "undirected"),
   center = 1
 ) {
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2, "mutual" = 3)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -2093,7 +2093,7 @@ ring <- function(...) constructor_spec(make_ring, ...)
 #' make_tree(10, 2)
 #' make_tree(10, 3, mode = "undirected")
 make_tree <- function(n, children = 2, mode = c("out", "in", "undirected")) {
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -2506,7 +2506,7 @@ make_full_bipartite_graph <- function(
   n2 <- as.numeric(n2)
   directed <- as.logical(directed)
   mode1 <- switch(
-    igraph.match.arg(mode),
+    igraph_match_arg(mode),
     "out" = 1,
     "in" = 2,
     "all" = 3,
@@ -2652,7 +2652,7 @@ make_full_multipartite <- function(
 ) {
   n <- as.numeric(n)
   directed <- as.logical(directed)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   res <- full_multipartite_impl(n = n, directed = directed, mode = mode)
   graph <- set_vertex_attr(res$graph, "type", value = res$types)
@@ -2980,8 +2980,8 @@ realize_bipartite_degseq <- function(
   method = c("smallest", "largest", "index")
 ) {
   check_dots_empty()
-  allowed.edge.types <- igraph.match.arg(allowed.edge.types)
-  method <- igraph.match.arg(method)
+  allowed.edge.types <- igraph_match_arg(allowed.edge.types)
+  method <- igraph_match_arg(method)
   g <- realize_bipartite_degree_sequence_impl(
     degrees1 = degrees1,
     degrees2 = degrees2,
diff --git a/R/minimum.spanning.tree.R b/R/minimum.spanning.tree.R
index d7bf8c6954d..7ed253c96fe 100644
--- a/R/minimum.spanning.tree.R
+++ b/R/minimum.spanning.tree.R
@@ -86,7 +86,7 @@ mst <- function(
   ...
 ) {
   ensure_igraph(graph)
-  algorithm <- igraph.match.arg(algorithm)
+  algorithm <- igraph_match_arg(algorithm)
   minimum_spanning_tree_impl(
     graph = graph,
     weights = weights,
diff --git a/R/operators.R b/R/operators.R
index 361775f32d3..2a58a86ca00 100644
--- a/R/operators.R
+++ b/R/operators.R
@@ -126,7 +126,7 @@ rename.attr.if.needed <- function(
   maps2 = NULL,
   ignore = character()
 ) {
-  type <- igraph.match.arg(type)
+  type <- igraph_match_arg(type)
 
   listfun <- switch(
     type,
diff --git a/R/plot.common.R b/R/plot.common.R
index 00b7f456164..4f78cce3d2a 100644
--- a/R/plot.common.R
+++ b/R/plot.common.R
@@ -548,7 +548,7 @@ i.parse.plot.params <- function(graph, params) {
     range = NULL,
     dontcall = FALSE
   ) {
-    type <- igraph.match.arg(type)
+    type <- igraph_match_arg(type)
     ret <- function() {
       v <- p[[type]][[name]]
       if (is.function(v) && !dontcall) {
diff --git a/R/plot.shapes.R b/R/plot.shapes.R
index 298e2e3391f..b8380cb10fe 100644
--- a/R/plot.shapes.R
+++ b/R/plot.shapes.R
@@ -351,7 +351,7 @@ shapes <- function(shape = NULL) {
 #' @rdname shapes
 #' @export
 shape_noclip <- function(coords, el, params, end = c("both", "from", "to")) {
-  end <- igraph.match.arg(end)
+  end <- igraph_match_arg(end)
 
   if (end == "both") {
     coords
diff --git a/R/rewire.R b/R/rewire.R
index 57801a36fb0..755fe8733ff 100644
--- a/R/rewire.R
+++ b/R/rewire.R
@@ -134,7 +134,7 @@ each_edge <- function(
   mode = c("all", "out", "in", "total")
 ) {
   mode <- switch(
-    igraph.match.arg(mode),
+    igraph_match_arg(mode),
     "out" = 1,
     "in" = 2,
     "all" = 3,
diff --git a/R/scan.R b/R/scan.R
index 0efea006863..a866b25faf9 100644
--- a/R/scan.R
+++ b/R/scan.R
@@ -163,7 +163,7 @@ local_scan <- function(
   }
 
   ## Check mode argument
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   cmode <- switch(mode, out = 1, `in` = 2, all = 3, total = 3)
 
   sumweights <- function(g) sum(E(g)$weight)
@@ -404,7 +404,7 @@ scan_stat <- function(
   ## ell must the a non-negative integer
   stopifnot(length(ell) == 1, ell >= 0, trunc(ell) == ell)
 
-  locality <- igraph.match.arg(locality)
+  locality <- igraph_match_arg(locality)
 
   ## number of time steps and number of vertices
   maxTime <- length(graphs)
diff --git a/R/similarity.R b/R/similarity.R
index 0feaa99ee46..d3edeeb0bc6 100644
--- a/R/similarity.R
+++ b/R/similarity.R
@@ -84,7 +84,7 @@ similarity <- function(
     }
   }
 
-  method <- igraph.match.arg(method)
+  method <- igraph_match_arg(method)
 
   switch(
     method,
diff --git a/R/structural-properties.R b/R/structural-properties.R
index 6f494f0919f..2931f5dd300 100644
--- a/R/structural-properties.R
+++ b/R/structural-properties.R
@@ -150,8 +150,8 @@ shortest.paths <- function(
 ) {
   # nocov start
   lifecycle::deprecate_soft("2.0.0", "shortest.paths()", "distances()")
-  algorithm <- igraph.match.arg(algorithm)
-  mode <- igraph.match.arg(mode)
+  algorithm <- igraph_match_arg(algorithm)
+  mode <- igraph_match_arg(mode)
   distances(
     graph = graph,
     v = v,
@@ -921,7 +921,7 @@ degree <- function(
   normalized = FALSE
 ) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   if (is.logical(loops)) {
     lifecycle::deprecate_soft(
@@ -935,7 +935,7 @@ degree <- function(
     }
   }
 
-  loops <- igraph.match.arg(loops)
+  loops <- igraph_match_arg(loops)
 
   res <- degree_impl(
     graph = graph,
@@ -964,7 +964,7 @@ max_degree <- function(
   loops = c("twice", "none", "once")
 ) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   if (is.logical(loops)) {
     lifecycle::deprecate_soft(
@@ -977,7 +977,7 @@ max_degree <- function(
       loops <- "none"
     }
   }
-  loops <- igraph.match.arg(loops)
+  loops <- igraph_match_arg(loops)
 
   maxdegree_impl(
     graph = graph,
@@ -1244,9 +1244,9 @@ distances <- function(
 
   v <- as_igraph_vs(graph, v)
   to <- as_igraph_vs(graph, to)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3)
-  algorithm <- igraph.match.arg(algorithm)
+  algorithm <- igraph_match_arg(algorithm)
   algorithm <- switch(
     algorithm,
     "automatic" = 0,
@@ -1327,11 +1327,11 @@ shortest_paths <- function(
   algorithm = c("automatic", "unweighted", "dijkstra", "bellman-ford")
 ) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3)
-  output <- igraph.match.arg(output)
+  output <- igraph_match_arg(output)
   output <- switch(output, "vpath" = 0, "epath" = 1, "both" = 2)
-  algorithm <- igraph.match.arg(algorithm)
+  algorithm <- igraph_match_arg(algorithm)
   algorithm <- switch(
     algorithm,
     "automatic" = 0,
@@ -1433,7 +1433,7 @@ all_shortest_paths <- function(
 ) {
   ensure_igraph(graph)
 
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   if (is.null(weights)) {
     if ("weight" %in% edge_attr_names(graph)) {
@@ -1553,7 +1553,7 @@ k_shortest_paths <- function(
 #' subcomponent(g, 1, "all")
 subcomponent <- function(graph, v, mode = c("all", "out", "in")) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -1627,7 +1627,7 @@ induced_subgraph <- function(
   # Argument checks
   ensure_igraph(graph)
   vids <- as_igraph_vs(graph, vids)
-  impl <- igraph.match.arg(impl)
+  impl <- igraph_match_arg(impl)
 
   # Function call
   res <- induced_subgraph_impl(
@@ -1818,7 +1818,7 @@ transitivity <- function(
   isolates = c("NaN", "zero")
 ) {
   ensure_igraph(graph)
-  type <- igraph.match.arg(type)
+  type <- igraph_match_arg(type)
   type <- switch(
     type,
     "undirected" = 0L,
@@ -1842,7 +1842,7 @@ transitivity <- function(
     weights <- NULL
   }
 
-  isolates <- igraph.match.arg(isolates)
+  isolates <- igraph_match_arg(isolates)
 
   if (type == 0) {
     transitivity_undirected_impl(
@@ -2084,7 +2084,7 @@ ego_size <- function(
   mindist = 0
 ) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3)
   mindist <- as.numeric(mindist)
 
@@ -2198,7 +2198,7 @@ ego <- function(
   mindist = 0
 ) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3)
   mindist <- as.numeric(mindist)
 
@@ -2233,7 +2233,7 @@ make_ego_graph <- function(
   mindist = 0
 ) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1L, "in" = 2L, "all" = 3L)
   mindist <- as.numeric(mindist)
 
@@ -2290,7 +2290,7 @@ make_neighborhood_graph <- make_ego_graph
 #'
 coreness <- function(graph, mode = c("all", "out", "in")) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -2333,7 +2333,7 @@ coreness <- function(graph, mode = c("all", "out", "in")) {
 #'
 topo_sort <- function(graph, mode = c("out", "all", "in")) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -2785,7 +2785,7 @@ bfs <- function(
     root <- 0 # ignored anyway
   }
   mode <- switch(
-    igraph.match.arg(mode),
+    igraph_match_arg(mode),
     "out" = 1,
     "in" = 2,
     "all" = 3,
@@ -3041,7 +3041,7 @@ dfs <- function(
 
   root <- as_igraph_vs(graph, root) - 1
   mode <- switch(
-    igraph.match.arg(mode),
+    igraph_match_arg(mode),
     "out" = 1,
     "in" = 2,
     "all" = 3,
@@ -3181,7 +3181,7 @@ dfs <- function(
 components <- function(graph, mode = c("weak", "strong")) {
   # Argument checks
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
 
   # Function call
   res <- connected_components_impl(
@@ -3211,7 +3211,7 @@ is_connected <- function(graph, mode = c("weak", "strong")) {
 #' @export
 count_components <- function(graph, mode = c("weak", "strong")) {
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   mode <- switch(mode, "weak" = 1L, "strong" = 2L)
 
   on.exit(.Call(R_igraph_finalizer))
@@ -3311,7 +3311,7 @@ count_reachable <- function(graph, mode = c("out", "in", "all", "total")) {
 unfold_tree <- function(graph, mode = c("all", "out", "in", "total"), roots) {
   # Argument checks
   ensure_igraph(graph)
-  mode <- igraph.match.arg(mode)
+  mode <- igraph_match_arg(mode)
   roots <- as_igraph_vs(graph, roots) - 1
 
   # Function call
diff --git a/R/topology.R b/R/topology.R
index 600a4839b29..1cc9821e320 100644
--- a/R/topology.R
+++ b/R/topology.R
@@ -457,7 +457,7 @@ isomorphic <- function(
 ) {
   ensure_igraph(graph1)
   ensure_igraph(graph2)
-  method <- igraph.match.arg(method)
+  method <- igraph_match_arg(method)
 
   if (method == "auto") {
     isomorphic_impl(
@@ -652,7 +652,7 @@ subgraph_isomorphic <- function(
   method = c("auto", "lad", "vf2"),
   ...
 ) {
-  method <- igraph.match.arg(method)
+  method <- igraph_match_arg(method)
 
   if (method == "auto") {
     method <- "lad"
@@ -711,7 +711,7 @@ is_subgraph_isomorphic_to <- subgraph_isomorphic
 #'   vertex.color2 = NULL
 #' )
 count_isomorphisms <- function(graph1, graph2, method = "vf2", ...) {
-  method <- igraph.match.arg(method)
+  method <- igraph_match_arg(method)
 
   if (method == "vf2") {
     graph.count.isomorphisms.vf2(graph1, graph2, ...)
@@ -816,7 +816,7 @@ count_subgraph_isomorphisms <- function(
   method = c("lad", "vf2"),
   ...
 ) {
-  method <- igraph.match.arg(method)
+  method <- igraph_match_arg(method)
 
   if (method == "lad") {
     length(graph.subisomorphic.lad(pattern, target, all.maps = TRUE, ...)$maps)
@@ -868,7 +868,7 @@ graph.count.subisomorphisms.vf2 <- function(
 #' @export
 #' @family graph isomorphism
 isomorphisms <- function(graph1, graph2, method = "vf2", ...) {
-  method <- igraph.match.arg(method)
+  method <- igraph_match_arg(method)
 
   if (method == "vf2") {
     graph.get.isomorphisms.vf2(graph1, graph2, ...)
@@ -939,7 +939,7 @@ subgraph_isomorphisms <- function(
   method = c("lad", "vf2"),
   ...
 ) {
-  method <- igraph.match.arg(method)
+  method <- igraph_match_arg(method)
 
   if (method == "lad") {
     graph.subisomorphic.lad(pattern, target, all.maps = TRUE, ...)$maps
diff --git a/R/utils-assert-args.R b/R/utils-assert-args.R
index d6bbf43419f..3f9a2708a7f 100644
--- a/R/utils-assert-args.R
+++ b/R/utils-assert-args.R
@@ -29,7 +29,7 @@ switch_igraph_arg <- function(
   if (length(arg) > 1) {
     values <- intersect(values, tolower(arg))
   }
-  match <- igraph.match.arg(
+  match <- igraph_match_arg(
     arg,
     values,
     error_arg = .error_arg,
@@ -38,7 +38,7 @@ switch_igraph_arg <- function(
   switch(match, ...)
 }
 
-igraph.match.arg <- function(
+igraph_match_arg <- function(
   arg,
   values,
   error_arg = rlang::caller_arg(arg),
diff --git a/tests/testthat/_snaps/utils-assert-args.md b/tests/testthat/_snaps/utils-assert-args.md
index be2c21ee633..88628bf245a 100644
--- a/tests/testthat/_snaps/utils-assert-args.md
+++ b/tests/testthat/_snaps/utils-assert-args.md
@@ -10,7 +10,7 @@
 
     Must provide a graph object (provided `NULL`).
 
-# igraph.match.arg() works
+# igraph_match_arg() works
 
     Code
       cluster_leiden(make_graph("Zachary"), objective_function = "something")
diff --git a/tests/testthat/test-utils-assert-args.R b/tests/testthat/test-utils-assert-args.R
index 0c5f88f7745..a2984d3a94b 100644
--- a/tests/testthat/test-utils-assert-args.R
+++ b/tests/testthat/test-utils-assert-args.R
@@ -6,7 +6,7 @@ test_that("ensure_igraph() works", {
   expect_silent(ensure_igraph(NULL, optional = TRUE))
 })
 
-test_that("igraph.match.arg() works", {
+test_that("igraph_match_arg() works", {
   expect_snapshot(
     cluster_leiden(make_graph("Zachary"), objective_function = "something"),
     error = TRUE
diff --git a/tools/py-stimulus/src/stimulus/generators/r.py b/tools/py-stimulus/src/stimulus/generators/r.py
index b1860106911..e59168c4b68 100644
--- a/tools/py-stimulus/src/stimulus/generators/r.py
+++ b/tools/py-stimulus/src/stimulus/generators/r.py
@@ -60,7 +60,7 @@ def format_switch_statement(code: str) -> str:
     switch_pattern = r'(switch\([^,]+)(,\s*)([^)]+)(\))'
 
     def format_switch_args(match):
-        prefix = match.group(1)  # "switch(igraph.match.arg(mode)"
+        prefix = match.group(1)  # "switch(igraph_match_arg(mode)"
         comma = match.group(2)   # ","
         args = match.group(3)    # the key-value pairs
         suffix = match.group(4)  # ")"

From 3e3abfd859f0893b71c7495bb7ef1272d5d309ee Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sun, 2 Nov 2025 01:49:36 +0000
Subject: [PATCH 151/154] vendor: Update vendored sources to
 igraph/igraph@e4fd29899ab2b2bf30fcd38affa87a032b0875da (#2474)

Co-authored-by: krlmlr 
---
 R/aaa-auto.R                                 | 2 +-
 src/vendor/cigraph/interfaces/functions.yaml | 2 +-
 src/vendor/igraph_version.h                  | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index 7ed4777e8aa..82f1fe21c45 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -1437,7 +1437,7 @@ hsbm_list_game_impl <- function(
 correlated_game_impl <- function(
   old_graph,
   corr,
-  p = edge_density(old_graph),
+  p = edge_density(old.graph),
   permutation = NULL
 ) {
   # Argument checks
diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml
index 8b6b5f5ce86..a1ba2d947ac 100644
--- a/src/vendor/cigraph/interfaces/functions.yaml
+++ b/src/vendor/cigraph/interfaces/functions.yaml
@@ -435,7 +435,7 @@ igraph_hsbm_list_game:
 igraph_correlated_game:
     PARAMS: |-
         OUT GRAPH new_graph, GRAPH old_graph,
-        REAL corr, REAL p=edge_density(old_graph), OPTIONAL INDEX_VECTOR permutation
+        REAL corr, REAL p=edge_density(old.graph), OPTIONAL INDEX_VECTOR permutation
 
 igraph_correlated_pair_game:
     PARAMS: |-
diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h
index 558c41ab6b7..e9600153efa 100644
--- a/src/vendor/igraph_version.h
+++ b/src/vendor/igraph_version.h
@@ -23,11 +23,11 @@
 
 IGRAPH_BEGIN_C_DECLS
 
-#define IGRAPH_VERSION "1.0.0-33-g6e6f6876c"
+#define IGRAPH_VERSION "1.0.0-34-ge4fd29899"
 #define IGRAPH_VERSION_MAJOR 1
 #define IGRAPH_VERSION_MINOR 0
 #define IGRAPH_VERSION_PATCH 0
-#define IGRAPH_VERSION_PRERELEASE "33-g6e6f6876c"
+#define IGRAPH_VERSION_PRERELEASE "34-ge4fd29899"
 
 IGRAPH_EXPORT void igraph_version(const char **version_string,
                                   int *major,

From 8c63e99e5b19a17a40f61717fc45b06d90169998 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 3 Nov 2025 01:50:38 +0000
Subject: [PATCH 152/154] vendor: Update vendored sources to
 igraph/igraph@fd0edb39a7b4e79b61d43f684197c81aba015fa2 (#2479)

Co-authored-by: krlmlr 
---
 R/aaa-auto.R                                 | 2 +-
 src/vendor/cigraph/interfaces/functions.yaml | 2 +-
 src/vendor/igraph_version.h                  | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index 82f1fe21c45..7ed4777e8aa 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -1437,7 +1437,7 @@ hsbm_list_game_impl <- function(
 correlated_game_impl <- function(
   old_graph,
   corr,
-  p = edge_density(old.graph),
+  p = edge_density(old_graph),
   permutation = NULL
 ) {
   # Argument checks
diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml
index a1ba2d947ac..8b6b5f5ce86 100644
--- a/src/vendor/cigraph/interfaces/functions.yaml
+++ b/src/vendor/cigraph/interfaces/functions.yaml
@@ -435,7 +435,7 @@ igraph_hsbm_list_game:
 igraph_correlated_game:
     PARAMS: |-
         OUT GRAPH new_graph, GRAPH old_graph,
-        REAL corr, REAL p=edge_density(old.graph), OPTIONAL INDEX_VECTOR permutation
+        REAL corr, REAL p=edge_density(old_graph), OPTIONAL INDEX_VECTOR permutation
 
 igraph_correlated_pair_game:
     PARAMS: |-
diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h
index e9600153efa..d6df5eeedc4 100644
--- a/src/vendor/igraph_version.h
+++ b/src/vendor/igraph_version.h
@@ -23,11 +23,11 @@
 
 IGRAPH_BEGIN_C_DECLS
 
-#define IGRAPH_VERSION "1.0.0-34-ge4fd29899"
+#define IGRAPH_VERSION "1.0.0-35-gfd0edb39a"
 #define IGRAPH_VERSION_MAJOR 1
 #define IGRAPH_VERSION_MINOR 0
 #define IGRAPH_VERSION_PATCH 0
-#define IGRAPH_VERSION_PRERELEASE "34-ge4fd29899"
+#define IGRAPH_VERSION_PRERELEASE "35-gfd0edb39a"
 
 IGRAPH_EXPORT void igraph_version(const char **version_string,
                                   int *major,

From 36b22dd2165e2348d8403279f95f2f66e1567c3a Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 4 Nov 2025 01:48:18 +0000
Subject: [PATCH 153/154] vendor: Update vendored sources to
 igraph/igraph@1e133a7c1fec746469f424e79c7c386a6f40594b (#2481)

Co-authored-by: krlmlr 
---
 src/vendor/cigraph/etc/cmake/compilers.cmake | 11 +++++++++++
 src/vendor/igraph_version.h                  |  4 ++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/vendor/cigraph/etc/cmake/compilers.cmake b/src/vendor/cigraph/etc/cmake/compilers.cmake
index c6b12121c94..c25a1e79e29 100644
--- a/src/vendor/cigraph/etc/cmake/compilers.cmake
+++ b/src/vendor/cigraph/etc/cmake/compilers.cmake
@@ -8,6 +8,17 @@ include(CheckCCompilerFlag)
 #  - https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
 add_compile_definitions(_POSIX_C_SOURCE=200809L)
 
+# On some Apple systems, with some compilers, defining _POSIX_C_SOURCE causes compilation
+# failures when including C++ headers. Defining _DARWIN_C_SOURCE explicitly usually fixes
+# this. Refs: https://trac.macports.org/ticket/60655 and https://trac.macports.org/ticket/73145
+# This is claimed to be due to _POSIX_C_SOURCE disabling APIs that C++ headers rely on
+# on some systems. _DARWIN_C_SOURCE re-enables these APIs, but _GNU_SOURCE alone does not 
+# necessarily do so. Using different global defined for C and C++ is problematic with CMake,
+# so instead of restricting _POSIX_C_SOURCE to C, we define _DARWIN_C_SOURCE.
+if(APPLE)
+  add_compile_definitions(_DARWIN_C_SOURCE)
+endif()
+
 if(MSVC)
   add_compile_options(/FS)
   add_compile_definitions(_CRT_SECURE_NO_WARNINGS) # necessary to compile for UWP
diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h
index d6df5eeedc4..ddb99d7367d 100644
--- a/src/vendor/igraph_version.h
+++ b/src/vendor/igraph_version.h
@@ -23,11 +23,11 @@
 
 IGRAPH_BEGIN_C_DECLS
 
-#define IGRAPH_VERSION "1.0.0-35-gfd0edb39a"
+#define IGRAPH_VERSION "1.0.0-36-g1e133a7c1"
 #define IGRAPH_VERSION_MAJOR 1
 #define IGRAPH_VERSION_MINOR 0
 #define IGRAPH_VERSION_PATCH 0
-#define IGRAPH_VERSION_PRERELEASE "35-gfd0edb39a"
+#define IGRAPH_VERSION_PRERELEASE "36-g1e133a7c1"
 
 IGRAPH_EXPORT void igraph_version(const char **version_string,
                                   int *major,

From 984204367328c1a993f810d49da0fd3f60162b72 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 5 Nov 2025 01:46:06 +0000
Subject: [PATCH 154/154] vendor: Update vendored sources to
 igraph/igraph@dafef9909d30e0d90e4654ce8052c99fc359b4d7 (#2486)

Co-authored-by: krlmlr 
---
 src/vendor/cigraph/CHANGELOG.md | 1 +
 src/vendor/igraph_version.h     | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/vendor/cigraph/CHANGELOG.md b/src/vendor/cigraph/CHANGELOG.md
index 7b087346766..dc069220c30 100644
--- a/src/vendor/cigraph/CHANGELOG.md
+++ b/src/vendor/cigraph/CHANGELOG.md
@@ -8,6 +8,7 @@
  - Eliminated references to `std::cout` from the igraph shared library, as required by CRAN.
  - Fixed a bug in `igraph_hub_and_authority_scores()` that printed a warning about zero entries in the result even when the number of zeros was below the threshold used in the corresponding checks.
  - Fixed compilation and tests when Infomap support is disabled.
+ - Fixed rare compilation issues on some Apple systems with some non-standard compilers due to incompatibilities between defining the `_POSIX_C_SOURCE` feature test macro and standard C++ headers. Now `_DARWIN_C_SOURCE` is defined when compiling igraph on Apple systems.
 
 ### Other
 
diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h
index ddb99d7367d..3d39de0b742 100644
--- a/src/vendor/igraph_version.h
+++ b/src/vendor/igraph_version.h
@@ -23,11 +23,11 @@
 
 IGRAPH_BEGIN_C_DECLS
 
-#define IGRAPH_VERSION "1.0.0-36-g1e133a7c1"
+#define IGRAPH_VERSION "1.0.0-37-gdafef9909"
 #define IGRAPH_VERSION_MAJOR 1
 #define IGRAPH_VERSION_MINOR 0
 #define IGRAPH_VERSION_PATCH 0
-#define IGRAPH_VERSION_PRERELEASE "36-g1e133a7c1"
+#define IGRAPH_VERSION_PRERELEASE "37-gdafef9909"
 
 IGRAPH_EXPORT void igraph_version(const char **version_string,
                                   int *major,